/* Server version: WI-V6.3.3.18185 Firebird 2.1 
   SQLDialect: 3. ODS: 11.0. Forced writes: On. Sweep inteval: 20000.
   Page size: 4096. Cache pages: 9500 (38000 Kb). Read-only: False. */
SET SQL DIALECT 3;

ALTER TABLE ARCHIVE_PAYMENT_EXTERNAL ADD EXTERNAL_IFC NAME_100;

ALTER TABLE ARCHIVE_PAYMENT_EXTERNAL ADD INTERNAL_DATA NAME_1000;

ALTER TABLE EAI_P2F_TRANSFER_LOG ADD TRANSFER_DT DATE_TIME DEFAULT current_timestamp;

ALTER TABLE EAI_P2F_TRANSFER_LOG ADD EXTERNAL_IFC NAME_100;

/* Create Foreign Key... */
RECONNECT;

ALTER TABLE ARCHIVE_DISCOUNT ADD CONSTRAINT FK_AD_DISCOUNT FOREIGN KEY (ID_DISCOUNT) REFERENCES NOM_DISCOUNT (ID_DISCOUNT) ON UPDATE CASCADE;

ALTER TABLE ARCHIVE_HEAD ADD CONSTRAINT FK_AH_OBJECT FOREIGN KEY (ID_OBJECT) REFERENCES NOM_OBJECT (ID_OBJECT) ON UPDATE CASCADE;

ALTER TABLE ARCHIVE_LINE ADD CONSTRAINT FK_AL_STOCK FOREIGN KEY (ID_STOCK) REFERENCES STOCK (ID_STOCK) ON UPDATE CASCADE;

ALTER TABLE ARCHIVE_LINE ADD CONSTRAINT FK_AL_VAT FOREIGN KEY (ID_VAT) REFERENCES NOM_VAT_GROUP (ID_VAT) ON UPDATE CASCADE;

ALTER TABLE ARCHIVE_MODIFFIER ADD CONSTRAINT FK_AMOD_STOCK FOREIGN KEY (ID_STOCK) REFERENCES STOCK (ID_STOCK) ON UPDATE CASCADE;

ALTER TABLE ARCHIVE_PAYMENT ADD CONSTRAINT FK_AP_PAYMENT_TYPE FOREIGN KEY (ID_PAYMENT_TYPE) REFERENCES NOM_PAYMENT_TYPE (ID_PAYMENT_TYPE) ON UPDATE CASCADE;

ALTER TABLE SMETKA_MODIFFIER ADD CONSTRAINT FK_SMOD_STOCK FOREIGN KEY (ID_STOCK) REFERENCES STOCK (ID_STOCK) ON UPDATE CASCADE;

/* Alter Procedure... */
/* Alter (BILL_PAYMENT_EXTERNAL_DATA) */
SET TERM ^ ;

ALTER PROCEDURE BILL_PAYMENT_EXTERNAL_DATA(ID_SMETKA_PAYMENT INTEGER,
EXTERNAL_IFC VARCHAR(200),
EXTERNAL_DATA VARCHAR(2000),
INTERNAL_DATA VARCHAR(2000))
 RETURNS(ERR_CODE INTEGER,
ERR_TEXT VARCHAR(500))
 AS
declare variable id_end_work integer;
  declare variable ext_interface varchar(100);

  declare variable id_smetka_head integer;
  declare variable new_id_smetka_front integer;
  declare variable id_account integer;
  declare variable guest_name varchar(100);
  declare variable room_name varchar(100);
  declare variable board_name varchar(100);
  declare variable hotel_name varchar(100);
  declare variable smetka_date date;
  declare variable pay_amount numeric(15,4);
begin
  err_code = 0;
  err_text = '';

  insert into SMETKA_PAYMENT_EXTERNAL (ID_SMETKA_PAYMENT, EXTERNAL_DATA, EXTERNAL_IFC, INTERNAL_DATA)
  values (:id_smetka_payment, :external_data, :external_ifc, :internal_data);

  select SP.ID_END_WORK, sh.ID_SMETKA_HEAD, PT.EXT_INTERFACE, SH.SMETKA_DATE
  from   SMETKA_PAYMENT SP
         join SMETKA_HEAD SH on SH.ID_SMETKA_HEAD = SP.ID_SMETKA_HEAD
         join NOM_PAYMENT_TYPE PT on PT.ID_PAYMENT_TYPE = SP.ID_PAYMENT_TYPE
  where  SP.ID_SMETKA_PAYMENT = :id_smetka_payment
  into   :id_end_work, :id_smetka_head, :ext_interface, :smetka_date;

  pay_amount = null;
  select sum(tl.TRANSFER_AMOUNT)
  from   EAI_P2F_TRANSFER_LOG tl
  where  tl.ID_SMETKA_HEAD = :id_smetka_head
         and tl.ID_SMETKA_PAYMENT is null
  into   :pay_amount;

  if (:pay_amount is not null) then begin
    update EAI_P2F_TRANSFER_LOG tl
    set    tl.ID_SMETKA_PAYMENT = :ID_SMETKA_PAYMENT
    where  tl.ID_SMETKA_HEAD = :id_smetka_head
           and tl.ID_SMETKA_PAYMENT is null;

    execute procedure BILL_PAYMENT_EXT_DATA_PARSE (:EXTERNAL_IFC, :EXTERNAL_DATA)
    returning_values (:ID_ACCOUNT, :GUEST_NAME, :ROOM_NAME, :HOTEL_NAME, :board_name);

    new_id_smetka_front = gen_id(gen_smetka_front_id, 1);
    insert into SMETKA_FRONT (ID_SMETKA_FRONT, ID_END_WORK,
      ID_ACCOUNT, GUEST_NAME, ROOM_NAME, HOTEL_NAME, SMETKA_DATE, GUEST_BOARD, TRANSFER_AMOUNT)
    values (:new_id_smetka_front, :id_end_work,
      :id_account, :guest_name, :room_name, :hotel_name, :smetka_date, :board_name, :pay_amount);
  
    update SMETKA_PAYMENT SP
    set    SP.ID_SMETKA_FRONT = :new_id_smetka_front
    where  SP.ID_SMETKA_PAYMENT = :id_smetka_payment;
  end

end
^

/* empty dependent procedure body */
/* Clear: BILL_POST_ADD$PDA for: BILL_POST_ADD */
ALTER PROCEDURE BILL_POST_ADD$PDA(ID_CLIENT_POS INTEGER,
ID_END_WORK INTEGER,
ID_SMETKA_HEAD INTEGER,
ID_SMETKA_TRANS INTEGER)
 RETURNS(ERR_CODE INTEGER,
ERR_TEXT VARCHAR(255),
TOTAL_SUM NUMERIC(15,4))
 AS
 BEGIN SUSPEND; END
^

/* empty dependent procedure body */
/* Clear: MANAGE_VOID_BILL for: BILL_POST_ADD */
ALTER PROCEDURE MANAGE_VOID_BILL(ID_CLIENT_POS INTEGER,
ID_SMETKA_HEAD INTEGER,
ID_VOID_REASON INTEGER,
ID_VOID_OVERRULE INTEGER)
 RETURNS(ERR_CODE INTEGER,
ERR_TEXT VARCHAR(255),
CLOSE_TYPE VARCHAR(10),
VIP_LINES INTEGER,
NEW_ID_SMETKA_TRANS INTEGER)
 AS
 BEGIN SUSPEND; END
^

/* Alter (BILL_POST_ADD) */
ALTER PROCEDURE BILL_POST_ADD(ID_END_WORK INTEGER,
ID_SMETKA_HEAD INTEGER,
ID_SMETKA_TRANS INTEGER,
ID_MENU_PRICE_LIST INTEGER,
ID_PRICE_LIST_OVERRULE INTEGER,
ID_STOCK INTEGER,
ID_INVENT INTEGER,
ID_VAT INTEGER,
QTY NUMERIC(15,4),
SALE_PRICE NUMERIC(15,4),
LINE_SUM NUMERIC(15,4),
ID_LINE_DISCOUNT INTEGER,
ID_LINE_VOID INTEGER,
EDIT_KIND VARCHAR(10),
ID_MASTER_LINE INTEGER,
LINE_TEXT VARCHAR(2000),
MOD_CNT INTEGER)
 RETURNS(ERR_CODE INTEGER,
ERR_TEXT VARCHAR(255),
NEW_ID_MOD_SESSION INTEGER)
 AS
declare variable cost_price numeric(15, 4);
  declare variable status integer;
  declare variable vqty numeric(15, 4);
  declare variable vsl_dbkey char(8);
  declare variable qty_post numeric(15, 4);
  declare variable qty_void numeric(15, 4);
  declare variable id_voided_discount integer;
  declare variable discount_sum numeric(15, 4);
  declare variable void_sum numeric(15, 4);
  declare variable id_smetka_bon integer;
  declare variable post_status integer;
  declare variable is_service integer;
  declare variable new_line_text integer;
  declare variable tax_percent numeric(15,4);
begin
  err_code = 0;
  err_text = '';
  id_smetka_bon = null;
  void_sum = 0;
  new_line_text = 0;

  select S.COST_PRICE, S.IS_SERVICE
  from   STOCK S
  where  S.ID_STOCK = :id_stock
  into   :cost_price, :is_service;
  if (:is_service = 1) then post_status = -3;
  else post_status = 1;

  select tg.TAXES_VALUE
  from   TAX_GROUP TG
  where  TG.ID_TAX_GROUP = :ID_VAT
  into   :tax_percent;

  if (:edit_kind in ('EDIT_VOID', 'EDIT_MOVE', '')) then begin
    if (:id_line_discount is not null) then begin
      select SD.DISCOUNT_SUM
      from   SMETKA_DISCOUNT SD
      where  SD.ID_SMETKA_DISCOUNT = :id_line_discount
      into   :discount_sum;
    end else discount_sum = 0;

    if (:edit_kind in ('EDIT_VOID', 'EDIT_MOVE')) then begin
      select SL.RDB$DB_KEY, SL.ID_LINE_DISCOUNT, SL.QTY, SL.QTY_POST, SL.QTY_VOID, SL.ID_MOD_SESSION
      from   SMETKA_LINE SL
      where  SL.ID_SMETKA_LINE = :id_master_line
      into   :vsl_dbkey, :id_voided_discount, :vqty, :qty_post, :qty_void, :new_id_mod_session;

      if (:vqty < :qty) then begin
        err_code = -1;
        err_text = 'QTY_FOR_VOID='||:qty||', QTY_NALICH='||:vqty||'ID_SMETKA_LINE'||:ID_MASTER_LINE;
        exit;
      end else if (:qty = 0) then status = -10;
      else status = 1;
      if (:edit_kind = 'EDIT_VOID') then begin
        qty_void = (:qty_void + (:vqty - :qty));
        qty_post = :qty_post;
      end else if (:edit_kind = 'EDIT_MOVE') then begin
        qty_void = :qty_void;
        qty_post = :qty_post - (:vqty - :qty);
      end

      update SMETKA_LINE SL
      set    SL.ID_LINE_DISCOUNT = :id_line_discount,
             SL.DISCOUNT_SUM = :discount_sum,
             SL.LINE_SUM     = :line_sum,
             SL.STATUS       = :status,
             SL.QTY_VOID     = :qty_void,
             SL.QTY_POST     = :qty_post,
             SL.QTY          = :qty,
             SL.NETO_SUM     = :line_sum
      where  SL.RDB$DB_KEY = :vsl_dbkey;
  
      if (:id_voided_discount is not null) then begin
        delete from SMETKA_DISCOUNT SD
        where SD.ID_SMETKA_DISCOUNT = :id_voided_discount;
      end

      exit;
    end
    if (:id_master_line is not null) then begin
      /* SPLITTING IS GOING ON  */
      select SL.ID_SMETKA_BON, SL.ID_MOD_SESSION
      from   SMETKA_LINE SL
      where  SL.ID_SMETKA_LINE = :id_master_line
      into   :id_smetka_bon, :new_id_mod_session;
      id_master_line = null;
    end else begin
      new_line_text = 1;
      new_id_mod_session = gen_id(gen_mod_session_id, 1);
      if (:mod_cnt = 0) then new_id_mod_session = -1*:new_id_mod_session;
    end
    qty_void = 0;
    qty_post = :qty;
    status = 1;
  end else begin
    /* PREPARING DATA FOR VOID LINES */
    qty_void = :qty;
    qty_post = 0;
    id_line_discount = null;
    discount_sum = 0;
    if (:edit_kind = 'CURRENT') then begin
      new_id_mod_session = gen_id(gen_mod_session_id, 1);
      status = -20;
      id_master_line = gen_id(gen_smetka_line_id, 1);
      insert into SMETKA_LINE (ID_SMETKA_LINE, ID_SMETKA_TRANS, ID_SMETKA_HEAD, ID_STOCK, ID_INVENT,
        QTY, QTY_POST, QTY_VOID, COST_PRICE, SALE_PRICE, LINE_SUM, VOID_SUM, ID_MENU_PRICE_LIST,
        ID_VOIDED_LINE, ID_LINE_VOID, ID_LINE_DISCOUNT, POST_STATUS, STATUS, ID_VAT, DISCOUNT_SUM,
        ID_PRICE_LIST_OVERRULE, ID_END_WORK, ID_MOD_SESSION, NETO_SUM, TAX_PERCENT)
      values (:id_master_line, :id_smetka_trans, :id_smetka_head, :id_stock, :id_invent,
        0, :qty, :qty, :cost_price, :sale_price, 0, 0, :id_menu_price_list,
        null, null, null, :post_status, :status, :id_vat, 0,
        :id_price_list_overrule, :id_end_work, :new_id_mod_session, 0, :tax_percent);

      new_line_text = 1;
    end else if (:edit_kind = 'OLD') then begin
      select SL.ID_MOD_SESSION
      from   SMETKA_LINE SL
      where  SL.ID_SMETKA_LINE = :id_master_line
      into   :new_id_mod_session;
      status = -10;
    end
    qty = 0; /* VOIDING LINES ARE WITH 0 VALID QTY */
    void_sum = :line_sum;
    line_sum = 0;
  end

  if (:new_line_text = 1) then begin
    insert into SMETKA_LINE_TEXT(ID_MOD_SESSION, ID_END_WORK, LINE_TEXT)
    values (:new_id_mod_session, :id_end_work, :line_text);
  end


  insert into SMETKA_LINE (ID_SMETKA_TRANS, ID_SMETKA_HEAD, ID_STOCK, ID_INVENT,
    QTY, QTY_POST, QTY_VOID, COST_PRICE, SALE_PRICE, LINE_SUM, VOID_SUM,
    ID_MENU_PRICE_LIST,
    ID_VOIDED_LINE, ID_LINE_VOID, ID_LINE_DISCOUNT, POST_STATUS, STATUS, ID_VAT,
    DISCOUNT_SUM, ID_PRICE_LIST_OVERRULE, ID_SMETKA_BON, ID_END_WORK,
    ID_MOD_SESSION, NETO_SUM, TAX_PERCENT)
  values (:id_smetka_trans, :id_smetka_head, :id_stock, :id_invent,
    :qty, :qty_post, :qty_void, :cost_price, :sale_price, :line_sum, :void_sum,
    :id_menu_price_list,
    :id_master_line, :id_line_void, :id_line_discount, :post_status, :status, :id_vat,
    :discount_sum, :id_price_list_overrule, :id_smetka_bon, :id_end_work,
    :new_id_mod_session, :line_sum, :tax_percent);

END
^

/* empty dependent procedure body */
/* Clear: BILL_POST_FINALIZE$PDA for: BILL_POST_ADD$PDA */
ALTER PROCEDURE BILL_POST_FINALIZE$PDA(ID_CLIENT_POS INTEGER,
ID_SMETKA_HEAD INTEGER,
TABLE_NO INTEGER,
ID_MANUAL_MENU INTEGER,
ID_END_WORK INTEGER,
CUSTOMER_CNT INTEGER)
 RETURNS(ERR_CODE INTEGER,
ERR_TEXT VARCHAR(255))
 AS
 BEGIN SUSPEND; END
^

/* Alter (BILL_POST_ADD$PDA) */
ALTER PROCEDURE BILL_POST_ADD$PDA(ID_CLIENT_POS INTEGER,
ID_END_WORK INTEGER,
ID_SMETKA_HEAD INTEGER,
ID_SMETKA_TRANS INTEGER)
 RETURNS(ERR_CODE INTEGER,
ERR_TEXT VARCHAR(255),
TOTAL_SUM NUMERIC(15,4))
 AS
declare variable dbg varchar(2000);

  declare variable post_price numeric(15,4);
  declare variable stock_name varchar(50);
  declare variable pbp_dbkey char(8);
  declare variable base_dbkey char(8);
  declare variable int_mod_cnt integer;
  declare variable int_base_price numeric (15,4);
  declare variable int_line_text varchar(2000);

  declare variable id_menu_price_list integer;
  declare variable id_stock integer;
  declare variable post_qty numeric(15,4);
  declare variable base_tot_price numeric(15,4);
  declare variable mod_price numeric(15,4);

  declare variable active_user varchar(50);
  declare variable id_invent integer;
  declare variable is_modifier integer;
  declare variable id_vat integer;
  declare variable line_sum numeric(15,4);
  declare variable line_text varchar(2000);
  declare variable mod_cnt integer;
  declare variable new_id_mod_session integer;
begin
  /*  Description:
  ||
  */
  err_code = 0;
  err_text = '';
  execute procedure SYSTEM_GET_VALUE(:id_client_pos, 'CURRENT_USER')
  returning_values  :active_user;


  base_dbkey = null;
  for
    select PBP.RDB$DB_KEY, PBP.POST_PRICE, S.IS_MODIFIER, F_FIRSTUPPERCASE(S.STOCK_NAME)
    from   PDA_BILL_POST PBP
           join STOCK S on S.ID_STOCK = PBP.ID_STOCK
    where  PBP.ID_SESSION = current_connection
    order by PBP.ID_PDA_POST
    into   :pbp_dbkey, :post_price, :is_modifier, :stock_name
  do begin
    if (:is_modifier = 1) then begin
      update PDA_BILL_POST PBPU
      set    PBPU.INT_BASE_PRICE = :post_price,
             PBPU.INT_MOD_CNT = 0,
             PBPU.INT_LINE_TEXT = ''
      where  PBPU.RDB$DB_KEY = :pbp_dbkey;
      int_base_price = :int_base_price + :post_price;
      int_mod_cnt = :int_mod_cnt + 1;
      int_line_text = :int_line_text || F_CRLF() || '    -' || :stock_name;
    end else if (:base_dbkey is not null) then begin
      update PDA_BILL_POST PBPU
      set    PBPU.INT_BASE_PRICE = :int_base_price,
             PBPU.INT_MOD_CNT = :int_mod_cnt,
             PBPU.INT_LINE_TEXT = :int_line_text
      where  PBPU.RDB$DB_KEY = :base_dbkey;
      base_dbkey = null;
    end
    if (:base_dbkey is null) then begin
      base_dbkey = :pbp_dbkey;
      int_base_price = :post_price;
      int_mod_cnt = 0;
      int_line_text = :stock_name;
    end
  end
  if (:base_dbkey is not null) then begin
    update PDA_BILL_POST PBPU
    set    PBPU.INT_BASE_PRICE = :int_base_price,
           PBPU.INT_MOD_CNT = :int_mod_cnt,
           PBPU.INT_LINE_TEXT = :int_line_text
    where  PBPU.RDB$DB_KEY = :base_dbkey;
  end
  new_id_mod_session = null;
  total_sum = 0;
  for
    select PBP.ID_MENU_PRICE_LIST, PBP.ID_STOCK, PBP.POST_QTY, PBP.INT_BASE_PRICE, PBP.POST_PRICE,
           PBP.INT_MOD_CNT, PBP.INT_LINE_TEXT, S.ID_VAT_GROUP, S.IS_MODIFIER
    from   PDA_BILL_POST PBP
           join STOCK S on S.ID_STOCK = PBP.ID_STOCK
    where  PBP.ID_SESSION = current_connection
    order by PBP.ID_PDA_POST
    into   :id_menu_price_list, :id_stock, :post_qty, :base_tot_price, :mod_price,
           :mod_cnt, :line_text, :id_vat, :is_modifier
  do begin
    select ML.ID_INVENT
    from   MENU_PRICE_LIST MPL
           join MENU_LINE ML on ML.ID_MENU_HEAD = MPL.ID_MENU_HEAD
    where  MPL.ID_MENU_PRICE_LIST = :id_menu_price_list
           and ML.ID_STOCK = :id_stock
    into   :id_invent;

    if (:is_modifier = 0) then begin
      line_sum = roundto(:post_qty * :base_tot_price, 0.01);
      execute procedure BILL_POST_ADD(:id_end_work, :id_smetka_head, :id_smetka_trans, :id_menu_price_list,
              null, :id_stock, :id_invent, :id_vat, :post_qty, :base_tot_price, :line_sum, null, null, '',
              null, :line_text, :mod_cnt)
      returning_values  :err_code, :err_text, :new_id_mod_session;
      if (:err_code < 0) then exit;
    end else begin
      line_sum = 0;

      insert into SMETKA_MODIFFIER (ID_END_WORK, ID_MOD_SESSION, ID_STOCK, SALE_PRICE, NETO_SUM, SURCHARGE_SUM, DISCOUNT_SUM)
      values (:id_end_work, :new_id_mod_session, :id_stock, :mod_price, null, 0, 0);
    end
    total_sum = :total_sum + :line_sum;
  end

  delete from PDA_BILL_POST PBP where PBP.ID_SESSION = current_connection;
end
^

/* Alter (BILL_POST_FINALIZE$PDA) */
ALTER PROCEDURE BILL_POST_FINALIZE$PDA(ID_CLIENT_POS INTEGER,
ID_SMETKA_HEAD INTEGER,
TABLE_NO INTEGER,
ID_MANUAL_MENU INTEGER,
ID_END_WORK INTEGER,
CUSTOMER_CNT INTEGER)
 RETURNS(ERR_CODE INTEGER,
ERR_TEXT VARCHAR(255))
 AS
declare variable new_lines_sum numeric(15,4);
  declare variable new_id_smetka_trans integer;
  declare variable id_smetka_discount integer;
  declare variable id_contragent_ integer;
  declare variable card_code_ varchar(50);

  declare variable id_surcharge_ integer;
  declare variable surcharge_value numeric(15,4);
  declare variable is_percent_surcharge integer;
  declare variable cnt_lines integer;
  declare variable cnt_voids integer;
  declare variable total_sum numeric(15,4);
  declare variable discount_sum numeric(15,4);
  declare variable surcharge_sum numeric(15,4);
  declare variable grand_total_sum numeric(15,4);
  declare variable vip_lines integer;

  declare variable id_discount integer;
  declare variable is_percent_discount integer;
  declare variable discount_base numeric(15,4);
  declare variable discount_value numeric(15,4);

  declare variable open_type varchar(20);
  declare variable close_type varchar(20);
  declare variable discount_status integer;
  declare variable id_discount_overrrule integer;
  declare variable smetka_num varchar(20);
  declare variable no_use varchar(100);
begin
  err_code = 0;
  err_text = '';
  if (:id_smetka_head > 0) then open_type = 'OPEN';
  else open_type = 'CREATE';

  execute procedure BILL_OPEN(:id_client_pos, :id_smetka_head, :table_no, :customer_cnt, 'OPEN', :id_end_work)
  returning_values  :err_code, :err_text, :id_smetka_head, :new_id_smetka_trans,
                    :no_use, :no_use, :no_use, :id_contragent_,
                    :no_use, :id_smetka_discount, :id_surcharge_, :no_use,
                    :surcharge_value, :is_percent_surcharge, :id_discount, :is_percent_discount,
                    :no_use, :discount_status, :discount_value, :no_use,
                    :no_use, :no_use, :card_code_;
  if (:err_code < 0) then exit;

  execute procedure BILL_POST_ADD$PDA(:id_client_pos, :id_end_work, :id_smetka_head, :new_id_smetka_trans)
  returning_values  :err_code, :err_text, :new_lines_sum;
  if (:err_code < 0) then exit;

  select sum(iif(SL.STATUS < 0, 0, SL.LINE_SUM)),
         sum(iif((SL.STATUS < 0) or (SL.ID_LINE_DISCOUNT is not null), 0, SL.LINE_SUM)),
         count(SL.ID_SMETKA_LINE),
         count(iif(SL.STATUS < 0, SL.ID_SMETKA_LINE, null))
  from   SMETKA_LINE SL
  where  SL.ID_SMETKA_HEAD = :id_smetka_head
  into   :total_sum, :discount_base, :cnt_lines, :cnt_voids;

  if (:id_discount is not null) then begin
    if (:is_percent_discount = 1) then begin
      discount_sum = roundto((:discount_value/100.00) * :discount_base, 0.01);
    end else discount_sum = :discount_value;
    if (:id_smetka_discount is not null) then begin
      select SD.ID_RIGHT_OVERRULE
      from   SMETKA_DISCOUNT SD
      where  SD.ID_SMETKA_DISCOUNT = :id_smetka_discount
      into   :id_discount_overrrule;
    end else id_discount_overrrule = null;
    execute procedure BILL_POST_ADD_DISC(:id_end_work, :id_smetka_head, :id_discount, :discount_status,
            :discount_base, :discount_value, :discount_sum, :id_discount_overrrule)
    returning_values  :err_code, :err_text, :id_smetka_discount;
    if (:err_code < 0) then exit;
  end else discount_sum = 0;

  if (:id_surcharge_ is not null) then begin
    if (:is_percent_surcharge = 1) then begin
      surcharge_sum = roundto((:surcharge_value/100.00) * (:total_sum - :discount_sum), 0.01);
    end else surcharge_sum = :surcharge_value;
  end else surcharge_sum = 0;

  grand_total_sum = :total_sum - :discount_sum + :surcharge_sum;
  if (:open_type = 'CREATE' and :cnt_lines = 0) then close_type = 'CANCEL';
  else close_type = 'ORDER';
  execute procedure BILL_POST_FINALIZE(:id_client_pos, :id_end_work, :id_smetka_head, :new_id_smetka_trans,
          :id_smetka_discount, :id_contragent_, null, :open_type,
          :close_type, :id_manual_menu, :id_surcharge_, :surcharge_value, :cnt_lines,
          :cnt_voids, :total_sum, :discount_sum, :surcharge_sum, :grand_total_sum,
          :customer_cnt, :card_code_)
  returning_values  :err_code, :err_text, :vip_lines;
  if (:err_code < 0) then exit;

  execute procedure BILL_POST_FINALIZE_NUM(:id_client_pos, :id_smetka_head, :new_id_smetka_trans, :close_type, null)
  returning_values  :err_code, :err_text, :smetka_num;
  if (:err_code < 0) then exit;

  execute procedure BILL_POST_PRINT$PDA(:id_client_pos, :id_smetka_head, :new_id_smetka_trans, :close_type, :vip_lines)
  returning_values  :err_code, :err_text;
end
^

/* Alter (EAI_FRONT) */
ALTER PROCEDURE EAI_FRONT(ID_END_WORK INTEGER,
HOTEL VARCHAR(50),
ID_SMETKA_HEAD INTEGER,
ID_EAI_MAP INTEGER,
EXTERNAL_IFC VARCHAR(100),
GUEST_BOARD VARCHAR(30) = null)
 RETURNS(TAG_VALUE VARCHAR(30),
TAG_NAME VARCHAR(50),
SUM_VALUE NUMERIC(15,4),
ALL_INCLUSIVE_PAYMENT_TYPE INTEGER)
 AS
declare variable id_map_tag integer;
  declare variable id_object integer;
  declare variable id_eai_map_allinclusive integer;
  declare variable id_stock_group integer;
  declare variable has_payable smallint;
  declare variable transfer_value numeric(15,4);
  declare variable group_name varchar(30);
begin
  /*  Description:
  ||
  */

  select SH.ID_OBJECT
  from   SMETKA_HEAD SH
  where  SH.ID_SMETKA_HEAD = :id_smetka_head
  into   :id_object;

  all_inclusive_payment_type = null;
  select first 1 A.ID_PAYMENT_TYPE, A.ID_EAI_MAP_ALLINCLUSIVE
  from   EAI_MAP_ALLINCLUSIVE A
  where  A.HOTEL = :hotel
         and A.ID_OBJECT = :id_object
         and ((coalesce(a.COMPATIBLE_GUEST_BOARD, '') = '')
              or (a.COMPATIBLE_GUEST_BOARD = coalesce(:GUEST_BOARD, '')))
  order by nullif(a.COMPATIBLE_GUEST_BOARD, '') asc nulls last
  into   :ALL_INCLUSIVE_PAYMENT_TYPE, :id_eai_map_allinclusive;

  has_payable = 0;
  for
    select IFS.ID_MAP_TAG, IFS.ID_STOCK_GROUP, sum(IFS.SUM_VALUE)
    from   EAI_FRONT_SUB(:id_end_work, :id_smetka_head, :id_eai_map, :external_ifc, :id_eai_map_allinclusive) IFS
    group by 1, 2
    into   :id_map_tag, :id_stock_group, :transfer_value
  do begin
    select MT.TAG_NAME, MT.TAG_VALUE
    from   EAI_MAP_TAG MT
    where  MT.ID_MAP_TAG = :id_map_tag
    into   :tag_name, :tag_value;

    select sg.STOCK_GROUP
    from   STOCK_GROUP SG
    where  sg.ID_STOCK_GROUP = :id_stock_group
    into   :group_name;

    insert into EAI_P2F_TRANSFER_LOG (ID_SMETKA_HEAD, ID_SMETKA_PAYMENT, ID_END_WORK, EXTERNAL_IFC,
           TAG_NAME, TAG_VALUE, STOCK_GROUP, TRANSFER_AMOUNT)
    values (:ID_SMETKA_HEAD, null, :ID_END_WORK, :EXTERNAL_IFC,
           :TAG_NAME, :TAG_VALUE, :group_name, :transfer_value);
    has_payable = 1;
  end

  tag_value = null;
  tag_name = null;
  sum_value = null;
  if (:has_payable = 1) then begin
    for
      select tl.TAG_NAME, tl.TAG_VALUE, sum(tl.TRANSFER_AMOUNT)
      from   EAI_P2F_TRANSFER_LOG tl
      where  tl.EXTERNAL_IFC is not distinct from :EXTERNAL_IFC
             and ( (tl.ID_SMETKA_HEAD = nullif(:ID_SMETKA_HEAD, -1) and tl.ID_SMETKA_PAYMENT is null)
                  or (tl.ID_END_WORK = nullif(:ID_END_WORK, -1))
                 )
      group by 1, 2
      into   :TAG_NAME, :TAG_VALUE, :SUM_VALUE
    do begin
      suspend;
    end
  end else begin
    suspend;
  end
/*  end*/
end
^

/* empty dependent procedure body */
/* Clear: ENDWORK_PROCESS for: ENDWORK_SUB_CLEAR */
ALTER PROCEDURE ENDWORK_PROCESS(ID_CLIENT_POS INTEGER,
END_WORK_KIND VARCHAR(30),
NEXT_DATE DATE,
EW_USER_LIST VARCHAR(3000),
ID_CURRENT_EW INTEGER)
 RETURNS(ERR_CODE INTEGER,
ERR_TEXT VARCHAR(255),
UPD_NEXT_DATE DATE,
UPD_NEXT_ID_EW INTEGER)
 AS
 BEGIN SUSPEND; END
^

/* empty dependent procedure body */
/* Clear: ENDWORK_REGENERATE for: ENDWORK_SUB_CLEAR */
ALTER PROCEDURE ENDWORK_REGENERATE(ID_DAY_EW INTEGER,
OPTIONS VARCHAR(255))
 RETURNS(ERR_CODE INTEGER)
 AS
 BEGIN SUSPEND; END
^

/* Alter (ENDWORK_SUB_CLEAR) */
ALTER PROCEDURE ENDWORK_SUB_CLEAR(ID_END_WORK INTEGER)
 RETURNS(ERR_CODE INTEGER)
 AS
declare variable cpcdb_key char(8);
begin
  err_code = 0;

  /* CLEAR POOL LOG */
  for
    select CPC.RDB$DB_KEY
    from   CONTRAGENT_POOL_CHRONOLOGY CPC
           join SMETKA_HEAD SH on SH.ID_SMETKA_HEAD = CPC.ID_SMETKA_HEAD
    where  CPC.ALREADY_IN_HISTORY = 1
           and SH.ID_END_WORK = :id_end_work

    union

    select CPC.RDB$DB_KEY
    from   CONTRAGENT_POOL_CHRONOLOGY CPC
    where  CPC.ALREADY_IN_HISTORY = 1
           and not exists(
             select SH.ID_SMETKA_HEAD
             from   SMETKA_HEAD SH
             where  SH.ID_SMETKA_HEAD = CPC.ID_SMETKA_HEAD
           )
    into   :cpcdb_key
  do begin
    delete from CONTRAGENT_POOL_CHRONOLOGY CPC
    where  CPC.RDB$DB_KEY = :cpcdb_key;
  end
   
  delete from CONTRAGENT_POOL_CHRONOLOGY CPC
  where  CPC.ID_SMETKA_HEAD is null
         and CPC.ALREADY_IN_HISTORY = 1;

  delete from SMETKA_LINE SHL
  where  SHL.ID_END_WORK = :id_end_work;

  delete from SMETKA_HEAD SHD
  where  SHD.ID_END_WORK = :id_end_work;

  delete from SMETKA_TRANS ST
  where  ST.ID_END_WORK = :id_end_work;

  delete from SMETKA_MANAGE SM
  where  SM.ID_END_WORK = :id_end_work;

  delete from SMETKA_LINE_TEXT SLT
  where  SLT.ID_END_WORK = :id_end_work;

  delete from SMETKA_MODIFFIER SM
  where  SM.ID_END_WORK = :id_end_work;

  delete from SMETKA_PRINT_QUEUE SPQ
  where  SPQ.ID_END_WORK = :id_end_work;

  delete from SMETKA_FRONT SF
  where  SF.ID_END_WORK = :id_end_work;

end
^

/* Alter (ENDWORK_UNDO) */
ALTER PROCEDURE ENDWORK_UNDO(ID_END_WORK INTEGER,
UNDO_TYPE VARCHAR(20))
 AS
declare variable dbg varchar(2000);
  declare variable id_object integer;
  declare variable prev_date date;
  declare variable id_end_work_m integer;
begin
  if (:undo_type not in ('REVERT', 'DELETE')) then begin
    exception WRONG_VALUE;
  end

  if (:undo_type = 'REVERT') then begin
    select EW.ID_OBJECT, EW.PREV_DATE
    from   SYSTEM_END_WORK EW
    where  EW.id_end_work = :id_end_work
    into   :id_object, :prev_date;
  
    /* 1 */
    insert into SMETKA_HEAD (ID_SMETKA_HEAD, ID_END_WORK, SMETKA_DATE, TABLE_NO,
      SMETKA_NUM, ID_OBJECT, ID_CONTRAGENT, ID_CONTRAGENT_OVERRULE, TOTAL_SUM,
      DISCOUNT_SUM, SURCHARGE_SUM, GRAND_TOTAL_SUM, CUSTOMER_CNT, USER_OWNER,
      START_DATE, START_TIME, STOP_DATETIME, ID_MANUAL_PRICE_LIST, ID_SURCHARGE,
      SURCHARGE_VALUE, ID_SMETKA_DISCOUNT, STATUS, END_WORK_USER,
      END_WORK_OBJECT)
    select SH.ID_SMETKA_HEAD, SH.ID_END_WORK, SH.SMETKA_DATE, SH.TABLE_NO,
      SH.SMETKA_NUM, SH.ID_OBJECT, SH.ID_CONTRAGENT, SH.ID_CONTRAGENT_OVERRULE, SH.TOTAL_SUM,
      SH.DISCOUNT_SUM, SH.SURCHARGE_SUM, SH.GRAND_TOTAL_SUM, SH.CUSTOMER_CNT, SH.USER_OWNER,
      SH.START_DATE, SH.START_TIME, SH.STOP_DATETIME, SH.ID_MANUAL_PRICE_LIST, SH.ID_SURCHARGE,
      SH.SURCHARGE_VALUE, SH.ID_SMETKA_DISCOUNT, SH.STATUS, SH.END_WORK_USER,
      SH.END_WORK_OBJECT
    from ARCHIVE_HEAD SH
    where  SH.ID_END_WORK = :id_end_work;
  
    /* 2 */
    insert into SMETKA_TRANS
    select * from ARCHIVE_TRANS ST
    where  ST.ID_END_WORK = :id_end_work;
  
    /* 3 */
    insert into SMETKA_BON_INVENT
    select * from ARCHIVE_BON_INVENT SBI
    where  SBI.ID_END_WORK = :id_end_work;
  
    /* 4 */
    insert into SMETKA_DISCOUNT
    select * from ARCHIVE_DISCOUNT SD
    where  SD.ID_END_WORK = :id_end_work;
  
    /* 5 */
    insert into SMETKA_MANAGE
    select * from ARCHIVE_MANAGE SM
    where  SM.ID_END_WORK = :id_end_work;
  
    /* 6 */
    insert into SMETKA_LINE
    select * from ARCHIVE_LINE SL
    where  SL.ID_END_WORK = :id_end_work;
  
    insert into SMETKA_LINE_TEXT
    select * from ARCHIVE_LINE_TEXT SL
    where  SL.ID_END_WORK = :id_end_work;

    insert into SMETKA_MODIFFIER
    select * from ARCHIVE_MODIFFIER SM
    where  SM.ID_END_WORK = :id_end_work;

    /* 7 */
    insert into SMETKA_FRONT (ID_SMETKA_FRONT, ID_END_WORK, ID_ACCOUNT,
      GUEST_NAME, ROOM_NAME, HOTEL_NAME, SMETKA_DATE, GUEST_BOARD, TRANSFER_AMOUNT)
    select SF.ID_SMETKA_FRONT, SF.ID_END_WORK, SF.ID_ACCOUNT,
      SF.GUEST_NAME, SF.ROOM_NAME, SF.HOTEL_NAME, SF.SMETKA_DATE, SF.GUEST_BOARD, SF.TRANSFER_AMOUNT
    from   ARCHIVE_FRONT SF
    where  SF.ID_END_WORK = :id_end_work;

    /* 8 */
    insert into SMETKA_PAYMENT (ID_SMETKA_PAYMENT, ID_SMETKA_HEAD, ID_END_WORK,
      ID_SMETKA_TRANS, ID_PAYMENT_TYPE, ID_PAYMENT_OVERRULE, ID_PAYMENT_VOID,
      PAYMENT_VALUE, CHANGE_VALUE, STATUS, FISC_STATUS, ID_SMETKA_FRONT)
    select SP.ID_SMETKA_PAYMENT, SP.ID_SMETKA_HEAD, SP.ID_END_WORK,
      SP.ID_SMETKA_TRANS, SP.ID_PAYMENT_TYPE, SP.ID_PAYMENT_OVERRULE, SP.ID_PAYMENT_VOID,
      SP.PAYMENT_VALUE, SP.CHANGE_VALUE, SP.STATUS, SP.FISC_STATUS, SP.ID_SMETKA_FRONT
    from ARCHIVE_PAYMENT SP
    where  SP.ID_END_WORK = :id_end_work;

    /* 9 */
    insert into SMETKA_PAYMENT_EXTERNAL(ID_SMETKA_PAYMENT, EXTERNAL_DATA, VOID_ERR_CODE,
           EXTERNAL_TEXT, EXTERNAL_IFC, INTERNAL_DATA)
    select SPE.ID_SMETKA_PAYMENT, SPE.EXTERNAL_DATA, SPE.VOID_ERR_CODE,
           SPE.EXTERNAL_TEXT, SPE.EXTERNAL_IFC, spe.INTERNAL_DATA
    from   ARCHIVE_PAYMENT_EXTERNAL SPE
           join ARCHIVE_PAYMENT SP on SP.ID_SMETKA_PAYMENT = SPE.ID_SMETKA_PAYMENT
    where  SP.ID_END_WORK = :id_end_work;

    /* 10 */
    insert into SMETKA_FOOTER
    select * from ARCHIVE_FOOTER SF
    where  SF.ID_END_WORK = :id_end_work;

    /* 11 */
    insert into SMETKA_TAX (ID_SMETKA_HEAD, ID_TAX, TAX_NAME, TAX_PERCENT, TAX_VALUE, TAXABLE_VALUE, ID_END_WORK)
    select ID_SMETKA_HEAD, ID_TAX, TAX_NAME, TAX_PERCENT, TAX_VALUE, TAXABLE_VALUE, ID_END_WORK
    from   ARCHIVE_TAX t
    where  t.ID_END_WORK = :id_end_work;

    update NOM_OBJECT O
    set    O.SYSTEM_DATE = :prev_date,
           O.ID_EW_NEXT  = :id_end_work
    where  O.ID_OBJECT   = :id_object;
  end

  delete from ARCHIVE_BON_INVENT
  where id_end_work = :id_end_work;

  delete from ARCHIVE_DISCOUNT
  where id_end_work = :id_end_work;

  delete from ARCHIVE_FOOTER
  where id_end_work = :id_end_work;

  delete from ARCHIVE_FRONT
  where id_end_work = :id_end_work;

  delete from ARCHIVE_HEAD
  where id_end_work = :id_end_work;

  delete from ARCHIVE_LINE
  where id_end_work = :id_end_work;

  delete from SMETKA_LINE_TEXT
  where id_end_work = :id_end_work;

  delete from SMETKA_MODIFFIER
  where id_end_work = :id_end_work;

  delete from ARCHIVE_MANAGE
  where id_end_work = :id_end_work;

  delete from ARCHIVE_PAYMENT
  where id_end_work = :id_end_work;
/* TRQBVA REFERENTALA DA SVYRSHI TOVA
  delete from ARCHIVE_PAYMENT_EXTERNAL
  where id_end_work = :id_end_work;
*/
  delete from ARCHIVE_TRANS
  where id_end_work = :id_end_work;

  delete from ARCHIVE_TAX
  where  ID_END_WORK = :id_end_work;

  delete from SUM_DAY
  where id_end_work = :id_end_work;

  delete from SUM_STOCK
  where id_end_work = :id_end_work;

  delete from SUM_DISCOUNT
  where id_end_work = :id_end_work;

  delete from SUM_VOID
  where id_end_work = :id_end_work;

  delete from EAI_P2F_TRANSFER_LOG tl
  where  tl.ID_END_WORK = :id_end_work;

  for
    select  EW.ID_END_WORK
    from    SYSTEM_END_WORK EW
    where   EW.ID_DAY_MASTER = :id_end_work
            and ((:undo_type = 'DELETE') or (EW.EW_KIND=2 /* DAY */))
    into    :id_end_work_m
  do begin
    delete from EAI_EFFECT_SALE S
    where  S.END_WORK_DAY = :id_end_work_m;

    delete from SYSTEM_END_WORK
    where id_end_work = :id_end_work_m;
  end
end
^

/* Alter (FISCALIZE_LINE$FISC) */
ALTER PROCEDURE FISCALIZE_LINE$FISC(ID_DOC_HEAD INTEGER,
DETAIL_LEVEL VARCHAR(20),
ADDITIONAL_PAYMENT_TEXT VARCHAR(30) = null)
 RETURNS(FISC_PRICE NUMERIC(15,4),
FISC_QTY NUMERIC(15,4),
FISC_TEXT VARCHAR(30),
FISC_GRP VARCHAR(10),
TRANSACTION_VALUE NUMERIC(15,4))
 AS
declare variable dbg varchar(2000);
  declare variable fisc_status integer;
begin
  /*  Description:
  ||   DETAIL_LEVEL = {1 group,  2 detail}

  function fiscalize(const text, taxGroup: string; qty, price, correction: Double): integer;
  function payment(const text, payType: string; summ: Double): integer;

  */
  fisc_price = null;
  fisc_text = null;
  fisc_grp = null;
  transaction_value = null;

/* PRINT THE DOC NUMBER AS FREE TEXT. NON SUPPORTED FOR NOW!
  fisc_text = :doc_num;
  suspend;
*/

  select max(SP.FISC_STATUS)
  from   SMETKA_PAYMENT SP
         join SMETKA_HEAD SH on SH.ID_SMETKA_HEAD = Sp.ID_SMETKA_HEAD
         join NOM_PAYMENT_TYPE PT on PT.ID_PAYMENT_TYPE = SP.ID_PAYMENT_TYPE
  where  SH.ID_SMETKA_HEAD = :id_doc_head
         and SP.ID_PAYMENT_VOID is null
         and SH.STATUS = 2
  into   :fisc_status;

  if (:fisc_status <> 1) then exit;

  if (:detail_level = 'group') then begin
    execute procedure SYSTEM_GET_TEXT(null, 'FISC_TEXT')
    returning_values  :fisc_text;
    for
      select VG.VAT_CODE, roundto(sum(SL.NETO_SUM), 0.01)
      from   SMETKA_HEAD SH
             join BILL_NETO SL on SL.ID_SMETKA_HEAD = SH.ID_SMETKA_HEAD
             --join SMETKA_LINE SL on SL.ID_SMETKA_HEAD = SH.ID_SMETKA_HEAD
             left outer join STOCK S on S.ID_STOCK = SL.ID_STOCK
             left outer join NOM_VAT_GROUP VG on VG.ID_VAT = S.ID_VAT_GROUP
      where  SH.ID_SMETKA_HEAD = :id_doc_head
             and SH.STATUS = 2
             and SL.STATUS > 0
      group by 1
      into   :fisc_grp, :transaction_value
    do begin
      fisc_qty = 1;
      fisc_price =  :transaction_value;
      suspend;
    end
  end else begin
    for
      select VG.VAT_CODE, S.STOCK_NAME, roundto(sum(SL.NETO_SUM), 0.01), sum(SL.QTY)
      from   SMETKA_HEAD SH
             join BILL_NETO SL on SL.ID_SMETKA_HEAD = SH.ID_SMETKA_HEAD
             --join SMETKA_LINE SL on SL.ID_SMETKA_HEAD = SH.ID_SMETKA_HEAD
             left outer join STOCK S on S.ID_STOCK = SL.ID_STOCK
             left outer join NOM_VAT_GROUP VG on VG.ID_VAT = S.ID_VAT_GROUP
      where  SL.ID_SMETKA_HEAD = :id_doc_head
             and SH.STATUS = 2
             and SL.STATUS > 0
      group by 1, 2
      into   :fisc_grp, :fisc_text, :transaction_value, :fisc_qty
    do begin
      fisc_price =  roundto(:transaction_value / :fisc_qty, 0.01);
      suspend;
    end
  end

  fisc_price = null;
  select SH.SURCHARGE_SUM, D.DISCOUNT_NAME, 'SRV', SH.SURCHARGE_SUM, 1
  from   SMETKA_HEAD SH
         join NOM_DISCOUNT D on D.ID_DISCOUNT = SH.ID_SURCHARGE
  where  SH.ID_SMETKA_HEAD = :id_doc_head
  into   :fisc_price, :fisc_text, :fisc_grp, :transaction_value, :FISC_QTY;
  if (:fisc_price is not null) then suspend;
end
^

/* Alter (MANAGE_VOID_BILL) */
ALTER PROCEDURE MANAGE_VOID_BILL(ID_CLIENT_POS INTEGER,
ID_SMETKA_HEAD INTEGER,
ID_VOID_REASON INTEGER,
ID_VOID_OVERRULE INTEGER)
 RETURNS(ERR_CODE INTEGER,
ERR_TEXT VARCHAR(255),
CLOSE_TYPE VARCHAR(10),
VIP_LINES INTEGER,
NEW_ID_SMETKA_TRANS INTEGER)
 AS
declare variable dbg varchar(2000);
  declare variable cnt_voids integer;
  declare variable id_smetka_void integer;
  declare variable active_user varchar(50);
  declare variable right_required varchar(20);
  declare variable smetka_status integer;
  declare variable id_smetka_line integer;
  declare variable id_menu_price_lis integer;
  declare variable id_invent integer;
  declare variable id_stock integer;
  declare variable id_vat integer;
  declare variable qty numeric(15, 4);
  declare variable sale_price numeric(15, 4);
  declare variable line_sum numeric(15, 4);
  declare variable VIP_lines_bill integer;
  declare variable id_contragent integer;
  declare variable id_current_ew integer;
  declare variable no_use integer;
  declare variable card_code varchar(50);
begin
  err_code = 0;
  err_text = '';
  select SH.STATUS, SH.ID_CONTRAGENT, SH.CARD_CODE
  from   SMETKA_HEAD SH
  where  SH.ID_SMETKA_HEAD = :id_smetka_head
  into   :smetka_status, :id_contragent, :card_code;

  if (:smetka_status is null) then err_code = -158;
  else if (:smetka_status not in (1, 2)) then err_code = -155;
  if (:err_code < 0) then exit;

  if (:smetka_status = 2) then begin
    right_required = 'BILL_VOID_TOTAL';
    close_type = 'TOTAL_VOID';
  end else if (:smetka_status = 1) then begin
    right_required = 'BILL_VOID_OPEN';
    close_type = 'OPEN_VOID';
  end

  execute procedure SYSTEM_CHECK_RIGHT(:id_client_pos, :right_required)
  returning_values  :err_code, :err_text;
  if (:err_code < 0) then exit;

  execute procedure MANAGE_COMMON(:id_client_pos, null, :id_smetka_head, :close_type,
    :id_void_reason, :id_void_overrule, '', 'LOG')
  returning_values  :err_code, :err_text, :id_smetka_void;
  if (:err_code < 0) then exit;

  execute procedure SYSTEM_GET_VALUE(:id_client_pos, 'CURRENT_USER')
  returning_values  :active_user;

  execute procedure SYSTEM_GET_VALUE(:id_client_pos, 'CURRENT_EW')
  returning_values  :id_current_ew;

  execute procedure BILL_TRANSACTION(null, :id_current_ew, :active_user, 0, 0, 'START')
  returning_values  :err_code, :err_text, :new_id_smetka_trans;
  if (:err_code < 0) then exit;

  /* 1. PAY_VOID  */
  if (:close_type = 'TOTAL_VOID') then begin
    update SMETKA_HEAD SH
    set    SH.STATUS = 1,
           SH.STOP_DATETIME = null
    where  SH.ID_SMETKA_HEAD = :id_smetka_head;

    execute procedure BILL_PAYMENT_VOID(:id_client_pos, :id_smetka_head, :new_id_smetka_trans,
      :id_void_reason, :id_void_overrule)
    returning_values  :err_code, :err_text;
    if (:err_code < 0) then exit;
  end

  /* 2. VOID_LINES */
  cnt_voids = 0;
  for
    select SL.ID_SMETKA_LINE, SL.ID_MENU_PRICE_LIST, SL.ID_INVENT, SL.ID_STOCK, SL.ID_VAT,
           SL.QTY, SL.SALE_PRICE, SL.LINE_SUM
    from   SMETKA_LINE SL
    where  SL.ID_SMETKA_HEAD = :id_smetka_head
           and SL.STATUS > 0
    into   :id_smetka_line, :id_menu_price_lis, :id_invent, :id_stock, :id_vat,
           :qty, :sale_price, :line_sum
  do begin
    execute procedure BILL_POST_ADD(:id_current_ew, :id_smetka_head, :new_id_smetka_trans, :id_menu_price_lis, null,
      :id_stock, id_invent, :id_vat, :qty, :sale_price, :line_sum, null, :id_smetka_void,
      'OLD', :id_smetka_line, null, null)
    returning_values  :err_code, :err_text, :no_use;
    if (:err_code < 0) then exit;

    execute procedure BILL_POST_ADD(:id_current_ew, :id_smetka_head, :new_id_smetka_trans, :id_menu_price_lis, null,
      :id_stock, id_invent, :id_vat, 0, :sale_price, 0, null, null,
      'EDIT_VOID', :id_smetka_line, null, null)
    returning_values  :err_code, :err_text, :no_use;
    if (:err_code < 0) then exit;
    cnt_voids = :cnt_voids + 1;
  end

  /* 3. BILL_FINILIZE */
  execute procedure BILL_POST_FINALIZE(:id_client_pos, :id_current_ew, :id_smetka_head, :new_id_smetka_trans, null,
   :id_contragent, null, 'OPEN', :close_type, null, null, 0, :cnt_voids, :cnt_voids, 0, 0, 0, 0, 0, :card_code)
  returning_values :err_code, err_text, :VIP_lines;
end
^

/* Alter (STOCK_MODIFY) */
ALTER PROCEDURE STOCK_MODIFY(ID_STOCK INTEGER,
STOCK_NAME VARCHAR(30),
STOCK_NAME_SEARCH VARCHAR(30),
COST_PRICE NUMERIC(15,4),
ID_STOCK_GROUP INTEGER,
IS_USE SMALLINT,
POS_CODE VARCHAR(30),
NOTE VARCHAR(100),
ID_VAT_GROUP INTEGER,
IS_SERVICE SMALLINT,
IS_FREE_VOID SMALLINT,
IS_FREE_PRICE SMALLINT,
IS_MODIFIER SMALLINT,
TRADE_CODE VARCHAR(30),
OPERATION VARCHAR(20))
 RETURNS(NEW_ID_STOCK INTEGER,
NEW_POS_CODE VARCHAR(30),
ERR_CODE INTEGER,
ERR_TEXT VARCHAR(255))
 AS
declare variable is_barcode integer;
  declare variable enterprise_mode varchar(255);
  declare variable s_dbkey char(8);
  declare variable old_is_service integer;
  declare variable old_is_modifier integer;
  declare variable service_status_can_be_changed integer;
  declare variable modifier_status_can_be_changed integer;
  declare variable max_pos_length integer;
  declare variable old_cost_price numeric(15,4);
begin
  err_code = 0;
  err_text = '';
  max_pos_length = 5;

  if (:operation not in('add', 'mod', 'del', 'gen_pos_code')) then begin
    err_code = -1;
    err_text = 'operation unknown !';
  end

  if (operation = 'gen_pos_code') then begin
    new_pos_code = null;
    select max(cast(S.POS_CODE as integer))+1
    from   STOCK S
    where  S.IS_BARCODE = 0
           and S.POS_CODE <> ''
    into   :new_pos_code;
    if (:new_pos_code is null) then new_pos_code = 1;
  end else if (operation = 'add') then begin
    if ((:id_stock is null) or (:id_stock <= 0)) then new_id_stock = gen_id(gen_stock_id, 1);
    else new_id_stock = :id_stock;

    if(StrLen(:pos_code) <= :max_pos_length) then is_barcode = 0;
    else is_barcode = 1;
    insert into stock (ID_STOCK, STOCK_NAME, STOCK_NAME_SEARCH, COST_PRICE,
      ID_STOCK_GROUP, IS_USE, POS_CODE, NOTE, ID_VAT_GROUP, IS_SERVICE,
      IS_FREE_VOID, IS_FREE_PRICE, IS_BARCODE, TRADE_CODE, IS_MODIFIER)
    values (:new_id_stock, :stock_name, :stock_name_search, :cost_price,
      :id_stock_group, :is_use, :pos_code, :note, :id_vat_group,:is_service,
      :is_free_void, :is_free_price, :is_barcode, :trade_code, :is_modifier);
  end else if (operation = 'mod') then begin
    if(StrLen(:pos_code) <= :max_pos_length) then is_barcode = 0;
    else is_barcode = 1;
    select S.rdb$db_key, S.IS_SERVICE, S.IS_MODIFIER, s.COST_PRICE
    from   STOCK S
    where  S.ID_STOCK = :id_stock
    into   :s_dbkey, :old_is_service, :old_is_modifier, :old_cost_price;

    if (:old_is_service <> :is_service) then begin
      /* CHECK IF THE STOCK IS SOLD */
      if (exists(
        select *
        from   SMETKA_LINE SL
        where  SL.ID_STOCK = :id_stock)
      ) then service_status_can_be_changed = 0;
      else if (exists(
        select *
        from   SUM_STOCK SS
        where  SS.ID_STOCK = :id_stock)
      ) then service_status_can_be_changed = 0;
      else service_status_can_be_changed = 1;

      if (:service_status_can_be_changed = 0) then begin
        err_code = -162;
        exit;
      end else begin
        update STOCK S
        set    S.IS_SERVICE = :is_service
        where  S.RDB$DB_KEY = :s_dbkey;
      end
    end

    if (:old_is_modifier <> :is_modifier) then begin
      /* CHECK IF THE STOCK IS SOLD OR PARTICIPATE IN MENU */
      if (exists(
        select *
        from   MENU_LINE ML
        where  ML.ID_STOCK = :id_stock)
      ) then modifier_status_can_be_changed = 0;
      else if (exists(
        select *
        from   SMETKA_LINE SL
        where  SL.ID_STOCK = :id_stock)
      ) then modifier_status_can_be_changed = 0;
      else if (exists(
        select *
        from   SUM_STOCK SS
        where  SS.ID_STOCK = :id_stock)
      ) then modifier_status_can_be_changed = 0;
      else modifier_status_can_be_changed = 1;
      if (:modifier_status_can_be_changed = 0) then begin
        err_code = -163;
        exit;
      end else begin
        update STOCK S
        set    S.IS_MODIFIER = :is_modifier
        where  S.RDB$DB_KEY = :s_dbkey;
      end
    end

    update STOCK S
    set    S.STOCK_NAME = :stock_name,
           S.STOCK_NAME_SEARCH = :stock_name_search,
           S.COST_PRICE = :cost_price,
           S.ID_STOCK_GROUP = :id_stock_group,
           S.IS_USE = :is_use,
           S.POS_CODE = :pos_code,
           S.NOTE = :note,
           S.ID_VAT_GROUP = :id_vat_group,
           S.IS_FREE_VOID = :is_free_void,
           S.IS_FREE_PRICE = :is_free_price,
           S.IS_BARCODE = :is_barcode,
           S.TRADE_CODE = :trade_code
    where  S.RDB$DB_KEY = :s_dbkey;

    if (:COST_PRICE is distinct from :old_cost_price) then
      execute procedure STOCK_INVALIDATE_PRICE_LIST (:ID_STOCK);

  end else if (operation = 'del') then begin
    execute procedure SYSTEM_INFO_GET('ENTERPRISE_MODE')
    returning_values  :enterprise_mode;
    if (:enterprise_mode = 'CENTRAL') then begin
      err_code = -3;
      err_text = 'IN ENTERPRISE MODE STOCKS ARE IMMUTABLE';
      exit;
    end
     
    delete from stock
    where  id_stock = :id_stock;

    when sqlcode -530 do begin
      ERR_CODE = -309;
      exit;
    end
  end
end
^

/* Alter (SYS_PRINT_TOTAL) */
ALTER PROCEDURE SYS_PRINT_TOTAL(ID_SMETKA_HEAD INTEGER)
 RETURNS(LINE_NAME VARCHAR(30))
 AS
declare variable sort_order integer;
  declare variable is_modifier integer;
  declare variable stock_name varchar(30);
  declare variable sale_price numeric (15,4);
  declare variable qty numeric (15,4);
  declare variable line_sum numeric (15,4);
  declare variable discount_value numeric (15,4);
  declare variable is_percent integer;
  declare variable id_line_discount integer;
  declare variable discount_text varchar(30);
  declare variable qformat varchar(30);
  declare variable pformat varchar(30);
  declare variable prev_line_name varchar(30);
  declare variable prev_sort_order integer;
  declare variable master_changed integer;
  declare variable print_modifiers integer;
begin
  /*  Description:
  ||
  */
  qformat = 'F;0.000';
  pformat = 'F;0.00';
  prev_sort_order = null;
  master_changed = 0;
/*
  execute procedure SYSTEM_GET_VALUE(, 'PRINT_MODIFIERS')
  returning_values  :print_modifiers;
*/
  select SV.SETTING_VALUE
  from   SMETKA_HEAD SH
         join NOM_OBJECT O on O.ID_OBJECT = SH.ID_OBJECT
         join SETTING_VALUE SV on SV.ID_SETTING_PROFILE = O.ID_SETTING_PROFILE
         join SETTING S on S.ID_SETTING = SV.ID_SETTING
  where  S.SETTING_CODE = 'PRINT_MODIFIERS'
         and SH.ID_SMETKA_HEAD = :id_smetka_head
  into   :print_modifiers;

  for
    /* AGGREGATE STOCKS WITHOUT MODIFIERS AND DISCOUNTS */
    select 0 as sort_order, -1 as is_modifier,
           S.STOCK_NAME, 
           SL.SALE_PRICE,
           sum(SL.QTY) as QTY,
           sum(SL.LINE_SUM) as LINE_SUM,
    
           cast(0 as numeric (15,4)) as DISCOUNT_VALUE,
           cast(0 as smallint) as IS_PERCENT,
           cast(null as integer) as ID_LINE_DISCOUNT
    from   SMETKA_LINE SL
           left outer join STOCK S on S.ID_STOCK = SL.ID_STOCK
    where  SL.ID_SMETKA_HEAD = :ID_SMETKA_HEAD
           and SL.STATUS > 0
           and SL.ID_LINE_DISCOUNT is null
           and ((SL.ID_MOD_SESSION < 0) or (:print_modifiers = 0))/* DOES NOT HAVE MODIFIERS */
    group by S.STOCK_NAME, SL.SALE_PRICE
    
    union all
    
    /* STOCKS WITH MODIFIERS AND WITHOUT DISCOUNTS */
    select SL.ID_SMETKA_LINE as sort_order, 0 as is_modifier,
           S.STOCK_NAME, 
           SL.SALE_PRICE,
           SL.QTY as QTY,
           SL.LINE_SUM,
    
           cast(0 as numeric (15,4)) as DISCOUNT_VALUE,
           cast(0 as smallint) as IS_PERCENT,
           cast(null as integer) as ID_LINE_DISCOUNT
    from   SMETKA_LINE SL
           left outer join STOCK S on S.ID_STOCK = SL.ID_STOCK
    where  SL.ID_SMETKA_HEAD = :ID_SMETKA_HEAD
           and SL.STATUS > 0
           and SL.ID_LINE_DISCOUNT is null
           and SL.ID_MOD_SESSION > 0 and :print_modifiers = 1 /* DOES HAVE MODIFIERS */

    union all
    
    /* STOCKS WITH DISCOUNTS, MODIFIERS DOESN`T MATTER */
    select SL.ID_SMETKA_LINE, 0 as is_modifier,
           S.STOCK_NAME, 
           SL.SALE_PRICE,
           SL.QTY as QTY,
           SL.LINE_SUM,
    
           SD.DISCOUNT_VALUE,
           D.IS_PERCENT,
           D.ID_DISCOUNT
    from   SMETKA_LINE SL
           left outer join STOCK S on S.ID_STOCK = SL.ID_STOCK
           join SMETKA_DISCOUNT SD on SL.ID_LINE_DISCOUNT = SD.ID_SMETKA_DISCOUNT
           join NOM_DISCOUNT D on D.ID_DISCOUNT = SD.ID_DISCOUNT
    where  SL.ID_SMETKA_HEAD = :ID_SMETKA_HEAD
           and SL.STATUS > 0
    
    union all

    /* STOCKS THAT ARE MODIFIERS */
    select SL.ID_SMETKA_LINE, 1 as is_modifier,
           S.STOCK_NAME, 
           SM.SALE_PRICE,
           cast(0 as numeric(15,4)),
           cast(0 as numeric(15,4)),

           cast(0 as numeric (15,4)) as DISCOUNT_VALUE,
           cast(0 as smallint) as IS_PERCENT,
           cast(null as integer) as ID_LINE_DISCOUNT
    from   SMETKA_LINE SL
           join SMETKA_MODIFFIER SM on SM.ID_MOD_SESSION = SL.ID_MOD_SESSION
           left outer join STOCK S on S.ID_STOCK = SM.ID_STOCK
    where  SL.ID_SMETKA_HEAD = :ID_SMETKA_HEAD
           and SL.STATUS > 0
           and :print_modifiers = 1
    order by 1 asc, 2 asc
    into  :sort_order, :is_modifier,
          :stock_name, :sale_price, :qty, :line_sum,
          :discount_value, :is_percent, :id_line_discount
  do begin
    if (:is_modifier >= 0) then begin
      if (:prev_sort_order is null) then prev_sort_order = :sort_order;
      else if (:sort_order <> :prev_sort_order) then begin
        line_name = :prev_line_name;
        suspend;
        prev_sort_order = :sort_order;
      end
    end
    if (:is_modifier <= 0) then begin
      if (:id_line_discount is not null) then begin
        if (:is_percent = 1) then discount_text = '('||float_to_str(:discount_value, 'F;0')||'%)';
        else discount_text = '('||float_to_str(:discount_value, 'F;0.00')||')';
      end else discount_text = '';
      line_name = substring(:discount_text||:stock_name from 1 for 30);
      suspend;
      prev_line_name = substring(
                    f_PadLeft(float_to_str(:qty, :qformat), ' ', 8)||'*'||
                    f_PadLeft(float_to_str(:sale_price, :pformat), ' ', 7)||'    ='||
                    f_PadLeft(float_to_str(:line_sum, :pformat), ' ', 9)
                  from 1 for 30);
      if (:is_modifier = -1) then begin
        line_name = :prev_line_name;
        suspend;
        prev_line_name = '';
      end
    end else begin
      line_name = substring(' *'||:stock_name from 1 for 30);
      suspend;
    end
  end
  if (:prev_sort_order is not null) then begin
    line_name = :prev_line_name;
    suspend;
  end
end
^

/* Restore proc. body: ENDWORK_PROCESS */
ALTER PROCEDURE ENDWORK_PROCESS(ID_CLIENT_POS INTEGER,
END_WORK_KIND VARCHAR(30),
NEXT_DATE DATE,
EW_USER_LIST VARCHAR(3000),
ID_CURRENT_EW INTEGER)
 RETURNS(ERR_CODE INTEGER,
ERR_TEXT VARCHAR(255),
UPD_NEXT_DATE DATE,
UPD_NEXT_ID_EW INTEGER)
 AS
declare variable dbg varchar(3000);
  declare variable id_object integer;
  declare variable id_sales integer;
  declare variable id_ew_next integer;
  declare variable user_name varchar(30);
  declare variable prev_date date;
  declare variable replication integer;
  declare variable id_current_day_ew integer;
  declare variable ew_user_name varchar(30);
  declare variable no_use integer;
  declare variable suppress_object integer;
begin
  err_code = 0;
  err_text = ''; replication = 0; /* MUST BE A SETTING */
  upd_next_id_ew = null;
  /* Description
  ||
  */
  if (:end_work_kind = 'SERVER_ALL') then end_work_kind = 'SERVER';
  if (:end_work_kind not in ('DAY', 'SERVER', 'OBJECT')) then begin
    err_code = -1;
    err_text = 'end_work_kind = '||:end_work_kind;
    exit;
  end
  /*  user expiration*/

  execute procedure SYSTEM_GET_VALUE(:id_client_pos, 'CURRENT_USER')
  returning_values  :user_name;

  execute procedure SYSTEM_GET_VALUE(:id_client_pos, 'CURRENT_EW')
  returning_values  :id_current_day_ew;

  execute procedure SYSTEM_GET_VALUE(:id_client_pos, 'CURRENT_OBJECT')
  returning_values  :id_object;

  select O.ID_EW_NEXT, O.SYSTEM_DATE
  from   NOM_OBJECT O
  where  O.ID_OBJECT = :id_object
  into   :id_ew_next, :prev_date;

  if (:end_work_kind = 'DAY') then begin
    execute procedure SYSTEM_GET_VALUE(:id_client_pos, 'SUPPRESS_OBJECT')
    returning_values  :suppress_object;
    if (:suppress_object = 1) then begin
      execute procedure NOM_MODIFY_OBJECT_SUPPRESS(:id_client_pos, :id_object, 'rise')
      returning_values  :err_code, :err_text;
      if (:err_code < 0) then exit;
    end
    insert into SYSTEM_END_WORK(ID_END_WORK, ID_OBJECT, PREV_DATE, NEXT_DATE,
      EW_USER, EW_KIND, ID_DAY_MASTER)
    values (:id_current_ew, :id_object, :prev_date, :next_date,
      :user_name, 2, :id_current_ew);

    update SYSTEM_END_WORK SEW
    set    SEW.ID_DAY_MASTER = :id_current_ew
    where  SEW.ID_OBJECT = :id_object
           and SEW.ID_DAY_MASTER is null;

    update SYSTEM_NOMERATOR N
    set    N.NUM_NEXT = 1
    where  N.NUM_CLASS = 'BILL'
           and N.NUM_OBJECT = :id_object;

    /* archive */
    execute procedure ENDWORK_SUB_ARCHIVE(:id_current_day_ew)
    returning_values  :err_code;
    if (:err_code < 0) then exit;

    if (:replication = 0) then begin
      /* summarize  */
      execute procedure ENDWORK_SUB_SUMMARY(:id_current_day_ew, :id_object, :prev_date)
      returning_values  :err_code;
      if (:err_code < 0) then exit;

      execute procedure ENDWORK_SUB_CLEAR(:id_current_day_ew)
      returning_values  :err_code;
      if (:err_code < 0) then exit;
    end
    upd_next_date = :next_date;
    execute procedure ENDWORK_GETID(:id_object, 'JUST_GEN', '')
    returning_values  :err_code, :err_text, :upd_next_id_ew, :no_use;
  end else if (:end_work_kind = 'OBJECT') then begin
    /* INTERFASE_TRADE */
    execute procedure EAI_EFFECT(:id_current_day_ew, :id_current_ew, :id_object, :prev_date)
    returning_values  :err_code, :id_sales;

    insert into SALES_HEAD (
      ID_SALES, ID_OBJECT, ID_END_WORK, SALE_DATE, IS_ACTIVE, IS_VALID, NOTE, SALE_NUM)
    select
      SH.ID_SALE_HEAD, SH.ID_OBJECT, SH.END_WORK_DAY, SH.SALE_DATE, SH.IS_ACTIVE, 1, SH.NOTE, SH.ID_SALE_HEAD
    from   EAI_EFFECT_SALE SH
    where  SH.ID_SALE_HEAD = :id_sales;
    
    insert into SALES_LINE (
      ID_SALE_LINE, ID_SALES, ID_STOCK, ID_INVENT, SALE_QTY, SALE_PRICE,
      BASE_PRICE, IS_DDS, DDS_STAVKA, DDS_GROUP, POS_CODE, IS_FISCAL, ID_MENU,
      ID_SMETKA, ID_TYPE_PAYMENT)
    select
      SL.ID_SALE_LINE, SL.ID_SALE_HEAD, SL.ID_POST_ITEM, SL.ID_INVENT_DELIVERY, SL.SALE_QTY, 0,
      0, 1, SL.VAT_VALUE, SL.VAT_NAME, SL.POS_CODE, 1, -1,
      -1, null
    from   EAI_EFFECT_LINE SL
    where  SL.ID_SALE_HEAD = :id_sales;

    update SMETKA_HEAD SH
    set    SH.END_WORK_OBJECT = :id_current_ew
    where  SH.ID_END_WORK = :id_current_day_ew
           and SH.END_WORK_OBJECT is null;

    insert into SYSTEM_END_WORK(ID_END_WORK, ID_OBJECT, PREV_DATE, NEXT_DATE,
      EW_USER, EW_KIND, ID_DAY_MASTER)
    values (:id_current_ew, :id_object, :prev_date, null,
      :user_name, 1, null);
  end else if (:end_work_kind = 'SERVER') then begin
    for
      select SSP.ITEM
      from   SYSTEM_STRING_PARSER(:ew_user_list, ',') SSP
      into   :ew_user_name
    do begin
      update SMETKA_HEAD SH
      set    SH.END_WORK_USER = :id_current_ew
      where  SH.ID_END_WORK = :id_current_day_ew
             and SH.END_WORK_USER is null
             and SH.USER_OWNER = :ew_user_name;
    end

    insert into SYSTEM_END_WORK(ID_END_WORK, ID_OBJECT, PREV_DATE, NEXT_DATE,
      EW_USER, EW_KIND, ID_DAY_MASTER)
    values (:id_current_ew, :id_object, :prev_date, null,
      :user_name, 0, null);
  end
end
^

/* Restore proc. body: ENDWORK_REGENERATE */
ALTER PROCEDURE ENDWORK_REGENERATE(ID_DAY_EW INTEGER,
OPTIONS VARCHAR(255))
 RETURNS(ERR_CODE INTEGER)
 AS
declare variable dbg varchar(2000);
  declare variable id_object integer;
  declare variable fiscal_date date;
  declare variable id_invent_ew integer;
  declare variable no_use varchar(20);
begin
  /*  Description:
  ||
  */
  select EW.ID_OBJECT, EW.PREV_DATE
  from   SYSTEM_END_WORK EW
  where  EW.ID_END_WORK = :id_day_ew
  into   :id_object, :fiscal_date;

  execute procedure ENDWORK_UNDO(:id_day_ew, 'REVERT');
  
  execute procedure ENDWORK_SUB_ARCHIVE(:id_day_ew)
  returning_values  :err_code;
  
  execute procedure ENDWORK_SUB_SUMMARY(:id_day_ew, :id_object, :fiscal_date)
  returning_values  :err_code;

  if (:options = 'with_effect_export') then begin
    for
      select EW.ID_END_WORK
      from   SYSTEM_END_WORK EW
      where  EW.ID_DAY_MASTER = :id_day_ew
             and EW.EW_KIND = 1
      into   :id_invent_ew
    do begin
      delete from EAI_EFFECT_SALE S
      where  S.END_WORK_DAY = :id_invent_ew;
      update SMETKA_HEAD SH
      set    SH.END_WORK_OBJECT = null
      where  SH.END_WORK_OBJECT = :id_invent_ew;
      execute procedure EAI_EFFECT(:id_day_ew, :id_invent_ew, :id_object, :fiscal_date)
      returning_values  :err_code, :no_use;
    end
  end
  execute procedure ENDWORK_SUB_CLEAR(:id_day_ew)
  returning_values  :err_code;
end
^

