powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Рефакторинг и оптимизация процедуры
13 сообщений из 13, страница 1 из 1
Рефакторинг и оптимизация процедуры
    #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
Рефакторинг и оптимизация процедуры
    #39528955
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gisterкаким образом можно оптимизировать закрытие чека, чтобы блокировки свести к минимумуИх не должно быть, блокировок. В закрытии чека должны быть только insert-ы.
...
Рейтинг: 0 / 0
Рефакторинг и оптимизация процедуры
    #39528958
gister
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Инсерты есть но блокируется таблица S_BILJRN и после нее выполняется еще несколько операций до commit'a получаем блокировку
...
Рейтинг: 0 / 0
Рефакторинг и оптимизация процедуры
    #39528959
gister
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Блокировка нужна чтобы не было наложений на номера счетов - фактур
...
Рейтинг: 0 / 0
Рефакторинг и оптимизация процедуры
    #39528983
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gisterБлокировка нужна чтобы не было наложений на номера счетов - фактурВидимо, я не пгмогу, т.к. не понимаю, зачем блокировать таблицу вообще в принципе и какие могут быть наложения.
...
Рейтинг: 0 / 0
Рефакторинг и оптимизация процедуры
    #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
Рефакторинг и оптимизация процедуры
    #39529030
gister
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Это запуск операции сценария, серверная процедура оплаты по pos терминалу
...
Рейтинг: 0 / 0
Рефакторинг и оптимизация процедуры
    #39529035
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gisterЭто запуск операции сценария, серверная процедура оплаты по pos терминалуОракл постерминалом управляет?
...
Рейтинг: 0 / 0
Рефакторинг и оптимизация процедуры
    #39529042
gister
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
YuRock,

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

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



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


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