Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Рефакторинг и оптимизация процедуры  [new]
gister
Member

Откуда:
Сообщений: 26
Добрый день! Есть процедура:
+
// закрытие чека общая 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;
В конце серверной процедуры
 // процедура закрытия чека spClose.ExecProc;
выполняется блокировка таблицы для присвоения номера счета-фактуры типа
SELECT ID INTO ITMP FROM S_BILJRN WHERE ID=P_ID FOR UPDATE;
. После процедуры закрытия чека в той же транзакции отрабатывает "тяжелая" процедура
 // оплата с pos терминала spCreateProc.ExecProc;
. С системой работает большое количество операторов, поэтому когда выполняется операция закрытия чека одним оператором, другие вынуждены ждать снятие блокировки с S_BILJRN таблицы. Процедуру
[SRC DELPHI] // процедура закрытия чека spClose.ExecProc;
[/SRC] модифицировать нельзя. Подскажите, пожалуйста, каким образом можно оптимизировать закрытие чека, чтобы блокировки свести к минимуму!? Спасибо!
1 окт 17, 06:49    [20834087]     Ответить | Цитировать Сообщить модератору
 Re: Рефакторинг и оптимизация процедуры  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2056
gister
каким образом можно оптимизировать закрытие чека, чтобы блокировки свести к минимуму
Их не должно быть, блокировок. В закрытии чека должны быть только insert-ы.
1 окт 17, 11:05    [20834213]     Ответить | Цитировать Сообщить модератору
 Re: Рефакторинг и оптимизация процедуры  [new]
gister
Member

Откуда:
Сообщений: 26
Инсерты есть но блокируется таблица S_BILJRN и после нее выполняется еще несколько операций до commit'a получаем блокировку
1 окт 17, 11:14    [20834223]     Ответить | Цитировать Сообщить модератору
 Re: Рефакторинг и оптимизация процедуры  [new]
gister
Member

Откуда:
Сообщений: 26
Блокировка нужна чтобы не было наложений на номера счетов - фактур
1 окт 17, 11:15    [20834224]     Ответить | Цитировать Сообщить модератору
 Re: Рефакторинг и оптимизация процедуры  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2056
gister
Блокировка нужна чтобы не было наложений на номера счетов - фактур
Видимо, я не пгмогу, т.к. не понимаю, зачем блокировать таблицу вообще в принципе и какие могут быть наложения.
1 окт 17, 12:51    [20834354]     Ответить | Цитировать Сообщить модератору
 Re: Рефакторинг и оптимизация процедуры  [new]
AX-Class
Member

Откуда:
Сообщений: 82
Много клиентского кода до коммит.
Это что:
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. А если эксепшн.
1 окт 17, 13:27    [20834420]     Ответить | Цитировать Сообщить модератору
 Re: Рефакторинг и оптимизация процедуры  [new]
gister
Member

Откуда:
Сообщений: 26
Это запуск операции сценария, серверная процедура оплаты по pos терминалу
1 окт 17, 18:32    [20834745]     Ответить | Цитировать Сообщить модератору
 Re: Рефакторинг и оптимизация процедуры  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2056
gister
Это запуск операции сценария, серверная процедура оплаты по pos терминалу
Оракл постерминалом управляет?
1 окт 17, 19:01    [20834769]     Ответить | Цитировать Сообщить модератору
 Re: Рефакторинг и оптимизация процедуры  [new]
gister
Member

Откуда:
Сообщений: 26
YuRock,

В оракле подготовка данных, после обработка в dll
1 окт 17, 19:13    [20834779]     Ответить | Цитировать Сообщить модератору
 Re: Рефакторинг и оптимизация процедуры  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2056
gister,
Функцию этой dll Оракл вызывает? Если да - это ужас.
И опять же, не понимаю, что там готовить. Терминалу нужна сумма и всё. Сумму чтоль эта процедура готовит?
Всё как-то очень сложно у вас. Не понятно, зачем.
1 окт 17, 19:22    [20834791]     Ответить | Цитировать Сообщить модератору
 Re: Рефакторинг и оптимизация процедуры  [new]
gister
Member

Откуда:
Сообщений: 26
В системе нужны проводки плюс ведётся журнал операций, поэтому нужен вызов дополнительных операций
1 окт 17, 19:33    [20834806]     Ответить | Цитировать Сообщить модератору
 Re: Рефакторинг и оптимизация процедуры  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2056
gister
В системе нужны проводки плюс ведётся журнал операций, поэтому нужен вызов дополнительных операций
Каких операций, если дело еще даже до терминала не дошло, не то, что до кассы?
Ну я понимаю еще "начало операции" записать для защиты от сбоев, ну хорошо. Еще что - я не знаю.
1 окт 17, 19:46    [20834823]     Ответить | Цитировать Сообщить модератору
 Re: Рефакторинг и оптимизация процедуры  [new]
schi
Member

Откуда: Москва
Сообщений: 2204
gister
В конце серверной процедуры
 // процедура закрытия чека spClose.ExecProc;
выполняется блокировка таблицы для присвоения номера счета-фактуры типа
SELECT ID INTO ITMP FROM S_BILJRN WHERE ID=P_ID FOR UPDATE;


Я не вижу тут блокировки таблицы. Блокируется конкретная запись.
1 окт 17, 22:16    [20834961]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить