Newer
Older
Midax / FS_ALTRIA.sql
create or replace package FS_ALTRIA AUTHID CURRENT_USER is

  -- Author  : Vesel
  -- Created : 26/03/2018 5:13:07 PM
  -- Purpose : this is export process for Altria - Tobacco program.
  --         Current Tobacoo program collect data for all Tobaco sales, 
  --         the organization that recieved this data as CSV file is named IRI
  --         As reward of collected data, Altria organization gives money to the merchant, thats why this process is so important for us, 
  --         our customers recieved some monay
  --         
  --         Simple description of the proces:
  --          
  --           Fase 1 - simple collection of the tobacco sales in file
  --           Fase 2 - this is extension of F1, and we add discounts in the file that merchant gaves to the customer at the moment of the sale.
  --         
  --         Midax has two types of processes:
  --           - extracting data from scratch - currenty this generate file in F1 and our current merchant who did that is Premiere Station. 
  --             The process is prepared to generate F2 file, but unfortunately, Premiere Station doesn't use our Loyalty Program and the final 
  --             result is F1 file
  --           - enriching data which is already in F1 - the current merchant that do that is GPM, we recieve file from GPM which is already 
  --             in F1 state, and enriched this file using Midax promotion system. The end result is file in F2 state
  --
  --         Description of Midax process:
  --           - To generate F1 we just need to extract our Sales table - easy
  --           - To generate F2, we do a little more, which is written bellow
  --         Because Midax doesn't kept the sales with discount for each product, (discount is attached to transaction, but not to the right saled product in the sale)
  --         the process is looping through Midax sales table and simulate each tobacoo sale again as it happens again.
  --         If we have promotion - discount on that transaction we are trying to apply it on tobacoo sale, using the Promotion rules that are 
  --         defined for Tobacoo sales (Thats why in Tobacoo promotion should contain in description the string  'Altria')
  --         Promotion business logic, is very important part of the process.
  --

  procedure trigger_proc(pChain varchar2, pWeek number default 0);
  procedure trigger_proc(pChain varchar2, pDate date default sysdate);
  procedure enrichment_proc(pChain varchar2);
  procedure import_external_file;
  procedure set_week_days(p_week_num number);
  procedure set_week_days(p_date date := sysdate);
  function set_sscs_store(p_store_no varchar2) return varchar2 deterministic;
  function set_loyalty_id(p_card_id number) return varchar2 deterministic;
 

end FS_ALTRIA;
/
create or replace package body FS_ALTRIA is

  g_start_date  date;
  g_end_date    date;
