Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Рефакторинг и оптимизация процедуры / 13 сообщений из 13, страница 1 из 1
01.10.2017, 06:49:31
    #39528930
gister
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рефакторинг и оптимизация процедуры
Добрый день! Есть процедура:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
// закрытие чека общая procedure TfrmRegCashOperJrn.actCloseCheckExecute(Sender: TObject);
var
  anObj: TItemObject;
  frm: TfrmaDialog;
  mess:string;
  bInTransaction: boolean;
  Proc_Id,
  Bop_Id,
  Oper: integer;
  sOutPrm: string;
  dmBPO: TdmBP_Oper;
  i: integer;
  sParams: string;
 procedure pCreTcd;
 begin
   //если оплата c помощью электронного кассира TCD
    if ((GetMainQuery.FieldByName('PAYTYPE').AsString = '1')
        and (Orcl.GetPar('S_PKGTCD.fGetTcdId(:VAL_CODE, :INCOM)',
        [GetMainQuery.FieldByName('VAL_CODE').AsString,Sign(GetMainQuery.FieldByName('CHK_SDOK_NAL_WST').AsInteger)])<>'')) then begin

      //подготовка параметров для работы с TCD
      with spTcd do begin
        if not Prepared then Prepare;
        ParamByName('idChk').AsInteger := GetMainQuery.FieldByName('CHK_ID').AsInteger;
        ParamByName('iIncomfl').AsInteger := Sign(GetMainQuery.FieldByName('CHK_SDOK_NAL_WST').AsInteger);

        spTcd.ExecProc;

        Proc_Id := ParamByName('idProc').AsInteger;
        Bop_Id := ParamByName('idBop').AsInteger;
        Oper := ParamByName('nOper').AsInteger;
      end;

      // запускаем процедуру работы с TCD
      if Proc_Id <>  null then begin
        dmBPO := TdmBP_Oper.Create(nil);
        try
          if not dmBPO.RunOperation(Proc_Id, Bop_Id, Oper, saNone, sParams, sOutPrm, True, 1, 1,false) then
            raise Exception.Create(Localize('Ошибка электронного кассира. Чек не закрыт.'));
        finally
         dmBPO.Free;
        end;
      end;
    end;
 end;
begin

  if CurrentObject(itOper)<> nil then
    anObj := CurrentObject(itOper)
  else if CurrentObject(itCheck)<> nil then
    anObj := CurrentObject(itCheck)
  else
    Exit;

  if GetMainQuery.FieldByName('CHK_SIGN_NAL').asinteger=1 then begin
    frm := LinkedForms.CreateForm('TfrmPstChRepDlg', Application) as TfrmaDialog;
    with frm do
      try
        ZLinkParams.AddItem('AMOUNT',anObj.FieldValue['CHK_SDOK_NAL']);
        ZLinkParams.AddItem('CHK_CODE',anObj.FieldValue['CODE']);
        ZLinkParams.AddItem('PAYTYPE',anObj.FieldValue['PAYTYPE']);
        ZLinkParams.AddItem('PRINTCSHRPT',1);
        ZLinkParams.AddItem('PRINTNSF',orcl.GetParameter('PST_PRINTNSF'));
        ZLinkParams.AddItem('SHOWNSF',orcl.GetParameter('PST_SHOWNSF'));
        if ShowModal = mrOK then
          with spClose do begin
            if not Prepared then Prepare;
            ParamByName('nID').asinteger := GetMainQuery.FieldByName('CHK_ID').asinteger;
            ParamByName('cPRINTFL').asString := VarToStr(frm.ZLinkParams.FieldValueByName('PRINTCSHRPT'));
            ParamByName('cPRINTNSF').asString := VarToStr(frm.ZLinkParams.FieldValueByName('PRINTNSF'));

            ProcessMessageShow(Localize(SPModify));
            StartWait;
            try
              // открываем транзакцию
              bInTransaction := Orcl.InTransaction;
              if not bInTransaction then
                Orcl.BeginTransaction;
              try
                // процедура закрытия чека
                spClose.ExecProc;

                //если оплата по карте
                if ((GetMainQuery.FieldByName('PAYTYPE').AsString = '5') or (GetMainQuery.FieldByName('PAYTYPE').AsString = '6')) then begin

                  //подготовка параметров для работы с pos-терминалом
                  with spCreateProc do begin
                    if not Prepared then Prepare;
                    ParamByName('P_ID').Clear;
                    ParamByName('P_CHK_ID').AsInteger := GetMainQuery.FieldByName('CHK_ID').AsInteger;

                    spCreateProc.ExecProc;

                    if ParamByName('P_ID').IsNull then
                      Proc_Id := 0
                    else
                     Proc_Id := ParamByName('P_ID').AsInteger;
                    Bop_Id := ParamByName('P_BOP_ID').AsInteger;
                    Oper := ParamByName('P_OPER').AsInteger;
                  end;

                  // запускаем процедуру работы с pos-терминалом
                  if Proc_Id <>  0 then begin
                    dmBPO := TdmBP_Oper.Create(nil);
                    try
                      if not dmBPO.RunOperation(Proc_Id, Bop_Id, Oper, saNone, sParams, sOutPrm, True, 1, 1,false) then
                        raise Exception.Create(Localize('Ошибка POS-терминала. Чек не закрыт.'));
                    finally
                     dmBPO.Free;
                    end;
                  end;
                end;

                //если оплата c помощью электронного кассира TCD
                pCreTcd;

                // закрываем транзакцию
                if not bInTransaction then
                    Orcl.CommitTransaction;
              except
                // откат транзакцию
                if not bInTransaction then
                  Orcl.RollbackTransaction;
                raise;
              end;
            finally
              StopWait;
              ProcessMessageHide;
              mnuRefresh.Click
            end;
          end;
      finally
        Free;
      end;
  end else begin
    if GetMainQuery.FieldByName('CHK_SIGN_NAL').AsInteger=-1 then begin
// если клиент принес марок, но мы ему должны отдать деньги, то мы ему отдаем с учетом этих марок
// если же клиент принес столько марок, что в целом дает больше, чем надо, то мы ему ничего не возвращаем
      if GetMainQuery.FieldByName('CHK_SDOK_NAL_WST').AsInteger < 0 then begin
        mess := Localize('Необходимо выдать ')+
        GetMainQuery.FieldByName('CHK_SDOK').AsString+' '+
        GetMainQuery.FieldByName('val_code').AsString+
        Localize('. Закрыть чек?');
      end
      else mess := Localize('Закрыть чек?');
    end
    else mess := Localize('Чек с нулевой суммой. Закрыть чек?');

    if MessageDlg2(Localize(mess), mtConfirmation,[mbYes,mbNo]) = mrYes then
      with spClose do begin
        if not Prepared then Prepare;
        ParamByName('nID').asinteger := GetMainQuery.FieldByName('CHK_ID').asinteger;

            ProcessMessageShow(Localize(SPModify));
            StartWait;
            try
              // открываем транзакцию
              bInTransaction := Orcl.InTransaction;
              if not bInTransaction then
                Orcl.BeginTransaction;
              try
                // процедура закрытия чека
                spClose.ExecProc;

                //если оплата c помощью электронного кассира TCD
                pCreTcd;

                // закрываем транзакцию
                if not bInTransaction then
                    Orcl.CommitTransaction;
              except
                // откат транзакцию
                if not bInTransaction then
                  Orcl.RollbackTransaction;
                raise;
              end;
            finally
              StopWait;
              ProcessMessageHide;
              mnuRefresh.Click
            end;
      end;
   end;

  if StrToInt(Orcl.GetPar('C_PkgUserRpt.CheckUnprinted')) > 0 then
    with LinkedForms.CreateForm('TRptToPrintList', Application) do
      try
        ShowModal;
      finally
        Free;
      end;
end;

В конце серверной процедуры
Код: pascal
1.
 // процедура закрытия чека spClose.ExecProc;

выполняется блокировка таблицы для присвоения номера счета-фактуры типа
Код: plsql
1.
SELECT ID INTO ITMP FROM S_BILJRN WHERE ID=P_ID FOR UPDATE;

. После процедуры закрытия чека в той же транзакции отрабатывает "тяжелая" процедура
Код: pascal
1.
 // оплата с pos терминала spCreateProc.ExecProc;

. С системой работает большое количество операторов, поэтому когда выполняется операция закрытия чека одним оператором, другие вынуждены ждать снятие блокировки с S_BILJRN таблицы. Процедуру
Код: pascal
1.
[SRC DELPHI] // процедура закрытия чека spClose.ExecProc;