/* Alter Procedure... */
/* Alter (ENDWORK_PROCESS) */
ALTER PROCEDURE ENDWORK_PROCESS(ID_CLIENT_POS INTEGER,
END_WORK_KIND VARCHAR(30),
NEXT_DATE DATE,
EW_USER_LIST VARCHAR(3000),
ID_CURRENT_EW INTEGER)
 RETURNS(ERR_CODE INTEGER,
ERR_TEXT VARCHAR(255),
UPD_NEXT_DATE DATE,
UPD_NEXT_ID_EW INTEGER)
 AS
declare variable dbg varchar(3000);
  declare variable id_object integer;
  declare variable id_sales integer;
  declare variable id_ew_next integer;
  declare variable user_name varchar(30);
  declare variable prev_date date;
  declare variable replication integer;
  declare variable id_current_day_ew integer;
  declare variable ew_user_name varchar(30);
  declare variable no_use integer;
  declare variable suppress_object integer;
begin
  err_code = 0;
  err_text = ''; replication = 0; /* MUST BE A SETTING */
  upd_next_id_ew = null;
  /* Description
  ||
  */
  if (:end_work_kind = 'SERVER_ALL') then end_work_kind = 'SERVER';
  if (:end_work_kind not in ('DAY', 'SERVER', 'OBJECT')) then begin
    err_code = -1;
    err_text = 'end_work_kind = '||:end_work_kind;
    exit;
  end
  /*  user expiration*/

  execute procedure SYSTEM_GET_VALUE(:id_client_pos, 'CURRENT_USER')
  returning_values  :user_name;

  execute procedure SYSTEM_GET_VALUE(:id_client_pos, 'CURRENT_EW')
  returning_values  :id_current_day_ew;

  execute procedure SYSTEM_GET_VALUE(:id_client_pos, 'CURRENT_OBJECT')
  returning_values  :id_object;

  select O.ID_EW_NEXT, O.SYSTEM_DATE
  from   NOM_OBJECT O
  where  O.ID_OBJECT = :id_object
  into   :id_ew_next, :prev_date;

  if (:end_work_kind = 'DAY') then begin
    execute procedure SYSTEM_GET_VALUE(:id_client_pos, 'SUPPRESS_OBJECT')
    returning_values  :suppress_object;
    if (:suppress_object = 1) then begin
      execute procedure NOM_MODIFY_OBJECT_SUPPRESS(:id_client_pos, :id_object, 'rise')
      returning_values  :err_code, :err_text;
      if (:err_code < 0) then exit;
    end
    insert into SYSTEM_END_WORK(ID_END_WORK, ID_OBJECT, PREV_DATE, NEXT_DATE,
      EW_USER, EW_KIND, ID_DAY_MASTER)
    values (:id_current_ew, :id_object, :prev_date, :next_date,
      :user_name, 2, :id_current_ew);

    update SYSTEM_END_WORK SEW
    set    SEW.ID_DAY_MASTER = :id_current_ew
    where  SEW.ID_OBJECT = :id_object
           and SEW.ID_DAY_MASTER is null;

    update SYSTEM_NOMERATOR N
    set    N.NUM_NEXT = 1
    where  N.NUM_CLASS = 'BILL'
           and N.NUM_OBJECT = :id_object;

    /* archive */
    execute procedure ENDWORK_SUB_ARCHIVE(:id_current_day_ew)
    returning_values  :err_code;
    if (:err_code < 0) then exit;

    if (:replication = 0) then begin
      /* summarize  */
      execute procedure ENDWORK_SUB_SUMMARY(:id_current_day_ew, :id_object, :prev_date)
      returning_values  :err_code;
      if (:err_code < 0) then exit;

      execute procedure ENDWORK_SUB_CLEAR(:id_current_day_ew)
      returning_values  :err_code;
      if (:err_code < 0) then exit;
    end
    upd_next_date = :next_date;
    execute procedure ENDWORK_GETID(:id_object, 'JUST_GEN', '')
    returning_values  :err_code, :err_text, :upd_next_id_ew, :no_use;
  end else if (:end_work_kind = 'OBJECT') then begin
    /* INTERFASE_TRADE */
    execute procedure EAI_EFFECT(:id_current_day_ew, :id_current_ew, :id_object, :prev_date)
    returning_values  :err_code, :id_sales;

    insert into SALES_HEAD (
      ID_SALES, ID_OBJECT, ID_END_WORK, SALE_DATE, IS_ACTIVE, IS_VALID, NOTE, SALE_NUM)
    select
      SH.ID_SALE_HEAD, SH.ID_OBJECT, SH.END_WORK_DAY, SH.SALE_DATE, SH.IS_ACTIVE, 1, SH.NOTE, SH.ID_SALE_HEAD
    from   EAI_EFFECT_SALE SH
    where  SH.ID_SALE_HEAD = :id_sales;
    
    insert into SALES_LINE (
      ID_SALE_LINE, ID_SALES, ID_STOCK, ID_INVENT, SALE_QTY, SALE_PRICE,
      BASE_PRICE, IS_DDS, DDS_STAVKA, DDS_GROUP, POS_CODE, IS_FISCAL, ID_MENU,
      ID_SMETKA, ID_TYPE_PAYMENT)
    select
      SL.ID_SALE_LINE, SL.ID_SALE_HEAD, SL.ID_POST_ITEM, SL.ID_INVENT_DELIVERY, SL.SALE_QTY, 0,
      0, 1, SL.VAT_VALUE, SL.VAT_NAME, SL.POS_CODE, 1, -1,
      -1, null
    from   EAI_EFFECT_LINE SL
    where  SL.ID_SALE_HEAD = :id_sales;

    update SMETKA_HEAD SH
    set    SH.END_WORK_OBJECT = :id_current_ew
    where  SH.ID_END_WORK = :id_current_day_ew
           and SH.END_WORK_OBJECT is null;

    insert into SYSTEM_END_WORK(ID_END_WORK, ID_OBJECT, PREV_DATE, NEXT_DATE,
      EW_USER, EW_KIND, ID_DAY_MASTER)
    values (:id_current_ew, :id_object, :prev_date, null,
      :user_name, 1, null);
  end else if (:end_work_kind = 'SERVER') then begin
    for
      select SSP.ITEM
      from   SYSTEM_STRING_PARSER(:ew_user_list, ',') SSP
      into   :ew_user_name
    do begin
      update SMETKA_HEAD SH
      set    SH.END_WORK_USER = :id_current_ew
      where  SH.ID_END_WORK = :id_current_day_ew
             and SH.END_WORK_USER is null
             and SH.USER_OWNER = :ew_user_name;
    end

    insert into SYSTEM_END_WORK(ID_END_WORK, ID_OBJECT, PREV_DATE, NEXT_DATE,
      EW_USER, EW_KIND, ID_DAY_MASTER)
    values (:id_current_ew, :id_object, :prev_date, null,
      :user_name, 0, null);
  end
end
^

/* Alter (ENDWORK_REGENERATE) */
ALTER PROCEDURE ENDWORK_REGENERATE(ID_DAY_EW INTEGER,
OPTIONS VARCHAR(255))
 RETURNS(ERR_CODE INTEGER)
 AS
declare variable dbg varchar(2000);
  declare variable id_object integer;
  declare variable fiscal_date date;
  declare variable id_invent_ew integer;
  declare variable no_use varchar(20);
begin
  /*  Description:
  ||
  */
  select EW.ID_OBJECT, EW.PREV_DATE
  from   SYSTEM_END_WORK EW
  where  EW.ID_END_WORK = :id_day_ew
  into   :id_object, :fiscal_date;

  execute procedure ENDWORK_UNDO(:id_day_ew, 'REVERT');
  
  execute procedure ENDWORK_SUB_ARCHIVE(:id_day_ew)
  returning_values  :err_code;
  
  execute procedure ENDWORK_SUB_SUMMARY(:id_day_ew, :id_object, :fiscal_date)
  returning_values  :err_code;

  if (:options = 'with_effect_export') then begin
    for
      select EW.ID_END_WORK
      from   SYSTEM_END_WORK EW
      where  EW.ID_DAY_MASTER = :id_day_ew
             and EW.EW_KIND = 1
      into   :id_invent_ew
    do begin
      delete from EAI_EFFECT_SALE S
      where  S.END_WORK_DAY = :id_invent_ew;
      update SMETKA_HEAD SH
      set    SH.END_WORK_OBJECT = null
      where  SH.END_WORK_OBJECT = :id_invent_ew;
      execute procedure EAI_EFFECT(:id_day_ew, :id_invent_ew, :id_object, :fiscal_date)
      returning_values  :err_code, :no_use;
    end
  end
  execute procedure ENDWORK_SUB_CLEAR(:id_day_ew)
  returning_values  :err_code;
end
^

SET TERM ; ^

ALTER TABLE ARCHIVE_PAYMENT_EXTERNAL ALTER COLUMN ID_SMETKA_PAYMENT POSITION 1;

ALTER TABLE ARCHIVE_PAYMENT_EXTERNAL ALTER COLUMN EXTERNAL_DATA POSITION 2;

ALTER TABLE ARCHIVE_PAYMENT_EXTERNAL ALTER COLUMN EXTERNAL_IFC POSITION 3;

ALTER TABLE ARCHIVE_PAYMENT_EXTERNAL ALTER COLUMN INTERNAL_DATA POSITION 4;

ALTER TABLE ARCHIVE_PAYMENT_EXTERNAL ALTER COLUMN VOID_ERR_CODE POSITION 5;

ALTER TABLE ARCHIVE_PAYMENT_EXTERNAL ALTER COLUMN EXTERNAL_TEXT POSITION 6;

ALTER TABLE EAI_P2F_TRANSFER_LOG ALTER COLUMN ID_SMETKA_HEAD POSITION 1;

ALTER TABLE EAI_P2F_TRANSFER_LOG ALTER COLUMN ID_SMETKA_PAYMENT POSITION 2;

ALTER TABLE EAI_P2F_TRANSFER_LOG ALTER COLUMN ID_END_WORK POSITION 3;

ALTER TABLE EAI_P2F_TRANSFER_LOG ALTER COLUMN TAG_NAME POSITION 4;

ALTER TABLE EAI_P2F_TRANSFER_LOG ALTER COLUMN TAG_VALUE POSITION 5;

ALTER TABLE EAI_P2F_TRANSFER_LOG ALTER COLUMN STOCK_GROUP POSITION 6;

ALTER TABLE EAI_P2F_TRANSFER_LOG ALTER COLUMN TRANSFER_AMOUNT POSITION 7;

ALTER TABLE EAI_P2F_TRANSFER_LOG ALTER COLUMN TRANSFER_DT POSITION 8;

ALTER TABLE EAI_P2F_TRANSFER_LOG ALTER COLUMN EXTERNAL_IFC POSITION 9;