--  g_delta       number := 9 * (1 /24 /60); /* 2 minutes */
  g_chain       varchar2(40);

  type product_rec 
    is record ( original_price   number,  -- retailer price
                quantity         number,  -- quantity sold for current upc
                loyalty_discount number,  -- loyalty discount applied in sale
                upc              varchar2(20), -- upc_no - similar to Midax UPC_NO
                all_quantity     number); -- quantity for all products in current sale
   

  type coupon_rec 
    is record ( sale_id                 number,      -- sale_id for coupon
                prom_id                 number,      -- promotion id for coupon
                prom_no                 varchar2(50),-- specific altria promotin num
                card_id                 number,
                cpn_trnsctn_amnt        number,      -- discount for promotion - can be sum of many coupons from the same type
                cpn_prise               number,      -- prise value for one coupon
                cpn_plu                 varchar2(20),-- upc_no - similar to Midax UPC_NO
                cpn_rqrd_qty            number,      -- required upc quantity necessary to satisfy promotion requirements
                upc_group_id            number,      -- elidgiable upc group for promotion
                cpn_count               number,      -- how many times this promotion was applied in the current sale
                cpn_type                varchar2(20),-- altria promotion types only
                cnt                     number);     -- how many different promotions were applied in the current sale (distinct  prom_id)
  
  -- -----------------------------------------------------------------
  -- Procedure :    set_query_variable
  -- Description :  
  -- Params :       see below.
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure  set_contex_variable(pVar in varchar2, pVal in varchar2) is
  begin
    DBMS_SESSION.set_context('ALTRIA', pVar, pVal);
  end set_contex_variable;
  
  -- -----------------------------------------------------------------
  -- Procedure :    get_contex_variable
  -- Description :  
  -- Params :       see below.
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  function get_contex_variable(pVar in varchar2)
    return varchar2 is
  begin
    return sys_context('ALTRIA', upper(pVar));
  end get_contex_variable;
  -- -----------------------------------------------------------------
  -- Procedure :    reset_query_variables
  -- Description :  This should be at the end when you set some query variables
  -- Params :       see below.
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure  reset_contex_variables is
  begin
    DBMS_SESSION.CLEAR_CONTEXT('ALTRIA');
  end reset_contex_variables;    

  -- -----------------------------------------------------------------
  -- Procedure :    Just simple sleep - stealed from the internet
  -- Description :  Sleep N seconds
  -- Params :       see below.
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure sleep(pSecs integer) is
    start_dts DATE := sysdate;
    curr_dts  DATE;
    eye       NUMBER := 0;
    l_one_sec constant number := 1 / 24 / 60 / 60;
  BEGIN
    LOOP
      eye      := eye + 1;
      curr_dts := sysdate;
      EXIT WHEN curr_dts > start_dts + l_one_sec * pSecs;
    END LOOP;
  END;

  -- -----------------------------------------------------------------
  -- Procedure :    get_week_days
  -- Description :  Get the first/last date in the week as global variables
  -- Params :       week number in the current year.
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure set_week_days(p_week_num number) is
  begin
    -- do some changes here - start / end should be from Sunday till Saturday - to be clear change the func
    with tgt as
     (select to_date(p_week_num * 7, 'DDD') as dt from dual)
    select dt as start_date,
           dt + 6  as end_date into g_start_date, g_end_date
      from tgt;
      
      -- bug fix - year changed and the Start Date and the End Date are going into next year:
      if to_date(p_week_num * 7, 'DDD') - trunc(sysdate, 'YY') > 7 then
        -- move the days into previous year -> to_char(sysdate, 'YYYY') - 1
        g_start_date := to_date(to_char(g_start_date, 'ddmm')||to_char(sysdate, 'YYYY') - 1, 'ddmmyyyy');
        -- end date should be allways in the next year
        g_end_date := to_date(to_char(g_end_date, 'ddmm')||to_char(sysdate, 'YYYY'), 'ddmmyyyy');
      end if;

    end;
    
  -- -----------------------------------------------------------------
  -- Procedure :    get_week_days
  -- Description :  Get the first/last date in the week as global variables 
  -- Params :       date.
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure set_week_days(p_date date := sysdate) is
  begin
    -- select trunc(p_date, 'WW') - 9, trunc(p_date, 'WW') - 9 + 6 into g_start_date, g_end_date from DUAL;
    select trunc(p_date) - 6, trunc(p_date)
      into g_start_date, g_end_date
      from DUAL;
    if g_end_date > sysdate then
      RAISE_APPLICATION_ERROR (-20000,'This is not prediction program, Enter correct date plese.'); 
    end if;
    if to_char(g_end_date,'d') <> 7 then
      RAISE_APPLICATION_ERROR (-20000,'You should enter only date that is Saturday.'); 
    end if;
  end;
  
  -- -----------------------------------------------------------------
  -- Procedure :    get_upc
  -- Description :  Get upc info for given upc_no 
  -- Params :       upc_no
  -- Author  :      Vesel
  -- -----------------------------------------------------------------  
  function get_reg_expr(pFLAG varchar2) return varchar2 is
    l_reg_expr ALTRIA_CONFIG_MAIN.Left_Reg_Expr%TYPE;
  begin
    if upper(pFLAG) = 'LEFT' then
      
      select C.Left_Reg_Expr
        into l_reg_expr
        from altria_config_main C
       where C.ENRICHMENT_FLAG = 1
         and C.Chain = g_chain;
         
    elsif upper(pFLAG) = 'RIGHT' then
    
      select C.Right_Reg_Expr
          into l_reg_expr
          from altria_config_main C
         where C.ENRICHMENT_FLAG = 1
           and C.Chain = g_chain;
    else
      -- unknown
      l_reg_expr := '';
    end if;
           
    return l_reg_expr;
  exception when OTHERS then 
    return '';
  end;  
  
  -- -----------------------------------------------------------------
  -- Procedure :    get_upc
  -- Description :  Get upc info for given upc_no 
  -- Params :       upc_no
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  function get_upc(p_upc_id number) return ot_upc is
    o ot_upc := ot_upc();
  begin 
    
    begin 
      select id, upc_no, description, department_id, nvl(measure_id, 'PACK'), nvl(unisize, 1)
        into o.upc_id, o.upc_no, o.upc_description, o.upc_department_id, o.upc_measure_id, o.upc_in_case
        from upc U
       where U.id = p_upc_id
         and U.Chain = g_chain
         and rownum = 1;

     exception
      when no_data_found then
        return ot_upc;
     end;
     
    begin
      
      select V.FIELD_VALUE into o.upc_mfg_name
        from ext_param_names N, ext_param_values V
       where N.chain = g_chain
         and N.Param_Name = 'MERCHANT'
         and V.Table_Id = 1 /* table_id = 1 -> upc table */
         and V.Param_Id = N.Param_Id
         and V.RECORD_ID = o.upc_id;
         
      exception 
        when no_data_found then
        o.upc_mfg_name := 'N/A';
      end;


     return o;
     
  exception when others then 
    raise;     
  end;

  -- -----------------------------------------------------------------
  -- Procedure :    get_upc
  -- Description :  Get upc info for given upc_no 
  -- Params :       upc_no
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  function get_store(p_store_id number) return ot_store is
    o ot_store := ot_store();
  begin 
    select id,
           store_no, description, address1, address2, city, state, zip /*,  contact1, contact2, phone1,
           phone2, fax, store_type, latitude, longitude*/
      into o.store_id, o.store_no, o.store_description, o.store_address1, o.store_address2, o.store_city, o.store_state, o.store_zip /*, o.store_contact1,
           o.store_contact2, o.store_phone1, o.store_phone2, o.store_fax, o.store_type, o.store_latitude, o.store_longitude*/
      from store
     where chain = g_chain
       and id = p_store_id;

    return o;
    
  exception
      when no_data_found then return o;
      when others then raise;
  end;
  
  -- -----------------------------------------------------------------
  -- Procedure :    get_midax_store
  -- Description :  if we have different stores in Midax and SSCS we are using mapping table, this table contains translation - on import
  -- Params :       sscs_store_no
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  function get_midax_store(p_store_no varchar2) return varchar2 deterministic is
    l_store_no varchar2(6);
  begin 

    select midax_store_no
      into l_store_no
      from altria_config_main C, altria_store s
     where chain = g_chain
       and C.account_id = s.account_id
       and sscs_store_no = p_store_no;
       
    return l_store_no;
    
  exception
      when no_data_found then return p_store_no;
      when others then raise;
  end;
  
  
  -- -----------------------------------------------------------------
  -- Procedure :    set_sscs_store
  -- Description :  if we have different stores in Midax and SSCS we are using mapping table, this table contains translation - on export
  -- Params :       midax_store_no
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  function set_sscs_store(p_store_no varchar2) return varchar2 deterministic is
    l_store_no varchar2(6);
  begin 

    select s.sscs_store_no
      into l_store_no
      from altria_config_main C, altria_store s
     where chain = g_chain
       and C.account_id = s.account_id
       and s.midax_store_no = p_store_no;
       
    return l_store_no;
    
  exception
      when no_data_found then return p_store_no;
      when others then raise;
  end;
    
  -- -----------------------------------------------------------------
  -- Procedure :    set_loyalty_id
  -- Description :  we set Midax PAN here, its defined as loyalty ID in IRI
  -- Params :       midax_store_no
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  function set_loyalty_id(p_card_id number) return varchar2 deterministic is
    l_pan varchar2(25);
  begin 

    select pan into l_pan from card where id = p_card_id;
    
    -- sometimes non loyalty customers in midax are identifyed by 0
    -- translate that to NONE or NULL
    if l_pan = 0 then
      return null;
    end if;
       
    return l_pan;
    
  exception
      when no_data_found then return null;
      when others then raise;
  end;
  
  -- -----------------------------------------------------------------
  -- Procedure :    get_account
  -- Description :  return account id
  -- Params :       account_id
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  function get_account return number is
    l_account_id number;
  begin 
    
    select account_id 
      into l_account_id 
      from ALTRIA_CONFIG_MAIN T 
     where chain = g_chain;

    return l_account_id;
  exception
      when no_data_found then return 0;
      when others then raise;
  end;  
    
  -- -----------------------------------------------------------------
  -- Procedure :    get_trips_array
  -- Description :  return array with all sales as sale_id  
  -- Params :       
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  function get_trips_array return t_sale as
    l_year_1 integer;
    l_year_2 integer;
    l_sql varchar2(4000);
    l_arr t_sale := t_sale();
  begin
    l_year_1 :=  EXTRACT(year from g_start_date);
    l_year_2 :=  EXTRACT(year from g_end_date);    

    -- The week belongs into one year
    if l_year_1 = l_year_2 then
      -- somthing like select sale_id from trips_2018 where time_id >=  sysdate - 1 and time_id <= sysdate + 1
      l_sql := 'select ot_sale(T1.time_id, T1.sale_id, T1.store_id, T1.terminal_id, T1.card_id, null, T1.amount, null, null) 
                  from trips_'|| l_year_1 ||' T1
                 where T1.time_id >= to_date('''|| g_start_date || ''') 
                   and T1.time_id < to_date(''' || g_end_date ||''') + 1';
     -- the week belongs to two years
    else
      l_sql := 'select ot_sale(T1.time_id, T1.sale_id, T1.store_id, T1.terminal_id, T1.card_id, null, T1.amount, null, null) 
                  from trips_'|| l_year_1 ||' T1
                 where T1.time_id >= to_date('''|| g_start_date || ''') 
                   and T1.time_id < to_date(''' || g_end_date || ''') + 1
                union all
                select ot_sale(T1.time_id, T1.sale_id, T1.store_id, T1.terminal_id, T1.card_id, null, T1.amount, null, null) 
                  from trips_'|| l_year_2 ||' T1
                 where time_id >= to_date('''|| g_start_date || ''') 
                   and time_id < to_date(''' || g_end_date ||''') + 1';
    end if;
    
    EXECUTE IMMEDIATE l_sql BULK COLLECT INTO l_arr;
    return l_arr;
  end;
    
-- -----------------------------------------------------------------
-- Procedure :    get_promotions
-- Description :  returns altria promotions defined in Midax - we recognize it by 'Altria' in description
-- Params :       
-- Author  :      Vesel
-- -----------------------------------------------------------------
  function get_promotions return t_promotion as
    l_arr t_promotion := t_promotion();
  begin

    select ot_promotion(prom_id,
                        description,
                        active,
                        date_begin,
                        date_end,
                        altria_type, -- external_type
                        altria_nom) -- external_no
           bulk collect
      into l_arr
      from (select prom_id,
                   description,
                   active,
                   date_begin,
                   date_end,
                   replace(REGEXP_SUBSTR(description, '-[^-]+-'), '-', '') altria_type,
                   replace(REGEXP_SUBSTR(description, '#[^#]+#'), '#', '') altria_nom
              from promotion_header H
             where lower(H.description) like '%altria%'
               and H.chain = g_chain
               and H.active = 1);

    return l_arr;
  end;

  -- -----------------------------------------------------------------
  -- Procedure :    get_rewards
  -- Description :  get all coupons for given promotions  
  -- Params :       
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  function get_rewards RETURN SYS_REFCURSOR is
    rewards_refcur SYS_REFCURSOR;
    l_promo        t_promotion;
    l_trips        t_sale;
  begin
    l_promo := get_promotions();
    l_trips := get_trips_array();
    --    coupon_rec is used with that func
    open rewards_refcur for
      select sale_id,
             prom_id,
             min(external_no) prom_no,
             min(card_id) card_id,
             sum(received_amount) cpn_trnsctn_amnt,
             sum(received_amount) / count(*) cpn_prise,
             min(plu) cpn_plu,
             min(required_qty) cpn_rqrd_qty,
             min(UPC_GROUP_ID) upc_group_id, 
             count(*) cpn_count,
             min(external_type) cpn_type,
             count(distinct prom_id) over(partition by sale_id) cnt
        from (select (select sale_id
                        from TABLE(l_trips) T
--                        from trips_2018 t                        
                       where t.time_id = ct.date_posted
                         and t.store_id = ct.store_id
                         and t.card_id = ct.card_id
                         and t.terminal_id = ct.pos_number
                         and rownum = 1) sale_id,
                     ct.card_id,
                     ct.prom_id,
                     ct.received_amount,
                     ct.kind,
                     cti.plu,
                     (select CMPR_VALUE1 * R.PTS_VAL_MIN -- different types of promootion can be aplied - this fix when we gave pnt for each box
                        from promotion_premises P, promotion_rewards R
                       where P.prom_id = CT.prom_id
                         and check_object = 1
                         and cmp_attr = 2
                         and P.prom_id = R.prom_id
                         and rownum = 1) REQUIRED_QTY,
                     (select CHECK_VALUE
                        from promotion_premises P, promotion_rewards R
                       where P.prom_id = CT.prom_id
                         and check_object = 1
                         and cmp_attr = 2
                         and P.prom_id = R.prom_id
                         and rownum = 1) UPC_GROUP_ID,
                     P.external_type,
                     P.external_no
                from coupons_trace CT,
                     coupon_trace_items CTI,
                     TABLE(l_promo) P
/*                 -- for debug - instead of TABLE(l_promo) P
                   (select prom_id,
                           description,
                           active,
                           date_begin,
                           date_end,
                           replace(REGEXP_SUBSTR(description, '-[^-]+-'), '-', '') external_type,
                           replace(REGEXP_SUBSTR(description, '#[^#]+#'), '#', '') external_no
                      from promotion_header H
                     where lower(H.description) like '%altria%'
                       and H.chain = 'PREMST'
                       and H.active = 1) P */                     
               where CT.prom_id = P.prom_id
                 and CT.date_posted >= g_start_date
                 and CT.date_posted < g_end_date + 1
                 and CT.Coupon_Id = CTI.Coupon_Id) B
       group by sale_id, prom_id
       order by sale_id;

    return rewards_refcur;

  end;