[/SRC] модифицировать нельзя. Подскажите, пожалуйста, каким образом можно оптимизировать закрытие чека, чтобы блокировки свести к минимуму!? Спасибо!
...
Рейтинг: 0 / 0
01.10.2017, 11:05:51
    #39528955
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рефакторинг и оптимизация процедуры
gisterкаким образом можно оптимизировать закрытие чека, чтобы блокировки свести к минимумуИх не должно быть, блокировок. В закрытии чека должны быть только insert-ы.
...
Рейтинг: 0 / 0
01.10.2017, 11:14:29
    #39528958
gister
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рефакторинг и оптимизация процедуры
Инсерты есть но блокируется таблица S_BILJRN и после нее выполняется еще несколько операций до commit'a получаем блокировку
...
Рейтинг: 0 / 0
01.10.2017, 11:15:44
    #39528959
gister
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рефакторинг и оптимизация процедуры
Блокировка нужна чтобы не было наложений на номера счетов - фактур
...
Рейтинг: 0 / 0
01.10.2017, 12:51:51
    #39528983
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рефакторинг и оптимизация процедуры
gisterБлокировка нужна чтобы не было наложений на номера счетов - фактурВидимо, я не пгмогу, т.к. не понимаю, зачем блокировать таблицу вообще в принципе и какие могут быть наложения.
...
Рейтинг: 0 / 0
01.10.2017, 13:27:33
    #39528996
AX-Class
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рефакторинг и оптимизация процедуры
Много клиентского кода до коммит.
Это что:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
dmBPO := TdmBP_Oper.Create(nil);
        try
          if not dmBPO.RunOperation(Proc_Id, Bop_Id, Oper, saNone, sParams, sOutPrm, True, 1, 1,false) then
            raise Exception.Create(Localize('Ошибка электронного кассира. Чек не закрыт.'));
        finally
         dmBPO.Free;
        end;


Не тяжеловато ли, чтоб все кассы ждали, пока у одного Create(nil)/Free. А если эксепшн.
...
Рейтинг: 0 / 0
01.10.2017, 18:32:10
    #39529030
gister
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рефакторинг и оптимизация процедуры
Это запуск операции сценария, серверная процедура оплаты по pos терминалу
...
Рейтинг: 0 / 0
01.10.2017, 19:01:17
    #39529035
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рефакторинг и оптимизация процедуры
gisterЭто запуск операции сценария, серверная процедура оплаты по pos терминалуОракл постерминалом управляет?
...
Рейтинг: 0 / 0
01.10.2017, 19:13:00
    #39529042
gister
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рефакторинг и оптимизация процедуры
YuRock,

В оракле подготовка данных, после обработка в dll
...
Рейтинг: 0 / 0
01.10.2017, 19:22:47
    #39529044
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рефакторинг и оптимизация процедуры
gister,
Функцию этой dll Оракл вызывает? Если да - это ужас.
И опять же, не понимаю, что там готовить. Терминалу нужна сумма и всё. Сумму чтоль эта процедура готовит?
Всё как-то очень сложно у вас. Не понятно, зачем.
...
Рейтинг: 0 / 0
01.10.2017, 19:33:32
    #39529046
gister
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рефакторинг и оптимизация процедуры
В системе нужны проводки плюс ведётся журнал операций, поэтому нужен вызов дополнительных операций
...
Рейтинг: 0 / 0
01.10.2017, 19:46:23
    #39529050
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рефакторинг и оптимизация процедуры
gisterВ системе нужны проводки плюс ведётся журнал операций, поэтому нужен вызов дополнительных операцийКаких операций, если дело еще даже до терминала не дошло, не то, что до кассы?
Ну я понимаю еще "начало операции" записать для защиты от сбоев, ну хорошо. Еще что - я не знаю.
...
Рейтинг: 0 / 0
01.10.2017, 22:16:56
    #39529077
schi
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рефакторинг и оптимизация процедуры
gisterВ конце серверной процедуры
Код: pascal
1.
 // процедура закрытия чека spClose.ExecProc;

выполняется блокировка таблицы для присвоения номера счета-фактуры типа
Код: plsql
1.
SELECT ID INTO ITMP FROM S_BILJRN WHERE ID=P_ID FOR UPDATE;



Я не вижу тут блокировки таблицы. Блокируется конкретная запись.
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Рефакторинг и оптимизация процедуры / 13 сообщений из 13, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]