-- -----------------------------------------------------------------
-- Procedure :    get_rewarded_products
-- Description :  get products in given sale that belongs to upc_group_id
-- Params :       sale_id
-- Author  :      Vesel
-- -----------------------------------------------------------------
  function get_rewarded_products(p_sale_id number, p_upc_group_id number)
    return t_upc is
    l_arr t_upc;
  begin
    -- collect this cursor in T_UPC nested table
    -- make this simple
    -- all_quantity, upc_no, null , null, null, null, quantity, loyalty_discount, original_price, null
    select ot_upc(all_quantity,
                  upc,
                  null,
                  null,
                  null,
                  null,
                  quantity,
                  loyalty_discount,
                  original_price,
                  null) bulk collect
      into l_arr
      from (select A.*, sum(quantity) over() all_quantity
              from (select (sum(R.Final_Price) +
                           sum(nvl(R.loyalty_discount, 0))) / sum(R.Quantity) original_price,
                           sum(R.Quantity) Quantity,
                           sum(nvl(R.loyalty_discount, 0)) loyalty_discount,
                           R.upc
                      from altria_reports R,
                           (select distinct plu_number
                              from sales_extra_info I
                             where sale_id = p_sale_id
                               and item_type = 0
                               and exists
                             (select *
                                      from upc_in_group U
                                     where U.UPC_ID = I.upc_id
                                       and U.GROUP_ID = p_upc_group_id)) EI
                     where R.midax_sale_id = p_sale_id
                       and (R.upc like
                           nvl(trim(both '0' from EI.Plu_Number), 'NULL') || '%' or
                           -- the next row is new one - for Nittany
                           trim(both '0' from R.upc) = nvl(trim(both '0' from EI.Plu_Number), 'NULL') or
                           R.upc = nvl(EI.Plu_Number, 'NULL'))
                     group by upc) A
             order by quantity desc, loyalty_discount desc);

    return l_arr;

  end get_rewarded_products;
  
  -- -----------------------------------------------------------------
  -- Procedure :    cast_to_obj
  -- Description :  cast rowtype to object type
  -- Params :       
  -- Author  :      Vesel
  -- -----------------------------------------------------------------

  function cast_to_obj(p_row ALTRIA_REPORTS%rowtype)
    return ot_altria_reports is
    o ot_altria_reports;
  begin
    o := ot_altria_reports(p_row.batch_id,
                           p_row.row_num,
                           p_row.midax_sale_id,
                           p_row.batch_date,
                           p_row.account_id,
                           p_row.store_no,
                           p_row.store_name,
                           p_row.store_address1,
                           p_row.store_address2,
                           p_row.store_city,
                           p_row.store_state,
                           p_row.store_zip,
                           p_row.store_phone,
                           p_row.store_contact,
                           p_row.store_email,
                           p_row.register_id,
                           p_row.category_id,
                           p_row.unit_measure,
                           p_row.unit_in_pack,
                           p_row.promotion_flag,
                           p_row.multi_pack_flag,
                           p_row.multi_pack_quantity,
                           p_row.multi_pack_discount,
                           p_row.transaction_id,
                           p_row.transaction_date,
                           p_row.mfg_name,
                           p_row.sku,
                           p_row.upc,
                           p_row.upc_description,
                           p_row.product_grp_code,
                           p_row.product_grp_name,
                           p_row.quantity,
                           p_row.mfg_deal_name1,
                           p_row.mfg_deal_discount2,
                           p_row.mfg_deal_name2,
                           p_row.mfg_deal_discount2,
                           p_row.mfg_deal_name3,
                           p_row.mfg_deal_discount3,
                           p_row.final_price,
                           p_row.loyalty_id,
                           p_row.loyalty_discount,
                           p_row.loyalty_promotion);
    return o;
  end cast_to_obj;
  
  -- -----------------------------------------------------------------
  -- Procedure :    post_process
  -- Description :  this is process keep data in history table
  -- Params :        
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure post_process is
    l_date date := sysdate;
    begin
/*      insert \*+ APPEND *\ 
        into altria_report_history
      select l_date, A.* from altria_reports A;*/
      null;
    end;
      
  -- -----------------------------------------------------------------
  -- Procedure :    split_items
  -- Description :  split all rows in the current sale to one row per each bought item
  -- Params :       sale_id, 
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure split_items(p_sale_id number,
                        p_tbl     out nocopy t_altria_reports) is
    cursor my_cur is
/*      select *
        from altria_reports R
       where midax_sale_id = p_sale_id
       order by R.Upc;*/
      -- coursor must be sorted
      select RR.*
        from altria_reports RR,
             (select R.row_num, sum(quantity) over(partition by upc) upc_qty
                from altria_reports R
               where midax_sale_id = p_sale_id) RS
       where RR.Row_Num = RS.row_num
       order by RS.upc_qty desc, RR.Upc;     
       
    l_row ALTRIA_REPORTS%rowtype;
    idx   integer;
    l_unit_price number;
  
  begin

    p_tbl := t_altria_reports();
  
    idx := 0;
    for i in my_cur loop
      l_row := i;
      
      -- collect the old row and continue;
      if i.quantity <= 1 then
        p_tbl := p_tbl MULTISET UNION ALL
                 t_altria_reports(cast_to_obj(l_row));
        continue;
      end if;
    
      for j in 1 .. i.quantity loop
        idx                   := idx + 1;        
        -- just do the balance the same as before the spliting
        -- first row
        if j = 1 then
          l_unit_price           := (l_row.final_price +
                                   nvl(i.loyalty_discount, 0)) / i.quantity;
          l_row.final_price      := l_unit_price  - nvl(i.loyalty_discount, 0);
          l_row.loyalty_discount := nvl(i.loyalty_discount, 0);
        else 
          l_row.final_price := l_unit_price;
          l_row.loyalty_discount   := 0;
          l_row.row_num            := altria_row_num.nextval;     
        end if;

        -- all rows
        l_row.quantity           := 1;

        -- insert row in collection
        p_tbl := p_tbl MULTISET UNION ALL
                 t_altria_reports(cast_to_obj(l_row));
      end loop;
    end loop;
  
  end split_items;
  

  -- -----------------------------------------------------------------
  -- Procedure :    merge_items
  -- Description :  the oposite of split process - group items into one row in the sale 
  -- Params :       sale_id, 
  -- Author  :      Vesel
  -- -----------------------------------------------------------------  
  procedure merge_items(p_report in out nocopy t_altria_reports) is
  begin
    insert into altria_reports
      select min(batch_id),
             min(row_num),
             min(midax_sale_id),
             min(batch_date),
             min(account_id),
             min(store_no),
             min(store_name),
             min(store_address1),
             min(store_address2),
             min(store_city),
             min(store_state),
             min(store_zip),
             min(store_phone),
             min(store_contact),
             min(store_email),
             min(register_id),
             min(category_id),
             min(unit_measure),
             min(unit_in_pack),
             min(promotion_flag),
             min(multi_pack_flag),
             min(multi_pack_quantity),
             min(multi_pack_discount),
             min(transaction_id),
             min(transaction_date),
             min(mfg_name),
             min(sku),
             min(upc),
             min(upc_description),
             min(product_grp_code),
             min(product_grp_name),
             sum(quantity),
             min(mfg_deal_name1),
             min(mfg_deal_discount1),
             min(mfg_deal_name2),
             min(mfg_deal_discount2),
             min(mfg_deal_name3),
             min(mfg_deal_discount3),
             sum(final_price),
             min(loyalty_id),
             decode(sum(nvl(loyalty_discount, 0)), 0, null, sum(nvl(loyalty_discount, 0))),
             decode(sum(nvl(loyalty_discount, 0)), 0, null, min(loyalty_promotion))             
        from TABLE(p_report)
       group by midax_sale_Id, register_id, upc order by register_id, upc;

  end merge_items;
  
  -- -----------------------------------------------------------------
  -- Procedure :    process_mpack
  -- Description :  Set single item to be part of multipack promotion
  -- Params :       
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure process_mpack(p_cpn coupon_rec, 
                           p_report in out nocopy t_altria_reports) is
    l_cpn_id          number := 1;
    l_bkp             t_altria_reports;
    l_upcs            t_upc;
    l_cnt             number;
    l_idx             number := 0;
    l_promoted_items_qty number; -- how many promoted items we have in the current sale;
  
  begin
    -- for debug
    if p_cpn.sale_id = 58852209 then
      null;
    end if;
        
    l_bkp := p_report;
        
    -- only promoted upc
    l_upcs := get_rewarded_products(p_cpn.sale_id, p_cpn.upc_group_id);

    
    l_promoted_items_qty := p_cpn.cpn_count * p_cpn.cpn_rqrd_qty;

      
    for i in 1..l_promoted_items_qty loop
      
      select count(*)
        into l_cnt
        from TABLE(l_upcs) T
       where T.upc_no = p_report(i).upc;

      -- if current upc is not eligiable for current promotion - continue  
      if l_cnt =  0 then continue; end if;
        
      l_idx := l_idx + 1;
      p_report(i).multi_pack_flag        := 'Y';
      p_report(i).multi_pack_quantity    := p_cpn.cpn_rqrd_qty;
      p_report(i).register_id            := l_cpn_id;
      p_report(i).multi_pack_discount    := p_cpn.cpn_prise;
      -- subtract discount from final price - specification requirement
      p_report(i).final_price := p_report(i).final_price - 
                                 nvl(p_report(i).multi_pack_discount / p_cpn.cpn_rqrd_qty , 0);      
--      p_report(i).register_id            := l_cpn_id;              
      
      if mod(l_idx, p_cpn.cpn_rqrd_qty) = 0 then 
        l_cpn_id := l_cpn_id + 1;
      end if;
    end loop;

  exception when others then 
    -- revert to original sale
    p_report := l_bkp;
  end;  
  -- -----------------------------------------------------------------
  -- Procedure :    process_mfg1
  -- Description :  MFG discounts can be applied only once per transaction 
  -- Params :       sale_id, coupon parameteres
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure process_mfg1(p_cpn coupon_rec, 
                         p_report in out nocopy t_altria_reports) is
    l_pan varchar2(20);
    
  
  begin
    null;
  end process_mfg1;
    
  -- -----------------------------------------------------------------
  -- Procedure :    process_mfg2
  -- Description :  
  -- Params :       sale_id, coupon parameteres
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure process_mfg2(p_cpn coupon_rec, 
                         p_report in out nocopy t_altria_reports) is
    l_cpn_id number := 1;
    l_pan varchar2(20);
    
  
  begin
    null;
  end process_mfg2;

  -- -----------------------------------------------------------------
  -- Procedure :    process_mfg3
  -- Description :  
  -- Params :       sale_id, coupon parameteres
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure process_mfg3(p_cpn    coupon_rec,
                         p_report in out nocopy t_altria_reports) is
    l_cpn_id          number := 1;
    l_rqty            number; -- how many products should be discounted - this is coming from the coupon
    l_idx             number := 1; -- just index
    l_pan             varchar2(20);
    l_cnt             number;
    l_bkp             t_altria_reports;
    l_upcs            t_upc;  

  begin
    l_bkp := p_report;
    -- for debug
    if p_cpn.sale_id = 59628799 then
      null;
    end if;
          
    -- only promoted upc
    l_upcs := get_rewarded_products(p_cpn.sale_id, p_cpn.upc_group_id);
        
    select pan into l_pan from card where id = p_cpn.card_id;

    for i in 1 .. p_cpn.cpn_rqrd_qty loop
      
      select count(*)
        into l_cnt
        from TABLE(l_upcs) T
       where T.upc_no = p_report(i).upc;

      -- if current upc is not eligiable for current promotion - continue  
      if l_cnt =  0 then continue; end if;
          
      p_report(i).register_id := p_report(i).register_id || l_cpn_id;
      p_report(i).mfg_deal_name3 := p_cpn.prom_no; -- altria prom NO (this is different from Midax prom ID)
      p_report(i).mfg_deal_discount3 := p_cpn.cpn_prise; -- MFG is applied only one time, doesn't matter how many coupons we have
      
      -- 1. specific for GPM, but I've made it common, I've chose Midax coupon instead of original discount which comming from the file.        
      if p_cpn.cpn_prise = nvl(p_report(i).loyalty_discount, 0) then
        p_report(i).final_price := p_report(i).final_price + nvl(p_report(i).loyalty_discount, 0);
        p_report(i).loyalty_discount := 0;                 -- reset file discount
      end if;
      -- 2. we set discount only to the first row of the discounted upc I've tried to make this simple, but somtimes its complex.
      -- the regulation of discount is setup in merge procedure - indeed when we group we take the sum of final prices of the products,
      -- and min(mfg_deal_discount3). This is necessary because I prcess final price with another logic in different function
      if l_idx = 1 then
        p_report(i).final_price := p_report(i).final_price - p_report(i).mfg_deal_discount3;
      end if;
      
      p_report(i).loyalty_id := l_pan;
      
      -- this type of promotions should happen only once
      if i = l_rqty then
        return;
      end if;
      l_idx := l_idx + 1;      
    end loop;

  exception
    when others then
      -- revert original sale - I don't know what to do if error exists
      p_report := l_bkp;
    
  end process_mfg3;
    
  -- -----------------------------------------------------------------
  -- Procedure :    set_all_discounts
  -- Description :  this should be the main function process
  -- Params :       message event.
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure set_all_discounts is
    l_rewards sys_refcursor;
    l_row ALTRIA_REPORTS%rowtype;
    l_rwd              coupon_rec;
    l_report          t_altria_reports; -- objects type array  
  begin
  
  -- get all rewards for the period
  l_rewards := get_rewards;
   
  loop 
    FETCH l_rewards
     into  l_rwd;
     EXIT WHEN l_rewards%NOTFOUND;
     
     split_items(l_rwd.sale_id, l_report);

     if l_rwd.cpn_type = 'MPACK' then
     null;
       process_mpack(l_rwd, l_report);
     elsif 
        l_rwd.cpn_type = 'MFG1' then   
       null;
     elsif
        l_rwd.cpn_type = 'MFG2' then   
       null;
     elsif
        l_rwd.cpn_type = 'MFG3' then
       null;
       process_mfg3(l_rwd, l_report);

     end if;
     delete from altria_reports where midax_sale_id = l_rwd.sale_id;
     merge_items(l_report);
  end loop;
  CLOSE l_rewards;

   
  exception
    when OTHERS then
      raise;
  end set_all_discounts;

  -- -----------------------------------------------------------------
  -- Procedure :    midax_tobacco
  -- Description :  not clear yet
  -- Params :       message event.
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure import_midax_tobacco is
    l_trips t_sale;
    o ot_upc;
    s ot_store;
    
  begin
    -- truncate working table and populate new data
    execute immediate 'truncate table ALTRIA_REPORTS';
    l_trips := get_trips_array;
            
    for l_row in (
      select null batch_id,
             null row_num, -- sequence here
             ei.sale_id midax_sale_id,
             null batch_date,
             null account_id,
             t.store_id store_no,
             null store_name,
             null store_address1,
             null store_address2,
             null store_city,
             null store_state,
             null store_zip,
             null store_phone,
             null store_contact,
             null store_email,
             null register_id,
             null category_id,
             null unit_measure,
             1 unit_in_pack, -- check this
             null promotion_flag,
             'N' multi_pack_flag,
             null multi_pack_quantity,
             null multi_pack_discount,
             ei.sale_id transaction_id,
             t.time_id transaction_date,
             null mfg_name,
             ei.upc_id sku,
             ei.plu_number upc,
             ei.description upc_description,
             ei.department product_grp_code,
             null product_grp_name,
             ei.quantity quantity,
             null mfg_deal_name1,
             null mfg_deal_discount1,
             null mfg_deal_name2,
             null mfg_deal_discount2,
             null mfg_deal_name3,
             null mfg_deal_discount3,
             ei.quantity * ei.original_price final_price,
             fs_altria.set_loyalty_id(T.card_id) loyalty_id,
             null loyalty_discount,
             null loyalty_promotion
        from sales_extra_info EI, TABLE(l_trips) T
       where exists (select *
                from upc U, altria_config_depart C
               where C.Department_Id = U.Department_Id
                 and c.chain = u.chain
                 and c.chain = g_chain
                 and u.id = ei.upc_id)
         and t.sale_id = ei.sale_id
       order by ei.sale_id, ei.row_id) loop
       
      o := ot_upc();    -- reset object - constructore set all to NULL
      s := ot_store();  -- reset object - constructore set all to NULL      
      -- GPM has different SKU and UPC
      begin
        o := get_upc( l_row.sku );
      exception when others then 
        o := get_upc( l_row.upc );        
      end;
      s := get_store( l_row.store_no );
      
      l_row.row_num            := altria_row_num.nextval;
      l_row.batch_id           := 1;                    -- this is batch_id - should be sequence
      l_row.batch_date         := g_end_date;           -- week end data       
      l_row.account_id         := get_account();        -- account id
      l_row.store_name         := s.store_description;  -- altria store_name
      l_row.store_no           := s.store_no;           -- altria store_number      
      l_row.store_address1     := s.store_address1;     -- altria store_address1
      l_row.store_address2     := s.store_address2;     -- altria store_address1
      l_row.store_city         := s.store_city;         -- altria store City
      l_row.store_state        := s.store_state;        -- altria store State         
      l_row.store_zip          := s.store_zip;          -- altria store ZIP Code         
      l_row.category_id        := o.upc_department_id;  -- I'm not sure for that field - to be clarify
      l_row.unit_measure       := o.upc_measure_id;     -- unit of measure
      l_row.mfg_name           := o.upc_mfg_name;  
      l_row.unit_in_pack       := o.upc_in_case;        -- how many items are in the pack - carton = 10 packs
      l_row.sku                := l_row.upc;            -- sku is midax upc_id, lets change with upc no
                 

      insert into ALTRIA_REPORTS values l_row;
    end loop;
    commit;
  
  exception
    when OTHERS then
      dbms_output.put_line('error');
      raise;
  end import_midax_tobacco;


 -- -----------------------------------------------------------------
  -- Procedure :    import_external_file
  -- Description :  Very custom proccess,
  --                we enrich third party file with trans that contains Midax Loyalty discounts
  -- Params :       message event.
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure import_external_file is

    l_row ALTRIA_REPORTS%rowtype;
    l_tmp varchar2(100);
    l_str_arr  fs_import_utils.split_row_array;
    l_batch_id number;
  
  begin
    execute immediate 'truncate table ALTRIA_REPORTS';
    l_batch_id := altria_batch_id.nextval;
    for i in (select * from ALTRIA_EXTRNL_TABLE ) loop
          l_str_arr.DELETE; -- reset object
          FS_IMPORT_UTILS.SPLIT_DELIMIT_LINE(i.txt_line, l_str_arr, '|');
          
          --lets parse 
          l_row.batch_id := l_batch_id;
          l_row.row_num := altria_row_num.nextval;
          l_row.account_id := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 0);
          l_tmp := null; -- reset          
          l_tmp := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 1);
          l_row.batch_date := to_date(l_tmp, 'YYYYMMDD');
          l_tmp := null; -- reset
--          l_row.transaction_date := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 3);           transaction time          
          l_tmp := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 2)||FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 3);
          l_row.transaction_date := to_date(l_tmp, 'YYYYMMDDHH24:MI:SS');
          l_row.transaction_id   := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 4);

          l_tmp                  := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 5);
          l_row.store_no         := get_midax_store(l_tmp);

          l_row.store_name       := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 6);
          l_row.store_address1   := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 7);
          l_row.store_city       := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 8);
          l_row.store_state      := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 9);
          l_row.store_zip        := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 10);
          
          l_row.category_id      := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 11);
          l_row.mfg_name         := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 12);
          l_row.sku              := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 13);
          l_row.upc              := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 14);
          l_row.upc_description  := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 15);
          
          l_row.unit_measure     := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 16);
          l_row.quantity         := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 17);
          l_row.unit_in_pack     := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 18);
          l_row.multi_pack_flag  := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 19);
          l_row.multi_pack_quantity := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 20);
          l_row.multi_pack_discount := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 21);
          
          l_row.loyalty_promotion   := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 22);
          l_row.loyalty_discount    := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 23);

          l_row.mfg_deal_name1      := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 24);
          l_row.mfg_deal_discount1  := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 25);
          l_row.mfg_deal_name2      := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 26);
          l_row.mfg_deal_discount2  := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 27);
          l_row.mfg_deal_name3      := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 28);
          l_row.mfg_deal_discount3  := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 29);
          
          l_row.final_price         := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 30);
          l_row.store_phone         := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 31);
          l_row.store_contact       := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 32);
          l_row.store_email         := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 33);
          
          l_row.product_grp_code    := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 34);
          l_row.product_grp_name    := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 35);
          l_row.loyalty_id          := FS_IMPORT_UTILS.GET_FROM_TABLE(l_str_arr, 36);

          insert into ALTRIA_REPORTS values l_row;                                                                                                                                                                          
    end loop;
    commit;
      

  exception
    when OTHERS then
      dbms_output.put_line('error');
      raise;
  end;

  -- -----------------------------------------------------------------
  -- Procedure :    set_midax_sale_id
  -- Description :  only for enrichment of external files - this means that we already have Altria file, but we want to add some customer info.
  --                The process is that we have external data in our ALTRIA_REPORTS table, then adding extra info, and the last step - export as CSV file
  -- Params :       .
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure set_midax_sale_id is

    l_trips t_sale;
    l_reg_expr1  ALTRIA_CONFIG_MAIN.Left_Reg_Expr%TYPE;
    l_reg_expr2 ALTRIA_CONFIG_MAIN.Right_Reg_Expr%TYPE; 
    -- !! Important - regular expression should contain groups - this brackets are group -> ()    
    
   
    
    cursor my_curr is 
      select B.midax_sale_id,
             B.midax_card_id,
             A.transaction_id
        from (
            select R.store_no,
                   R.transaction_id,
                   trunc(R.transaction_date) time_id,
                   -- make a good description here, we should capture a group  - substring from transaction_id, 
                   -- in such a manier we will combine transaction which will match with Midax,
                   -- the idea is we always to have 3 or 4 groups and most ot them to be NULL or empty string.
                   -- Combining '' || '' || 'abc' will give us trans_id = 'abc'
                   -- This is because in each Register (Merchant) the string thant define transaction_id can be different
                   -- in the current moment - end of 2018 we have only two different register
                   -- _(\d)-.+_(\d*)$
                   -- get the first and the fird group from regular expression - this (\d*) is a group and match only digits sign
                   -- get the desired group - 1st, 2nd or 3rd - the empty groups return empty string
                   regexp_substr(R.transaction_id, l_reg_expr1, 1,1,NULL,1) ||
                   regexp_substr(R.transaction_id, l_reg_expr1, 1,1,NULL,2) ||                   
                   regexp_substr(R.transaction_id, l_reg_expr1, 1,1,NULL,3) trans_id
              from altria_reports R) A,
                   (select time_id,
                           midax_sale_id,
                           midax_card_id,
                           store_no,
                           regexp_substr(trans_id, l_reg_expr2, 1,1,NULL,1) trans_id
                      from
                           (select trunc(T.time_id) time_id,
                                   t.sale_id midax_sale_id,
                                   t.card_id midax_card_id,
                                   (select store_no from store where id = T.store_id) store_no,
                                   pos_transaction_number,
                                   T.terminal_id || substr(pos_transaction_number, 1, 7) trans_id
                              from trips_extra_info I, TABLE(l_trips) T
                             where T.sale_id = I.sale_id)) B
             where A.time_id = B.time_id
               and A.Store_No = B.store_no
               and A.trans_id = B.trans_id; 
    
    TYPE t_id_tab IS TABLE OF my_curr%rowtype INDEX BY PLS_INTEGER;
    tab t_id_tab;
     
  begin

    l_trips := get_trips_array;
    l_reg_expr1 := get_reg_expr('LEFT');
    l_reg_expr2 := get_reg_expr('RIGHT');    
    
    open my_curr;
    loop
      fetch my_curr bulk collect
        into tab limit 3000;
      EXIT WHEN tab.COUNT = 0;
    
      FORALL indx IN 1 .. tab.COUNT
        update altria_reports S
           set S.midax_sale_id = tab(indx).midax_sale_id,
               S.Loyalty_Id = set_loyalty_id( tab(indx).midax_card_id )
         where S.transaction_id = tab(indx).transaction_id;
       commit;
    end loop;
    close my_curr;
    commit;    
    
  exception
    when OTHERS then
      raise;
  end;    
  
  -- -----------------------------------------------------------------
  -- Procedure :    set_midax_sale_id
  -- Description :  only for enrichment of external files - this means that we already have Altria file, but we want to add some customer info.
  --                The process is that we have external data in our ALTRIA_REPORTS table, then adding extra info, and the last step - export as CSV file
  -- Params :       .
  -- Author  :      Vesel
  -- -----------------------------------------------------------------
  procedure set_midax_sale_id1 is

    l_trips t_sale;
    l_reg_expr ALTRIA_CONFIG_MAIN.Left_Reg_Expr%TYPE;
    
   
    
    cursor my_curr is
    select B.*,
           replace(replace(replace(l_reg_expr, 
                   'TRANSACTION_ID', B.trans_id),
                   'TERMINAL_ID', B.terminal_id),
                   'YYYYMMDD', to_char(B.time_id, 'YYYYMMDD')) REG_EXPR_STR 
      from (
            select trunc(T.time_id) time_id,
                   t.sale_id midax_sale_id,
                   (select store_no from store where id = T.store_id) store_no,
                   T.terminal_id,
                   I.pos_transaction_number,
                   substr(pos_transaction_number, 1, 7) trans_id
              from trips_extra_info I, TABLE(l_trips) T
             where T.sale_id = I.sale_id) B;
               
                                                 
    
    TYPE t_id_tab IS TABLE OF my_curr%rowtype INDEX BY PLS_INTEGER;
    tab t_id_tab;    
  begin

    l_trips := get_trips_array;
    l_reg_expr := get_reg_expr('LEFT');
    
    open my_curr;
    loop
      fetch my_curr bulk collect
        into tab limit 6000;
      EXIT WHEN tab.COUNT = 0;
    
      FORALL indx IN 1 .. tab.COUNT
        update altria_reports S
           set S.midax_sale_id = tab(indx).midax_sale_id
         where S.transaction_id = REGEXP_SUBSTR(S.transaction_id, tab(indx).REG_EXPR_STR)
           and S.STORE_NO = tab(indx).store_no
           and trunc(S.TRANSACTION_DATE) = tab(indx).time_id;
           
    end loop;
    close my_curr;
    commit;    
    
  exception
    when OTHERS then
      raise;
  end;    
  
  -- -----------------------------------------------------------------
  -- Procedure :    trigger_proc
  -- Description :  This is not used any more - for delete
  -- Params :       .
  -- Author  :      Vesel
  -- -----------------------------------------------------------------    
  procedure trigger_proc(pChain varchar2, pWeek number default 0) is
  begin

    -- now the process is simple - we expect only week as number from the year as parameter and chain
    set_week_days(pWeek);
    g_chain := pChain;
    
    import_midax_tobacco;
    set_all_discounts;
    commit;

  exception
    when OTHERS then
      raise;
  end;

  -- -----------------------------------------------------------------
  -- Procedure :    trigger_proc
  -- Description :  
  -- Params :       .
  -- Author  :      Vesel
  -- -----------------------------------------------------------------    
  procedure trigger_proc(pChain varchar2, pDate date default sysdate) is
  begin

    -- now the process is simple - we expect only week as number from the year as parameter and chain
    set_week_days(pDate);
    g_chain := pChain;
    
    import_midax_tobacco;
    set_all_discounts;
    commit;

  exception
    when OTHERS then
      raise;
  end;  
  -- -----------------------------------------------------------------
  -- Procedure :    enrichment_proc
  -- Description :  
  -- Params :       .
  -- Author  :      Vesel
  -- -----------------------------------------------------------------  
  procedure enrichment_proc(pChain varchar2) is
 
  begin

    g_chain := pChain; 
    import_external_file;

    begin
      select trunc(min(transaction_date)), trunc(max(transaction_date))
        into g_start_date, g_end_date
        from altria_reports;
    exception when OTHERS then
      dbms_output.put_line('!!! Invalid date interval !!!');
      return;
    end;
    
    set_midax_sale_id;
    set_all_discounts;
    post_process;
    commit;
  end; 

begin
  DBMS_SESSION.set_identifier('ALTRIA_PROCESS');
end FS_ALTRIA;
/