 
/*********************************************\
*   ABSSOLUTE Oracle Objects                  *
*                                             *
*   Objects:           PROCEDURES             *
*   Database version:  09.09.00               *
*   Date:              15-APR-2026            *
\*********************************************/
 
set define off 
 
create or replace procedure ABSLOGSWRITE(PARAM_LOGSOURCE  IN varchar2,
                                         PARAM_PLANT_ID   IN number,
                                         PARAM_PRIORITY   IN number,
                                         PARAM_MESSAGE    IN VARCHAR2 ) is
begin
  insert into ABSLOG (ABSLOG_ID,LOGTYPE,LOGSOURCE,PLANT_ID,PRIORITY,TIMESTAMP,SYSTEMUSER_ID,MESSAGE)
    select seq_abslog.nextval,
           5,
           PARAM_LOGSOURCE,
           PARAM_PLANT_ID,
           case
             when PARAM_PRIORITY not in (1, 2, 3, 5) then
              1
             else
              PARAM_PRIORITY
           end case,
           SYSDATE,
           0,
           PARAM_MESSAGE
      from dual;
   commit;
end ABSLOGSWRITE;
/
create or replace PROCEDURE ABS_COMPILE_INVALID_OBJECTS(status           out integer,
                                                        run_dbms_utility in integer) is
  --uname varchar2(50) := 'ABSSOLUTE';
begin
  status := 0;

  for c in (select 'alter ' ||
       decode(object_type, 'PACKAGE BODY', 'package', object_type) || ' "' ||
       object_name || '" compile' ||
       decode(object_type, 'PACKAGE BODY', ' body', '') ddl
                           from user_objects
                           where status = 'INVALID'
                           order by object_type) loop
    begin
      execute immediate c.ddl;
    exception
      when others then
        status := status + 1;
    end;
  end loop;


end ABS_COMPILE_INVALID_OBJECTS;
/
create or replace procedure ABS_COMPILE_INVALID_OBJECTS_W is
  status integer;
begin

  for i in 1 .. 5 loop
    if i = 1 then
      ABS_COMPILE_INVALID_OBJECTS(status, 0);
    else
      ABS_COMPILE_INVALID_OBJECTS(status, 1);
    end if;
    if status = 0 then
      exit;
    end if;
    dbms_output.put_line(i || ' ' || status);
  end loop;

end ABS_COMPILE_INVALID_OBJECTS_W;
/
create or replace procedure abs_rebuildindex is
  ncounter  number := 0;
  vdel_perc number;
  vheight   number;
begin
  for x in (select *
            from   user_indexes s
            where  s.index_type <> 'LOB'
            and    s.partitioned = 'NO') loop
    begin
      ---analyse index
      execute immediate 'ANALYZE INDEX ' || x.index_name || ' VALIDATE STRUCTURE';
      ---check stats
      select (del_lf_rows / lf_rows) * 100, height
      into   vdel_perc, vheight
      from   index_stats
      where  lf_rows > 0;
      ---rebuild if needed
      if (vdel_perc > 25 or vheight > 5) then
        begin
          execute immediate 'alter index ' || x.index_name || ' rebuild tablespace INDX';
          ncounter := ncounter + 1;
        exception
          when others then
            dbms_output.put_line(' Error ABS_RebuildIndex, during rebuild: ' ||
                                 substr(sqlerrm, 1, 200));
        end;
      end if;
    exception
      when no_data_found then
        null;
      when others then
        dbms_output.put_line(' Error ABS_RebuildIndex during loop: ' || substr(sqlerrm, 1, 200));
    end;
  end loop;
  dbms_output.put_line(to_char(ncounter) || ' indexes rebuild.');
  dbms_output.put_line('ABS_RebuildIndex. Succesfully ran.');
end abs_rebuildindex;
/
create or replace procedure abs_rebuildindex_all is
  lvsindexname user_indexes.index_name%type;
begin
  for x in (select s.index_name
            from   user_indexes s
            where  s.partitioned = 'NO'
            and    s.index_type <> 'LOB'
            and    s.tablespace_name <> 'INDX') loop
    begin
      lvsindexname := x.index_name;
      execute immediate 'alter index ' || x.index_name || ' rebuild tablespace INDX';
    end;
  end loop;
  dbms_output.put_line('abs_rebuildindex_all. Succesfully ran.');
exception
  when others then
    begin
      dbms_output.put_line('Error abs_rebuildindex_all for index: ' || lvsindexname);
      dbms_output.put_line(substr(sqlerrm, 1, 200));
    end;
end abs_rebuildindex_all;
/
create or replace procedure AccpacExport(param_sysuser_ID                       IN systemuser.systemuser_id%type,
                                         param_plant_ID                         IN businessunit.plant_id%type,
                                         param_processlogjobpart_ID             IN abslogprocessjobpart.abslogprocessjobpart_id%type,
                                         gverrrormsg                            out abslog.message%type,
                                         gv_code                                out integer,
                                         gv_filename                            out varchar2,
                                         nb_invoices_exported                   out integer) is

  gvdirectory systemsetting.value%type;
  gvfile      utl_file.file_type;

  procedure write_log(fp_message  in abslog.message%type,
                      fp_priority in abslog.priority%type default 1) is
  begin
    /*
    Write message in ABSLOG with these priorities
    1 = Message
    2 = Warning
    3 = Error
    4 = Stack trace
    5 = Debug info
    */
    abslogwrite.abslogprocessjobline_write (param_processlogjobpart_ID,
                                            fp_priority,
                                            fp_message,
                                            param_sysuser_ID);
   end write_log;

  --get the value of the system setting FINEXPORTDIRECTORY of the plant
  procedure get_directory is
  begin

    gverrrormsg := 'get_directory';
    select nvl(ss.value, ss.factorydefault)
      into gvdirectory
      from plant p, systemsetting ss
     where p.plant_id = param_plant_ID
       and p.plant_id = ss.plant_id
       and ss.name = 'FINEXPORTDIRECTORY';

   exception when others then
      begin
      gverrrormsg := 'Error on getting system setting FINEXPORTDIRECTORY';
      gv_code:=1;
      write_log (gverrrormsg,3);
      end;
  end get_directory;

  procedure write_file is
    lv_timestamp varchar2(15);
    lv_plantcode plant.code%type;
  begin
    get_directory;
    gverrrormsg := 'open_file ' || gvdirectory || gv_filename;
    --get plant code
    select p.code
      into lv_plantcode
      from plant p
     where p.plant_id = param_plant_ID;
    --get timestamp
    select to_char(sysdate, 'yyyymmdd_hhmiss') into lv_timestamp from dual;
    gv_filename := 'ACCPAC_' || lv_plantcode || '_' || lv_timestamp ||
                   '.CSV';

    --create file
    gvfile := utl_file.fopen(gvdirectory, gv_filename, 'w');
    write_log('Created export file ' || gv_filename, 1);
  exception
    when others then
    begin
    gverrrormsg:='Error on creating/writing in file!';
    gv_code:=1;
    write_log (gverrrormsg,3);
    end;
 end write_file;

  --close file procedure
  procedure close_file is
  begin

    if utl_file.is_open(gvfile) = true then
      utl_file.fclose(gvfile);
    end if;
    utl_file.fclose_all;
    exception when others then
      begin
        gverrrormsg:='Error! Could not close file!';
        gv_code:=1;
        write_log (gverrrormsg,3);
        end;
  end close_file;

  --write first line
  procedure first_line is
  begin

    utl_file.put_line(gvfile,
                      'ACCPAC,' || 'Facility/Group Name,' || 'Invoice,' ||
                      '112,' || '243,' || '306,' || '311,' ||
                      '316,' || '337,' || '341,' || '347,' ||
                      '350,' || '361,' || '364,' || '365,' ||
                      '366,' || '367,' || '370,' || '371,' ||
                      '372,' || '373,' || '374,' || '375,' ||
                      '376,' || '377,' || '378,' || '379,' ||
                      '12011150');
  exception when others then
    begin
        gverrrormsg:='Error! Could not write header in file!';
        gv_code:=1;
        write_log (gverrrormsg,3);
        end;
  end first_line;

  --process line
  procedure process_line is
    cursor AccPac_customer is
      select x.artransaction_id artransaction_exported,
             min(x.searchname) searchname,
             min(x.legacycustomernumber) legacycustomernumber,
             min(x.name) name,
             min(x.invoicenumber) invoicenumber,
             min(x."a0112") a0112,
             sum(x."a0243")/decode(sum(x."aa"), null, 1, count(*)) a0243,
             sum(x."a0306")/decode(sum(x."aa"), null, 1, count(*)) a0306,
             sum(x."a0311")/decode(sum(x."aa"), null, 1, count(*)) a0311,
             sum(x."a0316")/decode(sum(x."aa"), null, 1, count(*)) a0316,
             sum(x."a0337")/decode(sum(x."aa"), null, 1, count(*)) a0337,
             sum(x."a0341")/decode(sum(x."aa"), null, 1, count(*)) a0341,
             sum(x."a0347")/decode(sum(x."aa"), null, 1, count(*)) a0347,
             sum(x."a0350")/decode(sum(x."aa"), null, 1, count(*)) a0350,
             sum(x."a0361")/decode(sum(x."aa"), null, 1, count(*)) a0361,
             sum(x."a0364")/decode(sum(x."aa"), null, 1, count(*)) a0364,
             sum(x."a0365")/decode(sum(x."aa"), null, 1, count(*)) a0365,
             sum(x."a0366")/decode(sum(x."aa"), null, 1, count(*)) a0366,
             sum(x."a0367")/decode(sum(x."aa"), null, 1, count(*)) a0367,
             sum(x."a0370")/decode(sum(x."aa"), null, 1, count(*)) a0370,
             sum(x."a0371")/decode(sum(x."aa"), null, 1, count(*)) a0371,
             sum(x."a0372")/decode(sum(x."aa"), null, 1, count(*)) a0372,
             sum(x."a0373")/decode(sum(x."aa"), null, 1, count(*)) a0373,
             sum(x."a0374")/decode(sum(x."aa"), null, 1, count(*)) a0374,
             sum(x."a0375")/decode(sum(x."aa"), null, 1, count(*)) a0375,
             sum(x."a0376")/decode(sum(x."aa"), null, 1, count(*)) a0376,
             sum(x."a0377")/decode(sum(x."aa"), null, 1, count(*)) a0377,
             sum(x."a0378")/decode(sum(x."aa"), null, 1, count(*)) a0378,
             sum(x."a0379")/decode(sum(x."aa"), null, 1, count(*)) a0379,
             sum(x."a12011150")/decode(sum(x."aa"), null, 1, count(*)) a12011150

        from (select a.artransaction_id,
                     c.searchname,
                     c.legacycustomernumber,
                     c.name,
                     a.invoicenumber,
                     a.amount*(-1) "a0112",
                     a.parentartransaction_id "aa",
                     case
                       when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=243)

                       when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=243
                         then
                           al.amount
                           else
                        null
                     end "a0243",

                     case
                        when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=306)
                       when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=306 then
                           al.amount
                       else
                        null
                     end "a0306",
                     case
                       when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=311)
                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=311 then
                           al.amount
                       else
                        null
                     end "a0311",
                     case
                        when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=316)
                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=316 then
                           al.amount
                       else
                        null
                     end "a0316",
                     case
                      when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=337)
                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=337 then
                           al.amount
                       else
                        null
                     end "a0337",
                     case
                       when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=341)
                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=341 then
                           al.amount
                       else
                        null
                     end "a0341",
                     case
                        when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=347)
                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=347 then
                           al.amount
                       else
                        null
                     end "a0347",
                     case
                        when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=350)
                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=350 then
                           al.amount
                       else
                        null
                     end "a0350",
                     case
                        when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=361)
                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=361 then
                           al.amount
                       else
                        null
                     end "a0361",
                     case
                       when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=364)
                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=364 then
                           al.amount
                       else
                        null
                     end "a0364",
                      case
                        when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=365)
                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=365 then
                           al.amount
                       else
                        null
                     end "a0365",
                     case
                      when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=366)

                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=366 then
                           al.amount
                       else
                        null
                     end "a0366",
                      case
                       when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=367)

                       when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=367
                         then
                           al.amount
                           else
                        null
                     end "a0367",
                     case
                       when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=370)

                       when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=370
                         then
                           al.amount
                           else
                        null
                     end "a0370",
                      case
                        when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=371)
                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=371 then
                           al.amount
                       else
                        null
                     end "a0371",
                      case
                        when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=372)
                       when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=372 then
                           al.amount
                       else
                        null
                     end "a0372",
                      case
                       when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=373)

                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=373 then
                           al.amount
                       else
                        null
                     end "a0373",
                      case
                       when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=374)

                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=374 then
                           al.amount
                       else
                        null
                     end "a0374",
                      case
                        when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=375)

                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=375 then
                           al.amount
                       else
                        null
                     end "a0375",
                      case
                        when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=376)

                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=376 then
                           al.amount
                       else
                        null
                     end "a0376",
                      case
                        when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=377)

                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=377 then
                           al.amount
                       else
                        null
                     end "a0377",
                      case
                       when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=378)
                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=378 then
                           al.amount
                       else
                        null
                     end "a0378",
                      case
                        when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=379)
                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=379 then
                           al.amount
                       else
                        null
                     end "a0379",
                      case
                        when a.parentartransaction_id is not null
                          then
                        (select sum(oll.amount)
                         from artransaction act2, artransledgeraccounts oll, ledgeraccounts ll
                         where a.parentartransaction_id = act2.parentartransaction_id
                         and a.artransaction_id = a.parentartransaction_id
                         and oll.artransaction_id = act2.artransaction_id
                         and ll.ledgeraccounts_id = oll.ledgeraccounts_id
                         and ll.accountnumber=12011150)
                        when a.parentartransaction_id is null and al.amount <> 0 and l.accountnumber=12011150 then
                           al.amount
                       else
                        null
                     end "a12011150"
                from artransledgeraccounts al,
                     ledgeraccounts        l,
                     artransaction         a,
                     customer              c,
                     artransactiontype     art,
                     businessunit          b
               where l.ledgeraccounts_id = al.ledgeraccounts_id
                 and a.artransaction_id = al.artransaction_id
                 and c.customer_id = a.billtocustomer_link_id
                 and a.exportstatus = 1
                 and b.plant_id = param_plant_ID
                 and art.artransactiontype_id = a.artransactiontype_id
                 and b.businessunit_id = a.businessunit_id
                 and a.invoicenumber <> 0
                 and art.debitcredit = 'D'
                 and art.typenumber = 1
                 and ((a.parentartransaction_id is null) or (a.parentartransaction_id = a.artransaction_id))) x
       group by x.artransaction_id;

    i                      integer := 0;

    accountcode           customer.searchname%type;
    facility              customer.name%type;
    invoicenb             artransaction.invoicenumber%type;
    art_0112              varchar2(20);
    art_0243              varchar2(20);
    art_0306              varchar2(20);
    art_0311              varchar2(20);
    art_0316              varchar2(20);
    art_0337              varchar2(20);
    art_0341              varchar2(20);
    art_0347              varchar2(20);
    art_0350              varchar2(20);
    art_0361              varchar2(20);
    art_0364              varchar2(20);
    art_0365              varchar2(20);
    art_0366              varchar2(20);
    art_0367              varchar2(20);
    art_0370              varchar2(20);
    art_0371              varchar2(20);
    art_0372              varchar2(20);
    art_0373              varchar2(20);
    art_0374              varchar2(20);
    art_0375              varchar2(20);
    art_0376              varchar2(20);
    art_0377              varchar2(20);
    art_0378              varchar2(20);
    art_0379              varchar2(20);
    art_12011150          varchar2(20);

    artrans_update        artransaction.artransaction_id%type;


  begin
    nb_invoices_exported:=0;
    for c_select_cust in AccPac_customer loop
      i := i + 1;

    art_0243  := NULL;
    art_0306  := NULL;
    art_0311  := NULL;
    art_0316  := NULL;
    art_0337  := NULL;
    art_0341  := NULL;
    art_0347  := NULL;
    art_0350  := NULL;
    art_0361  := NULL;
    art_0364  := NULL;
    art_0365  := NULL;
    art_0366  := NULL;
    art_0367  := NULL;
    art_0370  := NULL;
    art_0371  := NULL;
    art_0372  := NULL;
    art_0373  := NULL;
    art_0374  := NULL;
    art_0375  := NULL;
    art_0376  := NULL;
    art_0377  := NULL;
    art_0378  := NULL;
    art_0379  := NULL;
    art_12011150    := NULL;
      --get facility name
      if (instr(c_select_cust.name,',')>0) then
          facility := '"'||c_select_cust.name||'"';
          else
            facility := c_select_cust.name;
            end if;
      --get invoice number
      invoicenb := c_select_cust.invoicenumber;
      --get Invoice amount including taxes - column 0112
          art_0112 :=ltrim(to_char(c_select_cust.a0112,'9999990.99'),' ');
       --get Invoice amount including taxes - column 0243
               if c_select_cust.a0243 is not null then
               art_0243 :=ltrim(to_char(c_select_cust.a0243 ,'9999990.99'),' ');
         end if;


               --get Invoice amount including taxes - column 0306
                if c_select_cust.a0306 is not null then
                art_0306 :=ltrim(to_char(c_select_cust.a0306 ,'9999990.99'),' ');
         end if;

               --get Invoice amount including taxes - column 0311
                if c_select_cust.a0311 is not null then
                art_0311 :=ltrim(to_char(c_select_cust.a0311 ,'9999990.99'),' ');
         end if;

              --get Invoice amount including taxes - column 0316
                   if c_select_cust.a0316 is not null then
                   art_0316 :=ltrim(to_char(c_select_cust.a0316 ,'9999990.99'),' ');
         end if;

             --get Invoice amount including taxes - column 0337
                if c_select_cust.a0337 is not null then
                art_0337 :=ltrim(to_char(c_select_cust.a0337 ,'9999990.99'),' ');
         end if;


               --get Invoice amount including taxes - column 0341
               if c_select_cust.a0341 is not null then
               art_0341 :=ltrim(to_char(c_select_cust.a0341 ,'9999990.99'),' ');
         end if;

               --get Invoice amount including taxes - column 0347
                if c_select_cust.a0347 is not null then
                art_0347 :=ltrim(to_char(c_select_cust.a0347 ,'9999990.99'),' ');
         end if;

               --get Invoice amount including taxes - column 0350
                if c_select_cust.a0350 is not null then
                art_0350 :=ltrim(to_char(c_select_cust.a0350 ,'9999990.99'),' ');
         end if;

              --get Invoice amount including taxes - column 0361
                     if c_select_cust.a0361 is not null then
                     art_0361 :=ltrim(to_char(c_select_cust.a0361 ,'9999990.99'),' ');
         end if;

             --get Invoice amount including taxes - column 0364
                if c_select_cust.a0364 is not null then
                art_0364 :=ltrim(to_char(c_select_cust.a0364 ,'9999990.99'),' ');
         end if;

          --get Invoice amount including taxes - column 0365
                if c_select_cust.a0365 is not null then
                art_0365 :=ltrim(to_char(c_select_cust.a0365 ,'9999990.99'),' ');
         end if;

          --get Invoice amount including taxes - column 0366
                if c_select_cust.a0366 is not null then
                art_0366 :=ltrim(to_char(c_select_cust.a0366 ,'9999990.99'),' ');
         end if;

          --get Invoice amount including taxes - column 0367
                if c_select_cust.a0367 is not null then
                art_0367 :=ltrim(to_char(c_select_cust.a0367 ,'9999990.99'),' ');
         end if;

          --get Invoice amount including taxes - column 0370
                if c_select_cust.a0370 is not null then
                art_0370 :=ltrim(to_char(c_select_cust.a0370 ,'9999990.99'),' ');
         end if;

          --get Invoice amount including taxes - column 0371
                if c_select_cust.a0371 is not null then
                art_0371 :=ltrim(to_char(c_select_cust.a0371 ,'9999990.99'),' ');
         end if;

          --get Invoice amount including taxes - column 0372
                if c_select_cust.a0372 is not null then
                art_0372 :=ltrim(to_char(c_select_cust.a0372 ,'9999990.99'),' ');
         end if;

          --get Invoice amount including taxes - column 0373
                if c_select_cust.a0373 is not null then
                art_0373 :=ltrim(to_char(c_select_cust.a0373 ,'9999990.99'),' ');
         end if;

          --get Invoice amount including taxes - column 0374
                if c_select_cust.a0374 is not null then
                art_0374 :=ltrim(to_char(c_select_cust.a0374 ,'9999990.99'),' ');
         end if;

          --get Invoice amount including taxes - column 0375
                if c_select_cust.a0375 is not null then
                art_0375 :=ltrim(to_char(c_select_cust.a0375 ,'9999990.99'),' ');
         end if;

          --get Invoice amount including taxes - column 0376
                if c_select_cust.a0376 is not null then
                art_0376 :=ltrim(to_char(c_select_cust.a0376 ,'9999990.99'),' ');
         end if;

          --get Invoice amount including taxes - column 0377
                if c_select_cust.a0377 is not null then
                art_0377 :=ltrim(to_char(c_select_cust.a0377 ,'9999990.99'),' ');
         end if;

          --get Invoice amount including taxes - column 0378
                if c_select_cust.a0378 is not null then
                art_0378 :=ltrim(to_char(c_select_cust.a0378 ,'9999990.99'),' ');
         end if;

          --get Invoice amount including taxes - column 0379
                if c_select_cust.a0379 is not null then
                 art_0379 :=ltrim(to_char(c_select_cust.a0379 ,'9999990.99'),' ');
         end if;


          --get Invoice amount including taxes - column 12011150
                if c_select_cust.a12011150 is not null then
                art_12011150 :=ltrim(to_char(c_select_cust.a12011150 ,'9999990.99'),' ');
         end if;

      --get artransaction_id, necessary for update
      artrans_update:=c_select_cust.artransaction_exported;
      --get account code
      accountcode := c_select_cust.searchname;
        utl_file.put_line(gvfile,
                            accountcode || ',' || facility || ',' ||
                            invoicenb || ',' || art_0112 || ',' || art_0243 || ',' || art_0306 || ',' ||
                             art_0311 || ',' || art_0316 || ',' || art_0337 || ',' || art_0341 || ',' ||
                             art_0347 || ',' || art_0350 || ',' || art_0361 || ',' || art_0364 || ',' ||
                             art_0365 || ',' || art_0366 || ',' || art_0367 || ',' || art_0370 || ',' ||
                             art_0371 || ',' || art_0372 || ',' || art_0373 || ',' || art_0374 || ',' ||
                             art_0375 || ',' || art_0376 || ',' || art_0377 || ',' || art_0378 || ',' ||
                             art_0379 || ',' ||art_12011150 );
        update artransaction art
        set art.exportstatus=2
        where art.artransaction_id=c_select_cust.artransaction_exported;
        commit;
        nb_invoices_exported:=nb_invoices_exported+1;
    end loop;
    write_log('Number of invoices exported ' || nb_invoices_exported, 1);
    exception when others then
      begin
              gverrrormsg:='Error! Export ended with errors';
              gv_code:=1;
              write_log (gverrrormsg,3);
              rollback;
              end;
  end process_line;


begin
  gv_code:=0;
  write_file;
  first_line;
  process_line;
  close_file;
end AccpacExport;
/
create or replace procedure AddorUpdateProduct(pCode             in Product.Code%type,
                                               pDescription      in Product_Desc.Description%type,
                                               pLongdescription  in Product_Desc.Longdescription%type,
                                               pShortdescription in Product.Shortdescription%type,
                                               pLegacycode       in Product.Legacyproductcode%type,
                                               pPackingsequence  in Product.Packingsequence%type,
                                               -- pPack                in Product.Pack%type,
                                               pOccupancyrelated    in Product.Occupancyrelated%type,
                                               Bundlequantity       in number,
                                               pTheoreticalweight   in Product.Theoreticalweight%type,
                                               Colorcode            in Color.Code%type,
                                               Colordescription     in Color_Desc.Description%type,
                                               Fabriccode           in Fabric.Code%type,
                                               Fabricdescription    in Fabric_Desc.Description%type,
                                               Productgroupcode     in Productgroup.Code%type,
                                               Washprocesscode      in Washingprocess.code%type,
                                               Washprocessdesc      in Washingprocess_Desc.Description%type,
                                               pSuppliernumber      in Supplier.Suppliernumber%type,
                                               Suppliername         in Supplier.Name%type,
                                               Registrationunitcode in Registrationunit.code%type,
                                               pRecordpassivestock  in Product.Recordpassivestock%type,
                                               pTypeofmerchandise   in Product.Typeofmerchandise%type,
                                               Taxgroupcode         in varchar2,
                                               pPutuptype           in Product.Putuptype%type,
                                               pMaxwashes           in Product.Maxwashes%type,
                                               pExchangemethod      in Product.Exchangemethod%type,
                                               pSoilcountmethod     in Product.Soilcountmethod%type,
                                               pUniqueitempool      in Product.Uniquepoolitem%type,
                                               pFinishingcode       in Finishingcode.Finishingcode%type,
                                               Sizetypecode         in Sizetype.Code%type,
                                               Sizetypedescription  in Sizetype_Desc.Description%type,
                                               pOptimafactor        in Product.Optimafactor%type,
                                               Deftresvalschemecode in Residualvaluescheme.Code%type,
                                               pVolumeunits         in Product.Volumeunits%type,
                                               Status               out number) is
  productid             product.product_id%type;
  productgroupid        productgroup.productgroup_id%type;
  insertupdate          number; --0 insert, 1 update
  sizetypeid            sizetype.sizetype_id%type;
  systemuserid          systemuser.systemuser_id%type;
  languageid            languages.language_id%type;
  colorid               color.color_id%type;
  fabricid              fabric.fabric_id%type;
  washingprocessid      washingprocess.washingprocess_id%type;
  supplierid            supplier.supplier_id%type;
  registrationunitid    registrationunit.registrationunit_id%type;
  residualvalueschemeid residualvaluescheme.residualvaluescheme_id%type;
  finishingcodeid       finishingcode.finishingcode_id%type;
  countryid             country.country_id%type;
  taxgroupid            taxgroup.taxgroup_id%type;
  currencyid            currency.currency_id%type;
  addressid             address.address_id%type;
  SQLfile               utl_file.file_type;
  UTLDIR                varchar2(50); --:= please see ABS-92804 variable needs the name of an existing oracle directory
  FPsFilename           varchar2(50);
  debuglevel            integer := 1;
  sessionsid            integer;
  sessionserialnr       integer;
  pddescription         product_desc.description%type;
  pdlongdescription     product_desc.longdescription%type;
  uShortdescription     Product.Shortdescription%type;
  uLegacyproductcode    Product.Legacyproductcode%type;
  uPackingsequence      Product.Packingsequence%type;
  -- pPack                in Product.Pack%type,
  uOccupancyrelated    Product.Occupancyrelated%type;
  uTheoreticalweight   Product.Theoreticalweight%type;
  uRecordpassivestock  Product.Recordpassivestock%type;
  uTypeofmerchandise   Product.Typeofmerchandise%type;
  uPutuptype           Product.Putuptype%type;
  uMaxwashes           Product.Maxwashes%type;
  uExchangemethod      Product.Exchangemethod%type;
  uSoilcountmethod     Product.Soilcountmethod%type;
  uuniquepoolitem      Product.Uniquepoolitem%type;
  uOptimafactor        Product.Optimafactor%type;
  uVolumeunits         Product.Volumeunits%type;
  upackingamount       product.packingamount%type;
  productlinkid        product_link.product_link_id%type;
  registrationunitdesc registrationunit_desc.description%type;
  plddesc              product_link_desc.description%type;
begin
  --atentie utldir
  begin
    select s.dblogdir into UTLDIR from databasesettings s;
  EXCEPTION
    WHEN no_data_found then
      UTLDIR := 'C:\'; -- please see ABS-92804 variable needs the name of an existing oracle directory
  end;
  select a.SID, a.SERIAL#
    into sessionsid, sessionserialnr
    from SYS.V_$SESSION a
   where a.AUDSID = (SELECT sys_context('USERENV', 'SESSIONID') FROM dual);
  FPsFilename := 'AddorUpdateProduct_' ||
                 to_char(sysdate, 'YYYYMMDDHHMMSS') || '_' || sessionsid || '_' ||
                 sessionserialnr || '.txt';
  SqlFile     := UTL_FILE.FOPEN(UTLDIR, FPsFilename, 'a');
  begin
    Status       := 0;
    insertupdate := 1;
    begin
      select s.systemuser_id
        into systemuserid
        from systemuser s
       where s.username = 'AXAPTA';
    exception
      when no_data_found then
        select min(s.systemuser_id) into systemuserid from systemuser s;
    end;
    begin
      select p.product_id
        into productid
        from product p
       where p.code = pCode;
    exception
      when no_data_found then
        insertupdate := 0;
    end;
    begin
      select pg.productgroup_id
        into productgroupid
        from productgroup pg
       where pg.code = Productgroupcode;
    exception
      when no_data_found then
        Status := 2;
        if debuglevel > 0 then
          utl_file.put_line(SQLfile,
                            '!> Product group ' || Productgroupcode ||
                            ' not found ' || sqlcode || ' ' || sqlerrm);
        end if;
    end;
    if Status = 0 then
      begin
        select l.language_id
          into languageid
          from languages l
         where l.code = 'DA_DK';
      exception
        when no_data_found then
          Status := 3;
          if debuglevel > 0 then
            utl_file.put_line(SQLfile,
                              '!> Language DA_DK not found ' || sqlcode || ' ' ||
                              sqlerrm);
          end if;
      end;
    end if;
    select min(country_id) into countryid from country;
    select min(currency_id) into currencyid from currency;
    --check parameter values
    if Status = 0 then
      if pTypeofmerchandise in (1, 2, 3, 4, 5) and
         pPutuptype in (1, 2, 3, 4) and pExchangemethod in (1, 2, 3) and
         pSoilcountmethod in (0, 1, 2, 3) then
        Status := 0;
      else
        Status := 10;
        if debuglevel > 0 then
          utl_file.put_line(SQLfile,
                            '!> Parameters values out of range (typeofmerchandise or putuptype or exchangemethod or soilcountmethod)');
        end if;
      end if;
    end if;
    if Status = 0 then
      begin
        select st.sizetype_id
          into sizetypeid
          from sizetype st
         where st.code = Sizetypecode;
      exception
        when no_data_found then
          begin
            insert into sizetype
              (sizetype_id, code, systemuser_id, timestamp)
            values
              (seq_sizetype.nextval,
               upper(Sizetypecode),
               systemuserid,
               sysdate);
            insert into sizetype_desc
              (sizetype_id,
               language_id,
               description,
               systemuser_id,
               timestamp)
            values
              (seq_sizetype.currval,
               languageid,
               Sizetypedescription,
               systemuserid,
               sysdate);
          exception
            when others then
              Status := 20;
              if debuglevel > 0 then
                utl_file.put_line(SQLfile,
                                  '!> Sizetype ' || Sizetypecode ||
                                  ' insert failed  ' || sqlcode || ' ' ||
                                  sqlerrm);
              end if;
          end;
      end;
      begin
        select c.color_id
          into colorid
          from color c
         where c.code = Colorcode;
      exception
        when no_data_found then
          begin
            insert into color
              (color_id,
               code,
               ralcode,
               systemuser_id,
               timestamp,
               usedforemblem,
               pantonecode)
            values
              (seq_color.nextval,
               upper(Colorcode),
               null,
               systemuserid,
               sysdate,
               'N',
               null);
            insert into color_desc
              (color_id,
               language_id,
               description,
               systemuser_id,
               timestamp)
            values
              (seq_color.currval,
               languageid,
               Colordescription,
               systemuserid,
               sysdate);
          exception
            when others then
              Status := 21;
              if debuglevel > 0 then
                utl_file.put_line(SQLfile,
                                  '!> Color ' || Colorcode ||
                                  ' insert failed  ' || sqlcode || ' ' ||
                                  sqlerrm);
              end if;
          end;
      end;
      begin
        select f.fabric_id
          into fabricid
          from fabric f
         where f.code = Fabriccode;
      exception
        when no_data_found then
          begin
            insert into fabric
              (fabric_id, code, systemuser_id, timestamp, usedforemblem)
            values
              (seq_fabric.nextval,
               upper(Fabriccode),
               systemuserid,
               sysdate,
               'N');
            insert into fabric_desc
              (fabric_id,
               language_id,
               description,
               systemuser_id,
               timestamp)
            values
              (seq_fabric.currval,
               languageid,
               Fabricdescription,
               systemuserid,
               sysdate);
          exception
            when others then
              Status := 22;
              if debuglevel > 0 then
                utl_file.put_line(SQLfile,
                                  '!> Fabric ' || Fabriccode ||
                                  ' insert failed  ' || sqlcode || ' ' ||
                                  sqlerrm);
              end if;
          end;
      end;
      begin
        select w.washingprocess_id
          into washingprocessid
          from washingprocess w
         where w.code = Washprocesscode;
      exception
        when no_data_found then
          begin
            insert into washingprocess
              (washingprocess_id,
               code,
               systemuser_id,
               timestamp,
               color,
               sortcode)
            values
              (seq_washingprocess.nextval,
               upper(Washprocesscode),
               systemuserid,
               sysdate,
               '66ff 0', --grey
               null);
            insert into washingprocess_desc
              (washingprocess_id,
               language_id,
               description,
               systemuser_id,
               timestamp)
            values
              (seq_washingprocess.currval,
               languageid,
               Washprocessdesc,
               systemuserid,
               sysdate);
          exception
            when others then
              Status := 23;
              if debuglevel > 0 then
                utl_file.put_line(SQLfile,
                                  '!> Washprocess ' || Washprocesscode ||
                                  ' insert failed  ' || sqlcode || ' ' ||
                                  sqlerrm);
              end if;
          end;
      end;
      begin
        select s.supplier_id
          into supplierid
          from supplier s
         where s.suppliernumber = pSuppliernumber;
      exception
        when no_data_found then
          begin

            begin
              select min(a.address_id)
                into addressid
                from address a
               where a.street = '-'
                 and a.zipcode = '-'
                 and a.city = '-'
                 and a.housenumber = 0;
            exception
              when no_data_found then
                insert into address
                  (address_id,
                   street,
                   zipcode,
                   city,
                   systemuser_id,
                   timestamp,
                   housenumber)
                values
                  (seq_address.nextval,
                   '-',
                   '-',
                   '-',
                   systemuserid,
                   sysdate,
                   0);

            end;
            insert into supplier
              (supplier_id,
               suppliernumber,
               name,
               fax,
               phone,
               email,
               website,
               address_id,
               creditornumber,
               orderformremark,
               systemuser_id,
               timestamp,
               currency_id,
               averageshipmentcosts,
               sendpurchaseorder,
               printpriceonpo,
               discountpercdays,
               discountwithindays,
               discountpercoverall,
               paymentterms,
               deliveryterms,
               country_id,
               filelayout,
               formlayout_id)
            values
              (seq_supplier.nextval,
               pSuppliernumber,
               Suppliername,
               null, --fax,
               null, --phone,
               null, --email,
               null, --website,
               addressid,
               null, --creditornumber,
               null, ---orderformremark,
               systemuserid,
               sysdate,
               currencyid,
               0, --averageshipmentcosts,
               1, --sendpurchaseorder,
               'Y', --printpriceonpo,
               0, --discountpercdays,
               0, --discountwithindays,
               0, --discountpercoverall,
               '', --paymentterms,
               '', --deliveryterms,
               countryid,
               0, --filelayout,
               null); --formlayout_id);
          exception
            when others then
              Status := 24;
              if debuglevel > 0 then
                utl_file.put_line(SQLfile,
                                  '!> Supplier ' || pSuppliernumber ||
                                  ' insert failed  ' || sqlcode || ' ' ||
                                  sqlerrm);
              end if;
          end;
      end;
      begin
        select r.registrationunit_id
          into registrationunitid
          from registrationunit r
         where r.code = Registrationunitcode;
        select rd.description
          into registrationunitdesc
          from registrationunit_desc rd
         where rd.registrationunit_id = registrationunitid
           and rd.language_id = languageid;
      exception
        when no_data_found then
          Status := 4;
          if debuglevel > 0 then
            utl_file.put_line(SQLfile,
                              '!> Registration unit ' ||
                              Registrationunitcode || ' not found ' ||
                              sqlcode || ' ' || sqlerrm);
          end if;
      end;
    end if;
    if Status = 0 and pFinishingcode is not null then
      begin
        select f.finishingcode_id
          into finishingcodeid
          from finishingcode f
         where f.finishingcode = pFinishingcode;
      exception
        when no_data_found then
          Status := 5;
          if debuglevel > 0 then
            utl_file.put_line(SQLfile,
                              '!> Finishing code ' || pFinishingcode ||
                              ' not found ' || sqlcode || ' ' || sqlerrm);
          end if;
      end;
    end if;
    if Status = 0 then
      begin
        select r.residualvaluescheme_id
          into residualvalueschemeid
          from residualvaluescheme r
         where r.code = Deftresvalschemecode;
      exception
        when no_data_found then
          Status := 6;
          if debuglevel > 0 then
            utl_file.put_line(SQLfile,
                              '!> Residual value scheme ' ||
                              Deftresvalschemecode || ' not found ' ||
                              sqlcode || ' ' || sqlerrm);
          end if;
      end;
    end if;
    if Status = 0 and Taxgroupcode is not null then
      begin
        select t.taxgroup_id
          into taxgroupid
          from taxgroup t
         where t.code = Taxgroupcode
           and t.country_id = countryid;
      exception
        when no_data_found then
          Status := 1;
          if debuglevel > 0 then
            utl_file.put_line(SQLfile,
                              '!> Tax group code ' || Taxgroupcode ||
                              ' not found ' || sqlcode || ' ' || sqlerrm);
          end if;
      end;
    end if;
    if insertupdate = 0 and Status = 0 then
      begin
        insert into product
          (product_id,
           packingsequence,
           code,
           active,
           garmentset,
           pack,
           model,
           occupancyrelated,
           specialsize,
           productgroup_id,
           weighingcategory_id,
           sizetype_id,
           color_id,
           fabric_id,
           washingprocess_id,
           supplier_id,
           parentproduct_id,
           legacyproductcode,
           volumeunits,
           theoreticalweight,
           registrationunit_id,
           recordpassivestock,
           typeofmerchandise,
           minimumturnaround,
           autoreplacement,
           shortdescription,
           systemuser_id,
           timestamp,
           rentturnovergroup_id,
           washturnovergroup_id,
           replacementturnovergroup_id,
           salesturnovergroup_id,
           invoicecolumn,
           image_id,
           maxwashes,
           uniquepoolitem,
           exchangemethod,
           soilcountmethod,
           eannumber,
           finishingcode_id,
           fulfillmentgroup,
           putuptype,
           storeactivestocklocation,
           misproduct_id,
           intrastat_id,
           packingamount,
           benchmarkrelevant,
           lossturnovergroup_id,
           maxcartqty,
           advanceturnovergroup_id,
           correctionsturnovergroup_id,
           optimafactor,
           defaultresidualvaluescheme_id,
           abccode)
        values
          (seq_product.nextval,
           ppackingsequence,
           upper(pcode),
           'Y', --active
           'N', --garmentset,
           'N', --(ppack),
           'N', --model,
           upper(pOccupancyrelated),
           'N', --specialsize,
           productgroupid,
           null, --weighingcategory_id,
           sizetypeid,
           colorid,
           fabricid,
           washingprocessid,
           supplierid,
           seq_product.currval, --parentproduct_id,
           plegacycode,
           pvolumeunits,
           ptheoreticalweight,
           registrationunitid,
           upper(precordpassivestock),
           ptypeofmerchandise,
           0, --minimumturnaround,
           0.0, --autoreplacement,
           pshortdescription,
           systemuserid,
           sysdate,
           null, --rentturnovergroup_id, --
           null, --washturnovergroup_id,
           null, --replacementturnovergroup_id,
           null, --salesturnovergroup_id,
           0, --invoicecolumn,
           null, --image_id,
           pmaxwashes,
           upper(pUniqueitempool),
           pexchangemethod,
           psoilcountmethod,
           null, --eannumber,
           finishingcodeid,
           null, --fulfillmentgroup,
           pputuptype,
           'N', --storeactivestocklocation,
           null, --misproduct_id,
           null, --intrastat_id,
           Bundlequantity, ---packingamount, --???????
           'N', --benchmarkrelevant,
           null, --lossturnovergroup_id,
           0, --maxcartqty,
           null, --advanceturnovergroup_id,
           null, --correctionsturnovergroup_id,
           poptimafactor,
           residualvalueschemeid,
           null); --abccode);
      exception
        when others then
          Status := 25;
          if debuglevel > 0 then
            utl_file.put_line(SQLfile,
                              '!> Insert for Product ' || pcode ||
                              ' failed ' || sqlcode || ' ' || sqlerrm);
          end if;
      end;
      if Status = 0 then
        begin
          insert into product_desc
            (product_id,
             language_id,
             description,
             systemuser_id,
             timestamp,
             longdescription)
          values
            (seq_product.currval,
             languageid,
             pDescription,
             systemuserid,
             sysdate,
             pLongdescription);
        exception
          when others then
            Status := 26;
            if debuglevel > 0 then
              utl_file.put_line(SQLfile,
                                '!> Insert for Product description ' ||
                                pDescription || ' failed ' || sqlcode || ' ' ||
                                sqlerrm);
            end if;
        end;
      end if;
      if Status = 0 then
        begin
          insert into product_link
            (product_link_id,
             product_id,
             code,
             systemuser_id,
             legacyproductcode,
             timestamp,
             Productgroupcode)
          values
            (seq_product.currval,
             seq_product.currval,
             upper(pcode),
             systemuserid,
             plegacycode,
             sysdate,
             Productgroupcode);
        exception
          when others then
            Status := 26;
            if debuglevel > 0 then
              utl_file.put_line(SQLfile,
                                '!> Insert for Product_link ' || pcode ||
                                ' failed ' || sqlcode || ' ' || sqlerrm);
            end if;
        end;
      end if;
      if Status = 0 then
        begin
          insert into product_link_desc
            (product_link_id,
             language_id,
             description,
             longdescription,
             systemuser_id,
             timestamp,
             registrationunitdescription)
          values
            (seq_product.currval,
             languageid,
             pDescription,
             pLongdescription,
             systemuserid,
             sysdate,
             Registrationunitcode);
        exception
          when others then
            Status := 26;
            if debuglevel > 0 then
              utl_file.put_line(SQLfile,
                                '!> Insert for Product_link description ' ||
                                pDescription || ' failed ' || sqlcode || ' ' ||
                                sqlerrm);
            end if;
        end;
      end if;
      if Status = 0 and taxgroupid is not null then
        begin
          insert into producttax
            (product_id, country_id, taxgroup_id, timestamp, systemuser_id)
          values
            (seq_product.currval,
             countryid,
             taxgroupid,
             sysdate,
             systemuserid);
        exception
          when others then
            Status := 27;
            if debuglevel > 0 then
              utl_file.put_line(SQLfile,
                                '!> Insert for Product ' || pcode ||
                                ' Tax ' || Taxgroupcode || ' failed ' ||
                                sqlcode || ' ' || sqlerrm);
            end if;
        end;
      end if;
    end if;
    if insertupdate = 1 and Status = 0 and productid is not null then
      begin
        select u.packingsequence,
               u.occupancyrelated,
               u.legacyproductcode,
               u.volumeunits,
               u.theoreticalweight,
               u.recordpassivestock,
               u.typeofmerchandise,
               u.shortdescription,
               u.maxwashes,
               u.uniquepoolitem,
               u.exchangemethod,
               u.soilcountmethod,
               u.putuptype,
               u.packingamount,
               u.optimafactor
          into upackingsequence,
               uoccupancyrelated,
               ulegacyproductcode,
               uvolumeunits,
               utheoreticalweight,
               urecordpassivestock,
               utypeofmerchandise,
               ushortdescription,
               umaxwashes,
               uuniquepoolitem,
               uexchangemethod,
               usoilcountmethod,
               uputuptype,
               upackingamount,
               uoptimafactor
          from product u
         where u.product_id = productid;
        upackingsequence    := coalesce(pPackingsequence, upackingsequence);
        uoccupancyrelated   := coalesce(upper(pOccupancyrelated),
                                        uoccupancyrelated);
        ulegacyproductcode  := coalesce(pLegacycode, ulegacyproductcode);
        uvolumeunits        := coalesce(pVolumeunits, uvolumeunits);
        utheoreticalweight  := coalesce(pTheoreticalweight,
                                        utheoreticalweight);
        urecordpassivestock := coalesce(upper(pRecordpassivestock),
                                        urecordpassivestock);
        utypeofmerchandise  := coalesce(pTypeofmerchandise,
                                        utypeofmerchandise);
        ushortdescription   := coalesce(pShortdescription,
                                        ushortdescription);
        umaxwashes          := coalesce(pMaxwashes, umaxwashes);
        uuniquepoolitem     := coalesce(upper(pUniqueitempool),
                                        uuniquepoolitem);
        uexchangemethod     := coalesce(pExchangemethod, uexchangemethod);
        usoilcountmethod    := coalesce(pSoilcountmethod, usoilcountmethod);
        uputuptype          := coalesce(pPutuptype, uputuptype);
        upackingamount      := coalesce(Bundlequantity, upackingamount);
        uoptimafactor       := coalesce(pOptimafactor, uoptimafactor);
      exception
        when others then
          Status := 10;
          if debuglevel > 0 then
            utl_file.put_line(SQLfile,
                              '!> Parameters values for Product ' || pcode ||
                              ' out of range ' || sqlcode || ' ' || sqlerrm);
          end if;
      end;
      begin
        update product p
           set p.packingsequence = upackingsequence,
               --     code,
               --     active,
               --     garmentset,
               --pack
               --model,
               p.occupancyrelated = uoccupancyrelated,
               --   specialsize,
               p.productgroup_id = productgroupid,
               -- weighingcategory_id,
               p.sizetype_id       = sizetypeid,
               p.color_id          = colorid,
               p.fabric_id         = fabricid,
               p.washingprocess_id = washingprocessid,
               p.supplier_id       = supplierid,
               --parentproduct_id,
               p.legacyproductcode   = ulegacyproductcode,
               p.volumeunits         = uvolumeunits,
               p.theoreticalweight   = utheoreticalweight,
               p.registrationunit_id = registrationunitid,
               p.recordpassivestock  = urecordpassivestock,
               --permitinvoiceadjust,
               p.typeofmerchandise = utypeofmerchandise,
               -- minimumturnaround,
               -- autoreplacement,
               p.shortdescription = ushortdescription,
               p.systemuser_id    = systemuserid,
               p.timestamp        = sysdate,
               --rentturnovergroup_id,
               --washturnovergroup_id,
               --replacementturnovergroup_id,
               --salesturnovergroup_id,
               --invoicecolumn,
               --image_id,
               p.maxwashes       = umaxwashes,
               p.uniquepoolitem  = uuniquepoolitem,
               p.exchangemethod  = uexchangemethod,
               p.soilcountmethod = usoilcountmethod,
               --eannumber,
               p.finishingcode_id = finishingcodeid,
               --fulfillmentgroup,
               p.putuptype = uputuptype,
               --storeactivestocklocation,
               --misproduct_id,
               --intrastat_id,
               p.packingamount = upackingamount,
               --benchmarkrelevant,
               --lossturnovergroup_id,
               --maxcartqty,
               --advanceturnovergroup_id,
               --correctionsturnovergroup_id,
               p.optimafactor                  = uoptimafactor,
               p.defaultresidualvaluescheme_id = residualvalueschemeid
         where p.product_id = productid;
      exception
        when others then
          Status := 30;
          if debuglevel > 0 then
            utl_file.put_line(SQLfile,
                              '!> Update for Product ' || pcode ||
                              ' failed ' || sqlcode || ' ' || sqlerrm);
          end if;
      end;
      if Status = 0 then
        begin
          select pl.product_link_id
            into productlinkid
            from product_link pl
           where pl.product_id = productid;
          update product_link pl
             set pl.legacyproductcode = pLegacycode,
                 pl.productgroupcode  = Productgroupcode
           where pl.product_link_id = productlinkid;
        exception
          when no_data_found then
            begin
              insert into product_link
                (product_link_id,
                 product_id,
                 code,
                 systemuser_id,
                 legacyproductcode,
                 timestamp,
                 Productgroupcode)
              values
                (productid,
                 productid,
                 upper(pcode),
                 systemuserid,
                 plegacycode,
                 sysdate,
                 Productgroupcode);
            exception
              when others then
                Status := 26;
                if debuglevel > 0 then
                  utl_file.put_line(SQLfile,
                                    '!> Insert for Product_link ' || pcode ||
                                    ' failed ' || sqlcode || ' ' || sqlerrm);
                end if;
            end;
        end;
      end if;
      if Status = 0 then
        begin
          select x.description, x.longdescription
            into pddescription, pdlongdescription
            from product_desc x
           where x.product_id = productid
             and x.language_id = languageid;
          pddescription     := coalesce(pDescription, pddescription);
          pdLongdescription := coalesce(pLongDescription, pdLongdescription);
          update product_desc pd
             set pd.description     = pddescription,
                 pd.longdescription = pdLongdescription,
                 pd.systemuser_id   = systemuserid,
                 pd.timestamp       = sysdate
           where pd.product_id = productid
             and pd.language_id = languageid;
          if status = 0 then
            begin
              select pld.description
                into plddesc
                from product_link_desc pld
               where pld.product_link_id = productid
                 and pld.language_id = languageid;
              update product_link_desc pld
                 set pld.description                 = pddescription,
                     pld.longdescription             = pdlongdescription,
                     pld.registrationunitdescription = Registrationunitdesc
               where pld.product_link_id = productid
                 and pld.language_id = languageid;
            exception
              when no_data_found then
                insert into product_link_desc
                  (product_link_id,
                   language_id,
                   description,
                   longdescription,
                   systemuser_id,
                   timestamp,
                   registrationunitdescription)
                values
                  (productid,
                   languageid,
                   pdDescription,
                   pdlongdescription,
                   systemuserid,
                   sysdate,
                   Registrationunitdesc);

              when others then
                Status := 26;
                if debuglevel > 0 then
                  utl_file.put_line(SQLfile,
                                    '!> Update/Insert for Product_link description ' ||
                                    pDescription || ' failed ' || sqlcode || ' ' ||
                                    sqlerrm);
                end if;
            end;
          end if;
        exception
          when no_data_found then
            begin
              insert into product_desc
                (product_id,
                 language_id,
                 description,
                 systemuser_id,
                 timestamp,
                 longdescription)
              values
                (productid,
                 languageid,
                 pDescription,
                 systemuserid,
                 sysdate,
                 pLongdescription);
              insert into product_link_desc
                (product_link_id,
                 language_id,
                 description,
                 longdescription,
                 systemuser_id,
                 timestamp,
                 registrationunitdescription)
              values
                (productlinkid,
                 languageid,
                 pDescription,
                 plongdescription,
                 systemuserid,
                 sysdate,
                 Registrationunitdesc);
            exception
              when others then
                Status := 26;
                if debuglevel > 0 then
                  utl_file.put_line(SQLfile,
                                    '!> Insert for Product description/Product link description ' ||
                                    pDescription || ' failed ' || sqlcode || ' ' ||
                                    sqlerrm);
                end if;
            end;
          when others then
            Status := 31;
            if debuglevel > 0 then
              utl_file.put_line(SQLfile,
                                '!> Update for Product description ' ||
                                pDescription || ' failed ' || sqlcode || ' ' ||
                                sqlerrm);
            end if;
        end;
      end if; --product desc
      ----------------

      if Status = 0 and taxgroupid is not null then
        begin
          select pt.product_id
            into productid
            from producttax pt
           where pt.product_id = productid
             and pt.taxgroup_id = taxgroupid
             and pt.country_id = countryid;
        exception
          when no_data_found then
            begin
              insert into producttax
                (product_id,
                 country_id,
                 taxgroup_id,
                 timestamp,
                 systemuser_id)
              values
                (productid, countryid, taxgroupid, sysdate, systemuserid);
            exception
              when others then
                Status := 27;
                if debuglevel > 0 then
                  utl_file.put_line(SQLfile,
                                    '!> Insert for Product ' || pcode ||
                                    ' Tax ' || Taxgroupcode || ' failed ' ||
                                    sqlcode || ' ' || sqlerrm);
                end if;
            end;
        end;
      end if;
    end if; --end if product
    if debuglevel > 0 then
      utl_file.put_line(SQLfile, 'Product code ' || pcode);
      utl_file.put_line(SQLfile, 'Product description ' || pDescription);
      utl_file.put_line(SQLfile, 'Longdescription ' || pLongdescription);
      utl_file.put_line(SQLfile, 'Shortdescription ' || pShortdescription);
      utl_file.put_line(SQLfile, 'Packingsequence ' || pPackingsequence);
      --utl_file.put_line(SQLfile, 'Pack ' || pPack);
      utl_file.put_line(SQLfile, 'Occupancyrelated ' || pOccupancyrelated);
      utl_file.put_line(SQLfile, 'Bundlequantity ' || Bundlequantity);
      utl_file.put_line(SQLfile,
                        'Theoreticalweight ' || pTheoreticalweight);
      utl_file.put_line(SQLfile, 'Color code ' || Colorcode);
      utl_file.put_line(SQLfile, 'Color description ' || Colordescription);
      utl_file.put_line(SQLfile, 'Fabric code ' || Fabriccode);
      utl_file.put_line(SQLfile,
                        'Fabric description ' || Fabricdescription);
      utl_file.put_line(SQLfile, 'Productgroup code ' || Productgroupcode);
      utl_file.put_line(SQLfile, 'Washprocess code ' || Washprocesscode);
      utl_file.put_line(SQLfile,
                        'Washprocess description ' || Washprocessdesc);
      utl_file.put_line(SQLfile, 'Suppliernumber ' || pSuppliernumber);
      utl_file.put_line(SQLfile, 'Suppliername ' || Suppliername);
      utl_file.put_line(SQLfile,
                        'Registrationunitcode ' || Registrationunitcode);
      utl_file.put_line(SQLfile,
                        'Recordpassivestock ' || pRecordpassivestock);
      utl_file.put_line(SQLfile,
                        'Typeofmerchandise ' || pTypeofmerchandise);
      utl_file.put_line(SQLfile, 'Taxgroupcode ' || Taxgroupcode);
      utl_file.put_line(SQLfile, 'Putuptype ' || pPutuptype);
      utl_file.put_line(SQLfile, 'Maxwashes ' || pMaxwashes);
      utl_file.put_line(SQLfile, 'Exchangemethod ' || pExchangemethod);
      utl_file.put_line(SQLfile, 'Soilcountmethod ' || pSoilcountmethod);
      utl_file.put_line(SQLfile, 'Uniqueitempool ' || pUniqueitempool);
      utl_file.put_line(SQLfile, 'Finishing code ' || pFinishingcode);
      utl_file.put_line(SQLfile, 'Sizetype code ' || Sizetypecode);
      utl_file.put_line(SQLfile,
                        'Sizetype description ' || Sizetypedescription);
      utl_file.put_line(SQLfile, 'Optimafactor ' || pOptimafactor);
      utl_file.put_line(SQLfile,
                        'Residual value scheme code ' ||
                        Deftresvalschemecode);
      utl_file.put_line(SQLfile, 'Volumeunits ' || pVolumeunits);
      utl_file.put_line(SQLfile, 'Status ' || Status);
    end if;
    commit;
  exception
    when others then
      rollback;
      Status := 99;
      utl_file.put_line(SqlFile, pCode || ' ' || sqlcode || ' ' || sqlerrm);
  end;
  UTL_FILE.FCLOSE(SqlFile);
end AddorUpdateProduct;
/
create or replace procedure AddorUpdateProductSize(ProductCode        in Product.Code%type,
                                                   SizeCode           in Sizedefinition.Code%type,
                                                   SizeDescription    in Sizedefinition_Desc.Description%type,
                                                   Legacycode         in sizedefinition.legacysizecode%type,
                                                   pLength            in sizedefinition.length%type,
                                                   pWidth             in sizedefinition.width%type,
                                                   pTheoreticalweight in number,
                                                   Bundlequantity     in number,
                                                   Status             out number) is
  productid       product.product_id%type;
  sizeid          sizedefinition.sizedefinition_id%type;
  sizetypeid      sizetype.sizetype_id%type;
  maxsizetype_seq sizespersizetype.sequencenumber%type;
  productsize_seq productsize.sequencenumber%type;
  insertupdate    number; --0 insert, 1 update
  systemuserid    systemuser.systemuser_id%type;
  languageid      languages.language_id%type;
  SQLfile         utl_file.file_type;
  UTLDIR          varchar2(50);
  FPsFilename     varchar2(50);
  debuglevel      integer := 1;
  sessionsid      integer;
  sessionserialnr integer;
  sizelinkid      sizedefinition_link.sizedefinition_link_id%type;
  seqps           integer;
  sddesc          sizedefinition_desc.description%type;
begin
  begin
    select s.dblogdir into UTLDIR from databasesettings s;
  EXCEPTION
    WHEN no_data_found then
      UTLDIR := 'C:\'; --  please see ABS-92804 variable needs the name of an existing oracle directory
  end;
  select a.SID, a.SERIAL#
    into sessionsid, sessionserialnr
    from SYS.V_$SESSION a
   where a.AUDSID = (SELECT sys_context('USERENV', 'SESSIONID') FROM dual);
  FPsFilename  := 'AddorUpdateProductSize_' ||
                  to_char(sysdate, 'YYYYMMDDHHMMSS') || '_' || sessionsid || '_' ||
                  sessionserialnr || '.txt';
  SqlFile      := UTL_FILE.FOPEN(UTLDIR, FPsFilename, 'a');
  Status       := 0;
  insertupdate := 1;
  begin
    begin
      select s.systemuser_id
        into systemuserid
        from systemuser s
       where s.username = 'AXAPTA';
    exception
      when no_data_found then
        select min(s.systemuser_id) into systemuserid from systemuser s;
    end;
    begin
      select p.product_id, p.sizetype_id
        into productid, sizetypeid
        from product p
       where p.code = ProductCode;
    exception
      when no_data_found then
        Status := 1;
        if debuglevel > 0 then
          utl_file.put_line(SQLfile,
                            '!> Product code ' || Productcode ||
                            ' not found' || sqlcode || ' ' || sqlerrm);
        end if;
    end;
    if status = 0 then
      begin
        select max(s.sequencenumber)
          into maxsizetype_seq
          from sizespersizetype s
         where s.sizetype_id = sizetypeid;
        if maxsizetype_seq is null then
          maxsizetype_seq := 1;
        end if;
        begin
          select ps.sequencenumber
            into productsize_seq
            from productsize ps
           where ps.product_id = productid
             and ps.sequencenumber = maxsizetype_seq;
          select max(ps.sequencenumber) + 1
            into productsize_seq
            from productsize ps
           where ps.product_id = productid;
        exception
          when no_data_found then
            productsize_seq := maxsizetype_seq;
        end;
      exception
        when others then
          Status := 2;
          if debuglevel > 0 then
            utl_file.put_line(SQLfile,
                              '!> Max sequence per sizetype or per productsize cannot be determined' ||
                              sqlcode || ' ' || sqlerrm);
          end if;
      end;
    end if;
    if Status = 0 then
      begin
        select l.language_id
          into languageid
          from languages l
         where l.code = 'DA_DK';
      exception
        when no_data_found then
          Status := 3;
          if debuglevel > 0 then
            utl_file.put_line(SQLfile,
                              '!> Language DA_DK not found ' || sqlcode || ' ' ||
                              sqlerrm);
          end if;
      end;
    end if;
    if Status = 0 then
      begin
        select s.sizedefinition_id
          into sizeid
          from sizedefinition s
         where s.code = SizeCode;
      exception
        when no_data_found then
          begin
            insert into sizedefinition
              (sizedefinition_id,
               code,
               systemuser_id,
               unfinishedlength,
               legacysizecode,
               width,
               timestamp,
               length,
               usedforemblem,
               unfinishedsizedefinition_id)
            values
              (seq_sizedefinition.nextval,
               upper(SizeCode),
               systemuserid,
               'N',
               Legacycode,
               pWidth,
               sysdate,
               pLength,
               'N',
               null);
            insert into sizedefinition_link
              (sizedefinition_link_id,
               sizedefinition_id,
               code,
               systemuser_id,
               legacysizecode,
               timestamp)
            values
              (seq_sizedefinition.currval,
               seq_sizedefinition.currval,
               upper(SizeCode),
               systemuserid,
               Legacycode,
               sysdate);
          exception
            when others then
              Status := 4;
              if debuglevel > 0 then
                utl_file.put_line(SQLfile,
                                  '!> Insert into sizedefinition/sizedefinition_link failed ' ||
                                  sqlcode || ' ' || sqlerrm);
              end if;
          end;
          if Status = 0 then
            begin
              insert into sizedefinition_desc
                (sizedefinition_id,
                 language_id,
                 systemuser_id,
                 description,
                 timestamp)
              values
                (seq_sizedefinition.currval,
                 languageid,
                 systemuserid,
                 SizeDescription,
                 sysdate);
              insert into sizedefinition_link_desc
                (sizedefinition_link_id,
                 language_id,
                 description,
                 systemuser_id,
                 timestamp)
              values
                (seq_sizedefinition.currval,
                 languageid,
                 SizeDescription,
                 systemuserid,
                 sysdate);
            exception
              when others then
                Status := 5;
                if debuglevel > 0 then
                  utl_file.put_line(SQLfile,
                                    '!> Insert into sizedefinition_desc/sizedefinition_link_desc  failed ' ||
                                    sqlcode || ' ' || sqlerrm);
                end if;
            end;
          end if;
          if Status = 0 then
            begin
              insert into sizespersizetype
                (sizetype_id,
                 sizedefinition_id,
                 sequencenumber,
                 systemuser_id,
                 timestamp)
              values
                (sizetypeid,
                 seq_sizedefinition.currval,
                 maxsizetype_seq + 1,
                 systemuserid,
                 sysdate);
            exception
              when others then
                Status := 6;
                if debuglevel > 0 then
                  utl_file.put_line(SQLfile,
                                    '!> Insert into sizezpersizetype failed ' ||
                                    sqlcode || ' ' || sqlerrm);
                end if;
            end;
          end if;
          if Status = 0 then
            begin
              insert into productsize
                (product_id,
                 sizedefinition_id,
                 sequencenumber,
                 systemuser_id,
                 timestamp,
                 specialsize,
                 theoreticalweight,
                 packingamount)
              values
                (productid,
                 seq_sizedefinition.currval,
                 productsize_seq,
                 systemuserid,
                 sysdate,
                 'N',
                 pTheoreticalweight,
                 Bundlequantity);
              insertupdate := 0;
            exception
              when others then
                Status := 7;
                if debuglevel > 0 then
                  utl_file.put_line(SQLfile,
                                    '!> Insert into productsize failed ' ||
                                    sqlcode || ' ' || sqlerrm);
                end if;
            end;
          end if;
      end;
    end if;
    --update
    if sizeid is not null and status = 0 and insertupdate = 1 then
      begin
        update sizedefinition s
           set s.legacysizecode = Legacycode,
               s.length         = pLength,
               s.width          = pWidth,
               s.timestamp      = sysdate,
               s.systemuser_id  = systemuserid
         where s.sizedefinition_id = sizeid;
        begin
          select sl.sizedefinition_link_id
            into sizelinkid
            from sizedefinition_link sl
           where sl.sizedefinition_id = sizeid;

          update sizedefinition_link sl
             set sl.code           = SizeCode,
                 sl.systemuser_id  = systemuserid,
                 sl.timestamp      = sysdate,
                 sl.legacysizecode = Legacycode
           where sl.sizedefinition_link_id = sizelinkid;
        exception
          when no_data_found then
            insert into sizedefinition_link
              (sizedefinition_link_id,
               sizedefinition_id,
               code,
               systemuser_id,
               legacysizecode,
               timestamp)
            values
              (sizeid,
               sizeid,
               upper(SizeCode),
               systemuserid,
               Legacycode,
               sysdate);
        end;
        begin
          --sizedefinition_desc
          select sd.description
            into sddesc
            from sizedefinition_desc sd
           where sd.sizedefinition_id = sizeid
             and sd.language_id = languageid;
          update sizedefinition_desc sd
             set sd.description   = SizeDescription,
                 sd.systemuser_id = systemuserid,
                 sd.timestamp     = sysdate
           where sd.sizedefinition_id = sizeid
             and sd.language_id = languageid;

        exception
          when no_data_found then
            insert into sizedefinition_desc
              (sizedefinition_id,
               language_id,
               systemuser_id,
               description,
               timestamp)
            values
              (sizeid, languageid, systemuserid, SizeDescription, sysdate);
          when others then
            Status := 5;
            if debuglevel > 0 then
              utl_file.put_line(SQLfile,
                                '!> Insert Size/Sizelink description failed ' ||
                                sqlcode || ' ' || sqlerrm);
            end if;
        end;
        begin
          select sd.description
            into sddesc
            from sizedefinition_link_desc sd
           where sd.sizedefinition_link_id = sizeid
             and sd.language_id = languageid;
          update sizedefinition_link_desc sld
             set sld.description   = SizeDescription,
                 sld.systemuser_id = systemuserid,
                 sld.timestamp     = sysdate;
        exception
          when no_data_found then
            insert into sizedefinition_link_desc
              (sizedefinition_link_id,
               language_id,
               description,
               systemuser_id,
               timestamp)
            values
              (sizeid, languageid, SizeDescription, systemuserid, sysdate);
          when others then
            Status := 5;
            if debuglevel > 0 then
              utl_file.put_line(SQLfile,
                                '!> Insert Size/Sizelink description failed ' ||
                                sqlcode || ' ' || sqlerrm);
            end if;
        end; --sizedefinition_desc
        begin
          insert into sizespersizetype
            (sizetype_id,
             sizedefinition_id,
             sequencenumber,
             systemuser_id,
             timestamp)
          values
            (sizetypeid,
             sizeid,
             maxsizetype_seq + 1,
             systemuserid,
             sysdate);
        exception
          when dup_val_on_index then
            null;
          when others then
            Status := 6;
            if debuglevel > 0 then
              utl_file.put_line(SQLfile,
                                '!> Update/Insert SizesperSizetype failed ' ||
                                sqlcode || ' ' || sqlerrm);
            end if;
        end;
        begin
          select ps.sequencenumber
            into seqps
            from productsize ps
           where ps.product_id = productid
             and ps.sizedefinition_id = sizeid;
          update productsize ps
             set ps.theoreticalweight = pTheoreticalweight,
                 ps.packingamount     = Bundlequantity,
                 ps.systemuser_id     = systemuserid,
                 ps.timestamp         = sysdate
           where ps.product_id = productid
             and ps.sizedefinition_id = sizeid;
        exception
          when no_data_found then
            --begin
            insert into productsize
              (product_id,
               sizedefinition_id,
               sequencenumber,
               systemuser_id,
               timestamp,
               specialsize,
               theoreticalweight,
               packingamount)
            values
              (productid,
               sizeid,
               productsize_seq,
               systemuserid,
               sysdate,
               'N',
               pTheoreticalweight,
               Bundlequantity);
            --exception
          when others then
            Status := 8;
            if debuglevel > 0 then
              utl_file.put_line(SQLfile,
                                '!> Update/insert productsize failed ' ||
                                sqlcode || ' ' || sqlerrm);
            end if;
            -- end;
        end;
      end;
    end if;
    if debuglevel > 0 then
      utl_file.put_line(SQLfile, 'Product code ' || productcode);
      utl_file.put_line(SQLfile, 'Size code ' || sizecode);
      utl_file.put_line(SQLfile, 'Size description ' || SizeDescription);
      utl_file.put_line(SQLfile, 'Legacy code ' || Legacycode);
      utl_file.put_line(SQLfile, 'Lenght ' || pLength);
      utl_file.put_line(SQLfile, 'Width ' || pWidth);
      utl_file.put_line(SQLfile,
                        'Theoreticalweight ' || pTheoreticalweight);
      utl_file.put_line(SQLfile, 'Bundlequantity ' || Bundlequantity);
      utl_file.put_line(SQLfile, 'Status ' || Status);
    end if;
    commit;
  exception
    when others then
      rollback;
      Status := 99;
      utl_file.put_line(SqlFile,
                        '!> Error for product code' || productCode ||
                        ' and size code ' || SizeCode || sqlcode || ' ' ||
                        sqlerrm);
  end;
  UTL_FILE.FCLOSE(SqlFile);
end AddorUpdateProductSize;
/
create or replace procedure add_dv_to_existing_pn(fp_deliveryvariationsid in deliveryvariations.deliveryvariations_id%type,
                                                  fp_businessunitid       in businessunit.businessunit_id%type,
                                                  fp_plantdepartmentid    in plantdepartment.plantdepartment_id%type,
                                                  fp_systemuserid         in systemuser.systemuser_id%type default 0) is
  /* add_dv_to_existing_pn version 1.8 */
  gv_message       abslog.message%type;
  gv_packingnoteid packingnote.packingnote_id%type;
  pnline number;
  pnlineco number;

  procedure write_log(fp_message in varchar2, fp_priority in number default 3) is
  begin
    --write log
    abslogwrite.abslog_write(5, 'add_dv_to_existing_pn', null, fp_priority, fp_message,
                             fp_systemuserid);
  end write_log;
begin
  --initialize
  gv_message := 'deliveryvariations_id ' || to_char(fp_deliveryvariationsid) || ' bu id ' ||
                to_char(fp_businessunitid) || ' plant dep id ' || to_char(fp_plantdepartmentid);
  --check if fp_deliveryvariationsid qualifies for link to packingnote
  for x in (select dv.distributionpoint_id, dv.product_id, dv.sizedefinition_id,
                   dv.finishingmethod_id, dv.amount, dv.adjustmentreason_id, dv.deliverydate,
                   dv.processed, dv.origin, dv.causenote_id, dv.updaterentqty, dv.soilcountsubtype,
                   dv.weborderline_id, dv.reference, dv.reasoncode_id, p.packingsequence
            from   deliveryvariations dv
            join   product p
            on     p.product_id = dv.product_id
            where  dv.deliveryvariations_id = fp_deliveryvariationsid
            and    nvl(dv.packingnote_id, 0) = 0
            and    dv.addtoexistingpn = 'Y'
            and    dv.origin<> 3
            and exists ( select 1 from standarddeliveryline sd, productlistperdistribpoint plpd
                  where dv.distributionpoint_id=plpd.distributionpoint_id
                         and dv.product_id=plpd.product_id and dv.sizedefinition_id=plpd.sizedefinition_id
                         and dv.finishingmethod_id=plpd.finishingmethod_id and sd.productlistperdistribpoint_id=plpd.productlistperdistribpoint_id
                         and sd.dateactive < dv.deliverydate and sd.dateinactive > dv.deliverydate)
                    ) loop
    begin
      --check if there is an open packingnote
      --for the same distributionpoint/plantdepartment with status 10
      select min(pk.packingnote_id)
      into   gv_packingnoteid
      from   packingnote pk
      where  pk.distributionpoint_id = x.distributionpoint_id
      and    pk.processbusinessunit_id = fp_businessunitid
      and    pk.plantdepartment_id = fp_plantdepartmentid
      and    pk.deliverydate = x.deliverydate
      and    pk.status_id = (select st.status_id
                             from   status st
                             where  st.code = '10'
                             and    st.statustype = 'PN');
      gv_message := 'PN deliveryvariations_id ' || to_char(fp_deliveryvariationsid) || ' bu id ' ||
                    to_char(fp_businessunitid) || ' plant dep id ' || to_char(fp_plantdepartmentid) ||
                    ' packingnote_id ' || nvl(to_char(gv_packingnoteid), 'NULL');
      if gv_packingnoteid is not null then
        begin
          --pn found link DV to it
          --PACKINGNOTE_ID, PRODUCT_ID, SIZEDEFINITION_ID, FINISHINGMETHOD_ID
          merge into packingnoteline pkl
          using (select pkx.packingnote_id
                 from   packingnote pkx
                 where  pkx.packingnote_id = gv_packingnoteid) pklm
          on (pklm.packingnote_id = pkl.packingnote_id and pkl.product_id = x.product_id and pkl.sizedefinition_id = x.sizedefinition_id and pkl.finishingmethod_id = x.finishingmethod_id)
          when matched then
            update
            set    pkl.tobedeliveredamount = pkl.tobedeliveredamount + x.amount,
                   pkl.variationamount = pkl.variationamount + x.amount,
                   pkl.systemuser_id = fp_systemuserid, pkl.timestamp = sysdate
          when not matched then
             insert
              (packingnoteline_id, product_id, packingsequence, standardamount, variationamount,
               finishingmethod_id, deliveredamount, price, discount, packingnote_id,
               sizedefinition_id, systemuser_id, location, timestamp, remarkforpackinginstructions,
               tobedeliveredamount, customcode, customdescription, replacementqty,
               autoreplacementqty, updaterentqty, adjustmentreason_id, origin, putuptype,
               freeofchargereason_id, nochargefirstissue, nochargeactiveseason)
            values
              (seq_packingnoteline.nextval, x.product_id, x.packingsequence, 0
               /*standardamount*/, x.amount /*variationamount*/, x.finishingmethod_id, 0
               /*deliveredamount*/, null /*price*/, 0 /*discount*/, gv_packingnoteid,
               x.sizedefinition_id, fp_systemuserid, null /*location*/, sysdate
               /*timestamp*/, null /*remarkforpackinginstructions*/, x.amount
               /*tobedeliveredamount*/, null
               /*customcode*/, null /*customdescription*/, 0 /*replacementqty*/, 0
               /*autoreplacementqty*/, 0 /*updaterentqty*/, x.adjustmentreason_id, 0 /*origin*/, 0
               /*putuptype*/, null /*freeofchargereason_id*/, 0
               /*nochargefirstissue*/, 0 /*nochargeactiveseason*/);

               select distinct a.packingnoteline_id,nvl(pnc.packingnoteline_id,0) into pnline,pnlineco
               from packingnoteline a left outer join packingnotelinecontent pnc on a.packingnoteline_id=pnc.packingnoteline_id
                where a.packingnote_id=gv_packingnoteid
               and a.product_id =x.product_id and a.sizedefinition_id=  x.sizedefinition_id
               and a.finishingmethod_id= x.finishingmethod_id ;
                -- for added packinnoteline add also detail in packingnotelinecontent
               if  pnlineco =0 then
               for y in ( select packco.product_id, packco.sizedefinition_id, packco.finishingmethod_id,
                 sum(packco.amount)amount from  packcontents packco
                 where  packco.pack_id=x.product_id and packco.dateactive<x.deliverydate
                 and packco.dateinactive>x.deliverydate group by packco.product_id, packco.sizedefinition_id, packco.finishingmethod_id)
                 loop
                   insert into packingnotelinecontent (packingnoteline_id, product_id,sizedefinition_id,finishingmethod_id, quantity, systemuser_id, timestamp)
                   values(pnline,y.product_id, y.sizedefinition_id, y.finishingmethod_id, y.amount, fp_systemuserid,sysdate);
                   end loop;
                  end if;
          begin
            --reset deliveryvariations addtoexistingpn = 'N'
            update deliveryvariations dv
            set    dv.addtoexistingpn = 'N', dv.timestamp = sysdate,
                   dv.systemuser_id = fp_systemuserid, dv.packingnote_id = gv_packingnoteid
            where  dv.deliveryvariations_id = fp_deliveryvariationsid;
          exception
            when dup_val_on_index then
              begin
                delete from deliveryvariations dv
                where  dv.deliveryvariations_id = fp_deliveryvariationsid;
                /*
                DISTRIBUTIONPOINT_ID, PRODUCT_ID, SIZEDEFINITION_ID, FINISHINGMETHOD_ID,
                 PACKINGNOTE_ID, PROCESSED, DELIVERYDATE, ORIGIN, CAUSENOTE_ID,
                 UPDATERENTQTY, SOILCOUNTSUBTYPE, WEBORDERLINE_ID, REFERENCE,
                 ADJUSTMENTREASON_ID, REASONCODE_ID
                 */
                update deliveryvariations dvy
                set    dvy.amount = dvy.amount + x.amount, dvy.systemuser_id = fp_systemuserid,
                       dvy.timestamp = sysdate
                where  dvy.distributionpoint_id = x.distributionpoint_id
                and    dvy.product_id = x.product_id
                and    dvy.sizedefinition_id = x.sizedefinition_id
                and    dvy.finishingmethod_id = x.finishingmethod_id
                and    dvy.packingnote_id = gv_packingnoteid
                and    dvy.processed = x.processed
                and    dvy.deliverydate = x.deliverydate
                and    dvy.origin = x.origin
                and    dvy.updaterentqty = x.updaterentqty
                and    nvl(dvy.weborderline_id, -1) = nvl(x.weborderline_id, -1)
                and    dvy.soilcountsubtype = x.soilcountsubtype
                and    nvl(dvy.reference, '-1') = nvl(x.reference, '-1')
                and    nvl(dvy.adjustmentreason_id, -1) = nvl(x.adjustmentreason_id, -1)
                and    nvl(dvy.reasoncode_id, -1) = nvl(x.reasoncode_id, -1);
              end;
          end;
        end;
      end if;
    end;
  end loop; --x
  commit;
  write_log('Processed parameter deliveryvariations id ' || to_char(fp_deliveryvariationsid) ||
            ' to PackingNote id ' || nvl(to_char(gv_packingnoteid), 'NULL'), 1);
exception
  when others then
    begin
      --others error handling
      rollback;
      write_log(sqlerrm || gv_message);
    end;
end add_dv_to_existing_pn;
/
create or replace procedure add_product_stockroom(fp_stockroomlocation_id in stockroomlocation.stockroomlocation_id%type,
                                                  fp_product_id           in product.product_id%type,
                                                  fp_customerowned        in standardlocationperproduct.customerowned%type,
                                                  fp_customer_id          in customer.customer_id%type,
                                                  fp_allowedgrade         in standardlocationperproduct.allowedgrade%type,
                                                  fp_definepersize        in standardlocationperproduct.definepersize%type,
                                                  fp_sizedefinition_id    in sizedefinition.sizedefinition_id%type,
                                                  fp_defaultsupplier      in supplier.supplier_id%type default null) is
  gv_defaultuserid               systemuser.systemuser_id%type := 0;
  gv_message                     abslog.message%type;
  gv_stockroom_id                stockroom.stockroom_id%type;
  gv_defaultsupplier_id          supplier.supplier_id%type;
  gv_sizestar                    sizedefinition.sizedefinition_id%type;
  gv_stockdefperitem_id          stockdefinitionperitem.stockdefinitionperitem_id%type;
  gv_stockreservationpergrade_id stockreservationpergrade.stockreservationpergrade_id%type;

  procedure write_log is
  begin
    -- Logging: write message in ABSLOG with errors only, 3 = Error
    abslogwrite.abslog_write(5, 'add_product_stockroom', null, 3, gv_message || ' ' || sqlerrm,
                             gv_defaultuserid);
  end write_log;

  procedure initialize is
  begin
    gv_message := 'initialize';
    --get stockroom
    select l.stockroom_id
    into   gv_stockroom_id
    from   stockroomlocation l
    where  l.stockroomlocation_id = fp_stockroomlocation_id;
    if fp_defaultsupplier is null then
      --get supplier
      begin
        select p.supplier_id
        into   gv_defaultsupplier_id
        from   product p
        where  p.product_id = fp_product_id;
      exception
        when no_data_found then
          gv_defaultsupplier_id := null;
      end;
    else
      gv_defaultsupplier_id := fp_defaultsupplier;
    end if;
    --size star
    select s.sizedefinition_id into gv_sizestar from sizedefinition s where s.code = '*';
  end initialize;

  procedure create_stockquantity is
    rec_stockquantity stockquantity%rowtype;
  begin
    -- create_stockquantity;
    gv_message := 'create_stockquantity insert';
    --fill all values
    rec_stockquantity.stockreservationpergrade_id := gv_stockreservationpergrade_id;
    rec_stockquantity.stockroomlocation_id        := fp_stockroomlocation_id;
    rec_stockquantity.qtyunique                   := 0;
    rec_stockquantity.qtyuniquewithmodifications  := 0;
    rec_stockquantity.systemuser_id               := gv_defaultuserid;
    rec_stockquantity.timestamp                   := sysdate;
    rec_stockquantity.qtycounted                  := null;
    rec_stockquantity.datecounted                 := null;
    rec_stockquantity.qtynonunique                := 0;
    rec_stockquantity.stockdifference             := 0;
    rec_stockquantity.lastcountuser_id            := null;
    --insert stockquantity
    insert into stockquantity values rec_stockquantity;
  exception
    when dup_val_on_index then
      null;
  end create_stockquantity;

  procedure create_stockreservationpergrde(fp_qualitygrade_id qualitygrade.qualitygrade_id%type) is
    rec_stockreservationpergrade stockreservationpergrade%rowtype;
  begin
    --create_stockreservationpergrade
    gv_message := 'create_stockreservationpergrde select';
    begin
      --select stockreservationpergrade_id
      select sg.stockreservationpergrade_id
      into   gv_stockreservationpergrade_id
      from   stockreservationpergrade sg
      where  sg.stockdefinitionperitem_id = gv_stockdefperitem_id
      and    sg.qualitygrade_id = fp_qualitygrade_id;
    exception
      when no_data_found then
        begin
          --insert stockreservationpergrade
          gv_message := 'create_stockreservationpergrde insert';
          ---get next stockreservationpergrade_id
          select seq_stockreservationpergrade.nextval
          into   gv_stockreservationpergrade_id
          from   dual;
          --fill all values
          rec_stockreservationpergrade.stockreservationpergrade_id    := gv_stockreservationpergrade_id;
          rec_stockreservationpergrade.stockdefinitionperitem_id      := gv_stockdefperitem_id;
          rec_stockreservationpergrade.qualitygrade_id                := fp_qualitygrade_id;
          rec_stockreservationpergrade.qtyuniquereserved              := 0;
          rec_stockreservationpergrade.qtynonuniquereserved           := 0;
          rec_stockreservationpergrade.qtyuniquewiithmodifreserved    := 0;
          rec_stockreservationpergrade.qtynonunique                   := 0;
          rec_stockreservationpergrade.qtyuniqueordered               := 0;
          rec_stockreservationpergrade.qtynonuniqueordered            := 0;
          rec_stockreservationpergrade.systemuser_id                  := gv_defaultuserid;
          rec_stockreservationpergrade.timestamp                      := sysdate;
          rec_stockreservationpergrade.qtyuniqueordereddirectissue    := 0;
          rec_stockreservationpergrade.qtynonuniqueordereddirectissue := 0;
          --insert stockreservationpergrade
          insert into stockreservationpergrade values rec_stockreservationpergrade;
        end;
    end;
    --create stock quantity
    create_stockquantity;
  end create_stockreservationpergrde;

  procedure create_stockdefinitionperitem(gv_size_id in sizedefinition.sizedefinition_id%type) is
    rec_stockdefinitionperitem stockdefinitionperitem%rowtype;
  begin
    --create_stockdefinitionperitem
    gv_message := 'create_stockdefinitionperitem select';
    --select stockdefinitionperitem
    select sd.stockdefinitionperitem_id
    into   gv_stockdefperitem_id
    from   stockdefinitionperitem sd
    where  sd.stockroom_id = gv_stockroom_id
    and    sd.product_id = fp_product_id
    and    sd.sizedefinition_id = gv_size_id
    and    (sd.customer_id = fp_customer_id or (sd.customer_id is null and fp_customer_id is null))
    and    sd.customerowned = fp_customerowned;
  exception
    when no_data_found then
      begin
        --insert stockdefinitionperitem
        gv_message := 'create_stockdefinitionperitem insert';
        --get next id for stockdefinitionperitem_id
        select seq_stockdefinitionperitem.nextval into gv_stockdefperitem_id from dual;
        --fill all values
        rec_stockdefinitionperitem.stockdefinitionperitem_id := gv_stockdefperitem_id;
        rec_stockdefinitionperitem.stockroom_id              := gv_stockroom_id;
        rec_stockdefinitionperitem.product_id                := fp_product_id;
        rec_stockdefinitionperitem.sizedefinition_id         := gv_size_id;
        rec_stockdefinitionperitem.customer_id               := fp_customer_id;
        rec_stockdefinitionperitem.customerowned             := fp_customerowned;
        rec_stockdefinitionperitem.minqtynew                 := 0;
        rec_stockdefinitionperitem.minqtyused                := 0;
        rec_stockdefinitionperitem.maxqtynew                 := 0;
        rec_stockdefinitionperitem.maxqtyused                := 0;
        rec_stockdefinitionperitem.systemuser_id             := gv_defaultuserid;
        rec_stockdefinitionperitem.timestamp                 := sysdate;
        rec_stockdefinitionperitem.defaultsupplier_id        := gv_defaultsupplier_id;
        rec_stockdefinitionperitem.productconsumptiontype    := 3;
        rec_stockdefinitionperitem.productconsumptionranking := 1;
        rec_stockdefinitionperitem.supplychainpergradecategory := 0;
        rec_stockdefinitionperitem.stockroomproduct_id         := null;
        rec_stockdefinitionperitem.supplychaindefinition       := 0;
        --insert stockdefinitionperitem
        insert into stockdefinitionperitem values rec_stockdefinitionperitem;
      end;
  end create_stockdefinitionperitem;

  procedure get_grades is
  begin
    /* get_grades  standardlocationperproduct.allowedgrade
    N = only new allowed
    U = only used allowed
    B = both new and used allowed (default)
    D = only defect items */
    gv_message := 'get_grades';
    case fp_allowedgrade
      when 'N' then
        for n in (select q.qualitygrade_id
                  from   qualitygrade q
                  where  q.newgarment = 'Y'
                  and    q.defectitem = 'N'
                  order  by q.priority) loop
          begin
            create_stockreservationpergrde(n.qualitygrade_id);
          end;
        end loop; --N
      when 'U' then
        for u in (select q.qualitygrade_id
                  from   qualitygrade q
                  where  q.newgarment = 'N'
                  and    q.defectitem = 'N'
                  order  by q.priority) loop
          begin
            create_stockreservationpergrde(u.qualitygrade_id);
          end;
        end loop; --U
      when 'B' then
        for b in (select q.qualitygrade_id
                  from   qualitygrade q
                  where  q.defectitem = 'N'
                  order  by q.priority) loop
          begin
            create_stockreservationpergrde(b.qualitygrade_id);
          end;
        end loop; --B
      when 'D' then
        for d in (select q.qualitygrade_id
                  from   qualitygrade q
                  where  q.defectitem = 'Y'
                  order  by q.priority) loop
          begin
            create_stockreservationpergrde(d.qualitygrade_id);
          end;
        end loop; --D
    end case; --fp_allowedgrade
  end get_grades;

  procedure add_stockrecords(fp_size_id in sizedefinition.sizedefinition_id%type) is
  begin
    --add_stockrecords
    create_stockdefinitionperitem(fp_size_id);
    get_grades;
  end add_stockrecords;

  procedure add_all_sizes is
  begin
    gv_message := 'add_all_sizes';
    --add_all_sizes not size star
    for x in (select ps.sizedefinition_id
              from   productsize ps
              where  ps.product_id = fp_product_id
              and    ps.sizedefinition_id <> gv_sizestar
              order  by ps.sequencenumber) loop
      begin
        add_stockrecords(x.sizedefinition_id);
      end;
    end loop; --x
  end add_all_sizes;

begin
  --initialize
  initialize;
  --on size level N or else
  if fp_definepersize = 'N' then
    begin
      add_all_sizes;
    end;
  else
    --fp_definepersize=Y and no size, do nothing
    if fp_sizedefinition_id is not null and fp_sizedefinition_id <> gv_sizestar then
      begin
        add_stockrecords(fp_sizedefinition_id);
      end;
    end if;
  end if;
exception
  when others then
    begin
      write_log;
    end;
end add_product_stockroom;
/
create or replace procedure adjust_sqmaxitemincirculation_LST(fp_uiId                  in uniqueitem.uniqueitem_id%type,
                                                          fp_operation                 in number,
                                                          fp_oldStatusId               in status.status_id%type default null,
                                                          fp_oldLastScanDate           uniqueitem.lastscandate%type default null,
                                                          fp_oldLastInscanDate         uniqueitem.lastinscandate%type default null,
                                                          fp_oldStatusChangeDate       uniqueitem.statuschangedate%type default null,
                                                          fp_oldReturnFromCustomerDate date
                                                          ) is
/* Procedure adjust_sqmaxitemincirculation_LST version 0.8
  04/01/2024 ABS-146203 Customer SQ max quantities are not decrease immediately (return/rag garments)
  25/01/2024 ABS-158672 Improved logging
  19/02/2024 ABS-161589 Allow to put items in circulation in the same day as customer delivery day
  27/05/2025 ABSN-4523 Customer invoiced double for a garment
  15/07/2025 ABSN-8244 Improvement for adjust_sqmaxitemincirculation_LST
*/

dbCODE                 databasesettings.code%type;
statusInCirculation    status.status_id%type;
statusInStock          status.status_id%type;
statusId               status.status_id%type;
stayNr              stay.staynr%type;
productId              product.product_id%type;
sizedefId              sizedefinition.sizedefinition_id%type;
finishingMethodId      finishingmethod.finishingmethod_id%type;
customerOwned          uniqueitem.customerowned%type;
oldLastScanDate        uniqueitem.lastscandate%type;
oldLastInscanDate      uniqueitem.lastinscandate%type;
statusChangeDate       uniqueitem.statuschangedate%type;
oldStatusChangeDate    uniqueitem.statuschangedate%type;
wearerEmploymentId     uniqueitemnonpool.weareremployment_id%type;
freeExtraGarment       uniqueitemnonpool.freeextragarment%type;
endDateFreeExtra       uniqueitemnonpool.enddatefreeextra%type;
primaryId              uniqueitem.primaryid%type;
customerDelDay         number;
returnFromCustomerDate date;
debugMessage           varchar2(1000);
operationStr           varchar2(100);
putInCirculation       boolean := false;
takeOutOfCirculation   boolean := false;

  --Internal procedures
  procedure write_log(fp_message in varchar2) is
  begin
    /* Logging: write message in ABSLOG with priority 5 = Debug */
    abslogwrite.abslog_write(5, 'ADJUST_SQMAX - ' || operationStr, null, 5, fp_message);
  end write_log;

BEGIN
    dbCODE := getDatabaseCode;
    if (dbCode <> 'LST' and dbCode <> 'LSS') then
      return;
    end if;

    --status in circulation
    BEGIN
    SELECT st.status_id
      INTO statusInCirculation
      FROM status st
     WHERE st.statustype = 'UI'
           AND st.code = '20';
    EXCEPTION
      WHEN no_data_found THEN
        statusInCirculation := -1;
    END;

    --status in stock
    BEGIN
      SELECT st.status_id
        INTO statusInStock
        FROM status st
       WHERE st.statustype = 'UI'
             AND st.code = '10';
    EXCEPTION
      WHEN no_data_found THEN
        statusInStock := -1;
    END;

    BEGIN
      select ui.status_id,
           case fp_operation
             when 1 then nvl((select s.staynr from stay s where s.stay_id = ui.prevstay_id), 0)
             when 2 then nvl((select s.staynr from stay s where s.stay_id = ui.prevstay_id), 0)
             when 3 then nvl((select s.staynr from stay s where s.stay_id = ui.stay_id), 0)
           end stayNr,
           ui.product_id,
           ui.sizedefinition_id,
           ui.finishingmethod_id,
           ui.customerowned,
           ui.primaryid,
           decode(fp_operation, 3, ui.lastscandate, fp_oldLastScanDate),
           decode(fp_operation, 3, ui.lastinscandate, fp_oldLastInscanDate),
           decode(fp_operation, 3, nvl(ui.statuschangedate, getabsmindate), nvl(fp_oldStatusChangeDate, getabsmindate)),
           decode(fp_operation, 3, sysdate, nvl(ui.statuschangedate, getabsmindate)),
           nvl(uinp.weareremployment_id, -1),
           uinp.freeextragarment,
           nvl(uinp.enddatefreeextra, to_date('31/12/2099', 'dd/mm/yyyy')) enddatefreeextra,
           case fp_operation
             when 1 then 'CREATE_UNIQUEITEM'
             when 2 then 'UPDATE_UNIQUEITEM'
             when 3 then 'DELETE_UNIQUEITEM'
           end op
      into statusId,
           stayNr,
           productId,
           sizedefId,
           finishingMethodId,
           customerOwned,
           primaryId,
           oldLastScanDate,
           oldLastInscanDate,
           oldStatusChangeDate,
           statusChangeDate,
           wearerEmploymentId,
           freeExtraGarment,
           endDateFreeExtra,
           operationStr
      from uniqueitem ui left outer join uniqueitemnonpool uinp on uinp.uniqueitem_id = ui.uniqueitem_id
      where ui.uniqueitem_id = fp_uiId;
    EXCEPTION
      WHEN no_data_found THEN
        operationStr := '' || fp_operation;
        write_log('no data found for ui id = ' || fp_uiId);
    END;

    debugMessage := ' item ' || primaryId || '; wearerEmploymentID = ' || wearerEmploymentId
                 || '; productID = ' || productId || '; sizedefID = ' || sizedefId || '; finishingMethodID = ' || finishingMethodId;

     if (statusId = statusInCirculation and (fp_operation = 1 or (fp_operation = 2 and fp_oldStatusId <> statusInCirculation))) then
       putInCirculation := true;
       write_log('putInCirculation ' || debugMessage);
     end if;

     if ((statusId = statusInCirculation and fp_operation = 3) or (fp_operation = 2 and statusId = statusInStock and fp_oldStatusId = statusInCirculation)) then
       takeOutOfCirculation := true;
       write_log('takeOutOfCirculation ' || debugMessage);
     end if;

    -- exit if UI status change is irrelevant
    if not(putInCirculation or takeOutOfCirculation) then
      return;
    end if;

    -- exit if status changed after the last customer delivery day
    BEGIN
      select max(cdd.day_id) into customerDelDay
        from customerdeliveryday cdd, weareremployment we, wearer w
       where cdd.typeofmerchadise = 2
         and we.weareremployment_id = wearerEmploymentId
         and we.wearer_id = w.wearer_id
         and cdd.customer_id = w.customer_id;
    EXCEPTION
      WHEN no_data_found THEN
        customerDelDay := 0;
    END;
    if (customerDelDay < getdaynumber(sysdate)) then
      if (takeOutOfCirculation) then
        write_log('item taken out of circulation after the customer delivery day - skip; ' || debugMessage || '; customer delivery day = ' || customerDelDay);
        return;
        else
        write_log('item put in circulation after the customer delivery day - skip; ' || debugMessage || '; customer delivery day = ' || customerDelDay);
        return;
      end if;
    end if;

    if (customerDelDay = getdaynumber(sysdate)) then
      if (takeOutOfCirculation and (oldstatusChangeDate < trunc(sysdate) or oldstatusChangeDate >= trunc(sysdate) + interval '3' hour)) then
        write_log('item taken out of circulation after the customer delivery day - skip; ' || debugMessage || '; customer delivery day = ' || customerDelDay);
        return;
      end if;
      if (putInCirculation) then
        write_log('!!! item put in circulation ON the customer delivery day. will be processed further!  ' || debugMessage || '; customer delivery day = ' || customerDelDay);
      end if;
    end if;

    -- exit if UI is free item or customer owned
    if not(customerOwned = 'N' and (freeExtraGarment = 'N' or endDateFreeExtra < trunc(sysdate))) then
      write_log('free item - skip; ' || debugMessage);
      return;
    end if;

    -- put in circulation
    if (putInCirculation) then
      write_log('update plus adjustment for ' || debugMessage);
      PACK_SQMaxItemInCirculation.t_createOrStoreOnTrigger_UI(fp_uiId, 1, to_date('1900-01-01','yyyy-mm-dd'),
                                                                 productId, sizedefId, finishingMethodId, wearerEmploymentId);
      return;
    end if;

    write_log(debugMessage || '   statusChangeDate = ' || statusChangeDate || ' oldStatusChangeDate = ' || oldStatusChangeDate );
    -- take item out of circulation in the same day as putting in circulation - decrease plusAdjustment
    if  (trunc(statusChangeDate) = trunc(oldStatusChangeDate)) then
         write_log('decrease plus adjustment for ' || primaryId || ' - item taken out of circulation in the same day as putting in circulation');
         PACK_SQMaxItemInCirculation.t_createOrStoreOnTrigger_UI(fp_uiId, -1, to_date('1900-01-01','yyyy-mm-dd'),
                                                                 productId, sizedefId, finishingMethodId, wearerEmploymentId);
         return;
    end if;

    -- ragged in different day than putting in circulation - increase minusAdjustment
    -- item is not in Laundry -  procesing will continue as customer has another visit day this week
    if  stayNr not in (10, 28, 29, 30, 31, 32, 33)  then
      write_log('The stay of scanned item is NOT in the laundry but customer has another visit day this week in the future; ' || debugMessage || '; Stay number = ' || stayNr);
    end if;


    if (oldLastScanDate is not null) then
       returnFromCustomerDate := oldLastScanDate;
    else
      returnFromCustomerDate := fp_oldReturnFromCustomerDate;
    end if;

    if (trunc(returnFromCustomerDate) = to_date('1900-01-01','yyyy-mm-dd')) then
      write_log('minus adjustment not updated for ' || primaryId || ' - there is no return from customer date determined or item is not received in laundry');
    else
      write_log('update minus adjustment for ' || debugMessage || '; returnFromCustomerDate = ' || to_char(returnFromCustomerDate, 'dd/mm/yyyy'));
    end if;
    PACK_SQMaxItemInCirculation.t_createOrStoreOnTrigger_UI(fp_uiId, -1, returnFromCustomerDate,
                                                         productId, sizedefId, finishingMethodId, wearerEmploymentId);
exception
  when others then
    write_log(sqlerrm || '  ' || debugMessage);
end adjust_sqmaxitemincirculation_LST;
/
create or replace procedure alfatest is
  absUserID         systemuser.systemuser_id%type;
  statusStockID     status.status_id%type;
  stockDefItemID    stockdefinitionperitem.stockdefinitionperitem_id%type;
  stockResGradeID   stockreservationpergrade.stockreservationpergrade_id%type;
  stdLocPerProdID   standardlocationperproduct.standardlocationperproduct_id%type;
  qtyUI             stockquantity.qtyunique%type;
  qtyUIM            stockquantity.qtyuniquewithmodifications%type;
  countLines        int:=0;
  newLine           boolean;
  countStockDef     int:=0;
  countStockRes     int:=0;
  countStockQty     int:=0;
  countStdLoc       int:=0;
begin

  --dbms_output.enable(2000000);
  dbms_output.put_line('-------------------------------------------------------------');
  dbms_output.put_line('update stockquantity');
  dbms_output.put_line('-------------------------------------------------------------');
  begin
    select s.systemuser_id into absUserID from systemuser s where s.username = 'ABSADM';
  exception when others then absUserID:=0;
  end;
end alfatest;
/
create or replace procedure autocompletecleanroomcharges(fp_plantprocessid         in plantprocess.plantprocess_id%type,
                                                          fp_abslogprocessjobpartid in abslogprocessjobpart.abslogprocessjobpart_id%type default null,
                                                          fp_systemuserid           in systemuser.systemuser_id%type default 0) is
  lv_plantid        plant.plant_id%type;
  lv_statusid       status.status_id%type;
  gv_user_exception exception;
  gv_defaultuserid systemuser.systemuser_id%type := 0;
  gv_message       abslog.message%type;

  ----- Internal procedures/functions
  procedure write_log(fp_message in varchar2, fp_priority in number default 1) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'AUTOCOMPLETECLEANROOMCHARGES', null, fp_priority, fp_message, gv_defaultuserid);
    if fp_abslogprocessjobpartid is null then
      begin
        begin
          abslogwrite.abslog_write(5, 'AUTOCOMPLETECLEANROOMCHARGES', null, fp_priority, fp_message, gv_defaultuserid);
        end;
      end;
    else
      abslogwrite.abslogprocessjobline_write(fp_abslogprocessjobpartid, fp_priority, fp_message, gv_defaultuserid);
    end if;
  end write_log;

begin
  begin
  select pp.plant_id
    into lv_plantid
    from plantprocess pp
   where pp.plantprocess_id = fp_plantprocessid;
  exception
    when no_data_found then
        gv_message       := 'Plant process not found.';
        write_log(gv_message, 3);
  end;

 begin
  select s.status_id
    into lv_statusid
    from status s
   where s.code = 10
     and s.statustype = 'CA';
  exception
    when no_data_found then
        gv_message       := 'Status of type CA not found.';
        write_log(gv_message, 3);
  end;

  for x in (select sr.sterilizationrun_id, sr.chargenumber,
                   (select st.code from sterilizer st where st.sterilizer_id = sr.sterilizer_id) sterilizercode
              from sterilizationrun sr, businessunit bu
             where sr.businessunit_id = bu.businessunit_id
             and bu.plant_id= lv_plantid
              and sr.status = 4
               and sr.chargetype = 1 --cleanroom charges
               and ((sr.cooldownendtime is null)
                or (sr.cooldownendtime < sysdate))) loop
  begin
      update cart c
         set c.status_id           = lv_statusid,
             c.sterilizationrun_id = null,
             c.systemuser_id       = fp_systemuserid,
             c.timestamp           = sysdate
       where c.sterilizationrun_id = x.sterilizationrun_id;

      update sterilizationrun sr
         set sr.status        = 6,
             sr.systemuser_id = fp_systemuserid,
             sr.timestamp     = sysdate
       where sr.sterilizationrun_id = x.sterilizationrun_id;

      gv_message       := 'Charge ' || x.chargenumber || ' Sterilizer ' || x.sterilizercode || ' completed.';
      write_log(gv_message, 1);
  exception  --exception handling
  when others then
    begin
      rollback;
      gv_message := 'Error completing charge ' || x.chargenumber || ' Sterilizer ' || x.sterilizercode || '. Error :' || sqlerrm;
      write_log(gv_message, 3);
    end;
    end;
  end loop;
  commit;
end autocompletecleanroomcharges;
/
create or replace procedure bts_alpu_getgarmentdata(fp_i_idcode          in uniqueitem.primaryid%type,
                                                    fp_i_plantcode       in plant.code%type,
                                                    fp_o_customernumber  out nocopy customer.customernumber%type,
                                                    fp_o_customername    out nocopy customer.name%type,
                                                    fp_o_batchnumber     out nocopy uniqueitem.batchnumber%type,
                                                    fp_o_departmentdesc  out nocopy department.description%type,
                                                    fp_o_wearername      out nocopy wearer.fullname%type,
                                                    fp_o_product_desc    out nocopy product_desc.description%type,
                                                    fp_o_sizecode        out nocopy sizedefinition.code%type,
                                                    fp_o_banklocker      out nocopy varchar2,
                                                    fp_o_in_productgroup out nocopy varchar2,
                                                    fp_o_no_flag         out nocopy varchar2,
                                                    fp_o_expiration      out nocopy productfinishingmethod.expirationdays%type) is
  /*****
  --Version 1.01
  Parameters
  fp_o_in_productgroup Y als product group ID in (372,366, 395) ELSE N
  fp_o_no_flag is Y or N when there are flags on the wearer and or garment then it is N else Y
  ******/
  --Global variables
  gv_language_id languages.language_id%type := 1;
  gv_message     abslog.message%type;
  gv_plantid     plant.plant_id%type;

  ---internal procedure(s)
  procedure write_log(fp_message in varchar2 default null, fp_priority in number default 1) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'bts_alpu_getgarmentdata', null, nvl(fp_priority, 1),
                             nvl(fp_message, gv_message));
  end write_log;

begin
  --get plant id
  gv_message := ' plant code ' || nvl(fp_i_plantcode, 'NULL');
  select pt.plant_id into gv_plantid from plant pt where pt.code = fp_i_plantcode;
  --get uniqueitem
  gv_message := ' primary id ' || nvl(fp_i_idcode, 'NULL') || ' for plant code ' || fp_i_plantcode;
  --remark we always link with uniqueitem non pool, because we do NOT
  --show items on stock nor pool items
  select c.customernumber, c.name, u.batchnumber, t.description, w.fullname,
         (select pd.description
           from   product_desc pd
           where  pd.product_id = u.product_id
           and    pd.language_id = gv_language_id) product_desc, s.code,
         (select l.bank || '/' || l.locker from locker l where l.locker_id = we.locker_id) banklocker,
         case
           when p.productgroup_id in (372, 366, 395) then
            'Y'
           else
            'N'
         end in_productgroup,
         --check if flags are linked, we do not check flag start date yet
         case
           when ((select count(1)
                  from   uniqueitemflag uf
                  where  uf.uniqueitem_id = u.uniqueitem_id
                  and    uf.startdate <= trunc(sysdate)) + case
                  when (w.flagstartdate <= trunc(sysdate) and w.flag_id is not null) then
                   1
                  else
                   0
                end + case
                  when (we.flagstartdate <= trunc(sysdate) and we.flag_id is not null) then
                   1
                  else
                   0
                end) > 0 then
            'N'
           else
            'Y'
         end no_flag,
         (select pf.expirationdays
           from   productfinishingmethod pf
           where  pf.product_id = u.product_id
           and    pf.finishingmethod_id = u.finishingmethod_id) expirationdays
  into   fp_o_customernumber, fp_o_customername, fp_o_batchnumber, fp_o_departmentdesc,
         fp_o_wearername, fp_o_product_desc, fp_o_sizecode, fp_o_banklocker, fp_o_in_productgroup,
         fp_o_no_flag, fp_o_expiration
  from   uniqueitem u
  join   businessunit bu
  on     bu.businessunit_id = u.businessunit_id
  join   product p
  on     p.product_id = u.product_id
  join   sizedefinition s
  on     s.sizedefinition_id = u.sizedefinition_id
  join  (uniqueitemnonpool un
  join   weareremployment we
  on     we.weareremployment_id = un.weareremployment_id
  join   wearer w
  on     w.wearer_id = we.wearer_id
  join   customer c
  on     c.customer_id = w.customer_id
  join   distributionpoint dp
  on     dp.distributionpoint_id = we.distributionpoint_id
  join   department t
  on     t.department_id = dp.department_id) on un.uniqueitem_id = u.uniqueitem_id
  where  u.primaryid = fp_i_idcode
  and    bu.plant_id = gv_plantid;
exception
  --exception handling global
  when no_data_found then
    begin
      --return nothing because nothing was found
      fp_o_customernumber  := null;
      fp_o_customername    := null;
      fp_o_batchnumber     := null;
      fp_o_departmentdesc  := null;
      fp_o_wearername      := null;
      fp_o_product_desc    := null;
      fp_o_sizecode        := null;
      fp_o_banklocker      := null;
      fp_o_in_productgroup := null;
      fp_o_no_flag         := null;
      fp_o_expiration      := null;
    end;
  when others then
    begin
      write_log(sqlerrm, 5);
      write_log('Error Others during get ' || gv_message ||
                ' for detailed info see debug log message', 3);
      raise;
    end;
end bts_alpu_getgarmentdata;
/
create or replace procedure bts_alpu_outscan(fp_i_idcode         in uniqueitem.primaryid%type,
                                             fp_i_plantcode      in plant.code%type,
                                             fp_locationcode     in varchar2,
                                             fp_nextlocationcode in varchar2,
                                             fp_o_status         out varchar2) is
  --Version 1.00
  --Global variables
  gv_plantid   plant.plant_id%type;
  gv_plantcode plant.code%type;
  gv_counter   number;
begin
  --get plant id
  select min(pt.plant_id) into gv_plantid from plant pt where pt.code = fp_i_plantcode;
  --get sort info
  select count(1)
  into   gv_counter
  from   sortingimportdefinition s
  where  s.plant_id = gv_plantid
  and    s.transactiontype = 2 --outscan
  and    s.location = fp_locationcode
  and    (s.nextlocation = fp_nextlocationcode or
        s.nextlocation is null and fp_nextlocationcode is null);
  /*
  insert into sortingimportdefinition
    (sortingimportdefinition_id, plant_id, workstation_id, location, nextlocation, transactiontype,
     systemuser_id, timestamp)
    select seq_sortingimportdefinition.nextval, wo.plant_id, wo.workstation_id, substr(wo.code, 1, 6),
           null, 2, wo.systemuser_id, sysdate
    from   workstation wo
    where  wo.code = '123'  --->workstation CODE
    and    not exists (select 1
            from   sortingimportdefinition sox
            where  sox.location = substr(wo.code, 1, 6)
            and    sox.nextlocation is null
            and    sox.plant_id = wo.plant_id);
  */
  if gv_counter <> 1 then
    begin
      --was not outscan or sortingimportdefinition did not exist
      fp_o_status := 1;
      raise_application_error(-20123,
                              'OUTSCAN Locationcode ' || nvl(fp_locationcode, 'NULL') ||
                               ' and nextlocation code ' || fp_nextlocationcode ||
                               ' do not exist for plant ' || fp_i_plantcode || ' !');
    end;
  end if;
  --process outscan
  gv_plantcode := fp_i_plantcode;
  sendtrackinfo(fp_i_idcode, gv_plantcode, to_number(to_char(sysdate, 'YYYYMMDD')),
                to_char(sysdate, 'HH24MISS'), fp_locationcode, fp_nextlocationcode, null, null, null,
                null, null, null, null, null, fp_o_status);
end bts_alpu_outscan;
/
create or replace procedure calculate_residualvalue(fp_businessunitcode    in businessunit.code%type,
                                                    fp_systemuserid        in number default 0,
                                                    fp_loglevel            in number default 0,
                                                    fp_rv_percentage_round in number default 2,
                                                    fp_rv_amount_round     in number default 2) is
  --Procedure Calculate_Residualvalue Version 0.9
  --fp_loglevel 0 no extra logging
  --            1 ( <> 0 ) shows when PLPC does not have a residualvaluescheme
  --            2 extra messags when no replacement price is found
  --            3 extra message when replacment price used is 0
  --30-05-2022 ABS-135112 create simple version of pack residual value
  -- hvl 7-7-23.  fixes
  --              rounding % to 3 decimals
  --              total washes do include rewash
  --
  gv_userexception           exception;
  gv_message                 varchar2(1000);
  gv_businessunitid          number;
  gv_plantid                 number;
  gv_counter                 number := 0;
  gv_residualvalueschemeid   number;
  gv_replacementprice        customerreplacementprice.price%type;
  gv_residualvalue           number;
  gv_depreciation_percentage number;
  gv_sizestarid              number;
  gv_prev_custid             number := -1;
  gv_prev_prodid             number := -1;
  gv_prev_sizeid             number := -1;
  gv_prev_finid              number := -1;
  gv_price_found_yn          varchar2(1);

  --Internal procedures
  procedure write_log(fp_message in varchar2, fp_priority in number) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'calculate_residualvalue', gv_plantid, fp_priority, fp_message,
                             nvl(fp_systemuserid, 0));
    begin
      dbms_output.put_line(fp_message);
    exception
      when others then
        null; --ok no output does not matter
    end;
  end write_log;

  procedure initialize is
  begin
    --get size star id
    gv_message := 'Size star * ';
    select s.sizedefinition_id into gv_sizestarid from sizedefinition s where s.code = '*';
    --initialize check parameter fp_businessunitcode
    if fp_businessunitcode is null then
      begin
        gv_message := 'Parameter fp_businessunitcode cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        gv_message := 'Parameter fp_businessunitcode ' || fp_businessunitcode;
        select bu.businessunit_id, bu.plant_id
        into   gv_businessunitid, gv_plantid
        from   businessunit bu
        where  bu.code = fp_businessunitcode;
      end;
    end if;
    --Write log that the process can be started
    write_log('Start calculate_residualvalue for businessunit ' || fp_businessunitcode, 1);
  end initialize;

  procedure write_nice_log(fp_customerid        in number,
                           fp_productid         in number,
                           fp_sizeid            in number,
                           fp_finishingmethodid in number) is
    lv_customernumber number;
    lv_productcode    product.code%type;
    lv_sizecode       sizedefinition.code%type;
    lv_fincode        finishingmethod.code%type;
  begin
    --get customer number
    gv_message := 'customer id ' || to_char(fp_customerid);
    select c.customernumber
    into   lv_customernumber
    from   customer c
    where  c.customer_id = fp_customerid;
    --get product code
    gv_message := 'product id ' || to_char(fp_productid);
    select p.code into lv_productcode from product p where p.product_id = fp_productid;
    if fp_sizeid is null then
      begin
        lv_sizecode := null;
      end;
    else
      begin
        --get sizecode
        gv_message := 'size id ' || to_char(fp_sizeid);
        select s.code into lv_sizecode from sizedefinition s where s.sizedefinition_id = fp_sizeid;
      end;
    end if;
    if fp_finishingmethodid is null then
      begin
        if gv_price_found_yn = 'N' then
          write_log('No replacement price found for customer ' || to_char(lv_customernumber) ||
                    ' product ' || lv_productcode, 3);
        elsif gv_replacementprice = 0 then
          begin
            write_log('Replacement price 0 found for customer ' || to_char(lv_customernumber) ||
                      ' product ' || lv_productcode, 3);
          end;
        end if;
      end;
    else
      begin
        --get finishingmethod
        gv_message := 'finishingmethod id ' || to_char(fp_finishingmethodid);
        select f.code
        into   lv_fincode
        from   finishingmethod f
        where  f.finishingmethod_id = fp_finishingmethodid;
        --write log
        write_log('No residualvalue scheme for customer ' || to_char(lv_customernumber) ||
                  ' product ' || lv_productcode || ' size ' || lv_sizecode || ' fin.method ' ||
                  lv_fincode, 3);
      end;
    end if;
  end write_nice_log;

  function get_depreciation_percent_round(fp_resvaluescheme_id number,
                                          fp_washes_or_weeks   number,
                                          fp_rounding          number) return number is
    depreciation_percentage number := 0;
  begin
    begin
      select max(case
                   when r.definitiontype = 2 -- linear
                    then
                    round(r.startpercentage -
                          (((fp_washes_or_weeks - r.rangestart) / (r.rangeend - r.rangestart)) *
                          (r.startpercentage - r.endpercentage)), fp_rounding)
                   else -- fixed
                    r.fixedpercentage
                 end) depr_percentage
      into   depreciation_percentage
      from   resvalschemedefinition r
      where  r.residualvaluescheme_id = fp_resvaluescheme_id
      and    r.rangestart <= fp_washes_or_weeks
      and    r.rangeend >= fp_washes_or_weeks;
    exception
      when no_data_found then
        depreciation_percentage := 0;
    end;
    return nvl(depreciation_percentage, 0);
  end get_depreciation_percent_round;

  procedure get_residualvaluescheme(fp_customerid        in number,
                                    fp_productid         in number,
                                    fp_sizeid            in number,
                                    fp_finishingmethodid in number) is
  begin
    --get_residualvaluescheme
    if (fp_customerid <> gv_prev_custid or fp_productid <> gv_prev_prodid or
       fp_sizeid <> gv_prev_sizeid or fp_finishingmethodid <> gv_prev_finid) then
      begin
        gv_message               := 'get_residualvaluescheme';
        gv_residualvalueschemeid := null;
        --using active PLPC
        select l.residualvaluescheme_id
        into   gv_residualvalueschemeid
        from   productlistpercustomer l
        where  l.customer_id = fp_customerid
        and    l.product_id = fp_productid
        and    l.sizedefinition_id = fp_sizeid
        and    l.finishingmethod_id = fp_finishingmethodid
        and    trunc(sysdate) between l.dateactive and l.dateinactive;
      exception
        when no_data_found then
          begin
            --get active PLPC for size star
            select l.residualvaluescheme_id
            into   gv_residualvalueschemeid
            from   productlistpercustomer l
            where  l.customer_id = fp_customerid
            and    l.product_id = fp_productid
            and    l.sizedefinition_id = gv_sizestarid
            and    l.finishingmethod_id = fp_finishingmethodid
            and    trunc(sysdate) between l.dateactive and l.dateinactive;
          exception
            when no_data_found then
              begin
                --using INactive PLPC
                select max(l.residualvaluescheme_id)
                into   gv_residualvalueschemeid
                from   productlistpercustomer l
                where  l.customer_id = fp_customerid
                and    l.product_id = fp_productid
                and    l.sizedefinition_id = fp_sizeid
                and    l.finishingmethod_id = fp_finishingmethodid
                and    l.dateinactive <= trunc(sysdate);
                if gv_residualvalueschemeid is null then
                  begin
                    --get INactive PLPC for size star
                    select max(l.residualvaluescheme_id)
                    into   gv_residualvalueschemeid
                    from   productlistpercustomer l
                    where  l.customer_id = fp_customerid
                    and    l.product_id = fp_productid
                    and    l.sizedefinition_id = gv_sizestarid
                    and    l.finishingmethod_id = fp_finishingmethodid
                    and    l.dateinactive <= trunc(sysdate);
                  end;
                end if;
              end;
          end;
      end;
      --write log when no active residual value scheme has been found
      if gv_residualvalueschemeid is null and nvl(fp_loglevel, 0) <> 0 then
        begin
          write_nice_log(fp_customerid, fp_productid, fp_sizeid, fp_finishingmethodid);
        end;
      end if;
    end if;
  end get_residualvaluescheme;

  procedure get_residualvalue(fp_customerid          in number,
                              fp_productid           in number,
                              fp_sizeid              in number,
                              fp_firstissuedate      in date,
                              fp_lastissuedate       in date,
                              fp_washestotal         in number,
                              fp_daysincircprevissue in number,
                              fp_pricefirstissue     in number,
                              fp_pricelastissue      in number) is
    lv_washes_or_weeks number;

    function replacementprice(fp_pricedate in pricelistpercustomer.dateactive%type default null)
      return number is
      /* Returns the price, if not found, returns 0.  For use in calculations.  */
      lv_price            customerreplacementprice.price%type;
      lv_price_start_date customerreplacementprice.startdate%type;
      lv_result_code      number;
      lv_result_desc      varchar2(80);
      lv_price_list_type  varchar2(1);
      lv_price_list_code  generalpricelist.code%type;
      lv_price_list_desc  generalpricelist.description%type;
    begin
      pack_price.get_replacement_price_details(fp_customerid, fp_productid, fp_sizeid, null,
                                               fp_pricedate, lv_price, gv_price_found_yn,
                                               lv_price_start_date, lv_result_code, lv_result_desc,
                                               lv_price_list_type, lv_price_list_code,
                                               lv_price_list_desc);
      return(nvl(lv_price, 0));
    end replacementprice;
  begin
    --get_residualvalue
    gv_message := 'get_residualvalue';
    for y in (select rvs.residualvaluescheme_id, rvs.code, rvs.calculationweeks, rvs.systemuser_id,
                     rvs.timestamp, rvs.calculationbasis, rvs.internalvaluemaxweeks,
                     rvs.internalvaluemaxwashes, rvs.flagdelay, rvs.replacementpricetype
              from   residualvaluescheme rvs
              where  rvs.residualvaluescheme_id = gv_residualvalueschemeid) loop
      begin
        gv_price_found_yn := 'Y';
        --get_replacement_price
        --1 = actual residual value scheme and replacement price
        --2 = historic replacement price at moment of first issue
        --3 = historic replacement price at moment of last issue
        case y.replacementpricetype
          when 2 then
            if fp_pricefirstissue <> 0 then
              gv_replacementprice := fp_pricefirstissue;
            else
              gv_replacementprice := replacementprice(coalesce(fp_firstissuedate, fp_lastissuedate,
                                                               trunc(sysdate)));
            end if;
          when 3 then
            if fp_pricelastissue <> 0 then
              gv_replacementprice := fp_pricelastissue;
            else
              gv_replacementprice := replacementprice(coalesce(fp_lastissuedate, fp_firstissuedate,
                                                               trunc(sysdate)));
            end if;
          else
            gv_replacementprice := replacementprice(trunc(sysdate));
        end case;
        --CALCULATIONBASIS , get number of washes or weeks in circ
        --1 = weeks in circ
        --2 = number of washes
        --3 = actual weeks in use
        case y.calculationbasis
          when 1 then
            lv_washes_or_weeks := greatest(0,
                                           ceil(((trunc(sysdate) - fp_lastissuedate) +
                                                 fp_daysincircprevissue) / 7));
          when 2 then
            lv_washes_or_weeks := fp_washestotal;
          when 3 then
            --for now this, same as 1, simple method
            lv_washes_or_weeks := greatest(0,
                                           ceil(((trunc(sysdate) - fp_lastissuedate) +
                                                 fp_daysincircprevissue) / 7));
          else
            write_log('Unknown calculationbasis ' || to_char(y.calculationbasis) ||
                      ' for residualvaluescheme_id ' || to_char(gv_residualvalueschemeid), 3);
        end case;
        --get depreciation_percentage
        gv_depreciation_percentage := get_depreciation_percent_round(gv_residualvalueschemeid,
                                                                     lv_washes_or_weeks,
                                                                     fp_rv_percentage_round);
        --calc residualvalue
        gv_residualvalue := (gv_replacementprice * (gv_depreciation_percentage / 100));
      end;
    end loop; --y
    --write log when no active residual value scheme has been found
    if (((gv_price_found_yn = 'N' and nvl(fp_loglevel, 0) > 1) or
       (gv_price_found_yn = 'Y' and nvl(fp_loglevel, 0) > 2 and gv_replacementprice = 0)) and
       (fp_customerid <> gv_prev_custid or fp_productid <> gv_prev_prodid)) then
      begin
        write_nice_log(fp_customerid, fp_productid, null, null);
      end;
    end if;
  end get_residualvalue;
begin
  --Main program
  initialize;
  --start go though all uniqueitems non pool, in circulation
  gv_message := 'loop uniqueitemnonpool';
  for x in (select u.uniqueitem_id, u.primaryid, u.product_id, u.sizedefinition_id,
                   u.finishingmethod_id, we.weareremployment_id, w.wearer_id, w.customer_id,
                   dp.department_id, we.distributionpoint_id, u.replacementprice, u.residualvalue,
                   u.washestotal, u.rewashtotal, uf.currency_id,
                   nvl(u.residualvalueamount, 0) residualvalueamount, uf.daysincircprevissue,
                   uf.daysinstockprevious, uf.lastissuedate, uf.firstissuedate,
                   uf.histreplacementpricefirstissue, uf.histreplacementpricelastissue
            from   uniqueitem u
            join   uniqueitemfixedinfo uf
            on     uf.uniqueitem_id = u.uniqueitem_id
            join   uniqueitemnonpool un
            on     un.uniqueitem_id = u.uniqueitem_id
            join   weareremployment we
            on     we.weareremployment_id = un.weareremployment_id
            join   wearer w
            on     w.wearer_id = we.wearer_id
            join   distributionpoint dp
            on     dp.distributionpoint_id = we.distributionpoint_id
            where  u.poolitem = 2
            and    u.businessunit_id = gv_businessunitid
            and    nvl(u.leaseweeks, 0) = 0
            and    u.status_id in (select status_id
                                   from   status
                                   where  statustype = 'UI'
                                   and    code in ('20', '30'))
            and    u.customerowned = 'N'
            order  by w.customer_id, u.product_id, u.sizedefinition_id, u.finishingmethod_id) loop
    begin
      --get gv_residualvalueschemeid value
      get_residualvaluescheme(x.customer_id, x.product_id, x.sizedefinition_id,
                              x.finishingmethod_id);
      if gv_residualvalueschemeid is not null then
        begin
          --get_residualvalue
          get_residualvalue(x.customer_id, x.product_id, x.sizedefinition_id, x.firstissuedate,
                            x.lastissuedate, x.washestotal, x.daysincircprevissue,
                            x.histreplacementpricefirstissue, x.histreplacementpricelastissue);
          --update uniqueitem
          gv_message := 'update uniqueitem id ' || to_char(x.uniqueitem_id);
          update uniqueitem u
          set    u.residualvalue = gv_depreciation_percentage,
                 u.residualvalueamount = round(gv_residualvalue, fp_rv_amount_round),
                 u.replacementprice = gv_replacementprice, u.systemuser_id = nvl(fp_systemuserid, 0),
                 u.timestamp = sysdate
          where  u.uniqueitem_id = x.uniqueitem_id
          and    (u.residualvalue <> gv_depreciation_percentage or
                u.residualvalueamount <> gv_residualvalue or
                (u.residualvalueamount is null and gv_residualvalue is not null));
          --count uniqueitems processed
          gv_counter := gv_counter + sql%rowcount;
        end;
      end if;
      --set previous vlaues
      gv_prev_custid := x.customer_id;
      gv_prev_prodid := x.product_id;
      gv_prev_sizeid := x.sizedefinition_id;
      gv_prev_finid  := x.finishingmethod_id;
    end;
  end loop; --x
  if gv_counter > 0 then
    begin
      commit;
      write_log('Ran ok; ' || to_char(gv_counter) || ' uniqueitems updated for businessunit ' ||
                fp_businessunitcode, 1);
    end;
  else
    begin
      rollback;
      write_log('Ran ok, nothing updated for businessunit ' || fp_businessunitcode, 1);
    end;
  end if;
exception
  --Exception handling
  when gv_userexception then
    begin
      rollback;
      write_log(gv_message, 3);
    end;
  when no_data_found then
    begin
      rollback;
      write_log('Error, No Data Found ' || gv_message, 3);
    end;
  when others then
    begin
      rollback;
      write_log('Error ' || sqlerrm || ' ' || gv_message, 3);
    end;
end calculate_residualvalue;
/
create or replace procedure CFvExportPackages(UTLDIR in varchar2) is


  fSqlFile UTL_FILE.FILE_TYPE;
  FPsFilename          VARCHAR2(50);
  PreviousFileName     VARCHAR2(50);
  /* objects */
  CURSOR c_objects IS
     SELECT distinct owner, name, type
     FROM   sys.all_source
     WHERE  UPPER(owner) = UPPER(user)
     and type like 'PROCEDURE%'
     --and name = 'PACK_WORKORDERLINE'
     ORDER BY name , type ;

  /* Text */
  CURSOR c_text (obj_owner in varchar2, obj_name in varchar2, obj_type in varchar2) IS
     SELECT text
     FROM   sys.all_source
     WHERE  owner = UPPER(obj_owner)
     AND    name  = UPPER(obj_name)
     AND    type  = UPPER(obj_type)
     ORDER BY line;

BEGIN

  PreviousFileName := '';
  FOR r_objects IN c_objects LOOP
      FPsFilename:= r_objects.name ||'.prc';
      if (r_objects.name like PreviousFileName) then
         fSqlFile := UTL_FILE.FOPEN(UTLDIR, FPsFilename, 'a');
      else
         fSqlFile := UTL_FILE.FOPEN(UTLDIR, FPsFilename, 'w');
      end if;
      UTL_FILE.PUT(fSqlFile, 'create or replace ' );
  	  FOR r_text in c_text (r_objects.owner, r_objects.name, r_objects.type) LOOP
    	   UTL_FILE.PUT(fSqlFile, r_text.text);
      	 UTL_FILE.fflush(fSqlFile);
	    END LOOP;
      UTL_FILE.PUT_LINE(fSqlFile, '/');
      UTL_FILE.fflush(fSqlFile);
    	--if (r_objects.name like PreviousFileName) then
      	UTL_FILE.FCLOSE(fSqlFile);
      --end if;
      PreviousFileName := r_objects.name;

  END LOOP;



  EXCEPTION
  WHEN UTL_FILE.WRITE_ERROR THEN
       dbms_output.put_line ('Error: Utl_file.Write Error' );
       dbms_output.put_line ('An operating system error occured during write operation');
  WHEN UTL_FILE.READ_ERROR THEN
       dbms_output.put_line ('Error: Utl_file.Read Error ');
       dbms_output.put_line ('An operating system error occured during read operation');
  WHEN UTL_FILE.INVALID_FILEHANDLE THEN
       dbms_output.put_line ('Error: Utl_file.Invalid_Filehandle ');
       dbms_output.put_line ('The filehandle was invalid');
  WHEN UTL_FILE.INTERNAL_ERROR THEN
       dbms_output.put_line ('Error: Utl_file.Internal Error ');
       dbms_output.put_line ('An unspecified error in PL/SQL occured ');
  WHEN OTHERS THEN
       dbms_output.put_line ('Error: An unhandled exception occured ');

 end;
/
create or replace procedure checkViewsForExport is
  -- utl_file
  dir        VARCHAR2(60);
  filename   VARCHAR2(60);
  file       utl_file.file_type;
  v_text     varchar2(10000);
  issueFound boolean;
  pos1       number;
  pos2       number;

begin

  -- directory and filename where the reporting script will be created
  dir      := 'OUTPUT';
  filename := 'ViewsForExport.txt';

  -- open the file
  IF NOT utl_file.is_open(file) THEN
    file := utl_file.fopen(dir, filename, 'w');
  END IF;

  -- check for views with long text
  issueFound := false;
  for i in (select view_name from user_views where text_length >= 32767) loop
    if (not issueFound) then
      utl_file.put_line(file,
                        '----- Views too large - cannot be exported or checked -----' ||
                        chr(10));
      issueFound := true;
    end if;
    utl_file.put_line(file, i.view_name);
  end loop;

  if (issueFound) then
    utl_file.put_line(file, chr(10));
  end if;

  -- check for views with empty lines (consecutive CR's)
  issueFound := false;
  for i in (select view_name, text, ceil(text_length / 1000) numloops
              from user_views
             where text_length < 32767) loop
    for j in 0 .. i.numloops loop
      v_text := substr(i.text, (1 + j * 1000), 1001);

      if (instr(v_text, chr(10) || chr(10)) > 0) then
        if (not issueFound) then
          utl_file.put_line(file,
                            '----- Views with empty lines -----' || chr(10));
          issueFound := true;
        end if;
        utl_file.put_line(file, i.view_name);
        exit;
      end if;
    end loop;
  end loop;

  if (issueFound) then
    utl_file.put_line(file, chr(10));
  end if;

  -- check for lines too long to be exported
  issueFound := false;
  for i in (select view_name, text, ceil(text_length / 1000) numloops
              from user_views
             where text_length < 32767) loop
    pos1 := 0; -- last CR on current view text chunk
    pos2 := 0; -- first CR on current view text chunk - for calculating the length between CR when succesive CR's are on different view text chunks
    for j in 0 .. i.numloops loop
      v_text := substr(i.text, (1 + j * 1000), 1000);

      if (length(v_text) = 1000 and instr(lower(v_text), chr(10)) = 0) then
        if (not issueFound) then
          utl_file.put_line(file,
                            '----- Views with lines over 1000 chars -----' ||
                            chr(10));
          issueFound := true;
        end if;
        utl_file.put_line(file, i.view_name);
        exit;
      end if;

      pos2 := j * 1000 + instr(v_text, chr(10));
      if (pos2 = 0 and length(v_text) < 1000) then
        -- I'm on the last chunk so CR position = chunk length
        pos2 := j * 1000 + length(v_text);
      end if;

      if (pos2 - pos1 >= 1001) then
        if (not issueFound) then
          utl_file.put_line(file,
                            '----- Views with lines over 1000 chars -----' ||
                            chr(10));
          issueFound := true;
        end if;
        utl_file.put_line(file, i.view_name);
        exit;
      end if;

      pos1 := j * 1000 + instr(v_text, chr(10), -1);
    end loop;
  end loop;

  -- close the file
  utl_file.fclose(file);

exception
  when others then
    utl_file.put_line(file, 'ERROR!!!');
    utl_file.put_line(file,
                      'checkViewsForExport procedure has failed. Please check!!!');
    utl_file.fclose(file);

end checkViewsForExport;
/
create or replace procedure CleanupContainerScans(
      nPlantID                  plant.plant_id%type,
      nTransactionTypeID          transactiontype.transactiontype_id%type,
      dtOlderThanDate            date,
      nMinNoScansRemaining      int,
      nCountDeletedScans    out  int
) is

  cursor c_ui is
    select s.primaryid
      from containerscan s, businessunit b
     where s.businessunit_id = b.businessunit_id
       and b.plant_id = nPlantID
       and s.transactiontype_id = nTransactionTypeID
     group by s.primaryid
    having count(s.containerscan_id) > nMinNoScansRemaining;

  cursor c_select(nUniqueItemLinkID containerscan.primaryid%type) is
    select s.containerscan_id
      from containerscan s, businessunit b
     where s.primaryid = nUniqueItemLinkID
       and s.businessunit_id = b.businessunit_id
       and b.plant_id = nPlantID
       and s.transactiontype_id = nTransactionTypeID
     order by s.scantimestamp desc;

  countUpd   integer:=0;
  i          integer:=0;
  message    varchar2(150);

  procedure writelog(fp_message varchar2) is
  begin
    abslogwrite.abslog_write(5,'CLEANUPCONTAINERSCAN', nPlantID, 1, fp_message, 1);
  end;

begin

  message := 'Start process. Plant id: ' || nPlantID || ', TransactionType id: ' || nTransactionTypeID;
  if (nMinNoScansRemaining > 0) then
    message := message || ', MinNoScansRemaining: ' || nMinNoScansRemaining;
  else
    message := message || ', OlderThanDate: ' || to_char(dtOlderThanDate, 'dd/MON/yyyy');
  end if;
  writelog(message);

  if (nMinNoScansRemaining > 0) then

    for r_ui in c_ui loop
      i := 0;
      for x in c_select(r_ui.primaryid) loop
        i := i + 1;
        if (i > nMinNoScansRemaining) then
          delete from containerscan where containerscan_id = x.containerscan_id;
          commit;
          countUpd := countUpd + 1;
        end if;
      end loop;
    end loop;

  else
    for x in (select cs.containerscan_id from containerscan cs, businessunit bu
                      where cs.businessunit_id = bu.businessunit_id
                      and bu.plant_id = nPlantID
                      and cs.transactiontype_id = nTransactionTypeID
                      and cs.scantimestamp <= dtOlderThanDate) loop
      delete from containerscan where containerscan_id = x.containerscan_id;
      commit;
      countUpd := countUpd + 1;
    end loop;
  end if;

  nCountDeletedScans := countUpd;
  message := 'End process. Number of records deleted: ' || countUpd;
  writelog(message);
end;
/
create or replace procedure cleanupgarmentscans(fpnplantid             plant.plant_id%type,
                                                fpntransctiontypeid    transactiontype.transactiontype_id%type,
                                                fpdtolderthandate      date,
                                                fpnminnoscansremaining int,
                                                fpncountdeletedscans   out int) is
  lvnbusinessunit_id businessunit.businessunit_id%type;
  lvncount           number := 1;
  lvnlast_id         scan.scan_id%type := 0;
  lvbdata_exists     boolean := true;
  type lvtuniqueitem_list is table of number;
  type lvtcountscans is table of number;
  lvuniqueitem_list lvtuniqueitem_list;
  lvcountscans      lvtcountscans;

  cursor c1(pfrom number) is
    select s.uniqueitem_link_id uniqueitem_id, count(1) scancount
      from scan s
     where s.businessunit_id = lvnbusinessunit_id
       and s.transactiontype_id = fpntransctiontypeid
       and s.scantimestamp <= fpdtolderthandate
       and s.uniqueitem_link_id >= pfrom
     group by s.uniqueitem_link_id
    having count(s.scan_id) > fpnminnoscansremaining
     order by s.uniqueitem_link_id;
begin
  fpncountdeletedscans := 0;
  --get bu id
  for x in (select bu.businessunit_id
              from businessunit bu
             where bu.plant_id = fpnplantid) loop
    begin
      lvnbusinessunit_id := x.businessunit_id;
      --check
      if nvl(fpnminnoscansremaining, 0) <= 0 then
        begin
          while lvncount > 0 loop
            begin
              delete from scan s
               where s.businessunit_id = lvnbusinessunit_id
                 and s.transactiontype_id = fpntransctiontypeid
                 and s.scantimestamp <= fpdtolderthandate
                 and rownum <= 5000;
              lvncount := sql%rowcount;
              commit;
              fpncountdeletedscans := fpncountdeletedscans + lvncount;
            end;
          end loop;
        end;
      else
        begin
          while lvbdata_exists loop
            -- Loop needed to flush rollback space.
            -- Started to fill the cursor with the right start id.
            open c1(lvnlast_id);
            fetch c1 bulk collect
              into lvuniqueitem_list, lvcountscans limit 5000;
            for i in 1 .. lvuniqueitem_list.count loop
              begin
                lvnlast_id := lvuniqueitem_list(i);
                --delete barcodes
                delete from scan s
                 where s.uniqueitem_link_id = lvnlast_id
					       and s.transactiontype_id = fpntransctiontypeid
                   and rownum <= (lvcountscans(i) - fpnminnoscansremaining);
                fpncountdeletedscans := fpncountdeletedscans +
                                        lvcountscans(i) -
                                        fpnminnoscansremaining;
              end;
            end loop;
            if c1%notfound then
              lvbdata_exists := false;
            end if;
            close c1;
            commit; -- commit after closing cursor releases rollback space.
          end loop;
        end;
      end if;
    end;
  end loop; --x
end cleanupgarmentscans;
/
create or replace procedure CleanupGarmentScansTest(nPlantID             plant.plant_id%type,
                                                    nTransctionTypeID    transactiontype.transactiontype_id%type,
                                                    dtOlderThanDate      date,
                                                    nMinNoScansRemaining int,
                                                    nCountDeletedScans   out int) is

  /*cursor c_ui is
  select s.uniqueitem_link_id
    from scan s, businessunit b
   where s.businessunit_id = b.businessunit_id
     and b.plant_id = nPlantID
     and s.transactiontype_id = nTransctionTypeID
   group by s.uniqueitem_link_id
  having count(s.scan_id) > nMinNoScansRemaining;*/

  /* cursor c_select(nUniqueItemLinkID uniqueitem_link.uniqueitem_link_id%type) is
  select s.scantimestamp
    from scan s
   where s.uniqueitem_link_id = nUniqueItemLinkID
     and s.transactiontype_id = nTransctionTypeID
   order by s.scantimestamp desc;*/

  countUpd integer := 0;
  i        integer := 0;
  j        integer := 0;

begin

  dbms_output.put_line('1 ' || to_char(sysdate, 'dd/mm/yyyy hh24:mi:ss'));
  --update scan set markdelete = '' where markdelete is not null;

  execute immediate 'alter table scan disable constraint SCAN_BUSINESSUNIT_ID';
  execute immediate 'alter table scan disable constraint SCAN_CUSTOMER_LINK_ID';
  execute immediate 'alter table scan disable constraint SCAN_DISTRIBUTIONPOINT_LINK_ID';
  execute immediate 'alter table scan disable constraint SCAN_PREVSTAY_ID';
  execute immediate 'alter table scan disable constraint SCAN_PRODUCT_LINK_ID';
  execute immediate 'alter table scan disable constraint SCAN_QUALITYGRADE_ID';
  execute immediate 'alter table scan disable constraint SCAN_REASONCODE_ID';
  execute immediate 'alter table scan disable constraint SCAN_ROUTE_ID';
  execute immediate 'alter table scan disable constraint SCAN_SIZEDEFINITION_LINK_ID';
  execute immediate 'alter table scan disable constraint SCAN_STATUS_ID';
  execute immediate 'alter table scan disable constraint SCAN_STAY_ID';
  execute immediate 'alter table scan disable constraint SCAN_TRANSACTIONTYPE_ID';
  execute immediate 'alter table scan disable constraint SCAN_UNIQUEITEM_LINK_ID';
  execute immediate 'alter table scan disable constraint SCAN_WEAREREMPLOYMENT_LINK_ID';
  dbms_output.put_line('2 ' || to_char(sysdate, 'dd/mm/yyyy hh24:mi:ss'));

  if (nMinNoScansRemaining > 0) then

    for r_ui in (select s.uniqueitem_link_id
                   from scan s, businessunit b
                  where s.businessunit_id = b.businessunit_id
                    and b.plant_id = nPlantID
                    and s.transactiontype_id = nTransctionTypeID
                  group by s.uniqueitem_link_id
                 having count(s.scan_id) > nMinNoScansRemaining) loop
      i := 0;
      for r_select in (select s.scantimestamp
                         from scan s
                        where s.uniqueitem_link_id = r_ui.uniqueitem_link_id --nUniqueItemLinkID
                          and s.transactiontype_id = nTransctionTypeID
                          and s.scantimestamp <= dtOlderThanDate
                        order by s.scantimestamp desc) loop
        i := i + 1;
        if (i > nMinNoScansRemaining) then
          /* update scan
            set markdelete = 1
          where scan.uniqueitem_link_id = r_ui.uniqueitem_link_id
            and scan.transactiontype_id = nTransctionTypeID
            and scan.scantimestamp <= r_select.scantimestamp;*/
          delete scan
          --set markdelete = 1
           where scan.uniqueitem_link_id = r_ui.uniqueitem_link_id
             and scan.transactiontype_id = nTransctionTypeID
             and scan.scantimestamp <= r_select.scantimestamp;
          countUpd := countUpd + sql%rowcount;
          exit;
        end if;
      end loop;
      -- j := j + 1;
    /* if (j > 10000) then
                        commit;
                        j := 0;
                      end if;*/
    end loop;
    dbms_output.put_line('updated - now deleted' || countUpd);
    dbms_output.put_line('4 ' || to_char(sysdate, 'dd/mm/yyyy hh24:mi:ss'));

  else
    --update
    delete scan s
    --set markdelete = 1
     where exists (select b.businessunit_id
              from businessunit b
             where s.businessunit_id = b.businessunit_id
               and b.plant_id = nPlantID)
       and s.transactiontype_id = nTransctionTypeID
       and s.scantimestamp <= dtOlderThanDate;
    -- commit;
    dbms_output.put_line('updated - deleted now .....' || sql%rowcount);
    dbms_output.put_line('3 ' || to_char(sysdate, 'dd/mm/yyyy hh24:mi:ss'));

  end if;
  /*
  execute immediate 'alter table scan disable constraint SCAN_BUSINESSUNIT_ID';
  execute immediate 'alter table scan disable constraint SCAN_CUSTOMER_LINK_ID';
  execute immediate 'alter table scan disable constraint SCAN_DISTRIBUTIONPOINT_LINK_ID';
  execute immediate 'alter table scan disable constraint SCAN_PREVSTAY_ID';
  execute immediate 'alter table scan disable constraint SCAN_PRODUCT_LINK_ID';
  execute immediate 'alter table scan disable constraint SCAN_QUALITYGRADE_ID';
  execute immediate 'alter table scan disable constraint SCAN_REASONCODE_ID';
  execute immediate 'alter table scan disable constraint SCAN_ROUTE_ID';
  execute immediate 'alter table scan disable constraint SCAN_SIZEDEFINITION_LINK_ID';
  execute immediate 'alter table scan disable constraint SCAN_STATUS_ID';
  execute immediate 'alter table scan disable constraint SCAN_STAY_ID';
  execute immediate 'alter table scan disable constraint SCAN_TRANSACTIONTYPE_ID';
  execute immediate 'alter table scan disable constraint SCAN_UNIQUEITEM_LINK_ID';
  execute immediate 'alter table scan disable constraint SCAN_WEAREREMPLOYMENT_LINK_ID';*/

  /* delete /*+ INDEX (SCAN XIE5SCAN)  */
  /*from scan
  where markdelete = 1
    and transactiontype_id = nTransctionTypeID;*/
  nCountDeletedScans := sql%rowcount;
  --- commit;*/

  execute immediate 'alter table scan enable constraint SCAN_BUSINESSUNIT_ID';
  execute immediate 'alter table scan enable constraint SCAN_CUSTOMER_LINK_ID';
  execute immediate 'alter table scan enable constraint SCAN_DISTRIBUTIONPOINT_LINK_ID';
  execute immediate 'alter table scan enable constraint SCAN_PREVSTAY_ID';
  execute immediate 'alter table scan enable constraint SCAN_PRODUCT_LINK_ID';
  execute immediate 'alter table scan enable constraint SCAN_QUALITYGRADE_ID';
  execute immediate 'alter table scan enable constraint SCAN_REASONCODE_ID';
  execute immediate 'alter table scan enable constraint SCAN_ROUTE_ID';
  execute immediate 'alter table scan enable constraint SCAN_SIZEDEFINITION_LINK_ID';
  execute immediate 'alter table scan enable constraint SCAN_STATUS_ID';
  execute immediate 'alter table scan enable constraint SCAN_STAY_ID';
  execute immediate 'alter table scan enable constraint SCAN_TRANSACTIONTYPE_ID';
  execute immediate 'alter table scan enable constraint SCAN_UNIQUEITEM_LINK_ID';
  execute immediate 'alter table scan enable constraint SCAN_WEAREREMPLOYMENT_LINK_ID';
  dbms_output.put_line('deleted ' || nCountDeletedScans);
  dbms_output.put_line('5 ' || to_char(sysdate, 'dd/mm/yyyy hh24:mi:ss'));

end;
/
create or replace procedure confirmrouteimport(lvsplantnumber plant.code%type,
                                               lvdtroutedate  routecontrol.drivingdate%type,
                                               lvnroutenumber route.routenumber%type) is
begin
  update routecontrol rc
  set    rc.sortingstatus = 2
  where  rc.drivingdate = lvdtroutedate
  and    rc.route_id =
         (select r.route_id
           from   route r
           where  r.routenumber = lvnroutenumber
           and    r.plant_id = rc.plant_id
           and    r.drivingday_id = to_char(rc.originaldrivingdate - 1, 'd'))
  and    rc.plant_id = (select pt.plant_id from plant pt where pt.code = lvsplantnumber);
  commit;
exception
  when others then
    rollback;
end confirmrouteimport;
/
create or replace procedure confirmsortbatchimport(sortbatchnumber in sortbatch.sortbatch_id%type) is
  --confirmsortbatchimport version 2.0 log in abslog
  vstatus       sortbatch.status%type;
  sortbatchdate sortbatch.batchdate%type;
  batchnumber   sortbatch.batchnumber%type;
  plantid       plant.plant_id%type;

  --internal procedures
  procedure write_log(fp_message in varchar2, fp_priority in number default 1) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'confirmsortbatchimport', plantid, fp_priority, fp_message);
  end write_log;

begin
  select s.status, s.batchdate, s.batchnumber, s.plant_id
  into   vstatus, sortbatchdate, batchnumber, plantid
  from   sortbatch s
  where  s.sortbatch_id = sortbatchnumber;
  if vstatus = 0 then
    begin
      write_log('Warning; Confirm sort batch import: batch not exported ' || sortbatchdate || ' ' ||
                batchnumber, 2);
    end;
  else
    begin
      update sortbatch s set s.status = 2 where s.sortbatch_id = sortbatchnumber;
      commit;
      write_log('Ok; Confirm sort batch import: batch exported ' || sortbatchdate || ' ' ||
                batchnumber, 1);
    end;
  end if;
exception
  --Calling system will get error message when something is not ok!
  when no_data_found then
    begin
      write_log('No data found; Sort batch number ' || sortbatchnumber, 3);
      raise_application_error(-20114, 'No data found; Sort batch number  ' || sortbatchnumber);
    end;
  when others then
    begin
      write_log('Error; Confirm sort batch import: batch number ' || sortbatchnumber || sqlerrm, 3);
      raise_application_error(-20115,
                              'Error; Confirm sort batch import: batch number ' || sortbatchnumber ||
                               sqlerrm);
    end;
end confirmsortbatchimport;
/
create or replace procedure ConvertNonUniqueStockItems is
  cursor c1 is
    select 1
      from user_tables
     where table_name = 'BKP_STOCKRESERVATIONPERGRADE';
  cursor c2 is
    select 1 from user_tables where table_name = 'BKP_STOCKQUANTITY';
  cursor cStockLocation(c_srg_id in stockreservationpergrade.stockreservationpergrade_id%type) is
    select min(sq.stockroomlocation_id)
      from stockquantity sq
     where sq.stockreservationpergrade_id = c_srg_id;
  cursor cStdLocProdNotNull(c_stockroom_id in stockroomlocation.stockroom_id%type, c_prod_id in standardlocationperproduct.product_id%type, c_custOwned in standardlocationperproduct.customerowned%type, c_cust_id in standardlocationperproduct.customer_id%type) is
    select sl.stockroomlocation_id, sl.allowedgrade
      from standardlocationperproduct sl,
      stockroomlocation l
     where sl.stockroomlocation_id = l.stockroomlocation_id
       and l.stockroom_id = c_stockroom_id
       and sl.product_id = c_prod_id
       and sl.customerowned = c_custOwned
       and sl.customer_id = c_cust_id
       and sl.active = 'Y'
       and sl.definepersize = 'N'
     order by sl.priority;
  cursor cStdLocProdNull(c_stockroom_id in stockroomlocation.stockroom_id%type, c_prod_id in standardlocationperproduct.product_id%type, c_custOwned in standardlocationperproduct.customerowned%type) is
    select sl.stockroomlocation_id, sl.allowedgrade
      from standardlocationperproduct sl,
      stockroomlocation l
     where sl.stockroomlocation_id = l.stockroomlocation_id
       and l.stockroom_id = c_stockroom_id
       and sl.product_id = c_prod_id
       and sl.customerowned = c_custOwned
       and sl.customer_id is null
       and sl.active = 'Y'
       and sl.definepersize = 'N'
     order by sl.priority;
  cursor cStdLocProdDefPerSizeNotNull(c_stockroom_id in stockroomlocation.stockroom_id%type, c_prod_id in standardlocationperproduct.product_id%type, c_custOwned in standardlocationperproduct.customerowned%type, c_cust_id in standardlocationperproduct.customer_id%type, c_size_id standardlocationpersize.sizedefinition_id%type) is
     select sl.stockroomlocation_id, sl.allowedgrade
      from standardlocationperproduct sl,
      stockroomlocation l
     where sl.stockroomlocation_id = l.stockroomlocation_id
       and l.stockroom_id = c_stockroom_id
       and sl.product_id = c_prod_id
       and sl.customerowned = c_custOwned
       and sl.customer_id = c_cust_id
       and sl.active = 'Y'
       and sl.definepersize = 'Y'
       and exists (select 1
                    from standardlocationpersize sls
                   where sls.standardlocationperproduct_id =
                         sl.standardlocationperproduct_id
                     and sls.sizedefinition_id = c_size_id)
     order by sl.priority;
   cursor cStdLocProdDefPerSizeNull(c_stockroom_id in stockroomlocation.stockroom_id%type, c_prod_id in standardlocationperproduct.product_id%type, c_custOwned in standardlocationperproduct.customerowned%type, c_size_id standardlocationpersize.sizedefinition_id%type) is
     select sl.stockroomlocation_id, sl.allowedgrade
      from standardlocationperproduct sl,
      stockroomlocation l
     where sl.stockroomlocation_id = l.stockroomlocation_id
       and l.stockroom_id = c_stockroom_id
       and sl.product_id = c_prod_id
       and sl.customerowned = c_custOwned
       and sl.customer_id is null
       and sl.active = 'Y'
       and sl.definepersize = 'Y'
       and exists (select 1
                    from standardlocationpersize sls
                   where sls.standardlocationperproduct_id =
                         sl.standardlocationperproduct_id
                     and sls.sizedefinition_id = c_size_id)
     order by sl.priority;
   cursor cOverflowLoc(c_StockRoom_Id in stockroomlocation.stockroom_id%type) is
    select srl.stockroomlocation_id
      from stockroomlocation srl
     where srl.stockroom_id = c_StockRoom_Id
     and srl.overflowlocation='Y';

  cursor cStockRoomLocation(c_StockRoomLocation_Id in stockroomlocation.stockroomlocation_id%type) is
    select srl.rowcode, srl.locationcode
      from stockroomlocation srl
     where srl.stockroomlocation_id = c_StockRoomLocation_Id;
  cnumber               number;
  vStockRoomLocation_Id stockroomlocation.stockroomlocation_id%type;
  vAllowedGrade         standardlocationperproduct.allowedgrade%type;
  vSRLocation_ID        stockroomlocation.stockroomlocation_id%type;
  vStockLocationRow     stockroomlocation.rowcode%type;
  vStockLocationCode    stockroomlocation.locationcode%type;
  vMessage              sqlscript_log.message%type;
  vSQLCode              integer;
  vOverflowLoc          boolean;
begin
  --create backup tables
  --for StockReservationPerGrade
  open c1;
  fetch c1
    into cnumber;
  if c1%notfound then
    cnumber := -1;
  end if;
  close c1;
  if cnumber > -1 then
    delete BKP_STOCKRESERVATIONPERGRADE;
  end if;
  insert into BKP_STOCKRESERVATIONPERGRADE (select * from stockreservationpergrade);

  --for StockQuantity
  open c2;
  fetch c2
    into cnumber;
  if c2%notfound then
    cnumber := -1;
  end if;
  close c2;
  if cnumber > -1 then
    delete BKP_STOCKQUANTITY;
  end if;
  insert into BKP_STOCKQUANTITY (select * from STOCKQUANTITY);

  --delete the previous entries of this procedure in the log file
  delete from sqlscript_log
   where scriptname = 'ConvertNonUniqueStockItems';
  --insert in the log file the header of the report
  insert into sqlscript_log
    (scriptname, creationtimestamp, errorcode, message)
  values
    ('ConvertNonUniqueStockItems',
     sysdate,
     null,
     'Product_____' || 'Size________' || 'Grade_______' || 'Customer____' ||
     'Cust. Owned_' || 'Qty_________' || 'Stockroom___' || 'Row_________' ||
     'Location____' || 'Remark');

  --select all StockReservationPerGrade records having QtyNonUnique > 0
  for x in (select srg.stockreservationpergrade_id,
                   sdi.stockroom_id,
                   sdi.product_id,
                   sdi.sizedefinition_id,
                   sdi.customer_id,
                   sdi.customerowned,
                   srg.qualitygrade_id,
                   srg.qtynonunique,
                   qg.newgarment,
                   qg.defectitem,
                   p.code prodcode,
                   s.code sizecode,
                   qg.code qgcode,
                   (select c.customernumber
                      from customer c
                     where c.customer_id = sdi.customer_id) custno,
                   sr.code stockroomcode
              from stockreservationpergrade srg,
                   stockdefinitionperitem   sdi,
                   qualitygrade             qg,
                   product                  p,
                   sizedefinition           s,
                   stockroom                sr
             where srg.stockdefinitionperitem_id =
                   sdi.stockdefinitionperitem_id
               and srg.qualitygrade_id = qg.qualitygrade_id
               and srg.qtynonunique > 0
               and sdi.product_id = p.product_id
               and sdi.sizedefinition_id = s.sizedefinition_id
               and sdi.stockroom_id = sr.stockroom_id
              order by  sdi.stockroom_id, sdi.product_id) loop
    --determine the first stockroomlocation looking into StockQuantity if any
    vOverflowLoc := false;
    open cStockLocation(x.stockreservationpergrade_id);
    fetch cStockLocation
      into vStockRoomLocation_Id;
    if cStockLocation%notfound or vStockRoomLocation_Id is null then
      vStockRoomLocation_Id := -1;
    end if;
    close cStockLocation;
    --if no location was found via StockQuantity then search the standard location of the product
    if vStockRoomLocation_Id = -1 then
      --step 1: look for a standard location defined per size, for the SRPG size
      if x.customer_id is null then
        open cStdLocProdDefPerSizeNull (x.stockroom_id, x.product_id, x.customerowned, x.sizedefinition_id);
		fetch cStdLocProdDefPerSizeNull
		 into vSRLocation_ID, vAllowedGrade;
		while cStdLocProdDefPerSizeNull%found and (vStockRoomLocation_Id = -1) loop
		  if x.newgarment = 'Y' and
			 (vAllowedGrade = 'N' or vAllowedGrade = 'B') then
			vStockRoomLocation_Id := vSRLocation_ID;
		  elsif x.newgarment = 'N' and x.defectitem = 'N' and
				(vAllowedGrade = 'U' or vAllowedGrade = 'B') then
			vStockRoomLocation_Id := vSRLocation_ID;
		  elsif x.newgarment = 'N' and x.defectitem = 'Y' and
				vAllowedGrade = 'D' then
			vStockRoomLocation_Id := vSRLocation_ID;
		  end if;
		fetch cStdLocProdDefPerSizeNull
		 into vSRLocation_ID, vAllowedGrade;
		end loop;
		close cStdLocProdDefPerSizeNull;
	   else
		open cStdLocProdDefPerSizeNotNull (x.stockroom_id, x.product_id, x.customerowned, x.customer_id, x.sizedefinition_id);
		fetch cStdLocProdDefPerSizeNotNull
		 into vSRLocation_ID, vAllowedGrade;
		while cStdLocProdDefPerSizeNotNull%found and (vStockRoomLocation_Id = -1) loop
		  if x.newgarment = 'Y' and
			 (vAllowedGrade = 'N' or vAllowedGrade = 'B') then
			vStockRoomLocation_Id := vSRLocation_ID;
		  elsif x.newgarment = 'N' and x.defectitem = 'N' and
				(vAllowedGrade = 'U' or vAllowedGrade = 'B') then
			vStockRoomLocation_Id := vSRLocation_ID;
		  elsif x.newgarment = 'N' and x.defectitem = 'Y' and
				vAllowedGrade = 'D' then
			vStockRoomLocation_Id := vSRLocation_ID;
		  end if;
		fetch cStdLocProdDefPerSizeNotNull
		 into vSRLocation_ID, vAllowedGrade;
		end loop;
		close cStdLocProdDefPerSizeNotNull;
	   end if;
      end if;
      --step 2: if not found at previous step, then look for a standard location that isn't defined per size
   if vStockRoomLocation_Id = -1 then
     if x.customer_id is null then
      open cStdLocProdNull (x.stockroom_id, x.product_id, x.customerowned);
        fetch cStdLocProdNull
          into vSRLocation_ID, vAllowedGrade;
        while cStdLocProdNull%found and (vStockRoomLocation_Id = -1) loop
          if x.newgarment = 'Y' and
             (vAllowedGrade = 'N' or vAllowedGrade = 'B') then
            vStockRoomLocation_Id := vSRLocation_ID;
          elsif x.newgarment = 'N' and x.defectitem = 'N' and
                (vAllowedGrade = 'U' or vAllowedGrade = 'B') then
            vStockRoomLocation_Id := vSRLocation_ID;
          elsif x.newgarment = 'N' and x.defectitem = 'Y' and
                vAllowedGrade = 'D' then
            vStockRoomLocation_Id := vSRLocation_ID;
          end if;
        fetch cStdLocProdNull
         into vSRLocation_ID, vAllowedGrade;
        end loop;
        close cStdLocProdNull;
      else
        open cStdLocProdNotNull (x.stockroom_id, x.product_id, x.customerowned, x.customer_id);
        fetch cStdLocProdNotNull
          into vSRLocation_ID, vAllowedGrade;
        while cStdLocProdNotNull%found and (vStockRoomLocation_Id = -1) loop
          if x.newgarment = 'Y' and
             (vAllowedGrade = 'N' or vAllowedGrade = 'B') then
            vStockRoomLocation_Id := vSRLocation_ID;
          elsif x.newgarment = 'N' and x.defectitem = 'N' and
                (vAllowedGrade = 'U' or vAllowedGrade = 'B') then
            vStockRoomLocation_Id := vSRLocation_ID;
          elsif x.newgarment = 'N' and x.defectitem = 'Y' and
                vAllowedGrade = 'D' then
            vStockRoomLocation_Id := vSRLocation_ID;
        end if;
         fetch cStdLocProdNotNull
         into vSRLocation_ID, vAllowedGrade;
        end loop;
        close cStdLocProdNotNull;
      end if;
    end if;

   --step 3: if no standard location was found, then put the quantity in an overflow location
        if vStockRoomLocation_Id = -1 then
        open cOverflowLoc(x.stockroom_id);
        fetch cOverflowLoc
          into vStockRoomLocation_Id;
         close cOverflowLoc;
          vOverflowLoc := true;
       end if;
    --update stock quantities if a location was found
    if vStockRoomLocation_Id > -1 then
      --update StockQuantity
      update stockquantity sq
         set sq.qtynonunique  = sq.qtynonunique + x.qtynonunique,
             sq.systemuser_id = 1,
             sq.timestamp     = sysdate
       where sq.stockreservationpergrade_id = x.stockreservationpergrade_id
         and sq.stockroomlocation_id = vStockRoomLocation_Id;
       if(sql%rowcount = 0) then
        insert into stockquantity(stockreservationpergrade_id, stockroomlocation_id, qtyunique, qtyuniquewithmodifications, systemuser_id, timestamp,
               qtycounted, datecounted, qtynonunique)
         values(x.stockreservationpergrade_id, vStockRoomLocation_Id, 0, 0, 1, sysdate, 0, null, x.qtynonunique) ;
       end if;
      -- reset QtyNonUnique from StockReservationPerGrade table
      update stockreservationpergrade sr
         set sr.qtynonunique  = 0,
             sr.systemuser_id = 1,
             sr.timestamp     = sysdate
       where sr.stockreservationpergrade_id = x.stockreservationpergrade_id;
      --select stocklocation for log file
      open cStockRoomLocation(vStockRoomLocation_Id);
      fetch cStockRoomLocation
        into vStockLocationRow, vStockLocationCode;
      if cStockRoomLocation%found then
        insert into sqlscript_log
          (scriptname, creationtimestamp, errorcode, message)
        values
          ('ConvertNonUniqueStockItems',
           sysdate,
           null,
           substr(x.prodcode || '___________', 1, 12) ||
           substr(x.sizecode || '___________', 1, 12) ||
           substr(x.qgcode || '___________', 1, 12) ||
           substr(x.custno || '___________', 1, 12) ||
           substr(x.customerowned || '___________', 1, 12) ||
           substr(x.qtynonunique || '___________', 1, 12) ||
           substr(x.stockroomcode || '___________', 1, 12) ||
           substr(vStockLocationRow || '___________', 1, 12) ||
           substr(vStockLocationCode || '___________', 1, 12));
      end if;
      close cStockRoomLocation;
    else
      insert into sqlscript_log
        (scriptname, creationtimestamp, errorcode, message)
      values
        ('ConvertNonUniqueStockItems',
         sysdate,
         null,
         substr(x.prodcode || '___________', 1, 12) ||
         substr(x.sizecode || '___________', 1, 12) ||
         substr(x.qgcode || '___________', 1, 12) ||
         substr(x.custno || '___________', 1, 12) ||
         substr(x.customerowned || '___________', 1, 12) ||
         substr(x.qtynonunique || '___________', 1, 12) ||
         substr(x.stockroomcode || '___________', 1, 12) || '____________' ||
         '____________' || 'FAILED');
    end if;
    commit;
  end loop;
  commit;
exception
  when others then
    rollback;
    vMessage := sqlerrm;
    vSQLCode := sqlcode;
    insert into sqlscript_log
      (scriptname, creationtimestamp, errorcode, message)
    values
      ('ConvertNonUniqueStockItems', sysdate, vSQLCode, vMessage);
    commit;
end ConvertNonUniqueStockItems;
/
create or replace procedure copyplantsettings(fpsplantcode plant.code%type) is
  lvnplant_id plant.plant_id%type;
begin
  -- get plant id from which to copy.
  select p.plant_id into lvnplant_id from plant p where p.code = fpsplantcode;
  -- delete wrong system setting entries
  delete from systemsetting s where s.plant_id <> lvnplant_id;
  insert into systemsetting
    (name, groupname, value, typeofvalue, factorydefault, defaultallowed,
     usedasdefault, minvalue, maxvalue, allowedchars, description, systemuser_id,
     timestamp, plant_id, active)
    select s.name, s.groupname, s.value, s.typeofvalue, s.factorydefault,
           s.defaultallowed, s.usedasdefault, s.minvalue, s.maxvalue,
           s.allowedchars, s.description, s.systemuser_id, sysdate, p.plant_id,
           s.active
    from   systemsetting s, plant p
    where  p.code <> fpsplantcode;
  -- copy plant invoice settings.
  -- plantturnovergroup
  delete from plantturnovergroup t where t.plant_id <> lvnplant_id;
  insert into plantturnovergroup
    (plant_id, turnovergroup_id, timestamp, systemuser_id, commissionpercentage)
    select p.plant_id, t.turnovergroup_id, sysdate, t.systemuser_id,
           t.commissionpercentage
    from   plantturnovergroup t, plant p
    where  t.plant_id <> lvnplant_id;
  -- plantinvoicefrequency
  delete from plantinvoicefrequency where plant_id <> lvnplant_id;
  insert into plantinvoicefrequency
    (plant_id, invoicefrequency_id, systemuser_id, defaultfrequency,
     documenttype, timestamp)
    select p.plant_id, i.invoicefrequency_id, i.systemuser_id,
           i.defaultfrequency, i.documenttype, sysdate
    from   plantinvoicefrequency i, plant p
    where  p.plant_id <> lvnplant_id;
  -- plantinvoicelinetype
  delete from plantinvoicelinetype where plant_id <> lvnplant_id;
  insert into plantinvoicelinetype
    (plant_id, invoicelinetype_id, timestamp, systemuser_id, sequencenumber)
    select p.plant_id, l.invoicelinetype_id, sysdate, l.systemuser_id,
           l.sequencenumber
    from   plantinvoicelinetype l, plant p
    where  p.plant_id <> lvnplant_id;
  -- plant
  update plant p
  set    p.financechargepercentage = (select x.financechargepercentage
                                       from   plant x
                                       where  x.plant_id = lvnplant_id),
         p.creditsqueezeturnovergroup_id = (select x.creditsqueezeturnovergroup_id
                                             from   plant x
                                             where  x.plant_id = lvnplant_id)
  where  p.plant_id <> lvnplant_id;
  -- commit when all went well and give message saying update went ok.
  commit;
  dbms_output.put_line('CopyPlantSettings ' || fpsplantcode || ' succesfull!');
exception
  when others then
    rollback;
    dbms_output.put_line('CopyPlantSettings ' || fpsplantcode || ' failed: ' ||
                         substr(sqlerrm, 1, 200));
end copyplantsettings;
/
create or replace procedure correctionSQMAx (sqHeaderID            statusquoheader.statusquoheader_id%type,
                                             UTLDIR in varchar2
                                    ) is
sizeFound boolean;
plpcSearch boolean;
fSqlFile UTL_FILE.FILE_TYPE;
sizeStar sizedefinition.sizedefinition_id%type;
cursor sqMAx is
       select A.SQMAXITEMINCIRCULATION_ID, A.PRODUCT_LINK_ID, A.SIZEDEFINITION_LINK_ID, A.FINISHINGMETHOD_ID, C.CUSTOMER_ID,
       A.TIMESTAMP, PR.CODE productCode, SZ.CODE sizeCode , FM.CODE fmCode, CU.CUSTOMERNUMBER
        from Sqmaxitemincirculation A, COSTCENTER C, PRODUCT PR, SIZEDEFINITION SZ, FINISHINGMETHOD FM,CUSTOMER CU
        WHERE A.COSTCENTER_LINK_ID = C.COSTCENTER_ID
        AND A.STATUSQUOHEADER_ID = sqHeaderID
        AND PR.PRODUCT_ID = A.PRODUCT_LINK_ID
        AND SZ.SIZEDEFINITION_ID = A.SIZEDEFINITION_LINK_ID
        AND FM.FINISHINGMETHOD_ID = A.FINISHINGMETHOD_ID
        AND CU.CUSTOMER_ID = C.CUSTOMER_ID
        order by cu.customernumber,sz.code;
  begin
   select sz.sizedefinition_id
   into sizeStar
   from sizedefinition sz
   where sz.code = '*';
   fSqlFile := UTL_FILE.FOPEN(UTLDIR, 'SQcorrection.txt', 'a');
   for rsMAxWrong in sqMAx loop
      sizeFound := false;
      plpcSearch := true;
      for rsSize in (select pr.product_id, sz.sizedefinition_id
                      from product pr, productsize ps, sizedefinition sz
                      where pr.product_id = ps.product_id
                      and sz.sizedefinition_id = ps.sizedefinition_id) loop
            if (rsMAxWrong.Product_link_Id = rsSize.Product_Id and
                rsMAxWrong.Sizedefinition_link_Id = rsSize.Sizedefinition_Id
               ) then
                    sizeFound := true;
                 end if;
      end loop;
      if (sizeFound = false) then
          UTL_FILE.PUT(fSqlFile, 'Size not defined in the Sizes of the Product: ');
          UTL_FILE.PUT(fSqlFile, 'customer =');
          UTL_FILE.PUT(fSqlFile,rsMAxWrong.CUSTOMERNUMBER);
          UTL_FILE.PUT(fSqlFile,',Sqmaxitemincirculation_id = ');
          UTL_FILE.PUT(fSqlFile,rsMAxWrong.Sqmaxitemincirculation_Id);
          UTL_FILE.PUT(fSqlFile,',size = ');
          UTL_FILE.PUT(fSqlFile,rsMAxWrong.sizeCode);
          UTL_FILE.PUT(fSqlFile,',product = ');
          UTL_FILE.PUT(fSqlFile,rsMAxWrong.productCode);
          UTL_FILE.PUT(fSqlFile,',finishingMethod=');
          UTL_FILE.PUT(fSqlFile,rsMAxWrong.fmCode);
          UTL_FILE.PUT_LINE(fSqlFile, '/');
          UTL_FILE.fflush(fSqlFile);
          delete sqmaxitemincirculation sq where sq.sqmaxitemincirculation_id = rsmaxWrong.Sqmaxitemincirculation_Id;
          plpcSearch := false;
      end if;
      if (plpcSearch) then
        sizeFound := false;
        for rsSize in (select PLPC.PRODUCT_ID, PLPC.SIZEDEFINITION_ID, PLPC.FINISHINGMETHOD_ID, PLPC.CUSTOMER_ID
                       from PRODUCTLISTPERCUSTOMER PLPC
                       WHERE PLPC.DATEACTIVE<=TRUNC(rsMaxWrong.Timestamp)
                       AND PLPC.DATEINACTIVE>=TRUNC(rsMaxWrong.Timestamp)) loop
              if (rsMAxWrong.Product_link_Id = rsSize.Product_Id and
                  (rsMAxWrong.Sizedefinition_link_Id = rsSize.Sizedefinition_Id or
                   rsSize.Sizedefinition_Id = sizeStar) and
                  rsMaxWrong.Customer_Id = rsSize.customer_id and
                  rsMaxWrong.Finishingmethod_Id = rsSize.finishingmethod_id ) then
                      sizeFound := true;
                   end if;
        end loop;
        if (sizeFound = false) then
            UTL_FILE.PUT(fSqlFile, 'Size not defined in the PLPCs of the Product: ');
             UTL_FILE.PUT(fSqlFile, 'customer =');
            UTL_FILE.PUT(fSqlFile,rsMAxWrong.CUSTOMERNUMBER);
            UTL_FILE.PUT(fSqlFile,',Sqmaxitemincirculation_id = ');
            UTL_FILE.PUT(fSqlFile,rsMAxWrong.Sqmaxitemincirculation_Id);
            UTL_FILE.PUT(fSqlFile,',size = ');
            UTL_FILE.PUT(fSqlFile,rsMAxWrong.sizeCode);
            UTL_FILE.PUT(fSqlFile,',product = ');
            UTL_FILE.PUT(fSqlFile,rsMAxWrong.productCode);
            UTL_FILE.PUT(fSqlFile,',finishingMethod=');
            UTL_FILE.PUT(fSqlFile,rsMAxWrong.fmCode);
            UTL_FILE.PUT_LINE(fSqlFile, '/');
            UTL_FILE.fflush(fSqlFile);
            delete sqmaxitemincirculation sq where sq.sqmaxitemincirculation_id = rsmaxWrong.Sqmaxitemincirculation_Id;
        end if;
      end if;
   end loop;
   UTL_FILE.FCLOSE(fSqlFile);
end correctionSQMAx;
/
create or replace procedure correctionSQMAXUpdate(sqHeaderID            statusquoheader.statusquoheader_id%type,
                                                  UTLDIR in varchar2
                                                  ) is
sizeFound boolean;
plpcSearch boolean;
fSqlFile UTL_FILE.FILE_TYPE;
sizeStarID sizedefinition.sizedefinition_id%type;
statusUIInCirculation status.status_id%type;
difference number;
sqDate Date;
sqWeek int;
sqYear int;
cursor sqMAx is
select cu.customernumber,
       dip.costcenter_id,
       p.product_id,
       p.code productCode,
       s.sizedefinition_id,
       s.code sizeCode,
       f.finishingmethod_id,
       f.code fmCode,
       count(ui.uniqueitem_id) qtyPerPiece
  from uniqueitem             ui,
       uniqueitemfixedinfo    uifi,
       uniqueitemnonpool      uinp,
       weareremployment       we,
       wearerinventory        wi,
       distributionpoint      dip,
       department             dep,
       customeractivities     ca,
       product                p,
       productgroup           pg,
       sizedefinition         s,
       finishingmethod        f,
       productlistpercustomer plpc,
       customer               cu,
       costcenter             cc
 where ui.uniqueitem_id = uinp.uniqueitem_id
   and ui.uniqueitem_id = uifi.uniqueitem_id
   and uinp.weareremployment_id = we.weareremployment_id
   --and ui.product_id = p.product_id
   and we.distributionpoint_id = dip.distributionpoint_id
   and dip.department_id = dep.department_id
   and ui.substituteforsizedefinition_id = s.sizedefinition_id
   and ui.finishingmethod_id = f.finishingmethod_id
   and p.productgroup_id = pg.productgroup_id
   and abs(pg.activity_id) = abs(ca.activity_id)
   and dep.customer_id = ca.customer_id
   and uinp.wearerinventory_id = wi.wearerinventory_id
   and abs(ca.processbusinessunit_id) = abs(ui.businessunit_id)
   and ui.status_id = statusUIInCirculation
   and plpc.customer_id = dep.customer_id
   and plpc.product_id = p.product_id
   and (plpc.sizedefinition_id = s.sizedefinition_id or
       plpc.sizedefinition_id = sizeStarID)
   and plpc.finishingmethod_id = f.finishingmethod_id
   and sqDate between plpc.dateactive and plpc.dateinactive
   and plpc.billingmethod = 3
   and plpc.inventorybillingtype = 1
   and ui.customerowned = 'N'
   and ui.leaseweeks is null
   and dip.costcenter_id = cc.costcenter_id
   and cc.customer_id = cu.customer_id
   and not
        (uinp.freeextragarment = 'Y' and
        (uinp.enddatefreeextra > sqDate or uinp.enddatefreeextra is null))
   and not exists (select t.temporarygarmentrentstop_id
          from temporarygarmentrentstop t
         where t.customer_id = dep.customer_id
           and f_isinyearweeklifespan(startyear,
                                      startweek,
                                      sqYear,
                                      sqWeek,
                                      endyear,
                                      endweek) = 1)
   and ((sqDate < wi.temporaryrentstopstartdate or
       sqDate > temporaryrentstopenddate) or
       (wi.temporaryrentstopstartdate is null and
       wi.temporaryrentstopenddate is null))
   and (wi.season_id is null or exists
        (select sw.season_id
           from seasonweek sw
          where sw.season_id = wi.season_id
            and sw.weeknumber = sqWeek))
   and ((sqDate <= uifi.enddatefullrent and
       plpc.percentageafterdepreciation = 0) or
       (plpc.percentageafterdepreciation > 0))
   and ui.substituteforproduct_id is null --the product is not a substitute
   and ui.substituteforsizedefinition_id is not null --only the size is a substitute
 group by cu.customernumber,
          dip.costcenter_id,
          p.product_id, p.code,s.code, f.code,
          s.sizedefinition_id,
          f.finishingmethod_id;
cursor sqMAxGood is
          select dip.costcenter_id,
       p.product_id,
       s.sizedefinition_id,
       f.finishingmethod_id,
       count(ui.uniqueitem_id) qtyPerPiece
  from uniqueitem             ui,
       uniqueitemfixedinfo    uifi,
       uniqueitemnonpool      uinp,
       weareremployment       we,
       wearerinventory        wi,
       distributionpoint      dip,
       department             dep,
       customeractivities     ca,
       product                p,
       productgroup           pg,
       sizedefinition         s,
       finishingmethod        f,
       productlistpercustomer plpc
 where ui.uniqueitem_id = uinp.uniqueitem_id
   and ui.uniqueitem_id = uifi.uniqueitem_id
   and uinp.weareremployment_id = we.weareremployment_id
   and ui.product_id = p.product_id
   and we.distributionpoint_id = dip.distributionpoint_id
   and dip.department_id = dep.department_id
   and ui.substituteforsizedefinition_id = s.sizedefinition_id
   and ui.finishingmethod_id = f.finishingmethod_id
   and p.productgroup_id = pg.productgroup_id
   and abs(pg.activity_id) = abs(ca.activity_id)
   and dep.customer_id = ca.customer_id
   and uinp.wearerinventory_id = wi.wearerinventory_id
   and abs(ca.processbusinessunit_id) = abs(ui.businessunit_id)
   and ui.status_id = statusUIInCirculation
   and plpc.customer_id = dep.customer_id
   and plpc.product_id = p.product_id
   and (plpc.sizedefinition_id = s.sizedefinition_id or
       plpc.sizedefinition_id = sizeStarID)
   and plpc.finishingmethod_id = f.finishingmethod_id
   and sqDate between plpc.dateactive and plpc.dateinactive
   and plpc.billingmethod = 3
   and plpc.inventorybillingtype = 1
   and ui.customerowned = 'N'
   and ui.leaseweeks is null
   and not
        (uinp.freeextragarment = 'Y' and
        (uinp.enddatefreeextra > sqDate or uinp.enddatefreeextra is null))
   and not exists (select t.temporarygarmentrentstop_id
          from temporarygarmentrentstop t
         where t.customer_id = dep.customer_id
           and f_isinyearweeklifespan(startyear,
                                      startweek,
                                      sqYear,
                                      sqWeek,
                                      endyear,
                                      endweek) = 1)
   and ((sqDate < wi.temporaryrentstopstartdate or
       sqDate > temporaryrentstopenddate) or
       (wi.temporaryrentstopstartdate is null and
       wi.temporaryrentstopenddate is null))
   and (wi.season_id is null or exists
        (select sw.season_id
           from seasonweek sw
          where sw.season_id = wi.season_id
            and sw.weeknumber = sqWeek))
   and ((sqDate <= uifi.enddatefullrent and
       plpc.percentageafterdepreciation = 0) or
       (plpc.percentageafterdepreciation > 0))
   and ui.substituteforproduct_id is null --the product is not a substitute
   and ui.substituteforsizedefinition_id is not null --only the size is a substitute
 group by dip.costcenter_id,
          p.product_id,
          s.sizedefinition_id,
          f.finishingmethod_id;
  begin
   select s.statusquodate, s.year, s.week
   into sqDate, sqYear, sqWeek
   from statusquoheader s
   where s.statusquoheader_id = sqHeaderID;
   select sz.sizedefinition_id
   into sizeStarID
   from sizedefinition sz
   where sz.code = '*';
    select status_id
    into statusUIInCirculation
    from status
    where statustype = 'UI'
    and code = '20';
   fSqlFile := UTL_FILE.FOPEN(UTLDIR, 'SQcorrectionForUpdate.txt', 'a');
   for rsMAxWrong in sqMAx loop
        for rs in sqMAxGood loop
            if (rsMAxWrong.product_id = rs.Product_Id and
                rsMAxWrong.Sizedefinition_Id = rs.Sizedefinition_Id and
                rsMAxWrong.finishingmethod_id = rs.finishingmethod_id and
                rsMAxWrong.costcenter_id = rs.costcenter_id
               ) then
                    sizeFound := true;
                    difference := rsMAxWrong.qtyPerPiece - rs.qtyPerPiece;
                    exit;
                 end if;
        end loop;
        if ( difference > 0 ) then
            update sqmaxitemincirculation sq set sq.qtyrentedperpiece = sq.qtyrentedperpiece - difference
            where sq.statusquoheader_id = sqHeaderID and
                  sq.product_link_id = rsMAxWrong.product_id and
                  sq.sizedefinition_link_id = rsMAxWrong.sizedefinition_id and
                  sq.costcenter_link_id = rsMAxWrong.costcenter_id and
                  sq.finishingmethod_id = rsMAxWrong.finishingmethod_id;
            plpcSearch := false;
            UTL_FILE.PUT(fSqlFile, 'Wrong qty in SQ for :  ');
            UTL_FILE.PUT(fSqlFile, 'customer =');
            UTL_FILE.PUT(fSqlFile,rsMAxWrong.CUSTOMERNUMBER);
            UTL_FILE.PUT(fSqlFile,',size = ');
            UTL_FILE.PUT(fSqlFile,rsMAxWrong.sizeCode);
            UTL_FILE.PUT(fSqlFile,',product = ');
            UTL_FILE.PUT(fSqlFile,rsMAxWrong.productCode);
            UTL_FILE.PUT(fSqlFile,',finishingMethod=');
            UTL_FILE.PUT(fSqlFile,rsMAxWrong.fmCode);
            UTL_FILE.PUT(fSqlFile,',difference in qty =');
            UTL_FILE.PUT(fSqlFile, difference);
            UTL_FILE.PUT_LINE(fSqlFile, '/');
            UTL_FILE.fflush(fSqlFile);
         end if;
   end loop;
   UTL_FILE.FCLOSE(fSqlFile);
end correctionSQMAXUpdate;
/
create or replace procedure CreateNewBatchJobWSP(PlantNumber    in number,
                                                 YearNumber     in number,
                                                 WeekNumber     in number,
                                                 LineNumber     in number,
                                                 SequenceNumber in number,
                                                 Status         out number) is
  BatchNR           number(8);
  plantid           number(28, 0);
  plantdepartmentid number(28, 0);
  systemuserid      number(28, 0);
  cnt               INTeger;
begin
  Status := 0;
  if (length(PlantNumber) > 3 or PlantNumber is null) or
     (length(YearNumber) <> 4 or YearNumber is null) or
     (length(WeekNumber) > 2 or WeekNumber is null or WeekNumber = 0 or
     WeekNumber > 53) or
     (length(LineNumber) > 2 or LineNumber is null or LineNumber = 0) or
     (length(SequenceNumber) > 4 or SequenceNumber is null) then
    Status := 1;
  end if;
  if Status = 0 then
    begin
      begin
        select p.plant_id
          into plantid
          from plant p
         where p.code = to_char(PlantNumber);
      exception
        when no_data_found then
          --    IF @plantid IS NULL
          select min(plant_id) into plantid from plant;
      end;
      if length(WeekNumber) = 2 then
        select count(*)
          into cnt
          from batchjob
         where substr(cast(batchnumber as varchar2(8)), 1, 2) = WeekNumber and
               substr(cast(batchnumber as varchar2(8)), 3, 2) = LineNumber and
               batchjob.year = YearNumber and batchjob.plant_id = plantid and
               substr(cast(batchnumber as varchar2(8)), 5, 4) =
               SequenceNumber;
      end if;
      if length(WeekNumber) = 1 then
        select count(*)
          into cnt
          from batchjob
         where substr(cast(batchnumber as varchar2(7)), 1, 2) = WeekNumber and
               substr(cast(batchnumber as varchar2(7)), 2, 2) = LineNumber and
               batchjob.year = YearNumber and batchjob.plant_id = plantid and
               substr(cast(batchnumber as varchar2(7)), 4, 4) =
               SequenceNumber;
      end if;
      if cnt = 0 then
        begin
          BatchNR := WeekNumber * 1000000 + LineNumber * 10000 +
                     SequenceNumber;
          select pd.plantdepartment_id
            into plantdepartmentid
            from plantdepartment pd
           where pd.code = cast(LineNumber as varchar2(2)) and
                 pd.plant_id = plantid;
        exception
          when no_data_found then
            --     IF @plantdepartmentid IS NULL
            select min(a.plantdepartment_id)
              into plantdepartmentid
              from plantdepartment a
             where a.plant_id = plantid;
        end;
        begin
          select s.systemuser_id
            into systemuserID
            from systemuser s
           where s.username = 'WSP';
        Exception
          when no_data_found then
            -- IF @systemuserID IS NULL
            select min(systemuser_id) into systemuserID from systemuser;
        end;
        begin
          insert into batchjob
            (batchjob_id,
             plant_id,
             plantdepartment_id,
             workstation_id,
             year,
             batchnumber,
             creationdate,
             status,
             systemuser_id,
             timestamp)
          values
            (seq_batchjob.nextval,
             plantid,
             plantdepartmentid,
             null,
             YearNumber,
             BatchNR,
             sysdate,
             1,
             systemuserid,
             sysdate);
        Exception
          when others then
            Status := 1;
        end;
      else
        Status := 1;
      end if;
    end;
  end if;
  if Status = 1 then
    ROLLBACK;
  elsif Status = 0 then
    COMMIT;
  end if;
end CreateNewBatchJobWSP;
/
create or replace procedure CreatePackingnoteSeq(bucode  in businessunit.code%type,
                                                 packseq out integer) is
  SEQ_DELIVERYNOTE_name varchar2(50);
begin
  SEQ_DELIVERYNOTE_name := 'SEQ_DELIVERYNOTE_' || bucode;
  execute immediate 'select ' || SEQ_DELIVERYNOTE_name ||
                    '.nextval from DUAL'
    into packseq;
 /* dbms_output.put_line('nextval' || packseq);
  execute immediate 'select ' || SEQ_DELIVERYNOTE_name ||
                    '.currval from DUAL'
    into packseq;
  dbms_output.put_line('curentval' || packseq);*/
end CreatePackingnoteSeq;
/
create or replace procedure createresidentialinscan(fp_plantid                 in number,
                                                    fp_abslog_processjobpartid in number,
                                                    fp_systemuserid            in number default 0) is
  ---Procedure createresidentialinscan version 0.3
  ---ABS-13785
  ---internal global variables
  gv_userexception exception;
  gv_plantid        plant.plant_id%type := null;
  gv_message        abslog.message%type;
  gv_plantcode      plant.code%type;
  gv_record_counter number := 0;
  gv_stayinscanid   stay.stay_id%type;

  ---internal procedures
  procedure write_log(fp_message in varchar2, fp_priority in number) is
  begin
    --write_log
    if fp_abslog_processjobpartid is null then
      begin
        begin
          abslogwrite.abslog_write(5, 'createresidentialinscan', gv_plantid, fp_priority,
                                   fp_message, fp_systemuserid);
        end;
      end;
    else
      abslogwrite.abslogprocessjobline_write(fp_abslog_processjobpartid, fp_priority, fp_message,
                                             fp_systemuserid);
    end if;
  end write_log;

  procedure initialize is
  begin
    --get plant id
    if fp_plantid is null then
      begin
        gv_message := 'Parameter fp_plantid cannot be left blank';
        raise gv_userexception;
      end;
    else
      begin
        select pt.code into gv_plantcode from plant pt where pt.plant_id = fp_plantid;
      end;
    end if;
    --get stay inscan
    gv_message := 'Get stay 10, inscan for residential';
    select s.stay_id
    into   gv_stayinscanid
    from   stay s
    where  s.staytype = 5
    and    s.staynr = 10;
    write_log('Create Residential Inscans, for plant ' || gv_plantcode, 1);
  end initialize;

  procedure process is
    lv_firstinscantimestamp date;
    lv_scan_count           number;
  begin
    --loop clientdeliverynote that did not start outscan yet
    for x in (select cdn.clientdeliverynote_id, cdn.route_id, cdn.clientdeliverynotenumber,
                     cdn.batch_id, cdn.customer_link_id,
                     (select bc.batchnumber from batch bc where bc.batch_id = cdn.batch_id) batchnumber,
                     clr.departmentroom_id, c.customernumber, cl.clientnumber
              from   clientdeliverynote cdn
              join   businessunit bu
              on     bu.businessunit_id = cdn.processbusinessunit_id
              join   customer c
              on     c.customer_id = cdn.customer_link_id
              join   client cl
              on     cl.client_id = cdn.client_link_id
              left   outer join clientresident clr
              on     clr.client_id = cl.client_id
              where  cdn.closingdate is not null
              and    cdn.closingdate >= sysdate - 7
              and    cdn.inscancreated = 0
              and    bu.plant_id = fp_plantid) loop
      begin
        --reset count
        lv_scan_count := 0;
        --select lv_firstinscantimestamp
        select min(cdls.inscantimestamp)
        into   lv_firstinscantimestamp
        from   clientdelnotelinescan cdls
        join   clientdeliverynoteline cdln
        on     cdln.clientdeliverynoteline_id = cdls.inscanclientdelnoteline_id
        where  cdln.clientdeliverinote_id = x.clientdeliverynote_id;
        if lv_firstinscantimestamp is null then
          lv_firstinscantimestamp := sysdate;
        end if;
        --loop Y clientdelnotelinescan
        for y in (select uri.uniqueresidentialitem_id, uri.businessunit_id, uri.primaryid,
                         uri.client_id, urip.product_id, urip.sizedefinition_id,
                         urip.finishingmethod_id, uri.status_id, cdls.outscanclientdelnoteline_id,
                         cdls.clientdelnotelinescan_id
                  from   clientdelnotelinescan cdls
                  join   clientdeliverynoteline cdl
                  on     cdl.clientdeliverynoteline_id = cdls.outscanclientdelnoteline_id
                  join   uniqueresidentialitem uri
                  on     uri.uniqueresidentialitem_id = cdls.uniqueresidentialitem_link_id
                  join   uniqueresidentialitemproduct urip
                  on     urip.uniqueresidentialitem_id = uri.uniqueresidentialitem_id
                  where  cdl.clientdeliverinote_id = x.clientdeliverynote_id
                  and    cdls.inscanclientdelnoteline_id is null) loop
          begin
            --insert into residentialitemscan
            insert into residentialitemscan
              (residentialitemscan_id, scantimestamp, businessunit_id, primaryid, customer_link_id,
               client_id, departmentroom_id, product_link_id, sizedefinition_link_id,
               finishingmethod_id, status_id, stay_id, scanstation, route_id, year, week, daynumber,
               employeenumber, uniqueresidentialitem_link_id, transactiontype_id, systemuser_id,
               timestamp, batchnumber, clientdeliverynotenumber, batch_id, clientdeliverynoteline_id)
            values
              (seq_residentialitemscan.nextval, lv_firstinscantimestamp /*scantimestamp*/,
               y.businessunit_id /*businessunit_id*/, y.primaryid, x.customer_link_id, y.client_id,
               x.departmentroom_id, y.product_id, y.sizedefinition_id, y.finishingmethod_id,
               y.status_id, gv_stayinscanid, '-' /*scanstation*/, x.route_id,
               getyearofweek(lv_firstinscantimestamp) /*year*/, getisoweek(lv_firstinscantimestamp)
               /*week*/, getabsdaynumber(lv_firstinscantimestamp) /*daynumber*/, 0
               /*employeenumber*/, y.uniqueresidentialitem_id /*uniqueresidentialitem_link_id*/, 1
               /*transactiontype_id*/, fp_systemuserid, sysdate /*timestamp*/, x.batchnumber,
               x.clientdeliverynotenumber, x.batch_id, y.outscanclientdelnoteline_id
               /*clientdeliverynoteline_id*/);
            --count scans
            gv_record_counter := gv_record_counter + 1;
            lv_scan_count     := lv_scan_count + 1;
            --update clientdeliverynoteline
            update clientdeliverynoteline cdl
            set    cdl.qtyscannedin = cdl.qtyscannedin + 1, cdl.timestamp = sysdate,
                   cdl.systemuser_id = fp_systemuserid
            where  cdl.clientdeliverynoteline_id = y.outscanclientdelnoteline_id;
            --update clientdelnotelinescan
            update clientdelnotelinescan cdls
            set    cdls.inscanclientdelnoteline_id = cdls.outscanclientdelnoteline_id,
                   cdls.inscantimestamp = lv_firstinscantimestamp, cdls.timestamp = sysdate,
                   cdls.systemuser_id = fp_systemuserid
            where  cdls.clientdelnotelinescan_id = y.clientdelnotelinescan_id;
          end;
        end loop; --y
        --update clientdeliverynote
        update clientdeliverynote cdn
        set    cdn.inscancreated = 1, cdn.timestamp = sysdate, cdn.systemuser_id = fp_systemuserid
        where  cdn.clientdeliverynote_id = x.clientdeliverynote_id;
        --write log
        write_log('Note Number ' || x.clientdeliverynotenumber || ' Customer ' || x.customernumber ||
                  ' client ' || x.clientnumber || ' inscans created ' || to_char(lv_scan_count), 1);
      end;
    end loop; --x
  end process;

  procedure finalize is
  begin
    --finalize
    commit;
    gv_message := 'Finalize';
    write_log('Successfully ran for plant code ' || gv_plantcode || ' created ' ||
              to_char(gv_record_counter) || ' inscan for outscans', 1);
  end finalize;

begin
  --start main part procedure
  initialize;
  process;
  finalize;
exception
  when gv_userexception then
    begin
      write_log(gv_message, 2);
    end;
  when no_data_found then
    begin
      rollback;
      write_log('Error ' || gv_message || ' no data found', 5);
    end;
  when others then
    begin
      rollback;
      write_log('Error others during ' || gv_message || ' see debug info ' || sqlerrm, 3);
    end;
end createresidentialinscan;
/
create or replace procedure CREATEROUTECONTROLEXTRAINFO(fp_routecontrol_id routecontrol.routecontrol_id%type, fp_user_id systemuser.systemuser_id%type) is

  ---Procedure createroutecontrolextrainfo version 0.1
  ---ABS-157099/ABS-109442 - RSC ExtraInfo needs to be created/updated for virtual routes when RSC is created via PL code

  main_RCid routecontrol.routecontrol_id%type;
  hasRCExtraInfo varchar2(1);
  procedure write_log(fp_message in varchar2) is
  begin
    --write_log
    begin
      abslogwrite.abslog_write(7,
                               'CREATEROUTECONTROLEXTRAINFO',
                               null,
                               5,
                               fp_message,
                               null);
    end;
  end write_log;
begin
  -- check if RC is virtual (has a Main RC)
  begin
     select mainRC.ROUTECONTROL_ID,
            decode(nvl(RCEI.ROUTECONTROL_ID, -1), -1, 'N', 'Y')
            into main_RCid, hasRCExtraInfo
       from ROUTECONTROL mainRC
       join ROUTECONTROL virtualRC
         on mainRC.ORIGINALDRIVINGDATE = virtualRC.ORIGINALDRIVINGDATE
       join ROUTEEXTRAINFO REI
         on virtualRC.ROUTE_ID = REI.ROUTE_ID
       left outer join ROUTECONTROLEXTRAINFO RCEI
         on virtualRC.ROUTECONTROL_ID = RCEI.ROUTECONTROL_ID
      where REI.MAINROUTE_ID = mainRC.ROUTE_ID
        and virtualRC.ROUTECONTROL_ID = fp_routecontrol_id;

    if (hasRCExtraInfo = 'Y') then  -- RC is virtual and already has ExtraInfo - will be updated
      update ROUTECONTROLEXTRAINFO RCEI
         set RCEI.MAINROUTECONTROL_ID = main_RCid,
             rcei.systemuser_id       = fp_user_id,
             rcei.timestamp           = sysdate
       where RCEI.ROUTECONTROL_ID = fp_routecontrol_id;
        write_log('Routecontrol extra info updated for rc_id ' || fp_routecontrol_id || ' and mainroutecontrol id set to ' || main_RCid);
    else  -- RC is virtual and doesn't have ExtraInfo - will be inserted
        insert into routecontrolextrainfo
          (routecontrol_id,
           bulkpackingstatus,
           mainroutecontrol_id,
           systemuser_id,
           timestamp)
        values
          (fp_routecontrol_id,
           1,
           main_RCid,
           fp_user_id,
           sysdate);
           write_log('Routecontrol extra info created for rc_id ' || fp_routecontrol_id || ' and mainroutecontrol id set to ' || main_RCid);
    end if;
  exception
    when no_data_found then -- check if RC is Main and process its virtual RC's
      begin
        for virt_RC in
          (select virtualRC.ROUTECONTROL_ID,
                 decode(nvl(RCEI.ROUTECONTROL_ID, -1), -1, 'N', 'Y') hasRCExtraInfo
            from ROUTECONTROL mainRC
            join ROUTECONTROL virtualRC
              on mainRC.ORIGINALDRIVINGDATE = virtualRC.ORIGINALDRIVINGDATE
            join ROUTEEXTRAINFO REI
              on virtualRC.ROUTE_ID = REI.ROUTE_ID
            left outer join ROUTECONTROLEXTRAINFO RCEI
              on virtualRC.ROUTECONTROL_ID = RCEI.ROUTECONTROL_ID
           where REI.MAINROUTE_ID = mainRC.ROUTE_ID
             and mainRC.ROUTECONTROL_ID = fp_routecontrol_id)
        loop
          if (virt_RC.hasRCExtraInfo = 'Y') then  -- this virtual RC already has ExtraInfo - will be updated
            update ROUTECONTROLEXTRAINFO RCEI
               set RCEI.MAINROUTECONTROL_ID = fp_routecontrol_id,
                   rcei.systemuser_id       = fp_user_id,
                   rcei.timestamp           = sysdate
             where RCEI.ROUTECONTROL_ID = virt_RC.Routecontrol_Id;
             write_log('Routecontrol extra info updated for rc_id ' || virt_RC.Routecontrol_Id || ' and mainroutecontrol id set to ' || fp_routecontrol_id);
          else  -- this virtual RC doesn't have ExtraInfo - will be inserted
              insert into routecontrolextrainfo
                (routecontrol_id,
                 bulkpackingstatus,
                 mainroutecontrol_id,
                 systemuser_id,
                 timestamp)
              values
                (virt_RC.Routecontrol_Id,
                 1,
                 fp_routecontrol_id,
                 fp_user_id,
                 sysdate);
                  write_log('Routecontrol extra info created for rc_id ' || virt_RC.Routecontrol_Id || ' and mainroutecontrol id set to ' || fp_routecontrol_id);
          end if;
        end loop;
      end;
  end;

end CREATEROUTECONTROLEXTRAINFO;
/
create or replace procedure createroutecontrolinternalbu(fp_routecontrol_id routecontrol.routecontrol_id%type, fp_user_id systemuser.systemuser_id%type, fp_plant_id plant.plant_id%type) is
  lv_internal_bu number;
  lv_packing_status number;

  function getPackingStatus(fp_internalbu_id businessunit.businessunit_id%type) return number is
    num_new number;
    num_in_progress number;
    num_printed number;
    num_cancelled number;
    update_pn_status number;
    ret_status number := 1; -- NOT PUT UP = default value
  begin
    select ss.value
      into update_pn_status
      from systemsetting ss
     where ss.plant_id = fp_plant_id
       and ss.name = 'UPDATEPACKINGSTATUS';

    -- number of new PN
    select count(p.packingnote_id) into num_new
      from packingnote p, status s
     where p.status_id = s.status_id
       and p.routecontrol_id = fp_routecontrol_id
       and p.internalprocessingbu_id = fp_internalbu_id
       and s.code = '10';

    -- number of PN in progress
    select count(p.packingnote_id) into num_in_progress
      from packingnote p, status s
     where p.status_id = s.status_id
       and p.routecontrol_id = fp_routecontrol_id
       and p.internalprocessingbu_id = fp_internalbu_id
       and s.code = '20';

    -- number of PN processed
    select count(p.packingnote_id) into num_printed
      from packingnote p, status s
     where p.status_id = s.status_id
       and p.routecontrol_id = fp_routecontrol_id
       and p.internalprocessingbu_id = fp_internalbu_id
       and s.code = '30';

    -- number of PN cancelled
    select count(p.packingnote_id) into num_cancelled
      from packingnote p, status s
     where p.status_id = s.status_id
       and p.routecontrol_id = fp_routecontrol_id
       and p.internalprocessingbu_id = fp_internalbu_id
       and s.code = '40';

    if (num_new + num_in_progress + num_printed = 0) then
      return 1; -- NOT PUT UP
    end if;
    if (num_in_progress > 0) then
      return 3; -- IN PROGRESS
    end if;
    if (num_new > 0 and num_printed = 0) then
      return 2; -- PUT UP
    end if;
    if (num_new > 0 and num_printed > 0) then
      return 3; -- IN PROGRESS
    end if;

    if (num_printed + num_cancelled > 0) then
      if (update_pn_status = 0) then
        return 4; -- COMPLETED
      else
        select decode(count(1), 0, 1, 4) into ret_status from routecontrol rc where rc.routecontrol_id = fp_routecontrol_id and rc.invoicesgenerated = 3;
      end if;
    end if;

    return ret_status;
  end getPackingStatus;

begin
  for st in (
    select distinct ca.internalprocessingbu_id
      from stop s, customeractivities ca
     where ca.customer_id = s.customer_link_id
       and s.routecontrol_id = fp_routecontrol_id
       and ca.internalprocessingbu_id is not null ) loop
    lv_internal_bu := st.internalprocessingbu_id;
    lv_packing_status := getPackingStatus(st.internalprocessingbu_id);

    insert into routecontrolinternalbu rcbu
      (routecontrol_id, internalprocessingbu_id, packingstatus, systemuser_id, timestamp)
      values (fp_routecontrol_id, lv_internal_bu, lv_packing_status, fp_user_id, sysdate);
  end loop;
end createroutecontrolinternalbu;
/
create or replace procedure CreateSerialDevice(
					FPbrandType					serialdevice.brandtype%type,
					FPname							serialdevice.name%type,
					FPdeviceType				serialdevice.devicetype%type,
					FPbaudRate					serialdevice.baudrate%type,
					FPparity						serialdevice.parity%type,
					FPdataBits					serialdevice.databits%type,
					FPstopBits					serialdevice.stopbits%type,
					FPinitString				serialdevice.initstring%type,
					FPinitChar1					serialdevice.initchar1%type,
					FPinitChar2					serialdevice.initchar2%type,
					FPinitChar3					serialdevice.initchar3%type,
					FPverifyString			serialdevice.verifystring%type,
					FPverifyPosition		serialdevice.verifyposition%type,
					FPweightPosition		serialdevice.weightposition%type,
					FPweightStringSize	serialdevice.weightstringsize%type,
					FPweightDecimals		serialdevice.weightdecimals%type,
					FPendCharacter1			serialdevice.endcharacter1%type,
					FPendCharacter2			serialdevice.endcharacter2%type,
					FPalibiPrinter			serialdevice.alibiprinter%type,
					FPalibiInitString		serialdevice.alibiinitstring%type,
					FPalibiEndString		serialdevice.alibiendstring%type,
					FPalibiVerifyString			serialdevice.alibiverifystring%type,
					FPaccuracyLevelWeight		serialdevice.accuracylevelweight%type,
					FPtareInitString				serialdevice.tareinitstring%type,
					FPtareVerifyString			serialdevice.tareverifystring%type,
					FPweightseqnrposition		serialdevice.weightseqnrposition%type,
					FPweightseqnrlength			serialdevice.weightseqnrlength%type
) is
	serialDeviceID	serialdevice.serialdevice_id%type;
begin
	begin
		select serialdevice_id into serialDeviceID from serialdevice where brandtype = FPbrandType;
		update serialdevice set
					name = FPname,
					deviceType = FPdeviceType,
					baudRate = FPbaudRate,
					parity = FPparity,
					dataBits = FPdataBits,
					stopBits = FPstopBits,
					initString = FPinitString,
					initChar1 = FPinitChar1,
					initChar2 = FPinitChar2,
					initChar3 = FPinitChar3,
					verifyString = FPverifyString,
					verifyPosition = FPverifyPosition,
					weightPosition = FPweightPosition,
					weightStringSize = FPweightStringSize,
					weightDecimals = FPweightDecimals,
					endCharacter1 = FPendCharacter1,
					endCharacter2 = FPendCharacter2,
					alibiPrinter = FPalibiPrinter,
					alibiInitString = FPalibiInitString,
					alibiEndString = FPalibiEndString,
					alibiVerifyString = FPalibiVerifyString,
					accuracyLevelWeight = FPaccuracyLevelWeight,
					tareInitString = FPtareInitString,
					tareVerifyString = FPtareVerifyString,
					weightseqnrposition = FPweightseqnrposition,
					weightseqnrlength = FPweightseqnrlength
			where serialdevice_id = serialDeviceID
				and not exists (select serialdevice_id from comportconfiguration
									where serialdevice_id = serialDeviceID);
	exception
		when no_data_found then
			insert into serialdevice (serialdevice_id, brandtype, name, devicetype,
				 	baudrate, parity, databits, stopbits,
				 	initstring, initchar1, initchar2, initchar3, verifystring, verifyposition,
				 	weightposition, weightstringsize, weightdecimals, endcharacter1, endcharacter2,
				 	alibiprinter, alibiinitstring, alibiendstring, alibiverifystring,
				 	accuracylevelweight, tareinitstring, tareverifystring,
					weightseqnrposition, weightseqnrlength)
			values (seq_serialdevice.nextval, FPbrandType, FPname, FPdeviceType,
					FPbaudRate, FPparity, FPdataBits, FPstopBits,
					FPinitString, FPinitChar1, FPinitChar2, FPinitChar3, FPverifyString, FPverifyPosition,
					FPweightPosition, FPweightStringSize, FPweightDecimals, FPendCharacter1, FPendCharacter2,
					FPalibiPrinter, FPalibiInitString, FPalibiEndString, FPalibiVerifyString,
					FPaccuracyLevelWeight, FPtareInitString, FPtareVerifyString,
					FPweightseqnrposition, FPweightseqnrlength);
	end;
	commit;
end CreateSerialDevice;
/
create or replace procedure CreateSettingGroup(
					FPgroupName				settinggroup.groupname%type,
					FPABSAccessOnly		settinggroup.absaccessonly%type,
					FPpassword				settinggroup.password%type
) is
begin
	begin
		insert into settinggroup(groupname, absaccessonly, password)
		values (FPgroupName, FPABSAccessOnly, FPpassword);
		commit;
	exception
		when dup_val_on_index then null;
	end;
end CreateSettingGroup;
/
create or replace procedure createsqresidentialitem(fp_sqdate           in date,
                                                    fp_businessunitcode in varchar2,
                                                    fp_dayslastoutscan  in number default 0,
                                                    fp_systemuserid     in number default 0) is

  /*procedure createsqresidentialitem version 0.4*/
  gv_user_exception exception;
  gv_message        abslog.message%type;
  gv_businessunitid businessunit.businessunit_id%type;
  gv_plantid        plant.plant_id%type;
  gv_year           number;
  gv_week           number;
  gv_sqheaderid     statusquoheader.statusquoheader_id%type;
  gv_rowcount       number;

  --Internal procedures
  procedure write_log(fp_message in varchar2, fp_priority in number) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'createsqresidentialitem', gv_plantid, fp_priority, fp_message, 0);
    begin
      dbms_output.put_line(fp_message);
    exception
      when others then
        null;
    end;
  end write_log;

  procedure intialize is
  begin
    --intialize
    if fp_sqdate is null then
      begin
        gv_message := 'Parameter fp_sqdate cannot be left blank!';
        raise gv_user_exception;
      end;
    end if;
    if fp_sqdate > trunc(sysdate) then
      begin
        gv_message := 'Parameter fp_sqdate cannot be in the future! It is ' ||
                      to_char(fp_sqdate, 'dd-mm-yyyy');
        raise gv_user_exception;
      end;
    end if;
    --get year week
    gv_message := 'get year week from date_yearweekday for date ' ||
                  to_char(fp_sqdate, 'dd-mm-yyyy');
    select dyw.year, dyw.week
    into   gv_year, gv_week
    from   date_yearweekday dyw
    where  dyw.date_ = fp_sqdate;
    --get businessunit id and plant id
    if fp_businessunitcode is null then
      begin
        gv_message := 'Parameter fp_businessunitcode cannot be left blank!';
        raise gv_user_exception;
      end;
    else
      begin
        gv_message := 'get businessunit code ' || fp_businessunitcode;
        select bu.businessunit_id, bu.plant_id
        into   gv_businessunitid, gv_plantid
        from   businessunit bu
        where  bu.code = fp_businessunitcode;
      end;
    end if;
    if nvl(fp_dayslastoutscan, 0) < 0 then
      begin
        gv_message := 'Parameter fp_dayslastoutscan must be positive it is  ' || fp_dayslastoutscan;
        raise gv_user_exception;
      end;
    end if;
  end intialize;

  procedure create_sq_header is
  begin
    --cleanup old sq
    gv_message := 'cleanup old sq';
    delete statusquoheader sh
    where  sh.year = gv_year
    and    sh.week = gv_week
    and    sh.processbusinessunit_id = gv_businessunitid
    and    sh.invoicebusinessunit_id = gv_businessunitid
    and    sh.statusquotype = 15
    and    sh.totalquantity = 0;
    --create_sq_header
    gv_message := 'create_sq_header';
    insert into statusquoheader
      (statusquoheader_id, processbusinessunit_id, invoicebusinessunit_id, statusquodate,
       statusquotype, totalquantity, year, week, month, subtype, abslogprocessjob_id, systemuser_id,
       timestamp)
    values
      (seq_statusquoheader.nextval, gv_businessunitid, gv_businessunitid, fp_sqdate, 15, 0, gv_year,
       gv_week, to_number(to_char(fp_sqdate, 'MM')), 0, null, nvl(fp_systemuserid, 0), sysdate)
    returning statusquoheader_id into gv_sqheaderid;
  exception
    when dup_val_on_index then
      begin
        gv_message := 'statusquo did already run for BU ' || fp_businessunitcode || ' on ' ||
                      to_char(fp_sqdate, 'dd-mm-yyyy');
        raise gv_user_exception;
      end;
  end create_sq_header;

  procedure create_sqresidentialitem is
  begin
    --create_sqresidentialitem
    gv_message := 'create_sqresidentialitem';
    insert into sqresidentialitem
      (sqresidentialitem_id, statusquoheader_id, customer_link_id, client_link_id, product_link_id,
       sizedefinition_link_id, finishingmethod_id, quantity, dayssetting, dayssetting_quantity,
       systemuser_id, timestamp)
      select seq_sqresidentialitem.nextval, gv_sqheaderid, x.customer_id, x.client_id, x.product_id,
             x.sizedefinition_id, x.finishingmethod_id, x.primaryidcount, nvl(fp_dayslastoutscan, 0),
             x.daysx dayssetting_quantity, fp_systemuserid, sysdate
      from   (select c.customer_id, cl.client_id, urp.product_id, urp.sizedefinition_id,
                      urp.finishingmethod_id, count(1) primaryidcount,
                      sum(case
                            when nvl(fp_dayslastoutscan, 0) = 0 then
                             1
                            when ur.lastoutscandate > trunc(sysdate) - fp_dayslastoutscan then
                             1
                            else
                             0
                          end) daysx
               from   uniqueresidentialitemproduct urp
               join   uniqueresidentialitem ur
               on     ur.uniqueresidentialitem_id = urp.uniqueresidentialitem_id
               join   client cl
               on     cl.client_id = ur.client_id
               join   customer c
               on     c.customer_id = cl.customer_id
               where  fp_sqdate between cl.dateactive and cl.dateinactive
               and    fp_sqdate between c.dateactive and c.dateinactive
               and    ur.businessunit_id = gv_businessunitid
               group  by c.defaultbusinessunit_id, c.customer_id, cl.client_id, urp.product_id,
                         urp.sizedefinition_id, urp.finishingmethod_id) x;
    gv_rowcount := sql%rowcount;
  end create_sqresidentialitem;

  procedure finalize is
  begin
    --finalize
    gv_message := 'finalize';
    if nvl(gv_rowcount, 0) > 0 then
      begin
        gv_message := 'Finalize update statusquoheader.totalquantity with ' || to_char(gv_rowcount);
        update statusquoheader sq
        set    sq.totalquantity = gv_rowcount
        where  sq.statusquoheader_id = gv_sqheaderid;
      end;
    end if;
    commit;
    write_log('Ran ok. ' || to_char(nvl(gv_rowcount, 0)) ||
              ' rows added to sqresidentialitem for BU ' || fp_businessunitcode, 1);
  end finalize;
begin
  --intialize
  intialize;
  --create_sq_header
  create_sq_header;
  --create_sqresidentialitem
  create_sqresidentialitem;
  --finalize
  finalize;
exception
  when gv_user_exception then
    begin
      rollback;
      write_log(gv_message, 3);
    end;
  when no_data_found then
    begin
      rollback;
      write_log('No data found ' || gv_message, 3);
    end;
  when others then
    begin
      rollback;
      write_log(sqlerrm || ' ' || gv_message, 3);
    end;
end createsqresidentialitem;
/
create or replace procedure CreateSystemSetting
(
  fpgroupname      systemsetting.groupname%type,
  fpname           systemsetting.name%type,
  fpvalue          systemsetting.value%type,
  fptypeofvalue    systemsetting.typeofvalue%type,
  fpfactorydefault systemsetting.factorydefault%type,
  fpdefaultallowed systemsetting.defaultallowed%type,
  fpusedasdefault  systemsetting.usedasdefault%type,
  fpminvalue       systemsetting.minvalue%type,
  fpmaxvalue       systemsetting.maxvalue%type,
  fpallowedchars   systemsetting.allowedchars%type,
  fpdescription    long,
  fpisobsolete     varchar2
) is
  systemuserid   int := 0;
  activevalue    varchar2(1);
  oldtypeofvalue systemsetting.typeofvalue%type;
  oldvalue       systemsetting.value%type;
begin

  execute immediate 'alter session set nls_territory = america';
  if fpisobsolete = 'Y' then
    activevalue := 'N';
  else
    activevalue := 'Y';
  end if;

  for vcursor in (select plant_id from plant)
  loop
    begin
      insert into systemsetting
        (plant_id,
         groupname,
         name,
         value,
         typeofvalue,
         factorydefault,
         defaultallowed,
         usedasdefault,
         minvalue,
         maxvalue,
         allowedchars,
         description,
         systemuser_id,
         timestamp,
         active)
      values
        (vcursor.plant_id,
         fpgroupname,
         fpname,
         fpvalue,
         fptypeofvalue,
         fpfactorydefault,
         fpdefaultallowed,
         fpusedasdefault,
         fpminvalue,
         fpmaxvalue,
         fpallowedchars,
         fpdescription,
         systemuserid,
         sysdate,
         activevalue);
    exception
      when dup_val_on_index then

        select typeofvalue, value
        into   oldtypeofvalue, oldvalue
        from   systemsetting
        where  plant_id = vcursor.plant_id
               and name = fpname;

        update systemsetting
        set    groupname      = fpgroupname,
               typeofvalue    = fptypeofvalue,
               factorydefault = fpfactorydefault,
               defaultallowed = fpdefaultallowed,
               minvalue       = fpminvalue,
               maxvalue       = fpmaxvalue,
               allowedchars   = fpallowedchars,
               description    = fpdescription,
               timestamp      = sysdate,
               systemuser_id  = systemuserid,
               active         = activevalue
        where  plant_id = vcursor.plant_id
               and name = fpname
               and
               (groupname != fpgroupname or typeofvalue != fptypeofvalue or
               factorydefault != fpfactorydefault or
               defaultallowed != fpdefaultallowed or
               minvalue != fpminvalue or maxvalue != fpmaxvalue or
               allowedchars != fpallowedchars or
               description != fpdescription or active != activevalue);

        -- update the value if the type of value was changed
        if (((oldtypeofvalue != fptypeofvalue) and
           ((fpname = 'defaultcustomermin') or
           (fpname = 'defaultcustomermax')) and
           (oldvalue > fpmaxvalue or oldvalue < fpminvalue)) or
           ((oldtypeofvalue != fptypeofvalue) and
           (fpname != 'defaultcustomermin') and
           (fpname != 'defaultcustomermax') and
           (fpname != 'PDAFORCESTOCKCNTMINQTY') and
           (fpname != 'DELNOTEWARNINGLEVEL'))) then
          update systemsetting
          set    value = fpvalue
          where  plant_id = vcursor.plant_id
                 and name = fpname;
        end if;

    end;
  end loop;
  commit;
  dbms_output.put_line('restart server before ' || fpname ||
                       ' setting takes effect.');
end createsystemsetting;
/
create or replace procedure create_avgpurchaseprice(fp_stockroomid         in stockroom.stockroom_id%type,
                                                    fp_transactiontype     in stockvalueavgpp.transactiontype%type default 1,
                                                    fp_origin              in stockvalueavgpp.origin%type default 1,
                                                    fp_productid           in product.product_id%type,
                                                    fp_sizedefinitionid    in sizedefinition.sizedefinition_id%type,
                                                    fp_qualitygradeid      in qualitygrade.qualitygrade_id%type,
                                                    fp_customerowned       in stockvalueavgpp.customerowned%type default 'N',
                                                    fp_customerid          in stockvalueavgpp.customer_link_id%type default null,
                                                    fp_purchaseprice       in stockvalueavgpp.purchaseprice%type,
                                                    fp_currencyid          in stockvalueavgpp.purchase_currency_id%type,
                                                    fp_purchaseordernumber in stockvalueavgpp.purchaseordernumber%type default null,
                                                    fp_purchaseorderlineid in purchaseorderline.purchaseorderline_id%type default null,
                                                    fp_stocktransactionid  in stockvalueavgpp.stocktransaction_id%type,
                                                    fp_reasoncodeid        in stockvalueavgpp.reasoncode_id%type,
                                                    fp_systemuserid        in stockvalueavgpp.systemuser_id%type,
                                                    fp_resultmessage       out varchar2) is
  /*create_avgpurchaseprice version 0.5
  Update: 21/03/2023 - ABS-148698 , version 0.6*/
  gv_userexception exception;
  gv_stockreservationpergradeid stockreservationpergrade.stockreservationpergrade_id%type;
  gv_row_stockvalueavgpp        stockvalueavgpp%rowtype;
  gv_transportchargepercentage  aggsupplierorderingterms.transportchargepercentage%type;
  gv_stockvalue                 number;
  gv_row_purchaseorderline      purchaseorderline%rowtype;
  gv_old_exchangerate           currency.exchangerate%type;
  gv_currency_decimals          currency.decimals%type;

  procedure write_log(fp_message in abslog.message%type, fp_priority in abslog.priority%type) is
  begin
    /*
    Write message in ABSLOG with these priorities
    1 = Message
    2 = Warning
    3 = Error
    4 = Stack trace
    5 = Debug info
    */
    abslogwrite.abslog_write(5, 'create_avgpurchaseprice', null, fp_priority, fp_message,
                             fp_systemuserid);
  end write_log;

  function get_exchangerate return number is
    lv_exchangerate currencyexchangerate.exchangerate%type;
  begin
    --get_exchangerate
    if gv_row_stockvalueavgpp.stockvalue_currency_id = fp_currencyid then
      return 1;
    else
      begin
        --new method
        select cxr.exchangerate
        into   lv_exchangerate
        from   currencyexchangerate cxr
        where  cxr.basecurrency_id = gv_row_stockvalueavgpp.stockvalue_currency_id
        and    cxr.exchangecurrency_id = fp_currencyid
        and    cxr.startdate = (select max(xx.startdate)
                                from   currencyexchangerate xx
                                where  xx.basecurrency_id = cxr.basecurrency_id
                                and    xx.exchangecurrency_id = cxr.exchangecurrency_id
                                and    xx.startdate <= sysdate);
      exception
        when no_data_found then
          begin
            lv_exchangerate := gv_old_exchangerate;
          end;
      end;
    end if;
    return nvl(lv_exchangerate, 1);
  end get_exchangerate;

  procedure initialize is
  begin
    --initialize
    --check fp_transactiontype
    /*
    1 = Receive in Stock(stock increase)
    2 = Remove from Stock(stock decrease)
    3 = Administrative transaction (price change)
    */
    if nvl(fp_transactiontype, 1) not in (1, 2, 3) then
      begin
        fp_resultmessage := 'fp_transactiontype ' || nvl(to_char(fp_transactiontype), 'NULL') ||
                            ' must be 1,2 or 3!';
        raise gv_userexception;
      end;
    end if;
    gv_row_stockvalueavgpp.transactiontype := nvl(fp_transactiontype, 1);
    --check fp_origin
    /*
    TRANSACTIONTYPE=1(Receive in Stock):
    1 = Receive via PO
    2 = Receive without PO
    3 = Return to Stock
    4 = Stock correction
    5 = Grade change (Used to New)
    6 = Grade changed (Defect to New)
    7 = Receive via IPO
    TRANSACTIONTYPE=2(Remove from Stock):
    1=Return to Supplier
    TRANSACTIONTYPE=3(Administrative transaction):
    0=Initial fill
    9 = Inventory Value Charge
    */
    case nvl(fp_transactiontype, 1)
      when 1 then
        if nvl(fp_origin, 1) not in (1, 2, 3, 4, 5, 6, 7) then
          begin
            fp_resultmessage := 'fp_transactiontype = 1 then fp_origin ' ||
                                nvl(to_char(fp_origin), 'NULL') || ' must be 1,2,3,4,5,6 or 7!';
            raise gv_userexception;
          end;
        end if;
      when 2 then
        if nvl(fp_origin, 0) not in (1) then
          begin
            fp_resultmessage := 'fp_transactiontype = 1 then fp_origin ' ||
                                nvl(to_char(fp_origin), 'NULL') || ' must be 1!';
            raise gv_userexception;
          end;
        end if;
      when 3 then
        if nvl(fp_origin, 999) not in (0, 9) then
          begin
            fp_resultmessage := 'fp_origin ' || nvl(to_char(fp_origin), 'NULL') ||
                                ' must be 0 or 9!';
            raise gv_userexception;
          end;
        end if;
      else
        begin
          fp_resultmessage := 'fp_transactiontype ' || nvl(to_char(fp_transactiontype), 'NULL') ||
                              ' must be 1,2 or 3!';
          raise gv_userexception;
        end;
    end case;
    gv_row_stockvalueavgpp.origin := nvl(fp_origin, 1);
    --fp_stockroomid
    if fp_stockroomid is null then
      begin
        fp_resultmessage := 'Parameter fp_stockroomid cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        fp_resultmessage := 'fp_stockroomid ' || fp_stockroomid;
        select ct.defaultcurrency_id
        into   gv_row_stockvalueavgpp.stockvalue_currency_id
        from   stockroom sr
        join   businessunit bu
        on     bu.businessunit_id = sr.managedbybu_id
        join   plant pt
        on     pt.plant_id = bu.plant_id
        join   country ct
        on     ct.country_id = pt.country_id
        where  sr.stockroom_id = fp_stockroomid;
      end;
    end if;
    --fp_productid
    if fp_productid is null then
      begin
        fp_resultmessage := 'Parameter fp_productid cannot be left blank!';
        raise gv_userexception;
      end;
    end if;
    --fp_sizedefinitionid
    if fp_sizedefinitionid is null then
      begin
        fp_resultmessage := 'Parameter fp_sizedefinitionid cannot be left blank!';
        raise gv_userexception;
      end;
    end if;
    --fp_qualitygradeid
    if fp_qualitygradeid is null then
      begin
        fp_resultmessage := 'Parameter fp_qualitygradeid cannot be left blank!';
        raise gv_userexception;
      end;
    end if;
    --fp_purchaseprice
    if fp_purchaseprice is null then
      begin
        fp_resultmessage := 'Parameter fp_purchaseprice cannot be left blank!';
        raise gv_userexception;
      end;
    end if;
    --fp_currencyid
    if fp_currencyid is null then
      begin
        fp_resultmessage := 'Parameter fp_currencyid cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        --old method for exchangerate
        fp_resultmessage := 'Parameter fp_currencyid ' || fp_currencyid;
        select nvl(cr.exchangerate, 1), coalesce(cr.decimals, 2)
        into   gv_old_exchangerate, gv_currency_decimals
        from   currency cr
        where  cr.currency_id = fp_currencyid;
      end;
    end if;
    --fill values
    fp_resultmessage                              := 'fill values';
    gv_row_stockvalueavgpp.transactiondate        := sysdate; --todays transaction
    gv_row_stockvalueavgpp.stockroom_id           := fp_stockroomid;
    gv_row_stockvalueavgpp.product_link_id        := fp_productid;
    gv_row_stockvalueavgpp.sizedefinition_link_id := fp_sizedefinitionid;
    gv_row_stockvalueavgpp.qualitygrade_id        := fp_qualitygradeid;
    gv_row_stockvalueavgpp.customerowned          := nvl(fp_customerowned, 'N');
    gv_row_stockvalueavgpp.customer_link_id       := fp_customerid;
    gv_row_stockvalueavgpp.purchaseprice          := fp_purchaseprice;
    gv_row_stockvalueavgpp.purchase_currency_id   := fp_currencyid;
    gv_row_stockvalueavgpp.systemuser_id          := fp_systemuserid;
    gv_row_stockvalueavgpp.timestamp              := sysdate;
    gv_row_stockvalueavgpp.purchaseordernumber    := fp_purchaseordernumber;
    gv_row_stockvalueavgpp.reasoncode_id          := fp_reasoncodeid;
    gv_row_stockvalueavgpp.stocktransaction_id    := fp_stocktransactionid;
    gv_row_stockvalueavgpp.exported               := 'N';
    gv_row_stockvalueavgpp.erpexport              := 'N';
    gv_row_stockvalueavgpp.exchangerate           := get_exchangerate;
    gv_row_stockvalueavgpp.piecevalue             := round((fp_purchaseprice *
                                                           nvl(gv_row_stockvalueavgpp.exchangerate,
                                                                1)), gv_currency_decimals);
    --get gv_row_purchaseorderline
    if fp_purchaseorderlineid is null then
      begin
        gv_row_purchaseorderline := null;
      end;
    else
      begin
        fp_resultmessage := 'purchaseorderline_id ' || fp_purchaseorderlineid;
        select pol.*
        into   gv_row_purchaseorderline
        from   purchaseorderline pol
        where  pol.purchaseorderline_id = fp_purchaseorderlineid;
      end;
    end if;
  end initialize;

  procedure process_data is
  begin
    --process_data
    --check fp_stocktransactionid for stockreservationpergrade_id, quantity, reasoncode_id
    fp_resultmessage := 'stocktransaction_id ' || nvl(to_char(fp_stocktransactionid), 'NULL');
    select st.stockreservationpergrade_id,
           nvl(gv_row_stockvalueavgpp.reasoncode_id, st.reasoncode_id), st.quantity
    into   gv_stockreservationpergradeid, gv_row_stockvalueavgpp.reasoncode_id,
           gv_row_stockvalueavgpp.quantity
    from   stocktransaction st
    where  st.stocktransaction_id = fp_stocktransactionid;
    --f_getavgpurchaseprice to get prevavgpurchaseprice
    fp_resultmessage := 'f_getavgpurchaseprice for stockreservationpergrade_id ' ||
                        gv_stockreservationpergradeid;
    --
    gv_row_stockvalueavgpp.prevavgpurchaseprice := f_getavgpurchaseprice(gv_stockreservationpergradeid);
    --get actualstockquantity
    fp_resultmessage := 'get actualstockquantity';
    select sum(q.qtyunique + q.qtyuniquewithmodifications + q.qtynonunique)
    into   gv_row_stockvalueavgpp.actualstockquantity
    from   stockquantity q
    where  q.stockreservationpergrade_id = gv_stockreservationpergradeid;
    --calculate gv_row_stockvalueavgpp.quantity
    fp_resultmessage                    := 'calculate gv_row_stockvalueavgpp.quantity';
    gv_row_stockvalueavgpp.prevstockqty := gv_row_stockvalueavgpp.actualstockquantity -
                                           gv_row_stockvalueavgpp.quantity;
    --
    /*
    Determine transport cost percentage as defined on supplier product
    M_TransportChargePercentage = AggSupplierOrderingTerms.TransportChargePercentage
    */
    fp_resultmessage := 'Determine transport cost percentage';
    if (fp_purchaseorderlineid is null or gv_row_purchaseorderline.supplierorderingterms_id is null) then
      begin
        gv_transportchargepercentage := 0;
      end;
    else
      begin
        select asot.transportchargepercentage
        into   gv_transportchargepercentage
        from   aggsupplierorderingterms asot
        where  asot.supplierorderingterms_id = gv_row_purchaseorderline.supplierorderingterms_id;
      exception
        when no_data_found then
          gv_transportchargepercentage := 0;
      end;
    end if;
    /*
    M_StockValue =  (M_QtyCheckedIn * M_PieceValue) * ((100 + M_TransportChargePercentage) / 100)
                    + (M_PrevQtyStock * M_PrevAvgPrice)
    */
    fp_resultmessage := 'get stock value';
    gv_stockvalue    := (gv_row_stockvalueavgpp.quantity * gv_row_stockvalueavgpp.piecevalue) *
                        ((100 + gv_transportchargepercentage) / 100) +
                        (gv_row_stockvalueavgpp.prevstockqty *
                        gv_row_stockvalueavgpp.prevavgpurchaseprice);
    --M_NewAvgPrice = M_StockValue / M_TotalQtyStock
    fp_resultmessage                        := 'Get new avgpurchaseprice';
    if(gv_row_stockvalueavgpp.actualstockquantity = 0) then
      gv_row_stockvalueavgpp.avgpurchaseprice := gv_stockvalue;
    else
      gv_row_stockvalueavgpp.avgpurchaseprice := gv_stockvalue /
                                               gv_row_stockvalueavgpp.actualstockquantity;
     end if;
    --get stockvalueavgpp_id
    fp_resultmessage                          := 'Get seq_stockvalueavgpp.nextval';
    gv_row_stockvalueavgpp.stockvalueavgpp_id := seq_stockvalueavgpp.nextval;
    --insert into stockvalueavgpp
    fp_resultmessage := 'Insert into stockvalueavgpp';
    insert into stockvalueavgpp values gv_row_stockvalueavgpp;
  end process_data;

  procedure finalize is
  begin
    --finalize
    commit;
    fp_resultmessage := 'Ok';
  end finalize;
begin
  --initialize
  initialize;
  --process_data
  process_data;
  --finalize
  finalize;
exception
  --error handling messages
  when gv_userexception then
    begin
      rollback;
      write_log(fp_resultmessage, 3);
    end;
  when no_data_found then
    begin
      rollback;
      fp_resultmessage := fp_resultmessage || ' does not exist.';
      write_log(fp_resultmessage, 3);
    end;
  when others then
    begin
      rollback;
      fp_resultmessage := sqlerrm || ' ' || fp_resultmessage;
      write_log(fp_resultmessage, 5);
    end;
end create_avgpurchaseprice;
/
create or replace procedure create_erp_transaction_log is
  lv_createview clob;

  procedure write_log(fp_message in varchar2, fp_priority in number) is
  begin
    /* Logging: write message in ABSLOG with these priorities for fp_priority:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'erp_transaction_log', null, fp_priority, fp_message);
    begin
      dbms_output.put_line(fp_message);
    exception
      when others then
        null;
    end;
  end write_log;
begin
  --select all log tables
  for x in (select 'select ''' || t.table_name ||
                    ''' erp_tablename, transfer_id, transfer_status, text, process_status, timestamp from ' ||
                    t.table_name || ' 
union all
' createview
            from   user_tables t
            where  substr(t.table_name, 1, 4) = 'ERP_'
            and    substr(t.table_name, -3) = 'LOG'
            and    t.table_name not in ('ERP_TRANSACTION_LOG')
            order  by t.table_name) loop
    begin
      lv_createview := lv_createview || x.createview;
    end;
  end loop; --x
  lv_createview := 'CREATE OR REPLACE VIEW ERP_TRANSACTION_LOG AS ' || upper(lv_createview) ||
                   'SELECT ''ABSLOG'' ERP_TABLENAME, L.ABSLOG_ID TRANSFER_ID, 0 TRANSFER_STATUS, L.MESSAGE TEXT,
       CASE
         WHEN L.PRIORITY > 1 THEN
          1
         ELSE
          0
       END PROCESS_STATUS, L.TIMESTAMP
FROM   ABSLOG L
WHERE  L.LOGTYPE = 5
AND    L.LOGSOURCE = ''ERP_Interface''';
  --create a_table based on fp_tablename with name fp_audit_tablename
  execute immediate lv_createview;
  --write log
  write_log('Created erp_transaction_log', 1);
exception
  --exception handling
  when others then
    begin
      write_log('Error; ' || sqlerrm, 3);
      raise;
    end;
end create_erp_transaction_log;

/
create or replace procedure create_invoiceheaderxml(fp_businessunitcode in varchar2,
                                                    fp_systemuserid     in number,
                                                    fp_daysback         in number default 33) is
  /*procedure create_invoiceheaderxml version 1.0*/
  --typically scheduled daily. Min. schedule once a week
  gv_user_exception exception;
  gv_message        abslog.message%type;
  gv_plantid        plant.plant_id%type;
  gv_businessunitid businessunit.businessunit_id%type;
  gv_counter        number := 0;
  gv_no_xml         number := 0;
  gv_tmc_xml        clob;
  gv_status         number;

  procedure write_log(fp_message  in abslog.message%type,
                      fp_priority in abslog.priority%type default 1) is
  begin
    /*
    Write message in ABSLOG with these priorities
    1 = Message
    2 = Warning
    3 = Error
    4 = Stack trace
    5 = Debug info
    */
    abslogwrite.abslog_write(5, 'create_invoiceheaderxml', gv_plantid, fp_priority, fp_message,
                             fp_systemuserid);
    begin
      dbms_output.put_line(fp_message);
    exception
      when others then
        null; --cannot produce output but its in ABSLOG as well
    end;
  end write_log;

  procedure initialize is
  begin
    --initialize
    if fp_businessunitcode is null then
      begin
        gv_message := 'parameter businessunit cannot be left blank';
        raise gv_user_exception;
      end;
    else
      begin
        gv_message := 'businessunit code ' || fp_businessunitcode;
        select bu.businessunit_id, bu.plant_id
        into   gv_businessunitid, gv_plantid
        from   businessunit bu
        where  bu.code = fp_businessunitcode;
      end;
    end if;
  end initialize;

  procedure fix_invoicelines(fp_invoiceheaderid in number,
                             fp_countryid       in number,
                             fp_taxexemptcode   in varchar2) is
    lv_linenumber number := 9599;

    procedure addmissing_vatcode is
      lv_taxgroupcode varchar2(3) := 'AE';
      lv_taxgroupid   number;
    begin
      --addmissing_vatcode
      update invoiceline il
      set    il.taxgroupcode = lv_taxgroupcode
      where  il.taxgroupcode is null
      and    il.invoiceheader_id = fp_invoiceheaderid
      and    il.invoicelinetype_id <> 18;
      if sql%rowcount > 0 then
        begin
          select max(tx.taxgroup_id)
          into   lv_taxgroupid
          from   taxgroup tx
          where  tx.code = lv_taxgroupcode
          and    tx.country_id = fp_countryid;
          if lv_taxgroupid is null then
            begin
              insert into taxgroup
                (taxgroup_id, timestamp, systemuser_id, startdatetaxrate, oldtaxrate, taxrate,
                 active, description, code, country_id, turnovergroup_id)
              values
                (-23, sysdate, 1, trunc(sysdate - 33), 0, 0, 'Y',
                 'Tax Exemption ' || fp_taxexemptcode, lv_taxgroupcode, fp_countryid, null);
            end;
          end if;
        end;
      end if;
    end addmissing_vatcode;

    procedure create_invoiceline(fp_linenumber        in number,
                                 fp_code              in varchar2,
                                 fp_description       in varchar2,
                                 fp_amount            in number,
                                 fp_taxgroupcode      in varchar2,
                                 fp_taxrate           in number,
                                 fp_invoicelinetypeid in number,
                                 fp_turnovergroupid   in number,
                                 fp_overamount        in number,
                                 fp_systemuserid      in number) is
      lv_invoicelineid number;
    begin
      insert into invoiceline
        (invoiceline_id, invoiceheader_id, linenumber, invoicelinetype_id, code, description,
         adjustedamount, adjustedprice, adjustmentbilledqty, extend, amount, discountpercentage,
         price, billedqty, taxgroupcode, subjecttominimum, turnovergroup_id, systemuser_id,
         timestamp, taxtype, remark, generated, invoicelinesubtype)
      values
        (fp_linenumber * -1, fp_invoiceheaderid, fp_linenumber, fp_invoicelinetypeid, fp_code,
         fp_description, 0, 0, 0, 'Y', fp_amount, 0, 0, 0, fp_taxgroupcode, 'N', fp_turnovergroupid,
         fp_systemuserid, sysdate, 0, null, 'Y', 0)
      returning invoiceline_id into lv_invoicelineid;
      --
      insert into invoicelinevarious
        (invoiceline_id, percentage, timestamp, systemuser_id, overamount, minimumamount,
         maximumamount, taxauthoritytype)
      values
        (lv_invoicelineid, fp_taxrate, sysdate, fp_systemuserid, fp_overamount, 0, 0, 0);
    end create_invoiceline;

    procedure create_zero_vatline is
      lv_taxgroupid      number;
      lv_tax_description varchar2(80);
      lv_taxrate         number(7, 3);
      lv_taxgroupcode    varchar2(10);
      lv_turnovergroupid number;
    begin
      for zz in (select il.taxgroupcode, min(il.systemuser_id) systemuser_id,
                        sum(il.amount) overamount
                 from   invoiceline il
                 where  il.taxgroupcode is not null
                 and    il.invoiceheader_id = fp_invoiceheaderid
                 and    il.invoicelinetype_id <> 18 -- do not check tax lines
                 and    il.extend = 'Y'
                 and    not exists (select 1
                         from   invoiceline ilt
                         where  ilt.invoiceheader_id = il.invoiceheader_id
                         and    ilt.invoicelinetype_id = 18
                         and    ilt.code = il.taxgroupcode)
                 group  by il.taxgroupcode) loop
        begin
          --get taxgroup id
          select tx.taxgroup_id, tx.description, tx.turnovergroup_id, tx.taxrate
          into   lv_taxgroupid, lv_tax_description, lv_turnovergroupid, lv_taxrate
          from   taxgroup tx
          where  tx.code = zz.taxgroupcode
          and    tx.country_id = fp_countryid;
          --
          lv_linenumber   := lv_linenumber + 1;
          lv_taxgroupcode := zz.taxgroupcode;
          --
          create_invoiceline(lv_linenumber, lv_taxgroupcode, lv_tax_description, 0, lv_taxgroupcode,
                             lv_taxrate, 18, lv_turnovergroupid, zz.overamount, zz.systemuser_id);
        end;
      end loop;
    end create_zero_vatline;

    procedure check_discount_line is
      lv_vatamountheader          number;
      lv_discount                 number;
      lv_totalamountexclvat       number;
      lv_taxrate                  number(7, 3);
      lv_taxgroupcode             varchar2(10);
    begin
      --check_discount_line
      select (ih.paythisamount - ih.totalamountexclvat) vatamountheader, ih.creditsqueezeamount,
             ih.totalamountexclvat
      into   lv_vatamountheader, lv_discount, lv_totalamountexclvat
      from   invoiceheader ih
      join   customer c
      on     c.customer_id = ih.deltocustomer_link_id
      join   customer c
      on     c.customer_id = ih.deltocustomer_link_id
      where  ih.invoiceheader_id = fp_invoiceheaderid;
      if lv_discount <> 0 then
        begin
          --
          select max(tx.taxrate) taxrate, max(tx.code)
          into   lv_taxrate, lv_taxgroupcode
          from   invoiceline il
          join   taxgroup tx
          on     tx.code = il.taxgroupcode
          and    tx.country_id = fp_countryid
          where  il.invoiceheader_id = fp_invoiceheaderid
          and    il.invoicelinetype_id <> 18
          and    il.extend = 'Y';
          --
          if round((lv_totalamountexclvat + lv_discount) * lv_taxrate / 100, 2) -
             round(lv_vatamountheader, 2) = 0 then
            begin
              update invoiceheader ih
              set    ih.peppol_amount_correction = lv_discount*-1, ih.deltostate = lv_taxgroupcode,
                     ih.deltocounty = to_char(lv_taxrate)
              where  ih.invoiceheader_id = fp_invoiceheaderid;
            end;
          end if;
        end;
      end if;
    end check_discount_line;
  begin
    --make each line use vatcode
    addmissing_vatcode;
    --create_zero_vatline
    create_zero_vatline;
    --check discount line
    check_discount_line;
  end fix_invoicelines;

  procedure get_xml_rollback(fp_invoiceheaderid in number) is
  begin
    --get_xml_rollback
    --create xml for invoice
    select vx.tmc_xml
    into   gv_tmc_xml
    from   v_xml_peppol_billing vx
    where  vx.invoiceheader_id = fp_invoiceheaderid;
    if gv_tmc_xml is not null then
      begin
        gv_status  := 0;
        gv_counter := gv_counter + 1;
      end;
    else
      begin
        gv_status := 1;
        gv_no_xml := gv_no_xml + 1;
      end;
    end if;
    rollback;
  exception
    when no_data_found then
      begin
        rollback;
        gv_tmc_xml := 'NULL';
        gv_status  := 1;
        gv_no_xml  := gv_no_xml + 1;
      end;
  end get_xml_rollback;
begin
  --initialize
  initialize;
  --export into invoiceheaderxml
  gv_message := 'export into invoiceheaderxml';
  for x in (select ih.invoiceheader_id, c.country_id, c.taxexemptcode
            from   invoiceheader ih
            join   customer c
            on     c.customer_id = ih.billtocustomer_link_id
            where  ih.documenttype = 1
            and    ih.paythisamount <> 0
            and    ih.status_id = (select st.status_id
                                   from   status st
                                   where  st.code = '2'
                                   and    st.statustype = 'IN')
            and    (ih.parentinvoiceheader_id is null or
                  ih.parentinvoiceheader_id = ih.invoiceheader_id)
            and    ih.invoicebusinessunit_id = gv_businessunitid
            and    ih.creationtimestamp >= trunc(sysdate - nvl(fp_daysback, 33)) --this runs daily, min. once a month
            and    not exists (select 1
                    from   invoiceheaderxml ihx
                    where  ihx.invoiceheader_id = ih.invoiceheader_id)
            order  by ih.invoiceheader_id asc) loop
    begin
      --add 0 vat lines, add discount lines if needed
      fix_invoicelines(x.invoiceheader_id, x.country_id, x.taxexemptcode);
      --get_xml_rollback
      get_xml_rollback(x.invoiceheader_id);
      --add xml to header
      gv_message := 'add xml to header';
      insert into invoiceheaderxml
        (invoiceheader_id, invoicedata, status, systemuser_id, timestamp)
      values
        (x.invoiceheader_id, gv_tmc_xml, gv_status, nvl(fp_systemuserid, 1), sysdate);
      commit;
    exception
      when no_data_found then
        begin
          rollback;
          write_log('No data found ' || gv_message || ' for invoiceheader_id ' ||
                    to_char(x.invoiceheader_id), 3);
        end;
      when others then
        begin
          rollback;
          write_log(sqlerrm || ' for invoiceheader_id ' || to_char(x.invoiceheader_id), 3);
        end;
    end;
  end loop; --xinvoiceheader_id
  if gv_counter = 0 and gv_no_xml = 0 then
    begin
      write_log('Ran succesfully nothing inserted into invoiceheaderxml');
    end;
  else
    begin
      write_log('Succesfully ran, ' || to_char(gv_counter) || ' XMLs exported. ' ||
                to_char(gv_no_xml) || ' invoices with no XML');
    end;
  end if;
exception
  when gv_user_exception then
    begin
      rollback;
      write_log(gv_message, 3);
    end;
  when no_data_found then
    begin
      rollback;
      write_log('No data found ' || gv_message, 3);
    end;
  when others then
    begin
      rollback;
      write_log(sqlerrm || ' for businessunit code ' || fp_businessunitcode, 3);
    end;
end create_invoiceheaderxml;
/
create or replace procedure dbm_check_container(fp_container_primaryid in varchar2,
                                                fp_scanstation         in varchar2) is
  /*procedure DBM_Check_Container version 0.2*/
  --27-Jan-2023 ABS-113854 Interface with DBM picking robot for loading containers
  pragma udf;
  gv_counter number;
begin
  select count(1) into gv_counter from container cr where cr.primaryid = fp_container_primaryid;
  delete from dbm_container_result x where x.scanstation = fp_scanstation;
  insert into dbm_container_result
  values
    (fp_container_primaryid, fp_scanstation, case when gv_counter = 1 then 0 else 1 end, 1, sysdate);
  commit;
exception
  when others then
    begin
      abslogwrite.abslog_write(5, 'DBM_Check_Container', null, 3,
                               sqlerrm || ' while lookup fp_container_primaryid ' ||
                                nvl(fp_container_primaryid, 'left blank'));
    end;
end dbm_check_container;
/
create or replace procedure dbm_sendtrack(fp_container_primaryid in varchar2,
                                          fp_scanstation         in varchar2,
                                          fp_number_of_garments  in number,
                                          fp_last_item_batch     in number) is

  /*procedure DBM_Sendtrack version 0.7*/
  --25-Jan-2023 ABS-113854 Interface with DBM picking robot for loading containers
  --may 2023  changes to work without OUT parameters in procedure, use a table instead
  --sep 2023  bug in deliveryhistory fixed
  --okt 2023  fix for wrongly determined deliveryday
  --nov 2023  changed type of container scan
  -- ABSN-5713 DBMSENDTRACK clear message when customer has no route

  pragma udf;
  --Global variables
  gv_userexception          exception;
  gv_systemuserid           number := 0;
  gv_message                abslog.message%type;
  gv_plantid                plant.plant_id%type;
  gv_plantdepartmentid      plantdepartment.plantdepartment_id%type;
  gv_businessunitid         businessunit.businessunit_id%type;
  gv_pn_statusid            status.status_id%type;
  gv_cnt_stayid             stay.stay_id%type;
  gv_workstationid          workstation.workstation_id%type;
  rec_container             container%rowtype;
  gv_packingnotecontainerid packingnotecontainer.packingnotecontainer_id%type;
  gv_customerid             customer.customer_id%type;
  gv_currencyid             customer.currency_id%type;
  gv_dep_occupancy          department.occupancy%type;
  gv_departmentid           department.department_id%type;
  gv_distributionpointid    distributionpoint.distributionpoint_id%type;
  gv_prev_customernumber    customer.customernumber%type := -10;
  gv_prev_departmentnumber  department.departmentnumber%type := -10;
  gv_remarkondeliverynote   distributionpoint.remarkondeliverynote%type;
  gv_remarkonpackingnote    distributionpoint.remarkonpackingnote%type;
  gv_call_count             number := 0;
  gv_packingnoteid          packingnote.packingnote_id%type;
  gv_packingnotelineid      packingnoteline.packingnoteline_id%type;

  gv_log_customernumber   customer.customernumber%type;
  gv_log_departmentnumber department.departmentnumber%type;

  fp_status         number;
  fp_notenumber     number;
  fp_sequencenumber number;

  --Internal procedures
  procedure write_log(fp_message in varchar2, fp_priority in number) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'DBM_Sendtrack', gv_plantid, fp_priority, fp_message,
                             gv_systemuserid);
    begin
      dbms_output.put_line(fp_message);
    exception
      when others then
        null; --ok no output to screen
    end;
  end write_log;

  procedure getsystemuserid is
  begin
    --getsystemuserid
    gv_message := 'getsystemuserid';
    select max(st.systemuser_id) into gv_systemuserid from systemuser st where st.username = 'DBM';
    if gv_systemuserid is null then
      gv_systemuserid := 0;
    end if;
  end getsystemuserid;

  procedure initialize is
  begin
    --initialize
    fp_status := 0;

    --delete previous entry
    delete from dbm_sendtrack_result dsr where dsr.scanstation = fp_scanstation;
    commit; --- is commit here OK.  I always want to delete ?

    --getsystemuserid
    getsystemuserid;
    if fp_container_primaryid is null then
      begin
        gv_message := 'Parameter fp_container_primaryid cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        gv_message := 'Container (primaryid) ' || fp_container_primaryid;
        select cr.*
        into   rec_container
        from   container cr
        where  cr.primaryid = fp_container_primaryid;
      end;
    end if;
    if fp_scanstation is null then
      begin
        gv_message := 'Parameter fp_scanstation cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        gv_message := 'Scan station ' || fp_scanstation;
        select wo.workstation_id, wo.plant_id,
               (select min(pd.plantdepartment_id)
                 from   plantdepartment pd
                 where  pd.plant_id = wo.plant_id)
        into   gv_workstationid, gv_plantid, gv_plantdepartmentid
        from   workstation wo
        where  wo.code = fp_scanstation;
      end;
    end if;
    if nvl(fp_number_of_garments, 0) <= 0 then
      begin
        gv_message := 'Parameter fp_number_of_garments should be >=0';
        raise gv_userexception;
      end;
    end if;
    if nvl(fp_last_item_batch, -1) not in (0, 1) then
      begin
        gv_message := 'Parameter fp_last_item_batch should 0(batch open) or 1(batch closed)';
        raise gv_userexception;
      end;
    end if;
    --get container stay outscan
    gv_message := 'get staytype 2, nr 30 ( container outscan )';
    select st.stay_id
    into   gv_cnt_stayid
    from   stay st
    where  st.staytype = 2
    and    st.staynr = '30';
  end initialize;

  procedure get_packingnote_status is
  begin
    --get packingnote status
    gv_message := 'get packingnote status';
    select st.status_id
    into   gv_pn_statusid
    from   status st
    where  st.statustype = 'PN' --Packingnote
    and    st.code = '30'; -- In processed ( completed )
  end get_packingnote_status;

  procedure create_packingnote(rt_delscan in deliveryscan%rowtype) is
    lv_deliverydate       date;
    lv_transportarticleid transportarticle.transportarticle_id%type;
    lv_businessunit_code  businessunit.code%type;
    lv_routeid            route.route_id%type := null;
    lv_routecontrolid     routecontrol.routecontrol_id%type := null;
    lv_stopid             stop.stop_id%type := null;
    lv_stopnumber         stop.stopnumber%type := null;
    lv_returngarments     number;
    lv_customernumber     customer.customernumber%type;

    procedure check_previous_pn is
    begin
      --check_previous_pn
      gv_message       := 'check_previous_pn';
      gv_packingnoteid := null;
      if rt_delscan.pool_packingnote_id is not null then
        begin
          --then use existing pool packingnote linked to the deliveryscan
          gv_packingnoteid := rt_delscan.pool_packingnote_id;
        end;
      else
        begin
          --check if most recent pn for same station is for same customer etc
          for zz in (select cds.*
                     from   container_deliveryscan cds
                     where  cds.scanstation = fp_scanstation
                     and    cds.systemuser_id = gv_systemuserid
                     and    cds.packingnote_id is not null
                     and    cds.timestamp > sysdate - 0.1
                     order  by cds.timestamp desc) loop
            begin
              if (zz.customernumber = gv_prev_customernumber and
                 zz.departmentnumber = gv_prev_departmentnumber and
                 zz.distributionpoint_link_id = rt_delscan.distributionpoint_link_id) then
                begin
                  gv_packingnoteid := zz.packingnote_id;
                end;
              end if;
              exit;
            end;
          end loop;
        end;
      end if;
      --get previous notenumber
      gv_message := 'get previous notenumber';
      select max(pk.notenumber)
      into   fp_notenumber
      from   packingnote pk
      where  pk.packingnote_id = gv_packingnoteid;
    end check_previous_pn;

    procedure get_routeid is
    begin
      --get_routeid
      for p in (select r.route_id, rc.routecontrol_id, s.stop_id, s.stopnumber
                from   routecontrol rc
                join   stop s
                on     s.routecontrol_id = rc.routecontrol_id
                join   route r
                on     r.route_id = rc.route_id
                where  s.status in (0, 3)
                and    r.active = 'Y'
                and    r.plant_id = gv_plantid
                and    rc.drivingdate = lv_deliverydate
                and    (s.deliverypoint_id = rt_delscan.deliverypoint_link_id or
                      s.deliverypoint_id is null)
                and    s.customer_link_id = gv_customerid
                order  by nvl(s.deliverypoint_id, 0) desc) loop
        begin
          lv_routeid        := p.route_id;
          lv_routecontrolid := p.routecontrol_id;
          lv_stopid         := p.stop_id;
          lv_stopnumber     := p.stopnumber;
          --found so exit
          exit;
        end;
      end loop; --p
    end get_routeid;
  begin
    --check_previous_pn
    ---> check_previous_pn;  ---->disabled for now PN per container
    --create pn if needed
    if gv_packingnoteid is null then
      begin
        --get next deliverydate
        select c.returngarments, c.customernumber
        into   lv_returngarments, lv_customernumber
        from   customer c
        where  c.customer_id = gv_customerid;

        case
          when lv_returngarments = 8 ---- 8 = next visit including today
           then
            lv_deliverydate := nvl(pack_sort.getnextdeliverydate(trunc(sysdate), gv_customerid, 2),
                                   trunc(sysdate));
          else
            lv_deliverydate := nvl(pack_sort.getnextdeliverydate(trunc(sysdate) + 1, gv_customerid,
                                                                 2), trunc(sysdate) + 1);
        end case;

        if lv_deliverydate is null then
           gv_message := 'Customer ' || to_char(lv_customernumber) || ' has no route !';
           raise gv_userexception;
        end if;

        --get_routeid
        get_routeid;
        --get_packingnote_status
        get_packingnote_status;
        --create_packingnote
        gv_message := 'create_packingnote get businessunit id ' ||
                      to_char(rt_delscan.businessunit_id);
        --get businessunit code
        select bu.code
        into   lv_businessunit_code
        from   businessunit bu
        where  bu.businessunit_id = rt_delscan.businessunit_id;
        --get notenumber
        gv_message := 'get notenumber for bu code ' || lv_businessunit_code;
        execute immediate 'select SEQ_DELIVERYNOTE_' || lv_businessunit_code ||
                          '.nextval from dual'
          into fp_notenumber;
        --get defaulttransportarticle
        select ta.transportarticle_id
        into   lv_transportarticleid
        from   transportarticle ta
        where  ta.defaulttransportarticle = 'Y';
        --insert into packingnote
        gv_message := 'insert into packingnote';
        insert into packingnote
          (packingnote_id, notenumber, productiondate, deliverydate, status_id, remark,
           distributionpoint_id, deliverypoint_id, plantdepartment_id, transportarticle_id,
           systemuser_id, processbusinessunit_id, route_id, timestamp, cleanreturn, sequencenumber,
           deadline, occupancy, invoicebusinessunit_id, routecontrol_id, originaldeliverydate,
           origin, stopnumber, daynumber, correctednotenumber, creationtimestamp, referencenumber,
           returndateloan, stop_id, consignmentnote_id, straightevenreturn, numberofgarmentsinlocker,
           numberoflockers, bulkpackingnote_id, freeofchargereason_id, week, year, weighingticket_id,
           totalamount, totalamountexcludingvat, pricescalculated, showoninvoiceappendix,
           deliveryremark, exported, finishedpacking, picklistprinted, invoicestatus, numberofcolli,
           emailstatus, emailmaybesent, processedtimestamp, processedsystemuser_id, signed,
           internalprocessingbu_id, creationsystemuser_id, salesnote_id, parceltracecode,
           calculatetransportcosts, pdfarchived, correctionfornote_id, enddateforuse,
           correctconsignmentnote, pnremark, loadsequencenr, deliverysignature_id)
        values
          (seq_packingnote.nextval, fp_notenumber, trunc(sysdate), lv_deliverydate, gv_pn_statusid,
           gv_remarkondeliverynote, rt_delscan.distributionpoint_link_id,
           rt_delscan.deliverypoint_link_id, gv_plantdepartmentid, lv_transportarticleid,
           gv_systemuserid, rt_delscan.businessunit_id, lv_routeid, sysdate, 'N', 1, null,
           gv_dep_occupancy, rt_delscan.businessunit_id, lv_routecontrolid, trunc(sysdate) + 1, 1,
           lv_stopnumber, getdaynumber(lv_deliverydate), 0, sysdate,
           'DBM_SENDTRACK', null, lv_stopid, null, 'N', 0, 0, null, null,
           getisoweek(trunc(sysdate) + 1), getyearofweek(trunc(sysdate) + 1), null, 0, 0, 'N', 'Y',
           'N', 'N', 0, 'N', 0, 1, 0, 'N', sysdate, gv_systemuserid, 'N', null, gv_systemuserid,
           null, null, 'N', 'N', null, trunc(sysdate) + 1, 0, gv_remarkonpackingnote, 0, null)
        returning packingnote_id into gv_packingnoteid;
      end;
    end if;
  end create_packingnote;

  procedure create_packingnotecontainer is
  begin
    --create_packingnotecontainer
    gv_message := 'get lv_sequencenumber';
    select max(pnc.sequencenumber)
    into   fp_sequencenumber
    from   packingnotecontainer pnc
    where  pnc.packingnote_id = gv_packingnoteid;
    fp_sequencenumber := nvl(fp_sequencenumber, 0) + 1;
    --create packingnotecontainer
    gv_message := 'create_packingnotecontainer';
    insert into packingnotecontainer
      (packingnotecontainer_id, packingnote_id, sequencenumber, containertype_id, container_id,
       tareweight, grossweight, soilportion, weightdecimals, systemuser_id, timestamp)
    values
      (seq_packingnotecontainer.nextval, gv_packingnoteid, fp_sequencenumber,
       rec_container.containertype_id, rec_container.container_id, rec_container.tareweight, 0, 0, 0,
       gv_systemuserid, sysdate)
    returning packingnotecontainer_id into gv_packingnotecontainerid;
  end create_packingnotecontainer;

  procedure process_packingnote_line(rt_delscan in deliveryscan%rowtype) is
  begin
    --process_packingnote_line
    gv_message := 'process_packingnote_line';
    update packingnoteline pkl
    set    pkl.deliveredamount = pkl.deliveredamount + 1
    where  pkl.packingnote_id = gv_packingnoteid
    and    pkl.product_id = rt_delscan.product_link_id
    and    pkl.sizedefinition_id = rt_delscan.sizedefinition_link_id
    and    pkl.finishingmethod_id = rt_delscan.finishingmethod_id
    returning pkl.packingnoteline_id into gv_packingnotelineid;
    if sql%rowcount = 0 then
      begin
        select seq_packingnoteline.nextval into gv_packingnotelineid from dual;
        insert into packingnoteline
          (packingnoteline_id, product_id, packingsequence, finishingmethod_id, price, discount,
           packingnote_id, sizedefinition_id, systemuser_id, location, timestamp,
           remarkforpackinginstructions, customcode, customdescription, replacementqty,
           updaterentqty, adjustmentreason_id, origin, putuptype, freeofchargereason_id,
           nochargefirstissue, nochargeactiveseason, deliveredcogqty, auxiliarystatus,
           standardamount, variationamount, deliveredamount, tobedeliveredamount, amount,
           taxgroupcode, bundleqty, nochargefirstissuecog, scannedbundles, pricecog,
           nodeliveryamount, creationtimestamp, creationsystemuser_id, autoreplacementqty)
          select gv_packingnotelineid, p.product_id, p.packingsequence,
                 rt_delscan.finishingmethod_id, null, 0, gv_packingnoteid,
                 rt_delscan.sizedefinition_link_id, gv_systemuserid, null, sysdate, null, null, null,
                 0, 0, null, 1, 1, null, 0, 0, 0, null, 0, 0, 1, 0, 0, null, 0, 0, 0, null, 0,
                 sysdate, gv_systemuserid, 0
          from   product p
          where  p.product_id = rt_delscan.product_link_id;
      end;
    end if;
  end process_packingnote_line;

  procedure create_pkcontainercontent(rt_delscan in deliveryscan%rowtype) is
  begin
    --create_pkcontainercontent
    gv_message := 'create_pkcontainercontent';
    insert into packingnotecontainercontent
      (packingnotecontainer_id, uniqueitem_link_id, systemuser_id, timestamp, packingnoteline_id)
    values
      (gv_packingnotecontainerid, rt_delscan.uniqueitem_link_id, gv_systemuserid, sysdate,
       gv_packingnotelineid);
  end create_pkcontainercontent;

  procedure create_packingnotecontainerqty is
  begin
    --create_packingnotecontainerqty
    gv_message := 'create_packingnotecontainerqty';
    insert into packingnotecontainerqty
      (packingnotecontainerqty_id, packingnotecontainer_id, packingnoteline_id, deliveredqty,
       systemuser_id, timestamp)
      select seq_packingnotecontainerqty.nextval, gv_packingnotecontainerid, x.packingnoteline_id,
             x.qty, gv_systemuserid, sysdate
      from   (select pkc.packingnoteline_id, count(1) qty
               from   packingnotecontainercontent pkc
               where  pkc.packingnotecontainer_id = gv_packingnotecontainerid
               group  by pkc.packingnoteline_id) x;
  end create_packingnotecontainerqty;

  procedure link_deliveryscan_to_pnl(rt_delscan in deliveryscan%rowtype) is
  begin
    --link_deliveryscan_to_pnl
    gv_message := 'link_deliveryscan_to_pnl';
    update deliveryscan ds
    set    ds.packingnote_id = gv_packingnoteid
    where  ds.uniqueitem_link_id = rt_delscan.uniqueitem_link_id
    and    ds.businessunit_id = rt_delscan.businessunit_id
    and    ds.scantimestamp = rt_delscan.scantimestamp;
  end link_deliveryscan_to_pnl;

  procedure create_deliveryhistory is
    lv_rec_deliveryhistory deliveryhistory%rowtype;
  begin
    --create_deliveryhistory
    gv_message := 'create_deliveryhistory';
    for x in (select pk.deliverydate, pk.distributionpoint_id, pkl.product_id, pkl.sizedefinition_id,
                     pkl.finishingmethod_id, pk.processbusinessunit_id, dep.customer_id,
                     dep.department_id, nvl(sum(pkl.standardamount), 0) standardamount,
                     nvl(sum(pkl.variationamount), 0) variationamount,
                     nvl(sum(pkl.deliveredamount), 0) deliveredamount,
                     nvl(sum(pkl.tobedeliveredamount), 0) tobedeliveredamount,
                     max(pk.invoicebusinessunit_id) invoicebusinessunit_id,
                     max(p.parentproduct_id) parentproduct_id,
                     case
                       when sum((select count(1)
                                from   packingnotelinecontent pklc
                                where  pklc.packingnoteline_id = pkl.packingnoteline_id)) > 0 then
                        3
                       else
                        1
                     end packindication
              from   packingnote pk
              join   packingnoteline pkl
              on     pkl.packingnote_id = pk.packingnote_id
              join   product p
              on     p.product_id = pkl.product_id
              join   distributionpoint dp
              on     dp.distributionpoint_id = pk.distributionpoint_id
              join   department dep
              on     dep.department_id = dp.department_id
              where  pk.packingnote_id = gv_packingnoteid
              group  by pk.deliverydate, pk.distributionpoint_id, dep.customer_id, dep.department_id,
                        pkl.product_id, pkl.sizedefinition_id, pkl.finishingmethod_id,
                        pk.processbusinessunit_id) loop
      begin
        --fill data
        gv_businessunitid                                := x.processbusinessunit_id;
        lv_rec_deliveryhistory.deliveryhistory_id        := seq_deliveryhistory.nextval;
        lv_rec_deliveryhistory.processbusinessunit_id    := x.processbusinessunit_id;
        lv_rec_deliveryhistory.invoicebusinessunit_id    := x.invoicebusinessunit_id;
        lv_rec_deliveryhistory.deliverydate              := x.deliverydate;
        lv_rec_deliveryhistory.week                      := getisoweek(x.deliverydate);
        lv_rec_deliveryhistory.year                      := getyearofweek(x.deliverydate);
        lv_rec_deliveryhistory.daynumber                 := getabsdaynumber(x.deliverydate);
        lv_rec_deliveryhistory.customer_link_id          := x.customer_id; ---gv_customerid;
        lv_rec_deliveryhistory.department_link_id        := x.department_id; ---gv_departmentid;
        lv_rec_deliveryhistory.distributionpoint_link_id := x.distributionpoint_id;
        lv_rec_deliveryhistory.product_link_id           := x.product_id;
        lv_rec_deliveryhistory.sizedefinition_link_id    := x.sizedefinition_id;
        lv_rec_deliveryhistory.finishingmethod_id        := x.finishingmethod_id;
        lv_rec_deliveryhistory.amountordered             := x.standardamount + x.variationamount;
        lv_rec_deliveryhistory.amountdelivered           := x.deliveredamount;
        lv_rec_deliveryhistory.amountstandard            := x.standardamount;
        lv_rec_deliveryhistory.amountshortage := case
                                                   when (x.tobedeliveredamount - x.deliveredamount < 0 or
                                                        x.tobedeliveredamount = 0) then
                                                    0
                                                   else
                                                    x.tobedeliveredamount - x.deliveredamount
                                                 end;
        lv_rec_deliveryhistory.currency_id               := gv_currencyid;
        lv_rec_deliveryhistory.price                     := 0;
        lv_rec_deliveryhistory.discount                  := 0;
        lv_rec_deliveryhistory.internalprice             := 0;
        lv_rec_deliveryhistory.pieceweight               := 0;
        lv_rec_deliveryhistory.packindication            := x.packindication;
        lv_rec_deliveryhistory.parentproduct_link_id     := x.parentproduct_id;
        lv_rec_deliveryhistory.parentpackproduct_link_id := x.product_id;
        lv_rec_deliveryhistory.systemuser_id             := gv_systemuserid;
        lv_rec_deliveryhistory.timestamp                 := sysdate;
        --insert
        insert into deliveryhistory values lv_rec_deliveryhistory;
      exception
        when dup_val_on_index then
          begin
            update deliveryhistory dh
            set    dh.amountdelivered = dh.amountdelivered + lv_rec_deliveryhistory.amountdelivered,
                   dh.amountshortage = dh.amountshortage + lv_rec_deliveryhistory.amountshortage,
                   dh.amountordered = dh.amountordered + lv_rec_deliveryhistory.amountordered,
                   dh.amountstandard = dh.amountstandard + lv_rec_deliveryhistory.amountstandard
            where  dh.deliverydate = lv_rec_deliveryhistory.deliverydate
            and    dh.customer_link_id = lv_rec_deliveryhistory.customer_link_id
            and    dh.department_link_id = lv_rec_deliveryhistory.department_link_id
            and    dh.distributionpoint_link_id = lv_rec_deliveryhistory.distributionpoint_link_id
            and    dh.product_link_id = lv_rec_deliveryhistory.product_link_id
            and    dh.sizedefinition_link_id = lv_rec_deliveryhistory.sizedefinition_link_id
            and    dh.finishingmethod_id = lv_rec_deliveryhistory.finishingmethod_id
            and    dh.processbusinessunit_id = lv_rec_deliveryhistory.processbusinessunit_id
            and    dh.parentpackproduct_link_id = lv_rec_deliveryhistory.parentpackproduct_link_id
            and    dh.packindication = lv_rec_deliveryhistory.packindication;
          end;
      end;
    end loop; --x packingnote
  end create_deliveryhistory;

  procedure close_packingnote is
  begin
    --close_packingnote
    if fp_last_item_batch = 1 and gv_pn_statusid is null then
      begin
        --get_packingnote_status, pn was not created
        get_packingnote_status;
        --close packingnote
        gv_message := 'close_packingnote';
        update packingnote pk
        set    pk.status_id = gv_pn_statusid, pk.processedtimestamp = sysdate,
               pk.timestamp = sysdate, pk.systemuser_id = gv_systemuserid
        where  pk.packingnote_id = gv_packingnoteid
        and    pk.status_id <> gv_pn_statusid;
      end;
    end if;
  end close_packingnote;

  procedure update_container is
  begin
    --update_container
    gv_message := 'update_container';
    update container c
    set    c.prevstay_id = c.stay_id, c.stay_id = gv_cnt_stayid, c.staychangedate = sysdate,
           c.lastoutscandate = sysdate, c.lastnotenumber = fp_notenumber,
           c.lastdistributionpoint_link_id = c.distributionpoint_id,
           c.distributionpoint_id = gv_distributionpointid,
           c.numberofshipments = c.numberofshipments + 1, c.systemuser_id = gv_systemuserid,
           c.timestamp = sysdate
    where  c.container_id = rec_container.container_id;
  end update_container;

  procedure create_containerscan is
  begin
    --create_containerscan
    gv_message := 'create_containerscan';
    insert into containerscan
      (containerscan_id, scantimestamp, businessunit_id, primaryid, secondaryid,
       distributionpoint_link_id, containertype_id, stay_id, prevstay_id, transactiontype_id,
       scanstation, customerowned, year, week, dayno, container_id, tareweight, systemuser_id,
       timestamp)
    values
      (seq_containerscan.nextval, sysdate, gv_businessunitid, fp_container_primaryid, null,
       gv_distributionpointid, rec_container.containertype_id, gv_cnt_stayid, rec_container.stay_id,
       540, fp_scanstation,
       case when rec_container.ownercustomer_id is not null then 'Y' else 'N' end,
       getyearofweek(sysdate), getisoweek(sysdate), getabsdaynumber(sysdate),
       rec_container.container_id, rec_container.tareweight, gv_systemuserid, sysdate);
  end create_containerscan;

  procedure sendtrack_containerscan is
    lv_customernumber   customer.customernumber%type;
    lv_departmentnumber department.departmentnumber%type;
  begin
    --sendtrack_containerscan
    gv_message := 'sendtrack_containerscan';
    for x in (select ds.*
              from   deliveryscan ds
              where  ds.scanstation = fp_scanstation
              and    nvl(ds.packingnote_id, 0) = 0
              and    trunc(ds.scantimestamp) > trunc(sysdate) - 4 --- max 4 dagen oud
              order  by ds.scantimestamp asc) loop
      begin
        --get info
        gv_message := 'get distributionpoint id ' || to_char(x.distributionpoint_link_id);
        select c.customer_id, c.customernumber, c.currency_id, t.department_id, t.departmentnumber,
               dp.remarkondeliverynote, t.occupancy, dp.remarkonpackingnote
        into   gv_customerid, lv_customernumber, gv_currencyid, gv_departmentid, lv_departmentnumber,
               gv_remarkondeliverynote, gv_dep_occupancy, gv_remarkonpackingnote
        from   distributionpoint dp
        join   department t
        on     t.department_id = dp.department_id
        join   customer c
        on     c.customer_id = t.customer_id
        where  dp.distributionpoint_id = x.distributionpoint_link_id;

        gv_log_customernumber   := lv_customernumber;
        gv_log_departmentnumber := lv_departmentnumber;

        if (gv_prev_customernumber = -10 and gv_prev_departmentnumber = -10) then
          begin
            gv_prev_customernumber   := lv_customernumber;
            gv_prev_departmentnumber := lv_departmentnumber;
            gv_distributionpointid   := x.distributionpoint_link_id;
            --create_packingnote, 1 time per call of the procedure only
            create_packingnote(x);
            --create_packingnotecontainer
            create_packingnotecontainer;
          end;
        end if;
        --count scans processed
        if ((gv_call_count >= fp_number_of_garments and fp_last_item_batch = 0) or
           gv_prev_customernumber <> lv_customernumber or
           gv_prev_departmentnumber <> lv_departmentnumber or
           gv_distributionpointid <> x.distributionpoint_link_id) then
          begin
            exit; --exit loop
          end;
        end if;
        gv_call_count := gv_call_count + 1;
        --create/update packingnote line
        process_packingnote_line(x);
        --create packingnote containercontent
        create_pkcontainercontent(x);
        --link deliveryscan to packingnote line
        link_deliveryscan_to_pnl(x);
      end;
    end loop;
    if gv_call_count > 0 then
      begin
        --create packingnotecontainerqty
        create_packingnotecontainerqty;
        --fill deliveryhistory
        create_deliveryhistory;
        --close_packingnote
        close_packingnote;
        --update container
        update_container;
        --create containerscan
        create_containerscan;
      end;
    end if;
  end sendtrack_containerscan;

  procedure fill_container_deliveryscan is
  begin
    --fill_container_deliveryscan
    gv_message := 'fill_container_deliveryscan';
    if gv_prev_customernumber = -10 and gv_prev_departmentnumber = -10 then
      begin
        gv_prev_customernumber   := null;
        gv_prev_departmentnumber := null;
      end;
    end if;
    insert into container_deliveryscan
      (container_primaryid, scantimestamp, scanstation, number_of_garments, last_item_batch, status,
       customernumber, departmentnumber, distributionpoint_link_id, packingnote_id,
       actual_number_of_garments, timestamp, systemuser_id)
    values
      (fp_container_primaryid, sysdate, fp_scanstation, fp_number_of_garments, fp_last_item_batch,
       fp_status, gv_prev_customernumber, gv_prev_departmentnumber, gv_distributionpointid,
       gv_packingnoteid, gv_call_count, sysdate, gv_systemuserid);
  end fill_container_deliveryscan;

  procedure write_result_table is
  begin
    gv_message := 'write result table';
    insert into dbm_sendtrack_result
      (container_primaryid, scanstation, status, notenumber, sequence)
    values
      (fp_container_primaryid, fp_scanstation, fp_status, fp_notenumber, fp_sequencenumber);
  end write_result_table;

  procedure finalize is
  begin
    gv_message := 'finalize';
    --finalize
    --return message
    if gv_call_count <= 0 then
      begin
        rollback;
        --fill_container_deliveryscan
        fp_status := 4;
        fill_container_deliveryscan;
        commit;
        write_log('Error, no garments found to put into container (primaryid) ' ||
                  fp_container_primaryid, 3);
      end;
    else
      begin
        fill_container_deliveryscan;
        commit;
        write_log('Ok, created; Notenumber ' || to_char(fp_notenumber) || ' for container : ' ||
                  substr(fp_container_primaryid || '       ', 1, 8) || ' with ' ||
                  to_char(gv_call_count, '9999') || ' garments' || '  (' ||
                  to_char(fp_number_of_garments, '9999') || ') Lastitem ' || fp_last_item_batch ||
                  ' -C ' || to_char(gv_log_customernumber, '999999') || ' -D ' ||
                  to_char(gv_log_departmentnumber, '9999'), 1);
      end;
    end if;
    write_result_table;
    commit;
  end finalize;
begin
  --initialize
  initialize;
  --sendtrack_containerscan
  sendtrack_containerscan;
  --finalize
  finalize;
exception
  --Exception handling
  when gv_userexception then
    begin
      rollback;
      write_log(gv_message, 3);
      fp_status := 3;
      write_result_table;
      commit;
    end;
  when no_data_found then
    begin
      rollback;
      write_log('Error, No Data Found ' || gv_message, 3);
      fp_status     := 2;
      fp_notenumber := null;
      --fill_container_deliveryscan
      fill_container_deliveryscan;
      write_result_table;
      commit;
    end;
  when others then
    begin
      rollback;
      write_log('Error ' || sqlerrm || ' ' || gv_message, 3);
      fp_status     := 1;
      fp_notenumber := null;
      --fill_container_deliveryscan
      fill_container_deliveryscan;
      write_result_table;
      commit;
    end;
end dbm_sendtrack;
/
create or replace procedure DeleteProductSize(ProductCode in Product.Code%type,
                                              SizeCode    in Sizedefinition.Code%type,
                                              Status      out number) is
  productid       product.product_id%type;
  sizeid          sizedefinition.sizedefinition_id%type;
  countplpc       number;
  countw          number;
  SQLfile         utl_file.file_type;
  UTLDIR          varchar2(50);
  FPsFilename     varchar2(50);
  debuglevel      integer := 1;
  sessionsid      integer;
  sessionserialnr integer;
begin
  begin
    select s.dblogdir into UTLDIR from databasesettings s;
  EXCEPTION
    WHEN no_data_found then
      UTLDIR := 'C:\'; -- please see ABS-92804 variable needs the name of an existing oracle directory
  end;
  select a.SID, a.SERIAL#
    into sessionsid, sessionserialnr
    from SYS.V_$SESSION a
   where a.AUDSID = (SELECT sys_context('USERENV', 'SESSIONID') FROM dual);
  FPsFilename := 'DeleteProductSize_' || to_char(sysdate, 'YYYYMMDDHHMMSS') || '_' ||
                 sessionsid || '_' || sessionserialnr || '.txt';
  SqlFile     := UTL_FILE.FOPEN(UTLDIR, FPsFilename, 'a');
  begin
    select ps.sizedefinition_id, p.product_id
      into sizeid, productid
      from product p, productsize ps, sizedefinition s
     where p.code = ProductCode
       and p.product_id = ps.product_id
       and ps.sizedefinition_id = s.sizedefinition_id
       and s.code = SizeCode;
    select count(plpc.productlistpercustomer_id)
      into countplpc
      from productlistpercustomer plpc
     where plpc.product_id = productid
       and plpc.sizedefinition_id = sizeid
       and plpc.dateactive <= sysdate
       and plpc.dateinactive > sysdate;
    if countplpc > 0 then
      Status := 2;
      if debuglevel > 0 then
        utl_file.put_line(SqlFile,
                          '!> For product code' || productCode ||
                          ' and size code ' || SizeCode ||
                          ' there are active productlistpercustomer records');
      end if;
    else
      select count(w.wearerinventory_id)
        into countw
        from wearerinventory w
       where w.product_id = productid
         and w.sizedefinition_id = sizeid
         and w.dateactive <= sysdate
         and w.dateinactive > sysdate;
      if countw > 0 then
        Status := 3;
        if debuglevel > 0 then
          utl_file.put_line(SqlFile,
                            '!> For product code' || productCode ||
                            ' and size code ' || SizeCode ||
                            ' there are active wearerinventory records');
        end if;
      else
        delete from productsize ps
         where ps.product_id = productid
           and ps.sizedefinition_id = sizeid;
        Status := 0;
      end if;
    end if;
    commit;
  exception
    when no_data_found then
      Status := 1;
      if debuglevel > 0 then
        utl_file.put_line(SqlFile,
                          '!> Not found product code' || productCode ||
                          ' and size code ' || SizeCode || sqlcode || ' ' ||
                          sqlerrm);
      end if;
    when others then
      rollback;
      Status := 99;
      utl_file.put_line(SqlFile,
                        '!> Error for product code' || productCode ||
                        ' and size code ' || SizeCode || sqlcode || ' ' ||
                        sqlerrm);
  end;
  if debuglevel > 0 then
    utl_file.put_line(SQLfile,
                      'Product code ' || productcode || ' Size code ' ||
                      sizecode || ' Status ' || Status);
  end if;
  UTL_FILE.FCLOSE(SqlFile);
end DeleteProductSize;
/
create or replace procedure dpcostspecification(fp_invoiceheaderid     in invoiceheader.invoiceheader_id%type,
                                                fp_abslogprocess_jobid in abslogprocessjob.abslogprocessjob_id%type,
                                                fp_systemuser_id       in systemuser.systemuser_id%type,
                                                fp_dpcostspecification out nocopy number /*0=Ok, 1=Error*/) is
  --procedure dpcostspecification version 0.78
  gv_user_exception exception;
  gv_systemuserid            systemuser.systemuser_id%type;
  gv_message                 abslog.message%type;
  gv_abslog_processjobpartid abslogprocessjobpart.abslogprocessjobpart_id%type;
  gv_def_productgroupcode    productgroup.code%type := '999999';
  gv_def_productgroupid      productgroup.productgroup_id%type;
  gv_rec_invoiceheader       invoiceheader%rowtype;
  gv_record_counter          number;

  --internal procedures
  procedure write_log(fp_message in abslog.message%type, fp_priority in abslog.priority%type) is
  begin
    --check fp_abslogprocess_jobid
    if nvl(fp_abslogprocess_jobid, -1) = -1 then
      begin
        abslogwrite.abslog_write(5, 'dpcostspecification', null, fp_priority, fp_message,
                                 gv_systemuserid);
      end;
    else
      begin
        --write_log, get new abslogprocessjobpart?
        if gv_abslog_processjobpartid is null then
          begin
            gv_abslog_processjobpartid := abslogwrite.abslogprocessjobpart_write(fp_abslogprocess_jobid,
                                                                                 'Cost Specification per Department / Consumption Point',
                                                                                 gv_systemuserid);
          end;
        end if;
        --write the log line
        abslogwrite.abslogprocessjobline_write(gv_abslog_processjobpartid, fp_priority, fp_message,
                                               gv_systemuserid);
      end;
    end if;
  exception
    when others then
      begin
        --could not write itnto abslogjob, so we write into abslog instead
        abslogwrite.abslog_write(5, 'dpcostspecification', null, fp_priority, fp_message,
                                 gv_systemuserid);
      end;
  end write_log;

  procedure initialize is
    lv_activityid activity.activity_id%type;
  begin
    --initialize
    gv_message        := 'Initialize';
    gv_record_counter := 0;
    --check/get systemuser
    gv_message := 'Initialize get systemuser';
    if fp_systemuser_id is null then
      select min(s.systemuser_id) into gv_systemuserid from systemuser s;
    else
      gv_systemuserid := fp_systemuser_id;
    end if;
    --get invoiceheader
    gv_message := 'Initialize get invoiceheader id ' || to_char(fp_invoiceheaderid);
    select ih.*
    into   gv_rec_invoiceheader
    from   invoiceheader ih
    where  ih.invoiceheader_id = fp_invoiceheaderid;
    --get global variable default productgroup code, it must exist
    if gv_def_productgroupcode is null then
      begin
        gv_message := 'Value gv_def_productgroupcode cannot be left blank!';
        raise gv_user_exception;
      end;
    else
      begin
        gv_message := 'Default product group code ' || gv_def_productgroupcode;
        select pg.productgroup_id
        into   gv_def_productgroupid
        from   productgroup pg
        where  pg.code = gv_def_productgroupcode;
      exception
        when no_data_found then
          begin
            --we need a default productgroup so we create it
            select min(a.activity_id) into lv_activityid from activity a;
            --insert productgroup, remark NO description yet, no problem!
            insert into productgroup
              (productgroup_id, activity_id, code, legacyproductgroupcode, active, systemuser_id,
               timestamp)
            values
              (seq_productgroup.nextval, lv_activityid, gv_def_productgroupcode, null, 'N',
               fp_systemuser_id, sysdate)
            returning productgroup_id into gv_def_productgroupid;
          end;
      end;
    end if;
  end initialize;

  procedure process_invoicelines is

    procedure rent_garments is
    begin
      --rent_garments
      gv_message := 'rent_garments';
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, we.distributionpoint_id, il.billedqty, il.amount,
               p.productgroup_id, gv_systemuserid, sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   weareremployment we
        on     we.weareremployment_id = ilp.weareremployment_link_id
        join   product p
        on     p.product_id = ilp.product_link_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 1 --Rent
        and    il.invoicelinesubtype in (1, 2)
        and    il.extend = 'Y';
    end rent_garments;

    procedure rent_non_garments is
    begin
      --rent_non_garments
      gv_message := 'rent_non_garments';
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp,factor)
        select il.invoiceline_id, plpd.distributionpoint_id,
               sum(nvl((select sum(rqa.quantity)
                        from   rentalqtyadjustment rqa
                        where  rqa.productlistperdistribpoint_id =
                               plpd.productlistperdistribpoint_id
                        and    rqa.adjustmentdate <= gv_rec_invoiceheader.invoicedate),
                        (select sum(sdl.fixedrentquantity)
                          from   standarddeliveryline sdl
                          where  sdl.productlistperdistribpoint_id = plpd.productlistperdistribpoint_id))) billedqty,
               sum(nvl((select sum(rqa.quantity)
                        from   rentalqtyadjustment rqa
                        where  rqa.productlistperdistribpoint_id =
                               plpd.productlistperdistribpoint_id
                        and    rqa.adjustmentdate <= gv_rec_invoiceheader.invoicedate),
                        (select sum(sdl.fixedrentquantity)
                          from   standarddeliveryline sdl
                          where  sdl.productlistperdistribpoint_id = plpd.productlistperdistribpoint_id)) *
                    il.price) amount, p.productgroup_id, gv_systemuserid, sysdate
                ,    round(sum(nvl((select sum(rqa.quantity)
                        from   rentalqtyadjustment rqa
                        where  rqa.productlistperdistribpoint_id =
                               plpd.productlistperdistribpoint_id
                        and    rqa.adjustmentdate  <= gv_rec_invoiceheader.invoicedate),
                        (select sum(sdl.fixedrentquantity)
                          from   standarddeliveryline sdl
                          where  sdl.productlistperdistribpoint_id = plpd.productlistperdistribpoint_id))  /nullif(il.billedqty,0))*100,2)
                       factor
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   product p
        on     p.product_id = ilp.product_link_id
        cross  join (select dp.distributionpoint_id
                     from   department t
                     join   distributionpoint dp
                     on     dp.department_id = t.department_id
                     where  t.customer_id =
                            nvl(gv_rec_invoiceheader.deltocustomer_link_id,
                                gv_rec_invoiceheader.billtocustomer_link_id)) dpx
        join   productlistperdistribpoint plpd
        on     (plpd.distributionpoint_id = dpx.distributionpoint_id and
               plpd.product_id = ilp.product_link_id and
               plpd.sizedefinition_id = ilp.sizedefinition_link_id and
               plpd.finishingmethod_id = ilp.finishingmethod_id)
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 1 --Rent
        and    il.invoicelinesubtype = 0
        and    il.extend = 'Y'
        group  by il.invoiceline_id, plpd.distributionpoint_id, p.productgroup_id,il.billedqty;
    end rent_non_garments;

    procedure wash_per_wearer is
    begin
      --wash_per_wearer
      gv_message := 'wash_per_wearer';
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, we.distributionpoint_id, il.billedqty, il.amount,
               p.productgroup_id, gv_systemuserid, sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   weareremployment we
        on     we.weareremployment_id = ilp.weareremployment_link_id
        join   product p
        on     p.product_id = ilp.product_link_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 2 --Wash
        and    ((il.invoicelinesubtype in (1, 2, 3, 4)) or
              (il.invoicelinesubtype = 15 and ilp.weareremployment_link_id is not null))
        and    il.extend = 'Y';
    end wash_per_wearer;

    procedure wash_other is
    begin
      --wash_other
      gv_message := 'wash_other';
      --insert into invoicelinedp
      --No link using distributionpoint_id, according to analysis
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp, factor)
        select il.invoiceline_id, pk.distributionpoint_id,
               sum((pkl.deliveredamount - pkl.nochargefirstissue - pkl.nochargeactiveseason -
                    nvl(pkl.nochargefirstissuecog, 0) - pkl.nochargeprevrejected -
                    pkl.nochargeprevshortage)) billedqty,
               sum((pkl.deliveredamount - pkl.nochargefirstissue - pkl.nochargeactiveseason -
                    nvl(pkl.nochargefirstissuecog, 0) - pkl.nochargeprevrejected -
                    pkl.nochargeprevshortage) * il.price) amount, p.productgroup_id, gv_systemuserid,
               sysdate,
               round(sum((pkl.deliveredamount - pkl.nochargefirstissue - pkl.nochargeactiveseason -
                    nvl(pkl.nochargefirstissuecog, 0) - pkl.nochargeprevrejected -
                    pkl.nochargeprevshortage)) *100,2) factor
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   product p
        on     p.product_id = ilp.product_link_id
        join   packingnoteline pkl
        on     (pkl.invoiceheader_id = il.invoiceheader_id and pkl.product_id = ilp.product_link_id and
               (pkl.sizedefinition_id = ilp.sizedefinition_link_id or
               ilp.sizedefinition_link_id =
               (select sd.sizedefinition_id from sizedefinition sd where sd.code = '*')) and --add size *
               pkl.finishingmethod_id = ilp.finishingmethod_id)
        join   packingnote pk
        on     pk.packingnote_id = pkl.packingnote_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 2 --Wash
        and    ((il.invoicelinesubtype = 0) or
              (il.invoicelinesubtype = 15 and ilp.weareremployment_link_id is null))
        and    il.extend = 'Y'
        and    pk.origin in (0, 1, 4, 5, 6)
        group  by il.invoiceline_id, pk.distributionpoint_id, p.productgroup_id;
    end wash_other;

    procedure sales_via_deliverynote is
    begin
      --sales_via_deliverynote
      gv_message := 'sales_via_deliverynote';
      --No link using distributionpoint_id, according to analysis
      --Remark overlap PN with wash_other, except when different product code is used!!
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, pk.distributionpoint_id,
               sum((pkl.deliveredamount - pkl.nochargefirstissue - pkl.nochargeactiveseason -
                    nvl(pkl.nochargefirstissuecog, 0) - pkl.nochargeprevrejected -
                    pkl.nochargeprevshortage)) billedqty,
               sum((pkl.deliveredamount - pkl.nochargefirstissue - pkl.nochargeactiveseason -
                    nvl(pkl.nochargefirstissuecog, 0) - pkl.nochargeprevrejected -
                    pkl.nochargeprevshortage) * il.price) amount, p.productgroup_id, gv_systemuserid,
               sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   product p
        on     p.product_id = ilp.product_link_id
        join   packingnoteline pkl
        on     (pkl.invoiceheader_id = il.invoiceheader_id and pkl.product_id = ilp.product_link_id and
               pkl.sizedefinition_id = ilp.sizedefinition_link_id and
               pkl.finishingmethod_id = ilp.finishingmethod_id)
        join   packingnote pk
        on     pk.packingnote_id = pkl.packingnote_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 5 --Sales
        and    il.invoicelinesubtype = 0
        and    il.extend = 'Y'
        group  by il.invoiceline_id, pk.distributionpoint_id, p.productgroup_id;
      --garment_saleshistory_and_no_note
      gv_message := 'garment_saleshistory_and_no_note';
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, dpx.distributionpoint_id, sum(gsh.quantity) billedqty,
               sum(gsh.quantity * il.price) amount, p.productgroup_id, gv_systemuserid, sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   product p
        on     p.product_id = ilp.product_link_id
        cross  join (select dp.distributionpoint_id
                     from   department t
                     join   distributionpoint dp
                     on     dp.department_id = t.department_id
                     where  t.customer_id =
                            nvl(gv_rec_invoiceheader.deltocustomer_link_id,
                                gv_rec_invoiceheader.billtocustomer_link_id)) dpx
        join   garmentsaleshistory gsh
        on     (gsh.invoiceheader_id = il.invoiceheader_id and
               gsh.distributionpoint_link_id = dpx.distributionpoint_id and
               gsh.product_link_id = ilp.product_link_id and
               gsh.weareremployment_link_id = ilp.weareremployment_link_id and
               (gsh.status = 0 or (gsh.status = 1 and gsh.workorderline_id is not null)))
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 5 --Sales
        and    il.invoicelinesubtype = 0
        and    il.extend = 'Y'
        group  by il.invoiceline_id, dpx.distributionpoint_id, p.productgroup_id;
    end sales_via_deliverynote;

    procedure garment_saleshistory_and_note is
    begin
      --garment_saleshistory_and_note
      gv_message := 'garment_saleshistory_and_note';
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, dpx.distributionpoint_id, sum(gsh.quantity) billedqty,
               sum(gsh.quantity * il.price) amount, p.productgroup_id, gv_systemuserid, sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   product p
        on     p.product_id = ilp.product_link_id
        cross  join (select dp.distributionpoint_id
                     from   department t
                     join   distributionpoint dp
                     on     dp.department_id = t.department_id
                     where  t.customer_id =
                            nvl(gv_rec_invoiceheader.deltocustomer_link_id,
                                gv_rec_invoiceheader.billtocustomer_link_id)) dpx
        join   garmentsaleshistory gsh
        on     (gsh.invoiceheader_id = il.invoiceheader_id and
               gsh.distributionpoint_link_id = dpx.distributionpoint_id and
               gsh.product_link_id = ilp.product_link_id and
               gsh.sizedefinition_link_id = ilp.sizedefinition_link_id and
               (gsh.status = 0 or (gsh.status = 1 and gsh.workorderline_id is not null)))
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 5 --Sales
        and    il.invoicelinesubtype = 1
        and    il.extend = 'Y'
        group  by il.invoiceline_id, dpx.distributionpoint_id, p.productgroup_id;
    end garment_saleshistory_and_note;

    procedure loss_for_garments is
    begin
      --loss_for_garments
      gv_message := 'loss_for_garments';
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, we.distributionpoint_id, il.billedqty, il.amount,
               p.productgroup_id, gv_systemuserid, sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   weareremployment we
        on     we.weareremployment_id = ilp.weareremployment_link_id
        join   product p
        on     p.product_id = ilp.product_link_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 9 --Loss charges
        and    il.invoicelinesubtype in (16, 33, 34, 35, 36, 39)
        and    il.extend = 'Y';
    end loss_for_garments;

    procedure automatic_replacement is
    begin
      --automatic_replacement
      gv_message := 'automatic_replacement';
      --No link using distributionpoint_id, according to analysis
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, pk.distributionpoint_id, sum(pkl.autoreplacementqty) billedqty,
               sum(pkl.autoreplacementqty * il.price) amount, p.productgroup_id, gv_systemuserid,
               sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   product p
        on     p.product_id = ilp.product_link_id
        join   packingnoteline pkl
        on     (pkl.invoiceheader_id = il.invoiceheader_id and pkl.product_id = ilp.product_link_id and
               pkl.sizedefinition_id = ilp.sizedefinition_link_id and
               pkl.finishingmethod_id = ilp.finishingmethod_id)
        join   packingnote pk
        on     pk.packingnote_id = pkl.packingnote_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 8 --Automatic replacement
        and    il.invoicelinesubtype = 0
        and    il.extend = 'Y'
        and    pkl.autoreplacementqty <> 0
        group  by il.invoiceline_id, pk.distributionpoint_id, p.productgroup_id;
    end automatic_replacement;

    procedure residual_value is
    begin
      --residual_value
      gv_message := 'residual_value';
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, we.distributionpoint_id, il.billedqty, il.amount,
               p.productgroup_id, gv_systemuserid, sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   weareremployment we
        on     we.weareremployment_id = ilp.weareremployment_link_id
        join   product p
        on     p.product_id = ilp.product_link_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 10 --Residual value
        and    il.invoicelinesubtype = 0
        and    il.extend = 'Y';
    end residual_value;

    procedure materialmaintenanceprotection is
    begin
      --materialmaintenanceprotection
      gv_message := 'materialmaintenanceprotection';
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, plpd.distributionpoint_id,
               sum(nvl((select sum(rqa.quantity)
                        from   rentalqtyadjustment rqa
                        where  rqa.productlistperdistribpoint_id =
                               plpd.productlistperdistribpoint_id
                        and    rqa.adjustmentdate <= gv_rec_invoiceheader.invoicedate),
                        (select sum(sdl.fixedrentquantity)
                          from   standarddeliveryline sdl
                          where  sdl.productlistperdistribpoint_id = plpd.productlistperdistribpoint_id))) billedqty,
               sum(nvl((select sum(rqa.quantity)
                        from   rentalqtyadjustment rqa
                        where  rqa.productlistperdistribpoint_id =
                               plpd.productlistperdistribpoint_id
                        and    rqa.adjustmentdate <= gv_rec_invoiceheader.invoicedate),
                        (select sum(sdl.fixedrentquantity)
                          from   standarddeliveryline sdl
                          where  sdl.productlistperdistribpoint_id = plpd.productlistperdistribpoint_id)) *
                    il.price) amount, p.productgroup_id, 1, sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   product p
        on     p.product_id = ilp.product_link_id
        cross  join (select dp.distributionpoint_id
                     from   department t
                     join   distributionpoint dp
                     on     dp.department_id = t.department_id
                     where  t.customer_id =
                            nvl(gv_rec_invoiceheader.deltocustomer_link_id,
                                gv_rec_invoiceheader.billtocustomer_link_id)) dpx
        join   productlistperdistribpoint plpd
        on     (plpd.distributionpoint_id = dpx.distributionpoint_id and
               plpd.product_id = ilp.product_link_id and
               plpd.sizedefinition_id = ilp.sizedefinition_link_id and
               plpd.finishingmethod_id = ilp.finishingmethod_id)
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 11 --Insurance Budget Protection
        and    il.invoicelinesubtype = 26
        and    il.extend = 'Y'
        group  by il.invoiceline_id, plpd.distributionpoint_id, p.productgroup_id;
    end materialmaintenanceprotection;

    procedure garment_protection is
    begin
      --garment_protection
      gv_message := 'garment_protection';
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, we.distributionpoint_id, il.billedqty, il.amount,
               p.productgroup_id, gv_systemuserid, sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   weareremployment we
        on     we.weareremployment_id = ilp.weareremployment_link_id
        join   product p
        on     p.product_id = ilp.product_link_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 11 --Insurance Budget Protection
        and    il.invoicelinesubtype in (27, 28, 29, 30)
        and    il.extend = 'Y';
    end garment_protection;

    procedure prep_charges is
    begin
      --prep_charges
      gv_message := 'prep_charges';
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, ih.distributionpoint_link_id, sum(ih.prepcharge) billedqty,
               sum(ih.amount) amount, p.productgroup_id, gv_systemuserid, sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   weareremployment we
        on     we.weareremployment_id = ilp.weareremployment_link_id
        join   issuehistory ih
        on     (ih.invoiceheader_id = il.invoiceheader_id and
               ih.distributionpoint_link_id = we.distributionpoint_id and
               ih.product_link_id = ilp.product_link_id and
               ih.sizedefinition_link_id = ilp.sizedefinition_link_id)
        join   product p
        on     p.product_id = ih.product_link_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 12 --Stock handling
        and    il.invoicelinesubtype = 9 --Prep charge
        and    ih.issuestatus = 0 -- Charge
        and    il.extend = 'Y'
        and    ilp.product_link_id is not null
        group  by il.invoiceline_id, ih.distributionpoint_link_id, p.productgroup_id;
      if sql%rowcount = 0 then
        begin
          --insert into invoicelinedp
          insert into invoicelinedp
            (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
             systemuser_id, timestamp)
            select il.invoiceline_id, ih.distributionpoint_link_id, sum(ih.prepcharge) billedqty,
                   sum(ih.amount) amount, p.productgroup_id, gv_systemuserid, sysdate
            from   invoiceline il
            join   issuehistory ih
            on     ih.invoiceheader_id = il.invoiceheader_id
            join   product p
            on     p.product_id = ih.product_link_id
            where  il.invoiceheader_id = fp_invoiceheaderid
            and    il.invoicelinetype_id = 12 --Stock handling
            and    il.invoicelinesubtype = 9 --Prep charge
            and    ih.issuestatus = 0 -- Charge
            and    il.extend = 'Y'
            and    not exists (select 1
                    from   invoicelineproduct ilp
                    where  ilp.invoiceline_id = il.invoiceline_id)
            group  by il.invoiceline_id, ih.distributionpoint_link_id, p.productgroup_id;
        end;
      end if;
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, we.distributionpoint_id, il.billedqty billedqty, il.amount amount,
               (select pg.productgroup_id from productgroup pg where pg.code = '999999') productgroup_id,
               gv_systemuserid, sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   weareremployment we
        on     we.weareremployment_id = ilp.weareremployment_link_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 12 --Stock handling
        and    il.invoicelinesubtype = 9 --Prep charge
        and    il.extend = 'Y'
        and    ilp.product_link_id is null;
    end prep_charges;

    procedure emblem_charges is
    begin
      --emblem_charges
      gv_message := 'emblem_charges';
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, eh.distributionpoint_link_id, sum(eh.quantity) billedqty,
               sum(eh.emblemcharge) amount, p.productgroup_id, gv_systemuserid, sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   weareremployment we
        on     we.weareremployment_id = ilp.weareremployment_link_id
        join   emblemhistory eh
        on     (eh.invoiceheader_id = il.invoiceheader_id and
               eh.distributionpoint_link_id = we.distributionpoint_id and
               eh.product_link_id = ilp.product_link_id and
               eh.sizedefinition_link_id = ilp.sizedefinition_link_id)
        join   product p
        on     p.product_id = ilp.product_link_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 12 --Stock handling
        and    il.invoicelinesubtype = 10 --Emblem charge
        and    eh.status = 0 -- Charge
        and    il.extend = 'Y'
        and    ilp.product_link_id is not null
        group  by il.invoiceline_id, eh.distributionpoint_link_id, p.productgroup_id;
      if sql%rowcount = 0 then
        begin
          --insert into invoicelinedp
          insert into invoicelinedp
            (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
             systemuser_id, timestamp)
            select il.invoiceline_id, eh.distributionpoint_link_id, sum(eh.quantity) billedqty,
                   sum(eh.emblemcharge) amount, p.productgroup_id, gv_systemuserid, sysdate
            from   invoiceline il
            join   emblemhistory eh
            on     eh.invoiceheader_id = il.invoiceheader_id
            join   product p
            on     p.product_id = eh.product_link_id
            where  il.invoiceheader_id = fp_invoiceheaderid
            and    il.invoicelinetype_id = 12 --Stock handling
            and    il.invoicelinesubtype = 10 --Emblem charge
            and    eh.status = 0 -- Charge
            and    il.extend = 'Y'
            and    not exists (select 1
                    from   invoicelineproduct ilp
                    where  ilp.invoiceline_id = il.invoiceline_id)
            group  by il.invoiceline_id, eh.distributionpoint_link_id, p.productgroup_id;
        end;
      end if;
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, we.distributionpoint_id, il.billedqty, il.amount,
               (select pg.productgroup_id from productgroup pg where pg.code = '999999') productgroup_id,
               gv_systemuserid, sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   weareremployment we
        on     we.weareremployment_id = ilp.weareremployment_link_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 12 --Stock Handling
        and    il.invoicelinesubtype = 10 --Emblem Charges
        and    il.extend = 'Y'
        and    ilp.product_link_id is null;
    end emblem_charges;

    procedure label_charges is
    begin
      --label_charges
      gv_message := 'label_charges';
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, pq.distributionpoint_link_id, sum(pq.quantity) billedqty,
               sum(pq.amount) amount, p.productgroup_id, gv_systemuserid, sysdate
        from   invoiceline il
        join   printqueue pq
        on     pq.invoiceheader_id = il.invoiceheader_id
        join   labellayout ll
        on     ll.labellayout_id = pq.labellayout_id
        join   product p
        on     p.product_id = pq.product_link_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 12 --Stock handling
        and    il.invoicelinesubtype = 11 --Label charge
        and    pq.status = 0 -- Charge
        and    il.extend = 'Y'
        and    ((ll.labeltype = 1 --LabelType = 1 = Code
              and upper(substr(il.description, 1, 4)) = 'CODE') or
              (ll.labeltype = 2 --LabelType = 2 = Name
              and upper(substr(il.description, 1, 4)) = 'NAME'))
        group  by il.invoiceline_id, pq.distributionpoint_link_id, p.productgroup_id;
    end label_charges;

    procedure restocking_fee is
    begin
      --restocking_fee
      gv_message := 'restocking_fee';
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, och.distributionpoint_link_id, sum(och.quantity) billedqty,
               sum(och.amount) amount, p.productgroup_id, gv_systemuserid, sysdate
        from   invoiceline il
        join   outofcirculationhistory och
        on     och.invoiceheader_id = il.invoiceheader_id
        join   product p
        on     p.product_id = och.product_link_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 12 --Stock handling
        and    il.invoicelinesubtype = 12 --Restocking Fee
        and    och.chargetype = 2 --Restocking Fee
        and    och.status = 0 --Charge
        and    il.extend = 'Y'
        and    not exists
         (select 1 from invoicelineproduct ilp where ilp.invoiceline_id = il.invoiceline_id)
        group  by il.invoiceline_id, och.distributionpoint_link_id, p.productgroup_id;
    end restocking_fee;

    procedure custom_garment_charge is
    begin
      --custom_garment_charge
      gv_message := 'custom_garment_charge';
      --insert into invoicelinedp
      insert into invoicelinedp
        (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
         systemuser_id, timestamp)
        select il.invoiceline_id, we.distributionpoint_id, il.billedqty, il.amount,
               p.productgroup_id, gv_systemuserid, sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   weareremployment we
        on     we.weareremployment_id = ilp.weareremployment_link_id
        join   product p
        on     p.product_id = ilp.product_link_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 34 --Custom Garment Charge
        and    il.invoicelinesubtype = 0
        and    il.extend = 'Y';
    end custom_garment_charge;

  /*  procedure missing_automatic_replacem is
    begin
      ---check missing automatic repplacements
      gv_message := 'missing_automatic_replacem';
      for y in (select il.invoiceline_id, il.amount, il.billedqty, p.productgroup_id
                from   invoiceline il
                join   invoiceheader ih
                on     ih.invoiceheader_id = il.invoiceheader_id
                join   invoicelineproduct ilp
                on     ilp.invoiceline_id = il.invoiceline_id
                join   product p
                on     p.product_id = ilp.product_link_id
                where  not exists (select 1
                        from   invoicelinedp ildp
                        where  ildp.invoiceline_id = il.invoiceline_id)
                and    il.invoicelinetype_id = 8
                and    il.invoicelinesubtype = 0
                and    il.extend = 'Y'
                and    il.invoiceheader_id = fp_invoiceheaderid
                and    ih.invoicenumber > 0
                and    ih.invoicedate > sysdate - 365
                and    il.amount <> 0) loop
        begin
          for z in (select zz.distributionpoint_link_id,
                           round(((zz.dip_amount / zz.ih_sum) * 100), 2) factor, zz.dip_amount,
                           zz.ih_sum
                    from   (select ildp.distributionpoint_link_id, sum(ildp.amount) dip_amount,
                                    sum((select sum(wx.amount)
                                         from   invoicelinedp wx
                                         join   invoiceline lx
                                         on     lx.invoiceline_id = wx.invoiceline_id
                                         where  lx.invoiceheader_id = il.invoiceheader_id
                                         and    wx.productgroup_id = ildp.productgroup_id)) ih_sum
                             from   invoicelinedp ildp
                             join   invoiceline il
                             on     il.invoiceline_id = ildp.invoiceline_id
                             where  il.invoiceheader_id = fp_invoiceheaderid
                             and    ildp.productgroup_id = y.productgroup_id
                             group  by ildp.distributionpoint_link_id, il.invoiceheader_id
                             having sum(ildp.amount) <> 0) zz) loop
            begin
              --devide on invoiceline
              gv_message := 'devide on invoiceline';
              insert into invoicelinedp
                (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
                 systemuser_id, timestamp, factor)
              values
                (y.invoiceline_id, z.distributionpoint_link_id,
                 round((y.billedqty * z.factor / 100), 2), round((y.amount * z.factor / 100), 2),
                 y.productgroup_id, gv_systemuserid, sysdate, z.factor);
            end;
          end loop;
        end;
      end loop;
    end missing_automatic_replacem;*/

    procedure missing_automatic_replacem is
    begin
      ---check missing automatic repplacements
      gv_message := 'missing_automatic_replacem';
      for y in (select il.invoiceline_id, il.amount, il.billedqty, p.productgroup_id
                from   invoiceline il
                join   invoiceheader ih
                on     ih.invoiceheader_id = il.invoiceheader_id
                join   invoicelineproduct ilp
                on     ilp.invoiceline_id = il.invoiceline_id
                join   product p
                on     p.product_id = ilp.product_link_id
                where  not exists (select 1
                        from   invoicelinedp ildp
                        where  ildp.invoiceline_id = il.invoiceline_id)
                and    il.invoicelinetype_id = 8
                and    il.invoicelinesubtype = 0
                and    il.extend = 'Y'
                and    il.invoiceheader_id = fp_invoiceheaderid
                and    ih.invoicenumber > 0
                and    ih.invoicedate > sysdate - 365
                and    il.amount <> 0) loop
        begin
          for z in (select il.invoiceline_id, plpd.distributionpoint_id,
               (sum(nvl((select sum(rqa.quantity)
                        from   rentalqtyadjustment rqa
                        where  rqa.productlistperdistribpoint_id =
                               plpd.productlistperdistribpoint_id
                        and    rqa.adjustmentdate <= gv_rec_invoiceheader.invoicedate),
                        (select sum(sdl.fixedrentquantity)
                          from   standarddeliveryline sdl
                          where  sdl.productlistperdistribpoint_id = plpd.productlistperdistribpoint_id)))/sum(tot.billedqty))*100 factor,
                sum(nvl((select sum(rqa.quantity)
                        from   rentalqtyadjustment rqa
                        where  rqa.productlistperdistribpoint_id =
                               plpd.productlistperdistribpoint_id
                        and    rqa.adjustmentdate <= gv_rec_invoiceheader.invoicedate),
                        (select sum(sdl.fixedrentquantity)
                          from   standarddeliveryline sdl
                          where  sdl.productlistperdistribpoint_id = plpd.productlistperdistribpoint_id))) billedqty,
               sum(nvl((select sum(rqa.quantity)
                        from   rentalqtyadjustment rqa
                        where  rqa.productlistperdistribpoint_id =
                               plpd.productlistperdistribpoint_id
                        and    rqa.adjustmentdate <= gv_rec_invoiceheader.invoicedate),
                        (select sum(sdl.fixedrentquantity)
                          from   standarddeliveryline sdl
                          where  sdl.productlistperdistribpoint_id = plpd.productlistperdistribpoint_id)) *
                    il.price) amount, p.productgroup_id, gv_systemuserid, sysdate
        from   invoiceline il
        join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   product p
        on     p.product_id = ilp.product_link_id
        join (select il.invoiceline_id,
               sum(nvl((select sum(rqa.quantity)
                        from   rentalqtyadjustment rqa
                        where  rqa.productlistperdistribpoint_id =
                               plpd.productlistperdistribpoint_id
                        and    rqa.adjustmentdate <= gv_rec_invoiceheader.invoicedate),
                        (select sum(sdl.fixedrentquantity)
                          from   standarddeliveryline sdl
                          where  sdl.productlistperdistribpoint_id = plpd.productlistperdistribpoint_id))) billedqty
               from   invoiceline il
                join   invoicelineproduct ilp
        on     ilp.invoiceline_id = il.invoiceline_id
        join   product p
        on     p.product_id = ilp.product_link_id
        join   productlistperdistribpoint plpd
        on     (plpd.product_id = ilp.product_link_id and
               plpd.sizedefinition_id = ilp.sizedefinition_link_id and
               plpd.finishingmethod_id = ilp.finishingmethod_id)
        join (select dp.distributionpoint_id
              from   department t
              join   distributionpoint dp
              on     dp.department_id = t.department_id
              where  t.customer_id =
                nvl(gv_rec_invoiceheader.deltocustomer_link_id,
                    gv_rec_invoiceheader.billtocustomer_link_id)) dpx
        on dpx.distributionpoint_id = plpd.distributionpoint_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 8 --systematic replacement
        and    il.invoicelinesubtype = 0
        and    il.extend = 'Y'
        and    il.invoiceline_id=y.invoiceline_id
        group  by il.invoiceline_id) tot on tot.invoiceline_id=il.invoiceline_id
        join   productlistperdistribpoint plpd
        on     (plpd.product_id = ilp.product_link_id and
               plpd.sizedefinition_id = ilp.sizedefinition_link_id and
               plpd.finishingmethod_id = ilp.finishingmethod_id)
                join (select dp.distributionpoint_id
              from   department t
              join   distributionpoint dp
              on     dp.department_id = t.department_id
              where  t.customer_id =
                nvl(gv_rec_invoiceheader.deltocustomer_link_id,
                    gv_rec_invoiceheader.billtocustomer_link_id)) dpx
        on dpx.distributionpoint_id = plpd.distributionpoint_id
        where  il.invoiceheader_id = fp_invoiceheaderid
        and    il.invoicelinetype_id = 8 --systematic replacement
        and    il.invoicelinesubtype = 0
        and    il.extend = 'Y'
        and    il.invoiceline_id=y.invoiceline_id
        group  by il.invoiceline_id, plpd.distributionpoint_id, p.productgroup_id) loop
            begin
              --devide on invoiceline
              gv_message := 'devide on invoiceline';
              insert into invoicelinedp
                (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
                 systemuser_id, timestamp, factor)
              values
                (y.invoiceline_id, z.distributionpoint_id,
                 round((y.billedqty * z.factor/100 ), 2), round((y.amount * z.factor/100), 2),
                 y.productgroup_id, gv_systemuserid, sysdate, z.factor);
            end;
          end loop;
        end;
      end loop;
    end missing_automatic_replacem;


    procedure split_department_leftover_nt is
    begin
      --split per deparment left overs
      for y in (select il.invoiceline_id, il.amount, il.billedqty
                from   invoiceline il
                join   invoiceheader ih
                on     ih.invoiceheader_id = il.invoiceheader_id
                where  not exists (select 1
                        from   invoicelinedp ildp
                        where  ildp.invoiceline_id = il.invoiceline_id)
                and    il.extend = 'Y'
                and    il.invoiceheader_id = fp_invoiceheaderid
                and    ih.invoicenumber > 0
                and    ih.invoicedate > sysdate - 365
                and    il.amount <> 0
                and    il.invoicelinetype_id <> 18 --exclude tax lines
                ) loop
        begin
          for z in (select zz.distributionpoint_link_id,
                           round(((zz.dip_amount / zz.ih_sum) * 100), 2) factor, zz.dip_amount,
                           zz.ih_sum
                    from   (select ildp.distributionpoint_link_id, sum(ildp.amount) dip_amount,
                                    (select sum(wx.amount)
                                      from   invoicelinedp wx
                                      join   invoiceline lx
                                      on     lx.invoiceline_id = wx.invoiceline_id
                                      where  lx.invoiceheader_id = il.invoiceheader_id) ih_sum
                             from   invoicelinedp ildp
                             join   invoiceline il
                             on     il.invoiceline_id = ildp.invoiceline_id
                             where  il.invoiceheader_id = fp_invoiceheaderid
                             and    il.invoicelinetype_id <> 18 --exclude tax lines
                             group  by ildp.distributionpoint_link_id, il.invoiceheader_id
                             having sum(ildp.amount) <> 0) zz) loop
            begin
              --devide on invoiceline
              gv_message := 'devide on invoiceline';
              insert into invoicelinedp
                (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
                 systemuser_id, timestamp, factor)
              values
                (y.invoiceline_id, z.distributionpoint_link_id,
                 round((y.billedqty * z.factor / 100), 2), round((y.amount * z.factor / 100), 2),
                 gv_def_productgroupid, gv_systemuserid, sysdate, z.factor);
            end;
          end loop;
        end;
      end loop;
    end split_department_leftover_nt;

    procedure split_department_leftover_wt is
    begin
      --split per deparment left overs
      for y in (select il.invoiceline_id, il.amount, il.billedqty
                from   invoiceline il
                join   invoiceheader ih
                on     ih.invoiceheader_id = il.invoiceheader_id
                where  not exists (select 1
                        from   invoicelinedp ildp
                        where  ildp.invoiceline_id = il.invoiceline_id)
                and    il.extend = 'Y'
                and    il.invoiceheader_id = fp_invoiceheaderid
                and    ih.invoicenumber > 0
                and    ih.invoicedate > sysdate - 365
                and    il.amount <> 0
                and    il.invoicelinetype_id = 18 --exclude tax lines
                ) loop
        begin
          for z in (select zz.distributionpoint_link_id,
                           round(((zz.dip_amount / zz.ih_sum) * 100), 2) factor, zz.dip_amount,
                           zz.ih_sum
                    from   (select ildp.distributionpoint_link_id, sum(ildp.amount) dip_amount,
                                    (select sum(wx.amount)
                                      from   invoicelinedp wx
                                      join   invoiceline lx
                                      on     lx.invoiceline_id = wx.invoiceline_id
                                      where  lx.invoiceheader_id = il.invoiceheader_id
                                      and    lx.taxtype in (1, 2, 3)) ih_sum
                             from   invoicelinedp ildp
                             join   invoiceline il
                             on     il.invoiceline_id = ildp.invoiceline_id
                             where  il.invoiceheader_id = fp_invoiceheaderid
                             and    il.taxtype in (1, 2, 3)
                             group  by ildp.distributionpoint_link_id, il.invoiceheader_id
                             having sum(ildp.amount) <> 0) zz) loop
            begin
              --devide on invoiceline
              gv_message := 'devide on invoiceline';
              insert into invoicelinedp
                (invoiceline_id, distributionpoint_link_id, billedqty, amount, productgroup_id,
                 systemuser_id, timestamp, factor)
              values
                (y.invoiceline_id, z.distributionpoint_link_id,
                 round((y.billedqty * z.factor / 100), 2), round((y.amount * z.factor / 100), 2),
                 gv_def_productgroupid, gv_systemuserid, sysdate, z.factor);
            end;
          end loop;
        end;
      end loop;
    end split_department_leftover_wt;

    procedure check_line_totals is
    begin
      --check_line_totals
      gv_message := 'check_line_totals';
      for yes in (select y.invoiceline_id, sum(x.billedqty) nowbilledqty,
                         max(y.billedqty) linebillqty, max(y.price) price,
                         (max(y.billedqty) - sum(x.billedqty)) diffqty, x.productgroup_id,
                         max(x.distributionpoint_link_id) distributionpoint_link_id
                  from   invoicelinedp x
                  join   invoiceline y
                  on     y.invoiceline_id = x.invoiceline_id
                  where  y.invoiceheader_id = fp_invoiceheaderid
                  group  by y.invoiceline_id, x.productgroup_id
                  having round(sum(x.billedqty)) <> max(y.billedqty)) loop
        begin
          if yes.nowbilledqty = 0 then
            begin
              update invoicelinedp ff
              set    ff.billedqty = ff.billedqty + yes.diffqty,
                     ff.amount = round((ff.billedqty + yes.diffqty) * yes.price, 2)
              where  ff.invoiceline_id = yes.invoiceline_id
              and    ff.distributionpoint_link_id = yes.distributionpoint_link_id
              and    ff.productgroup_id = yes.productgroup_id;
            end;
          else
            begin
              for joe in (select rr.distributionpoint_link_id,
                                 round(((yes.diffqty / yes.nowbilledqty) * rr.billedqty), 2) addqty
                          from   invoicelinedp rr
                          where  rr.invoiceline_id = yes.invoiceline_id
                          and    rr.productgroup_id = yes.productgroup_id) loop
                begin
                  update invoicelinedp ff
                  set    ff.billedqty = ff.billedqty + joe.addqty,
                         ff.amount = round((ff.billedqty + joe.addqty) * yes.price, 2)
                  where  ff.invoiceline_id = yes.invoiceline_id
                  and    ff.distributionpoint_link_id = joe.distributionpoint_link_id
                  and    ff.productgroup_id = yes.productgroup_id;
                end;
              end loop; --joe
            end;
          end if;
        end;
      end loop; --zz;
      for fact in (select il.invoiceline_id, idp.factor, round((idp.billedqty/il.billedqty)*100,2) newfact, idp.distributionpoint_link_id, idp.productgroup_id
                  from   invoicelinedp idp
                  join   invoiceline il
                  left outer join invoicelineproduct ilp on ilp.invoiceline_id=il.invoiceline_id
                  on     il.invoiceline_id = idp.invoiceline_id
                  where  il.invoiceheader_id = fp_invoiceheaderid
                  and    idp.factor<>round((idp.billedqty/il.billedqty)*100,2)
                 AND ((il.invoicelinetype_id = 8 AND il.invoicelinesubtype = 0) or (il.invoicelinetype_id = 1 AND il.invoicelinesubtype = 0) or
                    ( il.invoicelinetype_id = 2 --Wash
                   and    ((il.invoicelinesubtype = 0) or
                   (il.invoicelinesubtype = 15 and ilp.weareremployment_link_id is null))))) loop
           begin
              update invoicelinedp idpf
              set    idpf.factor=fact.newfact
              where  idpf.invoiceline_id = fact.invoiceline_id
              and    idpf.distributionpoint_link_id = fact.distributionpoint_link_id
              and    idpf.productgroup_id = fact.productgroup_id;
            end;
       end loop;

    end check_line_totals;
  begin
    --process_invoicelines
    for x in (select il.invoicelinetype_id,
                     case
                       when il.invoicelinetype_id = 1 and il.invoicelinesubtype in (1, 2) then
                        1
                       when il.invoicelinetype_id = 2 and ((il.invoicelinesubtype in (1, 2, 3, 4)) or
                            (il.invoicelinesubtype = 15 and
                            ilpr.weareremployment_link_id is not null)) then
                        1
                       when il.invoicelinetype_id = 2 and
                            ((il.invoicelinesubtype = 0) or
                            (il.invoicelinesubtype = 15 and ilpr.weareremployment_link_id is null)) then
                        0
                       when il.invoicelinetype_id = 9 and
                            il.invoicelinesubtype in (16, 33, 34, 35, 36, 39) then
                        16
                       when il.invoicelinetype_id = 11 and il.invoicelinesubtype in (27, 28, 29, 30) then
                        27
                       else
                        il.invoicelinesubtype
                     end invoicelinesubtype
              from   invoiceline il
              left   outer join invoicelineproduct ilpr
              on     ilpr.invoiceline_id = il.invoiceline_id
              where  il.invoiceheader_id = fp_invoiceheaderid
              and    il.extend = 'Y'
              group  by il.invoicelinetype_id,
                        case
                          when il.invoicelinetype_id = 1 and il.invoicelinesubtype in (1, 2) then
                           1
                          when il.invoicelinetype_id = 2 and
                               ((il.invoicelinesubtype in (1, 2, 3, 4)) or
                               (il.invoicelinesubtype = 15 and
                               ilpr.weareremployment_link_id is not null)) then
                           1
                          when il.invoicelinetype_id = 2 and
                               ((il.invoicelinesubtype = 0) or
                               (il.invoicelinesubtype = 15 and ilpr.weareremployment_link_id is null)) then
                           0
                          when il.invoicelinetype_id = 9 and
                               il.invoicelinesubtype in (16, 33, 34, 35, 36, 39) then
                           16
                          when il.invoicelinetype_id = 11 and
                               il.invoicelinesubtype in (27, 28, 29, 30) then
                           27
                          else
                           il.invoicelinesubtype
                        end
              order  by il.invoicelinetype_id) loop
      begin
        case x.invoicelinetype_id
          when 1 then
            --2.2 RENT
            case
              when x.invoicelinesubtype in (1, 2) then
                rent_garments;
              when x.invoicelinesubtype = 0 then
                rent_non_garments;
              else
                null; --Skip
            end case; --RENT
          when 2 then
            --2.3 WASH
            case
              when x.invoicelinesubtype in (1, 2, 3, 4) then
                --wash_per_wearer
                wash_per_wearer;
              when x.invoicelinesubtype = 0 then
                --wash_other
                wash_other;
              else
                null; --Skip
            end case; --WASH
          when 5 then
            --2.4 SALES
            case
              when x.invoicelinesubtype = 0 then
                --sales_via_deliverynote
                sales_via_deliverynote;
              when x.invoicelinesubtype = 1 then
                --garment_saleshistory_and_note
                garment_saleshistory_and_note;
              else
                null; --Skip
            end case; --SALES
          when 9 then
            --2.5 LOSS
            case
              when x.invoicelinesubtype in (16, 33, 34, 35, 36, 39) then
                --loss_for_garments
                loss_for_garments;
              else
                null; --Skip
            end case; --LOSS
          when 8 then
            --2.6 AUTOMATIC REPLACEMENT
            case
              when x.invoicelinesubtype = 0 then
                --automatic_replacement
                automatic_replacement;
              else
                null; --Skip
            end case; --AUTOMATIC REPLACEMENT
          when 10 then
            --2.7 RESIDUAL VALUE
            case
              when x.invoicelinesubtype = 0 then
                --Residual_Value
                residual_value;
              else
                null; --Skip
            end case; --RESIDUAL VALUE
          when 11 then
            --2.8 INSURANCE_BUDGETPROTECTION
            case
              when x.invoicelinesubtype = 26 then
                --materialmaintenanceprotection
                materialmaintenanceprotection;
              when x.invoicelinesubtype in (27, 28, 29, 30) then
                --garment_protection
                garment_protection;
              else
                null; --Skip
            end case; --INSURANCE_BUDGETPROTECTION
          when 12 then
            --2.9 STOCKROOM_HANDLING
            case
              when x.invoicelinesubtype = 9 then
                --prep_charges
                prep_charges;
              when x.invoicelinesubtype = 10 then
                --emblem_charges
                emblem_charges;
              when x.invoicelinesubtype = 11 then
                --label_charges
                label_charges;
              when x.invoicelinesubtype = 12 then
                --restocking_fee
                restocking_fee;
              else
                null; --Skip
            end case; --STOCKROOM_HANDLING
          when 34 then
            --2.11 CUSTOM_GARMENT_CHARGE
            case
              when x.invoicelinesubtype = 0 then
                --custom_garment_charge
                custom_garment_charge;
              else
                null; --Skip
            end case; --CUSTOM_GARMENT_CHARGE
          else
            null; --Skip
        end case; --x.invoicelinetype_id
      end;
    end loop; --x
    --missing_automatic_replace
    missing_automatic_replacem;
    --split_department_leftover
    split_department_leftover_nt;
    split_department_leftover_wt;
    --check_line_totals
    check_line_totals;
  end process_invoicelines;

  procedure finalize is
  begin
    --finalize
    gv_message := 'Finalize';
    --commit;
    commit;
    fp_dpcostspecification := 0; -- Ok
  end finalize;

begin
  --initialize
  initialize;
  --process_invoicelines
  process_invoicelines;
  --finalize
  finalize;
exception
  when gv_user_exception then
    begin
      rollback;
      write_log(gv_message, 3);
      fp_dpcostspecification := 1; -- 1=Error
    end;
  when no_data_found then
    begin
      rollback;
      write_log('No data found! ' || trim(nvl(gv_message, ' ')) || ' ' || sqlerrm, 3);
      fp_dpcostspecification := 1; -- 1=Error
    end;
  when others then
    begin
      rollback;
      write_log('Error others ' || trim(nvl(gv_message, ' ')) || ' ' || sqlerrm, 3);
      fp_dpcostspecification := 1; -- 1=Error
    end;
end dpcostspecification;
/
create or replace procedure dropColumnInfo(
	sTableName	varchar2,
	sColumnName	varchar2
) is
	tableName varchar2(30):=ltrim(rtrim(upper(sTableName)));
	columnName varchar2(30):=ltrim(rtrim(upper(sColumnName)));
begin
  for c in (select i.index_name from user_ind_columns i
						where i.table_name = tableName and i.column_name = columnName) loop
		dbms_output.put_line(upper('drop index '||c.index_name||';'));
		dbms_output.new_line;
	end loop;
	for c in (select c.constraint_name from user_cons_columns c
							where c.table_name = tableName and
										c.column_name = columnName and
										c.constraint_name not like 'SYS_C%') loop
		dbms_output.put_line(upper('alter table '||tableName||' drop constraint '||c.constraint_name||';'));
		dbms_output.new_line;
	end loop;
	for c in (select 'DF__'||tableName||'__'||columnName constraintName from user_tab_columns c
							where c.table_name = tableName and
										c.column_name = columnName and
										c.data_default is not null) loop
		dbms_output.put_line(upper('alter table '||tableName||' drop constraint '||c.constraintName||';'));
		dbms_output.new_line;
	end loop;
	dbms_output.put_line(upper('alter table '||tableName||' drop column '||columnName||';'));
	dbms_output.new_line;
end;
/
create or replace procedure dropIndex(
	sIndexName	varchar2
) is
  cursor_name integer;
  rows_processed INTEGER;
begin
  cursor_name := dbms_sql.open_cursor;
  dbms_sql.parse(cursor_name, 'drop index '|| sIndexName, dbms_sql.native);
  rows_processed := dbms_sql.execute(cursor_name);
  dbms_sql.close_cursor(cursor_name);
exception
  when others then
     dbms_sql.close_cursor(cursor_name);
end dropIndex;
/
create or replace procedure EXPORT2MAMUT(FP_BUSINESSUNITID in BUSINESSUNIT.BUSINESSUNIT_ID%type,
                                         FP_SYSTEMUSERID   in SYSTEMUSER.SYSTEMUSER_ID%type,
                                         FP_STATUS_NUMBER  out number, --> 1 = error , 0 = ok
                                         FP_ABSLOGMESSAGE  out ABSLOG.MESSAGE%type --> Ok or the error message in case of error
                                         ) is
  --Version 0.01 Export to ABM
  --global variables
  GV_USEREXCEPTION    exception;
  GV_FILEEXISTS       exception;
  GV_FILEHANDLE       UTL_FILE.FILE_TYPE;
  GV_FILENAME         varchar2(128);
  GV_DEFAULTDIR       varchar2(256);
  GV_PLANTID          PLANT.PLANT_ID%type;
  GV_BUSINESSUNITCODE BUSINESSUNIT.CODE%type;
  GV_LEGALENTITYCODE  LEGALENTITY.CODE%type;
  GV_LANGUAGEID       LANGUAGES.LANGUAGE_ID%type;
  GV_SEPERATOR        varchar2(1) := ',';
  GV_CURRENTDATE      date;
  GV_ABSLOGMESSAGE    ABSLOG.MESSAGE%type;

  -- General used fields
  M_SYSTEM              varchar2(10) := 'GBAT10';
  M_DOCUMENT_TYPE       varchar2(1) := '1';
  M_INVOICENUMBER       INVOICEHEADER.INVOICENUMBER%type;
  M_ARTRANSACTIONDATE   ARTRANSACTION.ARTRANSACTIONDATE%type;
  M_MONTH               varchar(2);
  M_AMOUNT              number;
  M_CUSTOMERNUMBER      CUSTOMER.CUSTOMERNUMBER%type;
  M_CUSTOMERNAME        CUSTOMER.NAME%type;
  M_PAYMENTTERMSDUEDATE INVOICEHEADEREXTRAINFO.PAYMENTTERMSDUEDATE%type;
  M_NET                 varchar2(1) := 'T';
  M_KID                 varchar2(30);
  M_LEDGER_1510         varchar2(7) := '1510';
  M_LEDGER_3010         varchar2(7) := '3010';
  M_VAT_1               varchar2(5) := '1';
  M_VAT_10123           varchar2(5) := '10123';
  M_PAYMENTTERMS        varchar2(1) := '1';

  GV_TOTALAMOUNT ARTRANSACTION.AMOUNT%type := 0;

  --internal procedures
  procedure WRITE_LOG(FP_MESSAGE  in varchar2,
                      FP_PRIORITY in number default 1) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    ABSLOGWRITE.ABSLOG_WRITE(5,
                             'EXPORT2MAMUT',
                             GV_PLANTID,
                             FP_PRIORITY,
                             FP_MESSAGE,
                             FP_SYSTEMUSERID);
  end WRITE_LOG;

  procedure CLOSE_FILE is
  begin
    --close file(s)
    if UTL_FILE.IS_OPEN(GV_FILEHANDLE) = true then
      UTL_FILE.FCLOSE(GV_FILEHANDLE);
    end if;
  end CLOSE_FILE;

  procedure DELETE_FILE is
  begin
    --delete_file
    UTL_FILE.FREMOVE(GV_DEFAULTDIR, GV_FILENAME);
  end DELETE_FILE;

  procedure INITIALIZE is
    PV_SEPARATOR number;
    LV_SUFFIX    SYSTEMSETTING.VALUE%type;
  begin
    --initialize
    --get businessunit
    FP_ABSLOGMESSAGE := 'Initialize, businessunit id ' ||
                        TO_CHAR(FP_BUSINESSUNITID);
    select BU.PLANT_ID,
           BU.CODE,
           (select LPAD(SUBSTR(LE.CODE, 1, 4), 4, '0')
              from LEGALENTITY LE
             where LE.LEGALENTITY_ID = BU.LEGALENTITY_ID),
           (select PT.LANGUAGE_ID
              from PLANT PT
             where PT.PLANT_ID = BU.PLANT_ID) LANGUAGE_ID
      into GV_PLANTID,
           GV_BUSINESSUNITCODE,
           GV_LEGALENTITYCODE,
           GV_LANGUAGEID
      from BUSINESSUNIT BU
     where BU.BUSINESSUNIT_ID = FP_BUSINESSUNITID;
    --get system setting parameter for directory
    FP_ABSLOGMESSAGE := 'Initialize, get systemsetting FINEXPORTDIRECTORY (must be accessible for Oracle) for plant id ' ||
                        TO_CHAR(GV_PLANTID);
    select S.VALUE
      into GV_DEFAULTDIR
      from SYSTEMSETTING S
     where S.NAME = 'FINEXPORTDIRECTORY'
       and S.PLANT_ID = GV_PLANTID;

    select S.VALUE
      into PV_SEPARATOR
      from SYSTEMSETTING S
     where S.NAME = 'CSVGRIDEXPORTSEPARATOR'
       and S.PLANT_ID = GV_PLANTID;
    if PV_SEPARATOR = 2 then
      GV_SEPERATOR := ';';
    end if;

    GV_FILENAME := 'ABM_' || GV_BUSINESSUNITCODE || '_' ||
                   TO_CHAR(GV_CURRENTDATE, 'YYYYMMDD_HH24MI') || '.csv';

    FP_ABSLOGMESSAGE := ' get systemsetting FINEXPORTFILENAME for plant id ' ||
                        TO_CHAR(GV_PLANTID);
    select S.VALUE
      into GV_FILENAME
      from SYSTEMSETTING S
     where S.NAME = 'FINEXPORTFILENAME'
       and S.PLANT_ID = GV_PLANTID;

    --get system setting parameter for FINEXPORTFILENAMESUFFIX
    FP_ABSLOGMESSAGE := ' get systemsetting FINEXPORTFILENAMESUFFIX for plant id ' ||
                        TO_CHAR(GV_PLANTID);
    select NVL(max(trim(S.VALUE)), '0')
      into LV_SUFFIX
      from SYSTEMSETTING S
     where S.NAME = 'FINEXPORTFILENAMESUFFIX'
       and S.PLANT_ID = GV_PLANTID;
    case LV_SUFFIX
      when '1' then
        begin
          GV_FILENAME := SUBSTR(GV_FILENAME, 1, INSTR(GV_FILENAME, '.') - 1) || '_' ||
                         TO_CHAR(sysdate, 'YYYY-MM-DD') ||
                         SUBSTR(GV_FILENAME, INSTR(GV_FILENAME, '.'));
        end;
      when '2' then
        begin
          GV_FILENAME := SUBSTR(GV_FILENAME, 1, INSTR(GV_FILENAME, '.') - 1) || '_' ||
                         TO_CHAR(sysdate, 'YYYY-MM-DD_HH24MISS') ||
                         SUBSTR(GV_FILENAME, INSTR(GV_FILENAME, '.'));
        end;
      else
        null; --no suffix
    end case;

    select sysdate into GV_CURRENTDATE from DUAL;
  end INITIALIZE;

  function OPEN_FILE return UTL_FILE.FILE_TYPE is
  begin
    begin
      ---First check if file exists, if exist do NOT overwrite.
      GV_FILEHANDLE := UTL_FILE.FOPEN(GV_DEFAULTDIR, GV_FILENAME, 'r');
      CLOSE_FILE;
      FP_ABSLOGMESSAGE := 'The file ' || GV_FILENAME ||
                          ' already exists in directory ' || GV_DEFAULTDIR;
      raise GV_FILEEXISTS;
    exception
      when GV_FILEEXISTS then
        raise GV_FILEEXISTS;
      when others then
        --open file
        FP_ABSLOGMESSAGE := 'create the file in directory ' ||
                            GV_DEFAULTDIR || ' filename ' || GV_FILENAME;
        return UTL_FILE.FOPEN(GV_DEFAULTDIR, GV_FILENAME, 'w', 32767);
    end;
  exception
    when UTL_FILE.INVALID_PATH then
      RAISE_APPLICATION_ERROR(-20100, 'Invalid Path');
    when UTL_FILE.INVALID_MODE then
      RAISE_APPLICATION_ERROR(-20101, 'Invalid Mode');
    when UTL_FILE.INVALID_OPERATION then
      RAISE_APPLICATION_ERROR(-20102, 'Invalid Operation');
    when UTL_FILE.INVALID_FILEHANDLE then
      RAISE_APPLICATION_ERROR(-20103, 'Invalid FileHandle');
    when UTL_FILE.WRITE_ERROR then
      RAISE_APPLICATION_ERROR(-20104, 'Write Error');
    when UTL_FILE.READ_ERROR then
      RAISE_APPLICATION_ERROR(-20105, 'Read Error');
    when UTL_FILE.INTERNAL_ERROR then
      RAISE_APPLICATION_ERROR(-20106, 'Internal Error');
  end OPEN_FILE;

  procedure EXPORT2FILE is
    function F_AMOUNT(FP_AMOUNT in number, FP_LENGTH in number)
      return varchar2 is
    begin
      return LPAD(TO_CHAR(FP_AMOUNT,
                          '9999999999990D00',
                          'NLS_NUMERIC_CHARACTERS='', '''),
                  FP_LENGTH,
                  ' ');
    end F_AMOUNT;

    procedure WRITE_LINE(FP_EXPORT_STRING in varchar2) is
    begin
      --write_line
      UTL_FILE.PUT_LINE(GV_FILEHANDLE,
                        CONVERT(FP_EXPORT_STRING,
                                'WE8ISO8859P15',
                                'AL32UTF8'));

    end WRITE_LINE;

    procedure WRITE_ROW1 is
    begin
      FP_ABSLOGMESSAGE := 'write_row_1';
      WRITE_LINE(M_SYSTEM || GV_SEPERATOR || TO_CHAR(M_INVOICENUMBER) ||
                 GV_SEPERATOR || TO_CHAR(M_ARTRANSACTIONDATE, 'YYYYMMDD') ||
                 GV_SEPERATOR || M_DOCUMENT_TYPE || GV_SEPERATOR ||
                 M_MONTH || GV_SEPERATOR ||
                 TO_CHAR(M_ARTRANSACTIONDATE, 'YYYY') || GV_SEPERATOR ||
                 M_LEDGER_1510 || GV_SEPERATOR || M_VAT_1 || GV_SEPERATOR ||
                 TO_CHAR(M_AMOUNT) || GV_SEPERATOR ||
                 TO_CHAR(M_CUSTOMERNUMBER) || GV_SEPERATOR || GV_SEPERATOR ||
                 M_CUSTOMERNAME || GV_SEPERATOR || GV_SEPERATOR ||
                 GV_SEPERATOR || GV_SEPERATOR || TO_CHAR(M_INVOICENUMBER) ||
                 GV_SEPERATOR || M_KID || GV_SEPERATOR ||
                 TO_CHAR(M_PAYMENTTERMSDUEDATE, 'YYYYMMDD') ||
                 GV_SEPERATOR || GV_SEPERATOR || GV_SEPERATOR ||
                 GV_SEPERATOR || GV_SEPERATOR || GV_SEPERATOR ||
                 GV_SEPERATOR || GV_SEPERATOR || M_PAYMENTTERMS ||
                 GV_SEPERATOR || M_NET || GV_SEPERATOR || TO_CHAR(M_AMOUNT));
    end WRITE_ROW1;

    procedure WRITE_ROW2 is
    begin
      FP_ABSLOGMESSAGE := 'write_row_2';
      WRITE_LINE(M_SYSTEM || GV_SEPERATOR || TO_CHAR(M_INVOICENUMBER) ||
                 GV_SEPERATOR || TO_CHAR(M_ARTRANSACTIONDATE, 'YYYYMMDD') ||
                 GV_SEPERATOR || M_DOCUMENT_TYPE || GV_SEPERATOR ||
                 M_MONTH || GV_SEPERATOR ||
                 TO_CHAR(M_ARTRANSACTIONDATE, 'YYYY') || GV_SEPERATOR ||
                 M_LEDGER_3010 || GV_SEPERATOR || M_VAT_10123 ||
                 GV_SEPERATOR || TO_CHAR(M_AMOUNT * -1) || GV_SEPERATOR ||
                 GV_SEPERATOR || GV_SEPERATOR || GV_SEPERATOR ||
                 GV_SEPERATOR || GV_SEPERATOR || GV_SEPERATOR ||
                 GV_SEPERATOR || GV_SEPERATOR || GV_SEPERATOR ||
                 GV_SEPERATOR || GV_SEPERATOR || GV_SEPERATOR ||
                 GV_SEPERATOR || GV_SEPERATOR || GV_SEPERATOR ||
                 GV_SEPERATOR || M_PAYMENTTERMS || GV_SEPERATOR || M_NET ||
                 GV_SEPERATOR || TO_CHAR(M_AMOUNT * -1));
    end WRITE_ROW2;

  begin
    --export2file
    FP_ABSLOGMESSAGE := 'export2file';
    for X in (select AR.INVOICENUMBER,
                     AR.ARTRANSACTIONDATE,
                     sum(AR.AMOUNT) AMOUNT,
                     BILLTO.CUSTOMERNUMBER,
                     BILLTO.NAME,
                     IHEI.PAYMENTTERMSDUEDATE
                from ARTRANSACTION AR
                join INVOICEHEADER IH
                  on IH.INVOICEHEADER_ID = AR.INVOICEHEADER_ID
                join INVOICEHEADEREXTRAINFO IHEI
                  on IHEI.INVOICEHEADER_ID = IH.INVOICEHEADER_ID
                join CUSTOMER BILLTO
                  on BILLTO.CUSTOMER_ID = IH.BILLTOCUSTOMER_LINK_ID
               where AR.EXPORTSTATUS = -2
                 and NVL(AR.PARENTARTRANSACTION_ID, AR.ARTRANSACTION_ID) =
                     AR.ARTRANSACTION_ID
                 and AR.BUSINESSUNIT_ID = FP_BUSINESSUNITID
               group by AR.INVOICENUMBER,
                        AR.ARTRANSACTIONDATE,
                        BILLTO.CUSTOMERNUMBER,
                        BILLTO.NAME,
                        IHEI.PAYMENTTERMSDUEDATE) loop
      begin
        M_INVOICENUMBER     := X.INVOICENUMBER;
        M_ARTRANSACTIONDATE := X.ARTRANSACTIONDATE;
        if X.AMOUNT < 0 then
          M_DOCUMENT_TYPE := '3';
        else
          M_DOCUMENT_TYPE := '1';
        end if;
        M_AMOUNT              := X.AMOUNT;
        M_CUSTOMERNUMBER      := X.CUSTOMERNUMBER;
        M_CUSTOMERNAME        := X.NAME;
        M_PAYMENTTERMSDUEDATE := X.PAYMENTTERMSDUEDATE;
        M_KID                 := TO_CHAR(X.INVOICENUMBER * 10 +
                                         F_MOD10DIM(X.INVOICENUMBER,
                                                    LENGTH(TO_CHAR(X.INVOICENUMBER))));
        M_MONTH               := TO_CHAR(M_ARTRANSACTIONDATE, 'MM');
        GV_TOTALAMOUNT        := GV_TOTALAMOUNT + X.AMOUNT;

        WRITE_ROW1;
        WRITE_ROW2;

        GV_ABSLOGMESSAGE := RPAD(TO_CHAR(M_INVOICENUMBER), 8, ' ') || ' ' ||
                            RPAD(TO_CHAR(M_ARTRANSACTIONDATE, 'DD-MM-YYYY'),
                                 10,
                                 ' ') || ' ' || TO_CHAR(M_CUSTOMERNUMBER) || ' ' ||
                            RPAD(M_CUSTOMERNAME, 40, ' ') ||
                            TO_CHAR(M_AMOUNT);

        WRITE_LOG(GV_ABSLOGMESSAGE);
      end;
    end loop; --x

    GV_ABSLOGMESSAGE := 'Total : ' || TO_CHAR(GV_TOTALAMOUNT);
    WRITE_LOG(GV_ABSLOGMESSAGE);

  end EXPORT2FILE;

  procedure FINALIZE is
  begin
    --finalize
    FP_ABSLOGMESSAGE := 'finalize set artransaction to exported status = 2';
    update ARTRANSACTION AR
       set AR.EXPORTSTATUS = 2
     where AR.EXPORTSTATUS = -2
       and AR.BUSINESSUNIT_ID = FP_BUSINESSUNITID;
    commit;
    --show messages and write log
    FP_ABSLOGMESSAGE := 'Successfully exported into directory ' ||
                        GV_DEFAULTDIR || ' filename ' || GV_FILENAME;
    WRITE_LOG(FP_ABSLOGMESSAGE);
    FP_STATUS_NUMBER := 0;
  end FINALIZE;
begin
  --initialize
  INITIALIZE;
  --open_file
  GV_FILEHANDLE := OPEN_FILE;
  --export2file
  EXPORT2FILE;
  --close_file
  CLOSE_FILE;
  --finalize
  FINALIZE;

exception
  --exception handling
  when GV_FILEEXISTS then
    begin
      rollback;
      FP_ABSLOGMESSAGE := 'Error ' || FP_ABSLOGMESSAGE;
      WRITE_LOG(FP_ABSLOGMESSAGE, 3);
      FP_STATUS_NUMBER := 1;
    end;
  when GV_USEREXCEPTION then
    begin
      rollback;
      FP_ABSLOGMESSAGE := 'Error ' || FP_ABSLOGMESSAGE;
      WRITE_LOG(FP_ABSLOGMESSAGE, 3);
      CLOSE_FILE;
      DELETE_FILE;
      FP_STATUS_NUMBER := 1;
    end;
  when NO_DATA_FOUND then
    begin
      rollback;
      FP_ABSLOGMESSAGE := 'Error no data found ' || FP_ABSLOGMESSAGE;
      WRITE_LOG('Error No Data Found ' || FP_ABSLOGMESSAGE, 3);
      CLOSE_FILE;
      DELETE_FILE;
      FP_STATUS_NUMBER := 1;
    end;
  when others then
    begin
      rollback;
      FP_ABSLOGMESSAGE := 'Error ' || sqlerrm || ' ' || FP_ABSLOGMESSAGE;
      WRITE_LOG(sqlerrm, 5);
      WRITE_LOG('Error ' || sqlerrm || ' ' || FP_ABSLOGMESSAGE, 3);
      CLOSE_FILE;
      DELETE_FILE;
      FP_STATUS_NUMBER := 1;
    end;
end EXPORT2MAMUT;
/
create or replace procedure ExportARExchecker(param_reportParam_ID              IN reportparam.reportparam_id%type,
                                              param_divisionCode                IN division.code%type,
                                              param_sysuser_ID                  IN systemuser.systemuser_id%type,
                                              param_language                    IN languages.language_id%type,
                                              gverrrormsg                       OUT abslog.message%type,
                                              gv_code                           OUT integer, -- gv_code = 1 => error. read error message from gverrrormsg
                                              gv_filename_invoices              OUT varchar2) is -- text that should appear in process log file

  UTLDIR      varchar2(50) := 'EXPORTFILES';

  TYPE detail_row IS RECORD (
        isCreditLine boolean,
        detail_1     VARCHAR2(100),
        vat_value    number,
        detail_2     VARCHAR2(100));
--  TYPE detail_rows_array IS TABLE OF VARCHAR2(120) INDEX BY BINARY_INTEGER;
  TYPE detail_rows_array IS TABLE OF detail_row INDEX BY BINARY_INTEGER;
  -- variable
  v_frequency varchar2(13) := 'XX';
  v_file utl_file.file_type;
  ex_FinancialYearConversion EXCEPTION;
  ex_DivisionCode EXCEPTION;
  v_vatTotalPerInvoice number;
  v_noOfLines number;
  -- cursors declaration
  cursor c_invHeaders is
    select ar.artransaction_id,
        ar.artransactiondate,
        ih.invoiceheader_id,
        case
          when (ih.invoiceheader_id is not null) then
            case
              when (invf.invoicefrequencynumber = 200) then 'N'
              when invf.invoicefrequencynumber between 0 and 9 then 'D'
              when invf.invoicefrequencynumber between 10 and 99 then 'W'
              when invf.invoicefrequencynumber between 100 and 199 then 'M'
              else ''
              end
          else
            case
              when (invf1.invoicefrequencynumber = 200) then 'N'
              when invf1.invoicefrequencynumber between 0 and 9 then 'D'
              when invf1.invoicefrequencynumber between 10 and 99 then 'W'
              when invf1.invoicefrequencynumber between 100 and 199 then 'M'
              else ''
              end
          end freq,
        ih.invoicenumber,
        ih.prebillamount,
        ih.totalamountexclvat,
        ihe.paymenttermsduedate,
        nvl(c.legacycustomernumber, to_char(c.customernumber)) customernumber,
        c.name customername,
        ih.paythisamount - ih.totalamountexclvat vatamount,
        (select decode(trim(cc.code), '10', 'Pret_', '11', 'Eat_', '01', 'WTerminated_', '02', 'MTerminated_', '')
                from customercluster cc, customerspercluster cpc
                where cc.cluster_id = cpc.cluster_id and cpc.customer_id = c.customer_id and rownum = 1) clusterdesc,
        case
          when (to_number(to_char(ar.artransactiondate, 'yyyy')) >= 2015) then to_number(to_char(ar.artransactiondate, 'yyyy')) - 1900
          else
            nvl((select f.financialyear
              from financialyearconversion f
             where f.startdate =
                   (select max(f1.startdate)
                      from financialyearconversion f1
                     where f1.startdate < ar.artransactiondate)), -1)
          end financialyear,
        case
          when (to_number(to_char(ar.artransactiondate, 'yyyy')) = 2015 and to_number(to_char(ar.artransactiondate, 'mm')) >= 10) then to_number(to_char(ar.artransactiondate, 'mm')) - 10
          when (to_number(to_char(ar.artransactiondate, 'yyyy')) = 2015 and to_number(to_char(ar.artransactiondate, 'mm')) < 10) then to_number(to_char(ar.artransactiondate, 'mm'))
          when (to_number(to_char(ar.artransactiondate, 'yyyy')) > 2015) then to_number(to_char(ar.artransactiondate, 'mm'))
          else
             nvl((select f.period
              from financialyearconversion f
             where f.startdate =
                   (select max(f1.startdate)
                      from financialyearconversion f1
                     where f1.startdate < ar.artransactiondate)), -1)
          end period
  from reportparam rp, artransaction ar
  left outer join invoiceheader ih
    left outer join invoicefrequency invf
      on ih.invoicefrequency_id = invf.invoicefrequency_id
    left outer join invoiceheaderextrainfo ihe
      on ih.invoiceheader_id = ihe.invoiceheader_id
    on ar.invoiceheader_id = ih.invoiceheader_id,
  customer_link cl
    left outer join customer c
      left outer join invoicefrequency invf1
        on c.invoicefrequency_id = invf1.invoicefrequency_id
      on cl.customer_id = c.customer_id
 where rp.number_value = ar.artransaction_id
       and ar.billtocustomer_link_id = cl.customer_link_id
       and rp.reportparam_id = param_reportParam_ID
       and (ih.parentinvoiceheader_id = ih.invoiceheader_id or ih.parentinvoiceheader_id is null)
order by freq, clusterdesc, artransaction_id, invoicenumber;


  procedure write_file(param_divisionCode                IN division.code%type,
                       param_frequency                   IN varchar2,
                       param_cluster                     IN varchar2,
                       p_file                            OUT utl_file.file_type) is
    v_date varchar2(8);
    v_exists BOOLEAN;
    v_length NUMBER;
    v_blocksize NUMBER;
    v_filename varchar2(32);
  begin
    --get_directory;
/*    begin
      select nvl(s.dblogdir, 'C:\') into UTLDIR from databasesettings s;
    EXCEPTION
      WHEN no_data_found then
        UTLDIR := 'C:\';-- please see ABS-92804 variable needs the name of an existing oracle directory
    end;*/

    --get date
    select to_char(sysdate, 'ddmmyyyy') into v_date from dual;
    v_filename := param_cluster || param_divisionCode || param_frequency || v_date ||
                   '.CSV';

    gverrrormsg := 'open_file ' || v_filename;

    UTL_FILE.fgetattr (UTLDIR, v_filename, v_exists, v_length, v_blocksize);
    if (v_exists) then
      -- re-write existing file
      p_file := utl_file.fopen(UTLDIR, v_filename, 'w');
      gv_filename_invoices := gv_filename_invoices || 'File overwritten: ' || v_filename || '\n';
    else
      --create file
      p_file := utl_file.fopen(UTLDIR, v_filename, 'w');
      gv_filename_invoices := gv_filename_invoices || 'Created file: ' || v_filename || '\n';
    end if;

    --gv_filename_invoices := gv_filename_invoices || 'FILE ' || v_filename || ',';
  exception
    when utl_file.INVALID_OPERATION then
      gverrrormsg:='Directory ''D:\ExportFiles'' does not exists or is read only!';
      gv_code:=1;
      raise;
    when others then
    begin
      gverrrormsg:='Error on creating/writing in file ' || v_filename || '!';
      gv_code:=1;
      raise;
    end;
 end write_file;

  --close file procedure
  procedure close_file(p_file OUT utl_file.file_type) is
  begin
    if utl_file.is_open(p_file) = true then
      utl_file.fclose(p_file);
    end if;
    utl_file.fclose_all;
    exception when others then
      begin
        gverrrormsg:='Error! Could not close file!';
        gv_code:=1;
        end;
  end close_file;

  -- first line in export file - column names
  procedure first_line(p_file IN OUT utl_file.file_type) is
  begin
    utl_file.put_line(p_file,
                      'Record type,' || 'Link Ref,' || 'Account code,' ||
                      'Inv Ref,' || 'Currency,' || 'Accounting year,' ||
                      'Accounting period,' || 'Transaction date,' ||
                      'Due date,' || 'VAT Code,' || 'VAT Amount1,' || 'Net value,' || 'VAT Value,' ||
                      'Your Ref,' || 'Total lines,' || 'Manual VAT,' || 'Customer name');

  exception when others then
    begin
      gverrrormsg:='Error! Could not write header in file!';
      gv_code:=1;
      raise;
    end;
  end first_line;

  function get_converted_invoiceNumber(invNumber number) return varchar2 is
    v_convNumber varchar2(6);
    begin
      if (param_divisionCode = 'L' and invNumber between 10000001 and 10099999) then
        v_convNumber :=  'J' || substr(to_char(invNumber), 4);
      elsif (param_divisionCode = 'L' and invNumber between 10100000 and 10199999) then
        v_convNumber :=  'K' || substr(to_char(invNumber), 4);
      elsif (param_divisionCode = 'L' and invNumber between 10200000 and 10600000) then
        v_convNumber := substr(to_char(invNumber), 3);
      elsif (param_divisionCode = 'C' and invNumber between 20000000 and 20099999) then
        v_convNumber := 'C' || substr(to_char(invNumber), 4);
      elsif (param_divisionCode = 'C' and invNumber between 20100000 and 20199999) then
        v_convNumber := 'D' || substr(to_char(invNumber), 4);
      elsif (param_divisionCode = 'W' and invNumber between 30000000 and 30099999) then
        v_convNumber := 'F' || substr(to_char(invNumber), 4);
      elsif (param_divisionCode = 'W' and invNumber between 30100000 and 30199999) then
        v_convNumber := 'G' || substr(to_char(invNumber), 4);
      else
        v_convNumber := '-';
      end if;
      return v_convNumber;
  end get_converted_invoiceNumber;

  --process invoice header line
  procedure process_header_line(p_rec c_invHeaders%rowtype, p_file IN OUT utl_file.file_type) is
    v_row varchar2(170) := '"TH",';
    v_invoice boolean := case
                          when p_rec.invoiceheader_id is null then false
                          else true
                          end;
    v_link_ref varchar2(3);

    begin
      if (p_rec.prebillamount is not null and p_rec.prebillamount < 0) then
         v_link_ref := 'SCR';
      else
         v_link_ref := 'SIN';
      end if;

     -- Link Ref
      v_row := v_row || (case
            when v_invoice = false then ','
            else '"' || v_link_ref || '",'
            end);
      -- Account code
      v_row := v_row || (case
            when v_invoice = false then ','
            else '"' || p_rec.customernumber || '",'
            end);
      -- Inv Ref
      v_row := v_row || (case
            when v_invoice = false then ','
            else
               '"' || v_link_ref || get_converted_invoiceNumber(p_rec.invoicenumber) || '",'
            end);
      -- Currency
      v_row := v_row || '1,';
      -- Accounting year
      v_row := v_row || to_char(p_rec.financialyear) || ',';
      -- Accounting period
      v_row := v_row || to_char(p_rec.period) || ',';
      -- Transaction date
      v_row := v_row || to_char(p_rec.artransactiondate, 'dd/mm/yyyy') || ',';
      -- Due date
      v_row := v_row || (case
            when v_invoice = false then ','
            else
               to_char(p_rec.paymenttermsduedate, 'dd/mm/yyyy') || ','
            end);
      -- VAT Code
      v_row := v_row || '"S",';
      -- VAT Amount1
      if (v_link_ref = 'SCR') then
         v_row := v_row || to_char((-1) * p_rec.vatamount) || ','; --to_char(v_vatTotalPerInvoice) || ',';
      else
        v_row := v_row || to_char(p_rec.vatamount) || ',';
      end if;
      -- Net value
      if (v_invoice = false) then
        v_row := v_row || ',';
      else
        if (v_link_ref = 'SCR') then
           v_row := v_row || to_char((-1) * p_rec.totalamountexclvat) || ',';
        else
           v_row := v_row || to_char(p_rec.totalamountexclvat) || ',';
        end if;
      end if;
      -- VAT value
      if (v_link_ref = 'SCR') then
         v_row := v_row || to_char((-1) * p_rec.vatamount) || ','; --to_char(v_vatTotalPerInvoice) || ',';
      else
        v_row := v_row || to_char(p_rec.vatamount) || ',';
      end if;
      -- Your Ref
      v_row := v_row || (case
            when v_invoice = false then ','
            else
               '"' || p_rec.invoicenumber || '",'
            end);
      -- Total lines
      v_row := v_row || to_char(v_noOfLines) || ','; --p_rec.nolines) || ',';
      -- Manual VAT
      v_row := v_row || '"Y",';
      -- Customer name
      v_row := v_row || '"' || p_rec.customername || '"';

      utl_file.put_line(p_file, v_row);
    --write_log('Number of invoices exported ' || nb_invoices_exported, 1);
  exception when others then
    begin
      dbms_output.put_line(v_row);
      dbms_output.put_line(sqlerrm);
        gverrrormsg:='1 Error! Export ended with errors '|| v_row || sqlerrm;
        gv_code:=1;
        raise;
    end;
  end process_header_line;

  --process invoice lines
  function process_detail_lines(p_rec c_invHeaders%rowtype)
    return detail_rows_array is
    v_cons_count number := 0;
    v_row varchar2(120);
    v_link_ref varchar2(3);
    v_line_seq number;
    v_one_row detail_row;
    v_detail_rows detail_rows_array;
    v_vat_value number;
    v_highest_line_idx number;

    cursor c_cons_lines is
      select sum(il.amount) amount,
       la.description,
       tg.legacycode, sum(round(il.amount*nvl(tx.taxrate, 0)/100, 2)) vat
        from invoiceheader ih, invoiceline il
        left outer join turnovergroup tg
             left outer join taxgroup tx on tg.taxgroup_id = tx.taxgroup_id
             left outer join ledgeracctsperturnovergroup ltg inner join ledgeraccounts la on la.ledgeraccounts_id = ltg.ledgeraccounts_id
              on ltg.turnovergroup_id = tg.turnovergroup_id
          on tg.turnovergroup_id = il.turnovergroup_id
       where il.invoiceheader_id = ih.invoiceheader_id
         and ih.parentinvoiceheader_id = p_rec.invoiceheader_id
         and il.invoicelinetype_id != 18
       group by la.description, tg.legacycode
       order by tg.legacycode;

    cursor c_inv_lines is
      select sum(il.amount) amount,
       la.description,
       tg.legacycode, sum(round(il.amount*nvl(tx.taxrate, 0)/100, 2)) vat
        from invoiceline il
        left outer join turnovergroup tg
             left outer join taxgroup tx on tg.taxgroup_id = tx.taxgroup_id
             left outer join ledgeracctsperturnovergroup ltg inner join ledgeraccounts la on la.ledgeraccounts_id = ltg.ledgeraccounts_id
              on ltg.turnovergroup_id = tg.turnovergroup_id
          on tg.turnovergroup_id = il.turnovergroup_id
       where il.invoiceheader_id = p_rec.invoiceheader_id
         and il.invoicelinetype_id != 18
       group by la.description, tg.legacycode
       order by tg.legacycode;

  begin
      select count(1) into v_cons_count
        from invoiceheader ih, invoiceline il
       where il.invoiceheader_id = ih.invoiceheader_id
         and ih.parentinvoiceheader_id = p_rec.invoiceheader_id;

      -- determine prefix
      if (p_rec.prebillamount is not null and p_rec.prebillamount < 0) then
         v_link_ref := 'SCR';
      else
         v_link_ref := 'SIN';
      end if;

      if (v_cons_count = 0) then -- no consolidated invoice
        /*if (p_rec.nolines = 0) then return v_detail_row; -- no invoice lines
        end if;*/
        v_line_seq := 0;
        v_highest_line_idx := -1;
        v_vat_value := 0;
        for invl in c_inv_lines loop
          -- no need to export 0 amount lines
          if (invl.amount = 0) then
            continue;
          end if;

          -- set if credit line or not - for credit lines, amounts signs are reverted
          if (v_link_ref = 'SCR') then
            v_one_row.isCreditLine := true;
          else
            v_one_row.isCreditLine := false;
          end if;
         -- v_line_seq := v_line_seq + 1; index 0 not used
          v_row := '"TL",';
          -- Inv Ref
          v_row := v_row || '"' || v_link_ref || get_converted_invoiceNumber(p_rec.invoicenumber) || '",';
          -- Line Number
          v_row := v_row || to_char(v_line_seq + 1) || ',';
          -- Quantity
          v_row := v_row || '1,';
          -- Amount
          if (v_link_ref = 'SCR') then
             v_row := v_row || to_char((-1) * invl.amount) || ',';
          else
             v_row := v_row || to_char(invl.amount) || ',';
          end if;
          -- VAT Code
          v_row := v_row || '"S",';
          v_one_row.detail_1 := v_row;
          v_row := '';

          -- VAT value
          --v_row := v_row || to_char(invl.vat) || ',';
          v_one_row.vat_value := invl.vat;
          if (abs(invl.vat) > abs(v_vat_value)) then
            v_vat_value := invl.vat;
            v_highest_line_idx := v_line_seq; -- keep the line with highest value of the vat, for correction
          end if;

          -- Line description
          v_row := v_row || '"' || invl.description || '",';
          -- Line transaction date
          v_row := v_row || to_char(p_rec.artransactiondate, 'dd/mm/yyyy') || ',';
          --Y??
          v_row := v_row || '"Y",';
          -- GL control code
          v_row := v_row || invl.legacycode || ',';
          -- Cost centre
          v_row := v_row || '"' || param_divisionCode || '",';
          v_one_row.detail_2 := ',' || v_row;
          -- VAT value
          --if (invl.taxrate <> 0) then
            v_vatTotalPerInvoice := v_vatTotalPerInvoice + invl.vat; --round((v_qty * v_price)*invl.taxrate/100, 2);
          --end if;
          --utl_file.put_line(p_file, v_row);
          -- no of lines:
          --v_detail_row(v_line_seq) := v_row;
           v_detail_rows(v_line_seq) := v_one_row;

          --count index
           v_line_seq := v_line_seq + 1;
        end loop;
        -- add correction to the highest line
        if (v_highest_line_idx >= 0) then
           v_detail_rows(v_highest_line_idx).vat_value := v_detail_rows(v_highest_line_idx).vat_value + (p_rec.vatamount - v_vatTotalPerInvoice);
        end if;
      else -- for consolidated invoice
        v_line_seq := 0;
        v_highest_line_idx := -1;
        v_vat_value := 0;
        for invl in c_cons_lines loop
          -- no need to export 0 amount lines
          if (invl.amount = 0) then
            continue;
          end if;

          -- set if credit line or not - for credit lines, amounts signs are reverted
          if (v_link_ref = 'SCR') then
            v_one_row.isCreditLine := true;
          else
            v_one_row.isCreditLine := false;
          end if;

          /*v_line_seq := v_line_seq + 1;*/
          v_row := '"TL",';
          -- Inv Ref
          v_row := v_row || '"' || v_link_ref || get_converted_invoiceNumber(p_rec.invoicenumber) || '",';
          -- Line Number
          v_row := v_row || to_char(v_line_seq + 1) || ',';
          -- Quantity
          v_row := v_row || '1,';
          -- Amount
          if (v_link_ref = 'SCR') then
             v_row := v_row || to_char((-1) * invl.amount) || ',';
          else
             v_row := v_row || to_char(invl.amount) || ',';
          end if;
          -- VAT Code
          v_row := v_row || '"S",';
          v_one_row.detail_1 := v_row;
          v_row := '';

          -- VAT value
          --v_row := v_row || to_char(invl.vat) || ',';
          v_one_row.vat_value := invl.vat;
          if (abs(invl.vat) > abs(v_vat_value)) then
            v_vat_value := invl.vat;
            v_highest_line_idx := v_line_seq; -- keep the line with highest value of the vat, for correction
          end if;

          -- Line description
          v_row := v_row || '"' || invl.description || '",';
          -- Line transaction date
          v_row := v_row || to_char(p_rec.artransactiondate, 'dd/mm/yyyy') || ',';
          -- Y??
          v_row := v_row || '"Y",';
          -- GL control code
          v_row := v_row || invl.legacycode || ',';
          -- Cost centre
          v_row := v_row || '"' || param_divisionCode || '",';
          v_one_row.detail_2 := ',' || v_row;

          -- VAT value
          --if (invl.taxrate <> 0) then
            v_vatTotalPerInvoice := v_vatTotalPerInvoice + invl.vat; --round((v_qty * v_price)*invl.taxrate/100, 2);
          --end if;
          --utl_file.put_line(p_file, v_row);
          --v_detail_row(v_line_seq) := v_row;
          v_detail_rows(v_line_seq) := v_one_row;

          --count index
          v_line_seq := v_line_seq + 1;
        end loop;
        -- add correction to the highest line
        if (v_highest_line_idx >= 0) then
           v_detail_rows(v_highest_line_idx).vat_value := v_detail_rows(v_highest_line_idx).vat_value + (p_rec.vatamount - v_vatTotalPerInvoice);
        end if;
      end if;
      v_noOfLines := v_line_seq;
      return v_detail_rows;
  exception when others then
    begin
      dbms_output.put_line(v_row);
      gverrrormsg:='2 Error! Export ended with errors '|| v_row || sqlerrm;
      gv_code:=1;
      rollback;
    end;
  end process_detail_lines;


begin
  gv_code:=0;

  if (param_divisionCode is null or param_divisionCode not in ('C', 'L', 'W')) then
    raise ex_DivisionCode;
  end if;

  for inv in c_invHeaders loop
    declare
      v_detail_rows detail_rows_array;
    begin
      if (inv.financialyear = -1 or inv.period = -1) then
        raise ex_FinancialYearConversion;
      end if;
      if (trim(v_frequency) <> nvl(inv.clusterdesc, 'X') || inv.freq) then -- new file for each cluster/frequency
        if (trim(v_frequency) <> 'XX') then
          close_file(v_file);
        end if;
        v_frequency := nvl(inv.clusterdesc, 'X') || inv.freq;
        write_file(param_divisionCode, inv.freq, inv.clusterdesc, v_file);
        first_line(v_file);
      end if;
      v_vatTotalPerInvoice := 0;
      v_noOfLines := 0;
      if (inv.invoiceheader_id is not null) then
        v_detail_rows := process_detail_lines(inv);
        --gv_filename_invoices := gv_filename_invoices || 'Invoice: ' to_char(inv.invoicenumber) || '\n';
      end if;
      process_header_line(inv, v_file);
      gv_filename_invoices := gv_filename_invoices || 'Invoice: ' || to_char(inv.invoicenumber) || '\n';
      for i in 0..v_detail_rows.count - 1 loop
        -- check if is credit line, in order to switch VAT sign
        if (v_detail_rows(i).isCreditLine) then
           utl_file.put_line(v_file, (v_detail_rows(i).detail_1 || to_char((-1) * v_detail_rows(i).vat_value) || v_detail_rows(i).detail_2));
        else
           utl_file.put_line(v_file, (v_detail_rows(i).detail_1 || to_char(v_detail_rows(i).vat_value) || v_detail_rows(i).detail_2));
        end if;
      end loop;
  /*    if (inv.invoiceheader_id is not null) then
        v_detail_row := process_detail_lines(inv, param_language, v_file);
        --gv_filename_invoices := gv_filename_invoices || 'Invoice: ' to_char(inv.invoicenumber) || '\n';
      end if;*/
    end;
  end loop;
  close_file(v_file);

  -- update artransaction
  update artransaction ar
     set ar.exportstatus = 2,
         ar.systemuser_id = param_sysuser_ID,
         ar.timestamp = sysdate
   where ar.artransaction_id in
         (select rp.number_value
            from reportparam rp
           where rp.reportparam_id = param_reportParam_ID);

  -- delete from reportparam
  delete from reportparam rp where rp.reportparam_id = param_reportParam_ID;

  commit;
exception
  when ex_FinancialYearConversion then
  begin
    gverrrormsg:='Error! Could not determine the financial year and period. Please fill the financial year conversion table.';
    gv_code:=1;
    close_file(v_file);
    rollback;
  end;
  when ex_DivisionCode then
  begin
    gverrrormsg:='Error! Division Code value not acceptable: ' || nvl(param_divisionCode, 'null') || '!';
    gv_code:=1;
    close_file(v_file);
    rollback;
  end;
  when others then
    begin
      close_file(v_file);
      rollback;
    end;
end ExportARExchecker;
/
create or replace procedure export_invoiceheaderxml(fp_businessunitcode in varchar2,
                                                    fp_systemuserid     in number,
                                                    fp_exportdirectory  in varchar2) is
  /*procedure export_invoiceheaderxml version 0.1*/
  gv_user_exception exception;
  gv_message        abslog.message%type;
  gv_plantid        plant.plant_id%type;
  gv_businessunitid businessunit.businessunit_id%type;
  gv_counter        number := 0;

  procedure write_log(fp_message  in abslog.message%type,
                      fp_priority in abslog.priority%type default 1) is
  begin
    /*
    Write message in ABSLOG with these priorities
    1 = Message
    2 = Warning
    3 = Error
    4 = Stack trace
    5 = Debug info
    */
    abslogwrite.abslog_write(5, 'export_invoiceheaderxml', gv_plantid, fp_priority, fp_message,
                             fp_systemuserid);
    begin
      dbms_output.put_line(fp_message);
    exception
      when others then
        null; --cannot produce output but its in ABSLOG as well
    end;
  end write_log;

  procedure initialize is
  begin
    --initialize
    if fp_businessunitcode is null then
      begin
        gv_message := 'parameter fp_businessunitcode cannot be left blank';
        raise gv_user_exception;
      end;
    else
      begin
        gv_message := 'businessunit code ' || fp_businessunitcode;
        select bu.businessunit_id, bu.plant_id
        into   gv_businessunitid, gv_plantid
        from   businessunit bu
        where  bu.code = fp_businessunitcode;
      end;
    end if;
    if fp_exportdirectory is null then
      begin
        gv_message := 'parameter fp_exportdirectory cannot be left blank';
        raise gv_user_exception;
      end;
    end if;
  end initialize;

  procedure writexmlclob2file(fp_filename in varchar2, fp_clob in clob) is
  begin
    --writexmlclob2file
    gv_message := 'write clob2file directory ' || fp_exportdirectory || ' filename ' || fp_filename;
    dbms_xslprocessor.clob2file(flocation => fp_exportdirectory, fname => fp_filename,
                                cl => fp_clob);
  end writexmlclob2file;
begin
  --initialize
  initialize;
  --export into file
  for x in (select ihx.invoiceheader_id, ih.invoicenumber, ihx.invoicedata
            from   invoiceheaderxml ihx
            join   invoiceheader ih
            on     ih.invoiceheader_id = ihx.invoiceheader_id
            where  ih.invoicebusinessunit_id = gv_businessunitid
            and    ihx.status = 0
            order  by ihx.invoiceheader_id asc) loop
    begin
      --writexmlclob2file
      writexmlclob2file(fp_businessunitcode || '_' || to_char(x.invoicenumber) || '.xml',
                        x.invoicedata);
      --update invoiceheaderxml
      gv_message := 'update invoiceheaderxml for invoiceheader_id ' || to_char(x.invoiceheader_id) ||
                    ' invoicenumber ' || to_char(x.invoicenumber);
      update invoiceheaderxml xml
      set    xml.status = 1, xml.systemuser_id = fp_systemuserid, xml.timestamp = sysdate
      where  xml.invoiceheader_id = x.invoiceheader_id;
      --count
      gv_counter := gv_counter + 1;
    end;
  end loop; --x
  commit;
  if gv_counter = 0 then
    begin
      write_log('Ran succesfully nothing exported from invoiceheaderxml');
    end;
  else
    begin
      write_log('Succesfully ' || gv_counter || ' files exported into ' || fp_exportdirectory);
    end;
  end if;
exception
  when gv_user_exception then
    begin
      rollback;
      write_log(gv_message, 3);
    end;
  when no_data_found then
    begin
      rollback;
      write_log('No data found ' || gv_message, 3);
    end;
  when others then
    begin
      rollback;
      write_log(sqlerrm || ' for businessunit code ' || fp_businessunitcode, 3);
    end;
end export_invoiceheaderxml;
/
create or replace procedure fillInternalBUActivitiesTable is
begin
insert into internalbuactivities
  (internalbuactivities_id,
   businessunit_id,
   activity_id,
   internalprocessingbu_id,
   systemuser_id,
   timestamp)
  (select seq_internalbuactivities.nextval,
          bua.businessunit_id,
          bua.activity_id,
          intbu.businessunit_id,
          getminsystemuser(),
          sysdate
     from businessunitactivities bua, businessunit intbu
    where exists
    (select 1
             from customeractivities ca, customer c
            where ca.activity_id = bua.activity_id
              and ca.customer_id = c.customer_id
              and ca.processbusinessunit_id = bua.businessunit_id
              and ca.internalprocessingbu_id = intbu.businessunit_id
              and c.active = 'Y'));
	commit;
end;
/
create or replace PROCEDURE FillProdProcBufferSnapshot(Fp_Plant_ID IN NUMBER,
                                                       Fp_Abslogprocessjobid in abslogprocessjob.abslogprocessjob_id%type,
                                                       Fp_SystemUser_ID IN NUMBER default 0) IS
/* Purpose: Collect data about production process buffer contents multiple times per day,
            for reporting / BI analysis, by taking snapshots of the uniqueitembufferinfo table.
            It will store the info in a condensed way (number of items, not which unique items).
            This procedure is executed by the ABSSolute scheduled process for production buffer snapshots.
            It will not do anything, except writing a log line, incase it is executed outside plant operating hours
   Created: 27-09-2016 HVH ABS-7437 New developed for module UHF production process buffer tracking
   Changes: 14-01-2020 HVH ABS-62692 Added quanitty sleeping for items not seen longer than value of UHFMONITORDAYSNOTSEENLIMT setting
*/
  gv_rows_inserted         NUMBER := 0;
  gv_error_number          NUMBER := 0;
  gv_error_message         VARCHAR2(2000) := '';
  gv_ss_daysnotseenlimit   NUMBER := 0;

  procedure write_process_log(fp_prio in number, fp_msg in varchar2) is
   lv_abslogprocessjobpartid abslogprocessjobpart.abslogprocessjobpart_id%type;
  begin
    lv_abslogprocessjobpartid := abslogwrite.abslogprocessjobpart_write(Fp_Abslogprocessjobid,'Production Process Buffer Snapshot',Fp_SystemUser_ID);
    abslogwrite.abslogprocessjobline_write(lv_abslogprocessjobpartid, fp_prio, fp_msg,Fp_SystemUser_ID);
  end;

function is_within_plant_operationhours(fp_plant_id number, fp_checktimestamp date) return varchar2 is
  lv_result varchar2(1);
  begin
    begin
      lv_result := 'N';
      -- first check for current date.
      select 'Y'
        into lv_result
        from plantoperatinghours po
       where po.plant_id = fp_plant_id
         and po.day_id = GETABSDAYNUMBER(fp_checktimestamp)
         and ((po.endtime >  po.starttime and
               fp_checktimestamp between po.starttime-trunc(po.starttime)+trunc(fp_checktimestamp)
                                     and po.endtime-trunc(po.endtime)+trunc(fp_checktimestamp))
          or (po.endtime <= po.starttime and
              fp_checktimestamp between po.starttime-trunc(po.starttime)+trunc(fp_checktimestamp)
                                    and trunc(fp_checktimestamp)+1));
    exception
       when no_data_found then -- try for previous date
        begin
          select 'Y'
            into lv_result
            from plantoperatinghours po
           where po.plant_id = fp_plant_id
             and po.day_id = GETABSDAYNUMBER(fp_checktimestamp) - 1
             and po.endtime <= po.starttime
             and fp_checktimestamp between trunc(fp_checktimestamp)
                                       and po.endtime-trunc(po.endtime)+trunc(fp_checktimestamp);
        exception
         when no_data_found then
           lv_result := 'N';
        end;
    end;
    return(lv_result);
  end;

---- MAIN
BEGIN
 -- first check if current time is within plant operation hours.
 if is_within_plant_operationhours(fp_plant_id,sysdate) = 'Y'
   then
     write_process_log(1,'Process started');
     begin -- read system setting
       select s.value
         into gv_ss_daysnotseenlimit
         from systemsetting s
        where s.name='UHFMONITORDAYSNOTSEENLIMT'
          and s.plant_id = Fp_Plant_ID;
       exception
        when no_data_found then
         begin
          write_process_log(3,'Process ended unexpected: systemsetting UHFMONITORDAYSNOTSEENLIMT not defined');
          raise;
         end;
        when others then
         begin
          ROLLBACK;
            gv_error_number  := SQLCODE;
            gv_error_message := SQLERRM;
            rollback;
            write_process_log(3,'Process ended unexpected: ' || to_char(gv_error_number) || ' ' || gv_error_message);
            raise;
          end;
     end;
     begin
      insert
        into prodprocessbuffersnapshot (prodprocessbuffersnapshot_id,
                                        plant_id,
                                        businessunit_id,
                                        snapshotlocaldate,
                                        snapshotlocaltimeofday,
                                        productionprocessbuffer_id,
                                        product_link_id,
                                        sizedefinition_link_id,
                                        numberofitems,
                                        numberofitemssleeping,
                                        systemuser_id,
                                        timestamp)
        (select seq_prodprocessbuffersnapshot.nextval,
                x.plant_id,
                x.businessunit_id,
                x.snapshotlocaldate,
                x.snapshotlocaltimeofday,
                x.productionprocessbuffer_id,
                x.product_link_id,
                x.sizedefinition_link_id,
                x.numberofitems,
                x.numberofitemssleeping,
                Fp_Systemuser_ID,
                sysdate
            from (
                 select ub.plant_id,
                        ub.businessunit_id,
                        trunc(sysdate - (p.timezonehrsdiff / 24)) snapshotlocaldate,  -- Converted to plant date
                        to_number(to_char(sysdate - (p.timezonehrsdiff / 24),'HH24MI')) snapshotlocaltimeofday, -- Converted to plant date
                        ub.productionprocessbuffer_id,
                        ub.product_link_id,
                        ub.sizedefinition_link_id,
                        count(*) numberofitems,
                        sum(case when ub.lastscantimestamp <= trunc(sysdate) - gv_ss_daysnotseenlimit
                               then 1
                               else 0
                            end) as numberofitemssleeping
                   from uniqueitembufferinfo ub,
                        plant p
                  where ub.plant_id = Fp_Plant_ID
                    and p.plant_id = ub.plant_id
                  group by
                        ub.plant_id,
                        ub.businessunit_id,
                        trunc(sysdate - (p.timezonehrsdiff / 24)),
                        to_number(to_char(sysdate - (p.timezonehrsdiff / 24),'HH24MI')),
                        ub.productionprocessbuffer_id,
                        ub.product_link_id,
                        ub.sizedefinition_link_id) x);
       gv_rows_inserted := SQL%ROWCOUNT;
       COMMIT;
       if gv_rows_inserted > 0
         then write_process_log(1,'Process ended successfully. ' || gv_rows_inserted || ' rows inserted');
         else write_process_log(2,'Process ended with warning: no data found');
       end if;
       exception
        when dup_val_on_index then
         begin
          write_process_log(3,'Process ended unexpected: data already exists. Did process run multiple times in same minute?');
          raise;
         end;
        when others then
         begin
          ROLLBACK;
            gv_error_number  := SQLCODE;
            gv_error_message := SQLERRM;
            rollback;
            write_process_log(3,'Process ended unexpected: ' || to_char(gv_error_number) || ' ' || gv_error_message);
            raise;
          end;
     end;
 else
   write_process_log(1,'Process skipped. Outside plant operation times');
 end if; -- if is_within_plant_operationhours
end;
/
create or replace procedure fillroutestatuscontrol(fp_plantprocessid     in plantprocess.plantprocess_id%type default null,
                                                   fp_plantid            in plant.plant_id%type,
                                                   fp_abslogprocessjobid in abslogprocessjob.abslogprocessjob_id%type default null,
                                                   fp_systemuserid       in systemuser.systemuser_id%type default null,
                                                   fp_o_status           out number) is
  /****************************************************************************\
  *  FillRouteStatusControl version 0.5                                        *
  *  Create the RouteControl and Stop records in advance.                      *
  *  This procedure can be called via the ProcessScheduler (weekly frequency)  *
  *  --Parameter                                                               *
  *  fp_o_status Output parameter:    0 = Run OK                               *
  *                                   1 = Run with warning                     *
  *                                   2 = Error                                *
  * 19-Feb-2019 ABS-62419 Add routes automatically to the Route Status Control *
  * 09-Feb-2024 ABS-157099 Add RouteStatusControl ExtraInfo for virtual routes *
  * 15-Apr-2024 ABS-163954 Truck and Driver are missing FillRouteStatusControl *
  \****************************************************************************/

  --------Internal variables
  gv_userexception          exception;
  gv_systemuserid           systemuser.systemuser_id%type;
  gv_plantcode              plant.code%type;
  gv_message                abslog.message%type;
  gv_abslogprocessjobpartid abslogprocessjobpart.abslogprocessjobpart_id%type;
  gv_routecontrol_counter   number;
  gv_stop_counter           number;

  --internal procedure
  procedure write_log(fp_message in abslog.message%type, fp_priority in abslog.priority%type) is
  begin
    --write_log
    if fp_abslogprocessjobid is null then
      begin
        begin
          abslogwrite.abslog_write(5, 'fillroutestatuscontrol', fp_plantid, fp_priority, fp_message,
                                   gv_systemuserid);
        end;
      end;
    else
      begin
        if gv_abslogprocessjobpartid is null then
          begin
            gv_abslogprocessjobpartid := abslogwrite.abslogprocessjobpart_write(fp_abslogprocessjobid,
                                                                                'Fill Route Status Control',
                                                                                gv_systemuserid);
          end;
        end if;
        abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, fp_priority, fp_message,
                                               gv_systemuserid);
      end;
    end if;
  exception
    when others then
      begin
        abslogwrite.abslog_write(5, 'fillroutestatuscontrol', null, fp_priority,
                                 fp_message || ' ' || sqlerrm);
      end;
  end write_log;

  procedure initialize is
    lv_counter number;
  begin
    --initialize
    gv_message                := 'initialize';
    gv_routecontrol_counter   := 0;
    gv_stop_counter           := 0;
    gv_abslogprocessjobpartid := null;
    gv_plantcode              := null;
    if fp_systemuserid is null then
      select min(s.systemuser_id) into gv_systemuserid from systemuser s;
    else
      gv_systemuserid := fp_systemuserid;
    end if;
    --get plant
    if fp_plantid is null then
      begin
        gv_message := 'Error, parameter fp_plantid cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        gv_message := 'plant id ' || to_char(fp_plantid);
        select pt.code into gv_plantcode from plant pt where pt.plant_id = fp_plantid;
      end;
    end if;
    --check parameters fp_plantprocessid and fp_abslogprocessjobid match with fp_plantid
    if fp_plantprocessid is not null and fp_abslogprocessjobid is not null then
      begin
        select count(1)
        into   lv_counter
        from   abslogprocessjob al
        join   plantprocess pp
        on     pp.plantprocess_id = al.plantprocess_id
        where  al.abslogprocessjob_id = fp_abslogprocessjobid
        and    pp.plant_id = fp_plantid;
        if lv_counter = 0 then
          begin
            gv_message := 'Error, parameters fp_plantid, fp_plantprocessid and fp_abslogprocessjobid do not match!';
            raise gv_userexception;
          end;
        end if;
      end;
    end if;
  end initialize;

  procedure process_routecontrols is
    lv_routecontrolid routecontrol.routecontrol_id%type;
    lv_stopid         stop.stop_id%type;
    lv_rc_stop_count  number;

    procedure create_routecontrol(fp_routeid         in route.route_id%type,
                                  fp_drivingdate     in date,
                                  fp_packingdeadline in route.packingdeadline%type,
                                  fp_loadingdock     in route.loadingdock%type,
                                  fp_packingdayid    in route.packingday_id%type,
                                  fp_truckcode       in truck.code%type,
                                  fp_drivernumber    in employee.employeenumber%type) is
    begin
      --create_routecontrol
      gv_message := 'create_routecontrol for route_id ' || to_char(fp_routeid);
      insert into routecontrol
        (routecontrol_id, route_id, routelistprinted, soilticketsprinted, soilcountstatus,
         settlementstatus, packingstatus, originaldrivingdate, drivingdate, packingday_id, timestamp,
         systemuser_id, overageamount, voucheramount, totalcashcollected, totalcoddelayed,
         totalcodpaythisamnt, totalcodundelivered, totalcodplusadj, totalcodminusadj,
         totalcodprebilled, totalchargecollections, totalchargepaythisamnt, totalchargeundelivered,
         totalchargeplusadj, totalchargeminusadj, totalchargeprebilled, returntime, returndate,
         starttime, loadingdock, packingdeadline, truckcode, drivernumber, plant_id,
         invoicesgenerated, arbalance_id, pocketpcstatus, startmileage, endmileage,
         straightevenreturnstatus, routesettlementprinted, activestockcompleted,
         bulkputuproutecompleted, safetyremarks, optimizingstatus, exportdate, truckreloadcalculated)
      values
        (seq_routecontrol.nextval, fp_routeid, 'N', 'N', 1, 1, 1, fp_drivingdate, fp_drivingdate,
         fp_packingdayid, sysdate, gv_systemuserid, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         null, null, null, fp_loadingdock, fp_packingdeadline, fp_truckcode, fp_drivernumber,
         fp_plantid, 1, null, 0, 0, 0, 0, 'N', 'N', 'N', null, 0, null, 'N')
      returning routecontrol_id into lv_routecontrolid;
      --count routecontrol records that are added
      gv_routecontrol_counter := gv_routecontrol_counter + 1;
      lv_rc_stop_count        := 0;
    end create_routecontrol;

    function check_stop(fp_drivingdate in date,
                        fp_routestopid in routestop.routestop_id%type,
                        fp_dayid       in deliveryschemesperstop.day_id%type,
                        fp_customerid  in customer.customer_id%type) return number is
      lv_daycheck number;
    begin
      --check_stop
      gv_message := 'check_stop';
      for z in (select ds.frequency, ds.offsetweek
                from   deliveryschemesperstop dsps
                join   deliveryscheme ds
                on     ds.deliveryscheme_id = dsps.deliveryscheme_id
                where  dsps.routestop_id = fp_routestopid
                and    dsps.day_id = fp_dayid
                and    dsps.customer_id = fp_customerid
                order  by ds.frequency asc) loop
        begin
          select mod((getdateforweekyear(getabsdaynumber(fp_drivingdate), getisoweek(fp_drivingdate),
                                          getyearofweek(fp_drivingdate)) -
                      getdateforweekyear(getabsdaynumber(fp_drivingdate), ds.referenceweek,
                                          ds.referenceyear)), (z.frequency * 7)) -
                  (z.offsetweek * 7)
          into   lv_daycheck
          from   databasesettings ds;
          if lv_daycheck = 0 then
            begin
              return 1;
            end;
          end if;
        end;
      end loop; --x
      return 0;
    end check_stop;

    procedure create_stop(fp_rec_routestop in routestop%rowtype, fp_drivingdate in date) is
    begin
      --create_stop
      gv_message := 'create_stop for routestop id ' || to_char(fp_rec_routestop.routestop_id);
      --get next stop id
      select seq_stop.nextval into lv_stopid from dual;
      --insert into stop
      insert into stop
        (stop_id, routecontrol_id, routestop_id, customer_link_id, stopnumber, arrivaltime,
         departuretime, travelminutes, visitminutes, routelistinstructions, systemuser_id, timestamp,
         movedtostop_id, status, chargedeliveryfee, reasoncode_id, containerno, soilcountstartdate,
         inscanstartdate, services, unloadingstatus, sortingstatus, scrutinystatus, deliverypoint_id,
         contactperson_id, stoptype)
        select lv_stopid, lv_routecontrolid, fp_rec_routestop.routestop_id,
               fp_rec_routestop.customer_id, fp_rec_routestop.stopnumber, null, null, 0, 0,
               case
                 when fp_drivingdate between fp_rec_routestop.instructionsstartdate and
                      fp_rec_routestop.instructionsenddate then
                  fp_rec_routestop.routelistinstructions
                 else
                  null
               end, gv_systemuserid, sysdate, null,
               case
                 when fp_drivingdate between c.dateactive and c.dateinactive then
                  0
                 else
                  4
               end, fp_rec_routestop.chargedeliveryfee, null, fp_rec_routestop.containerno, null,
               null, 0, 1, 1, 11, fp_rec_routestop.deliverypoint_id,
               fp_rec_routestop.contactperson_id, fp_rec_routestop.stoptype
        from   customer c
        where  c.customer_id = fp_rec_routestop.customer_id;
      --count stops added
      gv_stop_counter  := gv_stop_counter + 1;
      lv_rc_stop_count := lv_rc_stop_count + 1;
    end create_stop;

    procedure update_packingnote(fp_routeid         in route.route_id%type,
                                 fp_drivingdate     in date,
                                 fp_customerid      in customer.customer_id%type,
                                 fp_deliverypointid in deliverypoint.deliverypoint_id%type) is
    begin
      --update_packingnote
      gv_message := 'update_packingnote';
      update packingnote pn
      set    pn.routecontrol_id = lv_routecontrolid, pn.stop_id = lv_stopid,
             pn.systemuser_id = gv_systemuserid, pn.timestamp = sysdate
      where  pn.route_id = fp_routeid
      and    pn.deliverydate = fp_drivingdate
      and    exists
       (select 1
              from   distributionpoint dp
              join   department t
              on     t.department_id = dp.department_id
              where  dp.distributionpoint_id = pn.distributionpoint_id
              and    t.customer_id = fp_customerid
              and    ((fp_deliverypointid is null) or (dp.deliverypoint_id = fp_deliverypointid)))
      and    pn.stop_id is null
      and    exists (select 1
              from   status st
              where  st.status_id = pn.status_id
              and    st.code in ('10', '20'));
    end update_packingnote;
  begin
    --process_routecontrols
    gv_message := 'process_routecontrols';
    for y in (select x.route_id, x.drivingdate, x.drivingday_id, x.packingdeadline, x.loadingdock,
                     x.packingday_id,
                     (select tr.code from truck tr where tr.truck_id = x.truck_id) truckcode,
                     (select dr.employeenumber from employee dr where dr.employee_id = x.driver_id) drivernumber
              from   (select r.route_id, r.drivingday_id, r.driver_id, r.packingdeadline,
                              r.loadingdock, r.packingday_id, trunc(sysdate + 14) drivingdate,
                              r.truck_id
                       from   route r
                       where  r.active = 'Y'
                       and    r.drivingday_id = getabsdaynumber(sysdate)
                       and    r.plant_id = fp_plantid) x
              where  not exists (select 1
                      from   routecontrol rc
                      where  rc.route_id = x.route_id
                      and    rc.drivingdate = x.drivingdate)
              and    exists
               (select 1
                      from   routestop rs
                      where  rs.route_id = x.route_id
                      and    rs.dateactive <= x.drivingdate
                      and    rs.dateinactive > x.drivingdate
                      and    exists (select 1
                              from   deliveryschemesperstop dsps
                              where  dsps.customer_id = rs.customer_id
                              and    dsps.day_id = x.drivingday_id
                              and    dsps.routestop_id = rs.routestop_id))) loop
      begin
        --create_routecontrol
        create_routecontrol(y.route_id, y.drivingdate, y.packingdeadline, y.loadingdock,
                            y.packingday_id, y.truckcode, y.drivernumber);
        for z in (select rs.*
                  from   routestop rs
                  where  rs.route_id = y.route_id
                  and    rs.dateactive <= y.drivingdate
                  and    rs.dateinactive > y.drivingdate
                  and    exists (select 1
                          from   deliveryschemesperstop dsps
                          where  dsps.customer_id = rs.customer_id
                          and    dsps.day_id = y.drivingday_id
                          and    dsps.routestop_id = rs.routestop_id)) loop
          begin
            --check_stop
            if check_stop(y.drivingdate, z.routestop_id, y.drivingday_id, z.customer_id) <> 0 then
              begin
                --create_stop
                create_stop(z, y.drivingdate);
                --update_packingnote
                update_packingnote(y.route_id, y.drivingdate, z.customer_id, z.deliverypoint_id);
              end;
            end if;
          end;
        end loop; --z
        if lv_rc_stop_count = 0 then
          begin
            --rollback no stops
            rollback;
          end;
        else
          begin
            -- insert routecontrol internal bu
            createroutecontrolinternalbu(lv_routecontrolid, gv_systemuserid, fp_plantid);

            -- insert RSC ExtraInfo for virtual route (if missing)
            createroutecontrolextrainfo(lv_routecontrolid, gv_systemuserid);
            --commit this RC
            commit;
          end;
        end if;
      end;
    end loop; --x
  end process_routecontrols;

  procedure finalize is
  begin
    --finalize
    gv_message := 'finalize';
    if gv_stop_counter = 0 then
      begin
        --No stops, do not create routecontrol
        gv_routecontrol_counter := 0;
        rollback;
        write_log('No RouteControl records created! ' || chr(13) || chr(10) ||
                  'And no Stop records created!' || chr(13) || chr(10) || 'For plant ' ||
                  gv_plantcode, 2);
      end;
    else
      begin
        commit;
        write_log('RouteControl record(s) created: ' || to_char(gv_routecontrol_counter) ||
                  chr(13) || chr(10) || 'Stop record(s) created: ' || to_char(gv_stop_counter) ||
                  chr(13) || chr(10) || 'For plant ' || gv_plantcode, 1);
      end;
    end if;
    fp_o_status := 0;
  end finalize;
  --start main part procedure
begin
  --initialize
  initialize;
  --process_routecontrols
  process_routecontrols;
  --finalize
  finalize;
exception
  when gv_userexception then
    begin
      write_log(gv_message, 3);
      fp_o_status := 2;
    end;
  when no_data_found then
    begin
      rollback;
      fp_o_status := 2;
      write_log(gv_message || ' no data found', 3);
    end;
  when others then
    begin
      rollback;
      write_log('Error others ' || gv_message || ' ' || sqlerrm, 3);
      fp_o_status := 2;
    end;
end fillroutestatuscontrol;
/
create or replace procedure FillSizeRatio(fp_plant_id       in plant.plant_id%type,
                                          fp_plantprocessid in plantprocess.plantprocess_id%type) is

  lv_message                abslogprocessjobline.message%type;
  lv_abslogprocessjobid     abslogprocessjob.abslogprocessjob_id%type;
  lv_abslogprocessjobpartid abslogprocessjobpart.abslogprocessjobpart_id%type;
  lv_systemuserid           systemuser.systemuser_id%type := 0;
  lv_ratio                  sizeratio.sizeratio%type;
  havingSizesAboveZero      boolean;
  procedure end_log is
  begin
    --end_log
    abslogwrite.abslogprocessjob_update(lv_abslogprocessjobid,
                                        sysdate,
                                        lv_systemuserid);
  exception
    when others then
      begin
        dbms_output.put_line(lv_message);
        dbms_output.put_line(sqlerrm);
      end;
  end end_log;

  procedure write_log(fp_priority abslogprocessjobline.priority%type default 1) is
  begin
    --write_log
    if lv_abslogprocessjobid is null then
      lv_abslogprocessjobid := abslogwrite.abslogprocessjob_write(fp_plant_id,
                                                                  sysdate,
                                                                  null,
                                                                  null,
                                                                  fp_plantprocessid,
                                                                  lv_systemuserid);
    end if;
    --write_log part
    if lv_abslogprocessjobpartid is null and
       lv_abslogprocessjobid is not null then
      lv_abslogprocessjobpartid := abslogwrite.abslogprocessjobpart_write(lv_abslogprocessjobid,
                                                                          'Fill Size Ratio',
                                                                          lv_systemuserid);
    end if;
    --write line
    abslogwrite.abslogprocessjobline_write(lv_abslogprocessjobpartid,
                                           fp_priority,
                                           lv_message,
                                           lv_systemuserid);
  exception
    when others then
      begin
        --give output when cannot safe error logs
        dbms_output.put_line(lv_message);
        dbms_output.put_line(sqlerrm);
      end;
  end write_log;
begin
  -- step 1: Clear the table
  --execute immediate ('truncate table sizeratio');
  delete from sizeratio;
  -- step 2: Calculate the nominal stock
  for rec in (select d.customer_id,
                   plpd.product_id,
                   plpd.sizedefinition_id,
                   sum(rqa.quantity) qty
              from product                    p,
                   productlistperdistribpoint plpd,
                   department                 d,
                   distributionpoint          dp,
                   rentalqtyadjustment        rqa
             where p.sizebreakdown = 'Y'
               and p.product_id = plpd.product_id
               and plpd.distributionpoint_id = dp.distributionpoint_id
               and dp.department_id = d.department_id
               and plpd.productlistperdistribpoint_id =
                   rqa.productlistperdistribpoint_id
               and rqa.origin <> 2
               and rqa.adjustmentdate <= sysdate
               and exists
               (select 1 from productlistpercustomer plpc
                where plpc.customer_id = d.customer_id
                  and plpc.product_id = plpd.product_id
                  and (plpc.sizedefinition_id = plpd.sizedefinition_id or plpc.sizedefinition_id = (select sd.sizedefinition_id from sizedefinition sd where sd.code = '*'))
                  and plpc.dateactive <= sysdate
                  and plpc.dateinactive > sysdate
                )
             group by d.customer_id, plpd.product_id, plpd.sizedefinition_id
            having sum(rqa.quantity) > 0) loop
    insert into sizeratio
      (sizeratio_id, customer_id, product_id, sizedefinition_id, sizeratio, quantity, systemuser_id, timestamp)
    values
      (seq_sizeratio.nextval, rec.customer_id, rec.product_id, rec.sizedefinition_id, 0, rec.qty, 0, sysdate);
  end loop;
  -- step 3: Calculate the size ratio
  update sizeratio sr set sr.sizeratio = round(1000 * (sr.quantity/(select sum(sr2.quantity) from sizeratio sr2
                                         where sr2.customer_id = sr.customer_id and sr2.product_id = sr.product_id)))/1000;
  -- step 4: Fill size ratio for 0 or bellow nominal stock
  for rec in (select c.customernumber,
                 c.defaultbusinessunit_id,
                 c.customer_id,
                 plpc.product_id,
                 count(plpc.sizedefinition_id) numSizes
            from productlistpercustomer plpc, customer c, product p
           where plpc.customer_id = c.customer_id
             and plpc.product_id = p.product_id
             and p.sizebreakdown = 'Y'
             and plpc.dateactive <= sysdate
             and plpc.dateinactive > sysdate
             and nvl((select sum(rqa.quantity)
                    from rentalqtyadjustment        rqa,
                         productlistperdistribpoint plpd,
                         distributionpoint          dp,
                         department                 d
                   where rqa.productlistperdistribpoint_id =
                         plpd.productlistperdistribpoint_id
                     and plpd.distributionpoint_id = dp.distributionpoint_id
                     and dp.department_id = d.department_id
                     and d.customer_id = plpc.customer_id
                     and plpd.product_id = plpc.product_id
                     and rqa.origin <> 2
                     and rqa.adjustmentdate <= sysdate), 0) <= 0
           group by c.customernumber,
                    c.defaultbusinessunit_id,
                    c.customer_id,
                    plpc.product_id) loop
    --step 4 bis - verify if one of the sizes is bigger then 0, then will have all the percentage
     havingSizesAboveZero := false;
     for recBis in (select d.customer_id,
                     plpd.product_id,
                     plpd.sizedefinition_id,
                     sum(rqa.quantity) qty
                from product                    p,
                     productlistperdistribpoint plpd,
                     department                 d,
                     distributionpoint          dp,
                     rentalqtyadjustment        rqa
               where p.sizebreakdown = 'Y'
                 and p.product_id = plpd.product_id
                 and plpd.distributionpoint_id = dp.distributionpoint_id
                 and dp.department_id = d.department_id
                 and plpd.productlistperdistribpoint_id =
                     rqa.productlistperdistribpoint_id
                 and rqa.origin <> 2
                 and rqa.adjustmentdate <= sysdate
                 and d.customer_id = rec.customer_id
                 and p.product_id = rec.product_id
                 and exists
                 (select 1 from productlistpercustomer plpc
                  where plpc.customer_id = d.customer_id
                    and plpc.product_id = plpd.product_id
                    and (plpc.sizedefinition_id = plpd.sizedefinition_id or plpc.sizedefinition_id = (select sd.sizedefinition_id from sizedefinition sd where sd.code = '*'))
                    and plpc.dateactive <= sysdate
                    and plpc.dateinactive > sysdate
                  )
               group by d.customer_id, plpd.product_id, plpd.sizedefinition_id
              having sum(rqa.quantity) > 0) loop
      havingSizesAboveZero := true;
    end loop;
    if (not havingSizesAboveZero) then
      lv_ratio := round(1000 * 1/rec.numSizes)/1000;
      insert into sizeratio(sizeratio_id, customer_id, product_id, sizedefinition_id, sizeratio, quantity, systemuser_id, timestamp)
                  (select seq_sizeratio.nextval, rec.customer_id, rec.product_id, plpc.sizedefinition_id, lv_ratio, 0,
                          0, sysdate from productlistpercustomer plpc
                     where plpc.customer_id = rec.customer_id
                           and plpc.product_id = rec.product_id

                    and plpc.dateactive <= sysdate
                  and plpc.dateinactive > sysdate

                           and not exists (select 1 from sizeratio sr
                                                    where sr.customer_id = plpc.customer_id
                                                    and sr.product_id = plpc.product_id
                                                    and sr.sizedefinition_id = plpc.sizedefinition_id));
    end if;
  end loop;
  -- step 5: Correct the rounding
  for rec2 in (select sr.customer_id, sr.product_id, sum(sr.sizeratio) total
                  from sizeratio sr
                 group by sr.customer_id, sr.product_id
                having sum(sr.sizeratio) <> 1
                ) loop
    update sizeratio sr set sr.sizeratio = 1 - (select sum(sr2.sizeratio) from sizeratio sr2
                                                  where sr2.customer_id = sr.customer_id
                                                  and sr2.product_id = sr.product_id
                                                  and sr2.sizedefinition_id <> sr.sizedefinition_id)
                        where sr.sizeratio_id = (select min(sr3.sizeratio_id) from sizeratio sr3
                                                        where sr3.customer_id = rec2.customer_id
                                                        and sr3.product_id = rec2.product_id
                                                        and sr3.quantity = (select max(sr4.quantity) from sizeratio sr4
                                                                                   where sr4.customer_id = rec2.customer_id
                                                                                   and sr4.product_id = rec2.product_id));
  end loop;

  -- step 6: writing abslog table:
  for rec in (select c.customernumber, p.code pcode, sd.code scode, sr.sizeratio
                from sizeratio sr, customer c, product p, sizedefinition sd
               where sr.customer_id = c.customer_id
                 and sr.product_id = p.product_id
                 and sr.sizedefinition_id = sd.sizedefinition_id
               order by c.customernumber, p.code, sd.code
              ) loop
    lv_message := 'Customer: ' || rec.customernumber || ', Product: ' || rec.pcode || ', Size: ' || rec.scode || ', Ratio: ' || rec.sizeratio;
    write_log(1);
  end loop;
  for rec in (select *
                from (select (select sum(sr.sizeratio)
                                from sizeratio sr
                               where sr.customer_id = d.customer_id
                                 and sr.product_id = plpd.product_id) srQty,
                             (select c.customernumber
                                from customer c
                               where d.customer_id = c.customer_id) customernumber,
                             (select code from product where product_id = plpd.product_id) pcode,
                             (select sum(rqa.quantity)
                                from rentalqtyadjustment rqa
                               where rqa.productlistperdistribpoint_id =
                                     plpd.productlistperdistribpoint_id
                                 and rqa.origin != 2
                                 and rqa.adjustmentdate < sysdate) qty
                        from productlistperdistribpoint plpd,
                             distributionpoint          dp,
                             department                 d,
                             product                    p
                       where plpd.distributionpoint_id = dp.distributionpoint_id
                         and dp.department_id = d.department_id
                         and plpd.product_id = p.product_id
                         and p.sizebreakdown = 'Y'
                         and exists
               (select 1 from productlistpercustomer plpc
                where plpc.customer_id = d.customer_id
                  and plpc.product_id = plpd.product_id
                  and (plpc.sizedefinition_id = plpd.sizedefinition_id or plpc.sizedefinition_id = (select sd.sizedefinition_id from sizedefinition sd where sd.code = '*'))
                  and plpc.dateactive <= sysdate
                  and plpc.dateinactive > sysdate
                ))
               where qty > 0
                 and (srQty is null or srQty != 1)
) loop
    if (rec.srqty is null) then
       lv_message := 'PLPD missing in SizeRatio: Customer: ' || rec.customernumber || ', Product: ' || rec.pcode;
    end if;
    if (rec.srqty < 1) then
       lv_message := 'Wrong Ratio for: Customer: ' || rec.customernumber || ', Product: ' || rec.pcode;
    end if;
    write_log(3);
  end loop;
exception
  when others then
    begin
      lv_message := 'Fill size ratio process not completed. Next error occurred: ' ||
                    sqlerrm;
      write_log(3);
      end_log;
      raise;
    end;
end FillSizeRatio;
/
create or replace PROCEDURE FILLSQARAGING(FpSTATUSQUOHEADER_ID IN NUMBER, FpSystemUser_ID IN NUMBER,
                         Fpabslogprocessjobid in abslogprocessjob.abslogprocessjob_id%type)    IS
--procedure FILLSQARAGING version 1.1
gvnabslogprocessjobpartid abslogprocessjobpart.abslogprocessjobpart_id%type;
gv_araginginvoicebu dwh_settings.araginginvoicebu%type;
BEGIN
  --to use PROCESSBUSINESSUNIT_ID (N) or INVOICEBUSINESSUNIT_ID (Y)
  select max(dwh.araginginvoicebu)
  into gv_araginginvoicebu
  from dwh_settings dwh;
if nvl(gv_araginginvoicebu,'N')='N' then
  begin
  --same statement but now with STATUSQUOHEADER.PROCESSBUSINESSUNIT_ID (default)
MERGE INTO SQARAGING A
USING (select c.customer_id,
              c.currency_id,
              F_GETARAGINGAMOUNTNORPPARAM(C.CUSTOMER_ID, 0) AMOUNTCURRENT,
              F_GETARAGINGAMOUNTNORPPARAM(C.CUSTOMER_ID, 1) AMOUNT30,
              F_GETARAGINGAMOUNTNORPPARAM(C.CUSTOMER_ID, 2) AMOUNT60,
              F_GETARAGINGAMOUNTNORPPARAM(C.CUSTOMER_ID, 3) AMOUNT90,
              F_GETARAGINGAMOUNTNORPPARAM(C.CUSTOMER_ID, 4) AMOUNT120,
              (select sum(y.amount-y.totalappliedamount)
                 from artransaction y, artransactiontype t
                where y.billtocustomer_link_id = C.CUSTOMER_ID
                  and t.artransactiontype_id = y.artransactiontype_id
                  and t.typenumber <> 2
                  and y.isopen_yn = 'Y'
                  and y.debitcredit = 'C') UNAPPLIEDCREDITAMOUNT
         FROM CUSTOMER C, STATUSQUOHEADER H
        WHERE H.STATUSQUOHEADER_ID = FpSTATUSQUOHEADER_ID
          AND C.DEFAULTBUSINESSUNIT_ID = H.PROCESSBUSINESSUNIT_ID) x
ON (x.customer_id = a.customer_link_id and
    FpSTATUSQUOHEADER_ID = a.statusquoheader_id)
WHEN NOT MATCHED THEN
  INSERT
    (a.sqaraging_id,
     a.statusquoheader_id,
     a.customer_link_id,
     a.currency_id,
     a.amountcurrent,
     a.amount30,
     a.amount60,
     a.amount90,
     a.amount120,
     a.unappliedcreditamount,
     a.systemuser_id,
     a.timestamp)
  VALUES
    (seq_sqaraging.nextval,
     FpSTATUSQUOHEADER_ID,
     x.customer_id,
     x.currency_id,
     x.amountcurrent,
     x.amount30,
     x.amount60,
     x.amount90,
     x.amount120,
     x.unappliedcreditamount,
     FpSystemUser_ID,
     sysdate);
     end;
else
  begin
  --same statement but now with STATUSQUOHEADER.INVOICEBUSINESSUNIT_ID
MERGE INTO SQARAGING A
USING (select c.customer_id,
              c.currency_id,
              F_GETARAGINGAMOUNTNORPPARAM(C.CUSTOMER_ID, 0) AMOUNTCURRENT,
              F_GETARAGINGAMOUNTNORPPARAM(C.CUSTOMER_ID, 1) AMOUNT30,
              F_GETARAGINGAMOUNTNORPPARAM(C.CUSTOMER_ID, 2) AMOUNT60,
              F_GETARAGINGAMOUNTNORPPARAM(C.CUSTOMER_ID, 3) AMOUNT90,
              F_GETARAGINGAMOUNTNORPPARAM(C.CUSTOMER_ID, 4) AMOUNT120,
              (select sum(y.amount-y.totalappliedamount)
                 from artransaction y, artransactiontype t
                where y.billtocustomer_link_id = C.CUSTOMER_ID
                  and t.artransactiontype_id = y.artransactiontype_id
                  and t.typenumber <> 2
                  and y.isopen_yn = 'Y'
                  and y.debitcredit = 'C') UNAPPLIEDCREDITAMOUNT
         FROM CUSTOMER C, STATUSQUOHEADER H
        WHERE H.STATUSQUOHEADER_ID = FpSTATUSQUOHEADER_ID
          AND C.DEFAULTBUSINESSUNIT_ID = H.INVOICEBUSINESSUNIT_ID) x
ON (x.customer_id = a.customer_link_id and
    FpSTATUSQUOHEADER_ID = a.statusquoheader_id)
WHEN NOT MATCHED THEN
  INSERT
    (a.sqaraging_id,
     a.statusquoheader_id,
     a.customer_link_id,
     a.currency_id,
     a.amountcurrent,
     a.amount30,
     a.amount60,
     a.amount90,
     a.amount120,
     a.unappliedcreditamount,
     a.systemuser_id,
     a.timestamp)
  VALUES
    (seq_sqaraging.nextval,
     FpSTATUSQUOHEADER_ID,
     x.customer_id,
     x.currency_id,
     x.amountcurrent,
     x.amount30,
     x.amount60,
     x.amount90,
     x.amount120,
     x.unappliedcreditamount,
     FpSystemUser_ID,
     sysdate);
  end;
end if;
COMMIT;
-- delete the rows with all nulls, this is faster than not filtering them out in the merge.
delete from sqaraging a
 where a.statusquoheader_id = FpSTATUSQUOHEADER_ID
   and a.amountcurrent is null
   and a.amount30 is null
   and a.amount60 is null
   and a.amount90 is null
   and a.amount120 is null
   and a.unappliedcreditamount is null;
COMMIT;
exception
  when others then
    begin
      rollback;
      gvnabslogprocessjobpartid := abslogwrite.abslogprocessjobpart_write(Fpabslogprocessjobid,
                                                                    'Fill SQ ARAging',
                                                                    FpSystemUser_ID);
      abslogwrite.abslogprocessjobline_write(gvnabslogprocessjobpartid, 3, substr(sqlerrm, 1, 200),
                 FpSystemUser_ID);
    end;
END;
/
create or replace procedure fill_activestocklocationdist(fp_businessunitcode in varchar2) is
  --Version 0.7 fill_activestocklocationdist
  --Will fill the table activestocklocationdist based upon x/ycoordinate activestocklocation
  --Global variables
  gv_userexception exception;
  gv_ins_counter    number := 0;
  gv_upd_counter    number := 0;
  gv_businessunitid businessunit.businessunit_id%type;
  gv_message        varchar2(1000);
  gv_systemuserid   number;

  --Internal procedures
  procedure write_log(fp_message in varchar2, fp_priority in number) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'fill_activestocklocationdist', null, fp_priority, fp_message,
                             gv_systemuserid);
    begin
      dbms_output.put_line(fp_message);
    exception
      when others then
        null; --ok no output to screen
    end;
  end write_log;

  procedure initialize is
  begin
    --initialize
    if fp_businessunitcode is null then
      begin
        gv_message := 'parameter fp_businessunitcode cannot be left blank';
        raise gv_userexception;
      end;
    else
      begin
        gv_message := 'get businessunit ' || fp_businessunitcode;
        select bu.businessunit_id
        into   gv_businessunitid
        from   businessunit bu
        where  bu.code = fp_businessunitcode;
      end;
    end if;
    --get systemuser
    gv_message := 'get systemuser';
    select max(st.systemuser_id)
    into   gv_systemuserid
    from   systemuser st
    where  st.username = 'CONVERSION';
    gv_systemuserid := nvl(gv_systemuserid, 1);
  end initialize;

  procedure insert_locationdist is
  begin
    --insert_locationdist
    gv_message := 'insert_locationdist';
    insert into activestocklocationdist
      (businessunit_id, activestocklocation_id, toactivestocklocation_id, distance, systemuser_id,
       timestamp)
      select fromasl.businessunit_id, fromasl.activestocklocation_id, toasl.activestocklocation_id,
             round(sqrt(power(fromasl.xcoordinate - toasl.xcoordinate, 2) +
                         power((fromasl.ycoordinate - toasl.ycoordinate) * 2, 2)), 2),
             gv_systemuserid, sysdate
      from   activestocklocation fromasl
      join   activestocklocation toasl
      on     fromasl.businessunit_id = toasl.businessunit_id
      where  fromasl.businessunit_id = gv_businessunitid
      and    not exists
       (select 1
              from   activestocklocationdist phl
              where  phl.activestocklocation_id = fromasl.activestocklocation_id
              and    phl.toactivestocklocation_id = toasl.activestocklocation_id);
    --count rows inserted
    gv_ins_counter := sql%rowcount;
  end insert_locationdist;

  procedure update_locationdist is
  begin
    --update_locationdist
    gv_message := 'update_locationdist';
    update activestocklocationdist phl
    set    phl.distance =
            (select round(sqrt(power(fromasl.xcoordinate - toasl.xcoordinate, 2) +
                                power((fromasl.ycoordinate - toasl.ycoordinate) * 2, 2)), 2)
             from   activestocklocation fromasl
             join   activestocklocation toasl
             on     fromasl.businessunit_id = toasl.businessunit_id
             where  fromasl.activestocklocation_id = phl.activestocklocation_id
             and    toasl.activestocklocation_id = phl.toactivestocklocation_id),
           phl.timestamp = sysdate, phl.systemuser_id = gv_systemuserid
    where  exists (select 1
            from   activestocklocation ax
            where  ax.activestocklocation_id = phl.activestocklocation_id
            and    ax.businessunit_id = gv_businessunitid)
    and    phl.distance <>
           (select round(sqrt(power(fromasl.xcoordinate - toasl.xcoordinate, 2) +
                                power((fromasl.ycoordinate - toasl.ycoordinate) * 2, 2)), 2)
             from   activestocklocation fromasl
             join   activestocklocation toasl
             on     fromasl.businessunit_id = toasl.businessunit_id
             where  fromasl.activestocklocation_id = phl.activestocklocation_id
             and    toasl.activestocklocation_id = phl.toactivestocklocation_id);
    --count rows inserted
    gv_upd_counter := sql%rowcount;
  end update_locationdist;

  procedure finalize is
    lv_total number;
  begin
    --finalize
    commit;
    --count total
    gv_message := 'finalize count total';
    select count(1) into lv_total from activestocklocationdist;
    --write message
    write_log('Ready inserted ' || gv_ins_counter || ' records, updated ' || gv_upd_counter ||
              ' records, total ' || to_char(lv_total) ||
              ' records now in activestocklocationdist for businessunitcode ' ||
              fp_businessunitcode, 1);
  end finalize;
begin
  --fill_activestocklocationdist
  --initialize
  initialize;
  --insert new
  insert_locationdist;
  --update difference
  update_locationdist;
  --finalize
  finalize;
exception
  --Exception handling
  when gv_userexception then
    begin
      rollback;
      write_log(gv_message, 3);
    end;
  when no_data_found then
    begin
      rollback;
      write_log('Error, No Data Found ' || gv_message, 3);
    end;
  when others then
    begin
      rollback;
      write_log('Error ' || sqlerrm || ' ' || gv_message || ' ran for BU ' || fp_businessunitcode,
                3);
    end;
end fill_activestocklocationdist;
/
create or replace procedure fill_date_yearweek(fp_update_coming_years in varchar2 default null) as
  --Procedure fill_date_yearweek version 2.0
  --ABS-145172 date_yearweekday procedure update for 2024 ( week numbers )
  lv_startyesno       number;
  lv_d_start_val_date date := to_date('31-12-1999', 'dd-mm-yyyy');
  lv_d_end_val_date   date := to_date('31-12-2099', 'dd-mm-yyyy');
  lv_d_date           date;
  lv_insertcount      number := 0;

  --Internal procedures
  procedure write_log(fp_message in varchar2, fp_priority in number) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'fill_date_yearweek', null, fp_priority, fp_message);
    begin
      dbms_output.put_line(fp_message);
    exception
      when others then
        null; --ok no output to screen
    end;
  end write_log;

  procedure fill_weekseq is
    lv_prevweek number := 0;
    lv_teller   number := -1;
    --set Sunday for ABS to current week for US
    lv_us_week number := 0;
    lv_us_year number := 0;
  begin
    begin
      execute immediate 'DROP INDEX XAK2DATE_YEARWEEKDAY';
    exception
      when others then
        null;
    end;
    ---
    for x in (select dyw.*,
                     (select min(cast(to_char(zz.date_, 'WW') as numeric)) us_week
                       from   date_yearweekday zz
                       where  zz.week = dyw.week
                       and    zz.year = dyw.year
                       and    zz.day <> 7) new_us_week,
                     (select max(cast(to_char(zz.date_, 'YYYY') as numeric)) us_year
                       from   date_yearweekday zz
                       where  zz.week = dyw.week
                       and    zz.year = dyw.year
                       and    zz.day <> 7) max_us_year
              from   date_yearweekday dyw
              where  ((fp_update_coming_years is not null and lv_startyesno <> 0 and
                     dyw.us_year > cast(to_char(sysdate, 'YYYY') as numeric)) or
                     (lv_startyesno = 0))
              order  by dyw.date_ asc) loop
      begin
        --update american weeknumbers
        if (lv_prevweek <> x.week and x.new_us_week = 1 and lv_us_week <> 1 and lv_us_week <> 0) or
           (lv_us_year = 0) then
          begin
            lv_us_week := 0;
            lv_us_year := x.max_us_year;
          end;
        end if;
        if lv_prevweek <> x.week then
          begin
            lv_teller   := lv_teller + 1;
            lv_prevweek := x.week;
            lv_us_week  := lv_us_week + 1;
          end;
        end if;
        update date_yearweekday y
        set    y.weekseq = lv_teller, y.us_week = lv_us_week, y.us_year = lv_us_year
        where  y.date_ = x.date_;
      end;
    end loop; --x
    execute immediate 'CREATE UNIQUE INDEX XAK2DATE_YEARWEEKDAY ON DATE_YEARWEEKDAY (US_YEAR, US_WEEK, DAY)';
  end fill_weekseq;

  procedure start_fill_table is
  begin
    --start_fill_table
    execute immediate 'ALTER SESSION SET NLS_LANGUAGE= ''AMERICAN'' NLS_TERRITORY= ''AMERICA''';
    for i in 0 .. lv_d_end_val_date - lv_d_start_val_date loop
      begin
        lv_d_date := lv_d_start_val_date + i;
        insert into date_yearweekday
          (date_, year, week, day, us_year, us_week, us_day)
        values
          (lv_d_date, cast(to_char(lv_d_date, 'IYYY') as numeric),
           cast(to_char(lv_d_date, 'IW') as numeric), getabsdaynumber(lv_d_date),
           cast(to_char(lv_d_date, 'IYYY') as numeric), cast(to_char(lv_d_date, 'IW') as numeric),
           cast(to_char(lv_d_date, 'D') as numeric));
        lv_insertcount := lv_insertcount + 1;
      exception
        when dup_val_on_index then
          begin
            write_log(sqlerrm || ' fill Date ' || to_char(lv_d_date, 'DD-MM-YYYY'), 3);
          end;
      end;
    end loop;
    --fill_weekseq
    fill_weekseq;
  end start_fill_table;
begin
  --run only once to fill the table
  select count(1) into lv_startyesno from date_yearweekday dyw;
  if lv_startyesno = 0 then
    begin
      start_fill_table;
      commit;
    end;
  elsif fp_update_coming_years is not null then
    begin
      fill_weekseq;
      commit;
    end;
  end if;
  commit;
  write_log('Ready', 1);
exception
  when others then
    begin
      rollback;
      write_log(sqlerrm, 3);
    end;
end fill_date_yearweek;
/
create or replace procedure fill_sq_daily_ar_u(fp_businessunitid in number,
                                               fp_systemuserid   in number default 1,
                                               fp_result         out nocopy number,
                                               fp_message        out nocopy varchar2) is
  --Version 0.4 fill_sq_daily_ar_u
  --Global variables
  gv_userexception exception;
  gv_plantid plant.plant_id%type;

  --Internal procedures
  procedure write_log(fp_priority in number) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'fill_sq_daily_ar_u', gv_plantid, fp_priority, fp_message);
    begin
      dbms_output.put_line(fp_message);
    exception
      when others then
        null; --ok no output to screen
    end;
  end write_log;

  procedure initialize is
  begin
    --initialize
    --check parameter fp_businessunitid
    if fp_businessunitid is null then
      begin
        fp_message := 'Parameter fp_businessunitid cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        --get plant id
        fp_message := 'parameter fp_businessunitid ' || to_char(fp_businessunitid);
        select bu.plant_id
        into   gv_plantid
        from   businessunit bu
        where  bu.businessunit_id = fp_businessunitid;
      end;
    end if;
    --check parameter  fp_systemuserid
    if fp_systemuserid is null then
      begin
        fp_message := 'Parameter fp_systemuserid cannot be left blank!';
        raise gv_userexception;
      end;
    end if;
  end initialize;

  procedure fill_sq_daily_ar is
  begin
    --fill_sq_daily_ar
    fp_message := 'fill_sq_daily_ar';
    insert into sq_daily_ar_u
      (sq_daily_ar_u_id, businessunit_id, currency_id, turnovergroup_id, artransactiondate,
       debitcredit, fiscalyear, fiscalmonth, debitamount, creditamount, proces_status, systemuser_id,
       timestamp)
      select seq_sq_daily_ar_u.nextval, x.businessunit_id, x.currency_id, x.turnovergroup_id,
             x.artransactiondate, x.debitcredit, x.fiscalyear, x.fiscalmonth, x.debitamount,
             x.creditamount, x.proces_status, fp_systemuserid, sysdate
      from   (select a.businessunit_id, a.currency_id, ad.turnovergroup_id, a.artransactiondate,
                      a.debitcredit,
                      max(nvl(dfy.fiscalyear, to_number(to_char(a.artransactiondate, 'YYYY')))) fiscalyear,
                      max(nvl(dfy.fiscalmonth, to_number(to_char(a.artransactiondate, 'MM')))) fiscalmonth,
                      case
                        when a.debitcredit = 'D' then
                         sum(ad.amount)
                        else
                         0
                      end debitamount,
                      case
                        when a.debitcredit = 'C' then
                         sum(ad.amount)
                        else
                         0
                      end creditamount, 0 proces_status
               from   artransaction a
               join   artransactiondetail ad
               on     ad.artransaction_id = a.artransaction_id
               left   outer join date_fiscalyear dfy
               on     dfy.date_ = a.artransactiondate
               where  a.artransactiondate between trunc(sysdate) - 64 and trunc(sysdate) - 1 --max 2 months back
               group  by a.artransactiondate, a.businessunit_id, a.currency_id, ad.turnovergroup_id,
                         a.debitcredit
               order  by a.artransactiondate, a.businessunit_id, a.currency_id, ad.turnovergroup_id) x
      where  not exists (select 1
              from   sq_daily_ar_u z
              where  z.businessunit_id = x.businessunit_id
              and    z.currency_id = x.currency_id
              and    z.turnovergroup_id = x.turnovergroup_id
              and    z.artransactiondate = x.artransactiondate
              and    z.debitcredit = x.debitcredit);
  end fill_sq_daily_ar;

  procedure finalize is
  begin
    --finalize
    commit;
    --return message
    fp_message := 'Ok';
    write_log(1);
    fp_result := 0;
  end finalize;
begin
  --initialize
  initialize;
  --fill_sq_daily_ar
  fill_sq_daily_ar;
  --finalize
  finalize;
exception
  --Exception handling
  when gv_userexception then
    begin
      rollback;
      write_log(3);
      fp_result := 1;
    end;
  when no_data_found then
    begin
      rollback;
      fp_message := 'Error, No Data Found ' || fp_message;
      write_log(3);
      fp_result := 2;
    end;
  when others then
    begin
      rollback;
      fp_message := 'Error ' || sqlerrm || ' ' || fp_message;
      write_log(3);
      fp_result := 3;
    end;
end fill_sq_daily_ar_u;
/
create or replace procedure generateinternetorders(fp_customerid           in customer.customer_id%type,
                                                   fp_stockcountscheduleid in stockcountschedule.stockcountschedule_id%type,
                                                   fp_language1_id         in languages.language_id%type,
                                                   fp_language2_id         in languages.language_id%type,
                                                   fp_webuserid            in webuser.webuser_id%type,
                                                   fp_fromdepartmentno     in number,
                                                   fp_todepartmentno       in number,
                                                   fp_order_date           in date,
                                                   fp_systemuserid         in systemuser.systemuser_id%type,
                                                   fp_reportrunid          in number) is
  --Version 2.2
  --ABS-54324 Redesign of generateinternetorders procedure
  --ABSN-1846 Fixed amount for internetorderlines based on system setting OVERRULESSTANDARDDELIVERY for order method
  gv_systemuserid         systemuser.systemuser_id%type := null;
  gv_plantid              plant.plant_id%type := null;
  gv_message              abslog.message%type;
  gv_ioh_id               internetorder.internetorder_id%type;
  gv_tmlinen              integer;
  gv_tmgarm               integer;
  gv_tmsales              integer;
  gv_sizestar_id          sizedefinition.sizedefinition_id%type;
  gv_databasecode         databasesettings.code%type;
  gv_deldaynrlin          integer;
  gv_deldatelin           date;
  gv_delweeklin           number;
  gv_deldaynrgarm         number;
  gv_delweekgarm          number;
  gv_deldategarm          date;
  gv_deldaynr             number;
  gv_deldatelindeldeterm  date;
  gv_deldaylindeldeterm   number;
  gv_deldategarmdeldeterm date;
  gv_deldaygarmdeldeterm  number;
  gv_fixedamount         systemsetting.value%type:='N';
  --internal procedures
 procedure write_log(fp_message in varchar2, fp_priority in number) is
  begin
    /* Logging: write message in ABSLOG with these priorities for fp_priority:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'GENERATEINTERNETORDERS', gv_plantid, fp_priority, fp_message,
                             gv_systemuserid);
    begin
      dbms_output.put_line(fp_message);
    exception
      when others then
        null;
    end;
  end write_log;

  procedure initialize is
    procedure determine_toms is
      lv_accesssales    webuser.accesssalesitems%type;
      lv_accessgarments webuser.accessgarments%type;
      lv_accesslinen    webuser.accessnongarments%type;
      lv_linen          boolean;
      lv_garments       boolean;
      lv_sales          boolean;
    begin
      --determine_toms
      gv_message := 'determine_toms';
      --webuser used
      if (fp_webuserid > -1) then
        begin
          --select WebUser record to determine the type of merchandise
          gv_message := 'webuser id ' || fp_webuserid;
          select w.accessgarments, w.accessnongarments, w.accesssalesitems
          into   lv_accessgarments, lv_accesslinen, lv_accesssales
          from   webuser w
          where  w.webuser_id = fp_webuserid;
          --Determine which TOM can be used
          if (lv_accessgarments = 'Y') then
            lv_garments := true;
          else
            lv_garments := false;
          end if;
          if (lv_accesslinen = 'Y') then
            lv_linen := true;
          else
            lv_linen := false;
          end if;
          if (lv_accesssales = 'Y') then
            lv_sales := true;
          else
            lv_sales := false;
          end if;
        end;
        begin
          --select CustomerInternetOptions to determine type of merchandise
          gv_message := 'customerinternetoptions for customer id ' || fp_customerid;
          select cio.ordergarments, cio.orderlinen, cio.ordersalesitems
          into   lv_accessgarments, lv_accesslinen, lv_accesssales
          from   customerinternetoptions cio
          where  cio.customer_id = fp_customerid;
          --Determine which TOM can be used
          if (lv_garments and lv_accessgarments = 'Y') then
            lv_garments := true;
          else
            lv_garments := false;
          end if;
          if (lv_linen and lv_accesslinen = 'Y') then
            lv_linen := true;
          else
            lv_linen := false;
          end if;
          if (lv_sales and lv_accesssales = 'Y') then
            lv_sales := true;
          else
            lv_sales := false;
          end if;
        exception
          when no_data_found then
            begin
              if not (fp_webuserid > -1) then
                begin
                  lv_garments := true;
                  lv_linen    := true;
                  lv_sales    := true;
                end;
              end if;
            end;
        end;
      else
        begin
          lv_garments := true;
          lv_linen    := true;
          lv_sales    := true;
        end;
      end if;
      --set allowed types of merchandise
      if (lv_garments = true) then
        gv_tmgarm := 2;
      else
        gv_tmgarm := 0;
      end if;
      if (lv_linen = true) then
        gv_tmlinen := 1;
      else
        gv_tmlinen := 0;
      end if;
      if (lv_sales = true) then
        gv_tmsales := 3;
      else
        gv_tmsales := 0;
      end if;
    end determine_toms;
  begin
    --initialize
    --determine_toms
    --read systemsetting
       if (fp_webuserid > -1) then
      select ss.value
          into    gv_fixedamount
          from   webuser w,systemsetting ss
          where  w.webuser_id = fp_webuserid
                 and ss.plant_id=  w.plant_id
                 and ss.name='OVERRULESSTANDARDDELIVERY';
     end if;
    determine_toms;
    --get size *
    gv_message := 'get size *';
    select s.sizedefinition_id into gv_sizestar_id from sizedefinition s where s.code = '*';
    --get databasesettings code for setting long product description -> todo 23837 for BCM
    gv_message := 'get database setting';
    select dbs.code into gv_databasecode from databasesettings dbs;
    --get day, week of delivery date for linen
    gv_message := 'get day/week number';
    begin
      gv_deldatelin := pack_sort.getnextdeliverydate(fp_order_date, fp_customerid, 1);
    exception
      when others then
        begin
          gv_deldatelin := fp_order_date;
        end;
    end;
    gv_delweeklin  := getisoweek(gv_deldatelin);
    gv_deldaynrlin := getabsdaynumber(gv_deldatelin);
    --get day, week of delivery date for garments
    begin
      gv_deldategarm := pack_sort.getnextdeliverydate(fp_order_date, fp_customerid, 2);
    exception
      when others then
        begin
          gv_deldategarm := fp_order_date;
        end;
    end;
    gv_delweekgarm  := getisoweek(gv_deldategarm);
    gv_deldaynrgarm := getabsdaynumber(gv_deldategarm);
    gv_deldaynr     := getabsdaynumber(fp_order_date);
  end initialize;

  procedure generate_orders is

    procedure getcreateinternetorder(fp_dip_id in number) is
      lv_internetorderstatus internetorder.status%type;
    begin
      --getcreateinternetorder
      gv_message := 'getcreateinternetorder for distributionpoint id ' || fp_dip_id;
      select io.internetorder_id, io.status
      into   gv_ioh_id, lv_internetorderstatus
      from   internetorder io
      where  io.distributionpoint_link_id = fp_dip_id
      and    io.orderdate = fp_order_date;
      if lv_internetorderstatus = 1 then
        begin
          --delete old lines, because we are going to do this again
          delete from internetorderline iol where iol.internetorder_id = gv_ioh_id;
        end;
      end if;
    exception
      when no_data_found then
        begin
          insert into internetorder
            (internetorder_id, orderdate, status, distributionpoint_link_id, systemuser_id,
             timestamp)
          values
            (seq_internetorder.nextval, fp_order_date, 1, fp_dip_id, fp_systemuserid, sysdate)
          returning internetorder_id into gv_ioh_id;
        end;
    end getcreateinternetorder;
  begin
    --generate_orders
    gv_message := 'generate_orders';
    --loop stockcountscheduledist / distributionpoint
    for x in (select scdist.distributionpoint_id, dp.department_id, max(t.occupancy) occupancy,
                     scs.deliverydaydetermination
              from   stockcountscheduledist scdist
              join   distributionpoint dp
              on     dp.distributionpoint_id = scdist.distributionpoint_id
              join   stockcountschedule scs
              on     scs.stockcountschedule_id = scdist.stockcountschedule_id
              join   department t
              on     t.department_id = dp.department_id
              where  dp.active = 'Y'
              and    t.active = 'Y'
              and    t.customer_id = fp_customerid
              and    (scdist.stockcountschedule_id = fp_stockcountscheduleid or
                    nvl(fp_stockcountscheduleid, -1) = -1)
              and    ((t.departmentnumber between fp_fromdepartmentno and fp_todepartmentno) or
                    nvl(fp_fromdepartmentno, -1) = -1)
              and    ((dp.department_id in
                    (select rp.number_value
                        from   reportparam rp
                        where  rp.reportparam_id = fp_reportrunid)) or
                    (nvl(fp_reportrunid, -1) = -1))
              and    exists
               (select 1
                      from   stockcountscheduleday scsd
                      where  scsd.stockcountschedule_id = scdist.stockcountschedule_id
                      and    scsd.day_id = gv_deldaynr)
              and    (exists (select 1
                              from   webuserdepartment wdep
                              join   webusercustomer wcust
                              on     wcust.webusercustomer_id = wdep.webusercustomer_id
                              where  wdep.department_id = t.department_id
                              and    (wcust.webuser_id = fp_webuserid)
                              and    wcust.customer_id = t.customer_id) or not exists
                     (select 1
                       from   webuserdepartment wdep
                       join   webusercustomer wcust
                       on     wcust.webusercustomer_id = wdep.webusercustomer_id
                       where  (wcust.webuser_id = fp_webuserid)
                       and    wcust.customer_id = t.customer_id))
              group  by scdist.distributionpoint_id, dp.department_id, scs.deliverydaydetermination) loop
      begin
        --getcreateinternetorder
        getcreateinternetorder(x.distributionpoint_id);
        if x.deliverydaydetermination = 1 then
          gv_deldatelindeldeterm  := determine_delivery_date(fp_customerid, gv_deldaynr,
                                                             fp_stockcountscheduleid, fp_webuserid,
                                                             fp_fromdepartmentno, fp_todepartmentno,
                                                             fp_reportrunid, fp_order_date,
                                                             x.distributionpoint_id, 1);
          gv_deldaylindeldeterm   := getabsdaynumber(gv_deldatelindeldeterm);
          gv_deldategarmdeldeterm := determine_delivery_date(fp_customerid, gv_deldaynr,
                                                             fp_stockcountscheduleid, fp_webuserid,
                                                             fp_fromdepartmentno, fp_todepartmentno,
                                                             fp_reportrunid, fp_order_date,
                                                             x.distributionpoint_id, 2);
          gv_deldaygarmdeldeterm  := getabsdaynumber(gv_deldategarmdeldeterm);
        end if;
        --loop productlistperdistribpoint / standarddeliveryline
        --insert into internetorderline
        gv_message := 'insert into internetorderline distributionpoint id ' ||
                      x.distributionpoint_id;
        insert into internetorderline
          (internetorderline_id, quantity, type, fixedamount, internetorder_id, product_link_id,
           sizedefinition_link_id, deliveryvariations_id, finishingmethod_id, productcode,
           systemuser_id, productdescription, timestamp, normstockamount, standarddeliveryamount,
           maxorderqty)
          select seq_internetorderline.nextval, null, y.orderingmethod, y.fixedamount, gv_ioh_id, y.product_id,
                 y.sizedefinition_id, null, y.finishingmethod_id, y.productcode, fp_systemuserid,
                 y.product_desc, sysdate, nvl(y.normstockamnt, 0), nvl(y.staamount, 0),
                 f_getmaxorderqty(y.plpd_id, fp_order_date)
          from   (select nvl(max((select l.customcode
                                   from   productlistpercustomer l
                                   where  l.productlistpercustomer_id = stl.productlistpercustomer_id)),
                               max(p.code)) productcode, plpd.product_id, plpd.sizedefinition_id,
                          plpd.finishingmethod_id, p.typeofmerchandise, plpd.orderingmethod,
                          max(plpd.productlistperdistribpoint_id) plpd_id,
                          sum((select sum(nsa.amount)
                               from   normstockamount nsa
                               where  nsa.productlistperdistribpoint_id =
                                      plpd.productlistperdistribpoint_id
                               and    plpd.orderingmethod <> 2
                               and    nsa.day_id = gv_deldaynr)) normstockamnt,
                          round(sum(((select sum(sta.amount)
                                       from   standarddeliveryamount sta
                                       where  sta.standarddeliveryline_id = stl.standarddeliveryline_id
                                       and    sta.day_id = case p.typeofmerchandise
                                                when 2 then
                                                 case x.deliverydaydetermination
                                                   when 1 then
                                                    gv_deldaygarmdeldeterm
                                                   else
                                                    gv_deldaynrgarm
                                                 end
                                                else
                                                 case x.deliverydaydetermination
                                                   when 1 then
                                                    gv_deldaylindeldeterm
                                                   else
                                                    gv_deldaynrlin
                                                 end
                                              end
                                       and    case p.typeofmerchandise
                                               when 2 then
                                                case x.deliverydaydetermination
                                                  when 1 then
                                                   gv_deldategarmdeldeterm
                                                  else
                                                   gv_deldategarm
                                                end
                                               else
                                                case x.deliverydaydetermination
                                                  when 1 then
                                                   gv_deldatelindeldeterm
                                                  else
                                                   gv_deldatelin
                                                end
                                             end between stl.dateactive and stl.dateinactive
                                       and    (stl.season_id is null or
                                             (stl.season_id is not null and exists
                                              (select s.season_id
                                                 from   seasonweek sw
                                                 join   season s
                                                 on     s.season_id = sw.season_id
                                                 where  sw.weeknumber = case
                                                          when p.typeofmerchandise = 2 then
                                                           gv_delweekgarm
                                                          else
                                                           gv_delweeklin
                                                        end
                                                 and    s.season_id = stl.season_id)))
                                       and    not exists
                                        (select dd.day_id
                                               from   deliveryday dd
                                               where  dd.department_id = x.department_id
                                               and    dd.day_id = case p.typeofmerchandise
                                                        when 2 then
                                                         case x.deliverydaydetermination
                                                           when 1 then
                                                            gv_deldaygarmdeldeterm
                                                           else
                                                            gv_deldaynrgarm
                                                         end
                                                        else
                                                         case x.deliverydaydetermination
                                                           when 1 then
                                                            gv_deldaylindeldeterm
                                                           else
                                                            gv_deldaynrlin
                                                         end
                                                      end)) * x.occupancy) / 100)) staamount,
                          case
                            when gv_databasecode = 'BCM' then
                             coalesce(max((select pd.description
                                          from   product_desc pd
                                          where  pd.product_id = plpd.product_id
                                          and    pd.language_id = fp_language1_id)),
                                      max((select pd.description
                                           from   product_desc pd
                                           where  pd.product_id = plpd.product_id
                                           and    pd.language_id = fp_language2_id)),
                                      (max((select l.customdescription
                                            from   productlistpercustomer l
                                            where  l.productlistpercustomer_id =
                                                   stl.productlistpercustomer_id))))
                            else
                             coalesce((max((select l.customdescription
                                           from   productlistpercustomer l
                                           where  l.productlistpercustomer_id =
                                                  stl.productlistpercustomer_id))),
                                      max((select pd.description
                                           from   product_desc pd
                                           where  pd.product_id = plpd.product_id
                                           and    pd.language_id = fp_language1_id)),
                                      max((select pd.description
                                           from   product_desc pd
                                           where  pd.product_id = plpd.product_id
                                           and    pd.language_id = fp_language2_id)))
                          end product_desc,
                          case
                            when plpd.orderingmethod <> 2 then 'N'
                              else nvl(gv_fixedamount,'N') end fixedamount
                   from   standarddeliveryline stl
                   join   productlistperdistribpoint plpd
                   on     plpd.productlistperdistribpoint_id = stl.productlistperdistribpoint_id
                   join   product p
                   on     p.product_id = plpd.product_id
                   where  plpd.distributionpoint_id = x.distributionpoint_id --loop for x.distributionpoint_id
                   and    fp_order_date between stl.dateactive and stl.dateinactive
                   and    plpd.sizedefinition_id != gv_sizestar_id
                   and    p.typeofmerchandise in (gv_tmlinen, gv_tmgarm, gv_tmsales)
                   and    exists (select 1
                           from   normstockamount nsa
                           where  nsa.productlistperdistribpoint_id =
                                  plpd.productlistperdistribpoint_id
                           and    nsa.day_id = gv_deldaynr)
                   and    plpd.orderingmethod in (1, 2)
                   group  by plpd.product_id, plpd.sizedefinition_id, plpd.finishingmethod_id,
                             p.typeofmerchandise, plpd.orderingmethod) y
          where  not exists (select 1
                  from   internetorderline il
                  where  il.internetorder_id = gv_ioh_id
                  and    il.product_link_id = y.product_id
                  and    il.sizedefinition_link_id = y.sizedefinition_id
                  and    il.finishingmethod_id = y.finishingmethod_id);
        --count lines
        if sql%rowcount = 0 then
          begin
            --remove internet order, because there are no lines
            gv_message := 'remove internet order with no lines gv_ioh_id ' || gv_ioh_id;
            delete internetorder io
            where  io.internetorder_id = gv_ioh_id
            and    not exists (select 1
                    from   internetorderline iol
                    where  iol.internetorder_id = io.internetorder_id);
          end;
        end if;
      end;
    end loop; --x
  end generate_orders;

  procedure finalize is
  begin
    --finalize
    gv_message := 'finalize';
    commit;
  end finalize;
begin
  --initialize
  initialize;
  --generate_orders
  generate_orders;
  --finalize
  finalize;
exception
  when no_data_found then
    begin
      rollback;
      write_log('No data found!' || gv_message, 3);
    end;
  when others then
    begin
      rollback;
      write_log(gv_message || ' ' || sqlerrm, 3);
    end;
end generateinternetorders;
/
create or replace procedure generateusagetargets(fp_customer_id in number,
                                                 fp_budgetunit_id in number,
                                                 fp_targetstartdate in date,
                                                 fp_adjustmentpercentage in number,
                                                 fp_periodtype in number,
                                                 fp_start_year in number,
                                                 fp_end_year in number,
                                                 fp_start_month in number,
                                                 fp_end_month in number,
                                                 fp_systemuser_id in number,
                                                 fp_abslogprocessjobid in abslogprocessjob.abslogprocessjob_id%type) is
gv_abslogprocessjobpartid abslogprocessjobpart.abslogprocessjobpart_id%type;
gv_nr_of_months          number;
gv_row_count             number;
gv_start_date            date;
gv_end_date              date;
gv_adjustmentfactor      number;
gv_dept_nr_of_months     number;
gv_dept_total_occupation number;

  cursor department_cursor is
  select d.department_id, d.departmentnumber
    from department d
   where d.customer_id = fp_customer_id
   order by d.departmentnumber;

gv_department_row        department_cursor%rowtype;


begin  -- MAIN
   gv_abslogprocessjobpartid := abslogwrite.abslogprocessjobpart_write(fp_abslogprocessjobid,'Generate Usage targets',fp_systemuser_id);
   abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 1, 'Started', fp_systemuser_id);

   -- Log Parameters
   abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 5, 'Param customer_id: ' || fp_customer_id , fp_systemuser_id);
   abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 5, 'Param budgetunit_id: ' || fp_budgetunit_id , fp_systemuser_id);
   abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 5, 'Param targetstartdate: ' || to_char(fp_targetstartdate,'yyyy-mm-dd') , fp_systemuser_id);
   abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 5, 'Param adjustmentpercentage: ' || fp_adjustmentpercentage , fp_systemuser_id);
   abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 5, 'Param periodtype: ' || fp_periodtype , fp_systemuser_id);
   abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 5, 'Param start_year: ' || fp_start_year , fp_systemuser_id);
   abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 5, 'Param start_month: ' || fp_start_month , fp_systemuser_id);
   abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 5, 'Param end_year: ' || fp_end_year , fp_systemuser_id);
   abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 5, 'Param end_month: ' || fp_end_month , fp_systemuser_id);

   -- calculate number of months/periods
   if fp_periodtype = 1 then -- calendar month
    gv_nr_of_months := (fp_end_year-fp_start_year)*12 - fp_start_month + fp_end_month + 1;
    gv_start_date := to_date(to_char(fp_start_year*10000+fp_start_month*100+1),'YYYYMMDD');
    gv_end_date := last_day(to_date(to_char(fp_end_year*10000+fp_end_month*100+1),'YYYYMMDD'));
   end if;
   if fp_periodtype = 2 then -- customer month definition
    gv_nr_of_months := (fp_end_year-fp_start_year)*12 - fp_start_month + fp_end_month + 1;
     select count(*)
       into gv_nr_of_months
       from customermonth cm
      where cm.customer_id = fp_customer_id and cm.year*100+cm.month between fp_start_year*100+fp_start_month and fp_end_year*100+fp_end_month;
     select cm.startdate
       into gv_start_date
       from customermonth cm
      where cm.customer_id = fp_customer_id and cm.year = fp_start_year and cm.month = fp_start_month;
     select cm.enddate
       into gv_end_date
       from customermonth cm
      where cm.customer_id = fp_customer_id and cm.year = fp_end_year and cm.month = fp_end_month;
   end if;
   if fp_periodtype = 3 then -- period
     select count(*)
       into gv_nr_of_months
       from period p
      where p.period_id between fp_start_year*100+fp_start_month and fp_end_year*100+fp_end_month;
     select p.startdate
       into gv_start_date
       from period p
      where p.year = fp_start_year and p.period = fp_start_month;
     select p.enddate
       into gv_end_date
       from period p
      where p.year = fp_end_year and p.period = fp_end_month;
   end if;

   -- calculate fp_adjustmentfactor
   gv_adjustmentfactor := 1 + (fp_adjustmentpercentage / 100);

   -- deleting rows with future startdate is needed to prevent overlapping rows
   delete
     from targetusageperbudgetunit t
    where t.department_link_id in (select d.department_id from department d where d.customer_id= fp_customer_id)
      and t.budgetunit_id = fp_budgetunit_id
      and t.startdate > fp_targetstartdate;
   gv_row_count := sql%rowcount;
   commit;
   if gv_row_count > 0 then
    abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 1, 'Deleted ' || gv_row_count || ' rows'  , fp_systemuser_id);
   end if;

   open department_cursor;

   loop
      fetch department_cursor into gv_department_row;
      exit when department_cursor%notfound;

      -- select total occupation for department in selected timeframe
      select count(*), sum(b.quantity)
        into gv_dept_nr_of_months,
             gv_dept_total_occupation
        from budget2 b
       where b.department_id = gv_department_row.department_id
         and b.year between fp_start_year and fp_end_year -- for performance
         and b.year * 100 + b.month between fp_start_year*100 + fp_start_month  and fp_end_year*100 + fp_end_month
         and b.budgetunit_id = fp_budgetunit_id;

      -- check if occupation is defined, and if so, for all months/periods in the timeframe.
      if gv_dept_nr_of_months = 0 or gv_dept_total_occupation = 0
        then
          abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 2, 'Department ' || gv_department_row.departmentnumber || ' skipped: no occupation defined in selected timeframe' , fp_systemuser_id);
        else
          if gv_dept_nr_of_months < gv_nr_of_months and gv_dept_total_occupation <> 0 then
            abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 2, 'Department ' || gv_department_row.departmentnumber || ' skipped: no occupation defined for all months/periods in selected timeframe' , fp_systemuser_id);
          end if;
      end if;

      if gv_dept_nr_of_months = gv_nr_of_months and gv_dept_total_occupation <> 0 then
        merge into targetusageperbudgetunit t
        using (
                select y.product_id,
                       y.sizedefinition_id,
                       y.finishingmethod_id,
                       round(y.total_pcs / gv_dept_total_occupation * gv_adjustmentfactor,2) targetusage
                 from
                    (select distinct plpd.product_id,
                                    plpd.sizedefinition_id,
                                    plpd.finishingmethod_id
                      from productlistperdistribpoint plpd,
                           standarddeliveryline       sdl,
                           standarddelivery           sd,
                           distributionpoint          dp
                     where plpd.productlistperdistribpoint_id = sdl.productlistperdistribpoint_id
                       and sdl.standarddelivery_id = sd.standarddelivery_id
                       and sdl.dateactive <= gv_end_date
                       and sdl.dateinactive >= gv_start_date
                       and dp.distributionpoint_id = sd.distributionpoint_id
                       and dp.department_id = gv_department_row.department_id) x,
                    (select dh.product_link_id product_id,
                           dh.sizedefinition_link_id sizedefinition_id,
                           dh.finishingmethod_id,
                           sum(dh.amountdelivered) total_pcs
                      from deliveryhistory dh
                     where dh.department_link_id = gv_department_row.department_id
                       and dh.deliverydate between gv_start_date and gv_end_date
                     group by dh.product_link_id,
                              dh.sizedefinition_link_id,
                              dh.finishingmethod_id) y
                    where x.product_id = y.product_id
                      and x.sizedefinition_id = y.sizedefinition_id
                      and x.finishingmethod_id = y.finishingmethod_id
              ) merge_subquery
         on (t.DEPARTMENT_LINK_ID = gv_department_row.department_id AND
             t.PRODUCT_ID         = merge_subquery.product_id AND
             t.SIZEDEFINITION_ID  = merge_subquery.sizedefinition_id AND
             t.FINISHINGMETHOD_ID = merge_subquery.finishingmethod_id AND
             t.BUDGETUNIT_ID      = fp_budgetunit_id AND
             t.STARTDATE          = fp_targetstartdate)
        when matched then
          update
             set targetusage = merge_subquery.targetusage,
                 systemuser_id = fp_systemuser_id,
                 timestamp  = sysdate
        when not matched then
          insert
            (targetusageperbudgetunit_id,
             department_link_id,
             product_id,
             sizedefinition_id,
             finishingmethod_id,
             budgetunit_id,
             startdate,
             targetusage,
             systemuser_id,
             timestamp,
             enddate,
             webuser_id)
          values
            (seq_targetusageperbudgetunit.nextval,
             gv_department_row.department_id,
             merge_subquery.product_id,
             merge_subquery.sizedefinition_id,
             merge_subquery.finishingmethod_id,
             fp_budgetunit_id,
             fp_targetstartdate,
             merge_subquery.targetusage,
             fp_systemuser_id,
             sysdate,
             to_date('20991231','yyyymmdd'),
             null);
        gv_row_count := sql%rowcount;

        -- update enddate of existing rows with older startdate to new startdate -1
        update targetusageperbudgetunit tbu
           set tbu.enddate = (select min(x.startdate)
                                from targetusageperbudgetunit x
                               where x.department_link_id = tbu.department_link_id
                                 and x.product_id = tbu.product_id
                                 and x.sizedefinition_id = tbu.sizedefinition_id
                                 and x.finishingmethod_id = tbu.finishingmethod_id
                                 and x.budgetunit_id = tbu.budgetunit_id
                                 and x.startdate between tbu.startdate and
                                     tbu.enddate
                                 and x.targetusageperbudgetunit_id <>
                                     tbu.targetusageperbudgetunit_id) - 1,
               tbu.systemuser_id = fp_systemuser_id,
               tbu.timestamp = sysdate
         where tbu.department_link_id = gv_department_row.department_id
           and tbu.targetusageperbudgetunit_id in
               (select t.targetusageperbudgetunit_id
                  from targetusageperbudgetunit t
                 where exists (select 1
                          from targetusageperbudgetunit q
                         where q.department_link_id = t.department_link_id
                           and q.product_id = t.product_id
                           and q.sizedefinition_id = t.sizedefinition_id
                           and q.finishingmethod_id = t.finishingmethod_id
                           and q.budgetunit_id = t.budgetunit_id
                           and q.startdate between t.startdate and t.enddate
                           and q.targetusageperbudgetunit_id <>
                               t.targetusageperbudgetunit_id));

        abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 1, 'Department ' || gv_department_row.departmentnumber || ' rows: ' || gv_row_count , fp_systemuser_id);
        commit;
      end if; -- gv_dept_nr_of_months = gv_nr_of_months and gv_dept_total_occupation <> 0

   end loop;

   close department_cursor;
   abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 1, 'Finished Successfully', fp_systemuser_id);

exception
  when others then
    begin
      rollback;
      abslogwrite.abslogprocessjobline_write(gv_abslogprocessjobpartid, 3, substr(sqlerrm, 1, 200), fp_systemuser_id);
    end;
end;
/
create or replace procedure generate_weighing_tickets(fp_plantid                in number,
                                                      fp_abslogprocessjobpartid in number,
                                                      fp_systemuserid           in number default 0) is
  --procedure generate_weighing_tickets version 0.3
  gv_user_exception exception;
  gv_message        varchar2(1000);
  gv_log_message    varchar2(1000);
  gv_debug_level    varchar2(100);
  gv_plantcode      plant.code%type;
  gv_plantname      plant.name%type;
  gv_statusid       status.status_id%type;

  --internal procedures
  ------
  procedure write_log(fp_message in abslog.message%type, fp_priority in abslog.priority%type) is
  begin
    if fp_abslogprocessjobpartid is null then
      begin
        --write_log
        abslogwrite.abslog_write(5, 'generate_weighing_tickets', fp_plantid, fp_priority,
                                 fp_message, nvl(fp_systemuserid, 0));
      end;
    else
      begin
        abslogwrite.abslogprocessjobline_write(fp_abslogprocessjobpartid, fp_priority, fp_message,
                                               nvl(fp_systemuserid, 0));
      end;
    end if;
    begin
      dbms_output.put_line(fp_message);
    exception
      when others then
        null; --ok no output to screen
    end;
  end write_log;

  procedure initialize is
  begin
    --initialize
    --check fp_plantid parameter
    if fp_plantid is null then
      begin
        gv_message := 'Parameter fp_plantid cannot be left blank!';
        raise gv_user_exception;
      end;
    end if;
    gv_message := 'plant id ' || fp_plantid;
    select pt.code, pt.name
    into   gv_plantcode, gv_plantname
    from   plant pt
    where  pt.plant_id = fp_plantid;
    --get debug level
    select max(st.value)
    into   gv_debug_level
    from   systemsetting st
    where  st.name = 'DEBUG_LEVEL'
    and    st.plant_id = fp_plantid;
    --get status
    gv_message := 'status type WN code 30';
    select st.status_id
    into   gv_statusid
    from   status st
    where  st.code = '30'
    and    st.statustype = 'WN';
    --
    write_log('Start processing weighing transactions for plant  ' || gv_plantcode || ' ' ||
              gv_plantname, 1);
  end initialize;

  procedure process_weighing_transactions_bu(fp_businessunitid in number) is
    lv_prev_weighingdate        weighingtransaction.weighingdate%type := trunc(sysdate + 999);
    lv_prev_customer_link_id    weighingtransaction.customer_link_id%type := -1;
    lv_prev_creationworkstation weighingtransaction.creationworkstation%type := 'NULL';
    lv_prev_lastindate          weighingtransaction.lastindate%type := trunc(sysdate + 999);
    lv_prev_lastinroute_id      weighingtransaction.lastinroute_id%type := -1;
    lv_prev_deliverydate        weighingtransaction.deliverydate%type := trunc(sysdate + 999);
    lv_invoicebusinessunitid    number;
    lv_processbusinessunitid    number;
    lv_weighingticketid         weighingticket.weighingticket_id%type;
    lv_weigh_sequencenumber     number;
    lv_referenceweighingsoil    weighingcategpercustomer.referenceweighingsoil%type;
    lv_weighingticketlineid     weighingticketline.weighingticketline_id%type;
    lv_min_distributionpointid  distributionpoint.distributionpoint_id%type;
    lv_ticketnumber             number;
    lv_customernumber           number;
    lv_departmentnumber         number;
    lv_weighingcatcode          weighingcategory.code%type;
    lv_workstationid            number;

    procedure marking_weighingtransactions is
    begin
      --marking_weighingtransactions
      gv_message := 'marking weighingtransactions for businessunit id ' ||
                    to_char(fp_businessunitid);
      update weighingtransaction wt
      set    wt.transferstatus = fp_businessunitid * -1, wt.timestamp = sysdate,
             wt.systemuser_id = nvl(fp_systemuserid, 0)
      where  wt.transferstatus = 0
      and    wt.businessunit_id = fp_businessunitid
      and    wt.cancellationtimestamp is null --do not pick up cancelled weighingtransaction
      and    wt.creationtimestamp <= (sysdate - (1 / 48)); --only when it exists for at least 30 min.
      --commit because we want to "lock" the records
      commit;
    end marking_weighingtransactions;

    procedure create_weighingticket(rec_wt in weighingtransaction%rowtype) is
      lv_internalprocessingbuid number;
      lv_processbucode          businessunit.code%type;
      lv_customername           customer.name%type;

      procedure get_customer_info is
      begin
        --reset data, so no old data is being used
        lv_invoicebusinessunitid   := null;
        lv_processbusinessunitid   := null;
        lv_internalprocessingbuid  := null;
        lv_processbucode           := null;
        lv_customernumber          := null;
        lv_customername            := null;
        lv_weighingcatcode         := null;
        lv_referenceweighingsoil   := null;
        lv_min_distributionpointid := null;
        lv_departmentnumber        := null;
        lv_workstationid           := null;
        --get_customer_info
        gv_message := 'get (weighing) info for customer id ' || to_char(rec_wt.customer_link_id);
        select ca.invoicebusinessunit_id, ca.processbusinessunit_id, ca.internalprocessingbu_id,
               bu.code, c.customernumber, c.name, wcc.referenceweighingsoil,
               wc.code weighingcategory,
               (select min(dp.distributionpoint_id)
                 from   distributionpoint dp
                 where  dp.department_id = rec_wt.department_link_id
                 and    dp.active = 'Y') min_distributionpointid,
               (select t.departmentnumber
                 from   department t
                 where  t.department_id = rec_wt.department_link_id) departmentnumber,
               (select wo.workstation_id
                 from   workstation wo
                 where  wo.code = rec_wt.creationworkstation) workstation_id
        into   lv_invoicebusinessunitid, lv_processbusinessunitid, lv_internalprocessingbuid,
               lv_processbucode, lv_customernumber, lv_customername, lv_referenceweighingsoil,
               lv_weighingcatcode, lv_min_distributionpointid, lv_departmentnumber, lv_workstationid
        from   weighingcategory wc
        join   customeractivities ca
        on     ca.activity_id = wc.activity_id
        join   weighingcategpercustomer wcc
        on     wcc.weighingcategory_id = wc.weighingcategory_id
        and    wcc.customer_id = ca.customer_id
        and    rec_wt.weighingdate between wcc.dateactive and wcc.dateinactive
        join   businessunit bu
        on     bu.businessunit_id = ca.processbusinessunit_id
        join   customer c
        on     c.customer_id = ca.customer_id
        where  wc.weighingcategory_id = rec_wt.weighingcategory_link_id
        and    ca.customer_id = rec_wt.customer_link_id
        and    ((ca.processbusinessunit_id = rec_wt.businessunit_id or
              ca.internalprocessingbu_id = rec_wt.businessunit_id) or
              (ca.allowallinternalbu = 'Y' and exists
               (select 1
                  from   internalbuactivities bua
                  where  bua.businessunit_id = ca.processbusinessunit_id
                  and    bua.activity_id = ca.activity_id
                  and    bua.internalprocessingbu_id = rec_wt.businessunit_id)))
        and    rownum = 1;
      end get_customer_info;

      procedure f_getnew_weighingticket is
      begin
        --f_getnew_WEIGHINGTICKET
        gv_message := 'Get seq_weighingticket_' || lower(lv_processbucode);
        execute immediate 'select seq_weighingticket_' || lv_processbucode || '.nextval from dual'
          into lv_ticketnumber;
        --get sequence
        lv_weighingticketid := seq_weighingticket.nextval;
      end f_getnew_weighingticket;
    begin
      --create_weighingticket
      --get_customer_info
      get_customer_info;
      --f_getnew_weighingticket
      f_getnew_weighingticket;
      --create weighing ticket
      gv_message := 'Creation of Weighing Ticket';
      insert into weighingticket
        (weighingticket_id, soilticket, ticketnumber, customer_id, weighingdate, status_id,
         employee_id, processbusinessunit_id, invoicebusinessunit_id, systemuser_id, timestamp,
         origin, correctednotenumber, daynumber, remark, deliverydate, weighingyear, weighingweek,
         consignmentnote_id, lastindate, lastinroute_id, creationsystemuser_id, creationtimestamp,
         processedsystemuser_id, processedtimestamp, internalprocessingbu_id, pdfarchived,
         cancelsystemuser_id, canceltimestamp, creationworkstation_id)
      values
        (lv_weighingticketid, 'Y', lv_ticketnumber, rec_wt.customer_link_id, rec_wt.weighingdate,
         gv_statusid, null, lv_processbusinessunitid, lv_invoicebusinessunitid,
         nvl(fp_systemuserid, 0), sysdate, 1, 0, getabsdaynumber(rec_wt.weighingdate), null,
         rec_wt.deliverydate, getyearofweek(rec_wt.weighingdate), getisoweek(rec_wt.weighingdate),
         null, rec_wt.lastindate, rec_wt.lastinroute_id, nvl(fp_systemuserid, 0), sysdate,
         nvl(fp_systemuserid, 0), sysdate, lv_internalprocessingbuid, 'N', null, null,
         lv_workstationid);
      --write log
      gv_log_message := 'Weighing Ticket ' || to_char(lv_ticketnumber) || ' created for ' ||
                        to_char(lv_customernumber) || ', ' || lv_customername || ' and date ' ||
                        to_char(rec_wt.weighingdate, 'dd-mm-yyyy');
    end create_weighingticket;

    procedure create_weighingticketline(rec_wt in weighingtransaction%rowtype) is
    begin
      --increase sequence
      lv_weigh_sequencenumber := lv_weigh_sequencenumber + 1;
      --create_weighingticketline
      gv_message := 'Creation of Weighing Ticket Line, sequencenumber ' ||
                    to_char(lv_weigh_sequencenumber);
      --write into weighingticketline
      insert into weighingticketline
        (weighingticketline_id, weighingticket_id, sequencenumber, containertype_id, department_id,
         weighingcategory_id, tareweight, grossweight, systemuser_id, timestamp, soilportion,
         weightdecimals, weighingsequencenr, weighingtimestamp, container_id, distributionpoint_id,
         invoiceheader_id, internalcalcprice, fixedinternalcalcprice, weightbaseddelhistory_id,
         referenceweighing)
      values
        (seq_weighingticketline.nextval, lv_weighingticketid, lv_weigh_sequencenumber,
         rec_wt.containertype_id, rec_wt.department_link_id, rec_wt.weighingcategory_link_id,
         rec_wt.tareweight, rec_wt.grossweight, nvl(fp_systemuserid, 0), sysdate, 0,
         rec_wt.weightdecimals, rec_wt.weighingsequencenr, rec_wt.creationtimestamp,
         rec_wt.container_id, rec_wt.distributionpoint_link_id, null, 0, 'N', null,
         lv_referenceweighingsoil)
      returning weighingticketline_id into lv_weighingticketlineid;
      if gv_debug_level = '6' then
        begin
          --write to log when debug level is 6
          write_log('Weighing Ticket Line# ' || to_char(lv_weigh_sequencenumber) ||
                    ' inserted for Ticket ' || to_char(lv_ticketnumber) || ' customer ' ||
                    to_char(lv_customernumber) || ' department ' || to_char(lv_departmentnumber) ||
                    ' and weighing category ' || lv_weighingcatcode, 1);
        end;
      end if;
    end create_weighingticketline;

    procedure create_weighinghistory(rec_wt in weighingtransaction%rowtype) is
    begin
      --insert weighinghistory
      gv_message := 'insert weighinghistory';
      insert into weighinghistory
        (weighinghistory_id, customer_link_id, department_link_id, distributionpoint_link_id,
         weighingcategory_link_id, weighingdate, year, week, daynumber, soilweight, cleanweight,
         processbusinessunit_id, invoicebusinessunit_id, systemuser_id, timestamp)
      values
        (seq_weighinghistory.nextval, rec_wt.customer_link_id, rec_wt.department_link_id,
         nvl(rec_wt.distributionpoint_link_id, lv_min_distributionpointid),
         rec_wt.weighingcategory_link_id, rec_wt.weighingdate, getyearofweek(rec_wt.weighingdate),
         getisoweek(rec_wt.weighingdate), getabsdaynumber(rec_wt.weighingdate),
         (rec_wt.grossweight - rec_wt.tareweight), 0, lv_processbusinessunitid,
         lv_invoicebusinessunitid, nvl(fp_systemuserid, 0), sysdate);
    exception
      when dup_val_on_index then
        begin
          --update weighinghistory
          gv_message := 'update weighinghistory';
          update weighinghistory wh
          set    wh.soilweight = wh.soilweight + (rec_wt.grossweight - rec_wt.tareweight)
          where  wh.customer_link_id = rec_wt.customer_link_id
          and    wh.department_link_id = rec_wt.department_link_id
          and    wh.distributionpoint_link_id =
                 nvl(rec_wt.distributionpoint_link_id, lv_min_distributionpointid)
          and    wh.weighingcategory_link_id = rec_wt.weighingcategory_link_id
          and    wh.weighingdate = rec_wt.weighingdate
          and    wh.processbusinessunit_id = lv_processbusinessunitid;
        end;
    end create_weighinghistory;

    procedure update_weighingtransactions(rec_wt in weighingtransaction%rowtype) is
    begin
      --update_weighingtransactions
      gv_message := 'update weighingtransactions';
      update weighingtransaction wt
      set    wt.transferstatus = 1, wt.weighingticketline_id = lv_weighingticketlineid,
             wt.timestamp = sysdate, wt.systemuser_id = nvl(fp_systemuserid, 0)
      where  wt.weighingtransaction_id = rec_wt.weighingtransaction_id;
    end update_weighingtransactions;
  begin
    --process_weighing_transactions_bu
    gv_message := 'process weighing_transactions for businessunit id ' ||
                  to_char(fp_businessunitid);
    --marking_weighingtransactions
    marking_weighingtransactions;
    --loop marked weighingtransaction
    for x in (select wt.*
              from   weighingtransaction wt
              where  wt.transferstatus = fp_businessunitid * -1
              and    wt.businessunit_id = fp_businessunitid
              order  by wt.weighingdate, wt.customer_link_id, wt.creationworkstation, wt.lastindate,
                        wt.lastinroute_id, wt.deliverydate) loop
      begin
        if (lv_prev_weighingdate <> x.weighingdate or
           lv_prev_customer_link_id <> x.customer_link_id or
           nvl(lv_prev_creationworkstation, 'NULL') <> nvl(x.creationworkstation, 'NULL') or
           nvl(lv_prev_lastindate, trunc(sysdate + 999)) <>
           nvl(x.lastindate, trunc(sysdate + 999)) or
           nvl(lv_prev_lastinroute_id, -1) <> nvl(x.lastinroute_id, -1) or
           nvl(lv_prev_deliverydate, trunc(sysdate + 999)) <>
           nvl(x.deliverydate, trunc(sysdate + 999))) then
          begin
            --store the data all went ok
            commit;
            write_log(gv_log_message, 1);
            gv_log_message := null;
            --create_weighingticket
            create_weighingticket(x);
            lv_weigh_sequencenumber := 0;
          end;
        end if;
        --create_weighingticketline
        create_weighingticketline(x);
        --create weighinghistory
        create_weighinghistory(x);
        --update_weighingtransactions
        update_weighingtransactions(x);
        --set previous record info into the variables
        lv_prev_weighingdate        := x.weighingdate;
        lv_prev_customer_link_id    := x.customer_link_id;
        lv_prev_creationworkstation := x.creationworkstation;
        lv_prev_lastindate          := x.lastindate;
        lv_prev_lastinroute_id      := x.lastinroute_id;
        lv_prev_deliverydate        := x.deliverydate;
      exception
        when gv_user_exception then
          begin
            rollback;
            write_log(gv_message, 3);
            gv_log_message := null;
          end;
        when no_data_found then
          begin
            rollback;
            write_log(gv_message || ' no data found', 3);
            gv_log_message := null;
          end;
        when others then
          begin
            rollback;
            if lv_customernumber is not null then
              begin
                write_log('Creation of weighingticket for customer ' || to_char(lv_customernumber) ||
                          ' department ' || to_char(lv_departmentnumber) ||
                          ' and weighing category ' || lv_weighingcatcode || ' failed. During ' ||
                          gv_message || ' ' || sqlerrm, 3);
              end;
            else
              begin
                write_log('Error in process. During ' || gv_message || ' ' || sqlerrm, 3);
              end;
            end if;
            gv_log_message := null;
          end;
      end;
    end loop; --x
    if gv_log_message is not null then
      begin
        --write log create weighing ticket
        write_log(gv_log_message, 1);
      end;
    end if;
  end process_weighing_transactions_bu;

  procedure finalize is
  begin
    --finalize
    commit;
    --write log
    write_log('End processing weighing transactions for plant ' || gv_plantcode || ' ' ||
              gv_plantname, 1);
  end finalize;
begin
  --initialize
  initialize;
  for x in (select bu.businessunit_id from businessunit bu where bu.plant_id = fp_plantid) loop
    begin
      --process weighing transactions per bu
      process_weighing_transactions_bu(x.businessunit_id);
    end;
  end loop; --x
  --finalize
  finalize;
exception
  when gv_user_exception then
    begin
      rollback;
      write_log(gv_message, 3);
    end;
  when no_data_found then
    begin
      rollback;
      write_log(gv_message || ' no data found', 3);
    end;
  when others then
    begin
      rollback;
      write_log('Error others during ' || gv_message || ' ' || sqlerrm, 3);
    end;
end generate_weighing_tickets;
/
create or replace procedure GETCONSTRAINTSSCRIPT (FPenable varchar2) is
	noString varchar2(2):='no';
begin
	dbms_output.enable(1000000);
	if (FPenable = 'Y' or FPenable = 'y') then noString:=''; end if;
	for c in (select table_name from user_tables) loop
		dbms_output.put_line('alter table '||c.table_name||' '||noString||'check constraint all;');
	end loop;
end;
/
create or replace procedure GetDefaultSupplierPurchaseInfo(p_Stockroom_ID      in stockroom.stockroom_id%type,
                                                           p_Product_Id        in product.product_id%type,
                                                           p_SizeDefinition_ID in Sizedefinition.Sizedefinition_Id%type,
                                                           p_Date              in date,
                                                           p_Supplier_ID       out supplier.supplier_id%type,
                                                           P_Currency_ID       out currency.currency_id%type,
                                                           P_PurchasePrice     out number) is

  procedure get_info as
  begin
    select su.currency_id
      into P_Currency_ID
      from supplier su
     where su.supplier_id = p_Supplier_ID;

    P_PurchasePrice := f_purchaseprice(p_Supplier_ID,
                                       p_Product_Id,
                                       p_SizeDefinition_ID,
                                       p_Date);
  end get_info;

  procedure get_ProductSupplierInfo as
  begin
    select pr.supplier_id
      into p_Supplier_ID
      from product pr
     where pr.product_id = p_Product_Id;

    if (p_Supplier_ID is not null and p_Supplier_ID > 0) then
      get_info;
    end if;
  end get_ProductSupplierInfo;

begin
  P_Supplier_ID := -1;
  P_Currency_ID := -1;
  P_PurchasePrice := 0.0;

  if (p_Stockroom_ID is not null and p_Stockroom_ID > 0) then
    begin
      select min(sdi.defaultsupplier_id)
        into p_Supplier_ID
        from stockdefinitionperitem sdi
       where sdi.stockroom_id = p_Stockroom_ID
         and sdi.product_id = p_Product_Id
         and sdi.sizedefinition_id = p_SizeDefinition_ID
         and sdi.customer_id is null
         and sdi.customerowned = 'N';

      if (p_Supplier_ID is not null and p_Supplier_ID > 0) then
        get_info;
        if (P_PurchasePrice <= 0) then
          get_ProductSupplierInfo;
        end if;
      else
        get_ProductSupplierInfo;
      end if;
    end;
  else
    get_ProductSupplierInfo;
  end if;

end GetDefaultSupplierPurchaseInfo;
/
create or replace procedure GetFIFOPurchaseInfoViaWO(p_Stockroom_ID         in stockroom.stockroom_id%type,
                                                     P_PreviousWorkOrder_ID in workorder.workorder_id%type,
                                                     p_Product_Id           in product.product_id%type,
                                                     p_SizeDefinition_ID    in Sizedefinition.Sizedefinition_Id%type,
                                                     P_QualityGrade_ID      in qualitygrade.qualitygrade_id%type,
                                                     P_Preferred_PurchOrderLine_ID      in purchaseorderline.purchaseorderline_id%type,
                                                     p_Date                 in date,
                                                     p_Supplier_ID          out supplier.supplier_id%type,
                                                     P_Currency_ID          out currency.currency_id%type,
                                                     P_PurchasePrice        out number,
                                                     P_PurchaseOrderLine_ID out purchaseorderline.purchaseorderline_id%type) is
  qg_found                   number;
  wo_processingstockroom_id  stockroom.stockroom_id%type;
  wo_workordernumber         workorder.workordernumber%type;
  svf_purchaseordernumber    purchaseorderheader.purchaseordernumber%type;
  poh_purchaseorderheader_id purchaseorderheader.purchaseorderheader_id%type;

begin
  P_Supplier_ID := -1;
  P_Currency_ID := -1;
  P_PurchasePrice := 0.0;
  P_PurchaseOrderLine_ID := -1;

  if (P_PreviousWorkOrder_ID is not null and P_PreviousWorkOrder_ID > 0) then
    select wo.processingstockroom_id, wo.workordernumber
      into wo_processingstockroom_id, wo_workordernumber
      from workorder wo
     where wo.workorder_id = P_PreviousWorkOrder_ID;

    select count(qg.qualitygrade_id)
      into qg_found
      from qualitygrade qg
     where qg.newgarment = 'Y'
       and qg.stockvaluationmethod = 1
       and qg.qualitygrade_id = P_QualityGrade_ID;

    if (qg_found > 0) then
      begin
        select svf.piecevalue, svf.purchaseordernumber
          into P_PurchasePrice, svf_purchaseordernumber
          from stockvaluefifo           svf,
               stockreservationpergrade srg,
               stockdefinitionperitem   sdi
         where svf.workordernumber = wo_workordernumber
           and svf.transactiontype = 2
           and svf.origin = 1
           and svf.stockreservationpergrade_id =
               srg.stockreservationpergrade_id
           and srg.qualitygrade_id = P_QualityGrade_ID
           and sdi.stockdefinitionperitem_id =
               srg.stockdefinitionperitem_id
           and sdi.stockroom_id = wo_processingstockroom_id
           and sdi.product_id = p_Product_Id
           and sdi.sizedefinition_id = p_SizeDefinition_ID
           and sdi.customer_id is null
           and sdi.customerowned = 'N'
           and  svf.purchaseordernumber =
             case when P_Preferred_PurchOrderLine_ID <= 0 then svf.purchaseordernumber
               else ( select poh.purchaseordernumber from purchaseorderline pol join purchaseorderheader poh on poh.purchaseorderheader_id = pol.purchaseorderheader_id
                 where pol.purchaseorderline_id = P_Preferred_PurchOrderLine_ID
                 )
              end;

        begin
          select poh.supplier_id,
                 poh.currency_id,
                 poh.purchaseorderheader_id
            into p_Supplier_ID, P_Currency_ID, poh_purchaseorderheader_id
            from purchaseorderheader poh
           where poh.purchaseordernumber = svf_purchaseordernumber;

          select pol.purchaseprice, pol.purchaseorderline_id
            into P_PurchasePrice, P_PurchaseOrderLine_ID
            from purchaseorderline pol
           where pol.purchaseorderheader_id = poh_purchaseorderheader_id
             and pol.product_link_id = p_Product_Id
             and pol.sizedefinition_link_id = p_SizeDefinition_ID;

        exception
          when no_data_found then
            begin
              P_PurchaseOrderLine_ID := null;
            end;
        end;

      exception
        when no_data_found then
          begin
            getdefaultsupplierpurchaseinfo(wo_processingstockroom_id,
                                           p_Product_Id,
                                           p_SizeDefinition_ID,
                                           p_Date,
                                           p_Supplier_ID,
                                           P_Currency_ID,
                                           P_PurchasePrice);
          end;
      end;

    else
      getdefaultsupplierpurchaseinfo(wo_processingstockroom_id,
                                     p_Product_Id,
                                     p_SizeDefinition_ID,
                                     p_Date,
                                     p_Supplier_ID,
                                     P_Currency_ID,
                                     P_PurchasePrice);
    end if;

  else
    getdefaultsupplierpurchaseinfo(p_Stockroom_ID,
                                   p_Product_Id,
                                   p_SizeDefinition_ID,
                                   p_Date,
                                   p_Supplier_ID,
                                   P_Currency_ID,
                                   P_PurchasePrice);
  end if;

end GetFIFOPurchaseInfoViaWO;
/
create or replace procedure getgarmentdata(idcode                 in uniqueitem.primaryid%type,
                                           plantcode              in plant.code%type,
                                           unitcode               out nocopy businessunit.code%type,
                                           status                 out nocopy integer,
                                           finishselection        out nocopy varchar2, --(6),
                                           checkpointselection    out nocopy varchar2, --(6),
                                           repairselection        out nocopy varchar2, --(6),
                                           destination            out nocopy varchar2, --(6),
                                           foldprogram            out nocopy varchar2, --(6),
                                           stackchangeinfo        out nocopy varchar2, --(60),
                                           routenumber            out nocopy route.routenumber%type,
                                           routeday               out nocopy route.drivingday_id%type,
                                           depot                  out nocopy depot.code%type,
                                           sortstring             out nocopy varchar2,
                                           alternatesortstring    out nocopy varchar2,
                                           stopnumber             out nocopy routestop.stopnumber%type,
                                           customernumber         out nocopy customer.customernumber%type,
                                           customername           out nocopy customer.name%type,
                                           wearernumber           out nocopy wearer.wearernumber%type,
                                           wearername             out nocopy wearer.searchname%type,
                                           banklocker             out nocopy varchar2,
                                           department             out nocopy department.departmentnumber%type,
                                           customeremployeenumber out nocopy wearer.customeremployeenumber%type,
                                           gender                 out nocopy wearer.sex%type,
                                           garmentdispensercode   out nocopy garmentdispenser.code%type,
                                           deliverypointcode      out nocopy deliverypoint.code%type,
                                           productcode            out nocopy product.code%type,
                                           productdescription     out nocopy product_desc.description%type,
                                           sizecode               out nocopy sizedefinition.code%type,
                                           productpicturecode     out nocopy image.code%type,
                                           deliverydaymask        out nocopy varchar2,
                                           secondaryid            out nocopy secondaryuniqueitem.secondaryid%type,
                                           flagcode1              out nocopy sortaddressperflag.sortaddress%type,
                                           flagcode2              out nocopy sortaddressperflag.sortaddress%type,
                                           flagcode3              out nocopy sortaddressperflag.sortaddress%type,
                                           flagcode4              out nocopy sortaddressperflag.sortaddress%type,
                                           flagdescription1       out nocopy flag_desc.description%type,
                                           flagdescription2       out nocopy flag_desc.description%type,
                                           flagdescription3       out nocopy flag_desc.description%type,
                                           flagdescription4       out nocopy flag_desc.description%type,
                                           infotext               out nocopy wearer.remark%type,
                                           requiredrepairs        out nocopy varchar2,
                                           spare1                 out nocopy varchar2,
                                           spare2                 in out nocopy varchar2) is
  --procedure getgarmentdata version 2.0
  flagfreetext1    uniqueitemflag.freetextitem%type;
  flagfreetext2    uniqueitemflag.freetextitem%type;
  flagfreetext3    uniqueitemflag.freetextitem%type;
  flagfreetext4    uniqueitemflag.freetextitem%type;
  routecodeonlabel route.codeonlabel%type;
  noofwashes       integer;
  defbypasscheck   flag.code%type;

  procedure get_systemsettings is
  begin
    begin
      --get_systemsettings
      select s.value
      into   noofwashes
      from   systemsetting s
      where  s.name = 'NOOFWASHESNOCHECKPOINT'
      and    s.plant_id = (select p.plant_id from plant p where p.code = plantcode);
    exception
      when no_data_found then
        noofwashes := 0;
    end;
    begin
      select s.value
      into   defbypasscheck
      from   systemsetting s
      where  s.name = 'DEFBYPASSCHECKPOINTFLAG'
      and    s.plant_id = (select p.plant_id from plant p where p.code = plantcode);
    exception
      when no_data_found then
        defbypasscheck := '-';
    end;
  end get_systemsettings;

  procedure get_sortingdata is
    lv_databasecode databasesettings.code%type;
    lv_gdsort       garmentdispenser.sortaddress1%type;
    lv_customer_id  customer.customer_id%type;
  begin
    --get_sortingdata
    select max(d.code) into lv_databasecode from databasesettings d;
    if nvl(lv_databasecode, 'NULL') in ('RFL', 'ABS') and status = 0 then
      begin
        select customer_id
        into   lv_customer_id
        from   customer c
        where  c.customernumber = getgarmentdata.customernumber;
        --
        select coalesce(to_number(max(x.sortaddress)), getgarmentdata.customernumber)
        into   routenumber
        from   deliverypoint x
        where  x.code = trim(getgarmentdata.deliverypointcode)
        and    x.customer_id = lv_customer_id;
        --
        stopnumber := 1;
        routeday   := getabsdaynumber(trunc(sysdate));
        -- unsorted garmentdispenser
        lv_gdsort := '';
        if garmentdispensercode is not null then
          begin
            select max(sortaddress1)
            into   lv_gdsort
            from   garmentdispenser
            where  code = trim(garmentdispensercode)
            and    customer_id = lv_customer_id;
          end;
        end if;
        if lv_gdsort = '*' then
          -- sort only on garmentdispenser when SORTADDRESS1='0'
          sortstring      := lpad(stopnumber, 6, '0') || substr(sortstring, 7, 12) || ' ' ||
                             lpad(department, 6, '0') || garmentdispensercode;
          stackchangeinfo := sortstring;
        else
          sortstring      := lpad(stopnumber, 6, '0') || substr(sortstring, 7);
          stackchangeinfo := lpad(stopnumber, 6, '0') || substr(stackchangeinfo, 7);
        end if;
      end;
    end if;
  exception
    when no_data_found then
      begin
        status          := 1;
        routenumber     := null;
        sortstring      := null;
        stackchangeinfo := null;
      end;
  end get_sortingdata;

  procedure check_flags is
    fill_flags                  boolean; --used for determining when to fill flags; SO 20012728
    ui_washestotal              uniqueitem.washestotal%type;
    m_bypass_checkpoint_flag_id flag.flag_id%type;
    m_bypass_sortaddress        sortaddressperflag.sortaddress%type;
    plpc_noofwashesnocheckpoint productlistpercustomer.noofwashesnocheckpoint%type;
    product_noofwashes          product.noofwashesnocheckpoint%type;
    -- RVI 20150218, Begin
    lv_languageid             languages.language_id%type;
    m_bypass_flag_description flag_desc.description%type;
    -- RVI 20150218, End

    procedure return_flags is
    begin
      --return_flags
      if fill_flags then
        -- RVI 20150218, Begin
        begin
          if flagcode1 is null then
            begin
              flagcode1        := m_bypass_sortaddress;
              flagdescription1 := m_bypass_flag_description;
            end;
          else
            if flagcode2 is null then
              begin
                flagcode2        := m_bypass_sortaddress;
                flagdescription2 := m_bypass_flag_description;
              end;
            else
              if flagcode3 is null then
                begin
                  flagcode3        := m_bypass_sortaddress;
                  flagdescription3 := m_bypass_flag_description;
                end;
              else
                begin
                  flagcode4        := m_bypass_sortaddress;
                  flagdescription4 := m_bypass_flag_description;
                end;
              end if;
            end if;
          end if;
        end;
        -- RVI 20150218, End
      end if;
    end return_flags;
  begin
    --check_flags
    fill_flags := false;
    if (((flagcode1 is null) or (flagcode2 is null) or (flagcode3 is null) or (flagcode4 is null)) and
       (noofwashes > 0) and status = 0) then
      begin
        begin
          --ui.washestotal is not null
          select ui.washestotal into ui_washestotal from uniqueitem ui where ui.primaryid = idcode;
        exception
          when no_data_found then
            ui_washestotal := 0;
        end;
        begin
          select fl.flag_id
          into   m_bypass_checkpoint_flag_id
          from   flag fl
          where  fl.code = defbypasscheck
          and    fl.flagtype = 1;
        exception
          when no_data_found then
            m_bypass_checkpoint_flag_id := -1;
        end;
        -- RVI 20150218, Begin
        if (m_bypass_checkpoint_flag_id > 0) then
          begin
            begin
              select pt.language_id into lv_languageid from plant pt where pt.code = plantcode;
            exception
              when no_data_found then
                lv_languageid := 1;
            end;
            begin
              select fld.description
              into   m_bypass_flag_description
              from   flag_desc fld
              where  fld.flag_id = m_bypass_checkpoint_flag_id
              and    fld.language_id = lv_languageid;
            exception
              when no_data_found then
                m_bypass_flag_description := null;
            end;
          end;
        end if;
        -- RVI 20150218, End
        if (m_bypass_checkpoint_flag_id > 0 and ui_washestotal > 0) then
          begin
            select s.sortaddress
            into   m_bypass_sortaddress
            from   sortaddressperflag s
            where  s.flag_id = m_bypass_checkpoint_flag_id
            and    s.plant_id = (select p.plant_id from plant p where p.code = plantcode);
            -- RVI 20150209, Begin
            begin
              -- RVI 20150209, End
              select plpc.noofwashesnocheckpoint
              into   plpc_noofwashesnocheckpoint
              from   uniqueitem ui, uniqueitemnonpool up, weareremployment we, wearer w, customer cu,
                     productlistpercustomer plpc
              where  ui.uniqueitem_id = up.uniqueitem_id
              and    up.weareremployment_id = we.weareremployment_id
              and    we.wearer_id = w.wearer_id
              and    w.customer_id = cu.customer_id
              and    cu.customer_id = plpc.customer_id
              and    plpc.product_id = ui.product_id
                    -- RVI 20150209, Begin
              and    plpc.sizedefinition_id = ui.sizedefinition_id
              and    plpc.finishingmethod_id = ui.finishingmethod_id
              and    plpc.dateactive <= sysdate
              and    plpc.dateinactive > sysdate
                    -- RVI 20150209, End
              and    ui.primaryid = idcode;
            exception
              when no_data_found then
                plpc_noofwashesnocheckpoint := null;
                -- RVI 20150209, Begin
              when others then
                plpc_noofwashesnocheckpoint := null;
                -- RVI 20150209, End
            end;
            -- RVI 20150209, Begin
            if plpc_noofwashesnocheckpoint is null then
              begin
                select max(plpc.noofwashesnocheckpoint)
                into   plpc_noofwashesnocheckpoint
                from   uniqueitem ui, uniqueitemnonpool up, weareremployment we, wearer w,
                       customer cu, productlistpercustomer plpc
                where  ui.uniqueitem_id = up.uniqueitem_id
                and    up.weareremployment_id = we.weareremployment_id
                and    we.wearer_id = w.wearer_id
                and    w.customer_id = cu.customer_id
                and    cu.customer_id = plpc.customer_id
                and    plpc.product_id = ui.product_id
                and    plpc.sizedefinition_id =
                       (select sd.sizedefinition_id from sizedefinition sd where sd.code = '*')
                and    plpc.finishingmethod_id = ui.finishingmethod_id
                and    plpc.dateactive <= sysdate
                and    plpc.dateinactive > sysdate
                and    ui.primaryid = idcode;
              end;
            end if;
            -- RVI 20150209, End
            if plpc_noofwashesnocheckpoint is null then
              begin
                select max(p.noofwashesnocheckpoint)
                into   product_noofwashes
                from   uniqueitem ui, product p
                where  ui.product_id = p.product_id
                and    ui.primaryid = idcode;
              end;
              if product_noofwashes is null then
                fill_flags := (ui_washestotal <= noofwashes);
              else
                fill_flags := (ui_washestotal <= product_noofwashes);
              end if;
            else
              fill_flags := (ui_washestotal <= plpc_noofwashesnocheckpoint);
            end if;
            -- RVI 20150209, Begin
          end;
          -- RVI 20150209, End
          --return_flags
          return_flags;
        end if;
        --<20012728
      end;
    end if;
  exception
    when no_data_found then
      null; --no problem this data is not needed
  end check_flags;
begin
  getgarmentdatabasic(idcode, plantcode, unitcode, status, finishselection, checkpointselection,
                      repairselection, destination, foldprogram, stackchangeinfo, routenumber,
                      routeday, depot, sortstring, alternatesortstring, stopnumber, customernumber,
                      customername, wearernumber, wearername, banklocker, department,
                      customeremployeenumber, gender, garmentdispensercode, deliverypointcode,
                      productcode, productdescription, sizecode, productpicturecode, deliverydaymask,
                      secondaryid, flagcode1, flagcode2, flagcode3, flagcode4, flagdescription1,
                      flagdescription2, flagdescription3, flagdescription4, infotext,
                      requiredrepairs, spare1, spare2, flagfreetext1, flagfreetext2, flagfreetext3,
                      flagfreetext4, routecodeonlabel);
  --> 20012728
  get_systemsettings;
  --get_sortingdata
  get_sortingdata;
  --check_flags
  check_flags;
end getgarmentdata;
/
create or replace procedure getgarmentdataamt(idcode      in uniqueitem.primaryid%type,
                                              plantcode   in out plant.code%type,
                                              sortaddress out nocopy varchar2,
                                              makescan    out nocopy varchar2) is
  uniqueitemid      uniqueitem.uniqueitem_id%type;
  plantid_param     plant.plant_id%type;
  plantid_garment   plant.plant_id%type;
  returnedplantcode plant.code%type;
  pool              uniqueitem.poolitem%type;
  businessunitid    integer;
  uistatus          varchar2(2);
  sortaddressamt    varchar2(20);
  unitcode          varchar2(20);
  status            integer;
  productid         product.product_id%type;
  sizedefinitionid  sizedefinition.sizedefinition_id%type;
  specialsizeid     sizedefinition.sizedefinition_id%type;
  finishingmethodid finishingmethod.finishingmethod_id%type;
  specialfmethodid  finishingmethod.finishingmethod_id%type;
  customerid        customer.customer_id%type;
  plpcid            productlistpercustomer.productlistpercustomer_id%type;
  debuglevel        integer;
  allowrepairscan   integer;
  --Todo 6660
  idprimary   uniqueitem.primaryid%type; --is never used in this procedure
  secondaryid secondaryuniqueitem.secondaryid%type; --not used
  lv_dummy    varchar2(255);
begin
  makescan := 'Y';
  pack_sort.determinegarmentid('AMT', idcode, plantcode, uniqueitemid, pool, unitcode,
                               businessunitid, plantid_garment, returnedplantcode,
                               --not used for metric, but used for  AMT
                               status, idprimary, plantid_param, secondaryid);
  pack_sort.getsystemsettings(plantid_param, debuglevel, lv_dummy, allowrepairscan);
  if plantcode is null then
    plantcode := returnedplantcode;
  end if;
  begin
    ---------------------------------------------------------------
    --other fields
    if status = 0 then
      begin
        select s.code
        into   uistatus
        from   uniqueitem u, status s
        where  u.uniqueitem_id = uniqueitemid
        and    u.status_id = s.status_id;
        if uistatus in ('20', '30') then
          --flags
          for vcursor in (select distinct o.confirm, f.priority, b.startdate, f.showalways, f.flag_id
                          from   uniqueitemflag b, flag f, flagoptions o, dialogs d
                          where  b.uniqueitem_id = uniqueitemid
                          and    b.flag_id = f.flag_id
                          and    f.flag_id = o.flag_id
                          and    o.dialog_id = d.dialog_id
                          and    d.code = 'OutScan'
                          and    o.show = 'Y'
                          and    (f.priority = 1 or f.showalways = 'Y')
                          and    b.startdate <= sysdate
                          order  by o.confirm desc, f.priority asc, b.startdate asc) loop
            begin
              select s.sortaddress
              into   sortaddressamt
              from   sortaddressperflag s
              where  s.flag_id = vcursor.flag_id
              and    s.plant_id = plantid_param;
            exception
              when no_data_found then
                null;
            end;
            if sortaddressamt is not null then
              exit;
            end if;
            -- end;
          end loop;
          if sortaddressamt is null then
            begin
              select g.sortaddress1
              into   sortaddressamt
              from   uniqueitemnonpool u, weareremployment e, garmentdispenser g
              where  u.uniqueitem_id = uniqueitemid
              and    u.weareremployment_id = e.weareremployment_id
              and    e.garmentdispenser_id = g.garmentdispenser_id
              and    g.sortaddress1 is not null;
              -- Locker sorting (extra for LIPS Emmen)
            exception
              when no_data_found then
                begin
                  select l.sortaddress
                  into   sortaddressamt
                  from   uniqueitemnonpool u, weareremployment e, locker l
                  where  u.uniqueitem_id = uniqueitemid
                  and    u.weareremployment_id = e.weareremployment_id
                  and    l.locker_id = e.locker_id
                  and    l.sortaddress is not null;
                exception
                  when no_data_found then
                    begin
                      select d.sortaddress
                      into   sortaddressamt
                      from   uniqueitemnonpool u, weareremployment e, distributionpoint di,
                             department d
                      where  u.uniqueitem_id = uniqueitemid
                      and    u.weareremployment_id = e.weareremployment_id
                      and    e.distributionpoint_id = di.distributionpoint_id
                      and    di.department_id = d.department_id
                      and    d.sortaddress is not null;
                    exception
                      when no_data_found then
                        --order 501407
                        begin
                          select u.finishingmethod_id, u.sizedefinition_id, p.product_id
                          into   finishingmethodid, sizedefinitionid, productid
                          from   uniqueitem u, product p, sizedefinition s
                          where  u.uniqueitem_id = uniqueitemid
                          and    u.product_id = p.product_id
                          and    u.sizedefinition_id = s.sizedefinition_id;
                          if pool = 1 then
                            begin
                              select c.customer_id
                              into   customerid
                              from   uniqueitem u, customer c
                              where  u.uniqueitem_id = uniqueitemid
                              and    u.relatedcustomer_id = c.customer_id;
                            exception
                              when no_data_found then
                                begin
                                  select c.customer_id
                                  into   customerid
                                  from   uniqueitem u, distributionpoint d, department e, customer c
                                  where  u.uniqueitem_id = uniqueitemid
                                  and    u.distributionpoint_id = d.distributionpoint_id
                                  and    d.department_id = e.customer_id
                                  and    e.customer_id = c.customer_id;
                                end;
                            end;
                          elsif pool = 2 then
                            begin
                              select c.customer_id
                              into   customerid
                              from   uniqueitemnonpool n, customer c, department d, wearer w,
                                     weareremployment e, distributionpoint di
                              where  n.uniqueitem_id = uniqueitemid
                              and    n.weareremployment_id = e.weareremployment_id
                              and    e.wearer_id = w.wearer_id
                              and    w.customer_id = c.customer_id
                              and    e.distributionpoint_id = di.distributionpoint_id
                              and    di.department_id = d.department_id;
                            exception
                              when no_data_found then
                                customerid := null;
                            end;
                          end if;
                          --if customerid is not null then
                          -- Start part: Extra check on single size and finishingmethod
                          -- in PLPC definition, otherwise use size * dd 22-03-2012
                          plpcid := f_getidcolumnfromactiveplpc(customerid, productid,
                                                                sizedefinitionid, finishingmethodid,
                                                                null, sysdate, 0);
                          if plpcid is null then
                            begin
                              select f.finishingmethod_id
                              into   specialfmethodid
                              from   finishingmethod f
                              where  f.code = 'TELLEN';
                              plpcid := f_getidcolumnfromactiveplpc(customerid, productid,
                                                                    sizedefinitionid,
                                                                    specialfmethodid,
                                                                    sizedefinitionid, sysdate, 0);
                            end;
                          end if;
                          -- End part: Extra check on single size and finishingmethod
                          if plpcid is null then
                            begin
                              select s.sizedefinition_id
                              into   specialsizeid
                              from   sizedefinition s
                              where  s.code = '*';
                              plpcid := f_getidcolumnfromactiveplpc(customerid, productid,
                                                                    sizedefinitionid,
                                                                    finishingmethodid, specialsizeid,
                                                                    sysdate, 0);
                            end;
                          end if;
                          select sp.sortaddress
                          into   sortaddressamt
                          from   sortaddressperprodpercust sp
                          where  sp.productlistpercustomer_id = plpcid
                          and    sp.plant_id = plantid_param
                          and    sp.sortaddress is not null;
                        exception
                          when no_data_found then
                            begin
                              select sp.sortaddress
                              into   sortaddressamt
                              from   uniqueitem u, sortaddressperproduct sp
                              where  u.uniqueitem_id = uniqueitemid
                              and    u.product_id = sp.product_id
                              and    sp.plant_id = plantid_param
                              and    sp.sortaddress is not null;
                            exception
                              when no_data_found then
                                begin
                                  select sp.sortaddress
                                  into   sortaddressamt
                                  from   uniqueitem u, sortaddressperproductsize sp
                                  where  u.uniqueitem_id = uniqueitemid
                                  and    u.product_id = sp.product_id
                                  and    sp.plant_id = plantid_param
                                  and    u.sizedefinition_id = sp.sizedefinition_id
                                  and    sp.sortaddress is not null;
                                exception
                                  when others then
                                    sortaddressamt := null;
                                    makescan       := 'Y'; --todo5860 make Y instead of N
                                    if debuglevel > 0 then
                                      pack_sort.write_logging(' IDCode ' || idcode ||
                                                              ' SortAddress not found, MakeScan ' ||
                                                              makescan || ' Status ' || status,
                                                              debuglevel,
                                                              'GETGARMENTDATAKANNEGIESSER',
                                                              plantid_param, 3, 1);
                                    end if;
                                end;
                            end;
                        end;
                    end;
                end;
            end;
          else
            --order501350
            makescan := 'N';
          end if;
        end if;
      end;
    else
      makescan := 'N';
    end if; --status=0
    sortaddress := sortaddressamt;
    if debuglevel > 0 then
      pack_sort.write_logging(' IDCode ' || idcode || ' SortAddress ' || sortaddressamt ||
                              ' MakeScan ' || makescan || ' Status ' || status, debuglevel,
                              'GETGARMENTDATAKANNEGIESSER', plantid_param, 1, 1);
    end if;
  exception
    when others then
      begin
        sortaddress := null;
        makescan    := 'N';
        pack_sort.write_logging(' IDCode' || idcode || ' SortAddress ' || sortaddressamt ||
                                ' MakeScan ' || makescan || ' Status' || status || ' ' || sqlerrm,
                                debuglevel, 'GETGARMENTDATAKANNEGIESSER', plantid_param, 3, 1);
      end;
  end;
end getgarmentdataamt;
/
create or replace procedure getgarmentdatabasic(idcode                 in uniqueitem.primaryid%type,
                                                plantcode              in plant.code%type,
                                                unitcode               out nocopy businessunit.code%type,
                                                status                 out nocopy integer,
                                                finishselection        out nocopy varchar2, --(6),
                                                checkpointselection    out nocopy varchar2, --(6),
                                                repairselection        out nocopy varchar2, --(6),
                                                destination            out nocopy varchar2, --(6),
                                                foldprogram            out nocopy varchar2, --(6),
                                                stackchangeinfo        out nocopy varchar2, --(60),
                                                routenumber            out nocopy route.routenumber%type,
                                                routeday               out nocopy route.drivingday_id%type,
                                                depot                  out nocopy depot.code%type,
                                                sortstring             out nocopy varchar2,
                                                alternatesortstring    out nocopy varchar2,
                                                stopnumber             out nocopy routestop.stopnumber%type,
                                                customernumber         out nocopy customer.customernumber%type,
                                                customername           out nocopy customer.name%type,
                                                wearernumber           out nocopy wearer.wearernumber%type,
                                                wearername             out nocopy wearer.searchname%type,
                                                banklocker             out nocopy varchar2,
                                                department             out nocopy department.departmentnumber%type,
                                                customeremployeenumber out nocopy wearer.customeremployeenumber%type,
                                                gender                 out nocopy wearer.sex%type,
                                                garmentdispensercode   out nocopy garmentdispenser.code%type,
                                                deliverypointcode      out nocopy deliverypoint.code%type,
                                                productcode            out nocopy product.code%type,
                                                productdescription     out nocopy product_desc.description%type,
                                                sizecode               out nocopy sizedefinition.code%type,
                                                productpicturecode     out nocopy image.code%type,
                                                deliverydaymask        out nocopy varchar2,
                                                secondaryid            out nocopy secondaryuniqueitem.secondaryid%type,
                                                flagcode1              out nocopy sortaddressperflag.sortaddress%type,
                                                flagcode2              out nocopy sortaddressperflag.sortaddress%type,
                                                flagcode3              out nocopy sortaddressperflag.sortaddress%type,
                                                flagcode4              out nocopy sortaddressperflag.sortaddress%type,
                                                flagdescription1       out nocopy flag_desc.description%type,
                                                flagdescription2       out nocopy flag_desc.description%type,
                                                flagdescription3       out nocopy flag_desc.description%type,
                                                flagdescription4       out nocopy flag_desc.description%type,
                                                infotext               out nocopy wearer.remark%type,
                                                requiredrepairs        out nocopy varchar2,
                                                spare1                 out nocopy varchar2,
                                                spare2                 in out nocopy varchar2,
                                                flagfreetext1          out nocopy uniqueitemflag.freetextitem%type,
                                                flagfreetext2          out nocopy uniqueitemflag.freetextitem%type,
                                                flagfreetext3          out nocopy uniqueitemflag.freetextitem%type,
                                                flagfreetext4          out nocopy uniqueitemflag.freetextitem%type,
                                                fp_routecodeonlabel    out route.codeonlabel%type,
                                                metricon               in varchar2 default 'N',
                                                freetext2descriptionyn in varchar2 default 'Y') is
  --procedure getgarmentdatabasic version 1.7
  uniqueitemid        uniqueitem.uniqueitem_id%type;
  plantid_param       plant.plant_id%type;
  plantid_garment     plant.plant_id%type;
  languageid          languages.language_id%type;
  pool                uniqueitem.poolitem%type;
  imageid             image.image_id%type;
  customerid          customer.customer_id%type;
  finishingcodeid     finishingcode.finishingcode_id%type;
  serviceteamid       serviceteam.serviceteam_id%type;
  colorid             color.color_id%type;
  finishingmethodid   finishingmethod.finishingmethod_id%type;
  productid           product.product_id%type;
  packingsequence     product.packingsequence%type;
  routeid             route.route_id%type;
  businessunitid      integer;
  wearerflagid        flag.flag_id%type;
  wearerflagstartdate date;
  empflagid           flag.flag_id%type;
  empflagstartdate    date;
  routestopid         routestop.routestop_id%type;
  planneddate         date;
  debuglevel          integer;
  stayid              stay.stay_id%type;
  staynumber          stay.staynr%type;
  allowrepairscan     integer;
  vchargerepairs      customer.chargerepairs%type;
  vcustomerowned      uniqueitem.customerowned%type;
  flagsinfo           varchar2(500);
  destinationstring   varchar2(3);
  returnedplantcode   plant.code%type;
  weekplanned         integer;
  repaircog           customer.chargerepaircog%type;
  repairlog           customer.chargerepairs%type;
  findpackingnote     varchar2(50);
  ordernumber         packingnote.notenumber%type;
  productsortgroupseq productsortgroupperplant.sequencenumber%type;
  lockersortgroup#    lockersortgroup.lockersortgroupnumber%type;
  distributionpoint#  distributionpoint.distributionpointnumber%type;
  --Order 502022
  routedate  date;
  dummy_date date;
  --
  --Order 501875
  spare2order varchar2(1); --is used for collecting first char from spar2 to see if it cames from getgarmentdataorder()
  --Todo 6660
  idprimary          uniqueitem.primaryid%type; --is never used in this procedure
  lv_washestotal     uniqueitem.washestotal%type;
  lv_dummy           varchar2(255);
  sortingsystem      varchar2(10);
  klantcode          varchar2(10);
  lv_sortroute       varchar2(1);
  lv_sortpackseq     varchar2(1);
  ui_status_assigned varchar2(1);
  gv_sortcustomerid  customer.sortcustomer_id%type;
  -- Order 20013679
  lv_deliverypointid        deliverypoint.deliverypoint_id%type;
  lv_allowcustlockersharing varchar2(1);
  -- TD 25504
  lv_stopnumber      stop.stopnumber%type;
  lv_sortingsystemstockroom systemsetting.value%type;
  lv_seasoncode season.code%type;
begin
  select min(code) into klantcode from databasesettings;
  spare2order := substr(spare2, 1, 1);
  /**********************************************************\
  19-April-2007 Order 502022 GETGARMENTDATA flexible scandate
  29-March-2017 ABS-48421 stack change includes route as well
  09-10-2023 ABS-156386 Add support season_change sortfield
  22-11-2023 ABS-158160 4 route getgarmentdata, use flexfield
  16-01-2024 ABS-160061 Change procedures CLB for Inwatec & WGID
  \**********************************************************/
  begin
    routedate := to_date(substr(spare2, 2, 8), 'YYYYMMDD');
  exception
    when others then
      routedate := sysdate;
  end;
  ---
  pack_sort.determinegarmentid('METRIC', idcode, plantcode, uniqueitemid, pool, unitcode,
                               businessunitid, plantid_garment, returnedplantcode,
                               --not used for metric
                               status, idprimary, plantid_param, secondaryid);
  if (status = 1 and klantcode = 'CLB' and length(idcode) = 16) then
    begin
      pack_sort.determinegarmentid('METRIC', '00' || substr(idcode, -10), plantcode,
                                   uniqueitemid, pool, unitcode, businessunitid, plantid_garment,
                                   returnedplantcode,
                                   --not used for metric
                                   status, idprimary, plantid_param, secondaryid);
      if status = 0 then
        begin
          --found
          update uniqueitem u
          set    u.primaryid = idcode, u.timestamp = sysdate
          where  u.primaryid = '00' || substr(idcode, -10);
          --commit the change
          commit;
        end;
      end if;
    end;
  end if;
  --ABS-79074
  if pool=0 then
    begin
       select min(s.value)
       into   lv_sortingsystemstockroom
       from   systemsetting s
       where  s.plant_id = plantid_param
       and    s.name = 'SORTINGSYSTEMSTOCKROOM';
       lv_sortingsystemstockroom := nvl(lv_sortingsystemstockroom,'0');
    end;
  else
    begin
      lv_sortingsystemstockroom:='0';
    end;
  end if;
  begin
    select ur.lastindate
    into   dummy_date
    from   uniqueitemroute ur
    where  ur.uniqueitem_id = uniqueitemid
    and    ur.lastindate > sysdate - 16
    and    exists (select t.code from databasesettings t where t.code = 'SMG');
    routedate := dummy_date;
  exception
    when others then
      null;
  end;
  begin
    pack_sort.getsystemsettings(plantid_param, debuglevel, lv_dummy, allowrepairscan);
    ---------------------------------------------------------------
    --other fields
    if status = 0 then
      begin
        findpackingnote := spare2order;
        sortingsystem := 'METRIC';
        if klantcode = 'KLA' then
          sortingsystem := 'SORTBATCH';
        end if;
        pack_sort.getgarmentdatainfo(sortingsystem, plantid_garment, uniqueitemid, languageid,
                                     finishingcodeid, serviceteamid, vchargerepairs, vcustomerowned,
                                     colorid, wearerflagid, wearerflagstartdate, empflagid,
                                     empflagstartdate, finishingmethodid, productid, productcode,
                                     productdescription, sizecode, customernumber, customerid,
                                     customername, wearernumber, wearername, banklocker, department,
                                     customeremployeenumber, gender, garmentdispensercode,
                                     deliverypointcode, infotext, routenumber, routeday, stopnumber,
                                     packingsequence, stayid, routeid, imageid, routestopid,
                                     planneddate, status, alternatesortstring, debuglevel,
                                     findpackingnote, ordernumber, routedate, lv_washestotal,
                                     fp_routecodeonlabel, plantid_param, gv_sortcustomerid);
        --todo4240
        if planneddate is not null then
          weekplanned := getisoweek(planneddate);
        end if;
        --Order 502022
        --Spare2 := weekplanned;
        --spare2 := substr(weekplanned, 1, 1);
        -----
        --order 501875
        if spare2order = 'Y' then
          spare2 := '';
          if weekplanned < 10 then
            spare2 := '0' || weekplanned || findpackingnote;
          else
            spare2 := weekplanned || findpackingnote;
          end if;
        else
          spare2      := weekplanned;
          ordernumber := 0;
        end if;
        if status = 0 then
          begin
            select stay.staynr into staynumber from stay where stay.stay_id = stayid;
            spare1 := staynumber;
          exception
            when others then
              null;
          end;
          begin
            --image code
            select i.code into productpicturecode from image i where i.image_id = imageid;
          exception
            when no_data_found then
              null;
          end;
          pack_sort.getdeliverydaysmask(customerid, deliverydaymask);
          pack_sort.getdepot(routeid, depot);
          begin
            --finishingcode
            select s.sortaddress
            into   finishselection
            from   finishingcode f, sortaddressperfinishingcode s
            where  f.finishingcode_id = finishingcodeid
            and    f.finishingcode_id = s.finishingcode_id
            and    s.plant_id = plantid_param;
          exception
            when no_data_found then
              null;
          end;
          begin
            --checkpoint selection
            select s.sortaddress
            into   checkpointselection
            from   serviceteam s
            where  s.serviceteam_id = serviceteamid;
          exception
            when no_data_found then
              null;
          end;
          --repairselection
          if customerid is not null then
            select nvl(max(c.chargerepairs), 0), nvl(max(c.chargerepaircog), 0)
            into   repairlog, repaircog
            from   customer c
            where  c.customer_id = customerid;
          else
            begin
              repairlog := 0;
              repaircog := 0;
            end;
          end if;
          repairselection := '';
          if ((vcustomerowned = 'Y' and repaircog in (1, 2)) or
             (vcustomerowned = 'N' and repairlog in (1, 2))) then
            begin
              select max(r.repairaddress)
              into   repairselection
              from   repairaddresspercolor r
              where  r.color_id = colorid
              and    r.plant_id = plantid_param;
            end;
          end if;
          begin
            --Destination
            select nvl(max(s.sortaddress), 0)
            into   destination
            from   sortaddressperfinishingmeth s
            where  s.finishingmethod_id = finishingmethodid
            and    s.plant_id = plantid_param;
          end;
          begin
            --fold program
            select f.foldingprogram
            into   foldprogram
            from   foldingprogramdefinition f
            where  f.product_id = productid
            and    f.finishingmethod_id = finishingmethodid
            and    f.plant_id = plantid_param;
          exception
            when no_data_found then
              null;
          end;
          --Alternate Sort String
          --order 501273
          if alternatesortstring = 'Y' then
            alternatesortstring := packingsequence;
          else
            alternatesortstring := '';
          end if;
          -- sort on packing sequence, if SORTPACKINGSEQUENCE = Y. packing sequence will be added in front of the product code
          select min(s.value)
          into   lv_sortpackseq
          from   systemsetting s
          where  s.plant_id = plantid_param
          and    s.name = 'SORTPACKINGSEQUENCE';
          if nvl(lv_sortpackseq, 'N') = 'Y' then
            productcode := lpad(to_char(packingsequence), 3, '0') ||
                           lpad(trim(productcode), 9, '0');
          end if;
          begin
            select nvl(psgp.sequencenumber, 0)
            into   productsortgroupseq
            from   productsortgroupperplant psgp, productsortgroup psg, product pr
            where  psgp.productsortgroup_id = psg.productsortgroup_id
            and    psg.productsortgroup_id = pr.productsortgroup_id
            and    psgp.plant_id = plantid_param
            and    pr.product_id = productid;
          exception
            when others then
              productsortgroupseq := 0;
          end;
          begin
            select nvl(lsg.lockersortgroupnumber, 0), di.distributionpointnumber,
                  (select ss.code --show season when NOT in the season!!
                   from   season ss
                   where  ss.season_id = wi.season_id
                   and    not exists (select 1
                           from   seasonweek sw
                           where  sw.season_id = ss.season_id
                           and    sw.weeknumber = getisoweek(sysdate))) seasoncode
            into   lockersortgroup#, distributionpoint#, lv_seasoncode
            from   uniqueitemnonpool n
            join   weareremployment e on e.weareremployment_id = n.weareremployment_id
            join   wearerinventory wi on wi.wearerinventory_id = n.wearerinventory_id
            join   distributionpoint di on di.distributionpoint_id = e.distributionpoint_id
            left   outer join(locker l
            join   lockersortgroup lsg
            -- Order 20013679, use external locker when not null e.locker_id  replaced with nvl(e.externallocker_id,e.locker_id)
            on     l.lockersortgroup_id = lsg.lockersortgroup_id) on nvl(e.externallocker_id, e.locker_id) = l.locker_id
            -- End Order 20013679
            where  n.uniqueitem_id = uniqueitemid;
          exception
            when others then
              lockersortgroup#   := 0;
              distributionpoint# := 0;
              lv_seasoncode      := ' ';
          end;
          -- Start Order 20013679 determine stop of sort customer in a better way, taking into account delivery point.
          if gv_sortcustomerid is not null then
            begin
              begin
                select s.value
                into   lv_allowcustlockersharing
                from   systemsetting s
                where  s.plant_id = plantid_garment
                and    s.name = 'ALLOWCUSTLOCKERSHARING';
              exception
                when others then
                  lv_allowcustlockersharing := '0';
              end;
              if lv_allowcustlockersharing = '0'
              then -- old implementation when lv_allowcustlockersharing = '0'
               select nvl(min(rs.stopnumber),0) into stopnumber
               from routestop rs join route r on r.route_id = rs.route_id
               where r.routenumber = routenumber
               and r.drivingday_id = routeday
               and rs.customer_id = gv_sortcustomerid
                  and trunc(sysdate) between rs.dateactive and rs.dateinactive;
              else -- new implementation when lv_allowcustlockersharing = '1'
                  select dp.deliverypoint_id
                    into lv_deliverypointid
                    from deliverypoint dp
                   where dp.customer_id = gv_sortcustomerid
                     and dp.code = trim(deliverypointcode);

                  select nvl(min(s.stopnumber),-1) into lv_stopnumber
                    from routecontrol rc, stop s
                   where rc.route_id = routeid
                     and rc.drivingdate = planneddate
                     and s.routecontrol_id = rc.routecontrol_id
                     and s.customer_link_id = gv_sortcustomerid
                     and s.deliverypoint_id = lv_deliverypointid;

                  if lv_stopnumber > -1 then
                    stopnumber := lv_stopnumber;
                  end if;
              end if; -- lv_allowcustlockersharing = '0'
            exception
              when others then
                null; -- if route/stop for sort customer could not be determined then user the already determined one.
            end;
          end if; -- gv_sortcustomerid is not null
          -- End Order 20013679
          sortstring := pack_sort.buildsortstring(productcode, sizecode, customernumber, customerid,
                                                  wearernumber, wearername, banklocker, department,
                                                  customeremployeenumber, gender,
                                                  garmentdispensercode, deliverypointcode, stopnumber,
                                                  plantid_param, vcustomerowned, ordernumber,
                                                  productsortgroupseq, lockersortgroup#,
                                                  distributionpoint#, gv_sortcustomerid, lv_seasoncode, finishselection);
          stackchangeinfo := pack_sort.buildstackchangeinfo(productcode, sizecode, customernumber,
                                                            customerid, wearernumber, wearername,
                                                            banklocker, department,
                                                            customeremployeenumber, gender,
                                                            garmentdispensercode, deliverypointcode,
                                                            stopnumber, plantid_param, vcustomerowned,
                                                            ordernumber, productsortgroupseq,
                                                            lockersortgroup#, distributionpoint#,
                                                            gv_sortcustomerid, lv_seasoncode, finishselection);
       if klantcode = 'CLO' and customerid is not null then
         begin
           routenumber := nvl(get_flexfield_number(customerid,'Customer','SRT'), routenumber);
           --use customer flexfield SRT (string) or when not filled use routenumber by default as before
           sortstring := lpad(to_char(nvl(routenumber,0)), 3, '0') ||sortstring;
           stackchangeinfo := lpad(to_char(nvl(routenumber,0)), 3, '0') ||stackchangeinfo;
           --always the same
           routeday:=1;
           stopnumber:=1;
         end;
       else
         begin
          -- sort on route, if SORTROUTE = A or D
          select min(s.value)
          into   lv_sortroute
          from   systemsetting s
          where  s.plant_id = plantid_param
          and    s.name = 'SORTROUTE';

          if lv_sortroute is not null then
            if lv_sortroute = 'A' then
              begin
              -- other option 'A' descending
              sortstring := lpad(to_char(routenumber), 3, '0') || sortstring;
              stackchangeinfo := lpad(to_char(routenumber), 3, '0') ||stackchangeinfo;
              end;
            elsif lv_sortroute = 'D' then
              begin
              -- other option 'D' descending
              sortstring := lpad(to_char(999 - routenumber), 3, '0') || sortstring;
              stackchangeinfo := lpad(to_char(999 - routenumber), 3, '0') || stackchangeinfo;
              end;
            end if;
          end if;
        end;
       end if;

          if repairselection is not null then
            --added from order501042
            --repairicon
            begin
              requiredrepairs := '';
              for vcursor in (select distinct r.repairicon
                              from   repairpointer r
                              where  r.uniqueitem_id = uniqueitemid) loop
                begin
                  requiredrepairs := requiredrepairs || vcursor.repairicon;
                end;
              end loop;
            exception
              when no_data_found then
                null;
            end;
          end if;
          --flags
          if (metricon = 'Y') then
            begin
              select case s.statustype
                       when 'UI' then
                        (case s.code
                          when '30' then
                           'Y'
                          else
                           'N'
                        end)
                       else
                        'N'
                     end
              into   ui_status_assigned
              from   uniqueitem u, status s, sizedefinition sz
              where  u.uniqueitem_id = uniqueitemid
              and    u.product_id = productid
              and    sz.code = sizecode
              and    u.sizedefinition_id = sz.sizedefinition_id
              and    u.status_id = s.status_id;
            exception
              when others then
                ui_status_assigned := 'N';
            end;
          else
            ui_status_assigned := 'N';
          end if;
          pack_sort.getflags(uniqueitemid, plantid_param, wearerflagid, wearerflagstartdate,
                             empflagid, empflagstartdate, languageid, 4, flagcode1, flagcode2,
                             flagcode3, flagcode4, flagdescription1, flagdescription2,
                             flagdescription3, flagdescription4, flagsinfo, destinationstring, 'N',
                             lv_dummy, lv_dummy, lv_dummy, lv_dummy, flagfreetext1, flagfreetext2,
                             flagfreetext3, flagfreetext4, ui_status_assigned,
                             freetext2descriptionyn, metricon);
        else
          if status = 1 then
            pack_sort.write_logging('Error for IDCODE ' || idcode ||
                                    ' DELIVERYSCHEME OR ROUTE STOPS NOT DEFINED FOR CUSTOMER ' ||
                                    customernumber, debuglevel, 'GETGARMENTDATA', plantid_param, 3,
                                    1);
          else
            pack_sort.write_logging('CHECKINTERNALSORTINGPLANT = 0, this idcode ' || idcode ||
                                    ' is not to be procesed by this plant ' || plantcode, debuglevel,
                                    'GETGARMENTDATA', plantid_param, 3, 1);
            status := 1;
          end if;
        end if; --for status=0
        --501875
        if spare2 <> weekplanned and spare2 is not null and status = 0 then
          commit;
        else
          rollback;
        end if;
      end;
    end if;
    if lv_sortingsystemstockroom = '1' and spare1=10 then
      begin
         --ABS-79074
         routenumber:=0;
         routeday:=1;
         stopnumber:=0;
         customernumber:=0;
         customername:='STOCKROOM';
         wearernumber:=1;
         wearername:='STOCKROOM';
         sortstring:=rpad(productcode, 12, ' ') || rpad(sizecode, 12, ' ');
         stackchangeinfo:=sortstring;
      end;
    end if;
    pack_sort.writelogfile('METRIC', debuglevel, plantcode, idcode, unitcode, status,
                           finishselection, checkpointselection, repairselection, destination,
                           foldprogram, stackchangeinfo, routenumber, stopnumber, routeday, depot,
                           sortstring, alternatesortstring, customernumber, customername,
                           wearernumber, wearername, department, customeremployeenumber, gender,
                           banklocker, garmentdispensercode, deliverypointcode, productcode,
                           productdescription, sizecode, productpicturecode, deliverydaymask,
                           secondaryid, flagcode1, flagcode2, flagcode3, flagcode4, flagdescription1,
                           flagdescription2, flagdescription3, flagdescription4, infotext,
                           requiredrepairs, '', '', 0, spare2);
  exception
    when others then
      pack_sort.write_logging(idcode || ' ' || sqlerrm, debuglevel, 'GETGARMENTDATA', plantid_param,
                              3, 1);
  end;
end getgarmentdatabasic;
/
create or replace procedure getgarmentdatakannegiesser(idcode    in uniqueitem.primaryid%type,
                                                       plantcode in out plant.code%type,
                                                       --UnitCode            in out NOCOPY BUSINESSUNIT.CODE%type,
                                                       status              out nocopy integer,
                                                       finisherselection   out nocopy varchar2,
                                                       finishercode        out nocopy integer,
                                                       pressselection      out nocopy varchar2,
                                                       presscode           out nocopy integer,
                                                       checkpointselection out nocopy varchar2,
                                                       checkpointcode      out nocopy integer,
                                                       repairselection     out nocopy varchar2,
                                                       repaircode          out nocopy integer,
                                                       destination         out nocopy varchar2,
                                                       destinationcode     out nocopy integer,
                                                       foldcode            out nocopy integer,
                                                       stackchangeinfo     out nocopy varchar2,
                                                       sortstring          out nocopy varchar2,
                                                       alternatesortstring out nocopy integer,
                                                       flags               out nocopy varchar2,
                                                       infotext            out nocopy wearer.remark%type,
                                                       productcode         out nocopy product.code%type,
                                                       productdescription  out nocopy product_desc.description%type,
                                                       routenumber         out nocopy route.routenumber%type,
                                                       routeday            out nocopy day.daynumber%type,
                                                       stopnumber          out nocopy routestop.stopnumber%type,
                                                       customernumber      out nocopy customer.customernumber%type,
                                                       wearernumber        out nocopy wearer.wearernumber%type) is
  --procedure getgarmentdatakannegiesser version 1.2
  uniqueitemid         uniqueitem.uniqueitem_id%type;
  plantid_param        plant.plant_id%type;
  plantid_garment      plant.plant_id%type;
  languageid           languages.language_id%type;
  finishingcodeid      finishingcode.finishingcode_id%type;
  serviceteamid        serviceteam.serviceteam_id%type;
  colorid              color.color_id%type;
  finishingmethodid    finishingmethod.finishingmethod_id%type;
  productid            product.product_id%type;
  cnt                  integer;
  wearerflagid         flag.flag_id%type;
  wearerflagstartdate  date;
  empflagid            flag.flag_id%type;
  empflagstartdate     date;
  debuglevel           integer;
  allowrepairscan      integer;
  vchargerepairs       customer.chargerepairs%type;
  vcustomerowned       uniqueitem.customerowned%type;
  customername         customer.name%type;
  customerid           customer.customer_id%type;
  banklocker           varchar2(20);
  garmentdispensercode garmentdispenser.code%type;
  deliverypointcode    deliverypoint.code%type;
  xsortaddress         varchar2(20);
  departmentnumber     department.departmentnumber%type;
  destinationstring    varchar2(3);
  flagcode1            sortaddressperflag.sortaddress%type;
  flagcode2            sortaddressperflag.sortaddress%type;
  flagcode3            sortaddressperflag.sortaddress%type;
  flagcode4            sortaddressperflag.sortaddress%type;
  flagdescription1     flag_desc.description%type;
  flagdescription2     flag_desc.description%type;
  flagdescription3     flag_desc.description%type;
  flagdescription4     flag_desc.description%type;
  flagsinfo            varchar2(500);
  customeremployee#    wearer.customeremployeenumber%type;
  wearername           wearer.searchname%type;
  gender               wearer.sex%type;
  sizecode             sizedefinition.code%type;
  packingsequence      product.packingsequence%type;
  pool                 uniqueitem.poolitem%type;
  businessunitid       businessunit.businessunit_id%type;
  stayid               stay.stay_id%type;
  routeid              route.route_id%type;
  imageid              product.image_id%type;
  routestopid          routestop.routestop_id%type;
  planneddate          date;
  bucode               businessunit.code%type;
  returnedplantcode    plant.code%type;
  valternatesortstring varchar2(28);
  repaircog            customer.chargerepaircog%type;
  repairlog            customer.chargerepairs%type;
  findpackingnote      varchar2(20);
  ordernumber          integer;
  --Order 502022
  routedate date;
  --Todo 6660
  idprimary      uniqueitem.primaryid%type; --is never used in this procedure
  lv_washestotal uniqueitem.washestotal%type;
  lv_dummy       varchar2(255);
  --Order 20012033
  routecodeonlabel    route.codeonlabel%type;
  secondaryid         secondaryuniqueitem.secondaryid%type; --not used
  gv_sortcustomerid   customer.sortcustomer_id%type;
  productsortgroupseq productsortgroupperplant.sequencenumber%type;
  lockersortgroup#    lockersortgroup.lockersortgroupnumber%type;
  distributionpoint#  distributionpoint.distributionpointnumber%type;
  lv_seasoncode       season.code%type;
begin
  routedate := sysdate;
  pack_sort.determinegarmentid('KANNEGIESSER', idcode, plantcode, uniqueitemid, pool, bucode,
                               businessunitid, plantid_garment, returnedplantcode, status, idprimary,
                               plantid_param, secondaryid);
  begin
    if plantcode is null then
      plantcode := returnedplantcode;
    end if;
    pack_sort.getsystemsettings(plantid_param, debuglevel, lv_dummy, allowrepairscan);
    ---------------------------------------------------------------
    --other fields
    if status = 0 then
      begin
        findpackingnote := '';
        ordernumber     := 0;
        pack_sort.getgarmentdatainfo('KANNEGIESSER', plantid_garment, uniqueitemid, languageid,
                                     finishingcodeid, serviceteamid, vchargerepairs, vcustomerowned,
                                     colorid, wearerflagid, wearerflagstartdate, empflagid,
                                     empflagstartdate, finishingmethodid, productid, productcode,
                                     productdescription, sizecode, customernumber, customerid,
                                     customername, wearernumber, wearername, banklocker,
                                     departmentnumber, customeremployee#, gender,
                                     garmentdispensercode, deliverypointcode, infotext, routenumber,
                                     routeday, stopnumber, packingsequence, stayid, routeid, imageid,
                                     routestopid, planneddate, status, valternatesortstring,
                                     debuglevel, findpackingnote, ordernumber, routedate,
                                     lv_washestotal, routecodeonlabel, null, gv_sortcustomerid);
        if status = 0 then
          --Alternate Sort String
          --order 501273
          if valternatesortstring = 'Y' then
            alternatesortstring := packingsequence;
          else
            alternatesortstring := '';
          end if;
          if gv_sortcustomerid is not null then
            begin
              --get sort customer stopnumber for route found
              select nvl(min(rs.stopnumber), 0)
              into   stopnumber
              from   routestop rs
              join   route r
              on     r.route_id = rs.route_id
              where  r.routenumber = routenumber
              and    r.drivingday_id = routeday
              and    rs.customer_id = gv_sortcustomerid
              and    trunc(sysdate) between rs.dateactive and rs.dateinactive;
            end;
          end if;
          begin
            select nvl(psgp.sequencenumber, 0)
            into   productsortgroupseq
            from   productsortgroupperplant psgp, productsortgroup psg, product pr
            where  psgp.productsortgroup_id = psg.productsortgroup_id
            and    psg.productsortgroup_id = pr.productsortgroup_id
            and    psgp.plant_id = plantid_param
            and    pr.product_id = productid;
          exception
            when others then
              productsortgroupseq := 0;
          end;
          begin
            select nvl(lsg.lockersortgroupnumber, 0), di.distributionpointnumber,
                  (select ss.code --show season when NOT in the season!!
                   from   season ss
                   where  ss.season_id = wi.season_id
                   and    not exists (select 1
                           from   seasonweek sw
                           where  sw.season_id = ss.season_id
                           and    sw.weeknumber = getisoweek(sysdate))) seasoncode
            into   lockersortgroup#, distributionpoint#, lv_seasoncode
            from   uniqueitemnonpool n
            join   weareremployment e on e.weareremployment_id = n.weareremployment_id
            join   wearerinventory wi on wi.wearerinventory_id = n.wearerinventory_id
            join   distributionpoint di on di.distributionpoint_id = e.distributionpoint_id
            left   outer join(locker l
            join   lockersortgroup lsg
            -- Order 20013679, use external locker when not null e.locker_id  replaced with nvl(e.externallocker_id,e.locker_id)
            on     l.lockersortgroup_id = lsg.lockersortgroup_id) on nvl(e.externallocker_id, e.locker_id) = l.locker_id
            -- End Order 20013679
            where  n.uniqueitem_id = uniqueitemid;
          exception
            when others then
              lockersortgroup#   := 0;
              distributionpoint# := 0;
              lv_seasoncode      := ' ';
          end;
          if gv_sortcustomerid is not null then
            begin
              --get sort customer stopnumber for route found
              select nvl(min(rs.stopnumber), 0)
              into   stopnumber
              from   routestop rs
              join   route r
              on     r.route_id = rs.route_id
              where  r.routenumber = routenumber
              and    r.drivingday_id = routeday
              and    rs.customer_id = gv_sortcustomerid
              and    trunc(sysdate) between rs.dateactive and rs.dateinactive;
            end;
          end if;
          --order1044
          begin
            --finishingcode
            select max(s.sortaddress)
            into   xsortaddress
            from   sortaddressperfinishingcode s
            where  s.finishingcode_id = finishingcodeid
            and    s.plant_id = plantid_param;
            if xsortaddress is null then
              finisherselection := 'B';
              finishercode      := 0;
            else
              finishercode      := substr(xsortaddress, 2, 2);
              finisherselection := substr(xsortaddress, 1, 1);
            end if;
            cnt := to_number(finishercode);
          exception
            when others then
              finisherselection := 'B';
              finishercode      := 0;
          end;
          sortstring      := pack_sort.buildsortstring(productcode, sizecode, customernumber,
                                                       customerid, wearernumber, wearername,
                                                       banklocker, departmentnumber,
                                                       customeremployee#, gender,
                                                       garmentdispensercode, deliverypointcode,
                                                       stopnumber, plantid_param, vcustomerowned,
                                                       ordernumber, productsortgroupseq,
                                                       lockersortgroup#, distributionpoint#,
                                                       gv_sortcustomerid, lv_seasoncode, nvl(xsortaddress,0));
          stackchangeinfo := pack_sort.buildstackchangeinfo(productcode, sizecode, customernumber,
                                                            customerid, wearernumber, wearername,
                                                            banklocker, departmentnumber,
                                                            customeremployee#, gender,
                                                            garmentdispensercode, deliverypointcode,
                                                            stopnumber, plantid_param, vcustomerowned,
                                                            ordernumber, productsortgroupseq,
                                                            lockersortgroup#, distributionpoint#,
                                                            gv_sortcustomerid, lv_seasoncode, nvl(xsortaddress,0));
          pressselection := 'B';
          presscode      := 0;
          begin
            --checkpoint selection
            select s.sortaddress
            into   xsortaddress --
            from   serviceteam s
            where  s.serviceteam_id = serviceteamid;
            if xsortaddress is null then
              checkpointselection := 'B';
              checkpointcode      := 0;
            else
              checkpointcode      := substr(xsortaddress, 2, 2);
              checkpointselection := substr(xsortaddress, 1, 1);
            end if;
            cnt := to_number(checkpointcode);
          exception
            when others then
              checkpointselection := 'B';
              checkpointcode      := 0;
          end;
          begin
            --repair selection
            repairselection := '1';
            if vcustomerowned = 'Y' then
              select c.chargerepaircog, c.chargerepairs
              into   repaircog, repairlog
              from   customer c
              where  c.customer_id = customerid;
              if repaircog = 0 then
                repairselection := 'B';
                repaircode      := 0;
              end if;
            else
              if repairlog = 0 then
                repairselection := 'B';
                repaircode      := 0;
              end if;
            end if;
            if repairselection = '1' then
              begin
                repairselection := '';
                select r.repairaddress
                into   xsortaddress --RepairSelection
                from   repairaddresspercolor r
                where  r.color_id = colorid
                and    r.plant_id = plantid_param;
                if xsortaddress is null then
                  repairselection := 'B';
                  repaircode      := 0;
                else
                  repaircode      := substr(xsortaddress, 2, 2);
                  repairselection := substr(xsortaddress, 1, 1);
                end if;
                cnt := to_number(repaircode);
              exception
                when others then
                  repairselection := 'B';
                  repaircode      := 0;
              end;
            end if;
          end;
          begin
            --Destination
            pack_sort.getflags(uniqueitemid, plantid_param, wearerflagid, wearerflagstartdate,
                               empflagid, empflagstartdate, languageid, 0, flagcode1, flagcode2,
                               flagcode3, flagcode4, flagdescription1, flagdescription2,
                               flagdescription3, flagdescription4, flagsinfo, destinationstring, 'N',
                               lv_dummy, lv_dummy, lv_dummy, lv_dummy);
            if destinationstring is not null then
              destinationcode := substr(destinationstring, 2, 2);
              destination     := substr(destinationstring, 1, 1);
            else
              begin
                select s.sortaddress
                into   xsortaddress --Destination
                from   sortaddressperfinishingmeth s
                where  s.finishingmethod_id = finishingmethodid
                and    s.plant_id = plantid_param;
                if xsortaddress is null then
                  destination     := 'M';
                  destinationcode := 0;
                else
                  destinationcode := substr(xsortaddress, 2, 2);
                  destination     := substr(xsortaddress, 1, 1);
                end if;
                cnt := to_number(destinationcode);
                if destination not in ('M', 'F', 'A', 'H') then
                  destination     := 'M';
                  destinationcode := 0;
                end if;
              exception
                when others then
                  destination     := 'M';
                  destinationcode := 0;
              end;
            end if;
          end;
          begin
            --fold program
            select f.foldingprogram
            into   xsortaddress --Fold
            from   foldingprogramdefinition f
            where  f.product_id = productid
            and    f.finishingmethod_id = finishingmethodid
            and    f.plant_id = plantid_param;
            if xsortaddress is null then
              foldcode := 0;
            else
              foldcode := substr(xsortaddress, 1, 2);
            end if;
            cnt := to_number(foldcode);
          exception
            when others then
              begin
                foldcode := 0;
                pack_sort.write_logging('Error for IDCODE ' || idcode ||
                                        'Folding Program not found' || sqlcode || ' ' || sqlerrm,
                                        debuglevel, 'GETGARMENTDATAKANNEGIESSER', plantid_param, 1,
                                        1);
              end;
          end;
          --flags
          pack_sort.getflags(uniqueitemid, plantid_param, wearerflagid, wearerflagstartdate,
                             empflagid, empflagstartdate, languageid, 100, flagcode1, flagcode2,
                             flagcode3, flagcode4, flagdescription1, flagdescription2,
                             flagdescription3, flagdescription4, flagsinfo, destinationstring, 'N',
                             lv_dummy, lv_dummy, lv_dummy, lv_dummy);
          flags := flagsinfo;
        else
          pack_sort.write_logging('Error for IDCODE ' || idcode ||
                                  ' DELIVERYSCHEME OR ROUTE STOPS NOT DEFINED FOR CUSTOMER' ||
                                  customernumber, debuglevel, 'GETGARMENTDATAKANNEGIESSER',
                                  plantid_param, 3, 1);
        end if; --for stATUS=0
      end;
    end if;
    pack_sort.writelogfile('KANNEGIESSER', debuglevel, plantcode, idcode, bucode, status,
                           finisherselection, checkpointselection, repairselection, destination,
                           to_char(foldcode), stackchangeinfo, routenumber, stopnumber, routeday, '',
                           sortstring, alternatesortstring, customernumber, '', wearernumber,
                           wearername, departmentnumber, customeremployee#, gender, banklocker,
                           garmentdispensercode, deliverypointcode, productcode, productdescription,
                           sizecode, '', '', '', '', '', '', '', '', '', '', '', infotext, '', flags,
                           '', 0, ' ');
  exception
    when others then
      pack_sort.write_logging(idcode || ' ' || sqlerrm, debuglevel, 'GETGARMENTDATAKANNEGIESSER',
                              plantid_param, 3, 1);
  end;
end getgarmentdatakannegiesser;
/
create or replace procedure getgarmentdatakannegiesser2(idcode              in uniqueitem.primaryid%type,
                                                        plantcode           in out plant.code%type,
                                                        fp_languagecode     in languages.code%type,
                                                        status              out nocopy integer,
                                                        finisherselection   out nocopy varchar2,
                                                        finishercode        out nocopy integer,
                                                        pressselection      out nocopy varchar2,
                                                        presscode           out nocopy integer,
                                                        checkpointselection out nocopy varchar2,
                                                        checkpointcode      out nocopy integer,
                                                        repairselection     out nocopy varchar2,
                                                        repaircode          out nocopy integer,
                                                        destination         out nocopy varchar2,
                                                        destinationcode     out nocopy integer,
                                                        foldcode            out nocopy integer,
                                                        stackchangeinfo     out nocopy varchar2,
                                                        sortstring          out nocopy varchar2,
                                                        alternatesortstring out nocopy integer,
                                                        flags               out nocopy varchar2,
                                                        infotext            out nocopy wearer.remark%type,
                                                        productcode         out nocopy product.code%type,
                                                        productdescription  out nocopy product_desc.description%type,
                                                        routenumber         out nocopy route.routenumber%type,
                                                        routeday            out nocopy day.daynumber%type,
                                                        stopnumber          out nocopy routestop.stopnumber%type,
                                                        customernumber      out nocopy customer.customernumber%type,
                                                        wearernumber        out nocopy wearer.wearernumber%type,
                                                        flagcode1           out nocopy sortaddressperflag.sortaddress%type,
                                                        flagcode2           out nocopy sortaddressperflag.sortaddress%type,
                                                        flagcode3           out nocopy sortaddressperflag.sortaddress%type,
                                                        flagcode4           out nocopy sortaddressperflag.sortaddress%type,
                                                        flagdescription1    out nocopy flag_desc.description%type,
                                                        flagdescription2    out nocopy flag_desc.description%type,
                                                        flagdescription3    out nocopy flag_desc.description%type,
                                                        flagdescription4    out nocopy flag_desc.description%type,
                                                        fp_washestotal      out nocopy uniqueitem.washestotal%type,
                                                        fp_productimagename out nocopy image.imagename%type,
                                                        fp_flag_freetext1   out nocopy uniqueitemflag.freetextitem%type,
                                                        fp_flag_freetext2   out nocopy uniqueitemflag.freetextitem%type,
                                                        fp_flag_freetext3   out nocopy uniqueitemflag.freetextitem%type,
                                                        fp_flag_freetext4   out nocopy uniqueitemflag.freetextitem%type) is
  --procedure getgarmentdatakannegiesser2 version 1.2
  uniqueitemid         uniqueitem.uniqueitem_id%type;
  plantid_param        plant.plant_id%type;
  plantid_garment      plant.plant_id%type;
  languageid           languages.language_id%type;
  finishingcodeid      finishingcode.finishingcode_id%type;
  serviceteamid        serviceteam.serviceteam_id%type;
  colorid              color.color_id%type;
  finishingmethodid    finishingmethod.finishingmethod_id%type;
  productid            product.product_id%type;
  cnt                  integer;
  wearerflagid         flag.flag_id%type;
  wearerflagstartdate  date;
  empflagid            flag.flag_id%type;
  empflagstartdate     date;
  debuglevel           integer;
  allowrepairscan      integer;
  vchargerepairs       customer.chargerepairs%type;
  vcustomerowned       uniqueitem.customerowned%type;
  customername         customer.name%type;
  customerid           customer.customer_id%type;
  banklocker           varchar2(20);
  garmentdispensercode garmentdispenser.code%type;
  deliverypointcode    deliverypoint.code%type;
  xsortaddress         varchar2(20);
  departmentnumber     department.departmentnumber%type;
  destinationstring    varchar2(3);
  flagsinfo            varchar2(500);
  customeremployee#    wearer.customeremployeenumber%type;
  wearername           wearer.searchname%type;
  gender               wearer.sex%type;
  sizecode             sizedefinition.code%type;
  packingsequence      product.packingsequence%type;
  pool                 uniqueitem.poolitem%type;
  businessunitid       businessunit.businessunit_id%type;
  stayid               stay.stay_id%type;
  routeid              route.route_id%type;
  imageid              product.image_id%type;
  routestopid          routestop.routestop_id%type;
  planneddate          date;
  bucode               businessunit.code%type;
  returnedplantcode    plant.code%type;
  valternatesortstring varchar2(28);
  repaircog            customer.chargerepaircog%type;
  repairlog            customer.chargerepairs%type;
  findpackingnote      varchar2(20);
  ordernumber          integer;
  --Order 502022
  routedate date;
  --Todo 6660
  idprimary uniqueitem.primaryid%type; --is never used in this procedure
  --Order 20012033
  routecodeonlabel    route.codeonlabel%type;
  secondaryid         secondaryuniqueitem.secondaryid%type; --not used
  gv_sortcustomerid   customer.sortcustomer_id%type;
  gv_vosplantcode     varchar2(10);
  gv_vosortcustomerid customer.sortcustomer_id%type;
  productsortgroupseq productsortgroupperplant.sequencenumber%type;
  lockersortgroup#    lockersortgroup.lockersortgroupnumber%type;
  distributionpoint#  distributionpoint.distributionpointnumber%type;
  lv_dummy            varchar2(255);
  lv_databasecode     databasesettings.code%type;
  lv_seasoncode       season.code%type;

  procedure get_productimagename is
  begin
    select max(i.imagename)
    into   fp_productimagename
    from   product p, image i
    where  p.product_id = productid
    and    p.image_id = i.image_id;
  end get_productimagename;

  procedure get_languageid is
  begin
    if fp_languagecode is not null then
      select l.language_id into languageid from languages l where l.code = fp_languagecode;
    end if;
  exception
    when no_data_found then
      languageid := null;
  end get_languageid;
begin
  --getgarmentdatakannegiesser2 version 0.5
  case plantcode
    when 'VOSALT' then
      begin
        gv_vosplantcode := plantcode;
        plantcode       := '1';
        select max(c.customer_id)
        into   gv_vosortcustomerid
        from   customer c
        where  c.customernumber = 777777;
      end;
    when 'VOSNEU' then
      begin
        gv_vosplantcode := plantcode;
        plantcode       := '1';
        select max(c.customer_id)
        into   gv_vosortcustomerid
        from   customer c
        where  c.customernumber = 777770;
      end;
    else
      begin
        gv_vosplantcode     := null;
        gv_vosortcustomerid := null;
      end;
  end case;
  select d.code into lv_databasecode from databasesettings d;
  get_languageid;
  pack_sort.determinegarmentid('KANNEGIESSER', idcode, plantcode, uniqueitemid, pool, bucode,
                               businessunitid, plantid_garment, returnedplantcode, status, idprimary,
                               plantid_param, secondaryid);
  if gv_vosplantcode = 'VOSNEU' and pool <> 1 then
    begin
      gv_vosortcustomerid := null;
    end;
  end if;
  if lv_databasecode = 'PAV' then
    begin
      --ABS-96306
      select ur.lastindate
      into   routedate
      from   uniqueitemroute ur
      where  ur.uniqueitem_id = uniqueitemid
      and    ur.lastindate > sysdate - 16;
    exception
      when others then
        null;
    end;
  end if;
  routedate := nvl(routedate, sysdate);
  begin
    if plantcode is null then
      plantcode := returnedplantcode;
    end if;
    pack_sort.getsystemsettings(plantid_param, debuglevel, lv_dummy, allowrepairscan);
    ---------------------------------------------------------------
    --other fields
    if status = 0 then
      begin
        findpackingnote := '';
        ordernumber     := 0;
        pack_sort.getgarmentdatainfo('KANNEGIESSER', plantid_garment, uniqueitemid, languageid,
                                     finishingcodeid, serviceteamid, vchargerepairs, vcustomerowned,
                                     colorid, wearerflagid, wearerflagstartdate, empflagid,
                                     empflagstartdate, finishingmethodid, productid, productcode,
                                     productdescription, sizecode, customernumber, customerid,
                                     customername, wearernumber, wearername, banklocker,
                                     departmentnumber, customeremployee#, gender,
                                     garmentdispensercode, deliverypointcode, infotext, routenumber,
                                     routeday, stopnumber, packingsequence, stayid, routeid, imageid,
                                     routestopid, planneddate, status, valternatesortstring,
                                     debuglevel, findpackingnote, ordernumber, routedate,
                                     fp_washestotal, routecodeonlabel, null, gv_sortcustomerid);
        if status = 0 then
          --Alternate Sort String
          --order 501273
          if valternatesortstring = 'Y' then
            alternatesortstring := packingsequence;
          else
            alternatesortstring := '';
          end if;
          get_productimagename; --502901
          begin
            select nvl(psgp.sequencenumber, 0)
            into   productsortgroupseq
            from   productsortgroupperplant psgp, productsortgroup psg, product pr
            where  psgp.productsortgroup_id = psg.productsortgroup_id
            and    psg.productsortgroup_id = pr.productsortgroup_id
            and    psgp.plant_id = plantid_param
            and    pr.product_id = productid;
          exception
            when others then
              productsortgroupseq := 0;
          end;
          begin
            select nvl(lsg.lockersortgroupnumber, 0), di.distributionpointnumber,
                  (select ss.code --show season when NOT in the season!!
                   from   season ss
                   where  ss.season_id = wi.season_id
                   and    not exists (select 1
                           from   seasonweek sw
                           where  sw.season_id = ss.season_id
                           and    sw.weeknumber = getisoweek(sysdate))) seasoncode
            into   lockersortgroup#, distributionpoint#, lv_seasoncode
            from   uniqueitemnonpool n
            join   weareremployment e on e.weareremployment_id = n.weareremployment_id
            join   wearerinventory wi on wi.wearerinventory_id = n.wearerinventory_id
            join   distributionpoint di on di.distributionpoint_id = e.distributionpoint_id
            left   outer join(locker l
            join   lockersortgroup lsg
            -- Order 20013679, use external locker when not null e.locker_id  replaced with nvl(e.externallocker_id,e.locker_id)
            on     l.lockersortgroup_id = lsg.lockersortgroup_id) on nvl(e.externallocker_id, e.locker_id) = l.locker_id
            -- End Order 20013679
            where  n.uniqueitem_id = uniqueitemid;
          exception
            when others then
              lockersortgroup#   := 0;
              distributionpoint# := 0;
              lv_seasoncode      := ' ';
          end;
          if gv_sortcustomerid is not null then
            begin
              --get sort customer stopnumber for route found
              select nvl(min(rs.stopnumber), 0)
              into   stopnumber
              from   routestop rs
              join   route r
              on     r.route_id = rs.route_id
              where  r.routenumber = routenumber
              and    r.drivingday_id = routeday
              and    rs.customer_id = gv_sortcustomerid
              and    trunc(sysdate) between rs.dateactive and rs.dateinactive;
            exception
              when others then
                stopnumber := 0;
            end;
          end if;
          --order1044
          begin
            --finishingcode
            select max(s.sortaddress)
            into   xsortaddress
            from   sortaddressperfinishingcode s
            where  s.finishingcode_id = finishingcodeid
            and    s.plant_id = plantid_param;
            if xsortaddress is null then
              finisherselection := 'B';
              finishercode      := 0;
            else
              finishercode      := substr(xsortaddress, 2, 2);
              finisherselection := substr(xsortaddress, 1, 1);
            end if;
            cnt := to_number(finishercode);
          exception
            when others then
              finisherselection := 'B';
              finishercode      := 0;
          end;
          sortstring      := pack_sort.buildsortstring(productcode, sizecode, customernumber,
                                                       customerid, wearernumber, wearername,
                                                       banklocker, departmentnumber,
                                                       customeremployee#, gender,
                                                       garmentdispensercode, deliverypointcode,
                                                       stopnumber, plantid_param, vcustomerowned,
                                                       ordernumber, productsortgroupseq,
                                                       lockersortgroup#, distributionpoint#,
                                                       nvl(gv_vosortcustomerid, gv_sortcustomerid),lv_seasoncode,nvl(xsortaddress,0));
          stackchangeinfo := pack_sort.buildstackchangeinfo(productcode, sizecode, customernumber,
                                                       customerid, wearernumber, wearername,
                                                       banklocker, departmentnumber,
                                                       customeremployee#, gender,
                                                       garmentdispensercode, deliverypointcode,
                                                       stopnumber, plantid_param, vcustomerowned,
                                                       ordernumber, productsortgroupseq,
                                                       lockersortgroup#, distributionpoint#,
                                                       nvl(gv_vosortcustomerid, gv_sortcustomerid),lv_seasoncode,nvl(xsortaddress,0));
          pressselection := 'B';
          presscode      := 0;
          begin
            --checkpoint selection
            select s.sortaddress
            into   xsortaddress --
            from   serviceteam s
            where  s.serviceteam_id = serviceteamid;
            if xsortaddress is null then
              checkpointselection := 'B';
              checkpointcode      := 0;
            else
              checkpointcode      := substr(xsortaddress, 2, 2);
              checkpointselection := substr(xsortaddress, 1, 1);
            end if;
            cnt := to_number(checkpointcode);
          exception
            when others then
              checkpointselection := 'B';
              checkpointcode      := 0;
          end;
          if customerid is not null then
            begin
              --repair selection
              /*
              only for LOG
              0 = No Repair allowed  and No charge repair
              1 = Repair allowed and No charge repair
              2 = Repair allowed and Charge repair
              only for COG
              0 = No Repair allowed  and No charge repair
              1 = Repair allowed and No charge repair
              2 = Repair allowed and Charge repair
              */
              repairselection := 'B';
              repaircode      := 0;

              select c.chargerepaircog, c.chargerepairs
              into   repaircog, repairlog
              from   customer c
              where  c.customer_id = customerid;

              select r.repairaddress
              into   xsortaddress --RepairSelection
              from   repairaddresspercolor r
              where  r.color_id = colorid
              and    r.plant_id = plantid_param;

              if vcustomerowned = 'Y' then
                if repaircog <> 0 then
                  --COG
                  repairselection := 'R';
                  repaircode      := substr(xsortaddress, 2, 2);
                end if;
              else
                if repairlog <> 0 then
                  --LOG
                  repairselection := 'R';
                  repaircode      := substr(xsortaddress, 2, 2);
                end if;
              end if;
            exception
              when no_data_found then
                begin
                  repairselection := 'B';
                  repaircode      := 0;
                end;
            end;
          else
            begin
              repairselection := 'B';
              repaircode      := 0;
            end;
          end if;
          begin
            --Destination
            pack_sort.getflags(uniqueitemid, plantid_param, wearerflagid, wearerflagstartdate,
                               empflagid, empflagstartdate, languageid, 0, flagcode1, flagcode2,
                               flagcode3, flagcode4, flagdescription1, flagdescription2,
                               flagdescription3, flagdescription4, flagsinfo, destinationstring, 'Y',
                               fp_flag_freetext1, fp_flag_freetext2, fp_flag_freetext3,
                               fp_flag_freetext4);
            if destinationstring is not null then
              destinationcode := substr(destinationstring, 2, 2);
              destination     := substr(destinationstring, 1, 1);
            else
              begin
                select s.sortaddress
                into   xsortaddress --Destination
                from   sortaddressperfinishingmeth s
                where  s.finishingmethod_id = finishingmethodid
                and    s.plant_id = plantid_param;
                if xsortaddress is null then
                  destination     := 'M';
                  destinationcode := 0;
                else
                  destinationcode := substr(xsortaddress, 2, 2);
                  destination     := substr(xsortaddress, 1, 1);
                end if;
                cnt := to_number(destinationcode);
                if destination not in ('M', 'F', 'A', 'H') then
                  destination     := 'M';
                  destinationcode := 0;
                end if;
              exception
                when others then
                  destination     := 'M';
                  destinationcode := 0;
              end;
            end if;
          end;
          begin
            --fold program
            select f.foldingprogram
            into   xsortaddress --Fold
            from   foldingprogramdefinition f
            where  f.product_id = productid
            and    f.finishingmethod_id = finishingmethodid
            and    f.plant_id = plantid_param;
            if xsortaddress is null then
              foldcode := 0;
            else
              foldcode := substr(xsortaddress, 1, 2);
            end if;
            cnt := to_number(foldcode);
          exception
            when others then
              begin
                foldcode := 0;
                pack_sort.write_logging('Error for IDCODE ' || idcode ||
                                        'Folding Program not found' || sqlcode || ' ' || sqlerrm,
                                        debuglevel, 'GETGARMENTDATAKANNEGIESSER2', plantid_param, 1,
                                        1);
              end;
          end;
          --flags
          pack_sort.getflags(uniqueitemid, plantid_param, wearerflagid, wearerflagstartdate,
                             empflagid, empflagstartdate, languageid, 4, flagcode1, flagcode2,
                             flagcode3, flagcode4, flagdescription1, flagdescription2,
                             flagdescription3, flagdescription4, flagsinfo, destinationstring, 'Y',
                             fp_flag_freetext1, fp_flag_freetext2, fp_flag_freetext3,
                             fp_flag_freetext4);
          flags := flagsinfo;
        else
          pack_sort.write_logging('Error for IDCODE ' || idcode ||
                                  ' DELIVERYSCHEME OR ROUTE STOPS NOT DEFINED FOR CUSTOMER' ||
                                  customernumber, debuglevel, 'GETGARMENTDATAKANNEGIESSER2',
                                  plantid_param, 3, 1);
        end if; --for stATUS=0
        if pool = 1 and lv_databasecode in ('ANG','TLK') then
          begin
            select nvl(max(pt.code), plantcode)
            into   plantcode
            from   uniqueitem u
            join   distributionpoint dp
            on     dp.distributionpoint_id =
                   nvl(u.distributionpoint_id, u.lastdistributionpoint_link_id)
            join   department t
            on     t.department_id = dp.department_id
            join   customer c
            on     c.customer_id = t.customer_id
            join   businessunit bu
            on     bu.businessunit_id = c.defaultbusinessunit_id
            join   plant pt
            on     pt.plant_id = bu.plant_id
            where  u.uniqueitem_id = uniqueitemid;
          end;
        end if;
      end;
    end if;
    pack_sort.writelogfile('KANNEGIESSER', debuglevel, plantcode, idcode, bucode, status,
                           finisherselection, checkpointselection, repairselection, destination,
                           to_char(foldcode), stackchangeinfo, routenumber, stopnumber, routeday, '',
                           sortstring, alternatesortstring, customernumber, '', wearernumber,
                           wearername, departmentnumber, customeremployee#, gender, banklocker,
                           garmentdispensercode, deliverypointcode, productcode, productdescription,
                           sizecode, '', '', '', flagcode1, flagcode2, flagcode3, flagcode4,
                           flagdescription1, flagdescription2, flagdescription3, flagdescription4,
                           infotext, '', flags, '', 0, ' ');
  exception
    when others then
      pack_sort.write_logging(idcode || ' ' || sqlerrm, debuglevel, 'GETGARMENTDATAKANNEGIESSER2',
                              plantid_param, 3, 1);
  end;
end getgarmentdatakannegiesser2;
/
create or replace procedure getgarmentdatakannegiesserloop(fp_idcode              in uniqueitem.primaryid%type,
                                                           fp_plantcode           in out plant.code%type,
                                                           fp_languagecode        in languages.code%type,
                                                           fp_status              out nocopy integer,
                                                           fp_finisherselection   out nocopy varchar2,
                                                           fp_finishercode        out nocopy integer,
                                                           fp_pressselection      out nocopy varchar2,
                                                           fp_presscode           out nocopy integer,
                                                           fp_checkpointselection out nocopy varchar2,
                                                           fp_checkpointcode      out nocopy integer,
                                                           fp_repairselection     out nocopy varchar2,
                                                           fp_repaircode          out nocopy integer,
                                                           fp_destination         out nocopy varchar2,
                                                           fp_destinationcode     out nocopy integer,
                                                           fp_foldcode            out nocopy integer,
                                                           fp_stackchangeinfo     out nocopy varchar2,
                                                           fp_sortstring          out nocopy varchar2,
                                                           fp_alternatesortstring out nocopy integer,
                                                           fp_flags               out nocopy varchar2,
                                                           fp_infotext            out nocopy wearer.remark%type,
                                                           fp_productcode         out nocopy product.code%type,
                                                           fp_productdescription  out nocopy product_desc.description%type,
                                                           fp_deliverypointcode   out nocopy varchar2,
                                                           fp_routenumber         out nocopy route.routenumber%type,
                                                           fp_routeday            out nocopy day.daynumber%type,
                                                           fp_stopnumber          out nocopy routestop.stopnumber%type,
                                                           fp_customernumber      out nocopy customer.customernumber%type,
                                                           fp_wearernumber        out nocopy wearer.wearernumber%type,
                                                           fp_flagcode1           out nocopy sortaddressperflag.sortaddress%type,
                                                           fp_flagcode2           out nocopy sortaddressperflag.sortaddress%type,
                                                           fp_flagcode3           out nocopy sortaddressperflag.sortaddress%type,
                                                           fp_flagcode4           out nocopy sortaddressperflag.sortaddress%type,
                                                           fp_flagdescription1    out nocopy flag_desc.description%type,
                                                           fp_flagdescription2    out nocopy flag_desc.description%type,
                                                           fp_flagdescription3    out nocopy flag_desc.description%type,
                                                           fp_flagdescription4    out nocopy flag_desc.description%type,
                                                           fp_washestotal         out nocopy uniqueitem.washestotal%type,
                                                           fp_productimagename    out nocopy image.imagename%type,
                                                           fp_flag_freetext1      out nocopy uniqueitemflag.freetextitem%type,
                                                           fp_flag_freetext2      out nocopy uniqueitemflag.freetextitem%type,
                                                           fp_flag_freetext3      out nocopy uniqueitemflag.freetextitem%type,
                                                           fp_flag_freetext4      out nocopy uniqueitemflag.freetextitem%type,
                                                           fp_departmentnumber    out nocopy department.departmentnumber%type,
                                                           fp_departmentdesc      out nocopy department.description%type,
                                                           fp_sizecode            out nocopy sizedefinition.code%type,
                                                           fp_batchnumber         out nocopy uniqueitem.batchnumber%type,
                                                           fp_piecesinbatch       out nocopy number) is
  --GetGarmentDataKannegiesserLoop Version 0.28
  lv_message                 abslog.message%type;
  lv_businessunitcode        businessunit.code%type;
  lv_plantid_paramater       plant.plant_id%type;
  lv_secondaryid             secondaryuniqueitem.secondaryid%type;
  lv_foldprogram             foldingprogramdefinition.foldingprogram%type;
  lv_deliverydaymask         varchar2(100);
  lv_customername            customer.name%type;
  lv_customerowned           uniqueitem.customerowned%type;
  lv_chargerepaircog         customer.chargerepaircog%type;
  lv_chargerepairs           customer.chargerepairs%type;
  lv_distributionpointnumber distributionpoint.distributionpointnumber%type;
  lv_street                  address.street%type;
  lv_street2                 address.street2%type;
  lv_city                    address.city%type;
  lv_zipcode                 address.zipcode%type;
  lv_deliverypointdesc       deliverypoint.description%type;
  lv_wearername              wearer.emblemname%type;
  lv_wearerfullname          wearer.fullname%type;
  lv_bank                    locker.bank%type;
  lv_locker                  locker.locker%type;
  lv_garmentdispensercode    garmentdispenser.code%type;
  lv_customeremployeenumber  wearer.customeremployeenumber%type;
  lv_productsortgroup        productsortgroup.code%type;
  lv_packingsequence         product.packingsequence%type;
  lv_finishingcodeid         product.finishingcode_id%type;
  lv_flagcode1               flag.code%type;
  lv_flagcode2               flag.code%type;
  lv_flagcode3               flag.code%type;
  lv_flagcode4               flag.code%type;
  lv_lastinscandate          uniqueitem.lastinscandate%type;
  lv_lastoutscandate         uniqueitem.lastoutscandate%type;
  lv_lastscandate            uniqueitem.lastscandate%type;
  lv_repairstotal            uniqueitem.repairstotal%type;
  lv_rewashtotal             uniqueitem.rewashtotal%type;
  lv_maxwashes               product.maxwashes%type;
  lv_residualvalueamount     residualvaluehistory.residualvalueamount%type;
  lv_residualvaluepercentage residualvaluehistory.residualvaluepercentage%type;
  lv_season                  season.code%type;

  ---internal procedures/functions
  procedure write_log(fp_message in varchar2 default null, fp_priority in number default 1) is
  begin
    abslogwrite.abslog_write(5, 'getgarmentdata_eut', lv_plantid_paramater, nvl(fp_priority, 1),
                             fp_message);
  end write_log;

  procedure fill_fixed_values is
  begin
    --fill_fixed_values
    fp_pressselection := 'B';
    fp_presscode      := 0;
    fp_repaircode     := 0;
  end fill_fixed_values;

  procedure build_flag_info is
  begin
    --build_flag_info
    fp_flags := case
                  when lv_flagcode1 is not null then
                   lv_flagcode1 || ':' || fp_flagdescription1 || chr(13) || chr(10)
                end || case
                  when lv_flagcode1 is not null then
                   lv_flagcode2 || ':' || fp_flagdescription2 || chr(13) || chr(10)
                end || case
                  when lv_flagcode1 is not null then
                   lv_flagcode3 || ':' || fp_flagdescription3 || chr(13) || chr(10)
                end || case
                  when lv_flagcode1 is not null then
                   lv_flagcode4 || ':' || fp_flagdescription4 || chr(13) || chr(10)
                end;
  end build_flag_info;

  procedure get_foldcode is
  begin
    --get_foldcode
    if lv_foldprogram is null then
      fp_foldcode := 0;
    else
      fp_foldcode := to_number(substr(fp_foldcode, 1, 2));
    end if;
  exception
    when others then
      begin
        fp_foldcode := 0;
      end;
  end get_foldcode;

  procedure get_destinationcode is
  begin
    --get_destinationcode
    if fp_flagcode1 is not null then
      begin
        if to_number(substr(fp_flagcode1, 2, 2)) >= 0 then
          fp_destinationcode := substr(fp_flagcode1, 1, 3);
        end if;
      end;
    end if;
    if fp_destination not in ('M', 'F', 'A', 'H') then
      fp_destination     := 'M';
      fp_destinationcode := 0;
    end if;
  exception
    when others then
      fp_destinationcode := '';
  end get_destinationcode;

  procedure get_finishcode is
    lv_sortaddress sortaddressperfinishingcode.sortaddress%type;
  begin
    --get_finishcode
    select s.sortaddress
    into   lv_sortaddress
    from   sortaddressperfinishingcode s
    where  s.finishingcode_id = lv_finishingcodeid
    and    s.plant_id = lv_plantid_paramater;
    if lv_sortaddress is null then
      fp_finisherselection := 'B';
      fp_finishercode      := 0;
    else
      fp_finishercode      := to_number(substr(lv_sortaddress, 2, 2));
      fp_finisherselection := substr(lv_sortaddress, 1, 1);
    end if;
  exception
    when others then
      begin
        --not a number then..
        fp_finisherselection := 'B';
        fp_finishercode      := 0;
      end;
  end get_finishcode;

  procedure get_checkpoint is
  begin
    --checkpoint selection
    if fp_checkpointselection is null then
      fp_checkpointselection := 'B';
      fp_checkpointcode      := 0;
    else
      fp_checkpointselection := to_number(substr(fp_checkpointselection, 1, 1));
      fp_checkpointcode      := substr(fp_checkpointselection, 2, 2);
    end if;
  exception
    when others then
      begin
        --not a number then..
        fp_checkpointselection := 'B';
        fp_checkpointcode      := 0;
      end;
  end get_checkpoint;

  procedure get_repairselection is
  begin
    --get_repairselection
    if lv_customerowned = 'Y' then
      if lv_chargerepaircog <> 0 then
        fp_repairselection := 'R';
      end if;
    elsif lv_chargerepairs <> 0 then
      fp_repairselection := 'R';
    else
      fp_repairselection := null;
    end if;
  exception
    when others then
      fp_repairselection := null;
  end get_repairselection;

  procedure count_pieces_in_batch is
  begin
    --count_pieces_in_batch
    if fp_batchnumber is not null then
      begin
        ---CREATE INDEX XBATCHUNIQUEITEM ON UNIQUEITEM (BATCHNUMBER, LASTSCANDATE);
        select count(1)
        into   fp_piecesinbatch
        from   uniqueitem u
        where  u.batchnumber = fp_batchnumber
        and    u.lastscandate > sysdate - 14;
      end;
    end if;
  end count_pieces_in_batch;
begin
  --fill_fixed_values
  fill_fixed_values;
  --getgarmentinfo
  pack_sort2.getgarmentinfo(fp_idcode, fp_plantcode, fp_languagecode, fp_status, lv_message,
                            lv_businessunitcode, lv_plantid_paramater, lv_secondaryid,
                            fp_checkpointselection, fp_destination, lv_foldprogram, fp_sortstring,
                            fp_alternatesortstring, fp_stackchangeinfo, fp_routenumber, fp_routeday,
                            fp_stopnumber, lv_deliverydaymask, fp_customernumber, lv_customername,
                            lv_customerowned, lv_chargerepaircog, lv_chargerepairs,
                            fp_departmentnumber, fp_departmentdesc, fp_deliverypointcode,
                            lv_deliverypointdesc, lv_street, lv_street2, lv_city, lv_zipcode,
                            lv_distributionpointnumber, fp_wearernumber, lv_wearerfullname,
                            lv_wearername, fp_infotext, lv_bank, lv_locker, lv_garmentdispensercode,
                            lv_customeremployeenumber, lv_productsortgroup, fp_productcode,
                            lv_packingsequence, fp_productdescription, fp_productimagename,
                            lv_finishingcodeid, fp_sizecode, lv_flagcode1, lv_flagcode2,
                            lv_flagcode3, lv_flagcode4, fp_flagcode1, fp_flagcode2, fp_flagcode3,
                            fp_flagcode4, fp_flagdescription1, fp_flagdescription2,
                            fp_flagdescription3, fp_flagdescription4, fp_flag_freetext1,
                            fp_flag_freetext2, fp_flag_freetext3, fp_flag_freetext4,
                            lv_lastinscandate, lv_lastoutscandate, lv_lastscandate, fp_washestotal,
                            lv_repairstotal, lv_rewashtotal, lv_maxwashes, lv_season,
                            lv_residualvalueamount, lv_residualvaluepercentage, fp_batchnumber);
  --build_flag_info
  build_flag_info;
  --get_foldcode
  get_foldcode;
  --get_destinationcode
  get_destinationcode;
  --get finish code
  get_finishcode;
  --get_checkpoint
  get_checkpoint;
  --count_pieces_in_batch
  count_pieces_in_batch;
exception
  when others then
    begin
      rollback;
      write_log('Error others fp_idcode ' || fp_idcode || ' fp_plantcode ' || fp_plantcode ||
                ' fp_languagecode ' || fp_languagecode || ' ' || sqlerrm, 5);
      fp_status := 5;
    end;
end getgarmentdatakannegiesserloop;
/
create or replace procedure getgarmentdatakannegiesser_wmu(idcode              in uniqueitem.primaryid%type,
                                                           plantcode           in out plant.code%type,
                                                           fp_languagecode     in languages.code%type,
                                                           status              out nocopy integer,
                                                           finisherselection   out nocopy varchar2,
                                                           finishercode        out nocopy integer,
                                                           pressselection      out nocopy varchar2,
                                                           presscode           out nocopy integer,
                                                           checkpointselection out nocopy varchar2,
                                                           checkpointcode      out nocopy integer,
                                                           repairselection     out nocopy varchar2,
                                                           repaircode          out nocopy integer,
                                                           destination         out nocopy varchar2,
                                                           destinationcode     out nocopy integer,
                                                           foldcode            out nocopy integer,
                                                           stackchangeinfo     out nocopy varchar2,
                                                           sortstring          out nocopy varchar2,
                                                           alternatesortstring out nocopy integer,
                                                           flags               out nocopy varchar2,
                                                           infotext            out nocopy wearer.remark%type,
                                                           productcode         out nocopy product.code%type,
                                                           productdescription  out nocopy product_desc.description%type,
                                                           routenumber         out nocopy route.routenumber%type,
                                                           routeday            out nocopy day.daynumber%type,
                                                           stopnumber          out nocopy routestop.stopnumber%type,
                                                           customernumber      out nocopy customer.customernumber%type,
                                                           wearernumber        out nocopy wearer.wearernumber%type,
                                                           flagcode1           out nocopy sortaddressperflag.sortaddress%type,
                                                           flagcode2           out nocopy sortaddressperflag.sortaddress%type,
                                                           flagcode3           out nocopy sortaddressperflag.sortaddress%type,
                                                           flagcode4           out nocopy sortaddressperflag.sortaddress%type,
                                                           flagdescription1    out nocopy flag_desc.description%type,
                                                           flagdescription2    out nocopy flag_desc.description%type,
                                                           flagdescription3    out nocopy flag_desc.description%type,
                                                           flagdescription4    out nocopy flag_desc.description%type,
                                                           fp_washestotal      out nocopy uniqueitem.washestotal%type,
                                                           fp_productimagename out nocopy image.imagename%type,
                                                           fp_flag_freetext1   out nocopy uniqueitemflag.freetextitem%type,
                                                           fp_flag_freetext2   out nocopy uniqueitemflag.freetextitem%type,
                                                           fp_flag_freetext3   out nocopy uniqueitemflag.freetextitem%type,
                                                           fp_flag_freetext4   out nocopy uniqueitemflag.freetextitem%type,
                                                           fp_searchname       out nocopy customer.searchname%type,
                                                           fp_weeksinuse       out nocopy number,
                                                           fp_ragdate          out nocopy varchar2,
                                                           sizecode            out nocopy varchar2) is
  --getgarmentdatakannegiesser_wmu version 0.5
  --4-4-2017 no error message when folding program not found
  --ABS-49900 new fields, 2 new output fields
  --07-04-2018 ABS-64289 sent size from ABS to Kannegieser
  --09-10-2023 ABS-156386 Add support season_change sortfield
  uniqueitemid         uniqueitem.uniqueitem_id%type;
  plantid_param        plant.plant_id%type;
  plantid_garment      plant.plant_id%type;
  languageid           languages.language_id%type;
  finishingcodeid      finishingcode.finishingcode_id%type;
  serviceteamid        serviceteam.serviceteam_id%type;
  colorid              color.color_id%type;
  finishingmethodid    finishingmethod.finishingmethod_id%type;
  productid            product.product_id%type;
  cnt                  integer;
  wearerflagid         flag.flag_id%type;
  wearerflagstartdate  date;
  empflagid            flag.flag_id%type;
  empflagstartdate     date;
  debuglevel           integer;
  allowrepairscan      integer;
  vchargerepairs       customer.chargerepairs%type;
  vcustomerowned       uniqueitem.customerowned%type;
  customername         customer.name%type;
  customerid           customer.customer_id%type;
  banklocker           varchar2(20);
  garmentdispensercode garmentdispenser.code%type;
  deliverypointcode    deliverypoint.code%type;
  xsortaddress         varchar2(20);
  departmentnumber     department.departmentnumber%type;
  destinationstring    varchar2(3);
  flagsinfo            varchar2(500);
  customeremployee#    wearer.customeremployeenumber%type;
  wearername           wearer.searchname%type;
  gender               wearer.sex%type;
  packingsequence      product.packingsequence%type;
  pool                 uniqueitem.poolitem%type;
  businessunitid       businessunit.businessunit_id%type;
  stayid               stay.stay_id%type;
  routeid              route.route_id%type;
  imageid              product.image_id%type;
  routestopid          routestop.routestop_id%type;
  planneddate          date;
  bucode               businessunit.code%type;
  returnedplantcode    plant.code%type;
  valternatesortstring varchar2(28);
  repaircog            customer.chargerepaircog%type;
  repairlog            customer.chargerepairs%type;
  findpackingnote      varchar2(20);
  ordernumber          integer;
  --Order 502022
  routedate date;
  --Todo 6660
  idprimary uniqueitem.primaryid%type; --is never used in this procedure
  --Order 20012033
  routecodeonlabel    route.codeonlabel%type;
  secondaryid         secondaryuniqueitem.secondaryid%type; --not used
  gv_sortcustomerid   customer.sortcustomer_id%type;
  productsortgroupseq productsortgroupperplant.sequencenumber%type;
  lockersortgroup#    lockersortgroup.lockersortgroupnumber%type;
  distributionpoint#  distributionpoint.distributionpointnumber%type;
  lv_dummy            varchar2(255);
  lv_databasecode     databasesettings.code%type;
  lv_seasoncode       season.code%type;

  procedure get_productimagename is
  begin
    select max(i.imagename)
    into   fp_productimagename
    from   product p, image i
    where  p.product_id = productid
    and    p.image_id = i.image_id;
  end get_productimagename;

  procedure get_languageid is
  begin
    if fp_languagecode is not null then
      select l.language_id into languageid from languages l where l.code = fp_languagecode;
    end if;
  exception
    when no_data_found then
      languageid := null;
  end get_languageid;
begin
  select d.code into lv_databasecode from databasesettings d;
  routedate := sysdate;
  get_languageid;
  pack_sort.determinegarmentid('KANNEGIESSER', idcode, plantcode, uniqueitemid, pool, bucode,
                               businessunitid, plantid_garment, returnedplantcode, status, idprimary,
                               plantid_param, secondaryid);
  begin
    if plantcode is null then
      plantcode := returnedplantcode;
    end if;
    pack_sort.getsystemsettings(plantid_param, debuglevel, lv_dummy, allowrepairscan);
    ---------------------------------------------------------------
    --other fields
    if status = 0 then
      begin
        findpackingnote := '';
        ordernumber     := 0;
        pack_sort.getgarmentdatainfo('KANNEGIESSER', plantid_garment, uniqueitemid, languageid,
                                     finishingcodeid, serviceteamid, vchargerepairs, vcustomerowned,
                                     colorid, wearerflagid, wearerflagstartdate, empflagid,
                                     empflagstartdate, finishingmethodid, productid, productcode,
                                     productdescription, sizecode, customernumber, customerid,
                                     customername, wearernumber, wearername, banklocker,
                                     departmentnumber, customeremployee#, gender,
                                     garmentdispensercode, deliverypointcode, infotext, routenumber,
                                     routeday, stopnumber, packingsequence, stayid, routeid, imageid,
                                     routestopid, planneddate, status, valternatesortstring,
                                     debuglevel, findpackingnote, ordernumber, routedate,
                                     fp_washestotal, routecodeonlabel, null, gv_sortcustomerid);
        --ABS-49900 new fields in getgarmentdatekannegiesser_wmu
        select max(round(ufi.daysincircprevissue / 7) +
                    round((trunc(sysdate) - nvl(ufi.lastissuedate, trunc(sysdate))) / 7))
        into   fp_weeksinuse
        from   uniqueitemfixedinfo ufi
        where  ufi.uniqueitem_id = uniqueitemid;
        if status = 0 then
          --Alternate Sort String
          --order 501273
          if valternatesortstring = 'Y' then
            alternatesortstring := packingsequence;
          else
            alternatesortstring := '';
          end if;
          get_productimagename; --502901
          begin
            select nvl(psgp.sequencenumber, 0)
            into   productsortgroupseq
            from   productsortgroupperplant psgp, productsortgroup psg, product pr
            where  psgp.productsortgroup_id = psg.productsortgroup_id
            and    psg.productsortgroup_id = pr.productsortgroup_id
            and    psgp.plant_id = plantid_param
            and    pr.product_id = productid;
          exception
            when others then
              productsortgroupseq := 0;
          end;
          begin
            select nvl(lsg.lockersortgroupnumber, 0), di.distributionpointnumber,
                  (select ss.code --show season when NOT in the season!!
                   from   season ss
                   where  ss.season_id = wi.season_id
                   and    not exists (select 1
                           from   seasonweek sw
                           where  sw.season_id = ss.season_id
                           and    sw.weeknumber = getisoweek(sysdate))) seasoncode
            into   lockersortgroup#, distributionpoint#, lv_seasoncode
            from   uniqueitemnonpool n
            join   weareremployment e on e.weareremployment_id = n.weareremployment_id
            join   wearerinventory wi on wi.wearerinventory_id = n.wearerinventory_id
            join   distributionpoint di on di.distributionpoint_id = e.distributionpoint_id
            left   outer join(locker l
            join   lockersortgroup lsg
            -- Order 20013679, use external locker when not null e.locker_id  replaced with nvl(e.externallocker_id,e.locker_id)
            on     l.lockersortgroup_id = lsg.lockersortgroup_id) on nvl(e.externallocker_id, e.locker_id) = l.locker_id
            -- End Order 20013679
            where  n.uniqueitem_id = uniqueitemid;
          exception
            when others then
              lockersortgroup#   := 0;
              distributionpoint# := 0;
              lv_seasoncode      := ' ';
          end;
          if gv_sortcustomerid is not null then
            begin
              --get sort customer stopnumber for route found
              select nvl(min(rs.stopnumber), 0)
              into   stopnumber
              from   routestop rs
              join   route r
              on     r.route_id = rs.route_id
              where  r.routenumber = routenumber
              and    r.drivingday_id = routeday
              and    rs.customer_id = gv_sortcustomerid
              and    trunc(sysdate) between rs.dateactive and rs.dateinactive;
            exception
              when others then
                stopnumber := 0;
            end;
          end if;
          --order1044
          begin
            --finishingcode
            select max(s.sortaddress)
            into   xsortaddress
            from   sortaddressperfinishingcode s
            where  s.finishingcode_id = finishingcodeid
            and    s.plant_id = plantid_param;
            if xsortaddress is null then
              finisherselection := 'B';
              finishercode      := 0;
            else
              finishercode      := substr(xsortaddress, 2, 2);
              finisherselection := substr(xsortaddress, 1, 1);
            end if;
            cnt := to_number(finishercode);
          exception
            when others then
              finisherselection := 'B';
              finishercode      := 0;
          end;
          sortstring      := pack_sort.buildsortstring(productcode, sizecode, customernumber,
                                                       customerid, wearernumber, wearername,
                                                       banklocker, departmentnumber,
                                                       customeremployee#, gender,
                                                       garmentdispensercode, deliverypointcode,
                                                       stopnumber, plantid_param, vcustomerowned,
                                                       ordernumber, productsortgroupseq,
                                                       lockersortgroup#, distributionpoint#,
                                                       gv_sortcustomerid, lv_seasoncode, nvl(xsortaddress,0));
          stackchangeinfo := pack_sort.buildstackchangeinfo(productcode, sizecode, customernumber,
                                                       customerid, wearernumber, wearername,
                                                       banklocker, departmentnumber,
                                                       customeremployee#, gender,
                                                       garmentdispensercode, deliverypointcode,
                                                       stopnumber, plantid_param, vcustomerowned,
                                                       ordernumber, productsortgroupseq,
                                                       lockersortgroup#, distributionpoint#,
                                                       gv_sortcustomerid, lv_seasoncode, nvl(xsortaddress,0));
          pressselection := 'B';
          presscode      := 0;
          if customerid is not null then
            begin
              --repair selection
              /*
              only for LOG
              0 = No Repair allowed  and No charge repair
              1 = Repair allowed and No charge repair
              2 = Repair allowed and Charge repair
              only for COG
              0 = No Repair allowed  and No charge repair
              1 = Repair allowed and No charge repair
              2 = Repair allowed and Charge repair
              */
              repairselection := 'B';
              repaircode      := 0;
              select c.chargerepaircog, c.chargerepairs, c.searchname
              into   repaircog, repairlog, fp_searchname
              from   customer c
              where  c.customer_id = customerid;
              if vcustomerowned = 'Y' then
                if repaircog <> 0 then
                  repairselection := 'R';
                end if;
              else
                if repairlog <> 0 then
                  repairselection := 'R';
                end if;
              end if;
            exception
              when no_data_found then
                begin
                  repairselection := 'B';
                  repaircode      := 0;
                end;
            end;
          else
            begin
              repairselection := 'B';
              repaircode      := 0;
            end;
          end if;
          begin
            --Destination
            pack_sort.getflags(uniqueitemid, plantid_param, wearerflagid, wearerflagstartdate,
                               empflagid, empflagstartdate, languageid, 0, flagcode1, flagcode2,
                               flagcode3, flagcode4, flagdescription1, flagdescription2,
                               flagdescription3, flagdescription4, flagsinfo, destinationstring, 'Y',
                               fp_flag_freetext1, fp_flag_freetext2, fp_flag_freetext3,
                               fp_flag_freetext4);
            if destinationstring is not null then
              destinationcode := substr(destinationstring, 2, 2);
              destination     := substr(destinationstring, 1, 1);
            else
              begin
                select s.sortaddress
                into   xsortaddress --Destination
                from   sortaddressperfinishingmeth s
                where  s.finishingmethod_id = finishingmethodid
                and    s.plant_id = plantid_param;
                if xsortaddress is null then
                  destination     := 'M';
                  destinationcode := 0;
                else
                  destinationcode := substr(xsortaddress, 2, 2);
                  destination     := substr(xsortaddress, 1, 1);
                end if;
                cnt := to_number(destinationcode);
                if destination not in ('M', 'F', 'A', 'H') then
                  destination     := 'M';
                  destinationcode := 0;
                end if;
              exception
                when others then
                  destination     := 'M';
                  destinationcode := 0;
              end;
            end if;
          end;
          begin
            --fold program
            select f.foldingprogram
            into   xsortaddress --Fold
            from   foldingprogramdefinition f
            where  f.product_id = productid
            and    f.finishingmethod_id = finishingmethodid
            and    f.plant_id = plantid_param;
            if xsortaddress is null then
              foldcode := 0;
            else
              foldcode := substr(xsortaddress, 1, 2);
            end if;
            cnt := to_number(foldcode);
          exception
            when others then
              begin
                foldcode := 0;
              end;
          end;
          --flags
          pack_sort.getflags(uniqueitemid, plantid_param, wearerflagid, wearerflagstartdate,
                             empflagid, empflagstartdate, languageid, 4, flagcode1, flagcode2,
                             flagcode3, flagcode4, flagdescription1, flagdescription2,
                             flagdescription3, flagdescription4, flagsinfo, destinationstring, 'Y',
                             fp_flag_freetext1, fp_flag_freetext2, fp_flag_freetext3,
                             fp_flag_freetext4);
          flags := flagsinfo;
        else
          pack_sort.write_logging('Error for IDCODE ' || idcode ||
                                  ' DELIVERYSCHEME OR ROUTE STOPS NOT DEFINED FOR CUSTOMER' ||
                                  customernumber, debuglevel, 'GETGARMENTDATAKANNEGIESSER2',
                                  plantid_param, 3, 1);
        end if; --for stATUS=0
      end;
    else
      begin
        --ABS-49900 new fields in getgarmentdatekannegiesser_wmu
        select to_char(max(rg.ragtimestamp), 'YYYYMMDD')
        into   fp_ragdate
        from   raggeditem rg
        where  rg.primaryid = idcode;
      end;
    end if;
    pack_sort.writelogfile('KANNEGIESSER', debuglevel, plantcode, idcode, bucode, status,
                           finisherselection, checkpointselection, repairselection, destination,
                           to_char(foldcode), stackchangeinfo, routenumber, stopnumber, routeday, '',
                           sortstring, alternatesortstring, customernumber, '', wearernumber,
                           wearername, departmentnumber, customeremployee#, gender, banklocker,
                           garmentdispensercode, deliverypointcode, productcode, productdescription,
                           sizecode, '', '', '', flagcode1, flagcode2, flagcode3, flagcode4,
                           flagdescription1, flagdescription2, flagdescription3, flagdescription4,
                           infotext, '', flags, '', 0, ' ');
  exception
    when others then
      pack_sort.write_logging(idcode || ' ' || sqlerrm, debuglevel, 'GETGARMENTDATAKANNEGIESSER2',
                              plantid_param, 3, 1);
  end;
end getgarmentdatakannegiesser_wmu;
/
create or replace procedure getgarmentdatalts(idcode      in uniqueitem.primaryid%type,
                                              plantcode   in out plant.code%type,
                                              sortaddress out nocopy varchar2,
                                              makescan    out nocopy varchar2) is
  --getgarmentdataLTS version 1.2
  uniqueitemid      uniqueitem.uniqueitem_id%type;
  plantid_param     plant.plant_id%type;
  plantid_garment   plant.plant_id%type;
  returnedplantcode plant.code%type;
  pool              uniqueitem.poolitem%type;
  businessunitid    integer;
  uistatus          varchar2(2);
  sortaddressamt    varchar2(20);
  unitcode          varchar2(20);
  status            integer;
  productid         product.product_id%type;
  sizedefinitionid  sizedefinition.sizedefinition_id%type;
  specialsizeid     sizedefinition.sizedefinition_id%type;
  finishingmethodid finishingmethod.finishingmethod_id%type;
  specialfmethodid  finishingmethod.finishingmethod_id%type;
  customerid        customer.customer_id%type;
  plpcid            productlistpercustomer.productlistpercustomer_id%type;
  debuglevel        integer;
  allowrepairscan   integer;
  --Todo 6660
  idprimary              uniqueitem.primaryid%type; --is never used in this procedure
  secondaryid            secondaryuniqueitem.secondaryid%type; --not used
  lv_dummy               varchar2(255);
  lv_distributionpointid distributionpoint.distributionpoint_id%type;
  lv_relatedcustid       customer.customer_id%type;
begin
  makescan := 'Y';
  pack_sort.determinegarmentid('AMT', idcode, plantcode, uniqueitemid, pool, unitcode,
                               businessunitid, plantid_garment, returnedplantcode,
                               --not used for metric, but used for  AMT
                               status, idprimary, plantid_param, secondaryid);
  pack_sort.getsystemsettings(plantid_param, debuglevel, lv_dummy, allowrepairscan);
  if plantcode is null then
    plantcode := returnedplantcode;
  end if;
  begin
    ---------------------------------------------------------------
    --other fields
    if status = 0 then
      begin
        select s.code
        into   uistatus
        from   uniqueitem u, status s
        where  u.uniqueitem_id = uniqueitemid
        and    u.status_id = s.status_id;
        if uistatus in ('20', '30') then
          --flags
          for vcursor in (select o.confirm, f.priority, b.startdate, f.showalways, f.flag_id
                          from   uniqueitemflag b, flag f, flagoptions o, dialogs d
                          where  b.uniqueitem_id = uniqueitemid
                          and    b.flag_id = f.flag_id
                          and    f.flag_id = o.flag_id
                          and    o.dialog_id = d.dialog_id
                          and    d.code = 'OutScan'
                          and    o.show = 'Y'
                          and    (f.priority = 1 or f.showalways = 'Y')
                          and    b.startdate <= sysdate
                          order  by o.confirm desc, f.priority asc, b.startdate asc) loop
            begin
              select s.sortaddress
              into   sortaddressamt
              from   sortaddressperflag s
              where  s.flag_id = vcursor.flag_id
              and    s.plant_id = plantid_param;
              if sortaddressamt is not null then
                exit;
              end if;
            exception
              when no_data_found then
                null;
            end;
          end loop;
          if sortaddressamt is null then
            begin
              select g.sortaddress1
              into   sortaddressamt
              from   uniqueitemnonpool u, weareremployment e, garmentdispenser g
              where  u.uniqueitem_id = uniqueitemid
              and    u.weareremployment_id = e.weareremployment_id
              and    e.garmentdispenser_id = g.garmentdispenser_id
              and    g.sortaddress1 is not null;
              -- Locker sorting (extra for LIPS Emmen)
            exception
              when no_data_found then
                begin
                  select l.sortaddress
                  into   sortaddressamt
                  from   uniqueitemnonpool u, weareremployment e, locker l
                  where  u.uniqueitem_id = uniqueitemid
                  and    u.weareremployment_id = e.weareremployment_id
                  and    l.locker_id = e.locker_id
                  and    l.sortaddress is not null;
                exception
                  when no_data_found then
                    begin
                      select d.sortaddress
                      into   sortaddressamt
                      from   uniqueitemnonpool u, weareremployment e, distributionpoint di,
                             department d
                      where  u.uniqueitem_id = uniqueitemid
                      and    u.weareremployment_id = e.weareremployment_id
                      and    e.distributionpoint_id = di.distributionpoint_id
                      and    di.department_id = d.department_id
                      and    d.sortaddress is not null;
                  exception -- Extra on Wearerinventory level sorting from Remark-field
                    when no_data_found then
                      begin
                        select substr(ltrim(wi.remark),1,20)
                          into SortAddressAMT
                          from uniqueitemnonpool u,
                          weareremployment  e,
                          wearerinventory wi
                        where u.uniqueitem_id = uniqueitemid
                          and u.weareremployment_id = e.weareremployment_id
                          and    u.wearerinventory_id = wi.wearerinventory_id
                          and    wi.remark is not null;
                        exception
                          when no_data_found then
                            --order 501407
                            begin
                              select u.finishingmethod_id, u.sizedefinition_id, u.product_id,
                                     coalesce(u.distributionpoint_id,
                                               u.lastdistributionpoint_link_id),
                                     u.relatedcustomer_id
                              into   finishingmethodid, sizedefinitionid, productid,
                                     lv_distributionpointid, lv_relatedcustid
                              from   uniqueitem u
                              where  u.uniqueitem_id = uniqueitemid;
                              if pool = 1 then
                                begin
                                  --For pool always M
                                  makescan := 'N';
                                  if lv_distributionpointid is not null then
                                    begin
                                      select t.customer_id
                                      into   customerid
                                      from   distributionpoint dp
                                      join   department t
                                      on     t.department_id = dp.department_id
                                      where  dp.distributionpoint_id = lv_distributionpointid;
                                    end;
                                  else
                                    begin
                                      customerid := lv_relatedcustid;
                                    end;
                                  end if;
                                end;
                              elsif pool = 2 then
                                begin
                                  select c.customer_id
                                  into   customerid
                                  from   uniqueitemnonpool n, customer c, department d, wearer w,
                                         weareremployment e, distributionpoint di
                                  where  n.uniqueitem_id = uniqueitemid
                                  and    n.weareremployment_id = e.weareremployment_id
                                  and    e.wearer_id = w.wearer_id
                                  and    w.customer_id = c.customer_id
                                  and    e.distributionpoint_id = di.distributionpoint_id
                                  and    di.department_id = d.department_id;
                                exception
                                  when no_data_found then
                                    customerid := null;
                                end;
                              end if;
                          --if customerid is not null then
                          -- Start part: Extra check on single size and finishingmethod
                          -- in PLPC definition, otherwise use size * dd 22-03-2012
                          plpcid := f_getidcolumnfromactiveplpc(customerid, productid,
                                                                sizedefinitionid, finishingmethodid,
                                                                null, sysdate, 0);
                          if plpcid is null then
                            begin
                              select f.finishingmethod_id
                              into   specialfmethodid
                              from   finishingmethod f
                              where  f.code = 'TELLEN';
                                  plpcid := f_getidcolumnfromactiveplpc(customerid, productid,
                                                                        sizedefinitionid,
                                                                        specialfmethodid,
                                                                        sizedefinitionid, sysdate, 0);
                                end;
                              end if;
                              -- End part: Extra check on single size and finishingmethod
                              if plpcid is null then
                                begin
                                  select s.sizedefinition_id
                                  into   specialsizeid
                                  from   sizedefinition s
                              where  s.code = '*';
                              plpcid := f_getidcolumnfromactiveplpc(customerid, productid,
                                                                    sizedefinitionid,
                                                                    finishingmethodid, specialsizeid,
                                                                    sysdate, 0);
                            end;
                          end if;
                          select sp.sortaddress
                              into   sortaddressamt
                              from   sortaddressperprodpercust sp
                              where  sp.productlistpercustomer_id = plpcid
                              and    sp.plant_id = plantid_param
                              and    sp.sortaddress is not null;
                            exception
                              when no_data_found then
                                begin
                                  select sp.sortaddress
                                  into   sortaddressamt
                                  from   uniqueitem u, sortaddressperproduct sp
                                  where  u.uniqueitem_id = uniqueitemid
                                  and    u.product_id = sp.product_id
                                  and    sp.plant_id = plantid_param
                                  and    sp.sortaddress is not null;
                                exception
                                  when no_data_found then
                                    begin
                                      select sp.sortaddress
                                      into   sortaddressamt
                                      from   uniqueitem u, sortaddressperproductsize sp
                                      where  u.uniqueitem_id = uniqueitemid
                                      and    u.product_id = sp.product_id
                                      and    sp.plant_id = plantid_param
                                      and    u.sizedefinition_id = sp.sizedefinition_id
                                      and    sp.sortaddress is not null;
                                    exception
                                      when others then
                                    sortaddressamt := null;
                                    makescan       := 'Y'; --todo5860 make Y instead of N
                                    if debuglevel > 0 then
                                      pack_sort.write_logging(' IDCode ' || idcode ||
                                                              ' SortAddress not found, MakeScan ' ||
                                                              makescan || ' Status ' || status,
                                                              debuglevel,
                                                              'GETGARMENTDATALTS',
                                                              plantid_param, 3, 1);
                                    end if;
                                end;
                            end;
                        end;
                        end;
                    end;
                end;
            end;
          else
            --order501350
            makescan := 'N';
          end if;
        end if;
      end;
    else
      makescan := 'N';
    end if; --status=0
    sortaddress := sortaddressamt;
    if debuglevel > 0 then
      pack_sort.write_logging(' IDCode ' || idcode || ' SortAddress ' || sortaddressamt ||
                              ' MakeScan ' || makescan || ' Status ' || status, debuglevel,
                              'GETGARMENTDATALTS', plantid_param, 1, 1);
    end if;
  exception
    when others then
      begin
        sortaddress := null;
        makescan    := 'N';
        pack_sort.write_logging(' IDCode' || idcode || ' SortAddress ' || sortaddressamt ||
                                ' MakeScan ' || makescan || ' Status' || status || ' ' || sqlerrm,
                                debuglevel, 'GETGARMENTDATALTS', plantid_param, 3, 1);
      end;
  end;
end getgarmentdatalts;
/
create or replace procedure getgarmentdatametricon(idcode                      in uniqueitem.primaryid%type,
                                                   plantcode                   in plant.code%type,
                                                   status                      out nocopy integer,
                                                   finishselection             out nocopy varchar2, --(6),
                                                   checkpointselection         out nocopy varchar2, --(6),
                                                   repairselection             out nocopy varchar2, --(6),
                                                   destination                 out nocopy varchar2, --(6),
                                                   foldprogram                 out nocopy varchar2, --(6),
                                                   stackchangeinfo             out nocopy varchar2, --(60),
                                                   routenumber                 out nocopy route.routenumber%type,
                                                   routeday                    out nocopy route.drivingday_id%type,
                                                   unitcode                    out nocopy businessunit.code%type,
                                                   depot                       out nocopy depot.code%type,
                                                   sortstring                  out nocopy varchar2,
                                                   alternatesortstring         out nocopy varchar2,
                                                   stopnumber                  out nocopy routestop.stopnumber%type,
                                                   customernumber              out nocopy customer.customernumber%type,
                                                   customername                out nocopy customer.name%type,
                                                   wearernumber                out nocopy wearer.wearernumber%type,
                                                   wearername                  out nocopy wearer.searchname%type,
                                                   banklocker                  out nocopy varchar2,
                                                   department                  out nocopy department.departmentnumber%type,
                                                   customeremployeenumber      out nocopy wearer.customeremployeenumber%type,
                                                   gender                      out nocopy wearer.sex%type,
                                                   garmentdispensercode        out nocopy garmentdispenser.code%type,
                                                   deliverypointcode           out nocopy deliverypoint.code%type,
                                                   productcode                 out nocopy product.code%type,
                                                   productdescription          out nocopy product_desc.description%type,
                                                   sizecode                    out nocopy sizedefinition.code%type,
                                                   productpicturecode          out nocopy image.code%type,
                                                   deliverydaymask             out nocopy varchar2,
                                                   secondaryid                 out nocopy secondaryuniqueitem.secondaryid%type,
                                                   flagcode1                   out nocopy sortaddressperflag.sortaddress%type,
                                                   flagcode2                   out nocopy sortaddressperflag.sortaddress%type,
                                                   flagcode3                   out nocopy sortaddressperflag.sortaddress%type,
                                                   flagcode4                   out nocopy sortaddressperflag.sortaddress%type,
                                                   flagdescription1            out nocopy flag_desc.description%type,
                                                   flagdescription2            out nocopy flag_desc.description%type,
                                                   flagdescription3            out nocopy flag_desc.description%type,
                                                   flagdescription4            out nocopy flag_desc.description%type,
                                                   flagfreetext1               out nocopy uniqueitemflag.freetextitem%type,
                                                   flagfreetext2               out nocopy uniqueitemflag.freetextitem%type,
                                                   flagfreetext3               out nocopy uniqueitemflag.freetextitem%type,
                                                   flagfreetext4               out nocopy uniqueitemflag.freetextitem%type,
                                                   infotext                    out nocopy wearer.remark%type,
                                                   requiredrepairs             out nocopy varchar2,
                                                   spare1                      out nocopy varchar2,
                                                   spare2                      in out nocopy varchar2,
                                                   departmentdescription       out department.description%type,
                                                   consumptionpointcode        out distributionpoint.distributionpointnumber%type,
                                                   consumptionpointdescription out distributionpoint.description%type,
                                                   deliverypointdescription    out deliverypoint.description%type,
                                                   deliverypointstreet1        out address.street%type,
                                                   deliverypointstreet2        out address.street2%type,
                                                   deliverypointzipcode        out address.zipcode%type,
                                                   deliverypointcity           out address.city%type,
                                                   routecodeonlabel            out route.codeonlabel%type,
                                                   transportarticledescription out transportarticle_desc.description%type) is
  lv_databasecode        databasesettings.code%type;
  lv_customerranking     customerranking.ranking%type;
  lv_getgarmentdatabasic boolean;
  lv_poolitem            uniqueitem.poolitem%type;
  lv_productid           product.product_id%type;
  lv_uniqueitemid        uniqueitem.uniqueitem_id%type;
  lv_customerid          customer.customer_id%type;
  lv_langaugeid          languages.language_id%type;
  lv_distributionpointid distributionpoint.distributionpoint_id%type;
  lv_options2            externalgarmentsortdata.options2%type;
  lv_statusdate          externalgarmentsortdata.statusdate%type;
  lv_repairallowed       externalgarmentsortdata.repairallowed%type;

  function get_flagdesc(fp_flagcode in varchar2) return varchar2 is
  begin
    case fp_flagcode
      when 'R' then
        return 'Reparatur';
      when 'W' then
        return 'Nachwasche';
      when 'X' then
        return 'Umtausch';
      when 'V' then
        return 'Verminderung';
      when 'L' then
        return 'Labelanderung';
      when 'C' then
        return 'Kundenservice';
      when 'K' then
        return 'Bypass Kontrolle';
      else
        return null;
    end case;
  end get_flagdesc;

  procedure makefieldsnull is
  begin
    unitcode               := null;
    finishselection        := null;
    checkpointselection    := null;
    repairselection        := null;
    destination            := null;
    foldprogram            := null;
    stackchangeinfo        := null;
    routenumber            := null;
    routeday               := null;
    depot                  := null;
    sortstring             := null;
    alternatesortstring    := null;
    stopnumber             := null;
    customernumber         := null;
    customername           := null;
    wearernumber           := null;
    wearername             := null;
    banklocker             := null;
    department             := null;
    customeremployeenumber := null;
    gender                 := null;
    garmentdispensercode   := null;
    deliverypointcode      := null;
    productcode            := null;
    productdescription     := null;
    sizecode               := null;
    productpicturecode     := null;
    deliverydaymask        := null;
    secondaryid            := null;
    infotext               := null;
    requiredrepairs        := null;
    flagfreetext1          := null;
    flagfreetext2          := null;
    flagfreetext3          := null;
    flagfreetext4          := null;
    spare1                 := null;
    spare2                 := null;
  end makefieldsnull;
begin
  lv_getgarmentdatabasic := true;
  select t.code into lv_databasecode from databasesettings t;
  if lv_databasecode = 'SMG' then
    begin
      status := 0;
      if idcode in ('020', '101') then
        lv_getgarmentdatabasic := false;
      else
        begin
          begin
            --get uniqueitem
            select u.poolitem, u.uniqueitem_id, u.relatedcustomer_id, u.product_id,
                   nvl(u.distributionpoint_id, u.lastdistributionpoint_link_id), p.code, s.code,
                   bu.code
            into   lv_poolitem, lv_uniqueitemid, lv_customerid, lv_productid, lv_distributionpointid,
                   productcode, sizecode, unitcode
            from   uniqueitem u, product p, sizedefinition s, businessunit bu
            where  u.primaryid = idcode
            and    u.product_id = p.product_id
            and    u.sizedefinition_id = s.sizedefinition_id
            and    u.businessunit_id = bu.businessunit_id;
            --get customer id
            if lv_poolitem = 2 then
              select w.customer_id
              into   lv_customerid
              from   uniqueitemnonpool n, weareremployment e, wearer w
              where  n.uniqueitem_id = lv_uniqueitemid
              and    n.weareremployment_id = e.weareremployment_id
              and    e.wearer_id = w.wearer_id;
            else
              if lv_customerid is null and lv_distributionpointid is not null then
                select t.customer_id
                into   lv_customerid
                from   distributionpoint d, department t
                where  lv_distributionpointid = d.distributionpoint_id
                and    d.department_id = t.department_id;
              end if;
            end if;
          exception
            when no_data_found then
              lv_customerid := null;
            when others then
              lv_customerid := null;
          end;
          if lv_customerid is null then
            lv_customerranking := '-';
            makefieldsnull;
          else
            begin
              --get customer ranking
              select cr.ranking, c.language_id
              into   lv_customerranking, lv_langaugeid
              from   customer c
              left   outer join customerranking cr
              on     c.customerranking_id = cr.customerranking_id
              where  c.customer_id = lv_customerid;
            exception
              when no_data_found then
                lv_customerranking := '-';
            end;
          end if;
          --check send track itm
          if lv_customerranking = 'ITM' then
            begin
              --do NOT also use getgarmentdatabasic
              lv_getgarmentdatabasic := false;
              begin
                --get product description, customer langauge id
                select max(ds.description)
                into   productdescription
                from   product_desc ds
                where  ds.product_id = lv_productid
                and    ds.language_id = lv_langaugeid;
                --get externalgarmentsortdata information
                select folddestination, foldprogram, finisherprogram, to_number(routeid),
                       to_number(trim(substr(routeid, 2, 1))), customerid, customername, employeeid,
                       employeename, substr(sortcriteriainfo, 1, 12), options2, infotext1, infotext2,
                       statusdate, to_number(trim(substr(sortcriteriainfo, 1, 3))), sortcriteriainfo,
                       repaircolor, repairallowed
                into   destination, foldprogram, finishselection, routenumber, routeday,
                       customernumber, customername, wearernumber, wearername, stackchangeinfo,
                       lv_options2, flagfreetext1, flagfreetext2, lv_statusdate, stopnumber,
                       sortstring, repairselection, lv_repairallowed
                from   externalgarmentsortdata es
                where  es.garmentid = idcode
                and    es.timestamp >= sysdate - 7; ---only accept entries 1 week old
                if lv_repairallowed = 0 then
                  begin
                    repairselection := null; --no repair allowed, no repair selection
                  end;
                end if;
              exception
                when no_data_found then
                  begin
                    lv_statusdate := null;
                    lv_options2   := null;
                    status        := 1;
                    makefieldsnull;
                  end;
              end;
              --check scan interval time with lv_statusdate
              if lv_statusdate is not null then
                begin
                  if trunc(sysdate) - lv_statusdate > 7 then
                    begin
                      status := 1;
                      makefieldsnull;
                    end;
                  end if;
                end;
              end if;
              --get flag information
              if lv_options2 is null or status = 1 then
                flagcode1        := null;
                flagcode2        := null;
                flagcode3        := null;
                flagcode4        := null;
                flagdescription1 := null;
                flagdescription2 := null;
                flagdescription3 := null;
                flagdescription4 := null;
              else
                flagcode1        := substr(lv_options2, 1, 1);
                flagcode2        := substr(lv_options2, 2, 1);
                flagcode3        := substr(lv_options2, 3, 1);
                flagcode4        := substr(lv_options2, 4, 1);
                flagdescription1 := get_flagdesc(flagcode1);
                flagdescription2 := get_flagdesc(flagcode2);
                flagdescription3 := get_flagdesc(flagcode3);
                flagdescription4 := get_flagdesc(flagcode4);
              end if;
            end;
          end if;
        end;
      end if;
    end;
  end if;
  if lv_getgarmentdatabasic then
    --normal process getgarmentdatabasic
    getgarmentdatabasic(idcode, plantcode, unitcode, status, finishselection, checkpointselection,
                        repairselection, destination, foldprogram, stackchangeinfo, routenumber,
                        routeday, depot, sortstring, alternatesortstring, stopnumber, customernumber,
                        customername, wearernumber, wearername, banklocker, department,
                        customeremployeenumber, gender, garmentdispensercode, deliverypointcode,
                        productcode, productdescription, sizecode, productpicturecode,
                        deliverydaymask, secondaryid, flagcode1, flagcode2, flagcode3, flagcode4,
                        flagdescription1, flagdescription2, flagdescription3, flagdescription4,
                        infotext, requiredrepairs, spare1, spare2, flagfreetext1, flagfreetext2,
                        flagfreetext3, flagfreetext4, routecodeonlabel, 'Y', 'N');
    pack_sort.getadditionalabelinfo(idcode, unitcode, deliverypointcode, departmentdescription,
                                    consumptionpointcode, consumptionpointdescription,
                                    deliverypointdescription, deliverypointstreet1,
                                    deliverypointstreet2, deliverypointzipcode, deliverypointcity,
                                    transportarticledescription);
  end if;
end getgarmentdatametricon;
/
create or replace procedure getgarmentdatametricon2(idcode                      in uniqueitem.primaryid%type,
                                                    plantcode                   in plant.code%type,
                                                    status                      out nocopy integer,
                                                    finishselection             out nocopy varchar2, --(6),
                                                    checkpointselection         out nocopy varchar2, --(6),
                                                    repairselection             out nocopy varchar2, --(6),
                                                    destination                 out nocopy varchar2, --(6),
                                                    foldprogram                 out nocopy varchar2, --(6),
                                                    stackchangeinfo             out nocopy varchar2, --(60),
                                                    routenumber                 out nocopy route.routenumber%type,
                                                    routeday                    out nocopy route.drivingday_id%type,
                                                    unitcode                    out nocopy businessunit.code%type,
                                                    depot                       out nocopy depot.code%type,
                                                    sortstring                  out nocopy varchar2,
                                                    alternatesortstring         out nocopy varchar2,
                                                    stopnumber                  out nocopy routestop.stopnumber%type,
                                                    customernumber              out nocopy customer.customernumber%type,
                                                    customername                out nocopy customer.name%type,
                                                    wearernumber                out nocopy wearer.wearernumber%type,
                                                    wearername                  out nocopy wearer.searchname%type,
                                                    banklocker                  out nocopy varchar2,
                                                    department                  out nocopy department.departmentnumber%type,
                                                    customeremployeenumber      out nocopy wearer.customeremployeenumber%type,
                                                    gender                      out nocopy wearer.sex%type,
                                                    garmentdispensercode        out nocopy garmentdispenser.code%type,
                                                    deliverypointcode           out nocopy deliverypoint.code%type,
                                                    productcode                 out nocopy product.code%type,
                                                    productdescription          out nocopy product_desc.description%type,
                                                    sizecode                    out nocopy sizedefinition.code%type,
                                                    productpicturecode          out nocopy image.code%type,
                                                    deliverydaymask             out nocopy varchar2,
                                                    secondaryid                 out nocopy secondaryuniqueitem.secondaryid%type,
                                                    flagcode1                   out nocopy sortaddressperflag.sortaddress%type,
                                                    flagcode2                   out nocopy sortaddressperflag.sortaddress%type,
                                                    flagcode3                   out nocopy sortaddressperflag.sortaddress%type,
                                                    flagcode4                   out nocopy sortaddressperflag.sortaddress%type,
                                                    flagdescription1            out nocopy flag_desc.description%type,
                                                    flagdescription2            out nocopy flag_desc.description%type,
                                                    flagdescription3            out nocopy flag_desc.description%type,
                                                    flagdescription4            out nocopy flag_desc.description%type,
                                                    flagfreetext1               out nocopy uniqueitemflag.freetextitem%type,
                                                    flagfreetext2               out nocopy uniqueitemflag.freetextitem%type,
                                                    flagfreetext3               out nocopy uniqueitemflag.freetextitem%type,
                                                    flagfreetext4               out nocopy uniqueitemflag.freetextitem%type,
                                                    infotext                    out nocopy wearer.remark%type,
                                                    requiredrepairs             out nocopy varchar2,
                                                    spare1                      out nocopy varchar2,
                                                    spare2                      in out nocopy varchar2,
                                                    departmentdescription       out nocopy department.description%type,
                                                    consumptionpointcode        out nocopy distributionpoint.distributionpointnumber%type,
                                                    consumptionpointdescription out nocopy distributionpoint.description%type,
                                                    deliverypointdescription    out nocopy deliverypoint.description%type,
                                                    deliverypointstreet1        out nocopy address.street%type,
                                                    deliverypointstreet2        out nocopy address.street2%type,
                                                    deliverypointzipcode        out nocopy address.zipcode%type,
                                                    deliverypointcity           out nocopy address.city%type,
                                                    routecodeonlabel            out nocopy route.codeonlabel%type,
                                                    transportarticledescription out nocopy transportarticle_desc.description%type,
                                                    imagecode                   out nocopy image.code%type,
                                                    repaircodes                 out nocopy varchar2,
                                                    repairxcoordinates          out nocopy varchar2,
                                                    repairycoordinates          out nocopy varchar2,
                                                    residualvalue               out number) is
  lv_counter             number := 0;
  lv_databasecode        databasesettings.code%type;
  lv_finishingmethodcode finishingmethod.code%type;

  procedure set_defaultstockvalues is
  begin
    --set_defaultstockvalues
    checkpointselection         := null;
    repairselection             := null;
    stackchangeinfo             := null;
    routenumber                 := 9999;
    routeday                    := getabsdaynumber(sysdate);
    alternatesortstring         := null;
    stopnumber                  := 999;
    customernumber              := 9999;
    customername                := 'STOCK';
    department                  := null;
    wearernumber                := null;
    wearername                  := null;
    banklocker                  := null;
    customeremployeenumber      := null;
    gender                      := null;
    deliverypointcode           := null;
    garmentdispensercode        := null;
    flagcode1                   := null;
    flagcode2                   := null;
    flagcode3                   := null;
    flagcode4                   := null;
    flagdescription1            := null;
    flagdescription2            := null;
    flagdescription3            := null;
    flagdescription4            := null;
    infotext                    := null;
    requiredrepairs             := null;
    spare1                      := null;
    spare2                      := null;
    flagfreetext1               := null;
    flagfreetext2               := null;
    flagfreetext3               := null;
    flagfreetext4               := null;
    departmentdescription       := null;
    consumptionpointcode        := null;
    consumptionpointdescription := null;
    deliverypointdescription    := null;
    deliverypointstreet1        := null;
    deliverypointstreet2        := null;
    deliverypointzipcode        := null;
    deliverypointcity           := null;
    routecodeonlabel            := null;
    transportarticledescription := null;
    imagecode                   := null;
    repaircodes                 := null;
    repairxcoordinates          := null;
    repairycoordinates          := null;
    residualvalue               := null;
  end set_defaultstockvalues;
begin
  --normal process getgarmentdatabasic
  getgarmentdatabasic(idcode, plantcode, unitcode, status, finishselection, checkpointselection,
                      repairselection, destination, foldprogram, stackchangeinfo, routenumber,
                      routeday, depot, sortstring, alternatesortstring, stopnumber, customernumber,
                      customername, wearernumber, wearername, banklocker, department,
                      customeremployeenumber, gender, garmentdispensercode, deliverypointcode,
                      productcode, productdescription, sizecode, productpicturecode, deliverydaymask,
                      secondaryid, flagcode1, flagcode2, flagcode3, flagcode4, flagdescription1,
                      flagdescription2, flagdescription3, flagdescription4, infotext,
                      requiredrepairs, spare1, spare2, flagfreetext1, flagfreetext2, flagfreetext3,
                      flagfreetext4, routecodeonlabel, 'Y', 'N');
  if (customernumber = 0 and (routenumber = 0 or routenumber is null)) then
    begin
      customernumber := 9999;
      routenumber    := 999;
      routeday       := 9;
      customername   := 'POOL';
    end;
  end if;
  --get image code
  select max(i.code)
  into   imagecode
  from   product p
  join   image i
  on     i.image_id = p.image_id
  where  p.code = productcode;
  --get database code
  select max(t.code) into lv_databasecode from databasesettings t;
  --get residual value and repair codes / info
  for x in (select nvl((select lpad(to_char(prt.exportcode), 2, '0')
                        from   plantrepairtypesettings prt
                        where  prt.repairtype_id = rp.repairtype_id
                        and    prt.plant_id = pt.plant_id), lpad(to_char(rt.code), 2, '0')) repairtypecode,
                   rp.xpercentage, rp.ypercentage, u.residualvalueamount, u.poolitem, bu.plant_id,
                   st.code stockroomcode, stl.rowcode, stl.locationcode, u.finishingmethod_id,
                   substr(w.fullname, 1, 25) fullname, u.customerowned, c.chargerepairs,
                   c.chargerepaircog
            from   uniqueitem u
            join   businessunit bu
            on     bu.businessunit_id = u.businessunit_id
            join   plant pt
            on     pt.plant_id = bu.plant_id
            left   outer join(repairpointer rp
            join   repairtype rt
            on     rt.repairtype_id = rp.repairtype_id) on rp.uniqueitem_id = u.uniqueitem_id
            join   uniqueitemfixedinfo ufi
            on     ufi.uniqueitem_id = u.uniqueitem_id
            left   outer join(stockroomlocation stl
            join   stockroom st
            on     st.stockroom_id = stl.stockroom_id) on stl.stockroomlocation_id = ufi.stockroomlocation_id
            left   outer join(uniqueitemnonpool un
            join   weareremployment we
            on     we.weareremployment_id = un.weareremployment_id
            join   wearer w
            on     w.wearer_id = we.wearer_id
            join   customer c
            on     c.customer_id = w.customer_id) on un.uniqueitem_id = u.uniqueitem_id
            where  u.primaryid = idcode
            and    (pt.code = plantcode or plantcode is null)
            order  by rp.sequencenumber asc) loop
    begin
      if lv_databasecode = 'CBD' then
        --ABS-8993
        spare1 := case
                    when x.customerowned = 'Y' and x.chargerepaircog in (1, 2) then
                     '1'
                    when x.customerowned = 'N' and x.chargerepairs in (1, 2) then
                     '2'
                    when x.customerowned = 'Y' and x.chargerepaircog = 0 then
                     '3'
                    when x.customerowned = 'N' and x.chargerepairs = 0 then
                     '4'
                    else
                     null
                  end;
      end if;
      if x.poolitem = 0 then
        begin
          --For uniqueitems on stock repair info NOT needed
          --And return different (default) values!!
          set_defaultstockvalues;
          sortstring := nvl(rpad(x.stockroomcode, 12, ' ') || rpad(x.rowcode, 12, ' ') ||
                            rpad(x.locationcode, 12, ' '), rpad(' ', 36, ' ')) ||
                        rpad(productcode, 12, ' ') || rpad(sizecode, 12, ' ');
          --Fill destination with value of system setting SORTSTOCKROOMDESTINATION
          select nvl(min(s.value), '0')
          into   destination
          from   systemsetting s
          where  s.plant_id = x.plant_id
          and    s.name = 'SORTSTOCKROOMDESTINATION';
          if lv_databasecode = 'CBD' then
            begin
              flagcode1        := 'K';
              flagdescription1 := 'STOCKROOM';
              --NEW BEGIN
              if foldprogram is null then
                begin
                  select max(fp.foldingprogram)
                  into   foldprogram
                  from   foldingprogramdefinition fp
                  where  fp.product_id =
                         (select p.product_id from product p where p.code = productcode)
                  and    fp.finishingmethod_id =
                         (select f.finishingmethod_id from finishingmethod f where f.code = 'G');
                end;
              end if;
              --NEW END
            end;
          end if;
          exit;
        end;
      else
        begin
          --diff. wearername full name first 25
          wearername  := x.fullname;
          repaircodes := repaircodes || x.repairtypecode;
          if x.xpercentage >= 100 then
            repairxcoordinates := repairxcoordinates || '99';
          else
            repairxcoordinates := repairxcoordinates || lpad(to_char(x.xpercentage), 2, '0');
          end if;
          if x.ypercentage >= 100 then
            repairycoordinates := repairycoordinates || '99';
          else
            repairycoordinates := repairycoordinates || lpad(to_char(x.ypercentage), 2, '0');
          end if;
          residualvalue := x.residualvalueamount;
          lv_counter    := lv_counter + 1;
          --special CBD request part
          if lv_databasecode = 'CBD' and flagcode1 is null then
            begin
              select max(f.code)
              into   lv_finishingmethodcode
              from   finishingmethod f
              where  f.finishingmethod_id = x.finishingmethod_id;
              if lv_finishingmethodcode = 'GEBH' then
                begin
                  flagcode1        := 'M';
                  flagdescription1 := 'Hand gebügelt hängend';
                end;
              end if;
            end;
          end if;
        end;
      end if;
      exit when lv_counter >= 10;
    end;
  end loop; --x
  --get getadditionalabelinfo
  pack_sort.getadditionalabelinfo(idcode, unitcode, deliverypointcode, departmentdescription,
                                  consumptionpointcode, consumptionpointdescription,
                                  deliverypointdescription, deliverypointstreet1,
                                  deliverypointstreet2, deliverypointzipcode, deliverypointcity,
                                  transportarticledescription);
end getgarmentdatametricon2;
/
create or replace procedure getgarmentdatametricon3(idcode                      in uniqueitem.primaryid%type,
                                                    plantcode                   in plant.code%type,
                                                    status                      out nocopy integer,
                                                    finishselection             out nocopy varchar2, --(6),
                                                    checkpointselection         out nocopy varchar2, --(6),
                                                    repairselection             out nocopy varchar2, --(6),
                                                    destination                 out nocopy varchar2, --(6),
                                                    foldprogram                 out nocopy varchar2, --(6),
                                                    stackchangeinfo             out nocopy varchar2, --(60),
                                                    routenumber                 out nocopy route.routenumber%type,
                                                    routeday                    out nocopy route.drivingday_id%type,
                                                    unitcode                    out nocopy businessunit.code%type,
                                                    depot                       out nocopy depot.code%type,
                                                    sortstring                  out nocopy varchar2,
                                                    alternatesortstring         out nocopy varchar2,
                                                    stopnumber                  out nocopy routestop.stopnumber%type,
                                                    customernumber              out nocopy customer.customernumber%type,
                                                    customername                out nocopy customer.name%type,
                                                    wearernumber                out nocopy wearer.wearernumber%type,
                                                    wearername                  out nocopy wearer.searchname%type,
                                                    banklocker                  out nocopy varchar2,
                                                    department                  out nocopy department.departmentnumber%type,
                                                    customeremployeenumber      out nocopy wearer.customeremployeenumber%type,
                                                    gender                      out nocopy wearer.sex%type,
                                                    garmentdispensercode        out nocopy garmentdispenser.code%type,
                                                    deliverypointcode           out nocopy deliverypoint.code%type,
                                                    productcode                 out nocopy product.code%type,
                                                    productdescription          out nocopy product_desc.description%type,
                                                    sizecode                    out nocopy sizedefinition.code%type,
                                                    productpicturecode          out nocopy image.code%type,
                                                    deliverydaymask             out nocopy varchar2,
                                                    secondaryid                 out nocopy secondaryuniqueitem.secondaryid%type,
                                                    flagcode1                   out nocopy sortaddressperflag.sortaddress%type,
                                                    flagcode2                   out nocopy sortaddressperflag.sortaddress%type,
                                                    flagcode3                   out nocopy sortaddressperflag.sortaddress%type,
                                                    flagcode4                   out nocopy sortaddressperflag.sortaddress%type,
                                                    flagdescription1            out nocopy flag_desc.description%type,
                                                    flagdescription2            out nocopy flag_desc.description%type,
                                                    flagdescription3            out nocopy flag_desc.description%type,
                                                    flagdescription4            out nocopy flag_desc.description%type,
                                                    flagfreetext1               out nocopy uniqueitemflag.freetextitem%type,
                                                    flagfreetext2               out nocopy uniqueitemflag.freetextitem%type,
                                                    flagfreetext3               out nocopy uniqueitemflag.freetextitem%type,
                                                    flagfreetext4               out nocopy uniqueitemflag.freetextitem%type,
                                                    infotext                    out nocopy wearer.remark%type,
                                                    requiredrepairs             out nocopy varchar2,
                                                    spare1                      out nocopy varchar2,
                                                    spare2                      in out nocopy varchar2,
                                                    departmentdescription       out nocopy department.description%type,
                                                    consumptionpointcode        out nocopy distributionpoint.distributionpointnumber%type,
                                                    consumptionpointdescription out nocopy distributionpoint.description%type,
                                                    deliverypointdescription    out nocopy deliverypoint.description%type,
                                                    deliverypointstreet1        out nocopy address.street%type,
                                                    deliverypointstreet2        out nocopy address.street2%type,
                                                    deliverypointzipcode        out nocopy address.zipcode%type,
                                                    deliverypointcity           out nocopy address.city%type,
                                                    routecodeonlabel            out nocopy route.codeonlabel%type,
                                                    transportarticledescription out nocopy transportarticle_desc.description%type,
                                                    imagecode                   out nocopy image.code%type,
                                                    repaircodes                 out nocopy varchar2,
                                                    repairxcoordinates          out nocopy varchar2,
                                                    repairycoordinates          out nocopy varchar2,
                                                    residualvalue               out number,
                                                    userinstructionsloading     out nocopy varchar2,
                                                    userinstructionscheckpoint  out nocopy varchar2,
                                                    userinstructionsrepair      out nocopy varchar2,
                                                    userinstructionsdivorce     out nocopy varchar2,
                                                    customerrankingdesc         out nocopy varchar2) is
  -- Procedure GetGarmentDataMetricon3 Version 2.3
  -- ABSN-4339 Adjust Metricon get garment data for CUL
  -- ABSN-5268 GetGarmentDataMetricon3 performance
  lv_counter                number := 0;
  lv_databasecode           databasesettings.code%type;
  lv_overalluniquegarmentid databasesettings.overalluniquegarmentid%type;
  lv_finishingmethodcode    finishingmethod.code%type;

  procedure set_defaultstockvalues is
  begin
    --set_defaultstockvalues
    checkpointselection         := null;
    repairselection             := null;
    stackchangeinfo             := null;
    routenumber                 := 9999;
    routeday                    := getabsdaynumber(sysdate);
    alternatesortstring         := null;
    stopnumber                  := 999;
    customernumber              := 9999;
    customername                := 'STOCK';
    department                  := null;
    wearernumber                := null;
    wearername                  := null;
    banklocker                  := null;
    customeremployeenumber      := null;
    gender                      := null;
    deliverypointcode           := null;
    garmentdispensercode        := null;
    flagcode1                   := null;
    flagcode2                   := null;
    flagcode3                   := null;
    flagcode4                   := null;
    flagdescription1            := null;
    flagdescription2            := null;
    flagdescription3            := null;
    flagdescription4            := null;
    infotext                    := null;
    requiredrepairs             := null;
    spare1                      := null;
    spare2                      := null;
    flagfreetext1               := null;
    flagfreetext2               := null;
    flagfreetext3               := null;
    flagfreetext4               := null;
    departmentdescription       := null;
    consumptionpointcode        := null;
    consumptionpointdescription := null;
    deliverypointdescription    := null;
    deliverypointstreet1        := null;
    deliverypointstreet2        := null;
    deliverypointzipcode        := null;
    deliverypointcity           := null;
    routecodeonlabel            := null;
    transportarticledescription := null;
    imagecode                   := null;
    repaircodes                 := null;
    repairxcoordinates          := null;
    repairycoordinates          := null;
    residualvalue               := null;
  end set_defaultstockvalues;

  procedure get_userinstructions is
    lv_customernumber customer.customernumber%type;
    lv_languageid     languages.language_id%type;
  begin
    --get_userinstructions
    begin
      --get language id plant
      select pt.language_id into lv_languageid from plant pt where pt.code = plantcode;
    exception
      when no_data_found then
        begin
          --not found take first language found
          select min(l.language_id) into lv_languageid from languages l;
        end;
    end;
    --needed because customernumber is also a field!!
    lv_customernumber := customernumber;
    --get customerrankingdesc
    select max(cr.ranking)
    into   customerrankingdesc
    from   customer c
    join   customerranking cr
    on     cr.customerranking_id = c.customerranking_id
    where  c.customernumber = lv_customernumber;
    --get userinstructionsloading
    userinstructionsloading := null;
    for a in (select 1 prio, cui.dateactive,
                     (select dbms_lob.substr(cuide.instruction, 80, 1)
                       from   customeruserinstruction_desc cuide
                       where  cuide.customeruserinstruction_id = us.customeruserinstruction_id
                       and    cuide.language_id = lv_languageid) instruction
              from   userinstructionperscreen us
              join   customeruserinstruction cui
              on     (cui.customeruserinstruction_id = us.customeruserinstruction_id and
                     sysdate between cui.dateactive and cui.dateinactive and
                     sysdate < cui.enddateautomsg)
              join   customer c
              on     (c.customer_id = cui.customer_id and c.customernumber = lv_customernumber)
              where  us.dialog_id =
                     (select pdf.dialog_id from dialogs pdf where pdf.code = 'SortingSystemLoading')
              union
              select 2 prio, gui.dateactive,
                     (select dbms_lob.substr(guide.instruction, 80, 1)
                       from   generaluserinstruction_desc guide
                       where  guide.generaluserinstruction_id = us.generaluserinstruction_id
                       and    guide.language_id = lv_languageid) instruction
              from   userinstructionperscreen us
              join   generaluserinstructionpercust guc
              on     guc.generaluserinstruction_id = us.generaluserinstruction_id
              join   customer c
              on     (c.customer_id = guc.customer_id and c.customernumber = lv_customernumber)
              join   generaluserinstruction gui
              on     (gui.generaluserinstruction_id = us.generaluserinstruction_id and
                     sysdate between gui.dateactive and gui.dateinactive and
                     sysdate < gui.enddateautomsg)
              where  us.dialog_id =
                     (select pdf.dialog_id from dialogs pdf where pdf.code = 'SortingSystemLoading')
              order  by 1, 2 desc) loop
      begin
        userinstructionsloading := a.instruction;
        exit;
      end;
    end loop;
    --SortingSystemCheckpoint
    userinstructionscheckpoint := null;
    for b in (select 1 prio, cui.dateactive,
                     (select dbms_lob.substr(cuide.instruction, 80, 1)
                       from   customeruserinstruction_desc cuide
                       where  cuide.customeruserinstruction_id = us.customeruserinstruction_id
                       and    cuide.language_id = lv_languageid) instruction
              from   userinstructionperscreen us
              join   customeruserinstruction cui
              on     (cui.customeruserinstruction_id = us.customeruserinstruction_id and
                     sysdate between cui.dateactive and cui.dateinactive and
                     sysdate < cui.enddateautomsg)
              join   customer c
              on     (c.customer_id = cui.customer_id and c.customernumber = lv_customernumber)
              where  us.dialog_id = (select pdf.dialog_id
                                     from   dialogs pdf
                                     where  pdf.code = 'SortingSystemCheckpoint')
              union
              select 2 prio, gui.dateactive,
                     (select dbms_lob.substr(guide.instruction, 80, 1)
                       from   generaluserinstruction_desc guide
                       where  guide.generaluserinstruction_id = us.generaluserinstruction_id
                       and    guide.language_id = lv_languageid) instruction
              from   userinstructionperscreen us
              join   generaluserinstructionpercust guc
              on     guc.generaluserinstruction_id = us.generaluserinstruction_id
              join   customer c
              on     (c.customer_id = guc.customer_id and c.customernumber = lv_customernumber)
              join   generaluserinstruction gui
              on     (gui.generaluserinstruction_id = us.generaluserinstruction_id and
                     sysdate between gui.dateactive and gui.dateinactive and
                     sysdate < gui.enddateautomsg)
              where  us.dialog_id = (select pdf.dialog_id
                                     from   dialogs pdf
                                     where  pdf.code = 'SortingSystemCheckpoint')
              order  by 1, 2 desc) loop
      begin
        userinstructionscheckpoint := b.instruction;
        exit;
      end;
    end loop;
    --SortingSystemRepair
    userinstructionsrepair := null;
    for c in (select 1 prio, cui.dateactive,
                     (select dbms_lob.substr(cuide.instruction, 80, 1)
                       from   customeruserinstruction_desc cuide
                       where  cuide.customeruserinstruction_id = us.customeruserinstruction_id
                       and    cuide.language_id = lv_languageid) instruction
              from   userinstructionperscreen us
              join   customeruserinstruction cui
              on     (cui.customeruserinstruction_id = us.customeruserinstruction_id and
                     sysdate between cui.dateactive and cui.dateinactive and
                     sysdate < cui.enddateautomsg)
              join   customer c
              on     (c.customer_id = cui.customer_id and c.customernumber = lv_customernumber)
              where  us.dialog_id =
                     (select pdf.dialog_id from dialogs pdf where pdf.code = 'SortingSystemRepair')
              union
              select 2 prio, gui.dateactive,
                     (select dbms_lob.substr(guide.instruction, 80, 1)
                       from   generaluserinstruction_desc guide
                       where  guide.generaluserinstruction_id = us.generaluserinstruction_id
                       and    guide.language_id = lv_languageid) instruction
              from   userinstructionperscreen us
              join   generaluserinstructionpercust guc
              on     guc.generaluserinstruction_id = us.generaluserinstruction_id
              join   customer c
              on     (c.customer_id = guc.customer_id and c.customernumber = lv_customernumber)
              join   generaluserinstruction gui
              on     (gui.generaluserinstruction_id = us.generaluserinstruction_id and
                     sysdate between gui.dateactive and gui.dateinactive and
                     sysdate < gui.enddateautomsg)
              where  us.dialog_id =
                     (select pdf.dialog_id from dialogs pdf where pdf.code = 'SortingSystemRepair')
              order  by 1, 2 desc) loop
      begin
        userinstructionsrepair := c.instruction;
        exit;
      end;
    end loop;
    --SortingSystemDivorce
    userinstructionsdivorce := null;
    for d in (select 1 prio, cui.dateactive,
                     (select dbms_lob.substr(cuide.instruction, 80, 1)
                       from   customeruserinstruction_desc cuide
                       where  cuide.customeruserinstruction_id = us.customeruserinstruction_id
                       and    cuide.language_id = lv_languageid) instruction
              from   userinstructionperscreen us
              join   customeruserinstruction cui
              on     (cui.customeruserinstruction_id = us.customeruserinstruction_id and
                     sysdate between cui.dateactive and cui.dateinactive and
                     sysdate < cui.enddateautomsg)
              join   customer c
              on     (c.customer_id = cui.customer_id and c.customernumber = lv_customernumber)
              where  us.dialog_id =
                     (select pdf.dialog_id from dialogs pdf where pdf.code = 'SortingSystemDivorce')
              union
              select 2 prio, gui.dateactive,
                     (select dbms_lob.substr(guide.instruction, 80, 1)
                       from   generaluserinstruction_desc guide
                       where  guide.generaluserinstruction_id = us.generaluserinstruction_id
                       and    guide.language_id = lv_languageid) instruction
              from   userinstructionperscreen us
              join   generaluserinstructionpercust guc
              on     guc.generaluserinstruction_id = us.generaluserinstruction_id
              join   customer c
              on     (c.customer_id = guc.customer_id and c.customernumber = lv_customernumber)
              join   generaluserinstruction gui
              on     (gui.generaluserinstruction_id = us.generaluserinstruction_id and
                     sysdate between gui.dateactive and gui.dateinactive and
                     sysdate < gui.enddateautomsg)
              where  us.dialog_id =
                     (select pdf.dialog_id from dialogs pdf where pdf.code = 'SortingSystemDivorce')
              order  by 1, 2 desc) loop
      begin
        userinstructionsdivorce := d.instruction;
        exit;
      end;
    end loop;
  end get_userinstructions;

  procedure create_ragged_delscan is
    lv_rec_raggeditem    raggeditem%rowtype;
    lv_plantdepartmentid plantdepartment.plantdepartment_id%type;

    procedure get_plant_lw is
    begin
      --get_plant_lw
      select pd.plantdepartment_id
      into   lv_plantdepartmentid
      from   plant pt
      join   plantdepartment pd
      on     pd.plant_id = pt.plant_id
      where  pt.code = plantcode
      and    pd.code = 'LW';
    end get_plant_lw;

    procedure get_raggeditem is
      procedure get_nonuniqueitem is
      begin
        --get_nonuniqueitem
        for x in (select rgi.*
                  from   raggeditem rgi
                  where  rgi.primaryid = idcode
                  order  by rgi.ragtimestamp desc) loop
          begin
            lv_rec_raggeditem := x;
            exit;
          end;
        end loop; --x
        if lv_rec_raggeditem.raggeditem_id is null then
          begin
            for y in (select rgi.*
                      from   raggeditem rgi
                      where  rgi.secondaryid = idcode
                      order  by rgi.ragtimestamp desc) loop
              begin
                lv_rec_raggeditem := y;
                exit;
              end;
            end loop; --x
          end;
        end if;
      end get_nonuniqueitem;
    begin
      --get_raggeditem
      lv_rec_raggeditem.raggeditem_id := null;
      if nvl(lv_overalluniquegarmentid, 'N') = 'Y' then
        begin
          get_nonuniqueitem;
        end;
      else
        begin
          for x in (select rgi.*
                    from   raggeditem rgi
                    join   businessunit bu
                    on     bu.businessunit_id = rgi.businessunit_id
                    join   plant pt
                    on     pt.plant_id = bu.plant_id
                    where  rgi.primaryid = idcode
                    and    pt.code = plantcode
                    order  by rgi.ragtimestamp desc) loop
            begin
              lv_rec_raggeditem := x;
              exit;
            end;
          end loop; --x
          if lv_rec_raggeditem.raggeditem_id is null then
            begin
              for y in (select rgi.*
                        from   raggeditem rgi
                        join   businessunit bu
                        on     bu.businessunit_id = rgi.businessunit_id
                        join   plant pt
                        on     pt.plant_id = bu.plant_id
                        where  rgi.secondaryid = idcode
                        and    pt.code = plantcode
                        order  by rgi.ragtimestamp desc) loop
                begin
                  lv_rec_raggeditem := y;
                  exit;
                end;
              end loop; --x
            end;
          end if;
          if lv_rec_raggeditem.raggeditem_id is null then
            begin
              --check is it might be an unique item anyway..
              get_nonuniqueitem;
            end;
          end if;
        end;
      end if;
    end get_raggeditem;

    procedure create_deliveryscan is
    begin
      --create_deliveryscan
      if lv_rec_raggeditem.poolitem = 2 then
        begin
          --create a deliveryscan for TODAY trunc(sysdate)
          --so no 2 deliveryscans can be made when scanned more then once
          insert into deliveryscan
            (businessunit_id, uniqueitem_link_id, scantimestamp, customer_link_id,
             weareremployment_link_id, distributionpoint_link_id, deliverypoint_link_id,
             product_link_id, sizedefinition_link_id, finishingmethod_id, routecontrol_id,
             packingnote_id, fromstock, previousstay_id, systemuser_id, timestamp, reasoncode_id,
             plantdepartment_id, chargewashing, locker_id, batchnumber, outscannodelivery,
             internalprocessingbu_id, wearerinvoicecategory_id, planneddeliverydate, scanstation,
             garmentbatch_id, pool_packingnote_id)
            select lv_rec_raggeditem.businessunit_id, lv_rec_raggeditem.raggeditem_id,
                   trunc(sysdate), w.customer_id, we.weareremployment_id, we.distributionpoint_id,
                   dp.deliverypoint_id, lv_rec_raggeditem.product_link_id,
                   lv_rec_raggeditem.sizedefinition_link_id,
                   nvl(lv_rec_raggeditem.finishingmethod_id, wi.finishingmethod_id), null, null, 'N',
                   lv_rec_raggeditem.prevstay_id, lv_rec_raggeditem.systemuser_id, sysdate,
                   lv_rec_raggeditem.reasoncode_id, lv_plantdepartmentid, 'Y', we.locker_id, null, 0,
                   lv_rec_raggeditem.businessunit_id, null, null, 'GETGARMENT', null, null
            from   weareremployment we
            join   wearer w
            on     w.wearer_id = we.wearer_id
            join   distributionpoint dp
            on     dp.distributionpoint_id = we.distributionpoint_id
            join   wearerinventory wi
            on     wi.weareremployment_id = we.weareremployment_id
            and    wi.product_id = lv_rec_raggeditem.product_link_id
            and    wi.sizedefinition_id = lv_rec_raggeditem.sizedefinition_link_id
            where  we.weareremployment_id = lv_rec_raggeditem.weareremployment_link_id;
          --commit when ok
          commit;
        exception
          when dup_val_on_index then
            begin
              --ok deliveryscan was already made
              rollback;
            end;
        end;
      end if;
    end create_deliveryscan;
  begin
    --get_plant_lw
    get_plant_lw;
    --create_ragged_delscan
    get_raggeditem;
    --create deliveryscan
    create_deliveryscan;
  exception
    when no_data_found then
      null; --no problem, no item found nothing to be done
  end create_ragged_delscan;
begin
  --get database code
  select max(t.code), max(t.overalluniquegarmentid)
  into   lv_databasecode, lv_overalluniquegarmentid
  from   databasesettings t;
  --normal process getgarmentdatabasic
  getgarmentdatabasic(idcode, plantcode, unitcode, status, finishselection, checkpointselection,
                      repairselection, destination, foldprogram, stackchangeinfo, routenumber,
                      routeday, depot, sortstring, alternatesortstring, stopnumber, customernumber,
                      customername, wearernumber, wearername, banklocker, department,
                      customeremployeenumber, gender, garmentdispensercode, deliverypointcode,
                      productcode, productdescription, sizecode, productpicturecode, deliverydaymask,
                      secondaryid, flagcode1, flagcode2, flagcode3, flagcode4, flagdescription1,
                      flagdescription2, flagdescription3, flagdescription4, infotext,
                      requiredrepairs, spare1, spare2, flagfreetext1, flagfreetext2, flagfreetext3,
                      flagfreetext4, routecodeonlabel, 'Y', 'N');
  if status <> 0 then
    begin
      --barcode has NOT been found, check if it is a rag
      if lv_databasecode = 'RFL' then
        begin
          --create_ragged_delscan
          create_ragged_delscan;
        end;
      end if;
    end;
  else
    begin
      if (customernumber = 0 and (routenumber = 0 or routenumber is null)) then
        begin
          customernumber := 9999;
          routenumber    := 999;
          routeday       := 9;
          customername   := 'POOL';
        end;
      end if;
      --get image code
      select max(i.code)
      into   imagecode
      from   product p
      join   image i
      on     i.image_id = p.image_id
      where  p.code = productcode;
      --get residual value and repair codes / info
      for x in (select nvl((select lpad(to_char(prt.exportcode), 2, '0')
                            from   plantrepairtypesettings prt
                            where  prt.repairtype_id = rp.repairtype_id
                            and    prt.plant_id = pt.plant_id), lpad(to_char(rt.code), 2, '0')) repairtypecode,
                       rp.xpercentage, rp.ypercentage, u.residualvalueamount, u.poolitem, bu.plant_id,
                       st.code stockroomcode, stl.rowcode, stl.locationcode, u.finishingmethod_id,
                       substr(w.fullname, 1, 25) fullname, u.customerowned, c.chargerepairs,
                       c.chargerepaircog, w.wearer_id, u.product_id, c.remark
                from   uniqueitem u
                join   (select ux.uniqueitem_id
                       from   uniqueitem ux
                       where  ux.primaryid = idcode
                       union all
                       select sx.uniqueitem_id
                       from   secondaryuniqueitem sx
                       where  sx.secondaryid = idcode) jx
                on     jx.uniqueitem_id = u.uniqueitem_id
                join   businessunit bu
                on     bu.businessunit_id = u.businessunit_id
                join   plant pt
                on     pt.plant_id = bu.plant_id
                left   outer join(repairpointer rp
                join   repairtype rt
                on     rt.repairtype_id = rp.repairtype_id) on rp.uniqueitem_id = u.uniqueitem_id
                join   uniqueitemfixedinfo ufi
                on     ufi.uniqueitem_id = u.uniqueitem_id
                left   outer join(stockroomlocation stl
                join   stockroom st
                on     st.stockroom_id = stl.stockroom_id) on stl.stockroomlocation_id = ufi.stockroomlocation_id
                left   outer join(uniqueitemnonpool un
                join   weareremployment we
                on     we.weareremployment_id = un.weareremployment_id
                join   wearer w
                on     w.wearer_id = we.wearer_id
                join   customer c
                on     c.customer_id = w.customer_id) on un.uniqueitem_id = u.uniqueitem_id
                where  (pt.code = plantcode or plantcode is null)
                order  by rp.sequencenumber asc) loop
        begin
          if lv_databasecode = 'CBD' then
            --ABS-8993
            spare1 := case
                        when x.customerowned = 'Y' and x.chargerepaircog in (1, 2) then
                         '1'
                        when x.customerowned = 'N' and x.chargerepairs in (1, 2) then
                         '2'
                        when x.customerowned = 'Y' and x.chargerepaircog = 0 then
                         '3'
                        when x.customerowned = 'N' and x.chargerepairs = 0 then
                         '4'
                        else
                         null
                      end;
          end if;
          if x.poolitem = 0 then
            begin
              --For uniqueitems on stock repair info NOT needed
              --And return different (default) values!!
              set_defaultstockvalues;
              sortstring := nvl(rpad(x.stockroomcode, 12, ' ') || rpad(x.rowcode, 12, ' ') ||
                                rpad(x.locationcode, 12, ' '), rpad(' ', 36, ' ')) ||
                            rpad(productcode, 12, ' ') || rpad(sizecode, 12, ' ');
              --Fill destination with value of system setting SORTSTOCKROOMDESTINATION
              select nvl(min(s.value), '0')
              into   destination
              from   systemsetting s
              where  s.plant_id = x.plant_id
              and    s.name = 'SORTSTOCKROOMDESTINATION';
              if lv_databasecode = 'CBD' then
                begin
                  flagcode1        := 'K';
                  flagdescription1 := 'STOCKROOM';
                  --NEW BEGIN
                  if foldprogram is null then
                    begin
                      select max(fp.foldingprogram)
                      into   foldprogram
                      from   foldingprogramdefinition fp
                      where  fp.product_id =
                             (select p.product_id from product p where p.code = productcode)
                      and    fp.finishingmethod_id =
                             (select f.finishingmethod_id from finishingmethod f where f.code = 'G');
                    end;
                  end if;
                  --NEW END
                end;
              end if;
              exit;
            end;
          else
            begin
              --diff. wearername full name first 25
              wearername  := x.fullname;
              repaircodes := repaircodes || x.repairtypecode;
              if x.xpercentage >= 100 then
                repairxcoordinates := repairxcoordinates || '99';
              else
                repairxcoordinates := repairxcoordinates || lpad(to_char(x.xpercentage), 2, '0');
              end if;
              if x.ypercentage >= 100 then
                repairycoordinates := repairycoordinates || '99';
              else
                repairycoordinates := repairycoordinates || lpad(to_char(x.ypercentage), 2, '0');
              end if;
              residualvalue := x.residualvalueamount;
              lv_counter    := lv_counter + 1;
              --special CBD request part
              if lv_databasecode = 'CBD' and flagcode1 is null then
                begin
                  select max(f.code)
                  into   lv_finishingmethodcode
                  from   finishingmethod f
                  where  f.finishingmethod_id = x.finishingmethod_id;
                  if lv_finishingmethodcode = 'GEBH' then
                    begin
                      flagcode1        := 'M';
                      flagdescription1 := 'Hand gebügelt hängend';
                    end;
                  end if;
                end;
              end if;
            end;
          end if;
          exit when lv_counter >= 10;
        end;
        if lv_databasecode = 'CUL' then
          select nvl(substr(get_flexfield_string(x.product_id, 'Product', 'FPD'), 1,1), foldprogram) into foldprogram from dual;
          select nvl(substr(get_flexfield_string(x.wearer_id, 'Wearer', 'FPO'), 1,1), foldprogram) into foldprogram from dual;
          infotext := nvl(x.remark, infotext);
          select get_flexfield_string(x.product_id, 'Product', 'MP') into spare2 from dual;
        end if;
      end loop; --x
      --get getadditionalabelinfo
      pack_sort.getadditionalabelinfo(idcode, unitcode, deliverypointcode, departmentdescription,
                                      consumptionpointcode, consumptionpointdescription,
                                      deliverypointdescription, deliverypointstreet1,
                                      deliverypointstreet2, deliverypointzipcode, deliverypointcity,
                                      transportarticledescription);
      --get_userinstructions
      get_userinstructions;
    end;
  end if;
end getgarmentdatametricon3;
/
create or replace procedure GetGarmentDataOrder(IDCode                 in UNIQUEITEM.PRIMARYID%type,
                                                PlantCode              in PLANT.CODE%type,
                                                UnitCode               out NOCOPY BUSINESSUNIT.CODE%type,
                                                Status                 out NOCOPY Integer,
                                                FinishSelection        out NOCOPY Varchar2, --(6),
                                                CheckpointSelection    out NOCOPY Varchar2, --(6),
                                                RepairSelection        out NOCOPY Varchar2, --(6),
                                                Destination            out NOCOPY Varchar2, --(6),
                                                FoldProgram            out NOCOPY Varchar2, --(6),
                                                StackChangeInfo        out NOCOPY Varchar2, --(60),
                                                RouteNumber            out NOCOPY ROUTE.ROUTENUMBER%type,
                                                RouteDay               out NOCOPY ROUTE.DRIVINGDAY_ID%type,
                                                Depot                  out NOCOPY DEPOT.CODE%type,
                                                SortString             out NOCOPY Varchar2,
                                                AlternateSortString    out NOCOPY Varchar2,
                                                StopNumber             out NOCOPY ROUTESTOP.STOPNUMBER%type,
                                                CustomerNumber         out NOCOPY CUSTOMER.CUSTOMERNUMBER%type,
                                                CustomerName           out NOCOPY CUSTOMER.NAME%type,
                                                WearerNumber           out NOCOPY WEARER.WEARERNUMBER%type,
                                                WearerName             out NOCOPY WEARER.SEARCHNAME%type,
                                                BankLocker             out NOCOPY Varchar2,
                                                Department             out NOCOPY DEPARTMENT.DEPARTMENTNUMBER%type,
                                                CustomerEmployeeNumber out NOCOPY WEARER.CUSTOMEREMPLOYEENUMBER%type,
                                                Gender                 out NOCOPY WEARER.SEX%type,
                                                GarmentDispenserCode   out NOCOPY GARMENTDISPENSER.CODE%type,
                                                DeliveryPointCode      out NOCOPY DELIVERYPOINT.CODE%type,
                                                ProductCode            out NOCOPY PRODUCT.CODE%type,
                                                ProductDescription     out NOCOPY PRODUCT_DESC.DESCRIPTION%type,
                                                SizeCode               out NOCOPY SIZEDEFINITION.CODE%type,
                                                ProductPictureCode     out NOCOPY IMAGE.CODE%type,
                                                DeliveryDayMask        out NOCOPY Varchar2,
                                                SecondaryID            out NOCOPY SECONDARYUNIQUEITEM.SECONDARYID%type,
                                                FlagCode1              out NOCOPY SORTADDRESSPERFLAG.SORTADDRESS%type,
                                                FlagCode2              out NOCOPY SORTADDRESSPERFLAG.SORTADDRESS%type,
                                                FlagCode3              out NOCOPY SORTADDRESSPERFLAG.SORTADDRESS%type,
                                                FlagCode4              out NOCOPY SORTADDRESSPERFLAG.SORTADDRESS%type,
                                                FlagDescription1       out NOCOPY FLAG_DESC.DESCRIPTION%type,
                                                FlagDescription2       out NOCOPY FLAG_DESC.DESCRIPTION%type,
                                                FlagDescription3       out NOCOPY FLAG_DESC.DESCRIPTION%type,
                                                FlagDescription4       out NOCOPY FLAG_DESC.DESCRIPTION%type,
                                                Infotext               out NOCOPY WEARER.REMARK%type,
                                                RequiredRepairs        out NOCOPY Varchar2,
                                                Spare1                 out NOCOPY Varchar2,
                                                Spare2                 out NOCOPY Varchar2) is
begin
  spare2 := 'Y';
  GetGarmentData(IDCode,
                 PlantCode,
                 UnitCode,
                 Status,
                 FinishSelection,
                 CheckpointSelection,
                 RepairSelection,
                 Destination,
                 FoldProgram,
                 StackChangeInfo,
                 RouteNumber,
                 RouteDay,
                 Depot,
                 SortString,
                 AlternateSortString,
                 StopNumber,
                 CustomerNumber,
                 CustomerName,
                 WearerNumber,
                 WearerName,
                 BankLocker,
                 Department,
                 CustomerEmployeeNumber,
                 Gender,
                 GarmentDispenserCode,
                 DeliveryPointCode,
                 ProductCode,
                 ProductDescription,
                 SizeCode,
                 ProductPictureCode,
                 DeliveryDayMask,
                 SecondaryID,
                 FlagCode1,
                 FlagCode2,
                 FlagCode3,
                 FlagCode4,
                 FlagDescription1,
                 FlagDescription2,
                 FlagDescription3,
                 FlagDescription4,
                 Infotext,
                 RequiredRepairs,
                 Spare1,
                 Spare2);

end GetGarmentDataOrder;
/
create or replace procedure getgarmentdatars(fp_idcode              in uniqueresidentialitem.primaryid%type,
                                             fp_plantcode           in plant.code%type,
                                             fp_unitcode            out nocopy businessunit.code%type,
                                             fp_status              out nocopy number,
                                             fp_errormessage        out nocopy varchar2,
                                             fp_finishingcode       out nocopy sortaddressperfinishingcode.sortaddress%type,
                                             fp_destination         out nocopy sortaddressperfinishingmeth.sortaddress%type,
                                             fp_foldprogram         out nocopy foldingprogramdefinition.foldingprogram%type,
                                             fp_stackchangeinfo     out nocopy varchar2,
                                             fp_routenumber         out nocopy route.routenumber%type,
                                             fp_routeday            out nocopy route.drivingday_id%type,
                                             fp_depot               out nocopy depot.code%type,
                                             fp_sortstring          out nocopy varchar2,
                                             fp_stopnumber          out nocopy clientdeliverynote.stopnumber%type,
                                             fp_customernumber      out nocopy customer.customernumber%type,
                                             fp_customername        out nocopy customer.name%type,
                                             fp_clientnumber        out nocopy client.clientnumber%type,
                                             fp_clientsearchname    out nocopy client.searchname%type,
                                             fp_roomnumber          out nocopy departmentroom.roomnumber%type,
                                             fp_departmentnumber    out nocopy department.departmentnumber%type,
                                             fp_clientadminnumber   out nocopy client.adminnumber%type,
                                             fp_gender              out nocopy client.gender%type,
                                             fp_deliverypointcode   out nocopy deliverypoint.code%type,
                                             fp_productcode         out nocopy product.code%type,
                                             fp_productdescription  out nocopy product_desc.description%type,
                                             fp_sizecode            out nocopy sizedefinition.code%type,
                                             fp_productsortgroup    out nocopy productsortgroup.code%type,
                                             fp_deliverydaymask     out nocopy varchar2, --varchar2(7)
                                             fp_flagcode1           out nocopy sortaddressperflag.sortaddress%type,
                                             fp_flagcode2           out nocopy sortaddressperflag.sortaddress%type,
                                             fp_flagcode3           out nocopy sortaddressperflag.sortaddress%type,
                                             fp_flagcode4           out nocopy sortaddressperflag.sortaddress%type,
                                             fp_flagdescription1    out nocopy varchar2,
                                             fp_flagdescription2    out nocopy varchar2,
                                             fp_flagdescription3    out nocopy varchar2,
                                             fp_flagdescription4    out nocopy varchar2,
                                             fp_infotext            out nocopy client.remark%type,
                                             fp_clientdeliverynote  out nocopy clientdeliverynote.clientdeliverynotenumber%type,
                                             fp_department_desc     out nocopy department.description%type,
                                             fp_clientfirstlastname out nocopy varchar2,
                                             fp_productvolume       out nocopy product.volumeunits%type) is
  pragma autonomous_transaction;
  ---getgarmentdatars version 1.9
  ---internal variables
  gv_userexception exception;
  gv_systemuserid            systemuser.systemuser_id%type;
  gv_plantid_paramater       plant.plant_id%type;
  gv_plantid_garment         plant.plant_id%type;
  gv_plantlanguageid         plant.language_id%type;
  gv_businessunitid          businessunit.businessunit_id%type;
  gv_uniqueresidentialitemid uniqueresidentialitem.uniqueresidentialitem_id%type;
  gv_message                 abslog.message%type;
  gv_clientid                client.client_id%type;
  gv_customerid              customer.customer_id%type;
  gv_routeid                 route.route_id%type;
  gv_serviceteamid           customer.serviceteam_id%type;
  gv_departmentroomid        departmentroom.departmentroom_id%type;
  gv_departmentroomseq       departmentroom.sequencenumber%type;
  gv_productid               product.product_id%type;
  gv_productgroupid          product.productgroup_id%type;
  gv_colorid                 color.color_id%type;
  gv_sizeid                  sizedefinition.sizedefinition_id%type;
  gv_finishingmethodid       finishingmethod.finishingmethod_id%type;
  gv_deliverypointid         deliverypoint.deliverypoint_id%type;
  gv_productsortgroupid      product.productsortgroup_id%type;
  gv_productsortgroupseq     productsortgroupperplant.sequencenumber%type;
  gv_timezonehrsdiff         plant.timezonehrsdiff%type;
  gv_clientdeliverynoteid    clientdeliverynote.clientdeliverynote_id%type;
  gv_clientdelnotlinescanid  clientdelnotelinescan.clientdelnotelinescan_id%type;
  gv_batchid                 batch.batch_id%type;
  gv_statusid                status.status_id%type;
  gv_lastinscandate          uniqueresidentialitem.lastinscandate%type;
  gv_lastoutscandate         uniqueresidentialitem.lastoutscandate%type;
  gv_lastrewashdate          uniqueresidentialitem.lastrewashdate%type;
  gv_lastrepairdate          uniqueresidentialitem.lastrepairdate%type;
  gv_loglevel                number;
  gv_departmentid            department.department_id%type;
  gv_databasecode            databasesettings.code%type;

  function converttonumber(fpstring varchar2) return number is
    v_length number;
    v_char   varchar2(1);
    v_string varchar2(30);
  begin
    v_length := length(fpstring);
    v_string := '9';
    for i in 1 .. v_length loop
      v_char := substr(fpstring, i, 1);
      if upper(v_char) = 'Y' then
        v_string := concatenate(v_string, '1');
      else
        if upper(v_char) = 'N' then
          v_string := concatenate(v_string, '0');
        end if;
      end if;
    end loop;
    return to_number(v_string);
  end;

  procedure get_extra_information is
    procedure fill_flags is
      lv_counter number := 0;
    begin
      gv_message := 'fill_flags';
      for x_fd in (select saf.sortaddress, fd.description || urf.freetextitem description
                   from   uniqueresidentialitemflag urf
                   join   flag f
                   on     urf.flag_id = f.flag_id
                   join   flagoptions fop
                   on     fop.flag_id = urf.flag_id
                   join   sortaddressperflag saf
                   on     (saf.flag_id = f.flag_id and saf.plant_id = gv_plantid_paramater)
                   join   flag_desc fd
                   on     (fd.flag_id = urf.flag_id and fd.language_id = gv_plantlanguageid)
                   where  urf.uniqueresidentialitem_id = gv_uniqueresidentialitemid
                   and    urf.startdate <= sysdate
                   and    exists (select 1
                           from   dialogs dg
                           where  dg.code in ('OutscanSort', 'CheckPointScan')
                           and    dg.dialog_id = fop.dialog_id)
                   and    saf.sortaddress is not null
                   order  by fop.confirm desc, f.priority asc, urf.startdate desc) loop
        begin
          lv_counter := lv_counter + 1;
          case lv_counter
            when 1 then
              fp_flagcode1        := x_fd.sortaddress;
              fp_flagdescription1 := x_fd.description;
            when 2 then
              fp_flagcode2        := x_fd.sortaddress;
              fp_flagdescription2 := x_fd.description;
            when 3 then
              fp_flagcode3        := x_fd.sortaddress;
              fp_flagdescription3 := x_fd.description;
            when 4 then
              fp_flagcode4        := x_fd.sortaddress;
              fp_flagdescription4 := x_fd.description;
            else
              exit;
          end case;
        end;
      end loop;
    end fill_flags;
  begin
    gv_message := 'get_extra_information';
    --get fp_destination / fp_foldprogram
    if gv_finishingmethodid is null then
      fp_destination := null;
      fp_foldprogram := null;
    else
      begin
        --get fp_destination
        select max(saf.sortaddress)
        into   fp_destination
        from   sortaddressperfinishingmeth saf
        where  saf.finishingmethod_id = gv_finishingmethodid
        and    saf.plant_id = gv_plantid_paramater;
        --get fp_foldprogram
        select max(fpd.foldingprogram)
        into   fp_foldprogram
        from   foldingprogramdefinition fpd
        where  fpd.product_id = gv_productid
        and    fpd.finishingmethod_id = gv_finishingmethodid
        and    fpd.plant_id = gv_plantid_paramater;
      end;
    end if;
    --get productsort group seq
    select nvl(max(psgp.sequencenumber), 0)
    into   gv_productsortgroupseq
    from   productsortgroupperplant psgp
    where  psgp.productsortgroup_id = gv_productsortgroupid
    and    psgp.plant_id = gv_plantid_paramater;
    --get fp_deliverydaymask
    pack_sort_rs.get_deliverydaysmask(gv_customerid, fp_deliverydaymask);
    --fill_flags
    fill_flags;
  end get_extra_information;

  procedure get_customer_specific_info is
    lv_ranking customerranking.ranking%type;
  begin
    --get_customer_specific_info
    gv_message := 'get_customer_specific_info';
    if gv_databasecode = 'RFL' then
      begin
        fp_routenumber := fp_customernumber;
        fp_routeday    := 1;
        fp_stopnumber  := 1;
      end;
    end if;
    if gv_databasecode = 'CLO' then
      begin
        fp_routeday   := 1;
        fp_stopnumber := 1;
        select max(cr.ranking)
        into   lv_ranking
        from   customerranking cr
        join   customer c
        on     c.customerranking_id = cr.customerranking_id
        where  c.customernumber = fp_customernumber;
        fp_routenumber := nvl(to_number(lv_ranking), fp_customernumber);
      exception
        when others then
          fp_routenumber := fp_customernumber;
      end;
    end if;
  end get_customer_specific_info;

  procedure check_client_active is
    lv_activeyn     varchar2(1);
    lv_clientnumber number;
  begin
    --check_client_active
    if gv_databasecode in ('CLO') and gv_clientid is not null then
      begin
        select case
                  when sysdate between cl.dateactive and cl.dateinactive then
                   'Y'
                  else
                   'N'
                end active_yn, cl.clientnumber
        into   lv_activeyn, lv_clientnumber
        from   client cl
        where  cl.client_id = gv_clientid;
        if lv_activeyn = 'N' then
          begin
            gv_message := 'Client ' || to_char(lv_clientnumber);
            raise gv_userexception;
          end;
        end if;
      end;
    end if;
  end check_client_active;
begin
  --get systemuser
  begin
    select s.systemuser_id into gv_systemuserid from systemuser s where s.username = 'SORT';
  exception
    when no_data_found then
      select min(systemuser_id) into gv_systemuserid from systemuser;
  end;
  --get get_uniqueitem_rs info
  pack_sort_rs.get_uniqueitem_rs(fp_idcode, fp_plantcode, 0, gv_plantlanguageid,
                                 gv_uniqueresidentialitemid, gv_plantid_paramater,
                                 gv_plantid_garment, fp_unitcode, gv_businessunitid, fp_status,
                                 gv_message, fp_customernumber, gv_customerid, fp_customername,
                                 gv_serviceteamid, fp_clientnumber, gv_clientid, fp_clientsearchname,
                                 fp_roomnumber, gv_departmentroomid, gv_departmentroomseq,
                                 fp_departmentnumber, fp_clientadminnumber, fp_gender,
                                 fp_deliverypointcode, gv_deliverypointid, fp_productcode,
                                 gv_productid, gv_productgroupid, fp_productdescription, gv_colorid,
                                 fp_sizecode, fp_productsortgroup, gv_productsortgroupid, gv_sizeid,
                                 gv_finishingmethodid, fp_infotext, gv_timezonehrsdiff, gv_statusid,
                                 gv_lastinscandate, gv_lastoutscandate, gv_lastrewashdate,
                                 gv_lastrepairdate, gv_loglevel, gv_departmentid, fp_department_desc,
                                 fp_clientfirstlastname, fp_productvolume, gv_databasecode);
  --get_extra_information
  get_extra_information;
  --get_plpc_info
  pack_sort_rs.get_plpc_info(gv_plantid_paramater, gv_customerid, gv_productid, gv_sizeid,
                             gv_finishingmethodid, fp_status, gv_message, fp_finishingcode);
  --get client del note
  pack_sort_rs.get_create_clientdelnote(gv_uniqueresidentialitemid, gv_businessunitid, fp_unitcode,
                                        gv_plantid_paramater, gv_customerid, gv_clientid,
                                        gv_productgroupid, gv_deliverypointid, fp_routenumber,
                                        gv_routeid, fp_routeday, fp_depot, fp_stopnumber,
                                        fp_clientdeliverynote, gv_clientdeliverynoteid,
                                        gv_clientdelnotlinescanid, gv_batchid, fp_status, gv_message,
                                        0, gv_loglevel, 'GETGARMENTDATARS', gv_systemuserid,
                                        gv_departmentid, fp_idcode, gv_productid, gv_sizeid,
                                        gv_finishingmethodid, sysdate, gv_databasecode);
  --get_customer_specific_info
  get_customer_specific_info;
  --get fp_sortstring
  fp_sortstring := pack_sort_rs.get_sortstring(gv_plantid_paramater, gv_customerid,
                                               fp_customernumber, fp_stopnumber, fp_departmentnumber,
                                               fp_clientnumber, fp_clientsearchname, fp_roomnumber,
                                               fp_productcode, gv_productsortgroupseq,
                                               fp_deliverypointcode, fp_clientdeliverynote,
                                               gv_departmentroomseq, 'N');
  --get fp_stackchangeinfo
  fp_stackchangeinfo := pack_sort_rs.get_sortstring(gv_plantid_paramater, gv_customerid,
                                                    fp_customernumber, fp_stopnumber,
                                                    fp_departmentnumber, fp_clientnumber,
                                                    fp_clientsearchname, fp_roomnumber,
                                                    fp_productcode, gv_productsortgroupseq,
                                                    fp_deliverypointcode, fp_clientdeliverynote,
                                                    gv_departmentroomseq, 'Y');
  --check if client is inactive
  check_client_active;
  --commit
  commit;
  fp_status       := 0;
  fp_errormessage := null;
  pack_sort_rs.write_logging('Ok, status 0; ID code ' || nvl(fp_idcode, 'NULL') || ' plant code ' ||
                             nvl(fp_plantcode, 'NULL'), gv_loglevel, 'GETGARMENTDATARS',
                             gv_plantid_paramater, 1, 0);
exception
  --error handling
  when gv_userexception then
    begin
      rollback;
      fp_status       := 5; --Inactive client
      fp_errormessage := 'Client inactive status 5; ' || gv_message || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'GETGARMENTDATARS',
                                 gv_plantid_paramater, 3, 0);
    end;
  when no_data_found then
    begin
      rollback;
      fp_status       := 1; --no_data_found
      fp_errormessage := 'No data found, status 1; ' || gv_message || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'GETGARMENTDATARS',
                                 gv_plantid_paramater, 3, 0);
    end;
  when too_many_rows then
    begin
      rollback;
      fp_status       := 2; --too many rows
      fp_errormessage := 'Too many rows, status 2; ' || gv_message || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'GETGARMENTDATARS',
                                 gv_plantid_paramater, 3, 0);
    end;
  when dup_val_on_index then
    begin
      rollback;
      fp_status       := 3; --dup_val_on_index
      fp_errormessage := 'Dup val on index, status 3; ' || gv_message || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'GETGARMENTDATARS',
                                 gv_plantid_paramater, 3, 0);
    end;
  when others then
    begin
      rollback;
      fp_status := 4; --others
      pack_sort_rs.write_logging('Error others, status 4; ' || gv_message || ' ID code ' ||
                                 nvl(fp_idcode, 'NULL') || ' plant code ' ||
                                 nvl(fp_plantcode, 'NULL') || ' see debug info!', gv_loglevel,
                                 'GETGARMENTDATARS', gv_plantid_paramater, 5, 0);
      fp_errormessage := 'Error others, status 4; ' || sqlerrm || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'GETGARMENTDATARS',
                                 gv_plantid_paramater, 5, 0);
    end;
end getgarmentdatars;
/
create or replace procedure getgarmentdatars_readonly(fp_idcode              in uniqueresidentialitem.primaryid%type,
                                                      fp_plantcode           in plant.code%type,
                                                      fp_unitcode            out nocopy businessunit.code%type,
                                                      fp_status              out nocopy number,
                                                      fp_errormessage        out nocopy varchar2,
                                                      fp_finishingcode       out nocopy sortaddressperfinishingcode.sortaddress%type,
                                                      fp_destination         out nocopy sortaddressperfinishingmeth.sortaddress%type,
                                                      fp_foldprogram         out nocopy foldingprogramdefinition.foldingprogram%type,
                                                      fp_stackchangeinfo     out nocopy varchar2,
                                                      fp_routenumber         out nocopy route.routenumber%type,
                                                      fp_routeday            out nocopy route.drivingday_id%type,
                                                      fp_depot               out nocopy depot.code%type,
                                                      fp_sortstring          out nocopy varchar2,
                                                      fp_stopnumber          out nocopy clientdeliverynote.stopnumber%type,
                                                      fp_customernumber      out nocopy customer.customernumber%type,
                                                      fp_customername        out nocopy customer.name%type,
                                                      fp_clientnumber        out nocopy client.clientnumber%type,
                                                      fp_clientsearchname    out nocopy client.searchname%type,
                                                      fp_roomnumber          out nocopy departmentroom.roomnumber%type,
                                                      fp_departmentnumber    out nocopy department.departmentnumber%type,
                                                      fp_clientadminnumber   out nocopy client.adminnumber%type,
                                                      fp_gender              out nocopy client.gender%type,
                                                      fp_deliverypointcode   out nocopy deliverypoint.code%type,
                                                      fp_productcode         out nocopy product.code%type,
                                                      fp_productdescription  out nocopy product_desc.description%type,
                                                      fp_sizecode            out nocopy sizedefinition.code%type,
                                                      fp_productsortgroup    out nocopy productsortgroup.code%type,
                                                      fp_deliverydaymask     out nocopy varchar2, --varchar2(7)
                                                      fp_flagcode1           out nocopy sortaddressperflag.sortaddress%type,
                                                      fp_flagcode2           out nocopy sortaddressperflag.sortaddress%type,
                                                      fp_flagcode3           out nocopy sortaddressperflag.sortaddress%type,
                                                      fp_flagcode4           out nocopy sortaddressperflag.sortaddress%type,
                                                      fp_flagdescription1    out nocopy varchar2,
                                                      fp_flagdescription2    out nocopy varchar2,
                                                      fp_flagdescription3    out nocopy varchar2,
                                                      fp_flagdescription4    out nocopy varchar2,
                                                      fp_infotext            out nocopy client.remark%type,
                                                      fp_department_desc     out nocopy department.description%type,
                                                      fp_clientfirstlastname out nocopy varchar2,
                                                      fp_productvolume       out nocopy product.volumeunits%type) is
  pragma autonomous_transaction;
  ---getgarmentdatars_readonly version 0.1
  ---internal variables
  gv_systemuserid            systemuser.systemuser_id%type;
  gv_plantid_paramater       plant.plant_id%type;
  gv_plantid_garment         plant.plant_id%type;
  gv_plantlanguageid         plant.language_id%type;
  gv_businessunitid          businessunit.businessunit_id%type;
  gv_uniqueresidentialitemid uniqueresidentialitem.uniqueresidentialitem_id%type;
  gv_message                 abslog.message%type;
  gv_clientid                client.client_id%type;
  gv_customerid              customer.customer_id%type;
  gv_serviceteamid           customer.serviceteam_id%type;
  gv_departmentroomid        departmentroom.departmentroom_id%type;
  gv_departmentroomseq       departmentroom.sequencenumber%type;
  gv_productid               product.product_id%type;
  gv_productgroupid          product.productgroup_id%type;
  gv_colorid                 color.color_id%type;
  gv_sizeid                  sizedefinition.sizedefinition_id%type;
  gv_finishingmethodid       finishingmethod.finishingmethod_id%type;
  gv_deliverypointid         deliverypoint.deliverypoint_id%type;
  gv_productsortgroupid      product.productsortgroup_id%type;
  gv_productsortgroupseq     productsortgroupperplant.sequencenumber%type;
  gv_timezonehrsdiff         plant.timezonehrsdiff%type;
  gv_statusid                status.status_id%type;
  gv_lastinscandate          uniqueresidentialitem.lastinscandate%type;
  gv_lastoutscandate         uniqueresidentialitem.lastoutscandate%type;
  gv_lastrewashdate          uniqueresidentialitem.lastrewashdate%type;
  gv_lastrepairdate          uniqueresidentialitem.lastrepairdate%type;
  gv_loglevel                number;
  gv_departmentid            department.department_id%type;
  gv_databasecode            databasesettings.code%type;

  function converttonumber(fpstring varchar2) return number is
    v_length number;
    v_char   varchar2(1);
    v_string varchar2(30);
  begin
    v_length := length(fpstring);
    v_string := '9';
    for i in 1 .. v_length loop
      v_char := substr(fpstring, i, 1);
      if upper(v_char) = 'Y' then
        v_string := concatenate(v_string, '1');
      else
        if upper(v_char) = 'N' then
          v_string := concatenate(v_string, '0');
        end if;
      end if;
    end loop;
    return to_number(v_string);
  end;

  procedure get_extra_information is
    procedure fill_flags is
      lv_counter number := 0;
    begin
      gv_message := 'fill_flags';
      for x_fd in (select saf.sortaddress, fd.description || urf.freetextitem description
                   from   uniqueresidentialitemflag urf
                   join   flag f
                   on     urf.flag_id = f.flag_id
                   join   flagoptions fop
                   on     fop.flag_id = urf.flag_id
                   join   sortaddressperflag saf
                   on     (saf.flag_id = f.flag_id and saf.plant_id = gv_plantid_paramater)
                   join   flag_desc fd
                   on     (fd.flag_id = urf.flag_id and fd.language_id = gv_plantlanguageid)
                   where  urf.uniqueresidentialitem_id = gv_uniqueresidentialitemid
                   and    urf.startdate <= sysdate
                   and    exists (select 1
                           from   dialogs dg
                           where  dg.code in ('OutscanSort', 'CheckPointScan')
                           and    dg.dialog_id = fop.dialog_id)
                   and    saf.sortaddress is not null
                   order  by fop.confirm desc, f.priority asc, urf.startdate desc) loop
        begin
          lv_counter := lv_counter + 1;
          case lv_counter
            when 1 then
              fp_flagcode1        := x_fd.sortaddress;
              fp_flagdescription1 := x_fd.description;
            when 2 then
              fp_flagcode2        := x_fd.sortaddress;
              fp_flagdescription2 := x_fd.description;
            when 3 then
              fp_flagcode3        := x_fd.sortaddress;
              fp_flagdescription3 := x_fd.description;
            when 4 then
              fp_flagcode4        := x_fd.sortaddress;
              fp_flagdescription4 := x_fd.description;
            else
              exit;
          end case;
        end;
      end loop;
    end fill_flags;
  begin
    gv_message := 'get_extra_information';
    --get fp_destination / fp_foldprogram
    if gv_finishingmethodid is null then
      fp_destination := null;
      fp_foldprogram := null;
    else
      begin
        --get fp_destination
        select max(saf.sortaddress)
        into   fp_destination
        from   sortaddressperfinishingmeth saf
        where  saf.finishingmethod_id = gv_finishingmethodid
        and    saf.plant_id = gv_plantid_paramater;
        --get fp_foldprogram
        select max(fpd.foldingprogram)
        into   fp_foldprogram
        from   foldingprogramdefinition fpd
        where  fpd.product_id = gv_productid
        and    fpd.finishingmethod_id = gv_finishingmethodid
        and    fpd.plant_id = gv_plantid_paramater;
      end;
    end if;
    --get productsort group seq
    select nvl(max(psgp.sequencenumber), 0)
    into   gv_productsortgroupseq
    from   productsortgroupperplant psgp
    where  psgp.productsortgroup_id = gv_productsortgroupid
    and    psgp.plant_id = gv_plantid_paramater;
    --get fp_deliverydaymask
    pack_sort_rs.get_deliverydaysmask(gv_customerid, fp_deliverydaymask);
    --fill_flags
    fill_flags;
  end get_extra_information;

  procedure get_customer_specific_info is
    lv_ranking customerranking.ranking%type;
  begin
    --get_customer_specific_info
    gv_message := 'get_customer_specific_info';
    if gv_databasecode = 'RFL' then
      begin
        fp_routenumber := fp_customernumber;
        fp_routeday    := 1;
        fp_stopnumber  := 1;
      end;
    end if;
    if gv_databasecode = 'CLO' then
      begin
        fp_routeday   := 1;
        fp_stopnumber := 1;
        select max(cr.ranking)
        into   lv_ranking
        from   customerranking cr
        join   customer c
        on     c.customerranking_id = cr.customerranking_id
        where  c.customernumber = fp_customernumber;
        fp_routenumber := nvl(to_number(lv_ranking), fp_customernumber);
      exception
        when others then
          fp_routenumber := fp_customernumber;
      end;
    end if;
  end get_customer_specific_info;

begin
  --get systemuser
  begin
    select s.systemuser_id into gv_systemuserid from systemuser s where s.username = 'SORT';
  exception
    when no_data_found then
      select min(systemuser_id) into gv_systemuserid from systemuser;
  end;
  fp_depot := null; --not used
  --get get_uniqueitem_rs info
  pack_sort_rs.get_uniqueitem_rs(fp_idcode, fp_plantcode, 0, gv_plantlanguageid,
                                 gv_uniqueresidentialitemid, gv_plantid_paramater,
                                 gv_plantid_garment, fp_unitcode, gv_businessunitid, fp_status,
                                 gv_message, fp_customernumber, gv_customerid, fp_customername,
                                 gv_serviceteamid, fp_clientnumber, gv_clientid, fp_clientsearchname,
                                 fp_roomnumber, gv_departmentroomid, gv_departmentroomseq,
                                 fp_departmentnumber, fp_clientadminnumber, fp_gender,
                                 fp_deliverypointcode, gv_deliverypointid, fp_productcode,
                                 gv_productid, gv_productgroupid, fp_productdescription, gv_colorid,
                                 fp_sizecode, fp_productsortgroup, gv_productsortgroupid, gv_sizeid,
                                 gv_finishingmethodid, fp_infotext, gv_timezonehrsdiff, gv_statusid,
                                 gv_lastinscandate, gv_lastoutscandate, gv_lastrewashdate,
                                 gv_lastrepairdate, gv_loglevel, gv_departmentid, fp_department_desc,
                                 fp_clientfirstlastname, fp_productvolume, gv_databasecode);
  --get_extra_information
  get_extra_information;
  --get_plpc_info
  pack_sort_rs.get_plpc_info(gv_plantid_paramater, gv_customerid, gv_productid, gv_sizeid,
                             gv_finishingmethodid, fp_status, gv_message, fp_finishingcode);
  --get_customer_specific_info
  get_customer_specific_info;
  --get fp_sortstring
  fp_sortstring := pack_sort_rs.get_sortstring(gv_plantid_paramater, gv_customerid,
                                               fp_customernumber, fp_stopnumber, fp_departmentnumber,
                                               fp_clientnumber, fp_clientsearchname, fp_roomnumber,
                                               fp_productcode, gv_productsortgroupseq,
                                               fp_deliverypointcode, null, gv_departmentroomseq, 'N');
  --get fp_stackchangeinfo
  fp_stackchangeinfo := pack_sort_rs.get_sortstring(gv_plantid_paramater, gv_customerid,
                                                    fp_customernumber, fp_stopnumber,
                                                    fp_departmentnumber, fp_clientnumber,
                                                    fp_clientsearchname, fp_roomnumber,
                                                    fp_productcode, gv_productsortgroupseq,
                                                    fp_deliverypointcode, null, gv_departmentroomseq,
                                                    'Y');
  commit;
  fp_status       := 0;
  fp_errormessage := null;
  pack_sort_rs.write_logging('Ok, status 0; ID code ' || nvl(fp_idcode, 'NULL') || ' plant code ' ||
                             nvl(fp_plantcode, 'NULL'), gv_loglevel, 'GETGARMENTDATARS',
                             gv_plantid_paramater, 1, 0);
exception
  --error handling
  when no_data_found then
    begin
      rollback;
      fp_status       := 1; --no_data_found
      fp_errormessage := 'No data found, status 1; ' || gv_message || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'GETGARMENTDATARS',
                                 gv_plantid_paramater, 3, 0);
    end;
  when too_many_rows then
    begin
      rollback;
      fp_status       := 2; --too many rows
      fp_errormessage := 'Too many rows, status 2; ' || gv_message || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'GETGARMENTDATARS',
                                 gv_plantid_paramater, 3, 0);
    end;
  when dup_val_on_index then
    begin
      rollback;
      fp_status       := 3; --dup_val_on_index
      fp_errormessage := 'Dup val on index, status 3; ' || gv_message || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'GETGARMENTDATARS',
                                 gv_plantid_paramater, 3, 0);
    end;
  when others then
    begin
      rollback;
      fp_status := 4; --others
      pack_sort_rs.write_logging('Error others, status 4; ' || gv_message || ' ID code ' ||
                                 nvl(fp_idcode, 'NULL') || ' plant code ' ||
                                 nvl(fp_plantcode, 'NULL') || ' see debug info!', gv_loglevel,
                                 'GETGARMENTDATARS', gv_plantid_paramater, 5, 0);
      fp_errormessage := 'Error others, status 4; ' || sqlerrm || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'GETGARMENTDATARS',
                                 gv_plantid_paramater, 5, 0);
    end;
end getgarmentdatars_readonly;
/
create or replace procedure getgarmentdatasmartline( /*input parameters*/fp_garmentid    in uniqueitem.primaryid%type,
                                                    fp_plantcode    in plant.code%type,
                                                    fp_languagecode in languages.code%type,
                                                    /*Output Parameters */
                                                    fp_status      out nocopy integer,
                                                    fp_secondaryid out nocopy secondaryuniqueitem.secondaryid%type,
                                                    /*Final destination group*/
                                                    fp_destinationselection out nocopy sortaddressperfinishingmeth.sortaddress%type,
                                                    fp_destinationcode      out nocopy sortaddressperfinishingmeth.sortaddress%type,
                                                    /*Process parameters*/
                                                    fp_finishingmethod out nocopy finishingcode.finishingcode%type,
                                                    /*Sorting criterias*/
                                                    fp_stackinfo  out nocopy varchar2,
                                                    fp_sortstring out nocopy varchar2,
                                                    /*Additional garment Information - for operational view ONLY*/
                                                    fp_flagsdestination   out nocopy varchar2,
                                                    fp_flagsinfo          out nocopy varchar2,
                                                    fp_productcode        out nocopy product.code%type,
                                                    fp_productdescription out nocopy product_desc.description%type,
                                                    /*Expedition route / delivery route */
                                                    fp_routenumber      out nocopy route.routenumber%type,
                                                    fp_routeday         out nocopy route.drivingday_id%type,
                                                    fp_stopnumber       out nocopy routestop.stopnumber%type,
                                                    fp_week             out nocopy number,
                                                    fp_routecodeonlabel out nocopy route.codeonlabel%type,
                                                    fp_servicefrequency out nocopy deliveryscheme.code%type,
                                                    /*Adresses and additional informations*/
                                                    fp_customernumber       out nocopy customer.customernumber%type,
                                                    fp_customername         out nocopy customer.name%type,
                                                    fp_department           out nocopy department.departmentnumber%type,
                                                    fp_wearernumber         out nocopy wearer.wearernumber%type,
                                                    fp_consumptionpoint     out nocopy distributionpoint.description%type,
                                                    fp_washestotal          out nocopy uniqueitem.washestotal%type,
                                                    fp_productimage         out nocopy image.imagename%type,
                                                    fp_firstissuedate       out nocopy uniqueitemfixedinfo.firstissuedate%type,
                                                    fp_lastissuedate        out nocopy uniqueitemfixedinfo.lastissuedate%type,
                                                    fp_daysincirculation    out nocopy number,
                                                    fp_depot                out nocopy depot.code%type,
                                                    fp_deliverydaymask      out nocopy varchar2,
                                                    fp_wearername           out nocopy wearer.fullname%type,
                                                    fp_customeremployee     out nocopy wearer.customeremployeenumber%type,
                                                    fp_banklocker           out nocopy varchar2,
                                                    fp_garmentdispensercode out nocopy garmentdispenser.code%type,
                                                    fp_gender               out nocopy wearer.sex%type,
                                                    fp_deliverypointcode    out nocopy deliverypoint.code%type,
                                                    fp_depotstreet          out nocopy address.street%type,
                                                    fp_depotcity            out nocopy address.city%type,
                                                    fp_deliverystreet       out nocopy address.street%type,
                                                    fp_deliverycity         out nocopy address.city%type,
                                                    fp_companyname          out nocopy plant.name%type,
                                                    fp_companyphoneno       out nocopy plant.phoneno%type,
                                                    fp_companyemail         out nocopy plant.email%type, --remark only 40 chars
                                                    fp_uniqueitemid         out nocopy uniqueitem.primaryid%type,
                                                    fp_sizecode             out nocopy varchar2,
                                                    fp_theoraticalweight    out nocopy product.theoreticalweight%type,
                                                    fp_productgroupcode     out nocopy productgroup.code%type,
                                                    fp_productgroupdesc     out nocopy varchar2,
                                                    fp_washprocess          out nocopy varchar2,
                                                    fp_deliverystreet2      out nocopy varchar2,
                                                    fp_deliverypointstatus  out nocopy varchar2,
                                                    /*extra fields for ABS-71077 Smartline interface adjustments*/
                                                    fp_labelprintmode       out nocopy varchar2,
                                                    fp_deliverytype         out nocopy varchar2,
                                                    fp_finishingmethod_desc out nocopy varchar2,
                                                    fp_deliveryzipcode      out nocopy varchar2,
                                                    fp_modification_ind     out nocopy varchar2,
                                                    fp_custlanguage         out nocopy varchar2,
                                                    fp_foldingprogram       out nocopy varchar2,
                                                    fp_statuscode           out nocopy varchar2,
                                                    fp_repairselection      out nocopy varchar2,
                                                    fp_repaircode           out nocopy varchar2,
                                                    fp_checkpointselection  out nocopy varchar2,
                                                    fp_checkpointsortaddres out nocopy varchar2,
                                                    fp_finishselection      out nocopy varchar2,
                                                    fp_finishsortadress     out nocopy varchar2) is
  /*Version 2.14*/
  gv_exception exception;
  gv_message             varchar2(1000);
  gv_languageid          languages.language_id%type;
  gv_pool                uniqueitem.poolitem%type;
  gv_businessunitcode    businessunit.code%type;
  gv_businessunitid      businessunit.businessunit_id%type;
  gv_plant_paramid       plant.plant_id%type;
  gv_plant_garmentid     plant.plant_id%type;
  gv_returnedplantcode   plant.code%type;
  gv_idprimary           uniqueitem.primaryid%type; --is never used in this procedure
  gv_debuglevel          integer;
  gv_dummy               varchar2(255);
  gv_finishingcodeid     finishingcode.finishingcode_id%type;
  gv_finishingmethodid   finishingmethod.finishingmethod_id%type;
  gv_serviceteamid       serviceteam.serviceteam_id%type;
  gv_chargerepairs       customer.chargerepairs%type;
  gv_customerowned       uniqueitem.customerowned%type;
  gv_colorid             color.color_id%type;
  gv_wearerflagid        flag.flag_id%type;
  gv_wearerflagstartdate wearer.flagstartdate%type;
  gv_wearerremark        wearer.remark%type;
  gv_empflagid           flag.flag_id%type;
  gv_empflagstartdate    date;
  gv_productid           product.product_id%type;
  gv_sortcustomerid      customer.sortcustomer_id%type;
  gv_customerid          customer.customer_id%type;
  gv_imageid             image.image_id%type;
  gv_routestopid         routestop.routestop_id%type;
  gv_planneddate         date;
  gv_routeid             route.route_id%type;
  gv_routedate           date;
  gv_packingsequence     product.packingsequence%type;
  gv_stayid              stay.stay_id%type;
  gv_alternatesortstring varchar2(255);
  gv_pnnumber            packingnote.notenumber%type;
  gv_findpackingnote     varchar2(255) := 'Y';
  gv_sortroute           systemsetting.value%type;
  gv_flagcode1           flag.code%type;
  gv_flagcode2           flag.code%type;
  gv_flagcode3           flag.code%type;
  gv_flagcode4           flag.code%type;
  gv_flagdescription1    flag_desc.description%type;
  gv_flagdescription2    flag_desc.description%type;
  gv_flagdescription3    flag_desc.description%type;
  gv_flagdescription4    flag_desc.description%type;
  gv_flagfreetextitem1   uniqueitemflag.freetextitem%type;
  gv_flagfreetextitem2   uniqueitemflag.freetextitem%type;
  gv_flagfreetextitem3   uniqueitemflag.freetextitem%type;
  gv_flagfreetextitem4   uniqueitemflag.freetextitem%type;
  gv_distributionpointid distributionpoint.distributionpoint_id%type;
  gv_uniqueitemid        uniqueitem.uniqueitem_id%type;
  gv_typeofmerchandise   product.typeofmerchandise%type;

  procedure check_stay is
    lv_staynr stay.staynr%type;
  begin
    --check_stay
    gv_message := '';
    select st.staynr into lv_staynr from stay st where st.stay_id = gv_stayid;
    if lv_staynr in (10, 11) then
      begin
        gv_message := 'stay is in stockroom ' || to_char(lv_staynr);
        fp_status  := 3;
        raise gv_exception;
      end;
    end if;
  end check_stay;

  procedure getdepot is
  begin
    --depot
    select nvl(d.code, ' '), nvl(ad.street, ' '), nvl(ad.city, ' ')
    into   fp_depot, fp_depotstreet, fp_depotcity
    from   depot d
    join   route r
    on     r.depot_id = d.depot_id
    join   address ad
    on     ad.address_id = d.address_id
    where  r.route_id = gv_routeid;
  exception
    when no_data_found then
      begin
        fp_depot       := ' ';
        fp_depotstreet := ' ';
        fp_depotcity   := ' ';
      end;
  end getdepot;

  procedure getsortstring is
  begin
    fp_sortstring := pack_sort.buildsortstring(fp_productcode, fp_sizecode, fp_customernumber,
                                               gv_customerid, fp_wearernumber, fp_wearername,
                                               fp_banklocker, fp_department, fp_customeremployee,
                                               fp_gender, fp_garmentdispensercode,
                                               fp_deliverypointcode, fp_stopnumber, gv_plant_paramid,
                                               gv_customerowned, gv_pnnumber, 0, 0, 0, null, ' ', ' ');
    -- sort on route, if SORTROUTE = A or D
    select min(s.value)
    into   gv_sortroute
    from   systemsetting s
    where  s.plant_id = gv_plant_paramid
    and    s.name = 'SORTROUTE';
    if gv_sortroute is not null then
      if gv_sortroute = 'A' then
        -- other option 'A' descending
        fp_sortstring := lpad(to_char(fp_routenumber), 3, '0') || fp_sortstring;
      elsif gv_sortroute = 'D' then
        -- other option 'D' descending
        fp_sortstring := lpad(to_char(999 - fp_routenumber), 3, '0') || fp_sortstring;
      end if;
    end if;
    fp_stackinfo := pack_sort.buildstackchangeinfo(fp_productcode, fp_sizecode, fp_customernumber,
                                                   gv_customerid, fp_wearernumber, fp_wearername,
                                                   fp_banklocker, fp_department, fp_customeremployee,
                                                   fp_gender, fp_garmentdispensercode,
                                                   fp_deliverypointcode, fp_stopnumber,
                                                   gv_plant_paramid, gv_customerowned, gv_pnnumber, 0,
                                                   0, 0, null, ' ', ' ');
  end getsortstring;

  procedure get_finishingmethod is
  begin
    --get_finishingmethod fp_finishingmethod
    select max(f.code), nvl(max(substr(trim(spf.sortaddress), 1, 1)), 'F'),
           nvl(max((select fd.description
                    from   finishingmethod_desc fd
                    where  fd.finishingmethod_id = f.finishingmethod_id
                    and    fd.language_id = gv_languageid)), max(f.code)),
           nvl(max((select fpd.foldingprogram
                    from   foldingprogramdefinition fpd
                    where  fpd.product_id = gv_productid
                    and    fpd.finishingmethod_id = f.finishingmethod_id
                    and    fpd.plant_id = gv_plant_paramid)), ' ')
    into   fp_finishingmethod, fp_deliverytype, fp_finishingmethod_desc, fp_foldingprogram
    from   finishingmethod f
    left   outer join sortaddressperfinishingmeth spf
    on     spf.finishingmethod_id = f.finishingmethod_id
    where  f.finishingmethod_id = gv_finishingmethodid
    group  by f.finishingmethod_id;
  exception
    when others then
      begin
        fp_finishingmethod      := ' ';
        fp_deliverytype         := 'F'; --default as requested by CWS
        fp_finishingmethod_desc := ' ';
        fp_foldingprogram       := ' ';
      end;
  end get_finishingmethod;

  procedure get_destination is
    lv_count number;
  begin
    --Destination
    fp_destinationcode := null;
    select max(saf.sortaddress), count(1)
    into   fp_destinationselection, lv_count
    from   sortaddressperflag saf
    join   flag f
    on     f.flag_id = saf.flag_id
    where  f.flagtype = 1
    and    f.code = substr(fp_flagsinfo, 1, instr(fp_flagsinfo, ':') - 1)
    and    saf.plant_id = gv_plant_garmentid;
    if fp_destinationselection is null and lv_count <> 0 then
      fp_destinationcode := '11'; --hardcode 11 when there is a flag
    end if;
    if fp_destinationselection is null then
      select max(s.sortaddress)
      into   fp_destinationselection
      from   sortaddressperfinishingmeth s
      where  s.finishingmethod_id = gv_finishingmethodid
      and    s.plant_id = gv_plant_paramid;
    end if;
    if fp_destinationcode is null then
      fp_destinationcode := substr(fp_destinationselection, 2); --from second char, sortaddress
    end if;
    fp_destinationselection := nvl(substr(fp_destinationselection, 1, 1), ' '); --only first char, sortaddress
  exception
    when others then
      begin
        fp_destinationcode      := ' ';
        fp_destinationselection := ' ';
      end;
  end get_destination;

  procedure get_extra_product_info is
  begin
    --get_extra_product_info
    select pg.code, p.typeofmerchandise,
           nvl((select pgd.description
                from   productgroup_desc pgd
                where  pgd.productgroup_id = p.productgroup_id
                and    pgd.language_id = gv_languageid), pg.code),
           coalesce((select max(ps.theoreticalweight)
                     from   productsize ps
                     join   sizedefinition s
                     on     s.sizedefinition_id = ps.sizedefinition_id
                     where  ps.product_id = p.product_id
                     and    s.code = fp_sizecode), p.theoreticalweight, 0),
           nvl((select wp.code
                from   washingprocess wp
                where  wp.washingprocess_id =
                       coalesce((select max(l.washingprocess_id)
                                from   productlistpercustomer l
                                where  l.customer_id = gv_customerid
                                and    l.product_id = p.product_id
                                and    sysdate between l.dateactive and l.dateinactive),
                                p.washingprocess_id)), ' ')
    into   fp_productgroupcode, gv_typeofmerchandise, fp_productgroupdesc, fp_theoraticalweight,
           fp_washprocess
    from   product p
    join   productgroup pg
    on     pg.productgroup_id = p.productgroup_id
    where  p.product_id = gv_productid;
  end get_extra_product_info;

  procedure get_deliverypointinfo is
    lv_nextdeldate_customer       date;
    lv_temporaryrentstopstartdate date;
    lv_temporaryrentstopenddate   date;
  begin
    --get_deliverypointinfo
    select nvl(ad.street, ' '), nvl(ad.city, ' '), nvl(ad.street2, ' '), nvl(dp.active, ' '),
           nvl(ad.zipcode, ' '),
           nvl((select l.code from languages l where l.language_id = c.language_id), ' ') language_code
    into   fp_deliverystreet, fp_deliverycity, fp_deliverystreet2, fp_deliverypointstatus,
           fp_deliveryzipcode, fp_custlanguage
    from   deliverypoint dp
    join   customer c
    on     c.customer_id = dp.customer_id
    join   address ad
    on     ad.address_id = dp.deliveryaddress_id
    where  dp.code = trim(fp_deliverypointcode)
    and    dp.customer_id = gv_customerid;
    --get fp_deliverypointstatus
    if fp_deliverypointstatus = 'N' then
      begin
        fp_deliverypointstatus := 'S';
      end;
    else
      begin
        begin
          lv_nextdeldate_customer := pack_sort.getnextdeliverydate(trunc(sysdate), gv_customerid,
                                                                   gv_typeofmerchandise);
        exception
          when no_data_found then
            lv_nextdeldate_customer := trunc(sysdate);
        end;
        --get temporaryrentstop from wearer inv.
        select max(wi.temporaryrentstopstartdate), max(wi.temporaryrentstopenddate)
        into   lv_temporaryrentstopstartdate, lv_temporaryrentstopenddate
        from   uniqueitemnonpool un
        join   wearerinventory wi
        on     wi.wearerinventory_id = un.wearerinventory_id
        where  un.uniqueitem_id = gv_uniqueitemid;
        --check if there is a temporaryrentstop
        if nvl(lv_nextdeldate_customer, trunc(sysdate)) between
           nvl(lv_temporaryrentstopstartdate, trunc(sysdate - 1)) and
           nvl(lv_temporaryrentstopenddate, trunc(sysdate - 1)) then
          fp_deliverypointstatus := 'P';
        else
          fp_deliverypointstatus := 'A';
        end if;
      end;
    end if;
  exception
    when no_data_found then
      begin
        fp_deliverystreet      := ' ';
        fp_deliverycity        := ' ';
        fp_deliverystreet2     := ' ';
        fp_deliverypointstatus := 'A';
      end;
  end get_deliverypointinfo;

  procedure get_image is
  begin
    if gv_imageid is not null then
      --get_image
      select i.imagename into fp_productimage from image i where i.image_id = gv_imageid;
    else
      fp_productimage := ' ';
    end if;
  exception
    when no_data_found then
      begin
        fp_productimage := ' ';
      end;
  end get_image;

  procedure getsendtrackinfo is
    lv_statusid            number;
    lv_dummynumber         number;
    lv_dummystring         varchar2(1000);
    lv_dummydate           date;
    lv_daysinstockprevious number;
    lv_daysincircprevissue number;
    lv_sortaddress         serviceteam.sortaddress%type;
  begin
    --getsendtrackinfo
    pack_sort.getsendtrackinfo(gv_pool, gv_uniqueitemid, gv_stayid, lv_statusid, gv_productid,
                               lv_dummynumber, lv_dummynumber, gv_customerid, fp_lastissuedate,
                               lv_dummynumber, gv_distributionpointid, lv_dummynumber,
                               lv_dummynumber, lv_dummystring, lv_dummynumber, fp_firstissuedate,
                               lv_dummynumber, lv_dummydate, lv_daysinstockprevious, lv_dummydate,
                               lv_daysinstockprevious, lv_daysincircprevissue, lv_dummynumber,
                               lv_dummynumber, lv_dummydate, lv_dummynumber, lv_dummynumber,
                               lv_dummynumber, lv_dummystring);
    --get status code
    select max(st.code) into fp_statuscode from status st where st.status_id = lv_statusid;
    --get distributionpointnumber
    select max(dp.description)
    into   fp_consumptionpoint
    from   distributionpoint dp
    where  dp.distributionpoint_id = gv_distributionpointid;
    fp_consumptionpoint := nvl(fp_consumptionpoint, ' ');
    --calc days in circ.
    fp_daysincirculation := lv_daysincircprevissue + trunc(sysdate) -
                            coalesce(fp_lastissuedate, trunc(sysdate));
    --Modification_Indicator
    select count(1)
    into   lv_dummynumber
    from   uniqueitemmodification um
    where  um.uniqueitem_id = gv_uniqueitemid;
    if lv_dummynumber > 0 then
      begin
        fp_modification_ind := 'V';
      end;
    else
      begin
        fp_modification_ind := ' ';
      end;
    end if;
    --checkpoint selection
    select max(s.sortaddress)
    into   lv_sortaddress
    from   serviceteam s
    where  s.serviceteam_id = gv_serviceteamid;
    if lv_sortaddress is null then
      begin
        fp_checkpointselection  := 'B';
        fp_checkpointsortaddres := 0;
      end;
    else
      begin
        fp_checkpointsortaddres := substr(lv_sortaddress, 2, 2);
        fp_checkpointselection  := substr(lv_sortaddress, 1, 1);
      end;
    end if;
    --finishingcode
    --finishingcode
    select max(s.sortaddress)
    into   lv_sortaddress
    from   finishingcode f
    join   sortaddressperfinishingcode s
    on     s.finishingcode_id = f.finishingcode_id
    where  f.finishingcode_id = gv_finishingcodeid
    and    s.plant_id = gv_plant_paramid;
    if lv_sortaddress is null then
      begin
        fp_finishselection  := 'B';
        fp_finishsortadress := 0;
      end;
    else
      begin
        fp_finishsortadress := substr(lv_sortaddress, 2, 2);
        fp_finishselection  := substr(lv_sortaddress, 1, 1);
      end;
    end if;
  exception
    when no_data_found then
      begin
        fp_consumptionpoint    := ' ';
        fp_firstissuedate      := to_date('1-1-1900', 'dd-mm-yyyy');
        fp_lastissuedate       := to_date('1-1-1900', 'dd-mm-yyyy');
        fp_modification_ind    := ' ';
        fp_checkpointselection := ' ';
        fp_daysincirculation   := 0;
      end;
  end getsendtrackinfo;

  procedure get_deliveryscheme is
  begin
    --get_deliveryscheme
    select min(ds.code)
    into   fp_servicefrequency
    from   customerdeliveryscheme cds
    join   deliveryscheme ds
    on     ds.deliveryscheme_id = cds.deliveryscheme_id
    where  cds.customer_id = gv_customerid;
  exception
    when no_data_found then
      begin
        fp_servicefrequency := ' ';
      end;
  end get_deliveryscheme;

  procedure get_flags is
    lv_counter number := 0;
  begin
    for ff in (select f.code flagcode, nvl(trim(ufx.freetextitem), ' ') freetextitem,
                      nvl((select fd.description
                           from   flag_desc fd
                           where  fd.flag_id = f.flag_id
                           and    fd.language_id = gv_languageid), f.code) flag_description
               from   flag f
               join   (select zz.flag_id, max(zz.freetextitem) freetextitem
                      from   (select uf.flag_id, uf.freetextitem
                               from   uniqueitemflag uf
                               where  uf.uniqueitem_id = gv_uniqueitemid
                               and    uf.startdate <= trunc(sysdate)
                               union all
                               select gv_wearerflagid, null
                               from   dual
                               union all
                               select gv_empflagid, null
                               from   dual) zz
                      group  by zz.flag_id) ufx
               on     ufx.flag_id = f.flag_id
               order  by f.priority asc, f.code asc) loop
      begin
        lv_counter := lv_counter + 1;
        case lv_counter
          when 1 then
            begin
              gv_flagcode1         := ff.flagcode;
              gv_flagdescription1  := ff.flag_description;
              gv_flagfreetextitem1 := ff.freetextitem;
            end;
          when 2 then
            begin
              gv_flagcode2         := ff.flagcode;
              gv_flagdescription2  := ff.flag_description;
              gv_flagfreetextitem2 := ff.freetextitem;
            end;
          when 3 then
            begin
              gv_flagcode3         := ff.flagcode;
              gv_flagdescription3  := ff.flag_description;
              gv_flagfreetextitem3 := ff.freetextitem;
            end;
          when 4 then
            begin
              gv_flagcode4         := ff.flagcode;
              gv_flagdescription4  := ff.flag_description;
              gv_flagfreetextitem4 := ff.freetextitem;
            end;
          else
            exit;
        end case;
      end;
    end loop; --ff
    --build flagsinfo
    fp_flagsinfo := rtrim(trim(case
                                 when gv_flagcode1 is not null then
                                  gv_flagcode1 || ':' || gv_flagdescription1 || '|'
                               end || case
                                 when gv_flagcode2 is not null then
                                  gv_flagcode2 || ':' || gv_flagdescription2 || '|'
                               end || case
                                 when gv_flagcode3 is not null then
                                  gv_flagcode3 || ':' || gv_flagdescription3 || '|'
                               end || case
                                 when gv_flagcode4 is not null then
                                  gv_flagcode4 || ':' || gv_flagdescription4
                               end), '|');
    --build fp_flagsdestination
    fp_flagsdestination := rtrim(trim(case
                                        when gv_flagfreetextitem1 is not null then
                                         gv_flagfreetextitem1 || '|'
                                      end || case
                                        when gv_flagfreetextitem2 is not null then
                                         gv_flagfreetextitem2 || '|'
                                      end || case
                                        when gv_flagfreetextitem3 is not null then
                                         gv_flagfreetextitem3 || '|'
                                      end || case
                                        when gv_flagfreetextitem4 is not null then
                                         gv_flagfreetextitem4
                                      end), '|');
  end get_flags;

  procedure get_companyinfo is
  begin
    --get_companyinfo
    select nvl(pt.name, ' '), nvl(pt.phoneno, ' '), nvl(substr(pt.email, 1, 40), ' ')
    into   fp_companyname, fp_companyphoneno, fp_companyemail
    from   businessunit bu
    join   plant pt
    on     pt.plant_id = bu.plant_id
    where  bu.businessunit_id = gv_businessunitid;
  exception
    when no_data_found then
      begin
        fp_companyname    := ' ';
        fp_companyphoneno := ' ';
        fp_companyemail   := ' ';
      end;
  end get_companyinfo;

  procedure ger_repair_info is
    lv_repaircog     customer.chargerepaircog%type;
    lv_repairlog     customer.chargerepairs%type;
    lv_repairaddress repairaddresspercolor.repairaddress%type;
  begin
    --ger_repair_info
    --repairselection
    if gv_customerid is not null then
      begin
        --repair selection
        /*
        only for LOG
        0 = No Repair allowed  and No charge repair
        1 = Repair allowed and No charge repair
        2 = Repair allowed and Charge repair
        only for COG
        0 = No Repair allowed  and No charge repair
        1 = Repair allowed and No charge repair
        2 = Repair allowed and Charge repair
        */
        fp_repairselection := 'B';
        fp_repaircode      := '0';
        --get COG LOG
        select c.chargerepaircog, c.chargerepairs
        into   lv_repaircog, lv_repairlog
        from   customer c
        where  c.customer_id = gv_customerid;
        --get repair address
        select max(r.repairaddress)
        into   lv_repairaddress
        from   repairaddresspercolor r
        where  r.color_id = gv_colorid
        and    r.plant_id = gv_plant_paramid;
        --get repaircode / selection
        if gv_customerowned = 'Y' then
          if lv_repaircog <> 0 then
            --COG
            fp_repairselection := 'R';
            fp_repaircode      := substr(nvl(lv_repairaddress, '0'), 2, 2);
          end if;
        else
          if lv_repairlog <> 0 then
            --LOG
            fp_repairselection := 'R';
            fp_repaircode      := substr(nvl(lv_repairaddress, '0'), 2, 2);
          end if;
        end if;
      exception
        when no_data_found then
          begin
            fp_repairselection := 'B';
            fp_repaircode      := '0';
          end;
      end;
    else
      begin
        fp_repairselection := 'B';
        fp_repaircode      := '0';
      end;
    end if;
  exception
    when no_data_found then
      begin
        fp_repairselection := 'B';
        fp_repaircode      := '0';
      end;
  end ger_repair_info;

  procedure get_labelprintcode is
  begin
    /* get_labelprintcode
    The following values are expected:
    - A = Delivery point changes
    - B = Locker number changes
    - C = Wearer number changes*/
    fp_labelprintmode := null;
    for x in (select sd.sortfield
              from   sortingdefinition sd
              where  (sd.customer_id = gv_customerid or sd.customer_id is null)
              and    sd.stackchange = 'Y'
              order  by nvl(sd.customer_id, 9999999999), sd.priority) loop
      begin
        case x.sortfield
          when 9 then
            --Delivery Point
            fp_labelprintmode := 'A';
          when 2 then
            --Wearer Number
            fp_labelprintmode := 'C';
          when 3 then
            --Wearer Name
            fp_labelprintmode := 'C';
          when 5 then
            --Bank/Locker
            fp_labelprintmode := 'C';
          when 13 then
            --Bank
            fp_labelprintmode := 'B';
          else
            fp_labelprintmode := 'A';
        end case;
        exit;
      end;
    end loop; --x
  exception
    when no_data_found then
      fp_labelprintmode := 'A';
  end get_labelprintcode;

  procedure fill_null_values is
  begin
    --fill_null_values
    fp_productcode          := nvl(fp_productcode, ' ');
    fp_sizecode             := nvl(fp_sizecode, ' ');
    fp_customernumber       := nvl(fp_customernumber, 0);
    fp_wearernumber         := nvl(fp_wearernumber, 0);
    fp_routenumber          := nvl(fp_routenumber, 0);
    fp_routeday             := nvl(fp_routeday, 0);
    fp_stopnumber           := nvl(fp_stopnumber, 0);
    fp_washestotal          := nvl(fp_washestotal, 0);
    fp_stackinfo            := nvl(fp_stackinfo, ' ');
    fp_sortstring           := nvl(fp_sortstring, ' ');
    fp_productdescription   := nvl(fp_productdescription, ' ');
    fp_secondaryid          := nvl(fp_secondaryid, ' ');
    fp_routecodeonlabel     := nvl(fp_routecodeonlabel, ' ');
    fp_customeremployee     := nvl(fp_customeremployee, ' ');
    fp_firstissuedate       := nvl(fp_firstissuedate, to_date('1-1-1900', 'dd-mm-yyyy'));
    fp_lastissuedate        := nvl(fp_lastissuedate, to_date('1-1-1900', 'dd-mm-yyyy'));
    fp_customername         := nvl(fp_customername, ' ');
    fp_department           := nvl(fp_department, 0);
    fp_wearername           := nvl(fp_wearername, ' ');
    fp_banklocker           := nvl(fp_banklocker, ' ');
    fp_garmentdispensercode := nvl(fp_garmentdispensercode, ' ');
    fp_gender               := nvl(fp_gender, ' ');
    fp_deliverypointcode    := nvl(fp_deliverypointcode, ' ');
    fp_labelprintmode       := nvl(fp_labelprintmode, 'A');
    fp_repairselection      := nvl(fp_repairselection, 'B');
    fp_repaircode           := nvl(fp_repaircode, '0');
    fp_checkpointselection  := nvl(fp_checkpointselection, 'B');
    fp_checkpointsortaddres := nvl(fp_checkpointsortaddres, '0');
    fp_finishselection      := nvl(fp_finishselection, 'B');
    fp_finishsortadress     := nvl(fp_finishsortadress, '0');
    fp_consumptionpoint     := nvl(fp_consumptionpoint, ' ');
    fp_modification_ind     := nvl(fp_modification_ind, ' ');
    fp_daysincirculation    := nvl(fp_daysincirculation, 0);
    fp_finishingmethod      := nvl(fp_finishingmethod, ' ');
    fp_deliverytype         := nvl(fp_deliverytype, 'F');
    fp_finishingmethod_desc := nvl(fp_finishingmethod_desc, ' ');
    fp_foldingprogram       := nvl(fp_foldingprogram, ' ');
    fp_week                 := nvl(fp_week, 0);
    fp_productimage         := nvl(fp_productimage, ' ');
    fp_depot                := nvl(fp_depot, ' ');
    fp_depotstreet          := nvl(fp_depotstreet, ' ');
    fp_depotcity            := nvl(fp_depotcity, ' ');
    fp_deliverystreet       := nvl(fp_deliverystreet, ' ');
    fp_deliverycity         := nvl(fp_deliverycity, ' ');
    fp_companyname          := nvl(fp_companyname, ' ');
    fp_companyphoneno       := nvl(fp_companyphoneno, ' ');
    fp_companyemail         := nvl(fp_companyemail, ' ');
    fp_uniqueitemid         := nvl(fp_uniqueitemid, 0);
    fp_productgroupcode     := nvl(fp_productgroupcode, ' ');
    fp_productgroupdesc     := nvl(fp_productgroupdesc, ' ');
    fp_washprocess          := nvl(fp_washprocess, ' ');
    fp_deliverystreet2      := nvl(fp_deliverystreet2, ' ');
    fp_deliverypointstatus  := nvl(fp_deliverypointstatus, ' ');
    fp_deliveryzipcode      := nvl(fp_deliveryzipcode, ' ');
    fp_custlanguage         := nvl(fp_custlanguage, ' ');
    fp_theoraticalweight    := nvl(fp_theoraticalweight, 0);
    fp_deliverydaymask      := nvl(fp_deliverydaymask, ' ');
    fp_statuscode           := nvl(fp_statuscode, ' ');
    fp_flagsinfo            := nvl(fp_flagsinfo, ' ');
    fp_flagsdestination     := nvl(fp_flagsdestination, ' ');
    fp_destinationcode      := nvl(fp_destinationcode, ' ');
    fp_destinationselection := nvl(fp_destinationselection, ' ');
    fp_servicefrequency     := nvl(fp_servicefrequency, ' ');
  end fill_null_values;
begin
  fp_status := null;
  --check to make sure Input Parameters are not NULL
  if fp_garmentid is null or fp_plantcode is null or fp_languagecode is null then
    begin
      gv_message := 'Parameters  fp_garmentid, fp_plantcode nor fp_languagecode cannot be left blank!';
      raise gv_exception;
    end;
  else
    begin
      --get language id
      select l.language_id
      into   gv_languageid
      from   languages l
      where  l.code = trim(upper(fp_languagecode));
    exception
      when no_data_found then
        begin
          gv_message := 'fp_languagecode ' || trim(upper(fp_languagecode)) || ' does not exist!';
          raise gv_exception;
        end;
    end;
  end if;
  --determinegarmentid
  pack_sort.determinegarmentid('METRIC', fp_garmentid, fp_plantcode, gv_uniqueitemid, gv_pool,
                               gv_businessunitcode, gv_businessunitid, gv_plant_garmentid,
                               gv_returnedplantcode, fp_status, gv_idprimary, gv_plant_paramid,
                               fp_secondaryid);
  --getsystemsettings
  pack_sort.getsystemsettings(gv_plant_paramid, gv_debuglevel, gv_dummy, gv_dummy);
  --getgarmentdatainfo
  pack_sort.getgarmentdatainfo('METRIC', gv_plant_paramid, gv_uniqueitemid, gv_languageid,
                               gv_finishingcodeid, gv_serviceteamid, gv_chargerepairs,
                               gv_customerowned, gv_colorid, gv_wearerflagid, gv_wearerflagstartdate,
                               gv_empflagid, gv_empflagstartdate, gv_finishingmethodid, gv_productid,
                               fp_productcode, fp_productdescription, fp_sizecode, fp_customernumber,
                               gv_customerid, fp_customername, fp_wearernumber, fp_wearername,
                               fp_banklocker, fp_department, fp_customeremployee, fp_gender,
                               fp_garmentdispensercode, fp_deliverypointcode, gv_wearerremark,
                               fp_routenumber, fp_routeday, fp_stopnumber, gv_packingsequence,
                               gv_stayid, gv_routeid, gv_imageid, gv_routestopid, gv_planneddate,
                               fp_status, gv_alternatesortstring, gv_debuglevel, gv_findpackingnote,
                               gv_pnnumber, gv_routedate, fp_washestotal, fp_routecodeonlabel,
                               gv_plant_paramid, gv_sortcustomerid);
  --check stay
  check_stay;
  --get planned week
  if gv_planneddate is not null then
    fp_week := getisoweek(gv_planneddate);
  else
    fp_week := 0;
  end if;
  --getdeliverydaysmask
  pack_sort.getdeliverydaysmask(gv_customerid, fp_deliverydaymask);
  --getdepot
  getdepot;
  --getsortstring
  getsortstring;
  --get finishingmethod
  get_finishingmethod;
  --get_extra_product_info
  get_extra_product_info;
  --get_deliverypointinfo
  get_deliverypointinfo;
  --get image
  get_image;
  --getsendtrackinfo
  getsendtrackinfo;
  --get deliveryscheme
  get_deliveryscheme;
  --get flags
  get_flags;
  --get_destination
  get_destination;
  --get company info
  get_companyinfo;
  --get repair info
  ger_repair_info;
  --get_labelprintcode
  get_labelprintcode;
  --fill primary id
  fp_uniqueitemid := fp_garmentid;
  --fill_null_values
  fill_null_values;
exception
  when gv_exception then
    begin
      --wrong or empty (NULL) parameter
      fp_status := nvl(fp_status, 1);
      fill_null_values;
      pack_sort.write_logging(fp_garmentid || ' ' || gv_message, nvl(gv_debuglevel, 1),
                              'GETGARMENTDATASMARTLINE', gv_plant_paramid, 3, 1);
    end;
  when no_data_found then
    begin
      fp_status := 2;
      fill_null_values;
      pack_sort.write_logging(fp_garmentid || ' ' || sqlerrm, nvl(gv_debuglevel, 1),
                              'GETGARMENTDATASMARTLINE', gv_plant_paramid, 3, 1);
    end;
  when others then
    begin
      fp_status := 9;
      fill_null_values;
      pack_sort.write_logging(fp_garmentid || ' ' || sqlerrm, nvl(gv_debuglevel, 1),
                              'GETGARMENTDATASMARTLINE', gv_plant_paramid, 3, 1);
    end;
end getgarmentdatasmartline;
/
create or replace procedure getgarmentdatasortbatch(idcode                 in uniqueitem.primaryid%type,
                                                    plantcode              in out plant.code%type,
                                                    unitcode               out nocopy businessunit.code%type,
                                                    status                 out nocopy integer,
                                                    finishselection        out nocopy varchar2, --(6),
                                                    checkpointselection    out nocopy varchar2, --(6),
                                                    repairselection        out nocopy varchar2, --(6),
                                                    destination            out nocopy varchar2, --(6),
                                                    foldprogram            out nocopy varchar2, --(6),
                                                    stackchangeinfo        out nocopy varchar2, --(60),
                                                    routenumber            out nocopy route.routenumber%type,
                                                    routeday               out nocopy route.drivingday_id%type,
                                                    depot                  out nocopy depot.code%type,
                                                    sortstring             out nocopy varchar2,
                                                    alternatesortstring    out nocopy varchar2,
                                                    stopnumber             out nocopy routestop.stopnumber%type,
                                                    customernumber         out nocopy customer.customernumber%type,
                                                    customername           out nocopy customer.name%type,
                                                    wearernumber           out nocopy wearer.wearernumber%type,
                                                    wearername             out nocopy wearer.searchname%type,
                                                    banklocker             out nocopy varchar2,
                                                    department             out nocopy department.departmentnumber%type,
                                                    customeremployeenumber out nocopy wearer.customeremployeenumber%type,
                                                    gender                 out nocopy wearer.sex%type,
                                                    garmentdispensercode   out nocopy garmentdispenser.code%type,
                                                    deliverypointcode      out nocopy deliverypoint.code%type,
                                                    productcode            out nocopy product.code%type,
                                                    productdescription     out nocopy product_desc.description%type,
                                                    sizecode               out nocopy sizedefinition.code%type,
                                                    productpicturecode     out nocopy image.code%type,
                                                    deliverydaymask        out nocopy varchar2,
                                                    secondaryid            out nocopy secondaryuniqueitem.secondaryid%type,
                                                    flagcode1              out nocopy sortaddressperflag.sortaddress%type,
                                                    flagcode2              out nocopy sortaddressperflag.sortaddress%type,
                                                    flagcode3              out nocopy sortaddressperflag.sortaddress%type,
                                                    flagcode4              out nocopy sortaddressperflag.sortaddress%type,
                                                    flagdescription1       out nocopy flag_desc.description%type,
                                                    flagdescription2       out nocopy flag_desc.description%type,
                                                    flagdescription3       out nocopy flag_desc.description%type,
                                                    flagdescription4       out nocopy flag_desc.description%type,
                                                    infotext               out nocopy wearer.remark%type,
                                                    staycode               out nocopy varchar2,
                                                    sortbatchnumber        out nocopy sortbatch.sortbatch_id%type,
                                                    alphaspare1            out nocopy varchar2,
                                                    alphaspare2            out nocopy varchar2,
                                                    alphaspare3            out nocopy varchar2,
                                                    alphaspare4            out nocopy varchar2,
                                                    alphaspare5            out nocopy varchar2,
                                                    numberspare1           out nocopy number,
                                                    numberspare2           out nocopy number,
                                                    numberspare3           out nocopy number,
                                                    numberspare4           out nocopy number,
                                                    numberspare5           out nocopy number) is
  --procedure getgarmentdatasortbatch version 1.1
  uniqueitemid uniqueitem.uniqueitem_id%type;
  --overalluniquegarmentID DATABASESETTINGS.OVERALLUNIQUEGARMENTID%type;
  plantid_param       plant.plant_id%type;
  plantid_garment     plant.plant_id%type;
  languageid          languages.language_id%type;
  pool                uniqueitem.poolitem%type;
  imageid             image.image_id%type;
  customerid          customer.customer_id%type;
  finishingcodeid     finishingcode.finishingcode_id%type;
  serviceteamid       serviceteam.serviceteam_id%type;
  colorid             color.color_id%type;
  finishingmethodid   finishingmethod.finishingmethod_id%type;
  productid           product.product_id%type;
  packingsequence     product.packingsequence%type;
  routeid             route.route_id%type;
  routestopid         routestop.routestop_id%type;
  businessunitid      integer;
  wearerflagid        flag.flag_id%type;
  wearerflagstartdate date;
  empflagid           flag.flag_id%type;
  empflagstartdate    date;
  debuglevel          integer;
  stayid              stay.stay_id%type;
  staynumber          stay.staynr%type;
  allowrepairscan     integer;
  vchargerepairs      customer.chargerepairs%type;
  vcustomerowned      uniqueitem.customerowned%type;
  flagsinfo           varchar2(500);
  destinationstring   varchar2(3);
  plannnedoutdate     date;
  returnedplantcode   plant.code%type;
  findpackingnote     varchar2(20);
  ordernumber         integer;
  --Order 502022
  routedate date;
  --Todo 6660
  idprimary      uniqueitem.primaryid%type; --is never used in this procedure
  lv_washestotal uniqueitem.washestotal%type;
  lv_dummy       varchar2(255);
  --Order 20012033
  routecodeonlabel  route.codeonlabel%type;
  gv_sortcustomerid customer.sortcustomer_id%type;
  lockersortgroup#    lockersortgroup.lockersortgroupnumber%type;
  distributionpoint#  distributionpoint.distributionpointnumber%type;
  lv_seasoncode       season.code%type;
begin
  routedate := sysdate;
  pack_sort.determinegarmentid('SORTBATCH', idcode, plantcode, uniqueitemid, pool, unitcode,
                               businessunitid, plantid_garment, returnedplantcode,
                               --not used here
                               status, idprimary, plantid_param, secondaryid);
  begin
    pack_sort.getsystemsettings(plantid_param, debuglevel, lv_dummy, allowrepairscan);
    ---------------------------------------------------------------
    --other fields
    if status = 0 then
      begin
        findpackingnote := '';
        ordernumber     := 0;
        pack_sort.getgarmentdatainfo('SORTBATCH', plantid_garment, uniqueitemid, languageid,
                                     finishingcodeid, serviceteamid, vchargerepairs, vcustomerowned,
                                     colorid, wearerflagid, wearerflagstartdate, empflagid,
                                     empflagstartdate, finishingmethodid, productid, productcode,
                                     productdescription, sizecode, customernumber, customerid,
                                     customername, wearernumber, wearername, banklocker, department,
                                     customeremployeenumber, gender, garmentdispensercode,
                                     deliverypointcode, infotext, routenumber, routeday, stopnumber,
                                     packingsequence, stayid, routeid, imageid, routestopid,
                                     plannnedoutdate, status, alternatesortstring, debuglevel,
                                     findpackingnote, ordernumber, routedate, lv_washestotal,
                                     routecodeonlabel, null, gv_sortcustomerid);
        if status = 0 then
          begin
            select stay.staynr into staynumber from stay where stay.stay_id = stayid;
            staycode := staynumber;
          exception
            when others then
              null;
          end;
          begin
            --image code
            select i.code into productpicturecode from image i where i.image_id = imageid;
          exception
            when no_data_found then
              null;
          end;
          pack_sort.getdeliverydaysmask(customerid, deliverydaymask);
          begin
            --depot
            select d.code
            into   depot
            from   depot d, route r
            where  r.route_id = routeid
            and    r.depot_id = d.depot_id;
          exception
            when no_data_found then
              depot := 0;
          end;
          --  end; -- finish nonpool items
          begin
            --finishingcode
            select nvl(max(s.sortaddress), 0)
            into   finishselection
            from   sortaddressperfinishingcode s
            where  s.finishingcode_id = finishingcodeid
            and    s.plant_id = plantid_param;
          exception
            when no_data_found then
              null;
          end;
          begin
            --checkpoint selection
            select s.sortaddress
            into   checkpointselection
            from   serviceteam s
            where  s.serviceteam_id = serviceteamid;
          exception
            when no_data_found then
              null;
          end;
          begin
            --repair selection
            repairselection := '1';
            if vchargerepairs = 0 and (allowrepairscan in (2, 4)) then
              repairselection := '';
            end if;
            if (allowrepairscan in (3, 4) and vcustomerowned = 'Y') then
              repairselection := '';
            end if;
            if repairselection = '1' then
              repairselection := '';
              select r.repairaddress
              into   repairselection
              from   repairaddresspercolor r
              where  r.color_id = colorid
              and    r.plant_id = plantid_param;
            end if;
          exception
            when no_data_found then
              null;
          end;
          begin
            --Destination
            select s.sortaddress
            into   destination
            from   sortaddressperfinishingmeth s
            where  s.finishingmethod_id = finishingmethodid
            and    s.plant_id = plantid_param;
          exception
            when no_data_found then
              destination := 0;
          end;
          begin
            --fold program
            select f.foldingprogram
            into   foldprogram
            from   foldingprogramdefinition f
            where  f.product_id = productid
            and    f.finishingmethod_id = finishingmethodid
            and    f.plant_id = plantid_param;
          exception
            when no_data_found then
              null;
              if debuglevel > 0 then
                pack_sort.write_logging('Error for IDCODE ' || idcode ||
                                        'Folding Program not found' || sqlcode || ' ' || sqlerrm,
                                        debuglevel, 'GETGARMENTDATASORTBATCH', plantid_param, 3,
                                        1);
              end if;
          end;
          begin
            select nvl(lsg.lockersortgroupnumber, 0), di.distributionpointnumber,
                  (select ss.code --show season when NOT in the season!!
                   from   season ss
                   where  ss.season_id = wi.season_id
                   and    not exists (select 1
                           from   seasonweek sw
                           where  sw.season_id = ss.season_id
                           and    sw.weeknumber = getisoweek(sysdate))) seasoncode
            into   lockersortgroup#, distributionpoint#, lv_seasoncode
            from   uniqueitemnonpool n
            join   weareremployment e on e.weareremployment_id = n.weareremployment_id
            join   wearerinventory wi on wi.wearerinventory_id = n.wearerinventory_id
            join   distributionpoint di on di.distributionpoint_id = e.distributionpoint_id
            left   outer join(locker l
            join   lockersortgroup lsg
            -- Order 20013679, use external locker when not null e.locker_id  replaced with nvl(e.externallocker_id,e.locker_id)
            on     l.lockersortgroup_id = lsg.lockersortgroup_id) on nvl(e.externallocker_id, e.locker_id) = l.locker_id
            -- End Order 20013679
            where  n.uniqueitem_id = uniqueitemid;
          exception
            when others then
              lockersortgroup#   := 0;
              distributionpoint# := 0;
              lv_seasoncode      := ' ';
          end;
          --Alternate Sort String
          --order 501273
          if alternatesortstring = 'Y' then
            alternatesortstring := packingsequence;
          else
            alternatesortstring := '';
          end if;
          if gv_sortcustomerid is not null then
            begin
              --get sort customer stopnumber for route found
               select nvl(min(rs.stopnumber),0) into stopnumber
               from routestop rs join route r on r.route_id = rs.routestop_id
               where r.routenumber = routenumber
              and    r.drivingday_id = routeday
              and    rs.customer_id = gv_sortcustomerid
              and    trunc(sysdate) between rs.dateactive and rs.dateinactive;
            end;
          end if;
          sortstring      := pack_sort.buildsortstring(productcode, sizecode, customernumber,
                                                       customerid, wearernumber, wearername,
                                                       banklocker, department, customeremployeenumber,
                                                       gender, garmentdispensercode,
                                                       deliverypointcode, stopnumber, plantid_param,
                                                       vcustomerowned, ordernumber, 0, lockersortgroup#,
                                                       distributionpoint#, gv_sortcustomerid, lv_seasoncode, finishselection);
          stackchangeinfo := pack_sort.buildstackchangeinfo(productcode, sizecode, customernumber,
                                                            customerid, wearernumber, wearername,
                                                            banklocker, department,
                                                            customeremployeenumber, gender,
                                                            garmentdispensercode, deliverypointcode,
                                                            stopnumber, plantid_param, vcustomerowned,
                                                            ordernumber, 0, lockersortgroup#, distributionpoint#,
                                                            gv_sortcustomerid, lv_seasoncode, finishselection);
          --flags
          pack_sort.getflags(uniqueitemid, plantid_param, wearerflagid, wearerflagstartdate, empflagid,
                             empflagstartdate, languageid, 4, flagcode1, flagcode2, flagcode3,
                             flagcode4, flagdescription1, flagdescription2, flagdescription3,
                             flagdescription4, flagsinfo, destinationstring, 'N',lv_dummy,lv_dummy,lv_dummy,lv_dummy);
        else
          pack_sort.write_logging('Error for IDCODE ' || idcode ||
                                  ' DELIVERYSCHEME OR ROUTE STOPS NOT DEFINED FOR CUSTOMER' ||
                                  customernumber, debuglevel, 'GETGARMENTDATASORTBATCH',
                                  plantid_param, 3, 1);
        end if; --for stATUS=0
      end;
      --added for Sort Batch      --
      begin
        --according with Erick changes from 07.07.2005
        select b.sortbatch_id, r.routenumber, rs.stopnumber, r.drivingday_id
        into   sortbatchnumber, routenumber, stopnumber, routeday
        from   sortbatch b
        join   sortbatchcontents c
        on     c.sortbatch_id = b.sortbatch_id
        join   routestop rs
        on     rs.routestop_id = c.routestop_id
        join   route r
        on     r.route_id = rs.route_id
        where  c.uniqueitem_id = uniqueitemid
        and    c.expectationlevel > 0
        and    b.status >= 1
        and    b.sortbatch_id = (select max(s.sortbatch_id)
                                 from   sortbatchcontents sc, sortbatch s
                                 where  sc.uniqueitem_id = uniqueitemid
                                 and    sc.sortbatch_id = s.sortbatch_id
                                 and    sc.expectationlevel > 0
                                 and    s.status >= 1);
      exception
        when others then
          sortbatchnumber := 0;
      end;
    end if;
    pack_sort.writelogfile('SORTBATCH', debuglevel, plantcode, idcode, unitcode, status,
                           finishselection, checkpointselection, repairselection, destination,
                           foldprogram, stackchangeinfo, routenumber, stopnumber, routeday, depot,
                           sortstring, alternatesortstring, customernumber, customername,
                           wearernumber, wearername, department, customeremployeenumber, gender,
                           banklocker, garmentdispensercode, deliverypointcode, productcode,
                           productdescription, sizecode, productpicturecode, deliverydaymask,
                           secondaryid, flagcode1, flagcode2, flagcode3, flagcode4, flagdescription1,
                           flagdescription2, flagdescription3, flagdescription4, infotext, '', '',
                           staycode, sortbatchnumber, ' ');
  exception
    when others then
      pack_sort.write_logging(idcode || ' ' || sqlerrm, debuglevel, 'GETGARMENTDATASORTBATCH',
                              plantid_param, 3, 1);
  end;
end getgarmentdatasortbatch;
/
create or replace procedure getgarmentdataui(idcode                     in uniqueitem.primaryid%type,
                                             plantcode                  in plant.code%type,
                                             unitcode                   out nocopy businessunit.code%type,
                                             status                     out nocopy integer,
                                             finishselection            out nocopy varchar2, --(6),
                                             checkpointselection        out nocopy varchar2, --(6),
                                             repairselection            out nocopy varchar2, --(6),
                                             destination                out nocopy varchar2, --(6),
                                             foldprogram                out nocopy varchar2, --(6),
                                             stackchangeinfo            out nocopy varchar2, --(60),
                                             routenumber                out nocopy route.routenumber%type,
                                             routeday                   out nocopy route.drivingday_id%type,
                                             depot                      out nocopy depot.code%type,
                                             sortstring                 out nocopy varchar2,
                                             alternatesortstring        out nocopy varchar2,
                                             stopnumber                 out nocopy routestop.stopnumber%type,
                                             customernumber             out nocopy customer.customernumber%type,
                                             customername               out nocopy customer.name%type,
                                             wearernumber               out nocopy wearer.wearernumber%type,
                                             wearername                 out nocopy wearer.searchname%type,
                                             banklocker                 out nocopy varchar2,
                                             department                 out nocopy department.departmentnumber%type,
                                             customeremployeenumber     out nocopy wearer.customeremployeenumber%type,
                                             gender                     out nocopy wearer.sex%type,
                                             garmentdispensercode       out nocopy garmentdispenser.code%type,
                                             deliverypointcode          out nocopy deliverypoint.code%type,
                                             productcode                out nocopy product.code%type,
                                             productdescription         out nocopy product_desc.description%type,
                                             sizecode                   out nocopy sizedefinition.code%type,
                                             productpicturecode         out nocopy image.code%type,
                                             deliverydaymask            out nocopy varchar2,
                                             secondaryid                out nocopy secondaryuniqueitem.secondaryid%type,
                                             flagcode1                  out nocopy sortaddressperflag.sortaddress%type,
                                             flagcode2                  out nocopy sortaddressperflag.sortaddress%type,
                                             flagcode3                  out nocopy sortaddressperflag.sortaddress%type,
                                             flagcode4                  out nocopy sortaddressperflag.sortaddress%type,
                                             flagdescription1           out nocopy flag_desc.description%type,
                                             flagdescription2           out nocopy flag_desc.description%type,
                                             flagdescription3           out nocopy flag_desc.description%type,
                                             flagdescription4           out nocopy flag_desc.description%type,
                                             infotext                   out nocopy wearer.remark%type,
                                             requiredrepairs            out nocopy varchar2,
                                             userinstructionsloading    out nocopy varchar2,
                                             userinstructionscheckpoint out nocopy varchar2,
                                             userinstructionsrepair     out nocopy varchar2,
                                             userinstructionsdivorce    out nocopy varchar2,
                                             spare1                     out nocopy varchar2,
                                             spare2                     in out nocopy varchar2,
                                             customerrankingdesc        out nocopy varchar2,
                                             imagecode                  out nocopy varchar2,
                                             repaircodes                out nocopy varchar2,
                                             repairxcoordinates         out nocopy varchar2,
                                             repairycoordinates         out nocopy varchar2,
                                             residualvalue              out nocopy number) is
  --procedure getgarmentdataui version 2.0
  flagfreetext1     uniqueitemflag.freetextitem%type;
  flagfreetext2     uniqueitemflag.freetextitem%type;
  flagfreetext3     uniqueitemflag.freetextitem%type;
  flagfreetext4     uniqueitemflag.freetextitem%type;
  routecodeonlabel  route.codeonlabel%type;
  lv_languageid     languages.language_id%type;
  lv_customernumber customer.customernumber%type;
-- RVI 20150209, Begin
  NOOFWASHES                              integer;
  DEFBYPASSCHECK                          flag.code%type;
  UI_WASHESTOTAL                          uniqueitem.washestotal%type;
  M_BYPASS_CHECKPOINT_FLAG_ID             flag.flag_id%type;
  M_BYPASS_SORTADDRESS                    sortaddressperflag.sortaddress%type;
  PLPC_NOOFWASHESNOCHECKPOINT             productlistpercustomer.noofwashesnocheckpoint%type;
  PRODUCT_NOOFWASHES                      product.noofwashesnocheckpoint%type;
  fill_flags        boolean; --used for determining when to fill flags; SO 20012728
-- RVI 20150209, End
-- RVI 20150218, Begin
  M_BYPASS_FLAG_DESCRIPTION               flag_desc.description%type;
  -- RVI 20150218, End
  lv_uniqueitemid number;
  lv_poolitem     number;
  lv_countbarcode number;

  procedure getrepaircodes is
  begin
    --getrepaircodes
    for x in (select lpad(substr(nvl((select max(prts.exportcode)
                                      from   plantrepairtypesettings prts
                                      join   plant pt
                                      on     pt.plant_id = prts.plant_id
                                      where  prts.repairtype_id = rp.repairtype_id
                                      and    pt.code = plantcode), rt.code), 1, 2), 2, '0') repaircodes,
                     lpad(to_char(case
                                    when rp.xcoordinate >= 100 then
                                     99
                                    else
                                     rp.xcoordinate
                                  end), 2, '0') xcoordinate,
                     lpad(to_char(case
                                    when rp.ycoordinate >= 100 then
                                     99
                                    else
                                     rp.ycoordinate
                                  end), 2, '0') ycoordinate
              from   repairpointer rp
              join   repairtype rt
              on     rt.repairtype_id = rp.repairtype_id
              where  rp.uniqueitem_id = lv_uniqueitemid
              order  by rp.sequencenumber) loop
      begin
        repaircodes        := repaircodes || x.repaircodes;
        repairxcoordinates := repairxcoordinates || x.xcoordinate;
        repairycoordinates := repairycoordinates || x.ycoordinate;
      end;
    end loop; --x
    repaircodes        := substr(repaircodes, 1, 20);
    repairxcoordinates := substr(repairxcoordinates, 1, 20);
    repairycoordinates := substr(repairycoordinates, 1, 20);
  exception
    when no_data_found then
      begin
        repaircodes        := null;
        repairxcoordinates := null;
        repairycoordinates := null;
      end;
  end getrepaircodes;
begin
  getgarmentdatabasic(idcode, plantcode, unitcode, status, finishselection, checkpointselection,
                      repairselection, destination, foldprogram, stackchangeinfo, routenumber,
                      routeday, depot, sortstring, alternatesortstring, stopnumber, customernumber,
                      customername, wearernumber, wearername, banklocker, department,
                      customeremployeenumber, gender, garmentdispensercode, deliverypointcode,
                      productcode, productdescription, sizecode, productpicturecode, deliverydaymask,
                      secondaryid, flagcode1, flagcode2, flagcode3, flagcode4, flagdescription1,
                      flagdescription2, flagdescription3, flagdescription4, infotext,
                      requiredrepairs, spare1, spare2, flagfreetext1, flagfreetext2, flagfreetext3,
                      flagfreetext4, routecodeonlabel);
  if status = 0 then
    begin
      --ABS-65229
      select max(u.residualvalueamount), count(1), max(u.uniqueitem_id),
             max((select i.code from image i where i.image_id = p.image_id)), max(u.poolitem)
      into   residualvalue, lv_countbarcode,lv_uniqueitemid, imagecode, lv_poolitem
      from   uniqueitem u
      join   product p
      on     p.product_id = u.product_id
      where  u.primaryid = idcode;
      --getrepaircodes
      getrepaircodes;
      --
      begin
        select pt.language_id into lv_languageid from plant pt where pt.code = plantcode;
      exception
        when no_data_found then
          lv_languageid := 1;
      end;
      --needed because customernumber is also a field!!
      lv_customernumber := customernumber;
      --get customerrankingdesc
      select max(cr.ranking)
      into   customerrankingdesc
      from   customer c
      join   customerranking cr
      on     cr.customerranking_id = c.customerranking_id
      where  c.customernumber = lv_customernumber;
      --sSortingSystemLoading
      userinstructionsloading := null;
      for a in (select 1 prio, cui.dateactive,
                       (select dbms_lob.substr(cuide.instruction, 80, 1)
                         from   customeruserinstruction_desc cuide
                         where  cuide.customeruserinstruction_id = us.customeruserinstruction_id
                         and    cuide.language_id = lv_languageid) instruction
                from   userinstructionperscreen us
                join   customeruserinstruction cui
                on     (cui.customeruserinstruction_id = us.customeruserinstruction_id and
                       sysdate between cui.dateactive and cui.dateinactive and
                       sysdate < cui.enddateautomsg)
                join   customer c
                on     (c.customer_id = cui.customer_id and c.customernumber = lv_customernumber)
                where  us.dialog_id =
                       (select pdf.dialog_id from dialogs pdf where pdf.code = 'SortingSystemLoading')
                union
                select 2 prio, gui.dateactive,
                       (select dbms_lob.substr(guide.instruction, 80, 1)
                         from   generaluserinstruction_desc guide
                         where  guide.generaluserinstruction_id = us.generaluserinstruction_id
                         and    guide.language_id = lv_languageid) instruction
                from   userinstructionperscreen us
                join   generaluserinstructionpercust guc
                on     guc.generaluserinstruction_id = us.generaluserinstruction_id
                join   customer c
                on     (c.customer_id = guc.customer_id and c.customernumber = lv_customernumber)
                join   generaluserinstruction gui
                on     (gui.generaluserinstruction_id = us.generaluserinstruction_id and
                       sysdate between gui.dateactive and gui.dateinactive and
                       sysdate < gui.enddateautomsg)
                where  us.dialog_id =
                       (select pdf.dialog_id from dialogs pdf where pdf.code = 'SortingSystemLoading')
                order  by 1, 2 desc) loop
        begin
          userinstructionsloading := a.instruction;
          exit;
        end;
      end loop;
      --SortingSystemCheckpoint
      userinstructionscheckpoint := null;
      for b in (select 1 prio, cui.dateactive,
                       (select dbms_lob.substr(cuide.instruction, 80, 1)
                         from   customeruserinstruction_desc cuide
                         where  cuide.customeruserinstruction_id = us.customeruserinstruction_id
                         and    cuide.language_id = lv_languageid) instruction
                from   userinstructionperscreen us
                join   customeruserinstruction cui
                on     (cui.customeruserinstruction_id = us.customeruserinstruction_id and
                       sysdate between cui.dateactive and cui.dateinactive and
                       sysdate < cui.enddateautomsg)
                join   customer c
                on     (c.customer_id = cui.customer_id and c.customernumber = lv_customernumber)
                where  us.dialog_id = (select pdf.dialog_id
                                       from   dialogs pdf
                                       where  pdf.code = 'SortingSystemCheckpoint')
                union
                select 2 prio, gui.dateactive,
                       (select dbms_lob.substr(guide.instruction, 80, 1)
                         from   generaluserinstruction_desc guide
                         where  guide.generaluserinstruction_id = us.generaluserinstruction_id
                         and    guide.language_id = lv_languageid) instruction
                from   userinstructionperscreen us
                join   generaluserinstructionpercust guc
                on     guc.generaluserinstruction_id = us.generaluserinstruction_id
                join   customer c
                on     (c.customer_id = guc.customer_id and c.customernumber = lv_customernumber)
                join   generaluserinstruction gui
                on     (gui.generaluserinstruction_id = us.generaluserinstruction_id and
                       sysdate between gui.dateactive and gui.dateinactive and
                       sysdate < gui.enddateautomsg)
                where  us.dialog_id = (select pdf.dialog_id
                                       from   dialogs pdf
                                       where  pdf.code = 'SortingSystemCheckpoint')
                order  by 1, 2 desc) loop
        begin
          userinstructionscheckpoint := b.instruction;
          exit;
        end;
      end loop;
      --SortingSystemRepair
      userinstructionsrepair := null;
      for c in (select 1 prio, cui.dateactive,
                       (select dbms_lob.substr(cuide.instruction, 80, 1)
                         from   customeruserinstruction_desc cuide
                         where  cuide.customeruserinstruction_id = us.customeruserinstruction_id
                         and    cuide.language_id = lv_languageid) instruction
                from   userinstructionperscreen us
                join   customeruserinstruction cui
                on     (cui.customeruserinstruction_id = us.customeruserinstruction_id and
                       sysdate between cui.dateactive and cui.dateinactive and
                       sysdate < cui.enddateautomsg)
                join   customer c
                on     (c.customer_id = cui.customer_id and c.customernumber = lv_customernumber)
                where  us.dialog_id =
                       (select pdf.dialog_id from dialogs pdf where pdf.code = 'SortingSystemRepair')
                union
                select 2 prio, gui.dateactive,
                       (select dbms_lob.substr(guide.instruction, 80, 1)
                         from   generaluserinstruction_desc guide
                         where  guide.generaluserinstruction_id = us.generaluserinstruction_id
                         and    guide.language_id = lv_languageid) instruction
                from   userinstructionperscreen us
                join   generaluserinstructionpercust guc
                on     guc.generaluserinstruction_id = us.generaluserinstruction_id
                join   customer c
                on     (c.customer_id = guc.customer_id and c.customernumber = lv_customernumber)
                join   generaluserinstruction gui
                on     (gui.generaluserinstruction_id = us.generaluserinstruction_id and
                       sysdate between gui.dateactive and gui.dateinactive and
                       sysdate < gui.enddateautomsg)
                where  us.dialog_id =
                       (select pdf.dialog_id from dialogs pdf where pdf.code = 'SortingSystemRepair')
                order  by 1, 2 desc) loop
        begin
          userinstructionsrepair := c.instruction;
          exit;
        end;
      end loop;
      --SortingSystemDivorce
      userinstructionsdivorce := null;
      for d in (select 1 prio, cui.dateactive,
                       (select dbms_lob.substr(cuide.instruction, 80, 1)
                         from   customeruserinstruction_desc cuide
                         where  cuide.customeruserinstruction_id = us.customeruserinstruction_id
                         and    cuide.language_id = lv_languageid) instruction
                from   userinstructionperscreen us
                join   customeruserinstruction cui
                on     (cui.customeruserinstruction_id = us.customeruserinstruction_id and
                       sysdate between cui.dateactive and cui.dateinactive and
                       sysdate < cui.enddateautomsg)
                join   customer c
                on     (c.customer_id = cui.customer_id and c.customernumber = lv_customernumber)
                where  us.dialog_id =
                       (select pdf.dialog_id from dialogs pdf where pdf.code = 'SortingSystemDivorce')
                union
                select 2 prio, gui.dateactive,
                       (select dbms_lob.substr(guide.instruction, 80, 1)
                         from   generaluserinstruction_desc guide
                         where  guide.generaluserinstruction_id = us.generaluserinstruction_id
                         and    guide.language_id = lv_languageid) instruction
                from   userinstructionperscreen us
                join   generaluserinstructionpercust guc
                on     guc.generaluserinstruction_id = us.generaluserinstruction_id
                join   customer c
                on     (c.customer_id = guc.customer_id and c.customernumber = lv_customernumber)
                join   generaluserinstruction gui
                on     (gui.generaluserinstruction_id = us.generaluserinstruction_id and
                       sysdate between gui.dateactive and gui.dateinactive and
                       sysdate < gui.enddateautomsg)
                where  us.dialog_id =
                       (select pdf.dialog_id from dialogs pdf where pdf.code = 'SortingSystemDivorce')
                order  by 1, 2 desc) loop
        begin
          userinstructionsdivorce := d.instruction;
          exit;
        end;
      end loop;
      -- RVI 20150209, Begin
      --> 20012728
      begin
        select s.value
          into   NOOFWASHES
          from   systemsetting s
         where  s.name = 'NOOFWASHESNOCHECKPOINT'
           and    s.plant_id = (select p.plant_id from plant p where p.code = plantcode);
      exception
        when no_data_found then
          NOOFWASHES := 0;
      end;
      fill_flags := false;
      --
      if (((flagcode1 is null) OR (flagcode2 is null) OR (flagcode3 is null) OR (flagcode4 is null)) and (noofwashes > 0)) then
        begin
          begin
            select s.value
              into DEFBYPASSCHECK
              from systemsetting s
             where s.name = 'DEFBYPASSCHECKPOINTFLAG'
               and s.plant_id = (select p.plant_id from plant p where p.code = plantcode);
          exception
            when no_data_found then
                 DEFBYPASSCHECK := '-';
          end;

          begin
            --ui.washestotal is not null
            select ui.washestotal
              into UI_WASHESTOTAL
              from uniqueitem ui
             where ui.primaryid = idcode;
          exception
            when no_data_found then
               UI_WASHESTOTAL := 0;
          end;

          begin
            select fl.flag_id
              into M_BYPASS_CHECKPOINT_FLAG_ID
             from flag fl
            where fl.code = DEFBYPASSCHECK
              and fl.flagtype = 1;
          exception
            when no_data_found then
               M_BYPASS_CHECKPOINT_FLAG_ID := -1;
          end;

          -- RVI 20150218, Begin
          if (M_BYPASS_CHECKPOINT_FLAG_ID > 0) then
            begin
              select fld.description
                into M_BYPASS_FLAG_DESCRIPTION
               from flag_desc fld
              where fld.flag_id = M_BYPASS_CHECKPOINT_FLAG_ID
                and fld.language_id = lv_languageid;
            exception
              when  no_data_found then
                 M_BYPASS_FLAG_DESCRIPTION := null;
            end;
          end if;
          -- RVI 20150218, End

          if (M_BYPASS_CHECKPOINT_FLAG_ID > 0 and UI_WASHESTOTAL > 0) then
            begin
              begin
                select s.sortaddress
                  into M_BYPASS_SORTADDRESS
                  from sortaddressperflag s
                 where s.flag_id = M_BYPASS_CHECKPOINT_FLAG_ID
                   and s.plant_id = (select p.plant_id from plant p where p.code = plantcode);
              exception
                  when no_data_found then
                       M_BYPASS_SORTADDRESS := NULL;
              end;
              if M_BYPASS_SORTADDRESS is not null then
                begin
                  begin
                    -- check exact match on size first
                    select plpc.noofwashesnocheckpoint
                      into PLPC_NOOFWASHESNOCHECKPOINT
                      from uniqueitem             ui,
                           uniqueitemnonpool      up,
                           weareremployment       we,
                           wearer                 w,
                           customer               cu,
                           productlistpercustomer plpc
                     where ui.uniqueitem_id = up.uniqueitem_id
                       and up.weareremployment_id = we.weareremployment_id
                       and we.wearer_id = w.wearer_id
                       and w.customer_id = cu.customer_id
                       and cu.customer_id = plpc.customer_id
                       and plpc.product_id = ui.product_id
                       and plpc.sizedefinition_id = ui.sizedefinition_id
                       and plpc.finishingmethod_id = ui.finishingmethod_id
                       and plpc.dateactive <= sysdate
                       and plpc.dateinactive > sysdate
                       and ui.primaryid = idcode;
                  exception
                    when no_data_found then
                      PLPC_NOOFWASHESNOCHECKPOINT := NULL;
                    when others then
                      PLPC_NOOFWASHESNOCHECKPOINT := NULL;
                  end;
                  -- check size '*' when no exact found on size
                  if PLPC_NOOFWASHESNOCHECKPOINT is null then
                    begin
                      select plpc.noofwashesnocheckpoint
                        into PLPC_NOOFWASHESNOCHECKPOINT
                        from uniqueitem             ui,
                             uniqueitemnonpool      up,
                             weareremployment       we,
                             wearer                 w,
                             customer               cu,
                             productlistpercustomer plpc
                       where ui.uniqueitem_id = up.uniqueitem_id
                         and up.weareremployment_id = we.weareremployment_id
                         and we.wearer_id = w.wearer_id
                         and w.customer_id = cu.customer_id
                         and cu.customer_id = plpc.customer_id
                         and plpc.product_id = ui.product_id
                         and plpc.sizedefinition_id = (select sd.sizedefinition_id
                                                         from sizedefinition sd
                                                        where sd.code = '*')
                         and plpc.finishingmethod_id = ui.finishingmethod_id
                         and plpc.dateactive <= sysdate
                         and plpc.dateinactive > sysdate
                         and ui.primaryid = idcode;
                    exception
                      when no_data_found then
                        PLPC_NOOFWASHESNOCHECKPOINT := NULL;
                      when others then
                        PLPC_NOOFWASHESNOCHECKPOINT := NULL;
                    end;
                  end if;
                 --  check product if nothing found on PLPC
                  if PLPC_NOOFWASHESNOCHECKPOINT is null then
                    begin
                      begin
                        select p.noofwashesnocheckpoint
                          into PRODUCT_NOOFWASHES
                          from uniqueitem ui, product p
                         where ui.product_id = p.product_id
                           and ui.primaryid = idcode;
                      exception
                        when no_data_found then
                          PRODUCT_NOOFWASHES := NULL;
                      end;
                      if PRODUCT_NOOFWASHES is null then
                        fill_flags := (UI_WASHESTOTAL <= NOOFWASHES);
                      else
                        fill_flags := (UI_WASHESTOTAL <= PRODUCT_NOOFWASHES);
                      end if;
                    end;
                  else
                    fill_flags := (UI_WASHESTOTAL <= PLPC_NOOFWASHESNOCHECKPOINT);
                  end if;
                  -- fill sort adress for flag when applicable
                  if fill_flags then
                  -- RVI 20150218, Begin
                    begin
                      if flagcode1 is null then
                        begin
                          flagcode1 := M_BYPASS_SORTADDRESS;
                          flagdescription1 := M_BYPASS_FLAG_DESCRIPTION;
                        end;
                      else
                        if flagcode2 is null then
                          begin
                            flagcode2 := M_BYPASS_SORTADDRESS;
                            flagdescription2 := M_BYPASS_FLAG_DESCRIPTION;
                          end;
                        else
                          if flagcode3 is null then
                            begin
                              flagcode3 := M_BYPASS_SORTADDRESS;
                              flagdescription3 := M_BYPASS_FLAG_DESCRIPTION;
                            end;
                          else
                            begin
                              flagcode4 := M_BYPASS_SORTADDRESS;
                              flagdescription4 := M_BYPASS_FLAG_DESCRIPTION;
                            end;
                          end if;
                        end if;
                      end if;
                    end;
                  -- RVI 20150218, End
                  end if ;
                end;
              end if;
            end;
          end if;
        end;
      end if;
      --<20012728
      -- RVI 20150209, End
      --ABS-65229
      if lv_poolitem = 0 then
        begin
          checkpointselection := null;
          repairselection     := null;
          depot               := 0;
          routenumber         := 9999;
          routeday            := getabsdaynumber(sysdate);
          stackchangeinfo     := null;
          --Fill Destination with value of system setting SORTSTOCKROOMDESTINATION
          select max(st.value)
          into   destination
          from   systemsetting st
          join   plant pt
          on     pt.plant_id = st.plant_id
          where  st.name = 'SORTSTOCKROOMDESTINATION'
          and    pt.code = plantcode;
        end;
      end if; -- lv_poolitem = 0
    end;
  end if;
  if lv_countbarcode > 1 then
    begin
      status := 2; --Double barcode
    end;
  end if;
exception
  when others then
    begin
      status := 1;
      pack_sort.write_logging(idcode || ' ' || sqlerrm, 1, 'GETGARMENTDATAUI', null, 3, 1);
    end;
end getgarmentdataui;
/
create or replace procedure getgarmentdata_eut(fp_idcode              in uniqueitem.primaryid%type,
                                               fp_plantcode           in out plant.code%type,
                                               fp_languagecode        in languages.code%type,
                                               fp_status              out nocopy integer,
                                               fp_finisherselection   out nocopy varchar2,
                                               fp_finishercode        out nocopy integer,
                                               fp_pressselection      out nocopy varchar2,
                                               fp_presscode           out nocopy integer,
                                               fp_checkpointselection out nocopy varchar2,
                                               fp_checkpointcode      out nocopy integer,
                                               fp_repairselection     out nocopy varchar2,
                                               fp_repaircode          out nocopy integer,
                                               fp_destination         out nocopy varchar2,
                                               fp_destinationcode     out nocopy integer,
                                               fp_foldcode            out nocopy integer,
                                               fp_stackchangeinfo     out nocopy varchar2,
                                               fp_sortstring          out nocopy varchar2,
                                               fp_alternatesortstring out nocopy integer,
                                               fp_flags               out nocopy varchar2,
                                               fp_infotext            out nocopy wearer.remark%type,
                                               fp_productcode         out nocopy product.code%type,
                                               fp_deliverypointcode   out nocopy varchar2,
                                               fp_routenumber         out nocopy route.routenumber%type,
                                               fp_routeday            out nocopy day.daynumber%type,
                                               fp_stopnumber          out nocopy routestop.stopnumber%type,
                                               fp_customernumber      out nocopy customer.customernumber%type,
                                               fp_wearernumber        out nocopy wearer.wearernumber%type,
                                               fp_flagcode1           out nocopy sortaddressperflag.sortaddress%type,
                                               fp_flagcode2           out nocopy sortaddressperflag.sortaddress%type,
                                               fp_flagcode3           out nocopy sortaddressperflag.sortaddress%type,
                                               fp_flagcode4           out nocopy sortaddressperflag.sortaddress%type,
                                               fp_flagdescription1    out nocopy flag_desc.description%type,
                                               fp_flagdescription2    out nocopy flag_desc.description%type,
                                               fp_flagdescription3    out nocopy flag_desc.description%type,
                                               fp_flagdescription4    out nocopy flag_desc.description%type,
                                               fp_washestotal         out nocopy uniqueitem.washestotal%type,
                                               fp_productimagename    out nocopy image.imagename%type,
                                               fp_flag_freetext1      out nocopy uniqueitemflag.freetextitem%type,
                                               fp_flag_freetext2      out nocopy uniqueitemflag.freetextitem%type,
                                               fp_flag_freetext3      out nocopy uniqueitemflag.freetextitem%type,
                                               fp_flag_freetext4      out nocopy uniqueitemflag.freetextitem%type,
                                               fp_wearername          out nocopy wearer.searchname%type,
                                               fp_customername        out nocopy customer.name%type,
                                               fp_banklocker          out nocopy varchar2,
                                               fp_street              out nocopy varchar2,
                                               fp_street2             out nocopy varchar2,
                                               fp_city                out nocopy varchar2,
                                               fp_zipcode             out nocopy varchar2,
                                               fp_residualvalue       out nocopy varchar2,
                                               fp_washreplacetext     out nocopy varchar2,
                                               fp_season              out nocopy varchar2,
                                               fp_deliverypointdesc   out nocopy varchar2) is
  --GetGarmentData_EUT Version 0.27
  lv_message                 abslog.message%type;
  lv_businessunitcode        businessunit.code%type;
  lv_plantid_paramater       plant.plant_id%type;
  lv_secondaryid             secondaryuniqueitem.secondaryid%type;
  lv_foldprogram             foldingprogramdefinition.foldingprogram%type;
  lv_deliverydaymask         varchar2(100);
  lv_customerowned           uniqueitem.customerowned%type;
  lv_chargerepaircog         customer.chargerepaircog%type;
  lv_chargerepairs           customer.chargerepairs%type;
  lv_departmentnumber        department.departmentnumber%type;
  lv_departmentdesc          department.description%type;
  lv_distributionpointnumber distributionpoint.distributionpointnumber%type;
  lv_wearerfullname          wearer.fullname%type;
  lv_bank                    locker.bank%type;
  lv_locker                  locker.locker%type;
  lv_garmentdispensercode    garmentdispenser.code%type;
  lv_customeremployeenumber  wearer.customeremployeenumber%type;
  lv_productsortgroup        productsortgroup.code%type;
  lv_productdescription      product_desc.description%type;
  lv_packingsequence         product.packingsequence%type;
  lv_finishingcodeid         product.finishingcode_id%type;
  lv_sizecode                sizedefinition.code%type;
  lv_flagcode1               flag.code%type;
  lv_flagcode2               flag.code%type;
  lv_flagcode3               flag.code%type;
  lv_flagcode4               flag.code%type;
  lv_lastinscandate          uniqueitem.lastinscandate%type;
  lv_lastoutscandate         uniqueitem.lastoutscandate%type;
  lv_lastscandate            uniqueitem.lastscandate%type;
  lv_repairstotal            uniqueitem.repairstotal%type;
  lv_rewashtotal             uniqueitem.rewashtotal%type;
  lv_maxwashes               product.maxwashes%type;
  lv_residualvalueamount     residualvaluehistory.residualvalueamount%type;
  lv_residualvaluepercentage residualvaluehistory.residualvaluepercentage%type;
  lv_batchnumber             uniqueitem.batchnumber%type;

  ---internal procedures/functions
  procedure write_log(fp_message in varchar2 default null, fp_priority in number default 1) is
  begin
    abslogwrite.abslog_write(5, 'getgarmentdata_eut', lv_plantid_paramater, nvl(fp_priority, 1),
                             fp_message);
  end write_log;

  procedure fill_fixed_values is
  begin
    --fill_fixed_values
    fp_pressselection := 'B';
    fp_presscode      := 0;
    fp_repaircode     := 0;
  end fill_fixed_values;

  procedure return_banklocker is
  begin
    --return_banklocker
    fp_banklocker := lpad(lv_bank, 6, ' ') || lpad(lv_locker, 6, ' ');
  end return_banklocker;

  procedure build_flag_info is
  begin
    --build_flag_info
    fp_flags := case
                  when lv_flagcode1 is not null then
                   lv_flagcode1 || ':' || fp_flagdescription1 || chr(13) || chr(10)
                end || case
                  when lv_flagcode1 is not null then
                   lv_flagcode2 || ':' || fp_flagdescription2 || chr(13) || chr(10)
                end || case
                  when lv_flagcode1 is not null then
                   lv_flagcode3 || ':' || fp_flagdescription3 || chr(13) || chr(10)
                end || case
                  when lv_flagcode1 is not null then
                   lv_flagcode4 || ':' || fp_flagdescription4 || chr(13) || chr(10)
                end;
  end build_flag_info;

  procedure get_foldcode is
  begin
    --get_foldcode
    if lv_foldprogram is null then
      fp_foldcode := 0;
    else
      fp_foldcode := to_number(substr(lv_foldprogram , 1, 2));
    end if;
  exception
    when others then
      begin
        fp_foldcode := 0;
      end;
  end get_foldcode;

  procedure get_destinationcode is
  begin
    --get_destinationcode
    if fp_flagcode1 is not null then
      begin
        if to_number(substr(fp_flagcode1, 2, 2)) >= 0 then
          fp_destinationcode := substr(fp_flagcode1, 1, 3);
        end if;
      end;
    end if;
    if fp_destination not in ('M', 'F', 'A', 'H') then
      fp_destination     := 'M';
      fp_destinationcode := 0;
    end if;
  exception
    when others then
      fp_destinationcode := '';
  end get_destinationcode;

  procedure get_finishcode is
    lv_sortaddress sortaddressperfinishingcode.sortaddress%type;
  begin
    --get_finishcode
    select s.sortaddress
    into   lv_sortaddress
    from   sortaddressperfinishingcode s
    where  s.finishingcode_id = lv_finishingcodeid
    and    s.plant_id = lv_plantid_paramater;
    if lv_sortaddress is null then
      fp_finisherselection := 'B';
      fp_finishercode      := 0;
    else
      fp_finishercode      := to_number(substr(lv_sortaddress, 2, 2));
      fp_finisherselection := substr(lv_sortaddress, 1, 1);
    end if;
  exception
    when others then
      begin
        --not a number then..
        fp_finisherselection := 'B';
        fp_finishercode      := 0;
      end;
  end get_finishcode;

  procedure get_checkpoint is
  begin
    --checkpoint selection
    if fp_checkpointselection is null then
      fp_checkpointselection := 'B';
      fp_checkpointcode      := 0;
    else
      fp_checkpointselection := to_number(substr(fp_checkpointselection, 1, 1));
      fp_checkpointcode      := substr(fp_checkpointselection, 2, 2);
    end if;
  exception
    when others then
      begin
        --not a number then..
        fp_checkpointselection := 'B';
        fp_checkpointcode      := 0;
      end;
  end get_checkpoint;

  procedure get_repairselection is
  begin
    --get_repairselection
    if lv_customerowned = 'Y' then
      if lv_chargerepaircog <> 0 then
        fp_repairselection := 'R';
      end if;
    elsif lv_chargerepairs <> 0 then
      fp_repairselection := 'R';
    else
      fp_repairselection := null;
    end if;
  exception
    when others then
      fp_repairselection := null;
  end get_repairselection;

  procedure get_washreplacetext is
    lvs_maxwashes varchar2(64);
  begin
    --get_washreplacetext
    if (lv_maxwashes = 0 or lv_maxwashes is null) then
      lvs_maxwashes := '---- (--%)';
    else
      lvs_maxwashes := lpad(to_char(lv_maxwashes), 4, '0') || ' (' ||
                       to_char(round(fp_washestotal / lv_maxwashes * 100)) || '%)';
    end if;
    fp_washreplacetext := 'LAV ' || lpad(to_char(fp_washestotal), 4, '0') || '/' || lvs_maxwashes ||
                          ' REP ' || lpad(to_char(lv_repairstotal), 4, '0');
  end get_washreplacetext;

  procedure get_residualvalue is
  begin
    if lv_residualvalueamount is null then
      fp_residualvalue := '100%';
    else
      begin
        --get_residualvalue
        fp_residualvalue := to_char(lv_residualvalueamount) || ' - ' ||
                            to_char(round(lv_residualvaluepercentage)) || '%';
      end;
    end if;
  end get_residualvalue;

begin
  --fill_fixed_values
  fill_fixed_values;
  --getgarmentinfo
  pack_sort2.getgarmentinfo(fp_idcode, fp_plantcode, fp_languagecode, fp_status, lv_message,
                            lv_businessunitcode, lv_plantid_paramater, lv_secondaryid,
                            fp_checkpointselection, fp_destination, lv_foldprogram, fp_sortstring,
                            fp_alternatesortstring, fp_stackchangeinfo, fp_routenumber, fp_routeday,
                            fp_stopnumber, lv_deliverydaymask, fp_customernumber, fp_customername,
                            lv_customerowned, lv_chargerepaircog, lv_chargerepairs,
                            lv_departmentnumber, lv_departmentdesc, fp_deliverypointcode,
                            fp_deliverypointdesc, fp_street, fp_street2, fp_city, fp_zipcode,
                            lv_distributionpointnumber, fp_wearernumber, lv_wearerfullname,
                            fp_wearername, fp_infotext, lv_bank, lv_locker, lv_garmentdispensercode,
                            lv_customeremployeenumber, lv_productsortgroup, fp_productcode,
                            lv_packingsequence, lv_productdescription, fp_productimagename,
                            lv_finishingcodeid, lv_sizecode, lv_flagcode1, lv_flagcode2,
                            lv_flagcode3, lv_flagcode4, fp_flagcode1, fp_flagcode2, fp_flagcode3,
                            fp_flagcode4, fp_flagdescription1, fp_flagdescription2,
                            fp_flagdescription3, fp_flagdescription4, fp_flag_freetext1,
                            fp_flag_freetext2, fp_flag_freetext3, fp_flag_freetext4,
                            lv_lastinscandate, lv_lastoutscandate, lv_lastscandate, fp_washestotal,
                            lv_repairstotal, lv_rewashtotal, lv_maxwashes, fp_season,
                            lv_residualvalueamount, lv_residualvaluepercentage, lv_batchnumber);
  --return banklocker
  return_banklocker;
  --build_flag_info
  build_flag_info;
  --get_foldcode
  get_foldcode;
  --get_destinationcode
  get_destinationcode;
  --get finish code
  get_finishcode;
  --get_checkpoint
  get_checkpoint;
  --get_repairselection
  get_repairselection;
  --get_washreplacetext
  get_washreplacetext;
  --get_residualvalue
  get_residualvalue;
exception
  when others then
    begin
      rollback;
      write_log('Error others fp_idcode ' || fp_idcode || ' fp_plantcode ' || fp_plantcode ||
                ' fp_languagecode ' || fp_languagecode || ' ' || sqlerrm, 5);
      fp_status := 5;
    end;
end getgarmentdata_eut;
/
create or replace procedure getgarmentflag(fp_businessunitcode in businessunit.code%type,
                                           fp_primaryid        in uniqueitem.primaryid%type,
                                           fp_flagyesno        out number, --1 yes, 0 no, 2 barcode not found
                                           fp_flagcode         out flag.code%type,
                                           fp_sortaddress      out sortaddressperflag.sortaddress%type) is
  lv_uniqueitemid uniqueitem.uniqueitem_id%type;
  lv_plantid      plant.plant_id%type;
begin
  --initialize
  fp_flagyesno   := 0;
  fp_flagcode    := null;
  fp_sortaddress := null;
  begin
    --get uniqueitem
    select u.uniqueitem_id, bu.plant_id
    into   lv_uniqueitemid, lv_plantid
    from   uniqueitem u, businessunit bu
    where  u.businessunit_id = bu.businessunit_id
    and    bu.code = fp_businessunitcode
    and    u.primaryid = fp_primaryid;
  exception
    when others then
      fp_flagyesno := 2; --uniqueitem not found!
  end;
  if fp_flagyesno = 0 then
    --get the flags, highest priority first. 1 is highest, then oldest flag first.
    for x in (select f.code, f.flag_id
              from   uniqueitemflag uf, flag f
              where  uf.uniqueitem_id = lv_uniqueitemid
              and    uf.flag_id = f.flag_id
              and    uf.startdate <= trunc(sysdate)
              order  by f.priority, f.timestamp asc) loop
      begin
        --get first flag code
        fp_flagyesno := 1;
        fp_flagcode  := x.code;
        begin
          --get sortaddress
          select sa.sortaddress
          into   fp_sortaddress
          from   sortaddressperflag sa
          where  sa.flag_id = x.flag_id
          and    sa.plant_id = lv_plantid;
        exception
          when no_data_found then
            fp_sortaddress := null;
        end;
        exit;
      end;
    end loop;
  end if;
  --calling/program must catch errors
end getgarmentflag;
/
create or replace procedure getnextbatchinwatec(businessunitcode in varchar2,
                                                locationcode     in varchar2,
                                                uhfbundleid      out nocopy number,
                                                status           out nocopy number,
                                                message          out varchar2) is
  /*procedure getnextbatchinwatec version 0.1*/
  gv_businessunitid businessunit.businessunit_id%type;
  gv_plantid        plant.plant_id%type;
  gv_workstationid  workstation.workstation_id%type;
  --Internal procedures
  procedure write_log(fp_message in varchar2, fp_priority in number) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'getnextbatchinwatec', gv_plantid, fp_priority, fp_message, 0);
  end write_log;
begin
  --get gv_businessunitid
  message := 'businessunitcode ' || nvl(businessunitcode, 'NULL');
  select bu.businessunit_id, bu.plant_id
  into   gv_businessunitid, gv_plantid
  from   businessunit bu
  where  bu.code = businessunitcode;
  --get gv_workstationid
  message := 'locationcode ' || nvl(locationcode, 'NULL') || ' for plant of ' || businessunitcode ||
             nvl(businessunitcode, ' null ');
  select sid.workstation_id
  into   gv_workstationid
  from   sortingimportdefinition sid
  where  sid.plant_id = gv_plantid
  and    sid.location = locationcode;
  --insert into uhfbundle
  message := 'insert into uhfbundle';
  insert into uhfbundle
    (uhfbundle_id, businessunit_id, product_link_id, sizedefinition_link_id, bundlesize,
     workstation, systemuser_id, timestamp, deliverystatus, pack, bundleprimaryid, creationdate,
     relatedcustomer_id, packingnote_id)
  values
    (seq_uhfbundle.nextval, gv_businessunitid, null, null, 0, gv_workstationid, 0, sysdate, 1, 'N',
     null, sysdate, null, null)
  returning uhfbundle_id into uhfbundleid;
  commit;
  message := 'Ok';
  status  := 0;
exception
  when others then
    begin
      rollback;
      message := sqlerrm || ' ' || nvl(message, ' ');
      status  := 1;
      write_log(message, 3);
    end;
end getnextbatchinwatec;
/
create or replace procedure GetNextSortBatch(UnitCode              in varchar2,
                                             Status                out integer,
                                             BatchDay              out integer,
                                             SortBatchNumber       out sortbatch.sortbatch_id%type,
                                             BatchDescription      out sortbatch.description%type,
                                             UtilizationPercentage out number,
                                             TotalQuantity         out Sortbatch.Numberofgarmentstotal%type,
                                             ExpectedInscan        out sortbatch.numberofgarmentsinscan%type,
                                             ExpectedNoInscan      out sortbatch.numberofgarmentsnoinscan%type,
                                             ShareBufferRail       out sortbatch.sharebufferrail%type,
                                             ByPassSort            out sortbatch.bypasssorting%type) is
  plantid     plant.plant_id%type;
  sortbatchid sortbatch.sortbatch_id%type;
  X           NUMBER(4, 1);
begin
  Status := 0;
  If UnitCode is not null then
    select plant_id into plantid from plant where code = UnitCode;

  else
    select min(plant_id) into plantid from plant;

  end if;
  select min(sortbatch_id)
    into sortbatchid
    from sortbatch
   where sortbatch.plant_id = plantid and sortbatch.status = 1;
  select s.day_id,
         s.sortbatch_id,
         s.description,
         s.numberofgarmentstotal,
         s.numberofgarmentsinscan,
         s.numberofgarmentsnoinscan,
         s.sharebufferrail,
         s.bypasssorting
    into BatchDay,
         SortBatchNumber,
         BatchDescription,
         TotalQuantity,
         ExpectedInscan,
         ExpectedNoInscan,
         ShareBufferRail,
         ByPassSort
    from Sortbatch s
   where s.sortbatch_id = sortbatchid;
  if TotalQuantity + ExpectedInscan = 0 then
    UtilizationPercentage := 0.0;
  else
    UtilizationPercentage := (ExpectedInscan + ExpectedNoInscan) /
                             (TotalQuantity + ExpectedInscan) * 100;
    X                     := UtilizationPercentage;
    UtilizationPercentage := X;
  end if;
exception
  when no_data_found then
    Status := 1;
end GetNextSortBatch;
/
create or replace procedure GetOldestFIFOPurchaseInfo(P_Stockroom_ID         in stockroom.stockroom_id%type,
                                                      P_Product_ID           in product.product_id%type,
                                                      P_SizeDefinition_ID    in sizedefinition.sizedefinition_id%type,
                                                      P_QualityGrade_ID      in qualitygrade.qualitygrade_id%type,
                                                      P_Date                 in date,
                                                      P_Supplier_ID          out supplier.supplier_id%type,
                                                      P_Currency_ID          out currency.currency_id%type,
                                                      P_PurchasePrice        out number,
                                                      P_PurchaseOrderLine_ID out purchaseorderline.purchaseorderline_id%type) is
  qg_found                   number;
  svf_purchaseordernumber    purchaseorderheader.purchaseordernumber%type;
  poh_purchaseorderheader_id purchaseorderheader.purchaseorderheader_id%type;
begin
  P_Supplier_ID := -1;
  P_Currency_ID := -1;
  P_PurchasePrice := 0.0;
  P_PurchaseOrderLine_ID := -1;

  select count(qg.qualitygrade_id)
    into qg_found
    from qualitygrade qg
   where qg.newgarment = 'Y'
     and qg.stockvaluationmethod = 1
     and qg.qualitygrade_id = P_QualityGrade_ID;

  if (qg_found > 0) then
    begin
      select svfmax.piecevalue, svfmax.purchaseordernumber
      into P_PurchasePrice, svf_purchaseordernumber
      from
      (
      select svf.piecevalue, svf.purchaseordernumber
        from stockvaluefifo           svf,
             stockreservationpergrade srg,
             stockdefinitionperitem   sdi
       where svf.transactiontype <> 2
         and svf.qtyactualstock > 0
         and svf.stockreservationpergrade_id =
             srg.stockreservationpergrade_id
         and srg.qualitygrade_id = P_QualityGrade_ID
         and sdi.stockdefinitionperitem_id = srg.stockdefinitionperitem_id
         and sdi.stockroom_id = P_Stockroom_ID
         and sdi.product_id = P_Product_ID
         and sdi.sizedefinition_id = P_SizeDefinition_ID
         and sdi.customer_id is null
         and sdi.customerowned = 'N'
         order by svf.purchaseordernumber desc nulls last
        ) svfmax
        where rownum = 1;

      select poh.supplier_id, poh.currency_id, poh.purchaseorderheader_id
        into P_Supplier_ID, P_Currency_ID, poh_purchaseorderheader_id
        from purchaseorderheader poh
       where poh.purchaseordernumber = svf_purchaseordernumber;

      begin
        select pol.purchaseprice, pol.purchaseorderline_id
          into P_PurchasePrice, P_PurchaseOrderLine_ID
          from purchaseorderline pol
         where pol.purchaseorderheader_id = poh_purchaseorderheader_id
           and pol.product_link_id = p_Product_Id
           and pol.sizedefinition_link_id = p_SizeDefinition_ID;
      exception
        when no_data_found then
          begin
            P_PurchaseOrderLine_ID := -1;
          end;
      end;

    exception
      when no_data_found then
        begin
          getdefaultsupplierpurchaseinfo(p_Stockroom_ID,
                                         p_Product_Id,
                                         p_SizeDefinition_ID,
                                         p_Date,
                                         p_Supplier_ID,
                                         P_Currency_ID,
                                         P_PurchasePrice);
        end;
    end;

  else
    getdefaultsupplierpurchaseinfo(p_Stockroom_ID,
                                   p_Product_Id,
                                   p_SizeDefinition_ID,
                                   p_Date,
                                   p_Supplier_ID,
                                   P_Currency_ID,
                                   P_PurchasePrice);
  end if;

end GetOldestFIFOPurchaseInfo;
/
create or replace procedure GetPurchaseInfoDirectViaWOL(P_WorkOrderLine_ID     in workorderline.workorderline_id%type,
                                                        P_Date                 in date,
                                                        P_Supplier_ID          out supplier.supplier_id%type,
                                                        P_Currency_ID          out currency.currency_id%type,
                                                        P_PurchasePrice        out number,
                                                        P_PurchaseOrderLine_ID out purchaseorderline.purchaseorderline_id%type) is
  wo_processingstockroom_id  stockroom.stockroom_id%type;
  wol_product_link_id        product.product_id%type;
  wol_sizedefinition_link_id sizedefinition.sizedefinition_id%type;
begin
  P_Supplier_ID := -1;
  P_Currency_ID := -1;
  P_PurchasePrice := 0.0;
  P_PurchaseOrderLine_ID := -1;

  begin
    select pol.purchaseorderline_id,
           pol.purchaseprice,
           poh.supplier_id,
           poh.currency_id
      into P_PurchaseOrderLine_ID,
           P_PurchasePrice,
           P_Supplier_ID,
           P_Currency_ID
      from workorderline       wol,
           purchaseorderline   pol,
           purchaseorderheader poh
     where wol.workorderline_id = P_WorkOrderLine_ID
       and pol.purchaseorderline_id = wol.purchaseorderline_id
       and poh.purchaseorderheader_id = pol.purchaseorderheader_id;

  exception
    when no_data_found then
      begin
        select wo.processingstockroom_id,
               wol.product_link_id,
               wol.sizedefinition_link_id
          into wo_processingstockroom_id,
               wol_product_link_id,
               wol_sizedefinition_link_id
          from workorder wo, workorderline wol
         where wol.workorderline_id = P_WorkOrderLine_ID
           and wo.workorder_id = wol.workorder_id;

        getdefaultsupplierpurchaseinfo(wo_processingstockroom_id,
                                       wol_product_link_id,
                                       wol_sizedefinition_link_id,
                                       p_Date,
                                       p_Supplier_ID,
                                       P_Currency_ID,
                                       P_PurchasePrice);
      end;
  end;

end GetPurchaseInfoDirectViaWOL;
/
create or replace procedure GetSortBatchUpdate(SortBatchNumber       in Sortbatch.Sortbatch_Id%type,
                                               Status                out integer,
                                               BatchDay              out day.daynumber%type,
                                               UtilizationPercentage out number,
                                               TotalQuantity         out Sortbatch.Numberofgarmentstotal%type,
                                               ExpectedInscan        out sortbatch.numberofgarmentsinscan%type,
                                               ExpectedNoInscan      out sortbatch.numberofgarmentsnoinscan%type,
                                               SharedBufferRail      out varchar2,
                                               ByPassSort            out varchar2) is
  X NUMBER(4, 1);
begin
  Status := 0;
  begin
    select day.daynumber,
           s.numberofgarmentstotal,
           s.numberofgarmentsinscan,
           s.numberofgarmentsnoinscan,
           s.sharebufferrail,
           s.bypasssorting
      into BatchDay,
           TotalQuantity,
           ExpectedInscan,
           ExpectedNoInscan,
           SharedBufferRail,
           ByPassSort
      from Sortbatch s, day
     where s.sortbatch_id = SortBatchNumber and s.day_id = day.day_id;
    if TotalQuantity + ExpectedInscan = 0 then
      UtilizationPercentage := 0.0;
    else
      UtilizationPercentage := (ExpectedInscan + ExpectedNoInscan) /
                               (TotalQuantity + ExpectedInscan) * 100;
      X                     := UtilizationPercentage;
      UtilizationPercentage := X;
    end if;
  exception
    when no_data_found then
      --   dbms_output.put_line(sqlcode || ' ' || sqlerrm);
      Status := 1;
    when others then
      null;
      --   dbms_output.put_line(sqlcode || ' ' || sqlerrm);
  end;
end GetSortBatchUpdate;
/
create or replace procedure getsortinginfoinwatec(fp_idcode                    in uniqueitem.primaryid%type,
                                                  fp_plantcode                 in plant.code%type,
                                                  fp_languagecode              in languages.code%type,
                                                  fp_status                    out nocopy integer, /*0=Ok otherwise error*/
                                                  fp_message                   out nocopy varchar2,
                                                  fp_secondaryid               out nocopy varchar2,
                                                  fp_productcode               out nocopy varchar2,
                                                  fp_productdescription        out nocopy varchar2,
                                                  fp_productlongdescription    out nocopy varchar2,
                                                  fp_shortdescription          out nocopy varchar2,
                                                  fp_productgroupcode          out nocopy varchar2,
                                                  fp_productgroupdescription   out nocopy varchar2,
                                                  fp_weighingcategorycode      out nocopy varchar2,
                                                  fp_weighingcategorydescrip   out nocopy varchar2,
                                                  fp_theoreticalweight         out nocopy number,
                                                  fp_colorcode                 out nocopy varchar2,
                                                  fp_colordescription          out nocopy varchar2,
                                                  fp_fabriccode                out nocopy varchar2,
                                                  fp_fabricdescription         out nocopy varchar2,
                                                  fp_washingprocesscode        out nocopy varchar2,
                                                  fp_washingprocessdescription out nocopy varchar2,
                                                  fp_washingprocsortingadress  out nocopy varchar2,
                                                  fp_legacyproductcode         out nocopy varchar2,
                                                  fp_soilcountedmethod         out nocopy number,
                                                  fp_typeofmerchandise         out nocopy number,
                                                  fp_flagcode                  out nocopy varchar2,
                                                  fp_flagdescription           out nocopy varchar2,
                                                  fp_flagsortaddress           out nocopy varchar2,
                                                  fp_customernumber            out nocopy number,
                                                  fp_customername              out nocopy varchar2,
                                                  fp_ownership                 out nocopy varchar2,
                                                  fp_washestotal               out nocopy number,
                                                  fp_rewashtotal               out nocopy number,
                                                  fp_isragged                  out nocopy varchar2,
                                                  fp_xrayprogram               out nocopy varchar2,
                                                  fp_maximumbatchweight        out nocopy number,
                                                  fp_maximumbatchqty           out nocopy number) is
  --GetSortingInfoInwatec Version 0.02
  fp_checkpointselection     serviceteam.sortaddress%type;
  fp_destination             sortaddressperfinishingmeth.sortaddress%type;
  fp_stackchangeinfo         varchar2(512);
  fp_sortstring              varchar2(512);
  fp_alternatesortstring     integer;
  fp_infotext                wearer.remark%type;
  fp_deliverypointcode       deliverypoint.code%type;
  fp_routenumber             route.routenumber%type;
  fp_routeday                day.daynumber%type;
  fp_stopnumber              routestop.stopnumber%type;
  fp_wearernumber            wearer.wearernumber%type;
  fp_flagcode1               sortaddressperflag.sortaddress%type;
  fp_flagcode2               sortaddressperflag.sortaddress%type;
  fp_flagcode3               sortaddressperflag.sortaddress%type;
  fp_flagcode4               sortaddressperflag.sortaddress%type;
  fp_flagsortaddress1        sortaddressperflag.sortaddress%type;
  fp_flagsortaddress2        sortaddressperflag.sortaddress%type;
  fp_flagsortaddress3        sortaddressperflag.sortaddress%type;
  fp_flagsortaddress4        sortaddressperflag.sortaddress%type;
  fp_flagdescription1        flag_desc.description%type;
  fp_flagdescription2        flag_desc.description%type;
  fp_flagdescription3        flag_desc.description%type;
  fp_flagdescription4        flag_desc.description%type;
  fp_productimagename        image.imagename%type;
  fp_flag_freetext1          uniqueitemflag.freetextitem%type;
  fp_flag_freetext2          uniqueitemflag.freetextitem%type;
  fp_flag_freetext3          uniqueitemflag.freetextitem%type;
  fp_flag_freetext4          uniqueitemflag.freetextitem%type;
  fp_wearername              wearer.searchname%type;
  fp_street                  address.street%type;
  fp_street2                 address.street2%type;
  fp_city                    address.city%type;
  fp_zipcode                 address.zipcode%type;
  fp_season                  season.code%type;
  fp_deliverypointdesc       deliverypoint.description%type;
  fp_businessunitcode        businessunit.code%type;
  fp_plantid_paramater       plant.plant_id%type;
  fp_foldprogram             foldingprogramdefinition.foldingprogram%type;
  fp_deliverydaymask         varchar2(100);
  fp_customerowned           uniqueitem.customerowned%type;
  fp_chargerepaircog         customer.chargerepaircog%type;
  fp_chargerepairs           customer.chargerepairs%type;
  fp_departmentnumber        department.departmentnumber%type;
  fp_departmentdesc          department.description%type;
  fp_distributionpointnumber distributionpoint.distributionpointnumber%type;
  fp_wearerfullname          wearer.fullname%type;
  fp_bank                    locker.bank%type;
  fp_locker                  locker.locker%type;
  fp_garmentdispensercode    garmentdispenser.code%type;
  fp_customeremployeenumber  wearer.customeremployeenumber%type;
  fp_productsortgroup        productsortgroup.code%type;
  fp_packingsequence         product.packingsequence%type;
  fp_finishingcodeid         product.finishingcode_id%type;
  fp_sizecode                sizedefinition.code%type;
  fp_lastinscandate          uniqueitem.lastinscandate%type;
  fp_lastoutscandate         uniqueitem.lastoutscandate%type;
  fp_lastscandate            uniqueitem.lastscandate%type;
  fp_repairstotal            uniqueitem.repairstotal%type;
  fp_maxwashes               product.maxwashes%type;
  fp_residualvalueamount     residualvaluehistory.residualvalueamount%type;
  fp_residualvaluepercentage residualvaluehistory.residualvaluepercentage%type;
  fp_batchnumber             uniqueitem.batchnumber%type;
  fp_weighingcategoryid      product.weighingcategory_id%type;

  ---internal procedures/functions
  procedure write_log(fp_message in varchar2 default null, fp_priority in number default 1) is
  begin
    abslogwrite.abslog_write(5, 'GetSortingInfoInwatec', fp_plantid_paramater, nvl(fp_priority, 1),
                             fp_message);
  end write_log;

  procedure get_garmentinfo(fp_chipcode in varchar2) is
    lv_databasecode varchar2(6);

    procedure get_info(fp_chipidcode in varchar2) is
    begin
      pack_sort2.getgarmentinfo_2(fp_chipidcode, fp_plantcode, fp_languagecode, fp_status,
                                  fp_message, fp_businessunitcode, fp_plantid_paramater,
                                  fp_secondaryid, fp_checkpointselection, fp_destination,
                                  fp_foldprogram, fp_sortstring, fp_alternatesortstring,
                                  fp_stackchangeinfo, fp_routenumber, fp_routeday, fp_stopnumber,
                                  fp_deliverydaymask, fp_customernumber, fp_customername,
                                  fp_customerowned, fp_chargerepaircog, fp_chargerepairs,
                                  fp_departmentnumber, fp_departmentdesc, fp_deliverypointcode,
                                  fp_deliverypointdesc, fp_street, fp_street2, fp_city, fp_zipcode,
                                  fp_distributionpointnumber, fp_wearernumber, fp_wearerfullname,
                                  fp_wearername, fp_infotext, fp_bank, fp_locker,
                                  fp_garmentdispensercode, fp_customeremployeenumber,
                                  fp_productsortgroup, fp_productcode, fp_typeofmerchandise,
                                  fp_packingsequence, fp_productdescription, fp_productimagename,
                                  fp_finishingcodeid, fp_sizecode, fp_flagcode1, fp_flagcode2,
                                  fp_flagcode3, fp_flagcode4, fp_flagsortaddress1,
                                  fp_flagsortaddress2, fp_flagsortaddress3, fp_flagsortaddress4,
                                  fp_flagdescription1, fp_flagdescription2, fp_flagdescription3,
                                  fp_flagdescription4, fp_flag_freetext1, fp_flag_freetext2,
                                  fp_flag_freetext3, fp_flag_freetext4, fp_lastinscandate,
                                  fp_lastoutscandate, fp_lastscandate, fp_washestotal,
                                  fp_repairstotal, fp_rewashtotal, fp_maxwashes, fp_season,
                                  fp_residualvalueamount, fp_residualvaluepercentage, fp_batchnumber,
                                  fp_legacyproductcode, fp_productlongdescription,
                                  fp_productgroupdescription, fp_productgroupcode,
                                  fp_shortdescription, fp_fabriccode, fp_fabricdescription,
                                  fp_colorcode, fp_colordescription, fp_theoreticalweight,
                                  fp_weighingcategoryid, fp_soilcountedmethod, fp_ownership,
                                  fp_weighingcategorycode, fp_weighingcategorydescrip,
                                  fp_washingprocesscode, fp_washingprocessdescription,
                                  fp_washingprocsortingadress);
    end get_info;
  begin
    --getgarmentinfo_2
    get_info(fp_chipcode);
    if fp_status = 1 then
      begin
        --no data found status = 1
        select d.code into lv_databasecode from databasesettings d;
        if lv_databasecode = 'CLB' and length(fp_idcode) = 16 then
          begin
            --ABS-160061
            get_info('00' || substr(fp_idcode, -10));
            if fp_status = 0 then
              begin
                --found
                update uniqueitem u
                set    u.primaryid = fp_idcode, u.timestamp = sysdate
                where  u.primaryid = '00' || substr(fp_idcode, -10);
                --commit the change
                commit;
              end;
            elsif fp_status = 1 then
              begin
                raise no_data_found;
              end;
            end if;
          end;
        else
          begin
            raise no_data_found;
          end;
        end if;
      end;
    end if;
  end get_garmentinfo;

  procedure get_extra_info is
  begin
    --get_extra_info
    --null values for now!!
    fp_xrayprogram        := null;
    fp_maximumbatchweight := null;
    fp_maximumbatchqty    := null;
    --get flag info from 1st flag
    fp_flagsortaddress := fp_flagsortaddress1;
    fp_flagcode        := fp_flagcode1;
    fp_flagdescription := fp_flagdescription1;
  end get_extra_info;

  procedure check_is_ragged is
  begin
    --check_is_ragged
    select rg.secondaryid, 'Y'
    into   fp_secondaryid, fp_isragged
    from   raggeditem rg
    where  rg.primaryid = fp_idcode
    and    rg.businessunit_id in
           (select bu.businessunit_id from businessunit bu where bu.plant_id = fp_plantid_paramater);
    fp_status := 98; --ragged link on same BU
  exception
    when no_data_found then
      begin
        select rg.secondaryid, 'Y'
        into   fp_secondaryid, fp_isragged
        from   raggeditem rg
        where  rg.primaryid = fp_idcode;
        fp_status := 97; --ragged for other BU(s)
      exception
        when no_data_found then
          begin
            fp_status := 1; --no_data_found
          end;
        when too_many_rows then
          begin
            fp_isragged := 'Y';
            fp_status   := 99; --ragged more then once
          end;
      end;
    when too_many_rows then
      begin
        fp_isragged := 'Y';
        fp_status   := 99; --ragged more then once
      end;
  end check_is_ragged;

begin
  fp_isragged := 'N';
  begin
    get_garmentinfo(fp_idcode);
    --get_extra_info
    get_extra_info;
  exception
    when no_data_found then
      begin
        --check_is_ragged
        check_is_ragged;
      end;
  end;
  fp_message := 'Ok';
exception
  when others then
    begin
      rollback;
      fp_message := 'error others ' || sqlerrm;
      write_log('error others fp_idcode ' || fp_idcode || ' fp_plantcode ' || fp_plantcode ||
                ' fp_languagecode ' || fp_languagecode || '
                    ' || sqlerrm, 5);
      fp_status := 5;
    end;
end getsortinginfoinwatec;
/
create or replace procedure GetWearerDataKannegiesser(PlantCode            in PLANT.CODE%type,
                                                      Route#               in ROUTE.ROUTENUMBER%type,
                                                      RouteDay#            in ROUTE.DRIVINGDAY_ID%type,
                                                      Stop#                in ROUTESTOP.STOPNUMBER%type,
                                                      Customer#            in CUSTOMER.CUSTOMERNUMBER%type,
                                                      Wearer#              in WEARER.WEARERNUMBER%type,
                                                      Status               out NOCOPY Integer,
                                                      Depot                out NOCOPY DEPOT.CODE%type,
                                                      CustomerName         out NOCOPY CUSTOMER.NAME%type,
                                                      DeliveryDayMask      out NOCOPY Varchar2,
                                                      WearerName           out NOCOPY WEARER.SEARCHNAME%type,
                                                      CustomerEmployee#    out NOCOPY WEARER.CUSTOMEREMPLOYEENUMBER%type,
                                                      BankLocker           out NOCOPY Varchar2,
                                                      Department#          out NOCOPY DEPARTMENT.DEPARTMENTNUMBER%type,
                                                      GarmentDispenserCode out NOCOPY GARMENTDISPENSER.CODE%type,
                                                      Gender               out NOCOPY WEARER.SEX%type,
                                                      DeliveryPointCode    out NOCOPY DELIVERYPOINT.CODE%type,
                                                      Totalamount          out NOCOPY integer) is
  customerid         customer.customer_id%type;
  lockerID           LOCKER.LOCKER_ID%type;
  garmentdispenserID GARMENTDISPENSER.GARMENTDISPENSER_ID%type;
  deliverypointId    DELIVERYPOINT.DELIVERYPOINT_ID%type;
  wearerid           wearer.wearer_id%type;
  routeid            route.route_id%type;
begin
  Status := 0;
  begin
    select w.searchname,
           c.name,
           c.customer_id,
           w.customeremployeenumber,
           w.sex,
           w.wearer_id
      into WearerName,
           CustomerName,
           customerid,
           customeremployee#,
           gender,
           wearerid
      from wearer w, customer c
     where w.wearernumber = wearer# and w.customer_id = c.customer_id and
           c.customernumber = customer#;
  exception
    when no_data_found then
      Status := 1;
  end;
  if Status = 0 then
    Pack_Sort.getdeliverydaysmask(customerid, deliverydaymask);
    begin
      select min(r.route_id) --  route_id changed to min(r.route_id) solved by HVH 19/11/2009 Todo 9740
        into routeid
        from route r, routestop rs, plant p
       where r.route_id = rs.route_id and r.routenumber = route# and
             rs.stopnumber = Stop# and r.drivingday_id = RouteDay# and
             r.plant_id = p.plant_id and p.code = Plantcode;
      Pack_Sort.getdepot(routeid, depot);
    exception
      when no_data_found then
        null;
    end;
    select we.deliverypoint_id,
           we.locker_id,
           we.garmentdispenser_id,
           d.departmentnumber
      into deliverypointid, lockerid, garmentdispenserid, department#
      from weareremployment we, distributionpoint di, department d
     where we.wearer_id = wearerid and we.sequencenumber = 1 and
           we.distributionpoint_id = di.distributionpoint_id and
           di.department_id = d.department_id;
    Pack_Sort.getgarmentlocation(lockerID,
                                 garmentdispenserID,
                                 deliverypointID,
                                 BankLocker,
                                 GarmentDispenserCode,
                                 DeliveryPointCode);
    Totalamount := 0;
  end if;
exception
  when others then
    null;
end GetWearerDataKannegiesser;
/
create or replace procedure GetWearerDataKannegiesser_RUS(PlantCode            in PLANT.CODE%type,
                                                      Route#               in ROUTE.ROUTENUMBER%type,
                                                      RouteDay#            in ROUTE.DRIVINGDAY_ID%type,
                                                      Stop#                in ROUTESTOP.STOPNUMBER%type,
                                                      Customer#            in CUSTOMER.CUSTOMERNUMBER%type,
                                                      Wearer#              in WEARER.WEARERNUMBER%type,
                                                      Status               out NOCOPY Integer,
                                                      Depot                out NOCOPY DEPOT.CODE%type,
                                                      CustomerName         out NOCOPY CUSTOMER.NAME%type,
                                                      DeliveryDayMask      out NOCOPY Varchar2,
                                                      WearerName           out NOCOPY WEARER.SEARCHNAME%type,
                                                      CustomerEmployee#    out NOCOPY WEARER.CUSTOMEREMPLOYEENUMBER%type,
                                                      BankLocker           out NOCOPY Varchar2,
                                                      Department#          out NOCOPY DEPARTMENT.DEPARTMENTNUMBER%type,
                                                      GarmentDispenserCode out NOCOPY GARMENTDISPENSER.CODE%type,
                                                      Gender               out NOCOPY WEARER.SEX%type,
                                                      DeliveryPointCode    out NOCOPY DELIVERYPOINT.CODE%type,
                                                      Totalamount          out NOCOPY integer,
                                                      departmentname       out NOCOPY DEPARTMENT.Description%TYPE) is
  customerid         customer.customer_id%type;
  lockerID           LOCKER.LOCKER_ID%type;
  garmentdispenserID GARMENTDISPENSER.GARMENTDISPENSER_ID%type;
  deliverypointId    DELIVERYPOINT.DELIVERYPOINT_ID%type;
  wearerid           wearer.wearer_id%type;
  routeid            route.route_id%type;
begin
  Status := 0;
  begin
    select w.searchname,
           c.name,
           c.customer_id,
           w.customeremployeenumber,
           w.sex,
           w.wearer_id
      into WearerName,
           CustomerName,
           customerid,
           customeremployee#,
           gender,
           wearerid
      from wearer w, customer c
     where w.wearernumber = wearer# and w.customer_id = c.customer_id and
           c.customernumber = customer#;
  exception
    when no_data_found then
      Status := 1;
  end;
  if Status = 0 then
    Pack_Sort.getdeliverydaysmask(customerid, deliverydaymask);
    begin
        select min(r.route_id) --  route_id changed to min(r.route_id) solved by HVH 19/11/2009 Todo 9740
        into routeid
        from route r, routestop rs, plant p
       where r.route_id = rs.route_id and r.routenumber = route# and
             rs.stopnumber = Stop# and r.drivingday_id = RouteDay# and
             r.plant_id = p.plant_id and p.code = Plantcode;
      Pack_Sort.getdepot(routeid, depot);
    exception
      when no_data_found then
        null;
    end;
    select we.deliverypoint_id,
           we.locker_id,
           we.garmentdispenser_id,
           d.departmentnumber,
           d.description
      into deliverypointid, lockerid, garmentdispenserid, department#, departmentname
      from weareremployment we, distributionpoint di, department d
     where we.wearer_id = wearerid and we.sequencenumber = 1 and
           we.distributionpoint_id = di.distributionpoint_id and
           di.department_id = d.department_id;
    Pack_Sort.getgarmentlocation(lockerID,
                                 garmentdispenserID,
                                 deliverypointID,
                                 BankLocker,
                                 GarmentDispenserCode,
                                 DeliveryPointCode);
    Totalamount := 0;
  end if;
exception
  when others then
    null;
end GetWearerDataKannegiesser_RUS;
/
create or replace procedure importNANNumber is

  gvsmasteraccount      customer.searchname%type;
  gvnean                productlistpercustomer.eannumber%type;
  gvnnan                productlistpercustomer.nannumber%type;
  gverrrormsg           abslog.message%type;
  gvdirectory           systemsetting.value%type;
  gvfilename            varchar2(10) := 'NAN.CSV';
  gvseparator           varchar2(1) := ';';
  hfile                 utl_file.file_type;
  gvline                varchar2(40);
  gvlinesprocessed      number := 0;

  procedure write_log(fp_message  in abslog.message%type,
                      fp_priority in abslog.priority%type default 1) is
  begin
    /*
    Write message in ABSLOG with these priorities
    1 = Message
    2 = Warning
    3 = Error
    4 = Stack trace
    5 = Debug info
    */
    abslogwrite.abslog_write(5, 'IMPORTNANNUMBER', null, fp_priority, fp_message,
                             null);
  end write_log;

  --get the value of the system setting of the plant
  procedure get_directory is
  begin
    gverrrormsg := 'get_directory';
    select nvl(ss.value, ss.factorydefault)
    into   gvdirectory
    from   plant p, systemsetting ss
    where  p.code = (select min(p2.code)
               from plant p2) and p.plant_id=ss.plant_id and ss.name='DATABASELOGDIR';
    if gvdirectory is null then
      gvdirectory := 'C:\';
    end if;
  end get_directory;

  --open file procedure
  procedure open_file is
  begin
    get_directory;
    gverrrormsg := 'open_file ' || gvdirectory || gvfilename;
    hfile       := utl_file.fopen(gvdirectory, gvfilename, 'r');
  exception
    when utl_file.invalid_path then
      raise_application_error(-20100, 'Invalid Path');
    when utl_file.invalid_mode then
      raise_application_error(-20101, 'Invalid Mode');
    when utl_file.invalid_filehandle then
      raise_application_error(-20102, 'Invalid Filehandle');
    when utl_file.invalid_operation then
      raise_application_error(-20103, 'Invalid Operation -- May signal a file locked by the OS or file does not exist');
    when utl_file.read_error then
      raise_application_error(-20104, 'Read Error');
    when utl_file.write_error then
      raise_application_error(-20105, 'Write Error');
    when utl_file.internal_error then
      raise_application_error(-20106, 'Internal Error');
    when utl_file.charsetmismatch then
      raise_application_error(-20107, 'Characterset Mismatch error');
    when utl_file.file_open then
      raise_application_error(-20108, 'Cannot perform the operation.File is open');
    when utl_file.invalid_maxlinesize then
      raise_application_error(-20109, 'Invalid Max line size');
    when utl_file.invalid_filename then
      raise_application_error(-20110, 'Invalid Filename');
    when utl_file.access_denied then
      raise_application_error(-20111, 'Access Denied');
    when utl_file.invalid_offset then
      raise_application_error(-20112, 'Invalid Offset');
    when utl_file.delete_failed then
      raise_application_error(-20113, 'File Delete failed');
    when utl_file.rename_failed then
      raise_application_error(-20114, 'File Rename failed');
    when no_data_found then
      raise_application_error(-20115, 'No Data Found');
    when value_error then
      raise_application_error(-20116, 'Value Error');
    when others then
      raise_application_error(-20117, 'Unknown UTL_FILE Error');
  end open_file;

--close file procedure
 procedure close_file is
  begin
    gverrrormsg := 'close_file  ' || gvdirectory || gvfilename;
    if utl_file.is_open(hfile) = true then
      utl_file.fclose(hfile);
    end if;
    utl_file.fclose_all;
  end close_file;

--read line
    procedure read_line is
  begin
    gverrrormsg       := 'read_line';
    gvsmasteraccount  := substr(gvline, 0, instr(gvline, gvseparator) -1);
    gvnean            := to_number(substr(gvline, instr(gvline, gvseparator,1,1) + 8, 5));
    gvnnan            := to_number(substr(gvline, instr(gvline, gvseparator,1,2) + 1,instr(gvline, gvseparator,1,3)-instr(gvline, gvseparator,1,2)-1));
  end read_line;

--process line
 procedure process_line is

      cursor customer_list(searchName  customer.searchname%type) is
             select c.customer_id from customer c
             where c.masteraccount_id
             in ( select cc.customer_id from customer cc where cc.searchname = searchName);
      cursor plpc_list(customerID  productlistpercustomer.customer_id%type) is
              select plpc.productlistpercustomer_id, plpc.eannumber from productlistpercustomer plpc
              where plpc.customer_id = customerID ;
      i        integer:=0;
      j        integer:=0;
 begin

     for r_customer in customer_list(gvsmasteraccount) loop
      i:=0;
      for r_plpc in plpc_list(r_customer.customer_id) loop
        i:=i+1;
        if (r_plpc.eannumber = gvnean ) then
          update productlistpercustomer plpc set plpc.nannumber = gvnnan
            where plpc.productlistpercustomer_id = r_plpc.productlistpercustomer_id;
        end if;
      end loop;
      j:=j+1;
      if (j > 10000) then commit; j:=0; end if;
    end loop;
    gvlinesprocessed := gvlinesprocessed + 1;
 end process_line;


 begin
  write_log('START');
  open_file;
     -- first line do not proces/read it! (first line = name of columns)
      utl_file.get_line(hfile, gvline);
  loop
    begin
      gvline := null;
      utl_file.get_line(hfile, gvline);
    exception
      when no_data_found then
        exit;
    end;
    begin
      read_line;
      process_line;
    end;
  end loop;
  close_file;
  commit;
  write_log(gvlinesprocessed || ' line(s) processed from ' || gvdirectory || gvfilename);
  write_log('ENDED SUCCESFULLY');
exception
  when no_data_found then
    begin
      rollback;
      write_log(gverrrormsg, 3);
      write_log('not found !', 3);
      write_log('ENDED WITH ERRORS');
      close_file;
      raise;
    end;
  when others then
    begin
      rollback;
      write_log(gverrrormsg, 3);
      write_log(sqlerrm, 3);
      write_log('ENDED WITH ERRORS');
      close_file;
      raise;
    end;
end importNANNumber;
/
create or replace procedure importsoilscan(fpnplantid      plant.plant_id%type,
                                           fpsreadfilename varchar2) is
  lvnsystemuserid       systemuser.systemuser_id%type;
  lvsplantcode          plant.code%type;
  lvsworkstationcode    workstation.code%type;
  lvninscanhourinterval number;
  lvslogdir             systemsetting.value%type;
  lvsreaddir            systemsetting.value%type;
  lvhlogfile            utl_file.file_type;
  lvhreadfile           utl_file.file_type;
  lvsreadline           varchar2(4000);
  lvnposition           number;
  lvserror              varchar2(155);
  lvsbarcode            uniqueitem.primaryid%type;
  lvnuniqueid           uniqueitem.uniqueitem_id%type;
  lvnsecondaryid        secondaryuniqueitem.uniqueitem_id%type;
  lvnbusinessunitid     businessunit.businessunit_id%type;
  lvdtpickupdate        date;
  lvdtscandate          date;
  lvdtlastscandate      uniqueitem.lastscandate%type;
  lvdtlastinscandate    uniqueitem.lastinscandate%type;
  lvsstatuscode         status.code%type;
  lvnstaynr             stay.staynr%type;
  lvsaccept             varchar2(1);
  lvndebuglevel         integer := 0;
  lvsscaninterval       varchar2(1);
  lvsscanbyroute        varchar2(1) := 'Y';
  lvscountwashesat      varchar2(1) := 'Y';
  lvuserexception exception;
  lvproceduretype varchar2(30) := 'Process import soil scan';
  lvretransferyn  varchar2(1);

  procedure write_log(fp_err_msg   in varchar2,
                      fp_debugmode in varchar2 default 'Y',
                      fp_priority  in number default 1) is
  begin
    /* writes conversion logs into database.
    priority
    1 = Message
    2 = Warning
    3 = Error
    4 = Stack trace
    5 = Debug info  */
    if fp_debugmode = 'Y' then
      abslogwrite.abslog_write(5, lvproceduretype, null, fp_priority, fp_err_msg, lvnsystemuserid);
    end if;
  end write_log;

begin
  --get systemuser
  lvserror := 'Error getting the sytem user';
  begin
    select s.systemuser_id into lvnsystemuserid from systemuser s where s.username = 'SORT';
  exception
    when no_data_found then
      select min(systemuser_id) into lvnsystemuserid from systemuser;
  end;
  --get plant id
  lvserror := 'Plant id ' || fpnplantid;
  select p.code into lvsplantcode from plant p where p.plant_id = fpnplantid;
  --get workstation
  lvserror := 'Error getting the inscan workstation for plant ' || lvsplantcode;
  select min(w.code)
  into   lvsworkstationcode
  from   sortingimportdefinition s, workstation w
  where  s.plant_id = fpnplantid
  and    s.transactiontype = 1
  and    s.workstation_id = w.workstation_id;
  --get inscan hour interval for plant
  lvserror := 'INSCANALLOWHOURINTERVAL for plant ' || lvsplantcode;
  select to_number(trim(s.value))
  into   lvninscanhourinterval
  from   systemsetting s
  where  s.name = 'INSCANALLOWHOURINTERVAL'
  and    s.plant_id = fpnplantid;
  --get log file
  lvserror := 'Getting DATABASELOGDIR for plant ' || lvsplantcode;
  select s.value
  into   lvslogdir
  from   systemsetting s
  where  s.name = 'DATABASELOGDIR'
  and    s.plant_id = fpnplantid;
  --get soil scan file
  lvserror   := 'opening processimportsoilscans.log in directory ' || lvslogdir || ' for plant ' ||
                lvsplantcode;
  lvhlogfile := utl_file.fopen(lvslogdir, 'processimportsoilscans.log', 'a');
  lvserror   := 'Getting IMPDIRSOILSCANORACLE for plant ' || lvsplantcode;
  select s.value
  into   lvsreaddir
  from   systemsetting s
  where  s.name = 'IMPDIRSOILSCANORACLE'
  and    s.plant_id = fpnplantid;
  lvserror    := 'opening ' || fpsreadfilename || ' for reading in directory ' || lvsreaddir ||
                 ' for plant ' || lvsplantcode;
  lvhreadfile := utl_file.fopen(lvsreaddir, fpsreadfilename, 'r');
  --check if it is a correction file
  if upper(substr(fpsreadfilename, length(fpsreadfilename) - 2, 3)) = 'ABC' then
    lvretransferyn := 'Y';
  else
    lvretransferyn := 'N';
  end if;
  --getting system settings
  lvserror := 'Getting system settings for plant ' || lvsplantcode;
  begin
    select substr(trim(s.value), 1, 1)
    into   lvscountwashesat
    from   systemsetting s
    where  s.name = 'COUNTWASHESAT'
    and    s.plant_id = fpnplantid;
  exception
    when no_data_found then
      lvscountwashesat := 'N';
  end;
  begin
    select substr(trim(s.value), 1, 1)
    into   lvsscanbyroute
    from   systemsetting s
    where  s.plant_id = fpnplantid
    and    s.name = 'SCANBYROUTE';
  exception
    when no_data_found then
      lvsscanbyroute := 'Y';
  end;
  --process fpsreadfilename file
  lvserror := 'reading ' || fpsreadfilename || ' reading in directory ' || lvsreaddir ||
              ' for plant ' || lvsplantcode;
  loop
    begin
      begin
        -- get line from file.
        utl_file.get_line(lvhreadfile, lvsreadline);
      exception
        when no_data_found then
          exit;
      end;
      --get barcode
      lvnposition := instr(lvsreadline, '''') - 1;
      lvsbarcode  := substr(lvsreadline, 1, lvnposition);
      lvserror    := 'None pool chipcode ' || lvsbarcode || ' for plant ' || lvsplantcode;
      select u.uniqueitem_id, u.businessunit_id, st.code, sy.staynr, u.lastscandate,
             u.lastinscandate
      into   lvnuniqueid, lvnbusinessunitid, lvsstatuscode, lvnstaynr, lvdtlastscandate,
             lvdtlastinscandate
      from   uniqueitem u, businessunit bu, status st, stay sy
      where  u.primaryid = lvsbarcode
      and    u.poolitem = 2
      and    u.businessunit_id = bu.businessunit_id
      and    bu.plant_id = fpnplantid
      and    u.status_id = st.status_id
      and    u.stay_id = sy.stay_id;
      --secondaryID
      begin
        select s.secondaryid
        into   lvnsecondaryid
        from   secondaryuniqueitem s
        where  s.uniqueitem_id = lvnuniqueid;
      exception
        when no_data_found then
          null;
      end;
      --get pickup date
      lvserror       := 'invalid pickupdate for chipcode ' || lvsbarcode;
      lvdtpickupdate := to_date(substr(lvsreadline, lvnposition + 4, 10), 'yyyy-mm-dd');
      --get scan date
      lvserror     := 'invalid scandate/time for chipcode ' || lvsbarcode;
      lvdtscandate := to_date(substr(lvsreadline, lvnposition + 17, 10) ||
                              substr(lvsreadline, lvnposition + 30, 8), 'yyyy-mm-dd hh24:mi:ss');
      --check barcode status
      if lvsstatuscode not in ('20', '30') then
        begin
          lvserror := 'Chipcode ' || lvsbarcode || ' has wrong status ' || lvsstatuscode;
          raise lvuserexception;
        end;
      end if;
      --check barcode last scandate with lastscandate
      if lvdtlastscandate > lvdtscandate and lvretransferyn = 'N' then
        begin
          lvserror := 'Chipcode ' || lvsbarcode || ' has been scanned already';
          raise lvuserexception;
        end;
      end if;
      --check inscan hour interval
      if lvninscanhourinterval > 0 and lvdtlastinscandate is not null and lvnstaynr = 30 and
         (lvdtlastinscandate + (lvninscanhourinterval / 24)) > lvdtscandate and
         lvretransferyn = 'N' then
        begin
          lvserror := 'Chipcode ' || lvsbarcode || ' has been scanned in less then ' ||
                      lvninscanhourinterval || ' hours before';
          raise lvuserexception;
        end;
      end if;
      --barcode is ok to be processed
      lvserror := 'Error during pack_sort.processinscan for barcode ' || lvsbarcode;
      pack_sort.processinscan(1, lvsbarcode, 2, lvnsecondaryid, fpnplantid, fpnplantid, lvnbusinessunitid,
                              lvnuniqueid, lvsworkstationcode,
                              to_number(to_char(lvdtscandate, 'YYYYMMDD')),
                              to_char(lvdtscandate, 'HH24MISS'), lvscountwashesat, lvsscanbyroute,
                              lvnsystemuserid, lvndebuglevel, lvsaccept, lvsscaninterval,
                              lvdtpickupdate, lvretransferyn);
      commit;
    exception
      when lvuserexception then
        begin
          rollback;
          dbms_output.put_line(lvserror);
          begin
            write_log(lvserror, 'Y', 3);
          end;
        end;
      when no_data_found then
        begin
          rollback;
          lvserror := lvserror || ' does not exist.';
          dbms_output.put_line(lvserror);
          begin
            write_log(lvserror, 'Y', 3);
          end;
        end;
      when others then
        begin
          rollback;
          lvserror := lvserror || ' ' || substr(sqlerrm, 1, 200);
          dbms_output.put_line(lvserror);
          begin
            write_log(lvserror, 'Y', 3);
          end;
        end;
    end;
  end loop;
  if utl_file.is_open(lvhlogfile) = true then
    begin
      utl_file.fclose(lvhlogfile);
    end;
  end if;
  if utl_file.is_open(lvhreadfile) = true then
    begin
      utl_file.fclose(lvhreadfile);
    end;
  end if;

exception
  when utl_file.invalid_path then
    begin
      lvserror := lvserror || ' Invalid Path';
      dbms_output.put_line(lvserror);
    end;
  when utl_file.invalid_mode then
    begin
      lvserror := lvserror || ' Invalid Mode';
      dbms_output.put_line(lvserror);
    end;
  when utl_file.invalid_operation then
    begin
      lvserror := lvserror || ' Invalid Operation';
      dbms_output.put_line(lvserror);
    end;
  when utl_file.invalid_filehandle then
    begin
      lvserror := lvserror || ' Invalid Filehandle';
      dbms_output.put_line(lvserror);
    end;
  when utl_file.write_error then
    begin
      lvserror := lvserror || ' Write Error';
      dbms_output.put_line(lvserror);
    end;
  when utl_file.read_error then
    begin
      lvserror := lvserror || ' Read Error';
      dbms_output.put_line(lvserror);
    end;
  when utl_file.internal_error then
    begin
      lvserror := lvserror || ' Internal Error';
      dbms_output.put_line(lvserror);
    end;
  when no_data_found then
    begin
      rollback;
      lvserror := lvserror || ' does not exist.';
      dbms_output.put_line(lvserror);
      begin
        write_log(lvserror, 'Y', 3);
        utl_file.fclose(lvhlogfile);
      end;
    end;
  when others then
    begin
      rollback;
      lvserror := lvserror || ' ' || substr(sqlerrm, 1, 200);
      dbms_output.put_line(lvserror);
      begin
        write_log(lvserror, 'Y', 3);
        utl_file.fclose(lvhlogfile);
      end;
      if utl_file.is_open(lvhreadfile) = true then
        begin
          utl_file.fclose(lvhreadfile);
        end;
      end if;
    end;
end importsoilscan;
/
create or replace procedure InactivateProduct(Productcode  in Product.Code%type,
                                              DateInactive in number,
                                              DateObsolete in number,
                                              Status       out number) is
  productid       product.product_id%type;
  systemuserid    systemuser.systemuser_id%type;
  SQLfile         utl_file.file_type;
  UTLDIR          varchar2(50);
  FPsFilename     varchar2(50);
  debuglevel      integer := 1;
  sessionsid      integer;
  sessionserialnr integer;
begin
  begin
    select s.dblogdir into UTLDIR from databasesettings s;
  EXCEPTION
    WHEN no_data_found then
      UTLDIR := 'C:\'; -- please see ABS-92804 variable needs the name of an existing oracle directory
  end;
  select a.SID, a.SERIAL#
    into sessionsid, sessionserialnr
    from SYS.V_$SESSION a
   where a.AUDSID = (SELECT sys_context('USERENV', 'SESSIONID') FROM dual);
  FPsFilename := 'InactivateProduct_' || to_char(sysdate, 'YYYYMMDDHHMMSS') || '_' ||
                 sessionsid || '_' || sessionserialnr || '.txt';
  SqlFile     := UTL_FILE.FOPEN(UTLDIR, FPsFilename, 'a');
  begin
    Status := 0;
    begin
      select s.systemuser_id
        into systemuserid
        from systemuser s
       where s.username = 'AXAPTA';
    exception
      when no_data_found then
        select min(s.systemuser_id) into systemuserid from systemuser s;
    end;
    begin
      select p.product_id
        into productid
        from product p
       where p.code = ProductCode;
    exception
      when no_data_found then
        Status := 1;
    end;
    If status = 0 then
      begin
        update product p
           set p.active        = 'N',
               p.systemuser_id = systemuserid,
               p.timestamp     = sysdate
         where p.product_id = productid;
      exception
        when others then
          Status := 1;
          if debuglevel > 0 then
            utl_file.put_line(SQLfile,
                              '!> Update for Product ' || Productcode ||
                              ' failed ' || sqlcode || ' ' || sqlerrm);
          end if;
      end;
    end if;
    if debuglevel > 0 then
      utl_file.put_line(SQLfile, 'Product code ' || productcode);
      utl_file.put_line(SQLfile, 'Date inactive ' || DateInactive);
      utl_file.put_line(SQLfile, 'Date obsolete ' || DateObsolete);
      utl_file.put_line(SQLfile, 'Satus ' || Status);
    end if;
    commit;
  exception
    when others then
      rollback;
      Status := 99;
      utl_file.put_line(SqlFile,
                        ProductCode || ' ' || sqlcode || ' ' || sqlerrm);
  end;
  UTL_FILE.FCLOSE(SqlFile);
end InactivateProduct;
/
create or replace procedure Ins_Data_CostCenterHistInvData(
                                                           fp_costcenterhistinvdata_id  COSTCENTERHISTINVDATA.COSTCENTERHISTINVDATA_ID%type,
                                                           fp_invoiceheader_id          COSTCENTERHISTINVDATA.INVOICEHEADER_ID%type,
                                                           fp_distributionpoint_link_id COSTCENTERHISTINVDATA.DISTRIBUTIONPOINT_LINK_ID%type,
                                                           fp_product_link_id           COSTCENTERHISTINVDATA.PRODUCT_LINK_ID%type,
                                                           fp_sizedefinition_link_id    COSTCENTERHISTINVDATA.SIZEDEFINITION_LINK_ID%type,
                                                           fp_finishingmethod_id        COSTCENTERHISTINVDATA.FINISHINGMETHOD_ID%type,
                                                           fp_deliveryscheme_id         COSTCENTERHISTINVDATA.DELIVERYSCHEME_ID%type,
                                                           fp_costcenter_link_id        COSTCENTERHISTINVDATA.COSTCENTER_LINK_ID%type,
                                                           fp_startdate                 COSTCENTERHISTINVDATA.STARTDATE%type,
                                                           fp_daysinperiod              COSTCENTERHISTINVDATA.DAYSINPERIOD%type,
                                                           fp_systemuser_id             COSTCENTERHISTINVDATA.SYSTEMUSER_ID%type,
                                                           fp_timestamp                 COSTCENTERHISTINVDATA.TIMESTAMP%type,
                                                           fp_origin                    COSTCENTERHISTINVDATA.ORIGIN%type,
                                                           fp_actualrentstop            ACTUALRENTSTOP_TAB1,
                                                           fp_actualprice               ACTUALPRICE_TAB1,
                                                           fp_actualdiscount            ACTUALDISCOUNT_TAB1,
                                                           fp_actualquantity            ACTUALQUANTITY_TAB1,
                                                           fp_actualsampleqty           ACTUALSAMPLEQTY_TAB1,
                                                           fp_actualcalcprice           ACTUALCALCPRICE_TAB1

                                                           ) is

begin

  insert into COSTCENTERHISTINVDATA
    (COSTCENTERHISTINVDATA_ID,
     INVOICEHEADER_ID,
     DISTRIBUTIONPOINT_LINK_ID,
     PRODUCT_LINK_ID,
     SIZEDEFINITION_LINK_ID,
     FINISHINGMETHOD_ID,
     DELIVERYSCHEME_ID,
     COSTCENTER_LINK_ID,
     STARTDATE,
     DAYSINPERIOD,
     SYSTEMUSER_ID,
     TIMESTAMP,
     ORIGIN,
     cc_rentstop,
     cc_actualprice,
     cc_actualdiscount,
     cc_actualquantity,
     cc_actualsampleqty,
     cc_calcprice)
  VALUES
    (fp_costcenterhistinvdata_id,
     fp_invoiceheader_id,
     fp_distributionpoint_link_id,
     fp_product_link_id,
     fp_sizedefinition_link_id,
     fp_finishingmethod_id,
     fp_deliveryscheme_id,
     fp_costcenter_link_id,
     fp_startdate,
     fp_daysinperiod,
     fp_systemuser_id,
     fp_timestamp,
     fp_origin,
     fp_actualrentstop,
     fp_actualprice,
     fp_actualdiscount,
     fp_actualquantity,
     fp_actualsampleqty,
     fp_actualcalcprice);
end;
/
create or replace procedure microsstransfersoil(customerid in varchar2,
                                                productid  in varchar2,
                                                lquantity  in number,
                                                timestamp  in number) is
 -- Updated : 30-09-2020 DLA ABS-108518 Delivery variations processbusinessunit_id and internalprocessingbu_id are not filled when creating DV from Pack_multiread

  /*MicrossTransferSoil Version 2.1*/
  gv_userexception exception;
  gv_message             abslog.message%type;
  gv_customerid          number(28, 0);
  gv_productid           number(28, 0);
  gv_distributionpointid number(28, 0);
  gv_sizeid              number(28, 0);
  gv_finishingmethodid   number(28, 0);
  gv_processbuid         number(28, 0);
  gv_plantid             number(28, 0);
  gv_systemuserid        number(28, 0);
  gv_delayevenexchange   number(28, 0);
  gv_plpcid              number(28, 0);
  gv_currentdate         date;
  gv_deliverypointid     number(28, 0);
  gv_typeofmerch         int;
  gv_invoicebuid         number(28, 0);
  gv_plpcsdid            number(28, 0);

  --internal procedures
  procedure write_log(fp_message in varchar2, fp_priority in number) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'microsstransfersoil', gv_plantid, fp_priority, fp_message,
                             gv_systemuserid);
  end write_log;

  procedure initialize is
  begin
    -- 'STEP1'
    --initialize
    gv_message     := 'check parameter timestamp (YYYYMMDD) ' || timestamp;
    gv_currentdate := to_date(timestamp, 'YYYYMMDD');
    begin
      gv_message := 'get systemuser';
      select s.systemuser_id into gv_systemuserid from systemuser s where s.username = 'SORT';
    exception
      when no_data_found then
        select min(systemuser_id) into gv_systemuserid from systemuser;
    end;
  end initialize;

  procedure check_parameters is
  begin
    -- 'STEP2'
    --check_parameters get customer id
    gv_message := 'Customer legacycustomernumber ' || customerid;
    select c.customer_id, c.defaultbusinessunit_id, bu.plant_id
    into   gv_customerid, gv_processbuid, gv_plantid
    from   customer c
    join   businessunit bu
    on     bu.businessunit_id = c.defaultbusinessunit_id
    where  c.legacycustomernumber = customerid;
    --get distributionpoint if
    gv_message := 'Distributionpoint id for customer legacycustomernumber ' || customerid;
    select di.distributionpoint_id
    into   gv_distributionpointid
    from   distributionpoint di
    where  di.department_id =
           (select min(d.department_id) from department d where d.customer_id = gv_customerid);
    --get product
    gv_message := 'get product legacyproductcode ' || productid;
    select p.product_id, p.typeofmerchandise
    into   gv_productid, gv_typeofmerch
    from   product p
    where  p.legacyproductcode = productid;
    --get size
    gv_message := 'get size';
    select min(ps.sizedefinition_id)
    into   gv_sizeid
    from   productsize ps
    where  ps.product_id = gv_productid
    and    ps.sizedefinition_id in
           (select s.sizedefinition_id from sizedefinition s where s.code <> '*');
    --get finisingmethod
    gv_message := 'get finishingmethod';
    select min(pf.finishingmethod_id)
    into   gv_finishingmethodid
    from   productfinishingmethod pf
    where  pf.product_id = gv_productid;
    --get deliverypoint
    gv_message := 'get deliverypoint';
    select min(dv.deliverypoint_id)
    into   gv_deliverypointid
    from   deliverypoint dv
    where  dv.customer_id = gv_customerid;
    --get gv_invoicebuid
    gv_message := 'get gv_invoicebuid';
    select coalesce(min(ca.invoicebusinessunit_id), gv_processbuid)
    into   gv_invoicebuid
    from   customeractivities ca, product p, productgroup pg, activity a
    where  ca.activity_id = a.activity_id
    and    a.activity_id = pg.activity_id
    and    pg.productgroup_id = p.productgroup_id
    and    ca.customer_id = gv_customerid
    and    p.product_id = gv_productid
    and    ca.processbusinessunit_id = gv_processbuid;
    --get plpc
    select min(plpc.productlistpercustomer_id)
    into   gv_plpcid
    from   productlistpercustomer plpc
    where  plpc.customer_id = gv_customerid
    and    plpc.product_id = gv_productid
    and    plpc.dateactive <= gv_currentdate
    and    plpc.dateinactive >= gv_currentdate;
    if gv_plpcid is not null then
     select plpc.finishingmethod_id
      into gv_finishingmethodid
      from productlistpercustomer plpc where plpc.productlistpercustomer_id=gv_plpcid;
      end if;
    if gv_plpcid is not null then
      begin
    select plpc.sizedefinition_id
           into gv_plpcsdid
           from productlistpercustomer plpc, sizedefinition sd
    where plpc.productlistpercustomer_id=gv_plpcid
    and plpc.sizedefinition_id=sd.sizedefinition_id
    and sd.code <> '*';
    if gv_plpcsdid is not null
      then
    gv_sizeid:=gv_plpcsdid;
    end if;
    end;
    end if;
    if gv_plpcid is null then gv_delayevenexchange:=0;
      else
    select nvl(plpc.delayedevenexchange,0)
    into   gv_delayevenexchange
    from   productlistpercustomer plpc
    where  plpc.productlistpercustomer_id = gv_plpcid;
     end if;
    gv_message := 'productlistpercustomer for customer/product ' || customerid || '/' || productid ||
                  ' with product/size/finishingmethod ID:' || gv_productid || '/' || gv_sizeid || '/' ||
                  gv_finishingmethodid;
    if gv_plpcid is null then
      begin
        gv_message := 'No data found! ' || gv_message;
        raise gv_userexception;
      end;
    end if;
  end check_parameters;

  procedure create_soilcount is
    soilcountid number(28, 0);
  begin
    --create_soilcount
    --'STEP3'
    gv_message := 'create_soilcount';
    begin
      select s.soilcount_id
      into   soilcountid
      from   soilcount s
      where  s.distributionpoint_link_id = gv_distributionpointid
      and    s.processbusinessunit_id = gv_processbuid
      and    s.countdate = trunc(gv_currentdate);
      --update soilcount
      gv_message := 'update soilcount';
      update soilcount s
      set    s.systemuser_id = gv_systemuserid, s.timestamp = sysdate
      where  s.soilcount_id = soilcountid;
    exception
      when no_data_found then
        begin
          --insert soilcountline
          gv_message := 'insert soilcountline';
          insert into soilcount
            (soilcount_id, distributionpoint_link_id, processbusinessunit_id, countdate,
             systemuser_id, timestamp)
          values
            (seq_soilcount.nextval, gv_distributionpointid, gv_processbuid,
             trunc(gv_currentdate), gv_systemuserid, sysdate);
        end;
    end;
    begin
      if soilcountid is not null then
        begin
          --insert into soilcountline
          gv_message := 'insert soilcountline';
          insert into soilcountline
            (soilcountline_id, soilcount_id, product_link_id, sizedefinition_link_id,
             finishingmethod_id, countconverted, countkeypad, countlightframe, countabused,
             soilweight, delayevenexchange, unrelatedloan, systemuser_id, timestamp)
          values
            (seq_soilcountline.nextval, soilcountid, gv_productid, gv_sizeid, gv_finishingmethodid,
             null, null, lquantity, 0, 0, gv_delayevenexchange, 'N', gv_systemuserid, sysdate);
        exception
          when dup_val_on_index then
            begin
              --update soilcountline
              gv_message := 'update soilcountline';
              update soilcountline
              set    countlightframe = nvl(countlightframe, 0) + lquantity,
                     systemuser_id = gv_systemuserid, timestamp = gv_currentdate
              where  soilcount_id = soilcountid
              and    product_link_id = gv_productid
              and    sizedefinition_link_id = gv_sizeid
              and    finishingmethod_id = gv_finishingmethodid;
            end;
        end;
      else
        begin
          --insert into soilcountline
          gv_message := 'insert into soilcountline';
          insert into soilcountline
            (soilcountline_id, soilcount_id, product_link_id, sizedefinition_link_id,
             finishingmethod_id, countconverted, countkeypad, countlightframe, countabused,
             soilweight, delayevenexchange, unrelatedloan, systemuser_id, timestamp)
          values
            (seq_soilcountline.nextval, seq_soilcount.currval, gv_productid, gv_sizeid,
             gv_finishingmethodid, null, null, lquantity, 0, 0, gv_delayevenexchange, 'N',
             gv_systemuserid, sysdate);
        end;
      end if;
    end;
    begin
      --insert into soilhistory
      gv_message := 'insert into soilhistory';
      insert into soilhistory
        (soilhistory_id, customer_link_id, product_link_id, sizedefinition_link_id,
         processbusinessunit_id, quantityabused, quantitysoil, daynumber, week, year, receivingdate,
         systemuser_id, timestamp, distributionpoint_link_id, invoicebusinessunit_id)
      values
        (seq_soilhistory.nextval, gv_customerid, gv_productid, gv_sizeid, gv_processbuid, 0,
         lquantity, getabsdaynumber(gv_currentdate), getisoweek(gv_currentdate),
         getyearofweek(gv_currentdate), trunc(gv_currentdate), gv_systemuserid, sysdate,
         gv_distributionpointid, gv_invoicebuid);
    exception
      when dup_val_on_index then
        begin
          --update soilhistory
          gv_message := 'update soilhistory';
          update soilhistory
          set    quantitysoil = nvl(quantitysoil, 0) + lquantity, systemuser_id = gv_systemuserid,
                 timestamp = gv_currentdate
          where  customer_link_id = gv_customerid
          and    product_link_id = gv_productid
          and    sizedefinition_link_id = gv_sizeid
          and    processbusinessunit_id = gv_processbuid
          and    distributionpoint_link_id = gv_distributionpointid
          and    receivingdate = trunc(gv_currentdate);
        end;
    end;
  end create_soilcount;

  procedure create_delevenexchange is
    lastindate           date;
    deliveryvariationsid number(28, 0);
    amount               number(28, 6); --deliveryvariations
    vdeliverydate        date;
    scanbyroute          varchar2(1);
    lastinroute          route.route_id%type;
    routestopin          routestop.routestop_id%type;
    deedeliveryschemeid  deliveryscheme.deliveryscheme_id%type;
    routestopid          routestop.routestop_id%type;
    plannedroute         route.route_id%type;
    soilcountsubtype     deliveryvariations.soilcountsubtype%type; --Todo9361
  begin
    --create_delevenexchange
    --'STEP4'
    gv_message := 'create_delevenexchange';
    if gv_delayevenexchange > 0 then
      begin
        --pack_sort.getlastinroute
        gv_message := 'pack_sort.getlastinroute';
        pack_sort.getlastinroute(gv_customerid, gv_currentdate, gv_deliverypointid, gv_typeofmerch,
                                 lastinroute, routestopin, lastindate);
        --pack_sort.fillplannedoutroute
        gv_message := 'pack_sort.fillplannedoutroute';
        pack_sort.fillplannedoutroute(gv_plantid, gv_currentdate, gv_typeofmerch,
                                      gv_delayevenexchange,
                                      --deliverymethod,
                                      deedeliveryschemeid, gv_plpcid, gv_customerid,
                                      gv_deliverypointid, lastinroute, lastindate, routestopin,
                                      routestopid, plannedroute, vdeliverydate,
                                      --planneddate,
                                      scanbyroute);
        if vdeliverydate is null then
          vdeliverydate := gv_currentdate + 7;
        end if;
        begin
          ---DISTRIBUTIONPOINT_ID, PRODUCT_ID, SIZEDEFINITION_ID, FINISHINGMETHOD_ID,
          -- PACKINGNOTE_ID, PROCESSED, DELIVERYDATE, ORIGIN, CAUSENOTE_ID,
          --UPDATERENTQTY, SOILCOUNTSUBTYPE, WEBORDERLINE_ID, REFERENCE,
          --ADJUSTMENTREASON_ID, REASONCODE_ID
          select deliveryvariations_id, amount
          into   deliveryvariationsid, amount
          from   deliveryvariations
          where  product_id = gv_productid
          and    sizedefinition_id = gv_sizeid
          and    finishingmethod_id = gv_finishingmethodid
          and    packingnote_id is null
          and    processed = 'N'
          and    causenote_id is null
          and    updaterentqty = 'N'
          and    origin = 1
          and    trunc(deliverydate) = trunc(vdeliverydate)
          and    reference = 'Micross'
          and    distributionpoint_id = gv_distributionpointid
          and    soilcountsubtype = 1
          and    weborderline_id is null;
          --update deliveryvariations
          gv_message := 'update deliveryvariations';
          update deliveryvariations
          set    amount = nvl(amount, 0) + lquantity, systemuser_id = gv_systemuserid,
                 timestamp = sysdate
          where  deliveryvariations.deliveryvariations_id = deliveryvariationsid;
        exception
          when no_data_found then
            begin
              --insert into deliveryvariations
              gv_message := 'insert into deliveryvariations';
              insert into deliveryvariations
                (deliveryvariations_id, product_id, packingnote_id, causenote_id, deliverydate,
                 origin, amount, finishingmethod_id, fixedamount, distributionpoint_id,
                 sizedefinition_id, reference, systemuser_id, processed, timestamp, updaterentqty,
                 adjustmentreason_id, soilcountsubtype, processbusinessunit_id, internalprocessingbu_id)
              values
                (seq_deliveryvariations.nextval, gv_productid, null, null, vdeliverydate, 1,
                 lquantity, gv_finishingmethodid, 'N', gv_distributionpointid, gv_sizeid, 'Micross',
                 gv_systemuserid, 'N', sysdate, 'N', null, 1, gv_processbuid, gv_processbuid);
            end;
        end;
      end;
    end if; --for delayevenexchange>0
  end create_delevenexchange;

  procedure create_onsiteinvadjustment is
    recordonsiteinv              varchar2(10);
    productlistperdistribpointid number(28, 0);
  begin
    --create_onsiteinvadjustment
    --'STEP5'
    gv_message := 'create_onsiteinvadjustment for gv_plpcid ' || gv_plpcid;
    if gv_plpcid is not null then
      begin
        select nvl(max(value), 'N')
        into   recordonsiteinv
        from   systemsetting
        where  name = 'RECORDONSITEINVENTORY'
        and    plant_id = gv_plantid;
        if recordonsiteinv = 'Y' then
          begin
            --select productlistperdistribpoint
            gv_message := 'select productlistperdistribpoint for distributionpoint_id ' ||
                          gv_distributionpointid || ' product_id ' || gv_productid || ' size ' ||
                          gv_sizeid || ' finishingmethod_id ' || gv_finishingmethodid;
            select productlistperdistribpoint_id
            into   productlistperdistribpointid
            from   productlistperdistribpoint
            where  distributionpoint_id = gv_distributionpointid
            and    product_id = gv_productid
            and    sizedefinition_id = gv_sizeid
            and    finishingmethod_id = gv_finishingmethodid;
            begin
              --insert into onsiteinventoryadjustment
              gv_message := 'insert into onsiteinventoryadjustment';
              insert into onsiteinventoryadjustment
                (onsiteinventoryadjustment_id, productlistperdistribpoint_id, origin, inventorydate,
                 quantity, reference, systemuser_id, timestamp)
              values
                (seq_onsiteinventoryadjustment.nextval, productlistperdistribpointid, 4,
                 trunc(gv_currentdate), lquantity * (-1), 'micross', gv_systemuserid, sysdate);
            exception
              when dup_val_on_index then
                begin
                  --update onsiteinventoryadjustment
                  gv_message := 'update onsiteinventoryadjustment';
                  update onsiteinventoryadjustment
                  set    quantity = nvl(quantity, 0) + (-1) * lquantity,
                         systemuser_id = gv_systemuserid, timestamp = sysdate
                  where  productlistperdistribpoint_id = productlistperdistribpointid
                  and    origin = 4
                  and    inventorydate = trunc(gv_currentdate)
                  and    reference = 'micross'
                  and    systemuser_id = gv_systemuserid;
                end;
            end;
          end;
        end if;
      end;
    end if;
  end create_onsiteinvadjustment;

  procedure finalize is
  begin
    --finalize
    gv_message := 'finalize';
    commit;
  end finalize;
begin
  --initialize
  initialize;
  --check_parameters
  check_parameters;
  --create_soilcount
  create_soilcount;
  --create_delevenexchange
  create_delevenexchange;
  --create_onsiteinvadjustment
  create_onsiteinvadjustment;
  --finalize
  finalize;
exception
  --error handling 1 place
  when gv_userexception then
    begin
      rollback;
      write_log(gv_message || ' Parameters used: customer ' || customerid || ' product ' ||
                productid || ' lquantity ' || lquantity || ' timestamp ' || gv_currentdate, 3);
    end;
  when no_data_found then
    begin
      rollback;
      write_log('No data found! ' || gv_message || ' Parameters used: customer ' || customerid ||
                ' product ' || productid || ' lquantity ' || lquantity || ' timestamp ' ||
                gv_currentdate, 3);
    end;
  when others then
    begin
      rollback;
      write_log('Error! ' || gv_message || ' Parameters used: customer ' || customerid ||
                ' product ' || productid || ' lquantity ' || lquantity || ' timestamp ' ||
                gv_currentdate || ' ' || sqlerrm, 3);
    end;
end microsstransfersoil;
/
create or replace procedure oracleTeleServicesCleaningData is
   lv_sqlstmt    VARCHAR2(3000);
begin
      update teleservicesimport set sr_note_details1_clean =regexp_replace(sr_note_details1,'[^' || CHR(1) || '-' || CHR(127) || ']',' ',1,0,'i'),
          sr_note_details2_clean = regexp_replace(sr_note_details2,'[^' || CHR(1) || '-' || CHR(127) || ']',' ',1,0,'i')
          where processed = 0;
      commit;

      update teleservicesimport set sr_note_details1_clean =regexp_replace(sr_note_details1_clean,' {2,}' ,' ',1,0,'m'),
          sr_note_details2_clean =regexp_replace(sr_note_details2_clean,' {2,}' ,' ',1,0,'m')
          where processed = 0;
      commit;


      for record in (select texttoremove, typeofremoval from TELESERVICESDATACLEAN) loop
          if record.typeofremoval =1 then
             lv_sqlstmt := 'update teleservicesimport set sr_note_details1_clean = regexp_replace(sr_note_details1_clean,' || '''^\s(' || record.texttoremove || ').*$''' || ',null,1,0,''m''),' ||
                          ' sr_note_details2_clean = regexp_replace(sr_note_details2_clean,' || '''^\s(' || record.texttoremove || ').*$''' || ',null,1,0,''m'') where processed = 0';
          elsif record.typeofremoval = 2 then
              lv_sqlstmt := 'update teleservicesimport set sr_note_details1_clean = regexp_replace(sr_note_details1_clean,' || '''^' || record.texttoremove || '$''' || ',null,1,0,''m''),' ||
                           ' sr_note_details2_clean = regexp_replace(sr_note_details2_clean,' || '''^' || record.texttoremove || '$''' || ',null,1,0,''m'') where processed = 0';
          else
              lv_sqlstmt := 'update teleservicesimport set sr_note_details1_clean = regexp_replace(sr_note_details1_clean,' || '''.*(' || record.texttoremove || ').*''' || ',null,1,0,''m''), ' ||
                          ' sr_note_details2_clean = regexp_replace(sr_note_details2_clean,' || '''^.*(' || record.texttoremove || ').*$''' || ',null,1,0,''m'') where processed = 0';
          end if;
          EXECUTE IMMEDIATE lv_sqlstmt;
          commit;
      end loop;

      update teleservicesimport set sr_note_details1_clean = translate(sr_note_details1_clean, chr(13) || chr(10)  ,'~~'),
                        sr_note_details2_clean =translate(sr_note_details2_clean, chr(13) || chr(10)  ,'~~')
             where processed = 0;
      commit;

      update teleservicesimport set sr_note_details1_clean = regexp_replace(sr_note_details1_clean,'~ ~' ,'~~',1,0,'i'),
                       sr_note_details2_clean = regexp_replace(sr_note_details2_clean,'~ ~' ,'~~',1,0,'i')
             where processed = 0;
      commit;

         update teleservicesimport set sr_note_details1_clean = LTRIM(sr_note_details1_clean, CHR (10) || CHR (13) || '~'),
                       sr_note_details2_clean = LTRIM(sr_note_details2_clean, CHR (10) || CHR (13) || '~')
             where processed = 0;
      commit;

      update teleservicesimport set sr_note_details1_clean = regexp_replace(sr_note_details1_clean,'~{2,}' ,chr(13) || chr(10) || chr(13) || chr(10) ,1,0,'i'),
                       sr_note_details2_clean =regexp_replace(sr_note_details2_clean,'~{2,}' ,chr(13) || chr(10) || chr(13) || chr(10) ,1,0,'i')
              where processed = 0;
      commit;

      update teleservicesimport set sr_note_details1_clean = regexp_replace(sr_note_details1_clean,'~{1}' ,chr(13) || chr(10) ,1,0,'i'),
                        sr_note_details2_clean = regexp_replace(sr_note_details2_clean,'~{1}' ,chr(13) || chr(10) , 1,0,'i')
               where processed = 0;
      commit;

      update teleservicesimport set sr_note_details1_clean = regexp_replace(sr_note_details1_clean,'^"' ,'' ,1,0,'m'),
                        sr_note_details2_clean = regexp_replace(sr_note_details2_clean,'^"' ,'' ,1,0,'m')
               where processed = 0;
      commit;

exception when others then
                 abslogwrite.abslog_write(5, 'oracleTeleservicesCleaningData', null, 5, substr(sqlerrm, 1, 200));
                 rollback;
end oracleTeleservicesCleaningData;
/
create or replace procedure populate_gacustomerproduct(fp_customer_id in number) is
-- Order 20013062
-- HVH 28/08/2014 Created new.
--                Derived from populate_lacustomerproduct. Differences:
--                this one also loads personalized garments and also looks at plpc size *
-- Purpose of this procedure it to populate and update the gacustomerproduct table for the passed customer_id
-- The gacustomerproduct table is for the GarmentAssistant PDA application to store in
-- one single number (gacustomerproduct_id) the combination of ABSSolute product_id, sizedef_id and finmethod_id

  gv_last_error_number          number := 0;
  gv_last_error_message         varchar2(2000) := '';
  gv_code_block                 varchar2(100) := '';
  gv_sizestar_id                number := 0;

    procedure writeabslog is
     begin
      abslogwrite.abslog_write(5,'populate_gacustomerproduct',null,3,'Error in '
      || gv_code_block || ' ' || to_char(gv_last_error_number) || ' ' || substr(gv_last_error_message, 1,1024));
     end;

begin
 begin
  gv_code_block := 'Get Size Star ID';
  select s.sizedefinition_id
    into gv_sizestar_id
    from sizedefinition s
   where s.code = '*';
  gv_code_block := 'Merge into gacustomerproduct';
  merge into gacustomerproduct using
    (
      select x.customer_id,
             x.product_id,
             x.sizedefinition_id,
             x.finishingmethod_id,
             coalesce((select max(plpc.customcode)
                         from productlistpercustomer plpc
                        where plpc.customer_id = x.customer_id
                          and plpc.product_id = p.product_id
                          and plpc.sizedefinition_id = s.sizedefinition_id
                          and plpc.finishingmethod_id = f.finishingmethod_id
                          and plpc.dateactive <= trunc(sysdate)
                          and plpc.dateinactive >= trunc(sysdate)),
                      (select max(plpc.customcode)
                         from productlistpercustomer plpc
                        where plpc.customer_id = x.customer_id
                          and plpc.product_id = p.product_id
                          and plpc.sizedefinition_id = gv_sizestar_id
                          and plpc.finishingmethod_id = f.finishingmethod_id
                          and plpc.dateactive <= trunc(sysdate)
                          and plpc.dateinactive >= trunc(sysdate)),
                      p.code) productcode,
             s.code sizecode,
             f.code finmethodcode,
             coalesce((select max(plpc.customdescription)
                         from productlistpercustomer plpc
                        where plpc.customer_id = x.customer_id
                          and plpc.product_id = p.product_id
                          and plpc.sizedefinition_id = s.sizedefinition_id
                          and plpc.finishingmethod_id = f.finishingmethod_id
                          and plpc.dateactive <= trunc(sysdate)
                          and plpc.dateinactive >= trunc(sysdate)),
                      (select max(plpc.customdescription)
                         from productlistpercustomer plpc
                        where plpc.customer_id = x.customer_id
                          and plpc.product_id = p.product_id
                          and plpc.sizedefinition_id = gv_sizestar_id
                          and plpc.finishingmethod_id = f.finishingmethod_id
                          and plpc.dateactive <= trunc(sysdate)
                          and plpc.dateinactive >= trunc(sysdate))) productcustomdesc,
             p.typeofmerchandise,
             nvl((select ps.sequencenumber from productsize ps where ps.product_id=p.product_id and ps.sizedefinition_id=s.sizedefinition_id),0) sizesequence,
             coalesce((select max(plpc.codeuniquely)
                         from productlistpercustomer plpc
                        where plpc.customer_id = x.customer_id
                          and plpc.product_id = p.product_id
                          and plpc.sizedefinition_id = s.sizedefinition_id
                          and plpc.finishingmethod_id = f.finishingmethod_id),
                      (select max(plpc.codeuniquely)
                         from productlistpercustomer plpc
                        where plpc.customer_id = x.customer_id
                          and plpc.product_id = p.product_id
                          and plpc.sizedefinition_id = gv_sizestar_id
                          and plpc.finishingmethod_id = f.finishingmethod_id),
                      'Y') codeuniquely,
             coalesce((select max(plpc.onsiteinventorycount)
                         from productlistpercustomer plpc
                        where plpc.customer_id = x.customer_id
                          and plpc.product_id = p.product_id
                          and plpc.sizedefinition_id = s.sizedefinition_id
                          and plpc.finishingmethod_id = f.finishingmethod_id
                          and plpc.dateactive <= trunc(sysdate)
                          and plpc.dateinactive >= trunc(sysdate)),
                      (select max(plpc.onsiteinventorycount)
                         from productlistpercustomer plpc
                        where plpc.customer_id = x.customer_id
                          and plpc.product_id = p.product_id
                          and plpc.sizedefinition_id = gv_sizestar_id
                          and plpc.finishingmethod_id = f.finishingmethod_id
                          and plpc.dateactive <= trunc(sysdate)
                          and plpc.dateinactive >= trunc(sysdate)),
                      'N') onsiteinventorycount
        from
            (select distinct
                   d.customer_id,
                   plpd.product_id,
                   plpd.sizedefinition_id,
                   plpd.finishingmethod_id
             from productlistperdistribpoint plpd,
                  distributionpoint dp,
                  department d
            where d.department_id = dp.department_id
              and plpd.distributionpoint_id = dp.distributionpoint_id
              and d.customer_id = fp_customer_id
            union
            select distinct
                   fp_customer_id,
                   u.product_id,
                   u.sizedefinition_id,
                   u.finishingmethod_id
             from uniqueitem u
            where u.poolitem = 1
              and u.distributionpoint_id in
                  (select dp.distributionpoint_id
                     from distributionpoint dp,
                          department d
                    where d.department_id = dp.department_id
                      and d.customer_id = fp_customer_id)
            union
            select distinct
                   fp_customer_id,
                   u.product_id,
                   u.sizedefinition_id,
                   u.finishingmethod_id
             from uniqueitem u,
                  uniqueitemnonpool unp,
                  weareremployment we,
                  wearer w
            where u.poolitem = 2
              and unp.uniqueitem_id = u.uniqueitem_id
              and we.weareremployment_id = unp.weareremployment_id
              and w.wearer_id = we.wearer_id
              and w.customer_id = fp_customer_id
          ) X,
          product p,
          sizedefinition s,
          finishingmethod f
      where x.product_id = p.product_id
        and x.sizedefinition_id = s.sizedefinition_id
        and x.finishingmethod_id = f.finishingmethod_id
    )
    MERGE_SUBQUERY
  ON (gacustomerproduct.customer_id = merge_subquery.customer_id AND
      gacustomerproduct.product_id = merge_subquery.product_id AND
      gacustomerproduct.sizedefinition_id = merge_subquery.sizedefinition_id AND
      gacustomerproduct.finishingmethod_id = merge_subquery.finishingmethod_id)
  when not matched then
    insert
      (gacustomerproduct_id,
       customer_id,
       product_id,
       sizedefinition_id,
       finishingmethod_id,
       productcode,
       productcustomdesc,
       sizecode,
       finmethodcode,
       typeofmerchandise,
       sizesequence,
       codeuniquely,
       onsiteinventorycount)
    values
      (seq_gacustomerproduct.nextval,
       merge_subquery.customer_id,
       merge_subquery.product_id,
       merge_subquery.sizedefinition_id,
       merge_subquery.finishingmethod_id,
       merge_subquery.productcode,
       merge_subquery.productcustomdesc,
       merge_subquery.sizecode,
       merge_subquery.finmethodcode,
       merge_subquery.typeofmerchandise,
       merge_subquery.sizesequence,
       merge_subquery.codeuniquely,
       merge_subquery.onsiteinventorycount)
  when matched then
    update
    set  productcode = merge_subquery.productcode,
         productcustomdesc = merge_subquery.productcustomdesc,
         sizecode = merge_subquery.sizecode,
         finmethodcode = merge_subquery.finmethodcode,
         typeofmerchandise = merge_subquery.typeofmerchandise,
         sizesequence = merge_subquery.sizesequence,
         codeuniquely = merge_subquery.codeuniquely,
         onsiteinventorycount = merge_subquery.onsiteinventorycount;
  commit;
 exception
   when others then
     begin
      gv_last_error_number  := SQLCODE;
      gv_last_error_message := SQLERRM;
      writeabslog;
    end;
 end;
end populate_gacustomerproduct;
/
create or replace procedure populate_lacustomerproduct(fp_customer_id in number) is
  -- Order 20015191
  -- HVH 02/05/2014 Created new.
  -- HVH 16/05/2014 Added column onsiteinventorycount
  -- HVH 28/08/2014 Fix issue with onsiteinventorycount sometimes having null value
  -- BVA 10/01/2017 (ABS-41480) onsiteinventorycount not updated to Y when plpc contains size '*'
  -- Purpose of this procedure it to populate and update the lacustomerproduct table for the passed customer_id
  -- The lacustomerproduct table is for the LinenAssistant PDA application to store in
  -- one single number (lacustomerproduct_id) the combination of ABSSolute product_id, sizedef_id and finmethod_id

  gv_last_error_number  number := 0;
  gv_last_error_message varchar2(2000) := '';
  gv_code_block         varchar2(100) := '';

  procedure writeabslog is
  begin
    abslogwrite.abslog_write(5,
                             'populate_lacustomerproduct',
                             null,
                             3,
                             'Error in ' || gv_code_block || ' ' ||
                             to_char(gv_last_error_number) || ' ' ||
                             substr(gv_last_error_message, 1, 1024));
  end;

begin
  begin
    gv_code_block := 'Merge into lacustomerproduct';
    merge into lacustomerproduct
    using (select x.customer_id,
                  x.product_id,
                  x.sizedefinition_id,
                  x.finishingmethod_id,
                  nvl((select max(plpc.customcode)
                        from productlistpercustomer plpc
                       where plpc.customer_id = x.customer_id
                         and plpc.product_id = p.product_id
                         and plpc.sizedefinition_id = s.sizedefinition_id
                         and plpc.finishingmethod_id = f.finishingmethod_id
                         and plpc.dateactive <= trunc(sysdate)
                         and plpc.dateinactive >= trunc(sysdate)),
                      p.code) productcode,
                  s.code sizecode,
                  f.code finmethodcode,
                  (select max(plpc.customdescription)
                     from productlistpercustomer plpc
                    where plpc.customer_id = x.customer_id
                      and plpc.product_id = p.product_id
                      and plpc.sizedefinition_id = s.sizedefinition_id
                      and plpc.finishingmethod_id = f.finishingmethod_id
                      and plpc.dateactive <= trunc(sysdate)
                      and plpc.dateinactive >= trunc(sysdate)) productcustomdesc,
                  p.typeofmerchandise,
                  nvl((select ps.sequencenumber
                        from productsize ps
                       where ps.product_id = p.product_id
                         and ps.sizedefinition_id = s.sizedefinition_id),
                      0) sizesequence,
                  nvl((select max(plpc.codeuniquely)
                        from productlistpercustomer plpc
                       where plpc.customer_id = x.customer_id
                         and plpc.product_id = p.product_id
                         and plpc.sizedefinition_id = s.sizedefinition_id
                         and plpc.finishingmethod_id = f.finishingmethod_id),
                      'Y') codeuniquely,
                  nvl((select max(plpc.onsiteinventorycount)
                        from productlistpercustomer plpc
                       where plpc.customer_id = x.customer_id
                         and plpc.product_id = p.product_id
                         and plpc.sizedefinition_id = s.sizedefinition_id
                         and plpc.finishingmethod_id = f.finishingmethod_id
                         and plpc.dateactive <= trunc(sysdate)
                         and plpc.dateinactive >= trunc(sysdate)),
                      nvl((select max(plpc.onsiteinventorycount)
                            from productlistpercustomer plpc
                           where plpc.customer_id = x.customer_id
                             and plpc.product_id = p.product_id
                             and (plpc.sizedefinition_id =
                                 (select s1.sizedefinition_id
                                     from sizedefinition s1
                                    where s1.code = '*'))
                             and plpc.finishingmethod_id =
                                 f.finishingmethod_id
                             and plpc.dateactive <= trunc(sysdate)
                             and plpc.dateinactive >= trunc(sysdate)),
                          'N')) onsiteinventorycount,
                  p.occupancyrelated
             from (select distinct d.customer_id,
                                   plpd.product_id,
                                   plpd.sizedefinition_id,
                                   plpd.finishingmethod_id
                     from productlistperdistribpoint plpd,
                          distributionpoint          dp,
                          department                 d
                    where d.department_id = dp.department_id
                      and plpd.distributionpoint_id = dp.distributionpoint_id
                      and d.customer_id = fp_customer_id
                   union
                   select distinct fp_customer_id,
                                   u.product_id,
                                   u.sizedefinition_id,
                                   u.finishingmethod_id
                     from uniqueitem u
                    where u.distributionpoint_id in
                          (select dp.distributionpoint_id
                             from distributionpoint dp, department d
                            where d.department_id = dp.department_id
                              and d.customer_id = fp_customer_id)) X,
                  product p,
                  sizedefinition s,
                  finishingmethod f
            where x.product_id = p.product_id
              and x.sizedefinition_id = s.sizedefinition_id
              and x.finishingmethod_id = f.finishingmethod_id) MERGE_SUBQUERY
    ON (lacustomerproduct.customer_id = merge_subquery.customer_id AND lacustomerproduct.product_id = merge_subquery.product_id AND lacustomerproduct.sizedefinition_id = merge_subquery.sizedefinition_id AND lacustomerproduct.finishingmethod_id = merge_subquery.finishingmethod_id)
    when not matched then
      insert
        (lacustomerproduct_id,
         customer_id,
         product_id,
         sizedefinition_id,
         finishingmethod_id,
         productcode,
         productcustomdesc,
         sizecode,
         finmethodcode,
         typeofmerchandise,
         sizesequence,
         codeuniquely,
         onsiteinventorycount,
         occupancyrelated)
      values
        (seq_lacustomerproduct.nextval,
         merge_subquery.customer_id,
         merge_subquery.product_id,
         merge_subquery.sizedefinition_id,
         merge_subquery.finishingmethod_id,
         merge_subquery.productcode,
         merge_subquery.productcustomdesc,
         merge_subquery.sizecode,
         merge_subquery.finmethodcode,
         merge_subquery.typeofmerchandise,
         merge_subquery.sizesequence,
         merge_subquery.codeuniquely,
         merge_subquery.onsiteinventorycount,
         merge_subquery.occupancyrelated)
    when matched then
      update
         set productcode          = merge_subquery.productcode,
             productcustomdesc    = merge_subquery.productcustomdesc,
             sizecode             = merge_subquery.sizecode,
             finmethodcode        = merge_subquery.finmethodcode,
             typeofmerchandise    = merge_subquery.typeofmerchandise,
             sizesequence         = merge_subquery.sizesequence,
             codeuniquely         = merge_subquery.codeuniquely,
             onsiteinventorycount = merge_subquery.onsiteinventorycount,
             occupancyrelated     = merge_subquery.occupancyrelated;
    commit;
  exception
    when others then
      begin
        gv_last_error_number  := SQLCODE;
        gv_last_error_message := SQLERRM;
        writeabslog;
      end;
  end;
end populate_lacustomerproduct;
/
create or replace PROCEDURE printClobOut(result IN OUT NOCOPY CLOB) IS
    xmlstr VARCHAR2(32767);
    line   VARCHAR2(2000);
  BEGIN
    xmlstr := dbms_lob.substr(result, 32767);
    LOOP
      EXIT WHEN xmlstr IS NULL;
      line := substr(xmlstr, 1, instr(xmlstr, chr(10)) - 1);
      dbms_output.put_line(line);
      xmlstr := substr(xmlstr, instr(xmlstr, chr(10)) + 1);
    END LOOP;
  END;
/
create or replace procedure print_clientdeliverynote(fp_unitcode            in businessunit.code%type,
                                                     fp_locationcode        in varchar2,
                                                     fp_clientdelnotenumber in clientdeliverynote.clientdeliverynotenumber%type,
                                                     fp_message             out nocopy abslog.message%type,
                                                     fp_idcode              in uniqueresidentialitem.primaryid%type default null) is
  --Procedure Print_ClientDeliveryNote version 1.3
  gv_clientinvoicedbasedon      systemsetting.value%type;
  lv_loglevel                   number;
  lv_plantid                    plant.plant_id%type;
  gv_proc_businessunitid        businessunit.businessunit_id%type;
  gv_invoicebusinessunitid      businessunit.businessunit_id%type;
  lv_workstationid              workstation.workstation_id%type;
  lv_workstationcode            workstation.code%type;
  lv_clientdeliverynoteid       clientdeliverynote.clientdeliverynote_id%type;
  lv_closingdate                clientdeliverynote.closingdate%type;
  gv_deliverydate               clientdeliverynote.deliverydate%type;
  lv_webserviceurl              systemsetting.value%type;
  lv_year                       number;
  lv_month                      number;
  lv_day                        number;
  lv_hour                       number;
  lv_minutes                    number;
  lv_seconds                    number;
  lv_milliseconds               number;
  lv_overalluniqueresidentialid databasesettings.overalluniquegarmentid%type;
  lv_clientdeliverynote         clientdeliverynote.clientdeliverynotenumber%type;
  lv_count_nextlocation_finish  number := 0;
  lv_databasecode               databasesettings.code%type;
  lv_customerid                 customer.customer_id%type;
  lv_next_deldate               date;
  gv_nextlocationcode           sortingimportdefinition.nextlocation%type;
  gv_nextdelivincltodaybefore   varchar2(100);
  lv_cdndeliverydate            systemsetting.value%type;
  gv_userexception exception;
  gv_systemuserid         number := 0;
  gv_outregistration_cust customerresidentialsettings.outregistration%type;
  gv_currencyid           customer.currency_id%type;
  gv_clientid             client.client_id%type;
  gv_batchid              batch.batch_id%type;
  gv_message_clob         clob;
  lv_systemuser                 systemuser.username%type;

  procedure close_cdn is
    gv_stayid_nr60_type5 stay.stay_id%type; --delayed

    procedure update_clientdeliverynote is
    begin
      --6 Update_ClientDeliveryNote
      fp_message     := 'update_clientdeliverynote';
      lv_closingdate := trunc(sysdate);
      update clientdeliverynote cd
      set    cd.closingdate = lv_closingdate, cd.timestamp = sysdate, cd.remark = '##'
      where  cd.clientdeliverynote_id = lv_clientdeliverynoteid;
    end update_clientdeliverynote;

    procedure set_to_delayed is
    begin
      --set_to_delayed
      fp_message := 'set_to_delayed';
      if gv_outregistration_cust = 0 then
        begin
          --get gv_stayid_nr60_type5
          fp_message := 'get gv_stayid_nr60_type5';
          select st.stay_id
          into   gv_stayid_nr60_type5
          from   stay st
          where  st.staytype = 5
          and    st.staynr = 60;
          /*(2) Set all unique items that are still in the laundry to "Delayed"
          If CustomerResidentialSettings.OutRegostration = 0 and
          stay of UniqueItem (CDS.UniqueItem_Link_ID) = 10 (Inscan/In laundry)*/
          update uniqueresidentialitem uri
          set    uri.laststay_id = uri.stay_id, uri.stay_id = gv_stayid_nr60_type5,
                 uri.systemuser_id = gv_systemuserid, uri.timestamp = sysdate
          where  uri.stay_id = (select s.stay_id
                                from   stay s
                                where  s.staytype = 5
                                and    s.staynr = 10)
          and    exists (select 1
                  from   client cl
                  where  cl.client_id = uri.client_id
                  and    cl.customer_id = lv_clientdeliverynoteid)
          and    exists
           (select 1
                  from   clientdelnotelinescan cdns
                  join   clientdeliverynoteline cdl
                  on     cdl.clientdeliverynoteline_id = cdns.inscanclientdelnoteline_id
                  where  cdl.clientdeliverinote_id = lv_clientdeliverynoteid
                  and    cdns.uniqueresidentialitem_link_id = uri.uniqueresidentialitem_id);
          /*(3) If CustomerResidentialSettings.OutRegistration = 0 and
          CDL.QtyCountedIn > CDL.QtyCountedOut then
          More items are counted in. These must be registered as "Delayed"
          Create ClientDeliveryNoteLineDelayed (CDD) for each item */
          for y in (select cdl.clientdeliverynoteline_id,
                           (cdl.qtycountedin - cdl.qtycountedout) difference
                    from   clientdeliverynoteline cdl
                    where  cdl.clientdeliverinote_id = lv_clientdeliverynoteid
                    and    cdl.qtycountedin > cdl.qtycountedout) loop
            begin
              for z in 1 .. y.difference loop
                begin
                  insert into clientdelnotelinedelayed
                    (clientdelnotelinedelayed_id, clientdeliverynoteline_id, deliverdline_id,
                     delivereddate, creditdate, systemuser_id, timestamp)
                  values
                    (seq_clientdelnotelinedelayed.nextval, y.clientdeliverynoteline_id, null
                     /*deliverdline_id*/, null /*delivereddate*/, null /*creditdate*/,
                     gv_systemuserid, sysdate);
                end;
              end loop; --z
            end;
          end loop; --y
        end;
      end if;
    end set_to_delayed;

    procedure update_deliveryhistory is
      lv_departmentid        department.department_id%type;
      lv_distributionpointid distributionpoint.distributionpoint_id%type;
    begin
      --4 update_deliveryhistory
      select dpr.department_id, dpr.distributionpoint_id
      into   lv_departmentid, lv_distributionpointid
      from   clientresident clr
      join   departmentroom dpr
      on     dpr.departmentroom_id = clr.departmentroom_id
      where  clr.client_id = gv_clientid;
      fp_message := 'update_deliveryhistory';
      for zz in (select *
                 from   clientdeliverynoteline cldn
                 where  cldn.clientdeliverinote_id = lv_clientdeliverynoteid) loop
        begin
          fp_message := 'update_deliveryhistory update';
          --CUSTOMER_LINK_ID, DEPARTMENT_LINK_ID, DISTRIBUTIONPOINT_LINK_ID,
          --PRODUCT_LINK_ID, SIZEDEFINITION_LINK_ID, FINISHINGMETHOD_ID,
          -- DELIVERYDATE, PROCESSBUSINESSUNIT_ID, PARENTPACKPRODUCT_LINK_ID, PACKINDICATION
          update deliveryhistory dh
          set    dh.amountdelivered = case gv_clientinvoicedbasedon
                                         when '0' then
                                          dh.amountdelivered + zz.qtyscannedout + zz.qtycountedout
                                         else
                                          dh.amountdelivered + zz.qtyscannedin + zz.qtycountedin
                                       end, dh.systemuser_id = gv_systemuserid,
                 dh.timestamp = sysdate
          where  dh.customer_link_id = lv_customerid
          and    dh.department_link_id = lv_departmentid
          and    dh.distributionpoint_link_id = lv_distributionpointid
          and    dh.product_link_id = zz.product_link_id
          and    dh.sizedefinition_link_id = zz.sizedefinition_link_id
          and    dh.finishingmethod_id = zz.finishingmethod_id
          and    dh.deliverydate = gv_deliverydate
          and    dh.processbusinessunit_id = gv_proc_businessunitid
          and    dh.parentpackproduct_link_id = zz.product_link_id
          and    dh.packindication = 1;
          if sql%rowcount = 0 then
            begin
              --does not yet exist so create it
              fp_message := 'update_deliveryhistory insert';
              insert into deliveryhistory
                (deliveryhistory_id, deliverydate, customer_link_id, department_link_id, week,
                 distributionpoint_link_id, product_link_id, sizedefinition_link_id, year,
                 finishingmethod_id, amountdelivered, currency_id, amountshortage, price,
                 amountordered, daynumber, internalprice, discount, processbusinessunit_id,
                 systemuser_id, invoicebusinessunit_id, timestamp, parentpackproduct_link_id,
                 packindication, parentproduct_link_id, amountstandard, pieceweight)
              values
                (seq_deliveryhistory.nextval, gv_deliverydate, lv_customerid, lv_departmentid,
                 getisoweek(gv_deliverydate) /*week*/, lv_distributionpointid, zz.product_link_id,
                 zz.sizedefinition_link_id, getyearofweek(gv_deliverydate) /*year*/,
                 zz.finishingmethod_id,
                 case gv_clientinvoicedbasedon when '0' then zz.qtyscannedout + zz.qtycountedout else
                  zz.qtyscannedin + zz.qtycountedin end /*amountdelivered*/, gv_currencyid, 0
                 /*amountshortage*/, 0 /*price*/, 0 /*amountordered*/,
                 getabsdaynumber(trunc(sysdate))
                 /*daynumber*/, 0
                 /*internalprice*/, 0 /*discount*/, gv_proc_businessunitid, gv_systemuserid,
                 nvl(gv_invoicebusinessunitid, gv_proc_businessunitid), sysdate, zz.product_link_id
                 /*parentpackproduct_link_id*/, 1 /*packindication*/, zz.product_link_id
                 /*parentproduct_link_id*/, 0 /*amountstandard*/, 0
                 /*pieceweight*/);
            end;
          end if;
        end;
      end loop;
    end update_deliveryhistory;
  begin
    --close_cdn
    fp_message := 'close_cdn';
    --1 we skip for now LTS does not use that (HVL), If the customer is not scanned out
    --6 Update_ClientDeliveryNote
    update_clientdeliverynote;
    --2/3 set_to_delayed
    set_to_delayed;
    --4 Update_deliveryhistory
    update_deliveryhistory;
    --5 we skip other steps
  end close_cdn;

  procedure close_batch is
    lv_open_cdn_count number;
  begin
    --close_batch
    fp_message := 'close_batch ' || to_char(gv_batchid);
    select count(1)
    into   lv_open_cdn_count
    from   clientdeliverynote cdn
    where  cdn.batch_id = gv_batchid
    and    cdn.closingdate is null;
    if lv_open_cdn_count = 0 then
      begin
        --close batch
        update batch bt
        set    bt.closingdate = trunc(sysdate), bt.status = 4, bt.closinguser_id = gv_systemuserid
        where  bt.batch_id = gv_batchid;
      end;
    end if;
  end close_batch;
begin
  --get log level
  begin
    select bu.plant_id into lv_plantid from businessunit bu where bu.code = fp_unitcode;
  exception
    when no_data_found then
      begin
        select min(p.plant_id) into lv_plantid from plant p;
      end;
  end;
  lv_loglevel := nvl(to_number(pack_sort_rs.get_systemsettting(lv_plantid, 'SORTLOGSENDTRACKINFOPWB')),
                     0);
  --get workstationid
  begin
    select min(sid.workstation_id), min(sid.nextlocation)
    into   lv_workstationid, gv_nextlocationcode
    from   sortingimportdefinition sid
    where  sid.transactiontype = 8
    and    sid.location = fp_locationcode
    and    sid.plant_id = lv_plantid;
    --get workstationcode
    select w.code into lv_workstationcode from workstation w
    where w.workstation_id = lv_workstationid;

    if lv_workstationid is null then
      begin
        fp_message := 'Unkown location ' || fp_locationcode || ' for plant id ' ||
                      to_char(lv_plantid);
        raise gv_userexception;
      end;
    end if;
  exception
    when no_data_found then
      begin
        fp_message := 'Unkown location ' || fp_locationcode || ' for plant id ' ||
                      to_char(lv_plantid);
        raise gv_userexception;
      end;
  end;
  --get system setting for clientinvoicedbasedon
  fp_message := 'Get systemsetting CLIENTINVOICEDBASEDON for plant of businessunit ' || fp_unitcode;
  select st.value
  into   gv_clientinvoicedbasedon
  from   systemsetting st
  where  st.name = 'CLIENTINVOICEDBASEDON'
  and    st.plant_id = lv_plantid;
  --get info overalluniquegarmentid
  select nvl(d.overalluniqueresidentialid, 'N'), d.code
  into   lv_overalluniqueresidentialid, lv_databasecode
  from   databasesettings d;
  --get clientdeliverynoteid based on id code (new)
  if fp_idcode is not null then
    begin
      --get from the ID code the latest outscanclientdelnote via outscanclientdelnoteline_id with the highest id
      fp_message := 'get lv_clientdeliverynoteid via fp_idcode ' || fp_idcode;
      if lv_overalluniqueresidentialid = 'Y' then
        select max(cdl.clientdeliverinote_id)
        into   lv_clientdeliverynoteid
        from   clientdelnotelinescan cds
        join   clientdeliverynoteline cdl
        on     cdl.clientdeliverynoteline_id = cds.outscanclientdelnoteline_id
        where  cds.uniqueresidentialitem_link_id in
               (select u.uniqueresidentialitem_id
                from   uniqueresidentialitem u
                where  u.primaryid = fp_idcode
                and    u.sequencenumber = 1);
      else
        select max(cdl.clientdeliverinote_id)
        into   lv_clientdeliverynoteid
        from   clientdelnotelinescan cds
        join   clientdeliverynoteline cdl
        on     cdl.clientdeliverynoteline_id = cds.outscanclientdelnoteline_id
        where  cds.uniqueresidentialitem_link_id =
               (select u.uniqueresidentialitem_id
                from   uniqueresidentialitem u, businessunit bu
                where  u.primaryid = fp_idcode
                and    u.sequencenumber = 1
                and    u.businessunit_id = bu.businessunit_id
                and    bu.code = fp_unitcode);
      end if;
      if lv_clientdeliverynoteid is not null then
        select cd.closingdate, cd.clientdeliverynotenumber, cd.customer_link_id, cd.client_link_id,
               cd.processbusinessunit_id, cd.invoicebusinessunit_id, cd.deliverydate, cd.batch_id
        into   lv_closingdate, lv_clientdeliverynote, lv_customerid, gv_clientid,
               gv_proc_businessunitid, gv_invoicebusinessunitid, gv_deliverydate, gv_batchid
        from   clientdeliverynote cd
        where  cd.clientdeliverynote_id = lv_clientdeliverynoteid;
      end if;
    end;
  end if;
  if lv_clientdeliverynoteid is null then
    --get clientdeliverynoteid based on clientdelnotenumber (old)
    begin
      lv_clientdeliverynote := fp_clientdelnotenumber;
      fp_message            := 'get lv_clientdeliverynoteid via fp_clientdelnotenumber ' ||
                               to_char(fp_clientdelnotenumber);
      if fp_unitcode is not null then
        select cdn.clientdeliverynote_id, cdn.closingdate, cdn.clientdeliverynotenumber,
               cdn.customer_link_id, cdn.client_link_id, cdn.processbusinessunit_id,
               cdn.invoicebusinessunit_id, cdn.deliverydate, cdn.batch_id, s.username
        into   lv_clientdeliverynoteid, lv_closingdate, lv_clientdeliverynote, lv_customerid,
               gv_clientid, gv_proc_businessunitid, gv_invoicebusinessunitid, gv_deliverydate,
               gv_batchid, lv_systemuser
        from   clientdeliverynote cdn, systemuser s
        where  cdn.clientdeliverynotenumber = fp_clientdelnotenumber
        and    cdn.systemuser_id = s.systemuser_id
        and    cdn.processbusinessunit_id =
               (select bu.businessunit_id from businessunit bu where bu.code = fp_unitcode);
      else
        select cdn.clientdeliverynote_id, cdn.closingdate, cdn.clientdeliverynotenumber,
               cdn.customer_link_id, cdn.client_link_id, cdn.processbusinessunit_id,
               cdn.invoicebusinessunit_id, cdn.deliverydate, cdn.batch_id, s.username
        into   lv_clientdeliverynoteid, lv_closingdate, lv_clientdeliverynote, lv_customerid,
               gv_clientid, gv_proc_businessunitid, gv_invoicebusinessunitid, gv_deliverydate,
               gv_batchid, lv_systemuser
        from   clientdeliverynote cdn, systemuser s
        where  cdn.clientdeliverynotenumber = fp_clientdelnotenumber
        and    cdn.systemuser_id = s.systemuser_id;
      end if;
    exception
      when no_data_found then
        begin
          fp_message := 'Unknown client delivery note number ' || to_char(fp_clientdelnotenumber);
          raise gv_userexception;
        end;
      when too_many_rows then
        begin
          fp_message := 'Multiple client delivery notes with the same number found ' ||
                        to_char(fp_clientdelnotenumber);
          raise gv_userexception;
        end;
    end;
  end if;
  if gv_nextlocationcode is not null then
    begin
      fp_message := 'check for gv_nextlocationcode ' || gv_nextlocationcode ||
                    ' different finishingmethods';
      select count(1)
      into   lv_count_nextlocation_finish
      from   clientdeliverynoteline cdl
      join   finishingmethod f
      on     f.finishingmethod_id = cdl.finishingmethod_id
      where  cdl.clientdeliverinote_id = lv_clientdeliverynoteid
      and    f.code <> gv_nextlocationcode;
      fp_message := 'OK';
    end;
  end if;
  if lv_count_nextlocation_finish = 0 then
    --only print when it is only HANG, or fp_nextlocationcode <> 'HANG'
    --call web service printclientdeliverynote in order to close and print the clientdeliverynote
    begin
      --get year, month, day, hour, minute, seconds
      select to_char(sysdate, 'YYYY'), to_char(sysdate, 'MM'), to_char(sysdate, 'DD'),
             to_char(sysdate, 'HH24'), to_char(sysdate, 'MI'),
             trunc(extract(second from systimestamp)) as seconds,
             mod(extract(second from systimestamp), 1) * 1000 as milliseconds
      into   lv_year, lv_month, lv_day, lv_hour, lv_minutes, lv_seconds, lv_milliseconds
      from   dual;
      if lv_databasecode = 'RFL' then
        begin
          --get system setting NEXTDELIVINCLTODAYBEFORE
          gv_nextdelivincltodaybefore := nvl(pack_sort_rs.get_systemsettting(lv_plantid,
                                                                             'NEXTDELIVINCLTODAYBEFORE'),
                                             '0');
          if to_number(gv_nextdelivincltodaybefore) > to_number(lv_hour) then
            begin
              lv_next_deldate := pack_sort_rs.get_next_deldate_tom5(trunc(sysdate - 1),
                                                                    lv_customerid, null,
                                                                    lv_databasecode);
            end;
          else
            begin
              lv_next_deldate := pack_sort_rs.get_next_deldate_tom5(trunc(sysdate), lv_customerid,
                                                                    null, lv_databasecode);
            end;
          end if;
          update clientdeliverynote cd
          set    cd.deliverydate = nvl(lv_next_deldate, cd.deliverydate), cd.timestamp = sysdate
          where  cd.clientdeliverynote_id = lv_clientdeliverynoteid
          returning cd.deliverydate into gv_deliverydate;
        end;
      else
        begin
          --get system setting CDNDELIVERYDATE
          lv_cdndeliverydate := nvl(pack_sort_rs.get_systemsettting(lv_plantid, 'CDNDELIVERYDATE'),
                                    '0');
          if to_number(lv_cdndeliverydate) > 0 then
            begin
              lv_next_deldate := pack_sort_rs.get_next_deldate_tom5(trunc(sysdate - 1),
                                                                    lv_customerid, null,
                                                                    lv_databasecode);
            end;
            update clientdeliverynote cd
            set    cd.deliverydate = nvl(lv_next_deldate, cd.deliverydate), cd.timestamp = sysdate
            where  cd.clientdeliverynote_id = lv_clientdeliverynoteid
            returning cd.deliverydate into gv_deliverydate;
          end if;
        end;
      end if;
      --get value for system setting WEBSERVICEURL
      begin
        select ss.value
        into   lv_webserviceurl
        from   systemsetting ss
        where  ss.name = 'WEBSERVICEURL'
        and    ss.plant_id = lv_plantid;
      exception
        when no_data_found then
          begin
            fp_message := 'Unknown webservice url, system setting WEBSERVICEURL for businessunit code ' ||
                          fp_unitcode || '  plant id ' || to_char(lv_plantid);
            raise gv_userexception;
          end;
      end;
      --call web service print client delivery note
      if lv_databasecode = 'RFL' then
        begin
          fp_message := 'get residentialsettings info for customer id ' || to_char(lv_customerid);
          select crs.outregistration, c.currency_id
          into   gv_outregistration_cust, gv_currencyid
          from   customerresidentialsettings crs
          join   customer c
          on     c.customer_id = crs.customer_id
          where  crs.customer_id = lv_customerid;
          if lv_closingdate is null then
            begin
              --close_cdn
              close_cdn;
            end;
          end if;
          --close_batch
          close_batch;
        end;
      end if;
      commit;
      if lv_databasecode = 'RFL' then
        gv_message_clob := printclientdelnote(fp_clientdelnotenumber, 'METBOV', 1, 'METBOV', 'http://abs01-rentex:8888/ClientDeliveryNotePrintJob');
      else
        gv_message_clob := printclientdelnote(fp_clientdelnotenumber, lv_systemuser, fp_unitcode,lv_workstationcode, lv_webserviceurl);
      end if;
      --convert clob to varchar2
      fp_message := DBMS_LOB.SUBSTR(gv_message_clob, 1000, 1);
      --check REST response
      if fp_message not like '%"OK"%' then
        begin
          pack_sort_rs.write_logging('Error Web service PRINT CLIENT DELIVERYNOTE NOT OK!! From location ' ||
                                     fp_locationcode || ' Clientdeliverynote number ' ||
                                     to_char(lv_clientdeliverynote) || ' fp_idcode ' ||
                                     nvl(fp_idcode, 'NULL'), lv_loglevel, 'PRINTCLIENTDELIVERYNOTE',
                                     lv_plantid, 3, 1);
          pack_sort_rs.write_logging(fp_message, 2, 'PRINTCLIENTDELIVERYNOTE', lv_plantid, 3, 1);
        end;
      else
        if lv_loglevel > 1 then
          begin
            pack_sort_rs.write_logging('Web service PRINT CLIENT DELIVERYNOTE OK. From location ' ||
                                       fp_locationcode || ' Clientdeliverynote number ' ||
                                       to_char(lv_clientdeliverynote) || ' fp_idcode ' ||
                                       nvl(fp_idcode, 'NULL'), lv_loglevel,
                                       'PRINTCLIENTDELIVERYNOTE', lv_plantid, 1, 1);
          end;
        end if;
      end if;
    end;
  end if; --lv_clientdeliverynoteid = 0 then
  commit;
exception
  --error handling
  when gv_userexception then
    begin
      rollback;
      pack_sort_rs.write_logging(fp_message, lv_loglevel, 'PRINTCLIENTDELIVERYNOTE', lv_plantid, 3,
                                 0);
    end;
  when no_data_found then
    begin
      rollback;
      fp_message := 'No data found ' || sqlerrm;
      pack_sort_rs.write_logging(fp_message, lv_loglevel, 'PRINTCLIENTDELIVERYNOTE', lv_plantid, 3,
                                 0);
    end;
  when too_many_rows then
    begin
      rollback;
      fp_message := 'Too many rows ' || sqlerrm;
      pack_sort_rs.write_logging(fp_message, lv_loglevel, 'PRINTCLIENTDELIVERYNOTE', lv_plantid, 3,
                                 0);
    end;
  when dup_val_on_index then
    begin
      rollback;
      fp_message := 'Dup val on index ' || sqlerrm;
      pack_sort_rs.write_logging(fp_message, lv_loglevel, 'PRINTCLIENTDELIVERYNOTE', lv_plantid, 3,
                                 0);
    end;
  when others then
    begin
      rollback;
      select utl_http.get_detailed_sqlerrm into fp_message from dual;
      fp_message := 'Error others ' || sqlerrm || ' ' || fp_message;
      pack_sort_rs.write_logging(fp_message, lv_loglevel, 'PRINTCLIENTDELIVERYNOTE', lv_plantid, 3,
                                 0);
    end;
end print_clientdeliverynote;
/
create or replace procedure ProcessCheckPointScan(transactiontp  in SORTINGIMPORTDEFINITION.TRANSACTIONTYPE%type,
                                                  IDCode         in UNIQUEITEM.PRIMARYID%type,
                                                  pool           in integer,
                                                  secondaryID    in secondaryuniqueitem.secondaryid%type,
                                                  businessunitID in BUSINESSUNIT.BUSINESSUNIT_ID%type,
                                                  uniqueitemID   in UNIQUEITEM.UNIQUEITEM_ID%type,
                                                  workstationID  in workstation.workstation_id%type,
                                                  Datep          in number,
                                                  Timep          in varchar2, --number,
                                                  systemuserid   in systemuser.systemuser_id%type,
                                                  debuglevel     in integer,
                                                  accept         out varchar2,
                                                  SQLfile        in out utl_file.file_type

                                                  ) is
  stayID              STAY.STAY_ID%type;
  statusID            STATUS.STATUS_ID%type;
  assigned            STATUS.STATUS_ID%type;
  incirc              STATUS.STATUS_ID%type;
  productID           PRODUCT.PRODUCT_ID%type;
  sizeID              SIZEDEFINITION.SIZEDEFINITION_ID%type;
  weareremploymentID  WEAREREMPLOYMENT.WEAREREMPLOYMENT_ID%type;
  customerID          CUSTOMER.CUSTOMER_ID%type;
  vissuedate          date;
  finishingmethodID   FINISHINGMETHOD.FINISHINGMETHOD_ID%type;
  distributionpointID distributionpoint.distributionpoint_id%type;
  lastdistribpointID  DISTRIBUTIONPOINT_LINK.DISTRIBUTIONPOINT_LINK_ID%type;
  vlastscandate       date;
  vlastscandatetime   timestamp;
  vpreviousstay       stay.stay_id%type;
  vwashestotal        integer;
  vyear               integer;
  vweek               integer;
  vdayno              integer;
  vcustomerowned      varchar2(1);
  routeid             route.route_id%type;
  --SQLfile                      utl_file.file_type;
  --UTLDIR                       varchar2 (20) := 'D:\output';-- please see ABS-92804 variable needs the name of an existing oracle directory
  --FPsFilename                  varchar2(25):= 'ProcessCheckPointScan.txt';
  x timestamp;
  y timestamp;
  z interval day to second;

begin
  x := current_timestamp;
  --SqlFile := UTL_FILE.FOPEN(UTLDIR, FPsFilename, 'w');
  if debuglevel > 0 then
    utl_file.put_line(SQLfile, 'CheckPointScan' || x);
  end if;
  accept            := 'Y';
  vlastscandate     := to_timestamp(to_char(Datep) || to_char(Timep),
                                    'YYYYMMDDHH24MISS');
  vlastscandatetime := to_timestamp(to_char(Datep) || to_char(Timep),
                                    'YYYYMMDDHH24MISS');
  vyear             := getyearofweek(vlastscandate); --to_number(to_char(vlastscandate,  'IYYY'));
  vweek             := getisoweek(vlastscandate); --to_char(vlastscandate,'IW');
  vdayno            := getabsdaynumber(vlastscandate);
  if pool = 2 then
    --nonpool
    begin
      select u.product_id,
             u.sizedefinition_id,
             u.finishingmethod_id,
             n.weareremployment_id,
             w.customer_id,
             f.lastissuedate,
             u.stay_id,
             u.status_id,
             u.washestotal,
             u.customerowned,
             e.distributionpoint_id
        into productID,
             sizeID,
             finishingmethodID,
             weareremploymentID,
             customerID,
             vissuedate,
             stayID,
             statusID,
             vWashesTotal,
             vcustomerowned,
             distributionpointID
        from uniqueitem          u,
             uniqueitemnonpool   n,
             uniqueitemfixedinfo f,
             weareremployment    e,
             wearer              w
       where u.uniqueitem_id = uniqueitemID and
             u.uniqueitem_id = n.uniqueitem_id and
             n.weareremployment_id = e.weareremployment_id and
             e.wearer_id = w.wearer_id and
             u.uniqueitem_id = f.uniqueitem_id;
    exception
      when no_data_found then
        accept := 'N';
        utl_file.put_line(SQLfile,
                          IDCode || ' ' || sqlcode || ' ' || sqlerrm);
    end;
  else
    --pool
    begin
      select u.relatedcustomer_id,
             u.product_id,
             u.sizedefinition_id,
             u.finishingmethod_id,
             f.lastissuedate,
             u.distributionpoint_id,
             u.stay_id,
             u.status_id,
             u.washestotal,
             u.customerowned
        into customerID,
             productID,
             sizeID,
             finishingmethodID,
             vissuedate,
             distributionpointID,
             stayID,
             statusID,
             vWashesTotal,
             vcustomerowned
        from uniqueitem u, uniqueitemfixedinfo f
       where u.uniqueitem_id = uniqueitemID and
             u.uniqueitem_id = f.uniqueitem_id;
      if customerID is null then
        if distributionpointid is not null then
          select e.customer_id
            into customerid
            from distributionpoint d, department e
           where distributionpointID = d.distributionpoint_id and
                 d.department_id = e.department_id;
        elsif lastdistribpointID is not null then
          select e.customer_link_id
            into customerid
            from distributionpoint_link d, department_link e
           where lastdistribpointID = d.distributionpoint_id and
                 d.department_link_id = e.department_link_id;
        end if;
      end if;
    exception
      when no_data_found then
        accept := 'N';
        utl_file.put_line(SQLfile,
                          IDCode || ' ' || sqlcode || ' ' || sqlerrm);
    end;
  end if;
  --stay, status
  vpreviousstay := stayID;
  select stay_id
    into StayID
    from stay
   where stay.staytype = 1 and stay.staynr = 33; --CheckPointScan
  select status_id
    into assigned
    from status
   where status.statustype = 'UI' and status.code = '30'; --assigned
  select status_id
    into incirc
    from status
   where status.statustype = 'UI' and status.code = '20'; --in circulation
  --if status is not incirc or assigned then doesn't scan
  if statusID not in (assigned, incirc) then
    accept := 'N';
    utl_file.put_line(SQLfile,
                      ' status not in circulation or assigned for IDCode:' ||
                      IDCode);
  end if;
  if accept = 'Y' then
    begin
      begin
        update uniqueitem u
           set u.lastscandate   = vlastscandatetime,
               u.prevstay_id    = vpreviousstay,
               u.stay_id        = stayID,
               u.staychangedate = vlastscandatetime,
               u.systemuser_id  = systemuserid,
               u.timestamp      = sysdate
         where u.uniqueitem_id = uniqueitemID;
        if debuglevel > 0 then
          utl_file.put_line(SQLfile, 'update uniqueitem' || uniqueitemid);
        end if;
      exception
        when others then
          accept := 'N';
          utl_file.put_line(SQLfile,
                            IDCode || ' ' || sqlcode || ' ' || sqlerrm);
      end;
      --scan record
      begin
        select u.lastoutroute_id
          into routeid
          from uniqueitemroute u
         where u.uniqueitem_id = uniqueitemID;
      exception
        when no_data_found then
          routeid := null;
      end;
      begin
        insert into scan
          (scan_id,
           businessunit_id,
           scantimestamp,
           primaryid,
           customer_link_id,
           weareremployment_link_id,
           distributionpoint_link_id,
           product_link_id,
           sizedefinition_link_id,
           stay_id,
           status_id,
           scanstation,
           issuedate,
           route_id,
           reasoncode_id,
           customerowned,
           year,
           week,
           dayno,
           qualitygrade_id,
           systemuser_id,
           timestamp,
           prevstay_id,
           transactiontype_id,
           dayslate,
           uniqueitem_link_id,
           secondaryid)
        values
          (seq_scan.nextval,
           businessunitID,
           vlastscandatetime,
           IDCode,
           customerID,
           weareremploymentID,
           distributionpointID,
           productID,
           sizeID,
           stayID,
           statusID,
           workstationID,
           vissuedate,
           routeid,
           null,
           vcustomerowned,
           vyear,
           vweek,
           vdayno,
           null,
           systemuserID,
           sysdate,
           vpreviousstay,
           transactiontp,
           0,
           uniqueitemID,
           secondaryID);
        if debuglevel > 0 then
          utl_file.put_line(SQLfile, 'insert scan' || idcode);
        end if;
      exception
        when others then
          accept := 'N';
          utl_file.put_line(SQLfile,
                            IDCode || ' ' || sqlcode || ' ' || sqlerrm);
      end;
    end; --for accept='Y'
  end if; --for accept='Y'
  y := current_timestamp;
  z := y - x;
  if debuglevel > 0 then
    utl_file.put_line(SQLfile, 'stop CheckPointScan' || z);
  end if;
  --UTL_FILE.FCLOSE(SqlFile);
end ProcessCheckPointScan;
/
create or replace procedure processDelQtysPlannedData(plant_id              Plant.plant_id%type,
                                                      plantprocess_id       PlantProcess.Plantprocess_Id%type,
                                                      systemuser_id         systemUser.systemUser_id%type) is

  lv_prevyear              varchar2(4);
  last_day_of_year        date;
  abslogprocessjob_id     number;
  abslogprocessjobpart_id number;
  rows_updated            number;
  total_del_qty           number;
  lv_plant_id             number;
begin
  abslogprocessjob_id := abslogwrite.abslogprocessjob_write(plant_id, sysdate, null, null, plantprocess_id, systemuser_id);
  abslogprocessjobpart_id := abslogwrite.abslogprocessjobpart_write(abslogprocessjob_id, 'Delivered Quantities Planned Data', systemuser_id);

  rows_updated := 0;
  total_del_qty := 0;

  select add_months(trunc(sysdate, 'YYYY') - 1, 12)
    into last_day_of_year
    from dual;

  if sysdate = last_day_of_year then
    select to_char(getyearofweek(sysdate)) --current year
      into lv_prevyear
      from dual;
  else
    select to_char(getyearofweek(trunc(sysdate, 'YYYY') - 1)) --previous year
      into lv_prevyear
      from dual;
  end if;
 lv_plant_id:=plant_id;

  for x in (select sum(PNl.Deliveredamount) delqtyprevyear,
                   PLDP.PRODUCTLISTPERDISTRIBPOINT_ID
              From PackingNote                PN,
                   PackingNoteLine            PNL,
                   ProductListPerDistribPoint PLDP,
                   BusinessUnit               BU,
                   StandardDelivery           SD,
                   DistributionPoint          DP,
                   Department                 DEP,
                   Customer                   C
             Where PNL.PackingNote_ID = PN.PackingNote_ID
               And PN.Status_ID = (select status_id
                                     from status
                                    where Code = '30' --processed
                                      and StatusType = 'PN')
               And SD.DistributionPoint_ID = PN.DistributionPoint_ID
               And SD.SequenceNumber = 1
               And DP.DistributionPoint_ID = PN.DistributionPoint_ID
               And DEP.Department_ID = DP.Department_ID
               And C.Customer_ID = DEP.Customer_ID
               And BU.BusinessUnit_ID = PN.ProcessBusinessUnit_ID
               And PLDP.DistributionPoint_ID = PN.DistributionPoint_ID
               And PLDP.Product_ID = PNL.PRODUCT_ID
               And PLDP.SizeDefinition_ID = PNL.SizeDefinition_ID
               And PLDP.FinishingMethod_ID = PNL.FinishingMethod_ID
               And sd.allowrecalcplanneddata = 1
               --and pn.origin <> 3 --including correction tickets
               And nvl(pn.freeofchargereason_id,0)=0
               And to_char(getyearofweek(PN.Deliverydate)) = lv_prevyear
               And BU.Plant_Id = lv_plant_id
             Group By PLDP.PRODUCTLISTPERDISTRIBPOINT_ID
             union all
             select 0 delqtyprevyear, PLDP.PRODUCTLISTPERDISTRIBPOINT_ID
              From ProductListPerDistribPoint PLDP,
                   StandardDelivery           SD,
                   DistributionPoint          DP,
                   Department                 DEP,
                   Customer                   C
             Where
               SD.DistributionPoint_ID = PLDP.DistributionPoint_ID
               And SD.SequenceNumber = 1
               And DEP.Department_ID = DP.Department_ID
               And C.Customer_ID = DEP.Customer_ID
               And PLDP.DistributionPoint_ID=DP.DISTRIBUTIONPOINT_ID
               and exists (select 1 from  customeractivities ca,businessunit b, product p, productgroup pg
               where ca.customer_id=c.customer_id and PLDP.Product_Id=p.product_id and p.productgroup_id=pg.productgroup_id
               and pg.activity_id=ca.activity_id and ca.processbusinessunit_id=b.businessunit_id and b.plant_id=lv_plant_id)
               And sd.allowrecalcplanneddata = 1
               And not exists( select 1 from PackingNote PN, PackingNoteLine PNL, BusinessUnit BU
                                 where BU.BusinessUnit_ID = PN.ProcessBusinessUnit_ID
                                       AND PNL.PackingNote_ID = PN.PackingNote_ID
                                       And PLDP.DistributionPoint_ID = PN.DistributionPoint_ID
                                       And PLDP.Product_ID = PNL.PRODUCT_ID
                                       And PLDP.SizeDefinition_ID = PNL.SizeDefinition_ID
                                       And PLDP.FinishingMethod_ID = PNL.FinishingMethod_ID
                                       And DP.DistributionPoint_ID = PN.DistributionPoint_ID
                                       And PN.Status_ID = (select status_id from status
                                                      where Code = '30' --processed
                                                        and StatusType = 'PN')
                                       And nvl(pn.freeofchargereason_id,0)=0
                                       And to_char(getyearofweek(PN.Deliverydate)) = lv_prevyear
                                       And BU.Plant_Id =lv_plant_id)
             )
  loop
    update productlistperdistribpoint plpdp
       set plpdp.delqtyprevyear           = x.delqtyprevyear,
           plpdp.prevyear                 = lv_prevyear,
           plpdp.planneddelqtycurrentyear = x.delqtyprevyear,
           plpdp.systemuser_id            = systemuser_id,
           plpdp.timestamp                = sysdate
     where plpdp.productlistperdistribpoint_id =
           x.productlistperdistribpoint_id;

     rows_updated := rows_updated + 1;
     total_del_qty := total_del_qty + x.delqtyprevyear;

     abslogwrite.abslogprocessjobline_write(abslogprocessjobpart_id, 1, 'PLPD_id = ' || x.productlistperdistribpoint_id || ', delqtyprevyear = ' || x.delqtyprevyear, systemuser_id);
  end loop;
  abslogwrite.abslogprocessjobline_write(abslogprocessjobpart_id, 1,
     'Total number of rows updated: ' || rows_updated || '; Total Delivered Quantity: ' || total_del_qty, systemuser_id);
  abslogwrite.abslogprocessjob_update(abslogprocessjob_id, sysdate, systemuser_id);
  commit;
end processDelQtysPlannedData;
/
create or replace procedure processfilldeliveryaverage(fp_abslog_processjobpartid in number default null,
                                                       fp_plantid                 in plant.plant_id%type default null,
                                                       fp_systemuserid            in number default 0) is
  --Version 0.5a processfilldeliveryaverage
  --Global variables
  gv_userexception exception;
  gv_message                   abslog.message%type;
  gv_plantid                   plant.plant_id%type;
  gv_deliveryaveragedeliveries number;
  gv_periodenddate             date;
  gv_statusprocessedid         status.status_id%type;
  gv_counter                   number;

  --internal procedures
  procedure write_log(fp_message in abslog.message%type, fp_priority in abslog.priority%type) is
  begin
    --write_log
    if fp_abslog_processjobpartid is null then
      begin
        begin
          abslogwrite.abslog_write(5, 'processfilldeliveryaverage', gv_plantid, fp_priority,
                                   fp_message, fp_systemuserid);
        end;
      end;
    else
      abslogwrite.abslogprocessjobline_write(fp_abslog_processjobpartid, fp_priority, fp_message,
                                             fp_systemuserid);
    end if;
  end write_log;

  procedure initialize is
  begin
    --initialize
    gv_counter := 0;
    if fp_abslog_processjobpartid is null and fp_plantid is null then
      begin
        gv_message := 'Both parameters fp_abslog_processjobpartid and fp_plantid cannot be left blank!';
        raise gv_userexception;
      end;
    end if;
    if fp_plantid is not null then
      begin
        --check if plant id exists
        gv_message := 'fp_plantid ' || fp_plantid;
        select pt.plant_id into gv_plantid from plant pt where pt.plant_id = fp_plantid;
      end;
    end if;
    if fp_abslog_processjobpartid is not null then
      begin
        --get fp_abslog_processjobpartid plant_id
        gv_message := 'fp_abslog_processjobpartid ' || fp_abslog_processjobpartid;
        select aj.plant_id
        into   gv_plantid
        from   abslogprocessjobpart alp
        join   abslogprocessjob aj
        on     aj.abslogprocessjob_id = alp.abslogprocessjob_id
        where  alp.abslogprocessjobpart_id = fp_abslog_processjobpartid;
      end;
    end if;
    --get system setting DELIVERYAVERAGEWEEKS for plant id
    gv_message := 'System setting DELIVERYAVERAGEWEEKS for plant id ' || gv_plantid;
    select to_number(st.value)
    into   gv_deliveryaveragedeliveries
    from   systemsetting st
    where  st.name = 'DELIVERYAVERAGEDELIVERIES'
    and    st.plant_id = gv_plantid;
    --get status processed packingnote
    gv_message := 'get status processed packingnote 30/PN';
    select st.status_id
    into   gv_statusprocessedid
    from   status st
    where  st.code = '30'
    and    st.statustype = 'PN';
    --set end date
    gv_periodenddate := trunc(sysdate) - 1;
  end initialize;

  procedure process is
    lv_numberofdeliveries number;
    lv_totaldelivered     number;
    lv_calculationday     number(1); --Day of week from (current date - 1 day)
    lv_periodstartdate    date;
  begin
    --get calculationday
    gv_message        := 'get calculationday';
    lv_calculationday := getabsdaynumber(sysdate - 1);
    --loop productlistperdistribpoint
    gv_message := 'loop x productlistperdistribpoint';
    for x in (select pldp.productlistperdistribpoint_id, bu.businessunit_id,
                     pldp.distributionpoint_id, pldp.product_id, pldp.sizedefinition_id,
                     pldp.finishingmethod_id, min(stl.dateactive) dateactive,
                     min(ds.frequency) frequency
              from   productlistperdistribpoint pldp
              join   standarddeliveryline stl
              on     stl.productlistperdistribpoint_id = pldp.productlistperdistribpoint_id
              join   deliveryscheme ds
              on     ds.deliveryscheme_id = stl.deliveryscheme_id
              join   distributionpoint dip
              on     dip.distributionpoint_id = pldp.distributionpoint_id
              join   department t
              on     t.department_id = dip.department_id
              join   product p
              on     p.product_id = pldp.product_id
              join   productgroup pg
              on     pg.productgroup_id = p.productgroup_id
              join   customeractivities ca
              on     ca.customer_id = t.customer_id
              join   businessunit bu
              on     bu.businessunit_id = ca.processbusinessunit_id
              join   customerdeliveryday cdd
              on     cdd.customer_id = t.customer_id
              where  bu.plant_id = gv_plantid
              and    ca.activity_id = pg.activity_id
              and    cdd.typeofmerchadise = p.typeofmerchandise
              and    cdd.day_id = lv_calculationday
              and    stl.dateactive <= gv_periodenddate
              and    stl.dateinactive > gv_periodenddate
              and    ds.frequency > 0 --is always true, just extra check to be sure
              and    exists (select 1
                      from   standarddeliveryamount sta
                      where  sta.standarddeliveryline_id = stl.standarddeliveryline_id
                      and    sta.day_id = lv_calculationday)
              group  by pldp.productlistperdistribpoint_id, bu.businessunit_id,
                        pldp.distributionpoint_id, pldp.product_id, pldp.sizedefinition_id,
                        pldp.finishingmethod_id) loop
      begin
        --reset variables
        lv_numberofdeliveries := 0;
        lv_totaldelivered     := 0;
        lv_periodstartdate    := gv_periodenddate -
                                 round(gv_deliveryaveragedeliveries * x.frequency * 7) + 1;
        if x.dateactive < lv_periodstartdate then
          begin
            lv_numberofdeliveries := gv_deliveryaveragedeliveries;
          end;
        else
          begin
            lv_periodstartdate    := x.dateactive;
            lv_numberofdeliveries := round((gv_periodenddate - x.dateactive + 1) /
                                           (7 * x.frequency));
          end;
        end if;
        --loop y values
        gv_message := 'loop y packingnote/line';
        select sum(pnl.deliveredamount) deliveredamount
        into   lv_totaldelivered
        from   packingnote pn
        join   packingnoteline pnl
        on     pnl.packingnote_id = pn.packingnote_id
        where  pn.status_id = (select st.status_id
                               from   status st
                               where  st.statustype = 'PN'
                               and    st.code = '30')
        and    pn.daynumber = lv_calculationday
        and    pn.processbusinessunit_id = x.businessunit_id
        and    pn.distributionpoint_id = x.distributionpoint_id
        and    pn.deliverydate between lv_periodstartdate and gv_periodenddate
        and    pnl.product_id = x.product_id
        and    pnl.sizedefinition_id = x.sizedefinition_id
        and    pnl.finishingmethod_id = x.finishingmethod_id;
        if lv_totaldelivered > 0 and lv_numberofdeliveries > 0 then
          begin
            --count
            gv_counter := gv_counter + 1;
            --update deliveryaverage
            gv_message := 'update deliveryaverage';
            update deliveryaverage da
            set    da.deliveries = lv_numberofdeliveries, da.totaldelivered = lv_totaldelivered,
                   da.average = round(lv_totaldelivered / lv_numberofdeliveries),
                   da.systemuser_id = fp_systemuserid, da.timestamp = sysdate
            where  da.productlistperdistribpoint_id = x.productlistperdistribpoint_id
            and    da.plant_id = gv_plantid
            and    da.day_id = lv_calculationday;
            if sql%rowcount = 0 then
              begin
                --insert into deliveryaverage
                gv_message := 'insert into deliveryaverage';
                insert into deliveryaverage
                  (deliveryaverage_id, productlistperdistribpoint_id, day_id, plant_id,
                   totaldelivered, deliveries, average, systemuser_id, timestamp)
                values
                  (seq_deliveryaverage.nextval, x.productlistperdistribpoint_id, lv_calculationday,
                   gv_plantid, lv_totaldelivered, lv_numberofdeliveries,
                   round(lv_totaldelivered / lv_numberofdeliveries), fp_systemuserid, sysdate);
              end;
            end if; --exists DA
          end;
        end if; --lv_totaldelivered > 0 and lv_numberofdeliveries > 0
      end;
    end loop; --x
  end process;

  procedure finalize is
  begin
    --finalize
    commit;
    write_log('Ran ok, ' || to_char(gv_counter) || ' deliveryaverage records procesed', 1);
  end finalize;
begin
  --ProcessFillDeliveryAverage
  --initialize
  initialize;
  --process
  process;
  --finalize
  finalize;
exception
  --Exception handling
  when gv_userexception then
    begin
      rollback;
      write_log(gv_message, 3);
    end;
  when no_data_found then
    begin
      rollback;
      write_log('Error, No Data Found ' || gv_message, 3);
    end;
  when others then
    begin
      rollback;
      write_log('Error ' || sqlerrm || ' ' || gv_message, 3);
    end;
end processfilldeliveryaverage;
/
create or replace procedure ProcessRepairScan(transactiontp  in SORTINGIMPORTDEFINITION.TRANSACTIONTYPE%type,
                                              IDCode         in UNIQUEITEM.PRIMARYID%type,
                                              pool           in integer,
                                              secondaryID    in secondaryuniqueitem.secondaryid%type,
                                              businessunitID in BUSINESSUNIT.BUSINESSUNIT_ID%type,
                                              uniqueitemID   in UNIQUEITEM.UNIQUEITEM_ID%type,
                                              workstationID  in workstation.workstation_id%type,
                                              Datep          in number,
                                              Timep          in varchar2, --number,
                                              RepairsDone    in varchar2,
                                              systemuserid   in systemuser.systemuser_id%type,
                                              debuglevel     in integer,
                                              accept         out varchar2,
                                              SQLfile        in out utl_file.file_type) is
  statusID            status.status_id%type;
  assigned            STATUS.STATUS_ID%type;
  incirc              STATUS.STATUS_ID%type;
  stayID              STAY.STAY_ID%type;
  vpreviousstay       STAY.STAY_ID%type;
  stayrepair          STAY.STAY_ID%type;
  productID           PRODUCT.PRODUCT_ID%type;
  sizeID              SIZEDEFINITION.SIZEDEFINITION_ID%type;
  finishingmethodID   FINISHINGMETHOD.FINISHINGMETHOD_ID%type;
  vlastscandate       date;
  vlastscandatetime   timestamp;
  weareremploymentID  WEAREREMPLOYMENT.WEAREREMPLOYMENT_ID%type;
  customerID          CUSTOMER.CUSTOMER_ID%type;
  distributionpointID distributionpoint.distributionpoint_id%type;
  lastdistribpointID  distributionpoint_link.distributionpoint_link_id%type;
  vrepairstotal       integer;
  vrepairsthisissue   integer;
  vyear               integer;
  vweek               integer;
  vdayno              integer;
  auxstring           varchar2(7);
  repairstring        varchar2(7);
  vchargerepairs      customer.chargerepairs%type;
  repairtypeid        repairtype.repairtype_id%type;
  vdefaulttime        repairtype.defaulttime%type;
  cnt                 integer;
  i                   integer;
  vcustomerowned      varchar2(1);
  qualitygradeID      qualitygrade.qualitygrade_id%type;
  --reasoncodeID                  reasoncode.reasoncode_id%type;
  vlastissuedate        date;
  lastinroute           route.route_id%type;
  vdayslate             integer;
  primaryID             uniqueitem.primaryid%type;
  vpool                 repairhistory.pool%type;
  invoicebusinessunitID businessunit.businessunit_id%type;
  deliverypointID       deliverypoint.deliverypoint_id%type;
  lockerID              locker.locker_id%type;
  garmentdispenserID    garmentdispenser.garmentdispenser_id%type;
  vtypeofmerch          product.typeofmerchandise%type;
  routestopIN           routestop.routestop_id%type;
  lastdatein            date;
  gv_maxrepairsproduct  number;
  gv_maxrepairsplpc     number;
  gv_maxrepflagattached number;
  gv_maxrepairsflagid   number;
  --SQLfile                      utl_file.file_type;
  --UTLDIR                       varchar2 (20) := 'D:\output';-- please see ABS-92804 variable needs the name of an existing oracle directory
  --FPsFilename                  varchar2(20):= 'ProcessRepair.txt';
  x timestamp;
  y timestamp;
  z interval day to second;

begin
  x := current_timestamp;
  --SqlFile := UTL_FILE.FOPEN(UTLDIR, FPsFilename, 'w');
  if debuglevel > 0 then
    utl_file.put_line(SQLfile, 'Repair Scan' || x);
  end if;
  accept            := 'Y';
  vlastscandate     := to_timestamp(to_char(Datep) || to_char(Timep),
                                    'YYYYMMDDHH24MISS');
  vlastscandatetime := to_timestamp(to_char(Datep) || to_char(Timep),
                                    'YYYYMMDDHH24MISS');
  vyear             := getyearofweek(vlastscandate); --to_number(to_char(vlastscandate,  'IYYY'));
  vweek             := getisoweek(vlastscandate); --to_char(vlastscandate,'IW');
  vdayno            := getabsdaynumber(vlastscandate);
  if pool = 2 then
    --nonpool
    begin
      vpool := 'N';
      select u.primaryid,
             u.product_id,
             u.sizedefinition_id,
             u.finishingmethod_id,
             n.weareremployment_id,
             w.customer_id,
             u.stay_id,
             u.status_id,
             e.distributionpoint_id,
             f.lastissuedate,
             u.repairstotal,
             u.customerowned,
             f.qualitygrade_id, --f.reasoncode_id,
             n.repairsthisissue,
             e.deliverypoint_id,
             e.garmentdispenser_id,
             e.locker_id
        into primaryid,
             productID,
             sizeID,
             finishingmethodID,
             weareremploymentID,
             customerID,
             stayID,
             statusID,
             distributionpointID,
             vlastissuedate,
             vRepairsTotal,
             vcustomerowned,
             qualitygradeID, --reasoncodeID,
             vrepairsthisissue,
             deliverypointID,
             garmentdispenserID,
             lockerID
        from uniqueitem          u,
             uniqueitemnonpool   n,
             uniqueitemfixedinfo f,
             weareremployment    e,
             wearer              w
       where u.uniqueitem_id = uniqueitemID
         and u.uniqueitem_id = n.uniqueitem_id
         and n.weareremployment_id = e.weareremployment_id
         and e.wearer_id = w.wearer_id
         and u.uniqueitem_id = f.uniqueitem_id;
    exception
      when no_data_found then
        accept := 'N';
        utl_file.put_line(SQLfile,
                          IDCode || ' ' || sqlcode || ' ' || sqlerrm);
    end;
  else
    --pool
    begin
      vpool := 'Y';
      select u.primaryid,
             u.relatedcustomer_id,
             u.product_id,
             u.sizedefinition_id,
             u.finishingmethod_id,
             u.distributionpoint_id,
             u.lastdistributionpoint_link_id,
             u.stay_id,
             u.status_id,
             u.repairstotal,
             u.customerowned,
             f.qualitygrade_id,
             f.lastissuedate --f.reasoncode_id
        into primaryid,
             customerID,
             productID,
             sizeID,
             finishingmethodID,
             distributionpointID,
             lastdistribpointID,
             stayID,
             statusID,
             vRepairsTotal,
             vcustomerowned,
             qualitygradeID,
             vlastissuedate --reasoncodeID
        from uniqueitem u, uniqueitemfixedinfo f
       where u.uniqueitem_id = uniqueitemID
         and u.uniqueitem_id = f.uniqueitem_id;
      if customerID is null then
        if distributionpointid is not null then
          select e.customer_id
            into customerid
            from distributionpoint d, department e
           where distributionpointID = d.distributionpoint_id
             and d.department_id = e.department_id;
        elsif lastdistribpointID is not null then
          select e.customer_link_id
            into customerid
            from distributionpoint_link d, department_link e
           where lastdistribpointID = d.distributionpoint_id
             and d.department_link_id = e.department_link_id;
        end if;
      end if;
    exception
      when no_data_found then
        accept := 'N';
        utl_file.put_line(SQLfile,
                          IDCODE || ' ' || sqlcode || ' ' || sqlerrm);
    end;
  end if;
  --stay,status
  vpreviousstay := stayID;
  select s.status_id
    into assigned
    from status s
   where s.statustype = 'UI'
     and s.code = '30';
  select s.status_id
    into incirc
    from status s
   where s.statustype = 'UI'
     and s.code = '20';
  if statusID not in (assigned, incirc) then
    accept := 'N';
    utl_file.put_line(SQLfile, IDCODE || 'status not assigned or incirc');
  end if;
  select stay.stay_id
    into stayrepair
    from stay
   where stay.staytype = 1
     and stay.staynr = 32; --repair stay
  if accept = 'Y' then
    begin
      If customerID is not null then
        select customer.chargerepairs
          into vchargerepairs
          from customer
         where customer.customer_id = customerid;
      else
        vchargerepairs := 0;
      end if;
      if vchargerepairs = 0 then
        vchargerepairs := 1; --freeofcharge for field Status in RepairHistory table
      else
        vchargerepairs := 0; --charge field Status In RepairHistory;
      end if;
      if customerID is not null then
        begin
          select CUSTOMERACTIVITIES.INVOICEBUSINESSUNIT_ID
            into invoicebusinessunitID
            from CUSTOMERACTIVITIES, PRODUCTGROUP, PRODUCT
           where CUSTOMERACTIVITIES.CUSTOMER_ID = customerID
             and CUSTOMERACTIVITIES.ACTIVITY_ID = PRODUCTGROUP.ACTIVITY_ID
             and PRODUCT.PRODUCTGROUP_ID = PRODUCTGROUP.PRODUCTGROUP_ID
             and PRODUCT.PRODUCT_ID = productID;
        exception
          when others then
            null;
            -- utl_file.put_line(SQLfile,IDCODE||' '||sqlcode||' '||sqlerrm);
        end;
      end if;
      if RepairsDone is null or RepairsDone = ' ' then
        cnt := 0;
      else
        cnt := Length(RepairsDone);
      end if;
      if cnt > 7 then
        repairstring := substr(RepairsDone, 1, 7);
      else
        repairstring := RepairsDone;
      end if;
      if cnt > 0 then
        for i in 1 .. cnt loop
          auxString := substr(repairstring, i, 1);
          if auxstring <> ' ' and auxstring <> '0' then
            begin
              vrepairstotal := vrepairstotal + 1;
              if pool = 2 then
                vrepairsthisissue := vrepairsthisissue + 1;
              end if;
              select r.repairtype_id, r.defaulttime
                into repairtypeid, vdefaulttime
                from repairtype r
               where r.defaultfor = auxstring;
              insert into repairhistory
                (repairhistory_id,
                 supplier_id,
                 currency_id,
                 product_link_id,
                 distributionpoint_link_id,
                 weareremployment_link_id,
                 customer_link_id,
                 repairtype_id,
                 uniqueitem_link_id,
                 businessunit_id,
                 repairdate,
                 minutes,
                 year,
                 week,
                 day,
                 pool,
                 unitprice,
                 priceperminute,
                 systemuser_id,
                 timestamp,
                 status,
                 invoicebusinessunit_id,
                 invoiceheader_id,
                 primaryid,
                 amount)
              values
                (seq_repairhistory.nextval,
                 null,
                 null,
                 productid,
                 distributionpointid,
                 weareremploymentid,
                 customerid,
                 repairtypeid,
                 uniqueitemid,
                 businessunitid,
                 vlastscandate,
                 vdefaulttime,
                 vyear,
                 vweek,
                 vdayno,
                 vpool,
                 null,
                 null,
                 systemuserid,
                 sysdate,
                 vchargerepairs,
                 invoicebusinessunitID,
                 null,
                 primaryid,
                 0);
            exception
              when no_data_found then
                null;
              when others then
                accept := 'N';
                --utl_file.put_line(SQLfile,'NOT inserted into repairhistory'||uniqueitemID);
                utl_file.put_line(SQLfile,
                                  IDCODE || ' ' || sqlcode || ' ' ||
                                  sqlerrm);
            end;
          end if;
        end loop;
      end if;
      --only starting with 7.26 - according with order 874
      if cnt = 0 and accept = 'Y' then
        for vCursor in (select a.repairtype_id, a.defaulttime
                          from repairtype a
                         where a.autoaddonrepairscan = 'Y'
                           and a.active = 'Y') loop
          begin
            vrepairstotal := vrepairstotal + 1;
            if pool = 2 then
              vrepairsthisissue := vrepairsthisissue + 1;
            end if; ---comment here end if
            insert into repairhistory
              (repairhistory_id,
               supplier_id,
               currency_id,
               product_link_id,
               distributionpoint_link_id,
               weareremployment_link_id,
               customer_link_id,
               repairtype_id,
               uniqueitem_link_id,
               businessunit_id,
               repairdate,
               minutes,
               year,
               week,
               day,
               pool,
               unitprice,
               priceperminute,
               systemuser_id,
               timestamp,
               status,
               invoicebusinessunit_id,
               invoiceheader_id,
               primaryid,
               amount)
            values
              (seq_repairhistory.nextval,
               null,
               null,
               productid,
               distributionpointid,
               weareremploymentid,
               customerid,
               vCursor.repairtype_id,
               uniqueitemid,
               businessunitid,
               vlastscandate,
               vCursor.defaulttime,
               vyear,
               vweek,
               vdayno,
               vpool,
               null,
               null,
               systemuserid,
               sysdate,
               vchargerepairs,
               invoicebusinessunitID,
               null,
               primaryid,
               0);
          exception
            when others then
              accept := 'N';
              -- utl_file.put_line(SQLfile,'NOT inserted into repairhistory'||uniqueitemID);
              utl_file.put_line(SQLfile,
                                IDCODE || ' ' || sqlcode || ' ' || sqlerrm);
              ---- end if;-
          end;
        end loop;
      end if;
      --update uniqueitem
      if accept = 'Y' then
        begin
          update uniqueitem u
             set u.lastscandate   = vlastscandatetime,
                 u.repairstotal   = vrepairstotal,
                 u.prevstay_id    = vpreviousstay,
                 u.stay_id        = stayrepair,
                 u.staychangedate = vlastscandatetime,
                 u.systemuser_id  = systemuserid,
                 u.timestamp      = sysdate
           where u.uniqueitem_id = uniqueitemID;
          if debuglevel > 0 then
            utl_file.put_line(SQLfile,
                              'update uniqueitem' || uniqueitemID ||
                              ' Repairstotal' || vrepairstotal);
          end if;
        exception
          when others then
            begin
              accept := 'N';
              --utl_file.put_line(SQLfile,'NOT update uniqueitem'||uniqueitemID);
              utl_file.put_line(SQLfile,
                                IDCODE || ' ' || sqlcode || ' ' || sqlerrm);
            end;
        end;
      end if;
      --update uniqueitemnonpool
      if pool = 2 and accept = 'Y' then
        begin
          update uniqueitemnonpool n
             set n.repairsthisissue = vrepairsthisissue
           where n.uniqueitem_id = uniqueitemID;
          if debuglevel > 0 then
            utl_file.put_line(SQLfile,
                              'update uniqueitemnonpool' || uniqueitemID ||
                              ' Repairs this issue' || vrepairsthisissue);
          end if;
        exception
          when others then
            accept := 'N';
            --utl_file.put_line(SQLfile,'NOT update uniqueitemnonpool'||uniqueitemID);
            utl_file.put_line(SQLfile,
                              IDCODE || ' ' || sqlcode || ' ' || sqlerrm);
        end;
      end if;
      ----scan record
      if accept = 'Y' then
        vdayslate := 0;
        if deliverypointID is null and pool = 2 then
          if lockerID is not null then
            select l.deliverypoint_id
              into DeliveryPointID
              from locker l
             where l.locker_id = lockerID;
          elsif garmentdispenserID is not null then
            select g.deliverypoint_id
              into DeliveryPointID
              from garmentdispenser g
             where g.garmentdispenser_id = garmentdispenserID;
          end if;
        end if;
        select p.typeofmerchandise
          into vtypeofmerch
          from product p
         where p.product_id = productID;
        if customerID is not null and pool = 2 then
          Pack_Sort.getLastInRoute(CustomerID,
                                   vlastscandate,
                                   deliverypointID,
                                   vtypeofmerch,
                                   lastinroute,
                                   routestopIN,
                                   lastdatein);
        end if;
        begin
          insert into scan
            (scan_id,
             businessunit_id,
             scantimestamp,
             primaryid,
             customer_link_id,
             weareremployment_link_id,
             distributionpoint_link_id,
             product_link_id,
             sizedefinition_link_id,
             stay_id,
             status_id,
             scanstation,
             issuedate,
             route_id,
             reasoncode_id,
             customerowned,
             year,
             week,
             dayno,
             qualitygrade_id,
             systemuser_id,
             timestamp,
             prevstay_id,
             transactiontype_id,
             dayslate,
             uniqueitem_link_id,
             secondaryid)
          values
            (seq_scan.nextval,
             businessunitID,
             vlastscandate,
             IDCode,
             customerID,
             weareremploymentID,
             distributionpointID,
             productID,
             sizeID,
             stayrepair,
             statusID,
             workstationID,
             vlastissuedate,
             lastinroute,
             null,
             vcustomerowned,
             vyear,
             vweek,
             vdayno,
             qualitygradeID,
             systemuserID,
             sysdate,
             vpreviousstay,
             transactiontp,
             vdayslate,
             uniqueitemID,
             secondaryID);
          if debuglevel > 0 then
            utl_file.put_line(SQLfile, 'insert scan' || IDcode);
          end if;
        exception
          when others then
            begin
              accept := 'N';
              --utl_file.put_line(SQLfile,'NOT insert scan'||uniqueitemID);
              --dbms_output.put_line(sqlerrm);
              utl_file.put_line(SQLfile,
                                IDCODE || ' ' || sqlcode || ' ' || sqlerrm);
            end;
        end;
      end if;

      -- if the max number of repairs has been exceeded, add flag
      begin
        select af.flag_id
          into gv_maxrepairsflagid
          from automaticflag af
         where af.event = 'Maximum Number of Repairs';

        select count(*)
          into gv_maxrepflagattached
          from uniqueitemflag uif
         where uif.uniqueitem_id = uniqueitemID
           and uif.flag_id = gv_maxrepairsflagid;

        if (gv_maxrepflagattached = 0 and gv_maxrepairsflagid is not null) then

          if pool = 2 then
            select nvl(max(plpc.maximumnumberofrepairs), 0),
                   nvl(max(p.maximumnumberofrepairs), 0)
              into gv_maxrepairsplpc, gv_maxrepairsproduct
              from productlistpercustomer plpc,
                   uniqueitemnonpool      uinp,
                   wearerinventory        wi,
                   weareremployment       we,
                   wearer                 w,
                   product                p
             where uinp.uniqueitem_id = uniqueitemID
               and wi.product_id = plpc.product_id
               and (wi.sizedefinition_id = plpc.sizedefinition_id or
                   plpc.sizedefinition_id =
                   (select sd.sizedefinition_id
                       from sizedefinition sd
                      where sd.code = '*'))
               and wi.finishingmethod_id = plpc.finishingmethod_id
               and uinp.wearerinventory_id = wi.wearerinventory_id
               and wi.weareremployment_id = we.weareremployment_id
               and we.wearer_id = w.wearer_id
               and w.customer_id = plpc.customer_id
               and wi.product_id = p.product_id
               and plpc.dateactive < vlastscandatetime
               and plpc.dateinactive > vlastscandatetime;

            if (gv_maxrepairsplpc > 0 and vrepairstotal > gv_maxrepairsplpc) or
               (gv_maxrepairsproduct > 0 and
               vrepairstotal > gv_maxrepairsproduct and
               gv_maxrepairsplpc = 0) then

              insert into uniqueitemflag
                (uniqueitem_id,
                 flag_id,
                 startdate,
                 systemuser_id,
                 timestamp)
              values
                (uniqueitemID,
                 gv_maxrepairsflagid,
                 sysdate,
                 systemuserid,
                 sysdate);
            end if;

          else
            select nvl(max(plpc.maximumnumberofrepairs), 0),
                   nvl(max(p.maximumnumberofrepairs), 0)
              into gv_maxrepairsplpc, gv_maxrepairsproduct
              from productlistpercustomer plpc,
                   distributionpoint      dp,
                   department             d,
                   product                p
             where p.product_id = plpc.product_id
               and (plpc.sizedefinition_id = sizeID or
                   plpc.sizedefinition_id =
                   (select sd.sizedefinition_id
                       from sizedefinition sd
                      where sd.code = '*'))
               and plpc.finishingmethod_id = finishingmethodID
               and dp.distributionpoint_id = distributionpointID
               and dp.department_id = d.department_id
               and d.customer_id = plpc.customer_id
               and p.product_id = productID
               and plpc.dateactive < vlastscandatetime
               and plpc.dateinactive > vlastscandatetime;

            if (gv_maxrepairsplpc > 0 and vrepairstotal > gv_maxrepairsplpc) or
               (gv_maxrepairsproduct > 0 and
               vrepairstotal > gv_maxrepairsproduct and
               gv_maxrepairsplpc = 0) then
              insert into uniqueitemflag
                (uniqueitem_id,
                 flag_id,
                 startdate,
                 systemuser_id,
                 timestamp)
              values
                (uniqueitemID,
                 gv_maxrepairsflagid,
                 sysdate,
                 systemuserid,
                 sysdate);
            end if;

          end if;
        end if;
      exception
        when others then
          accept := 'N';
          abslogwrite.abslog_write(5,
                                   5,
                                   null,
                                   3,
                                   sqlcode || ' ' || sqlerrm);
      end;
      ------------TODO--------------------------------------------------------------------------------------
      ---remove flags
      --begin
      ---there are flags that should be removed on repairs
      --end;
    end;
  end if;
  if accept = 'Y' then
    commit;
  else
    rollback;
  end if;

  y := current_timestamp;
  z := y - x;
  --if debuglevel>0 then
  --utl_file.put_line(SQLfile,'stop Repair'||z);
  --end if;
  --UTL_FILE.FCLOSE(SqlFile);
  --exception when others then accept:='N';
end ProcessRepairScan;
/
create or replace procedure ProcessSortScan(transactiontp  in SORTINGIMPORTDEFINITION.TRANSACTIONTYPE%type,
                                            IDCode         in UNIQUEITEM.PRIMARYID%type,
                                            pool           in integer,
                                            secondaryID    in secondaryuniqueitem.secondaryid%type,
                                            businessunitID in BUSINESSUNIT.BUSINESSUNIT_ID%type,
                                            uniqueitemID   in UNIQUEITEM.UNIQUEITEM_ID%type,
                                            workstationID  in workstation.workstation_id%type,
                                            Datep          in number,
                                            Timep          in varchar2, --number,
                                            systemuserid   in systemuser.systemuser_id%type,
                                            debuglevel     in integer,
                                            accept         out varchar2,
                                            SQLfile        in out utl_file.file_type) is
  stayID              STAY.STAY_ID%type;
  statusID            STATUS.STATUS_ID%type;
  assigned            STATUS.STATUS_ID%type;
  incirc              STATUS.STATUS_ID%type;
  productID           PRODUCT.PRODUCT_ID%type;
  sizeID              SIZEDEFINITION.SIZEDEFINITION_ID%type;
  weareremploymentID  WEAREREMPLOYMENT.WEAREREMPLOYMENT_ID%type;
  customerID          CUSTOMER.CUSTOMER_ID%type;
  vissuedate          date;
  finishingmethodID   FINISHINGMETHOD.FINISHINGMETHOD_ID%type;
  distributionpointID distributionpoint.distributionpoint_id%type;
  lastdistribpointID  distributionpoint_link.distributionpoint_link_id%type;
  vlastscandate       date;
  vlastscandatetime   timestamp;
  vpreviousstay       stay.stay_id%type;
  vwashestotal        integer;
  vyear               integer;
  vweek               integer;
  vdayno              integer;
  vcustomerowned      varchar2(1);
  routeid             route.route_id%type;
  --SQLfile                      utl_file.file_type;
  --UTLDIR                       varchar2 (20) := 'D:\output';-- please see ABS-92804 variable needs the name of an existing oracle directory
  --FPsFilename                  varchar2(25):= 'ProcessSortScan.txt';
  x timestamp;
  y timestamp;
  z interval day to second;
begin
  x := current_timestamp;
  -- SqlFile := UTL_FILE.FOPEN(UTLDIR, FPsFilename, 'w');
  if debuglevel > 0 then
    utl_file.put_line(SQLfile, 'Sort scan' || x);
  end if;
  accept            := 'Y';
  vlastscandate     := to_timestamp(to_char(Datep) || to_char(Timep),
                                    'YYYYMMDDHH24MISS');
  vlastscandatetime := to_timestamp(to_char(Datep) || to_char(Timep),
                                    'YYYYMMDDHH24MISS');
  vyear             := getyearofweek(vlastscandate); --to_number(to_char(vlastscandate,  'IYYY'));
  vweek             := getisoweek(vlastscandate); --to_char(vlastscandate,'IW');
  vdayno            := getabsdaynumber(vlastscandate);
  if pool = 2 then
    --nonpool
    begin
      select u.product_id,
             u.sizedefinition_id,
             u.finishingmethod_id,
             n.weareremployment_id,
             w.customer_id,
             f.lastissuedate,
             u.stay_id,
             u.status_id,
             u.washestotal,
             u.customerowned,
             e.distributionpoint_id --, --f.qualitygrade_id,
        into productID,
             sizeID,
             finishingmethodID,
             weareremploymentID,
             customerID,
             vissuedate,
             stayID,
             statusID,
             vWashesTotal,
             vcustomerowned,
             distributionpointID --, --qualitygradeID,
        from uniqueitem          u,
             uniqueitemnonpool   n,
             uniqueitemfixedinfo f,
             weareremployment    e,
             wearer              w
       where u.uniqueitem_id = uniqueitemID and
             u.uniqueitem_id = n.uniqueitem_id and
             n.weareremployment_id = e.weareremployment_id and
             e.wearer_id = w.wearer_id and
             u.uniqueitem_id = f.uniqueitem_id;
    exception
      when no_data_found then
        accept := 'N';
        utl_file.put_line(SQLfile,
                          IDCode || ' ' || sqlcode || ' ' || sqlerrm);
    end;
  else
    --pool
    begin
      select u.relatedcustomer_id,
             u.product_id,
             u.sizedefinition_id,
             u.finishingmethod_id,
             f.lastissuedate,
             u.distributionpoint_id,
             u.stay_id,
             u.status_id,
             u.washestotal,
             u.customerowned --, --f.qualitygrade_id,
        into customerID,
             productID,
             sizeID,
             finishingmethodID,
             vissuedate,
             distributionpointID,
             stayID,
             statusID,
             vWashesTotal,
             vcustomerowned --, --qualitygradeID,
        from uniqueitem u, uniqueitemfixedinfo f
       where u.uniqueitem_id = uniqueitemID and
             u.uniqueitem_id = f.uniqueitem_id;
      if customerID is null then
        if distributionpointid is not null then
          select e.customer_id
            into customerid
            from distributionpoint d, department e
           where distributionpointID = d.distributionpoint_id and
                 d.department_id = e.department_id;
        elsif lastdistribpointID is not null then
          select e.customer_link_id
            into customerid
            from distributionpoint_link d, department_link e
           where lastdistribpointID = d.distributionpoint_id and
                 d.department_link_id = e.department_link_id;
        end if;
      end if;
    exception
      when no_data_found then
        accept := 'N';
        utl_file.put_line(SQLfile,
                          IDCode || ' ' || sqlcode || ' ' || sqlerrm);
    end;
  end if;
  --stay, status
  vpreviousstay := stayID;
  select stay_id
    into StayID
    from stay
   where stay.staytype = 1 and stay.staynr = 34; --Sorted
  select status_id
    into assigned
    from status
   where status.statustype = 'UI' and status.code = '30'; --assigned
  select status_id
    into incirc
    from status
   where status.statustype = 'UI' and status.code = '20'; --in circulation
  --if status is not incirc or assigned then doesn't scan
  if statusID not in (assigned, incirc) then
    accept := 'N';
    utl_file.put_line(SQLfile,
                      IDCode || ' ' ||
                      ' Status not in circulation or assigned for IDcode ');
  end if;
  if accept = 'Y' then
    begin
      begin
        update uniqueitem u
           set u.lastscandate   = vlastscandatetime,
               u.prevstay_id    = vpreviousstay,
               u.stay_id        = stayID,
               u.staychangedate = vlastscandatetime,
               u.systemuser_id  = systemuserid,
               u.timestamp      = sysdate
         where u.uniqueitem_id = uniqueitemID;
        if debuglevel > 0 then
          utl_file.put_line(SQLfile, 'update uniqueitem' || uniqueitemid);
        end if;
      exception
        when others then
          accept := 'N';
          utl_file.put_line(SQLfile,
                            IDCode || ' ' || sqlcode || ' ' || sqlerrm);
      end;
      --scan record
      begin
        select u.lastoutroute_id
          into routeid
          from uniqueitemroute u
         where u.uniqueitem_id = uniqueitemID;
      exception
        when no_data_found then
          routeid := null;
      end;
      begin
        insert into scan
          (scan_id,
           businessunit_id,
           scantimestamp,
           primaryid,
           customer_link_id,
           weareremployment_link_id,
           distributionpoint_link_id,
           product_link_id,
           sizedefinition_link_id,
           stay_id,
           status_id,
           scanstation,
           issuedate,
           route_id,
           reasoncode_id,
           customerowned,
           year,
           week,
           dayno,
           qualitygrade_id,
           systemuser_id,
           timestamp,
           prevstay_id,
           transactiontype_id,
           dayslate,
           uniqueitem_link_id,
           secondaryid)
        values
          (seq_scan.nextval,
           businessunitID,
           vlastscandate,
           IDCode,
           customerID,
           weareremploymentID,
           distributionpointID,
           productID,
           sizeID,
           stayID,
           statusID,
           workstationID,
           vissuedate,
           routeid,
           null,
           vcustomerowned,
           vyear,
           vweek,
           vdayno,
           null,
           systemuserID,
           sysdate,
           vpreviousstay,
           transactiontp,
           0,
           uniqueitemID,
           secondaryID);
        if debuglevel > 0 then
          utl_file.put_line(SQLfile, 'insert scan' || idcode);
        end if;
      exception
        when others then
          accept := 'N';
          utl_file.put_line(SQLfile,
                            IDCode || ' ' || sqlcode || ' ' || sqlerrm);
      end;
    end; --for accept='Y'
  end if; --for accept='Y'
  y := current_timestamp;
  z := y - x;
  if debuglevel > 0 then
    utl_file.put_line(SQLfile, 'stop SortScan' || z);
  end if;
  --UTL_FILE.FCLOSE(SqlFile);
end ProcessSortScan;
/
create or replace procedure productconversionwizard(fp_from_productid          in out product.product_id%type,
                                                    fp_from_sizedefinitionid   in out sizedefinition.sizedefinition_id%type,
                                                    fp_to_productid            in out product.product_id%type,
                                                    fp_to_sizedefinitionid     in out sizedefinition.sizedefinition_id%type,
                                                    fp_businessunitid          in businessunit.businessunit_id%type default null,
                                                    fp_includepricelists       in varchar2 default 'N',
                                                    fp_testrun                 in varchar2,
                                                    fp_languageid              in languages.language_id%type,
                                                    fp_systemuserid            in systemuser.systemuser_id%type,
                                                    fp_abslog_processjobpartid in abslogprocessjobpart.abslogprocessjobpart_id%type default null,
                                                    fp_selection               in varchar2 default 'N',
                                                    fp_jobrunid                in customerproductconversion.jobrun_id%type default null,
                                                    fp_result                  out nocopy number /*0=Ok, Others is error*/,
                                                    fp_result_message          out nocopy varchar2) is
  /*Procedure ProductConversionWizard version 1.0
  Based on document
  --  ProductConversionWizardDlg.doc
  When TESTRUN is checked then only the log is created, nothing is updated.
  All updating must be done in 1 database transaction:
  Only if all updates are successful then the transaction is committed.
  If one update fails, a rollback is done for all updates (even though log mentions it is updated!)

  --Update 5-5-2017 ABS-47932, ABS-50496 Product Conversion Wizard - Phase 2
  --Please add this index: reate index XSPTDELIVERYSCAN on DELIVERYSCAN (BUSINESSUNIT_ID, PRODUCT_LINK_ID, NVL(PACKINGNOTE_ID,0));
  --Update 22-Feb-2018 ABS-58027 Enhancements to Product Conversion Wizard / ABS-62595 Updating procedure
  --Update 18-Jan-2023 ABS-143390 error product conversion wizard
  --Update 19-01-2023 ABS-145532 Product Conversion Wizard - not converting WOs with status picked
  --Update 14-06-2023 ABS-149911 Item Conversion not works
  --Update 10/11/2023 ABS-155717 Product Conversion Wizard - Constraint Error
  --Update 14-10-2024 ABS-169884 Product conversion Wizard - Coeff value from PLPC not kept
  --Update 06-11-2024 ABS-170927 Error on Product Conversion Wizard
  --Update 16-12-2024 ABSN-278 UNF D_UBS_2590 Global exchange didn t move the SRC percentage price
  --Update 10-03-2025 ABSN-682 Product Conversion Wizard not copy over Budget Protection
  --Update 25-09-2025 ABSN-10407 ORA-600 when running product conversion wizard
  --Update 22-10-2025 ABSN-ABSN-11328 Error on Include Price Lists when only prices/discountsfor size * is defined in general price/discount lists
  */
  --global variables
  gv_message varchar2(1000);
  gv_userexception exception;
  gv_languagecode             languages.code%type;
  gv_from_productcode         product.code%type;
  gv_from_product_activityid  productgroup.activity_id%type;
  gv_from_product_groupid     product.productgroup_id%type;
  gv_from_prodrecordpassstock product.recordpassivestock%type;
  gv_from_product_tom         product.typeofmerchandise%type;
  gv_to_productcode           product.code%type;
  gv_to_product_activityid    productgroup.activity_id%type;
  gv_to_product_groupid       product.productgroup_id%type;
  gv_to_prodrecordpassstock   product.recordpassivestock%type;
  gv_productsupplierid        supplier.supplier_id%type;
  gv_from_sizecode            sizedefinition.code%type;
  gv_to_sizecode              sizedefinition.code%type;
  gv_usergroupid              systemuser.usergroup_id%type;
  gv_bucode                   businessunit.code%type;
  gv_reasoncodeid             reasoncode.reasoncode_id%type;
  gv_sizestarid               sizedefinition.sizedefinition_id%type; --Size *
  gv_size_only_change         number; --0=fales, 1=true
  gv_transactiontypeid        transactiontype.transactiontype_id%type := 81; --81 product change, fixed value
  gv_customernumber           customer.customernumber%type;

  ---internal procedures
  procedure write_log(fp_message in varchar2, fp_priority in number default 1) is
  begin
    --write_log
    if fp_abslog_processjobpartid is null then
      begin
        begin
          abslogwrite.abslog_write(5,
                                   'productconversionwizard test ' ||
                                    nvl(substr(fp_testrun, 1, 1), 'Y'), fp_businessunitid, fp_priority,
                                   fp_message, fp_systemuserid);
        end;
      end;
    else
      abslogwrite.abslogprocessjobline_write(fp_abslog_processjobpartid, fp_priority, fp_message,
                                             fp_systemuserid);
    end if;
  end write_log;

  procedure initialize is
    --initialize local variables
    lv_from_productdesc product_desc.description%type;
    lv_from_sizedesc    sizedefinition_desc.description%type;
    lv_to_productdesc   product_desc.description%type;
    lv_to_product_tom   product.typeofmerchandise%type;
    lv_to_sizedesc      sizedefinition_desc.description%type;
    lv_budesc           businessunit.description%type;
    lv_username         systemuser.username%type;

    procedure write_log_header is
    begin
      --write_log_header
      gv_message := 'write_log_header';
      write_log(rpad('Convert product: ', 18, ' ') || rpad(gv_from_productcode, 13, ' ') || ' ' ||
                lv_from_productdesc);
      write_log(rpad('Size: ', 18, ' ') || rpad(gv_from_sizecode, 13, ' ') || ' ' ||
                lv_from_sizedesc);
      write_log(rpad('To product: ', 18, ' ') || rpad(gv_to_productcode, 13, ' ') || ' ' ||
                lv_to_productdesc);
      write_log(rpad('To size: ', 18, ' ') || rpad(gv_to_sizecode, 13, ' ') || ' ' ||
                lv_to_sizedesc);
      write_log(rpad('Business unit: ', 18, ' ') || rpad(gv_bucode, 13, ' ') || ' ' || lv_budesc);
      write_log(rpad('Gen.Pricelists: ', 18, ' ') || fp_includepricelists);
      write_log(rpad('Conversion date: ', 18, ' ') || to_char(sysdate, 'DD-MM-YYYY'));
      write_log(rpad('Converted by: ', 18, ' ') || lv_username);
      write_log(rpad('Test run: ', 18, ' ') || fp_testrun);
    end write_log_header;
  begin
    --initialize
    gv_message := 'initialize';
    --get size star
    gv_message := 'Size *';
    select s.sizedefinition_id into gv_sizestarid from sizedefinition s where s.code = '*';
    --check fp_languageid
    if fp_languageid is null then
      begin
        gv_message := 'Parameter fp_languageid cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        gv_message := 'Parameter fp_languageid ' || to_char(fp_languageid);
        select l.code into gv_languagecode from languages l where l.language_id = fp_languageid;
      end;
    end if;
    --check fp_from_productid
   if fp_from_productid is null then
      begin
        gv_message := 'Parameter fp_from_productid cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        gv_message := 'Parameter fp_from_productid ' || to_char(fp_from_productid);
        select p.code, p.recordpassivestock, pg.activity_id, p.productgroup_id, p.typeofmerchandise
        into   gv_from_productcode, gv_from_prodrecordpassstock, gv_from_product_activityid,
               gv_from_product_groupid, gv_from_product_tom
        from   product p
        join   productgroup pg
        on     pg.productgroup_id = p.productgroup_id
        where  p.product_id = fp_from_productid;
        --get product description
        gv_message := 'Product description for product code ' || gv_from_productcode ||
                      ' for language ' || gv_languagecode;
        select pd.description
        into   lv_from_productdesc
        from   product_desc pd
        where  pd.product_id = fp_from_productid
        and    pd.language_id = fp_languageid;
      end;
    end if;
    --check fp_from_sizedefinitionid
    if fp_from_sizedefinitionid is null then
      begin
        gv_from_sizecode := null;
      end;
    else
      begin
        --check that the size from is not size *
        if fp_from_sizedefinitionid = gv_sizestarid then
          begin
            gv_message := 'Parameter fp_from_sizedefinitionid cannot be size * (star)!  Please, leave the parameter empty instead (null).';
            raise gv_userexception;
          end;
        end if;
        --get from size
        gv_message := 'Parameter fp_from_sizedefinitionid ' || to_char(fp_from_sizedefinitionid);
        select s.code
        into   gv_from_sizecode
        from   sizedefinition s
        where  s.sizedefinition_id = fp_from_sizedefinitionid;
        --get sizedescription
        gv_message := 'Size description for size code ' || gv_from_sizecode || ' for language ' ||
                      gv_languagecode;
        select sd.description
        into   lv_from_sizedesc
        from   sizedefinition_desc sd
        where  sd.sizedefinition_id = fp_from_sizedefinitionid
        and    sd.language_id = fp_languageid;
      end;
    end if;
    --check fp_to_productid
    if fp_to_productid is null then
      begin
        gv_message := 'Parameter fp_to_productid cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        gv_message := 'Parameter fp_to_productid ' || to_char(fp_to_productid);
        select p.code, p.recordpassivestock, p.supplier_id, pg.activity_id, p.productgroup_id,
               p.typeofmerchandise
        into   gv_to_productcode, gv_to_prodrecordpassstock, gv_productsupplierid,
               gv_to_product_activityid, gv_to_product_groupid, lv_to_product_tom
        from   product p
        join   productgroup pg
        on     pg.productgroup_id = p.productgroup_id
        where  p.product_id = fp_to_productid;
        --check stockroom changes
        if gv_from_prodrecordpassstock = 'N' and gv_to_prodrecordpassstock = 'Y' then
          begin
            /*
            This should not be possible, handled via the selections.
            */
            gv_message := 'From product recordpassivestock = N and To product recordpassivestock = Y is not allowed!';
            raise gv_userexception;
          end;
        end if;
        --check Type of Merchandise
        if gv_from_product_tom <> lv_to_product_tom then
          begin
            gv_message := 'Different Type Of Merchandise (TOM) is not allowed! From Product TOM = ' ||
                          to_char(gv_from_product_tom) || ' and To product TOM = ' ||
                          to_char(lv_to_product_tom);
            raise gv_userexception;
          end;
        end if;
        --get product description
        gv_message := 'Product description for product code ' || gv_to_productcode ||
                      ' for language ' || gv_languagecode;
        select pd.description
        into   lv_to_productdesc
        from   product_desc pd
        where  pd.product_id = fp_to_productid
        and    pd.language_id = fp_languageid;
        --check if it is ONLY a size change Yes or No
        if fp_to_productid = fp_from_productid then
          gv_size_only_change := 1;
        else
          gv_size_only_change := 0;
        end if;
      end;
    end if;
    --check fp_to_sizedefinitionid
    if fp_to_sizedefinitionid is null then
      begin
        gv_to_sizecode := null;
      end;
    else
      begin
        --check if combo is ok
        if fp_from_sizedefinitionid is null then
          begin
            gv_message := 'Parameter fp_from_sizedefinitionid cannot be left blank when fp_to_sizedefinitionid is blank!';
            raise gv_userexception;
          end;
        end if;
        --check that the size from is not size *
        if fp_to_sizedefinitionid = gv_sizestarid then
          begin
            gv_message := 'Parameter fp_to_sizedefinitionid cannot be size * (star)! Please, leave the parameter empty instead (null).';
            raise gv_userexception;
          end;
        end if;
        --get to size
        gv_message := 'Parameter fp_to_sizedefinitionid ' || to_char(fp_to_sizedefinitionid);
        select s.code
        into   gv_to_sizecode
        from   sizedefinition s
        where  s.sizedefinition_id = fp_to_sizedefinitionid;
        --get sizedescription
        gv_message := 'Size description for size code ' || gv_to_sizecode || ' for language ' ||
                      gv_languagecode;
        select sd.description
        into   lv_to_sizedesc
        from   sizedefinition_desc sd
        where  sd.sizedefinition_id = fp_to_sizedefinitionid
        and    sd.language_id = fp_languageid;
      end;
    end if;
    --when it is the same product, both sizes must be filled
    if fp_from_productid = fp_to_productid and
       (fp_from_sizedefinitionid is null or fp_to_sizedefinitionid is null) then
      begin
        gv_message := 'No product conversion needed, products are the same size is left blank!';
        raise gv_userexception;
      end;
    end if;
    --check fp_plantid
    if fp_businessunitid is null then
      begin
        gv_bucode := 'ALL';
        lv_budesc := 'BU';
      end;
    else
      begin
        gv_message := 'Parameter fp_businessunitid ' || to_char(fp_businessunitid);
        select bu.code, bu.description
        into   gv_bucode, lv_budesc
        from   businessunit bu
        where  bu.businessunit_id = fp_businessunitid;
      end;
    end if;
    --check fp_includepricelists
    if fp_includepricelists is null then
      begin
        gv_message := 'Parameter fp_includepricelists cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        if fp_includepricelists not in ('Y', 'N') then
          begin
            gv_message := 'Parameter fp_includepricelists must be Y or N but it is ' ||
                          fp_includepricelists;
            raise gv_userexception;
          end;
        end if;
      end;
    end if;
    --check fp_testrun
    if fp_testrun is null then
      begin
        gv_message := 'Parameter fp_testrun cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        if fp_testrun not in ('Y', 'N') then
          begin
            gv_message := 'Parameter fp_testrun must be Y or N but it is ' || fp_testrun;
            raise gv_userexception;
          end;
        end if;
      end;
    end if;
    --check fp_systemuserid
    if fp_systemuserid is null then
      begin
        gv_message := 'Parameter fp_systemuserid cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        gv_message := 'Parameter fp_systemuserid ' || to_char(fp_systemuserid);
        select su.username, su.usergroup_id
        into   lv_username, gv_usergroupid
        from   systemuser su
        where  su.systemuser_id = fp_systemuserid;
      end;
    end if;
    --get phase out products reasoncode
    gv_message := 'Phase In Out Products Reasoncode';
    select rs.reasoncode_id
    into   gv_reasoncodeid
    from   reasoncode rs
    where  rs.phaseinoutproducts = 'Y';
    --write_log_header;
    write_log_header;
  end initialize;

  procedure convertproducts is
    function get_stockdefinitionperitem(fp_stockroomid   in number,
                                        fp_productid     in number,
                                        fp_sizeid        in number,
                                        fp_customerid    in number,
                                        fp_customerowned in varchar2) return number is
      lv_stockdefinitionperitemid number;
    begin
      --get stockdefinitionperitem
      gv_message := 'get stockdefinitionperitem';
      select sdpi.stockdefinitionperitem_id
      into   lv_stockdefinitionperitemid
      from   stockdefinitionperitem sdpi
      where  sdpi.stockroom_id = fp_stockroomid
      and    sdpi.product_id = fp_productid
      and    sdpi.sizedefinition_id = fp_sizeid
      and    (sdpi.customer_id = fp_customerid or
            (sdpi.customer_id is null and fp_customerid is null))
      and    sdpi.customerowned = fp_customerowned;
      return lv_stockdefinitionperitemid;
    exception
      when no_data_found then
        begin
          insert into stockdefinitionperitem
            (stockdefinitionperitem_id, stockroom_id, product_id, sizedefinition_id, customer_id,
             customerowned, minqtynew, minqtyused, maxqtynew, maxqtyused, systemuser_id, timestamp,
             defaultsupplier_id)
          values
            (seq_stockdefinitionperitem.nextval, fp_stockroomid, fp_productid, fp_sizeid,
             fp_customerid, fp_customerowned, 0, 0, 999, 999, fp_systemuserid, sysdate,
             gv_productsupplierid)
          returning stockdefinitionperitem_id into lv_stockdefinitionperitemid;
          return lv_stockdefinitionperitemid;
        end;
    end get_stockdefinitionperitem;

    function get_stockreservationpergrade(fp_stockdefinitionperitemid in number,
                                          fp_qualitygradeid           in number) return number is
      lv_stockreservationpergradeid number;
    begin
      --get_stockreservationpergrade
      gv_message := 'get stockreservation per grade id';
      select srg.stockreservationpergrade_id
      into   lv_stockreservationpergradeid
      from   stockreservationpergrade srg
      where  srg.stockdefinitionperitem_id = fp_stockdefinitionperitemid
      and    srg.qualitygrade_id = fp_qualitygradeid;
      return lv_stockreservationpergradeid;
    exception
      when no_data_found then
        begin
          insert into stockreservationpergrade
            (stockreservationpergrade_id, stockdefinitionperitem_id, qualitygrade_id,
             qtyuniquereserved, qtynonuniquereserved, qtyuniquewiithmodifreserved, qtynonunique,
             qtyuniqueordered, qtynonuniqueordered, systemuser_id, timestamp,
             qtyuniqueordereddirectissue, qtynonuniqueordereddirectissue)
          values
            (seq_stockreservationpergrade.nextval, fp_stockdefinitionperitemid, fp_qualitygradeid,
             0, 0, 0, 0, 0, 0, fp_systemuserid, sysdate, 0, 0)
          returning stockreservationpergrade_id into lv_stockreservationpergradeid;
          return lv_stockreservationpergradeid;
        end;
    end get_stockreservationpergrade;

    procedure create_missing_productsizes is
      lv_sequencenumber productsize.sequencenumber%type;
    begin
      --create_missing_productsizes
      gv_message := 'create_missing_productsizes';
      for sx in (select nvl(fp_to_sizedefinitionid, ps.sizedefinition_id) sizedefinition_id,
                        sequencenumber, fp_systemuserid, ps.specialsize, ps.packingamount,
                        ps.theoreticalweight, ps.provisiongroup_id, ps.legacycode, ps.squaremeters,
                        ps.defaultstockroom_id, ps.fixedstockroom, ps.standardlength, ps.maxcartqty,
                        ps.executedby,
                        (select s.code
                          from   sizedefinition s
                          where  s.sizedefinition_id =
                                 nvl(fp_to_sizedefinitionid, ps.sizedefinition_id)) sizecode
                 from   productsize ps
                 where  ps.product_id = fp_from_productid
                 and    ((fp_from_sizedefinitionid is null) or
                       (fp_from_sizedefinitionid = ps.sizedefinition_id))
                 and    not exists
                  (select 1
                         from   productsize psx
                         where  psx.product_id = fp_to_productid
                         and    psx.sizedefinition_id =
                                nvl(fp_to_sizedefinitionid, ps.sizedefinition_id))) loop
        begin
          --get next sequencenumber for fp_to_productid
          gv_message := 'get next sequencenumber for fp_to_productid';
          select nvl(max(sequencenumber), 0) + 1
          into   lv_sequencenumber
          from   productsize
          where  product_id = fp_to_productid;
          --insert into productsize
          gv_message := 'for fp_to_productid insert into productsize for size id ' ||
                        sx.sizedefinition_id;
          insert into productsize
            (product_id, sizedefinition_id, sequencenumber, systemuser_id, timestamp, specialsize,
             packingamount, theoreticalweight, provisiongroup_id, legacycode, squaremeters,
             defaultstockroom_id, fixedstockroom, standardlength, maxcartqty, executedby)
          values
            (fp_to_productid, sx.sizedefinition_id, lv_sequencenumber, fp_systemuserid, sysdate
             /*timestamp*/, sx.specialsize, sx.packingamount, sx.theoreticalweight,
             sx.provisiongroup_id, sx.legacycode, sx.squaremeters, sx.defaultstockroom_id,
             sx.fixedstockroom, sx.standardlength, sx.maxcartqty, sx.executedby);
          --write log
          write_log('Create Product-Size; Product ' || gv_to_productcode || ' Size ' ||
                    sx.sizecode);
        end;
      end loop; --sx
    end create_missing_productsizes;

    procedure create_missing_prodfinishmeth is
    begin
      --create_missing_prodfinishmeth
      gv_message := 'create_missing_prodfinishmeth';
      insert into productfinishingmethod
        (product_id, finishingmethod_id, systemuser_id, timestamp, expirationdays)
        select fp_to_productid, pf.finishingmethod_id, fp_systemuserid, sysdate /*timestamp*/,
               pf.expirationdays
        from   productfinishingmethod pf
        where  pf.product_id = fp_from_productid
        and    not exists (select 1
                from   productfinishingmethod pfx
                where  pfx.product_id = fp_to_productid
                and    pfx.finishingmethod_id = pf.finishingmethod_id);
      if sql%rowcount > 0 then
        begin
          --write log
          write_log('Copied ' || sql%rowcount || ' product finishingmethod records from Product ' ||
                    gv_from_productcode || ' to product ' || gv_to_productcode);
        end;
      end if;
    end create_missing_prodfinishmeth;

    procedure check_deactivate_product is
    begin
      --3.1.1 Product settings
      --check_deactivate_product
      gv_message := 'check_deactivate_product ' || gv_from_productcode;
      if fp_businessunitid is null and fp_from_sizedefinitionid is null and fp_selection = 'N' then
        begin
          update product p
          set    p.active = 'N', p.systemuser_id = fp_systemuserid, p.timestamp = sysdate
          where  p.product_id = fp_from_productid;
        end;
      end if;
    end check_deactivate_product;

    procedure copy_generalpricelists(fp_customerid customer.customer_id%type default null) is
      --3.1.2 General Price / Discount Lists
      procedure copy_generalrentprice is
      begin
        --copy_generalrentprice
        gv_message := 'copy_generalrentprice';
        --GENERALPRICELIST_ID,
        --PRODUCT_ID, SIZEDEFINITION_ID, FINISHINGMETHOD_ID, TYPEOFRENT,
        --STARTDATE, CHANGESPERWEEK, INVOICEFREQUENCYNUMBER
        for grpx in (select grp.generalpricelist_id, grp.sizedefinition_id, grp.finishingmethod_id,
                            grp.price,
                            case
                              when grp.startdate < trunc(sysdate) then
                               trunc(sysdate)
                              else
                               grp.startdate
                            end startdate, grp.changesperweek, grp.typeofrent,
                            grp.invoicefrequencynumber, gp.code generalpricelistcode,
                            (select s.code
                              from   sizedefinition s
                              where  s.sizedefinition_id = grp.sizedefinition_id) sizecode,
                            (select f.code
                              from   finishingmethod f
                              where  f.finishingmethod_id = grp.finishingmethod_id) finishingmethodcode,
                             grp.sizebillinggroup_id
                     from   generalrentprice grp
                     join   generalpricelist gp
                     on     gp.generalpricelist_id = grp.generalpricelist_id
                     where  grp.product_id = fp_from_productid
                     and    (fp_from_sizedefinitionid is null or
                           grp.sizedefinition_id = fp_from_sizedefinitionid
                           or grp.sizedefinition_id = gv_sizestarid)
                     and    grp.startdate >=
                            coalesce((select max(zz.startdate)
                                      from   generalrentprice zz
                                      where  zz.generalpricelist_id = grp.generalpricelist_id
                                      and    zz.product_id = grp.product_id
                                      and    zz.sizedefinition_id = grp.sizedefinition_id
                                      and    zz.finishingmethod_id = grp.finishingmethod_id
                                      and    zz.changesperweek = grp.changesperweek
                                      and    zz.typeofrent = grp.typeofrent
                                      and    zz.invoicefrequencynumber = grp.invoicefrequencynumber
                                      and    nvl(zz.sizebillinggroup_id,0) = nvl(grp.sizebillinggroup_id,0)
                                      and    zz.startdate <= trunc(sysdate)), trunc(sysdate))
                     and (gp.generalpricelist_id in (select cp.generalpricelist_id
                                                     from contractpricelist cp
                                                     where cp.contract_id in (select cc.contract_id
                                                                              from contractcustomer cc
                                                                              where cc.customer_link_id = fp_customerid)) or fp_customerid is null)
                     and    not exists
                      (select 1
                             from   generalrentprice grpy
                             where  grpy.generalpricelist_id = grp.generalpricelist_id
                             and    grpy.product_id = fp_to_productid
                             and    grpy.sizedefinition_id  in (fp_to_sizedefinitionid, grp.sizedefinition_id,gv_sizestarid)
                             and    grpy.finishingmethod_id = grp.finishingmethod_id
                             and    grpy.changesperweek = grp.changesperweek
                             and    grpy.typeofrent = grp.typeofrent
                             and    grpy.invoicefrequencynumber = grp.invoicefrequencynumber
                             and    nvl(grpy.sizebillinggroup_id,0) = nvl(grp.sizebillinggroup_id,0))) loop
          begin
            --insert into generalrentprice
            gv_message := 'insert into generalrentprice';
            insert into generalrentprice
              (generalrentprice_id, generalpricelist_id, product_id, sizedefinition_id,
               finishingmethod_id, timestamp, systemuser_id, price, startdate, changesperweek,
               typeofrent, invoicefrequencynumber, sizebillinggroup_id)
            values
              (seq_generalrentprice.nextval, grpx.generalpricelist_id, fp_to_productid,
               case when grpx.sizedefinition_id != gv_sizestarid then coalesce(fp_to_sizedefinitionid, grpx.sizedefinition_id)
                 else grpx.sizedefinition_id end, grpx.finishingmethod_id,
               sysdate /*timestamp*/, fp_systemuserid, grpx.price, grpx.startdate,
               grpx.changesperweek, grpx.typeofrent, grpx.invoicefrequencynumber, grpx.sizebillinggroup_id);
            --write log
            write_log('Created General Rent Price, for ' || grpx.generalpricelistcode ||
                      ' for product ' || gv_to_productcode || ' size ' ||
                      coalesce(gv_to_sizecode, grpx.sizecode) || ' finishingmethod ' ||
                      grpx.finishingmethodcode || ' startdate ' ||
                      to_char(grpx.startdate, 'DD-MON-YYYY'));
          end;
        end loop; --grpx
      end copy_generalrentprice;

      procedure copy_generalemblemprice is
      begin
        --copy_generalemblemprice
        gv_message := 'copy_generalemblemprice';
        for gepx in (select geb.sizedefinition_id, geb.price,
                            case
                              when geb.startdate < trunc(sysdate) then
                               trunc(sysdate)
                              else
                               geb.startdate
                            end startdate, geb.generalpricelist_id, gp.code generalpricelistcode,
                            (select s.code
                              from   sizedefinition s
                              where  s.sizedefinition_id = geb.sizedefinition_id) sizecode
                     from   generalemblemprice geb
                     join   generalpricelist gp
                     on     gp.generalpricelist_id = geb.generalpricelist_id
                     where  geb.product_id = fp_from_productid
                     and    (fp_from_sizedefinitionid is null or
                           geb.sizedefinition_id = fp_from_sizedefinitionid
                           or geb.sizedefinition_id = gv_sizestarid)
                     and    geb.startdate >=
                            coalesce((select max(zz.startdate)
                                      from   generalemblemprice zz
                                      where  zz.generalpricelist_id = geb.generalpricelist_id
                                      and    zz.product_id = geb.product_id
                                      and    zz.sizedefinition_id = geb.sizedefinition_id
                                      and    zz.startdate <= trunc(sysdate)), trunc(sysdate))
                     and (gp.generalpricelist_id in (select cp.generalpricelist_id
                                                     from contractpricelist cp
                                                     where cp.contract_id in (select cc.contract_id
                                                                              from contractcustomer cc
                                                                              where cc.customer_link_id = fp_customerid)) or fp_customerid is null)
                     and    not exists
                      (select 1
                             from   generalemblemprice geby
                             where  geby.generalpricelist_id = geb.generalpricelist_id
                             and    geby.product_id = fp_to_productid
                             and    geby.sizedefinition_id in (fp_to_sizedefinitionid,geb.sizedefinition_id,gv_sizestarid))) loop
          begin
            --insert into generalemblemprice
            gv_message := 'insert into generalemblemprice';
            insert into generalemblemprice
              (generalemblemprice_id, product_id, sizedefinition_id, price, startdate,
               systemuser_id, timestamp, generalpricelist_id)
            values
              (seq_generalemblemprice.nextval, fp_to_productid, case when gepx.sizedefinition_id != gv_sizestarid
               then coalesce(fp_to_sizedefinitionid, gepx.sizedefinition_id)
                else gepx.sizedefinition_id end, gepx.price, gepx.startdate,
               fp_systemuserid, sysdate /*timestamp*/, gepx.generalpricelist_id);
            --write log
            write_log('Created General Emblem Price, for ' || gepx.generalpricelistcode ||
                      ' for product ' || gv_to_productcode || ' size ' ||
                      coalesce(gv_to_sizecode, gepx.sizecode) || ' startdate ' ||
                      to_char(gepx.startdate, 'DD-MON-YYYY'));
          end;
        end loop; --gepx
      end copy_generalemblemprice;

      procedure copy_generalinsuranceprice is
      begin
        --copy_generalinsuranceprice
        gv_message := 'copy_generalinsuranceprice';
        for gipx in (select gip.generalpricelist_id, gip.sizedefinition_id, gip.finishingmethod_id,
                            gip.price,
                            case
                              when gip.startdate < trunc(sysdate) then
                               trunc(sysdate)
                              else
                               gip.startdate
                            end startdate, gp.code generalpricelistcode,
                            (select s.code
                              from   sizedefinition s
                              where  s.sizedefinition_id = gip.sizedefinition_id) sizecode,
                            (select f.code
                              from   finishingmethod f
                              where  f.finishingmethod_id = gip.finishingmethod_id) finishingmethodcode
                     from   generalinsuranceprice gip
                     join   generalpricelist gp
                     on     gp.generalpricelist_id = gip.generalpricelist_id
                     where  gip.product_id = fp_from_productid
                     and    (gip.sizedefinition_id = fp_from_sizedefinitionid or
                           fp_from_sizedefinitionid is null
                           or gip.sizedefinition_id = gv_sizestarid)
                     and    gip.startdate >=
                            coalesce((select max(zz.startdate)
                                      from   generalinsuranceprice zz
                                      where  zz.generalpricelist_id = gip.generalpricelist_id
                                      and    zz.product_id = gip.product_id
                                      and    zz.sizedefinition_id = gip.sizedefinition_id
                                      and    zz.finishingmethod_id = gip.finishingmethod_id
                                      and    zz.startdate <= trunc(sysdate)), trunc(sysdate))
                     and (gp.generalpricelist_id in (select cp.generalpricelist_id
                                                     from contractpricelist cp
                                                     where cp.contract_id in (select cc.contract_id
                                                                              from contractcustomer cc
                                                                              where cc.customer_link_id = fp_customerid)) or fp_customerid is null)
                     and    not exists
                      (select 1
                             from   generalinsuranceprice gipy
                             where  gipy.generalpricelist_id = gip.generalpricelist_id
                             and    gipy.product_id = fp_to_productid
                             and    gipy.sizedefinition_id in (fp_to_sizedefinitionid, gip.sizedefinition_id,gv_sizestarid)
                             and    gipy.finishingmethod_id = gip.finishingmethod_id)) loop
          begin
            --insert into generalinsuranceprice
            gv_message := 'insert into generalinsuranceprice';
            insert into generalinsuranceprice
              (generalinsuranceprice_id, generalpricelist_id, product_id, sizedefinition_id,
               finishingmethod_id, price, startdate, systemuser_id, timestamp)
            values
              (seq_generalinsuranceprice.nextval, gipx.generalpricelist_id, fp_to_productid,
              case when gipx.sizedefinition_id != gv_sizestarid then coalesce(fp_to_sizedefinitionid, gipx.sizedefinition_id)
                 else gipx.sizedefinition_id end, gipx.finishingmethod_id,
               gipx.price, gipx.startdate, fp_systemuserid, sysdate /*timestamp*/);
            --write log
            write_log('Created General Insurance Price, for ' || gipx.generalpricelistcode ||
                      ' for product ' || gv_to_productcode || ' size ' ||
                      coalesce(gv_to_sizecode, gipx.sizecode) || ' finishingmethod ' ||
                      gipx.finishingmethodcode || ' startdate ' ||
                      to_char(gipx.startdate, 'DD-MON-YYYY'));
          end;
        end loop; --gipx
      end copy_generalinsuranceprice;

      procedure copy_generalrentdiscount is
      begin
        --copy_generalrentdiscount
        gv_message := 'copy_generalrentdiscount';
        for grdx in (select grd.generaldiscountlist_id, grd.sizedefinition_id, grd.finishingmethod_id,
                            grd.discount,
                            case
                              when grd.startdate < trunc(sysdate) then
                               trunc(sysdate)
                              else
                               grd.startdate
                            end startdate, grd.typeofrent, gd.code generaldiscountcode,
                            (select s.code
                              from   sizedefinition s
                              where  s.sizedefinition_id = grd.sizedefinition_id) sizecode,
                            (select f.code
                              from   finishingmethod f
                              where  f.finishingmethod_id = grd.finishingmethod_id) finishingmethodcode
                     from   generalrentdiscount grd
                     join   generaldiscountlist gd
                     on     gd.generaldiscountlist_id = grd.generaldiscountlist_id
                     where  grd.product_id = fp_from_productid
                     and    (grd.sizedefinition_id = fp_from_sizedefinitionid or
                           fp_from_sizedefinitionid is null
                           or grd.sizedefinition_id = gv_sizestarid)
                     and    grd.startdate >=
                            coalesce((select max(zz.startdate)
                                      from   generalrentdiscount zz
                                      where  zz.generaldiscountlist_id = grd.generaldiscountlist_id
                                      and    zz.product_id = grd.product_id
                                      and    zz.sizedefinition_id = grd.sizedefinition_id
                                      and    zz.finishingmethod_id = grd.finishingmethod_id
                                      and    zz.typeofrent = grd.typeofrent
                                      and    zz.startdate <= trunc(sysdate)), trunc(sysdate))
                    and (gd.generaldiscountlist_id in (select cdl.generaldiscountlist_id
                                                     from contractdiscountlist cdl
                                                     where cdl.contract_id in (select cc.contract_id
                                                                              from contractcustomer cc
                                                                              where cc.customer_link_id = fp_customerid)) or fp_customerid is null)
                     and    not exists
                      (select 1
                             from   generalrentdiscount grdy
                             where  grdy.generalrentdiscount_id = grd.generaldiscountlist_id
                             and    grdy.product_id = fp_to_productid
                             and    grdy.sizedefinition_id in (fp_to_sizedefinitionid, grd.sizedefinition_id,gv_sizestarid)
                             and    grdy.finishingmethod_id = grd.finishingmethod_id
                             and    grdy.typeofrent = grd.typeofrent)) loop
          begin
            --insert into generalrentdiscount
            gv_message := 'insert into generalrentdiscount';
            insert into generalrentdiscount
              (generalrentdiscount_id, generaldiscountlist_id, product_id, sizedefinition_id,
               finishingmethod_id, timestamp, systemuser_id, discount, startdate, typeofrent)
            values
              (seq_generalrentdiscount.nextval, grdx.generaldiscountlist_id, fp_to_productid,
              case when grdx.sizedefinition_id != gv_sizestarid then coalesce(fp_to_sizedefinitionid, grdx.sizedefinition_id)
                 else grdx.sizedefinition_id end, grdx.finishingmethod_id,
               sysdate /*timestamp*/, fp_systemuserid, grdx.discount, grdx.startdate,
               grdx.typeofrent);
            --write log
            write_log('Created General Rent Discount, for ' || grdx.generaldiscountcode ||
                      ' for product ' || gv_to_productcode || ' size ' ||
                      coalesce(gv_to_sizecode, grdx.sizecode) || ' finishingmethod ' ||
                      grdx.finishingmethodcode || ' startdate ' ||
                      to_char(grdx.startdate, 'DD-MON-YYYY'));
          end;
        end loop; --grdx
      end copy_generalrentdiscount;

      procedure copy_generalreplacementprice is
      begin
        --copy_generalreplacementprice
        gv_message := 'copy_generalreplacementprice';
        for grpx in (select grp.generalpricelist_id, grp.sizedefinition_id, grp.price,
                            case
                              when grp.startdate < trunc(sysdate) then
                               trunc(sysdate)
                              else
                               grp.startdate
                            end startdate,
                            (select s.code
                              from   sizedefinition s
                              where  s.sizedefinition_id = grp.sizedefinition_id) sizecode,
                            gp.code generalpricelistcode,
                            grp.sizebillinggroup_id
                     from   generalreplacementprice grp
                     join   generalpricelist gp
                     on     gp.generalpricelist_id = grp.generalpricelist_id
                     where  grp.product_id = fp_from_productid
                     and    (grp.sizedefinition_id = fp_from_sizedefinitionid or
                           fp_from_sizedefinitionid is null
                           or grp.sizedefinition_id = gv_sizestarid)
                     and    grp.startdate >=
                            coalesce((select max(zz.startdate)
                                      from   generalreplacementprice zz
                                      where  zz.generalpricelist_id = grp.generalpricelist_id
                                      and    zz.product_id = grp.product_id
                                      and    zz.sizedefinition_id = grp.sizedefinition_id
                                      and    nvl(zz.sizebillinggroup_id,0) = nvl(grp.sizebillinggroup_id,0)
                                      and    zz.startdate <= trunc(sysdate)), trunc(sysdate))
                     and (gp.generalpricelist_id in (select cp.generalpricelist_id
                                                     from contractpricelist cp
                                                     where cp.contract_id in (select cc.contract_id
                                                                              from contractcustomer cc
                                                                              where cc.customer_link_id = fp_customerid)) or fp_customerid is null)
                     and    not exists
                      (select 1
                             from   generalreplacementprice grpy
                             where  grpy.generalpricelist_id = grp.generalpricelist_id
                             and    grpy.product_id = fp_to_productid
                             and    grpy.sizedefinition_id in (fp_to_sizedefinitionid, grp.sizedefinition_id,gv_sizestarid)
                             and    nvl(grpy.sizebillinggroup_id,0) = nvl(grp.sizebillinggroup_id,0))) loop
          begin
            --insert into generalreplacementprice
            gv_message := 'insert into generalreplacementprice';
            insert into generalreplacementprice
              (generalreplacementprice_id, generalpricelist_id, product_id, sizedefinition_id,
               timestamp, systemuser_id, price, startdate, sizebillinggroup_id)
            values
              (seq_generalreplacementprice.nextval, grpx.generalpricelist_id, fp_to_productid,
              case when grpx.sizedefinition_id != gv_sizestarid then coalesce(fp_to_sizedefinitionid, grpx.sizedefinition_id)
                 else grpx.sizedefinition_id end, sysdate /*timestamp*/,
               fp_systemuserid, grpx.price, grpx.startdate, grpx.sizebillinggroup_id);
            --write log
            write_log('Created General Replacement Price, for ' || grpx.generalpricelistcode ||
                      ' for product ' || gv_to_productcode || ' size ' ||
                      coalesce(gv_to_sizecode, grpx.sizecode) || ' startdate ' ||
                      to_char(grpx.startdate, 'DD-MON-YYYY'));
          end;
        end loop; --grpx
      end copy_generalreplacementprice;

      procedure copy_generalsalesprice is
      begin
        --copy_generalsalesprice
        gv_message := 'copy_generalsalesprice';
        for gspx in (select gsp.generalpricelist_id, gsp.sizedefinition_id, gsp.price,
                            case
                              when gsp.startdate < trunc(sysdate) then
                               trunc(sysdate)
                              else
                               gsp.startdate
                            end startdate, gsp.volumeprice, gp.code generalpricelistcode,
                            (select s.code
                              from   sizedefinition s
                              where  s.sizedefinition_id = gsp.sizedefinition_id) sizecode,
                              gsp.sizebillinggroup_id
                     from   generalsalesprice gsp
                     join   generalpricelist gp
                     on     gp.generalpricelist_id = gsp.generalpricelist_id
                     where  gsp.product_id = fp_from_productid
                     and    (gsp.sizedefinition_id = fp_from_sizedefinitionid or
                           fp_from_sizedefinitionid is null
                           or gsp.sizedefinition_id = gv_sizestarid)
                     and    gsp.startdate >=
                            coalesce((select max(zz.startdate)
                                      from   generalsalesprice zz
                                      where  zz.generalpricelist_id = gsp.generalpricelist_id
                                      and    zz.product_id = gsp.product_id
                                      and    zz.sizedefinition_id = gsp.sizedefinition_id
                                      and    zz.volumeprice = gsp.volumeprice
                                      and    nvl(zz.sizebillinggroup_id,0) = nvl(gsp.sizebillinggroup_id,0)
                                      and    zz.startdate <= trunc(sysdate)), trunc(sysdate))
                     and (gp.generalpricelist_id in (select cp.generalpricelist_id
                                                     from contractpricelist cp
                                                     where cp.contract_id in (select cc.contract_id
                                                                              from contractcustomer cc
                                                                              where cc.customer_link_id = fp_customerid)) or fp_customerid is null)
                     and    not exists
                      (select 1
                             from   generalsalesprice gspy
                             where  gspy.generalpricelist_id = gsp.generalpricelist_id
                             and    gspy.product_id = fp_to_productid
                             and    gspy.sizedefinition_id in (fp_to_sizedefinitionid, gsp.sizedefinition_id,gv_sizestarid)
                             and    nvl(gspy.sizebillinggroup_id,0) = nvl(gsp.sizebillinggroup_id,0))) loop
          begin
            --insert into generalsalesprice
            gv_message := 'insert into generalsalesprice';
            insert into generalsalesprice
              (generalsalesprice_id, generalpricelist_id, product_id, sizedefinition_id, timestamp,
               systemuser_id, price, startdate, volumeprice, sizebillinggroup_id)
            values
              (seq_generalsalesprice.nextval, gspx.generalpricelist_id, fp_to_productid,
              case when gspx.sizedefinition_id != gv_sizestarid then coalesce(fp_to_sizedefinitionid, gspx.sizedefinition_id)
                 else gspx.sizedefinition_id end, sysdate /*timestamp*/,
               fp_systemuserid, gspx.price, gspx.startdate, gspx.volumeprice, gspx.sizebillinggroup_id);
            --write log
            write_log('Created General Sales Price, for ' || gspx.generalpricelistcode ||
                      ' for product ' || gv_to_productcode || ' size ' ||
                      coalesce(gv_to_sizecode, gspx.sizecode) || ' startdate ' ||
                      to_char(gspx.startdate, 'DD-MON-YYYY'));
          end;
        end loop; --gspx
      end copy_generalsalesprice;

      procedure copy_generalwashdiscount is
      begin
        --copy_generalwashdiscount
        gv_message := 'copy_generalwashdiscount';
        for gwdx in (select gwd.generaldiscountlist_id, gwd.sizedefinition_id, gwd.finishingmethod_id,
                            gwd.discount,
                            case
                              when gwd.startdate < trunc(sysdate) then
                               trunc(sysdate)
                              else
                               gwd.startdate
                            end startdate, gd.code generaldiscountcode,
                            (select s.code
                              from   sizedefinition s
                              where  s.sizedefinition_id = gwd.sizedefinition_id) sizecode,
                            (select f.code
                              from   finishingmethod f
                              where  f.finishingmethod_id = gwd.finishingmethod_id) finishingmethodcode
                     from   generalwashdiscount gwd
                     join   generaldiscountlist gd
                     on     gd.generaldiscountlist_id = gwd.generaldiscountlist_id
                     where  gwd.product_id = fp_from_productid
                     and    (gwd.sizedefinition_id = fp_from_sizedefinitionid or
                           fp_from_sizedefinitionid is null
                           or gwd.sizedefinition_id = gv_sizestarid)
                     and    gwd.startdate >=
                            coalesce((select max(zz.startdate)
                                      from   generalwashdiscount zz
                                      where  zz.generaldiscountlist_id = gwd.generaldiscountlist_id
                                      and    zz.product_id = gwd.product_id
                                      and    zz.sizedefinition_id = gwd.sizedefinition_id
                                      and    zz.finishingmethod_id = gwd.finishingmethod_id
                                      and    zz.startdate <= trunc(sysdate)), trunc(sysdate))
                     and (gd.generaldiscountlist_id in (select cdl.generaldiscountlist_id
                                                     from contractdiscountlist cdl
                                                     where cdl.contract_id in (select cc.contract_id
                                                                              from contractcustomer cc
                                                                              where cc.customer_link_id = fp_customerid)) or fp_customerid is null)
                     and    not exists
                      (select 1
                             from   generalwashdiscount gwdy
                             where  gwdy.generaldiscountlist_id = gwd.generaldiscountlist_id
                             and    gwdy.product_id = fp_to_productid
                             and    gwdy.sizedefinition_id in (fp_to_sizedefinitionid, gwd.sizedefinition_id,gv_sizestarid)
                             and    gwdy.finishingmethod_id = gwd.finishingmethod_id)) loop
          begin
            --insert into generalwashdiscount
            gv_message := 'insert into generalwashdiscount';
            insert into generalwashdiscount
              (generalwashdiscount_id, generaldiscountlist_id, product_id, sizedefinition_id,
               finishingmethod_id, timestamp, systemuser_id, discount, startdate)
            values
              (seq_generalwashdiscount.nextval, gwdx.generaldiscountlist_id, fp_to_productid,
              case when gwdx.sizedefinition_id != gv_sizestarid then coalesce(fp_to_sizedefinitionid, gwdx.sizedefinition_id)
                 else gwdx.sizedefinition_id end, gwdx.finishingmethod_id,
               sysdate /*timestamp*/, fp_systemuserid, gwdx.discount, gwdx.startdate);
            --write log
            write_log('Created General Wash Discount, for ' || gwdx.generaldiscountcode ||
                      ' for product ' || gv_to_productcode || ' size ' ||
                      coalesce(gv_to_sizecode, gwdx.sizecode) || ' finishingmethod ' ||
                      gwdx.finishingmethodcode || ' startdate ' ||
                      to_char(gwdx.startdate, 'DD-MON-YYYY'));
          end;
        end loop; --gwdx
      end copy_generalwashdiscount;

      procedure copy_generalwashprice is
      begin
        --copy_generalwashprice
        gv_message := 'copy_generalwashprice';
        for gwpx in (select gwp.generalpricelist_id, gwp.sizedefinition_id, gwp.finishingmethod_id,
                            gwp.price,
                            case
                              when gwp.startdate < trunc(sysdate) then
                               trunc(sysdate)
                              else
                               gwp.startdate
                            end startdate, gwp.pricetype, gp.code generalpricelistcode,
                            (select s.code
                              from   sizedefinition s
                              where  s.sizedefinition_id = gwp.sizedefinition_id) sizecode,
                            (select f.code
                              from   finishingmethod f
                              where  f.finishingmethod_id = gwp.finishingmethod_id) finishingmethodcode
                     from   generalwashprice gwp
                     join   generalpricelist gp
                     on     gp.generalpricelist_id = gwp.generalpricelist_id
                     where  gwp.product_id = fp_from_productid
                     and    (fp_from_sizedefinitionid is null or
                           gwp.sizedefinition_id = fp_from_sizedefinitionid
                           or gwp.sizedefinition_id = gv_sizestarid)
                     and    gwp.startdate >=
                            coalesce((select max(zz.startdate)
                                      from   generalwashprice zz
                                      where  zz.generalpricelist_id = gwp.generalpricelist_id
                                      and    zz.product_id = gwp.product_id
                                      and    zz.sizedefinition_id = gwp.sizedefinition_id
                                      and    zz.finishingmethod_id = gwp.finishingmethod_id
                                      and    zz.pricetype = gwp.pricetype
                                      and    zz.startdate <= trunc(sysdate)), trunc(sysdate))
                     and (gp.generalpricelist_id in (select cp.generalpricelist_id
                                                     from contractpricelist cp
                                                     where cp.contract_id in (select cc.contract_id
                                                                              from contractcustomer cc
                                                                              where cc.customer_link_id = fp_customerid)) or fp_customerid is null)
                     and    not exists
                      (select 1
                             from   generalwashprice gwpy
                             where  gwpy.generalpricelist_id = gwp.generalpricelist_id
                             and    gwpy.product_id = fp_to_productid
                             and    gwpy.sizedefinition_id in (fp_to_sizedefinitionid, gwp.sizedefinition_id,gv_sizestarid)
                             and    gwpy.finishingmethod_id = gwp.finishingmethod_id
                             and    gwpy.pricetype = gwp.pricetype)) loop
          begin
            --insert into generalwashprice
            gv_message := 'insert into generalwashprice';
            insert into generalwashprice
              (generalwashprice_id, generalpricelist_id, product_id, sizedefinition_id,
               finishingmethod_id, timestamp, systemuser_id, price, startdate, pricetype)
            values
              (seq_generalwashprice.nextval, gwpx.generalpricelist_id, fp_to_productid,
              case when gwpx.sizedefinition_id != gv_sizestarid then coalesce(fp_to_sizedefinitionid, gwpx.sizedefinition_id)
                 else gwpx.sizedefinition_id end, gwpx.finishingmethod_id,
               sysdate /*timestamp*/, fp_systemuserid, gwpx.price, gwpx.startdate, gwpx.pricetype);
            --write log
            write_log('Created General Wash Price, for ' || gwpx.generalpricelistcode ||
                      ' for product ' || gv_to_productcode || ' size ' ||
                      coalesce(gv_to_sizecode, gwpx.sizecode) || ' finishingmethod ' ||
                      gwpx.finishingmethodcode || ' startdate ' ||
                      to_char(gwpx.startdate, 'DD-MON-YYYY'));
          end;
        end loop; --gwpx
      end copy_generalwashprice;

      procedure copy_generalbgprotectionprice is
      begin
        --copy_generalbgprotectionprice
        gv_message := 'copy_generalbgprotectionprice';
        for gbgpx in (select gbgp.sizedefinition_id, gbgp.pricecomponent, gbgp.price,
                            case
                              when gbgp.startdate < trunc(sysdate) then
                               trunc(sysdate)
                              else
                               gbgp.startdate
                            end startdate, gbgp.generalpricelist_id, gp.code generalpricelistcode,
                            (select s.code
                              from   sizedefinition s
                              where  s.sizedefinition_id = gbgp.sizedefinition_id) sizecode
                     from   generalbgprotectionprice gbgp
                     join   generalpricelist gp
                     on     gp.generalpricelist_id = gbgp.generalpricelist_id
                     where  gbgp.product_id = fp_from_productid
                     and    (fp_from_sizedefinitionid is null or
                           gbgp.sizedefinition_id = fp_from_sizedefinitionid
                           or gbgp.sizedefinition_id = gv_sizestarid)
                     and    gbgp.startdate >=
                            coalesce((select max(zz.startdate)
                                      from   generalbgprotectionprice zz
                                      where  zz.generalpricelist_id = gbgp.generalpricelist_id
                                      and    zz.product_id = gbgp.product_id
                                      and    zz.sizedefinition_id = gbgp.sizedefinition_id
                                      and    zz.startdate <= trunc(sysdate)), trunc(sysdate))
                     and (gp.generalpricelist_id in (select cp.generalpricelist_id
                                                     from contractpricelist cp
                                                     where cp.contract_id in (select cc.contract_id
                                                                              from contractcustomer cc
                                                                              where cc.customer_link_id = fp_customerid)) or fp_customerid is null)
                     and    not exists
                      (select 1
                             from   generalbgprotectionprice gbgpy
                             where  gbgpy.generalpricelist_id = gbgp.generalpricelist_id
                             and    gbgpy.product_id = fp_to_productid
                             and    gbgpy.sizedefinition_id in (fp_to_sizedefinitionid, gbgp.sizedefinition_id,gv_sizestarid))) loop
          begin
            --insert into generalemblemprice
            gv_message := 'insert into generalbgprotectionprice';
            insert into generalbgprotectionprice
              (generalbgprotectionprice_id, product_id, sizedefinition_id, pricecomponent, price, startdate,
               systemuser_id, timestamp, generalpricelist_id)
            values
              (seq_generalbgprotectionprice.nextval, fp_to_productid,
              case when gbgpx.sizedefinition_id != gv_sizestarid then coalesce(fp_to_sizedefinitionid, gbgpx.sizedefinition_id)
                 else gbgpx.sizedefinition_id end, gbgpx.pricecomponent, gbgpx.price, gbgpx.startdate,
               fp_systemuserid, sysdate /*timestamp*/, gbgpx.generalpricelist_id);
            --write log
            write_log('Created General BG Protection Price, for ' || gbgpx.generalpricelistcode ||
                      ' for product ' || gv_to_productcode || ' size ' ||
                      coalesce(gv_to_sizecode, gbgpx.sizecode) || ' startdate ' ||
                      to_char(gbgpx.startdate, 'DD-MON-YYYY'));
          end;
        end loop; --gepx
      end copy_generalbgprotectionprice;

      procedure copy_generalspecsizeprice is
        begin
          for gsspx in (select gssp.sizedefinition_id, gssp.price,
                            case
                              when gssp.startdate < trunc(sysdate) then
                               trunc(sysdate)
                              else
                               gssp.startdate
                            end startdate, gssp.generalpricelist_id, gp.code generalpricelistcode,
                            (select s.code
                              from   sizedefinition s
                              where  s.sizedefinition_id = gssp.sizedefinition_id) sizecode
                     from   generalspecsizechargeprice gssp
                     join   generalpricelist gp
                     on     gp.generalpricelist_id = gssp.generalpricelist_id
                     where  gssp.product_id = fp_from_productid
                     and    (fp_from_sizedefinitionid is null or
                           gssp.sizedefinition_id = fp_from_sizedefinitionid
                           or gssp.sizedefinition_id = gv_sizestarid)
                     and    gssp.startdate >=
                            coalesce((select max(zz.startdate)
                                      from   generalspecsizechargeprice zz
                                      where  zz.generalpricelist_id = gssp.generalpricelist_id
                                      and    zz.product_id = gssp.product_id
                                      and    zz.sizedefinition_id = gssp.sizedefinition_id
                                      and    zz.startdate <= trunc(sysdate)), trunc(sysdate))
                     and (gp.generalpricelist_id in (select cp.generalpricelist_id
                                                     from contractpricelist cp
                                                     where cp.contract_id in (select cc.contract_id
                                                                              from contractcustomer cc
                                                                              where cc.customer_link_id = fp_customerid)) or fp_customerid is null)
                     and    not exists
                      (select 1
                             from   generalspecsizechargeprice gsspy
                             where  gsspy.generalpricelist_id = gssp.generalpricelist_id
                             and    gsspy.product_id = fp_to_productid
                             and    gsspy.sizedefinition_id in (fp_to_sizedefinitionid, gssp.sizedefinition_id,gv_sizestarid))) loop
          begin
            --insert into generalspecsizechargeprice
            gv_message := 'insert into generalspecsizechargeprice';
            insert into generalspecsizechargeprice
              (generalspecsizechargeprice_id, generalpricelist_id, product_id, sizedefinition_id, startdate, price, systemuser_id, timestamp)
            values
              (seq_generalspecsizechargeprice.nextval, gsspx.generalpricelist_id, fp_to_productid,
              case when gsspx.sizedefinition_id != gv_sizestarid then coalesce(fp_to_sizedefinitionid, gsspx.sizedefinition_id)
                 else gsspx.sizedefinition_id end, gsspx.startdate, gsspx.price, fp_systemuserid, sysdate /*timestamp*/);
            --write log
            write_log('Created General Special Size Charge Price, for ' || gsspx.generalpricelistcode ||
                      ' for product ' || gv_to_productcode || ' size ' ||
                      coalesce(gv_to_sizecode, gsspx.sizecode) || ' startdate ' ||
                      to_char(gsspx.startdate, 'DD-MON-YYYY'));
          end;
        end loop; --gsspx
      end copy_generalspecsizeprice;

    begin
      if fp_includepricelists = 'Y' then
        begin
          --copy_generalpricelists
          gv_message := 'copy_generalpricelists';
          --copy_generalrentprice
          copy_generalrentprice;
          --copy_generalemblemprice
          copy_generalemblemprice;
          --copy_generalinsuranceprice
          copy_generalinsuranceprice;
          --copy_generalrentdiscount
          copy_generalrentdiscount;
          --copy_generalreplacementprice
          copy_generalreplacementprice;
          --copy_generalsalesprice
          copy_generalsalesprice;
          --copy_generalwashdiscount
          copy_generalwashdiscount;
          --copy_generalwashprice
          copy_generalwashprice;
          --copy_generalbgprotectionprice;
          copy_generalbgprotectionprice;
          --copy_generalspecsizeprice
          copy_generalspecsizeprice;
        end;
      end if;
    end copy_generalpricelists;

    procedure convert_stockroom_product is
      /*See analyse
      --3.2 Stockroom
      Please note:
      - Purchase orders and outstanding ordered stock are not handled in this conversion.
      - Reserved stock is handled via the work orders.
      - If for a product RecordPassiveStock is set to N but still the stock tables are filled, this is ignored.
      */
      lv_dest_stockdefperitemid  number;
      lv_dest_stockrespergradeid number;

      procedure check_stdlocationperproduct(fp_stockroomid   in stockroom.stockroom_id%type,
                                            fp_stockroomcode in stockroom.code%type,
                                            fp_customerid    in customer.customer_id%type,
                                            fp_customerowned in stockdefinitionperitem.customerowned%type) is
        lv_stockroomlocationid       stockroomlocation.stockroomlocation_id%type;
        lv_standardlocationperprodid standardlocationperproduct.standardlocationperproduct_id%type;
      begin
        --check_stdlocationperproduct
        gv_message := 'check_stdlocationperproduct fp_stockroomid ' || fp_stockroomid ||
                      ' fp_customerid ' || fp_customerid || ' fp_customerowned ' ||
                      fp_customerowned;
        select sl.stockroomlocation_id
        into   lv_stockroomlocationid
        from   standardlocationperproduct slp
        join   stockroomlocation sl
        on     sl.stockroomlocation_id = slp.stockroomlocation_id
        where  slp.product_id = fp_to_productid
        and    nvl(slp.customer_id, 0) = nvl(fp_customerid, 0)
        and    slp.customerowned = fp_customerowned
        and    slp.active = 'Y'
        and    sl.stockroom_id = fp_stockroomid;
      exception
        when too_many_rows then
          null; ---> no problem it is already there
        when no_data_found then
          begin
            --create
            for slx in (select slpsource.standardlocationperproduct_id,
                               slpsource.stockroomlocation_id, slpsource.priority,
                               slpsource.allowedgrade, slpsource.definepersize,
                               slpsource.standardtruckload, slpsource.active
                        from   standardlocationperproduct slpsource
                        join   stockroomlocation sl
                        on     sl.stockroomlocation_id = slpsource.stockroomlocation_id
                        where  slpsource.product_id = fp_from_productid
                        and    nvl(slpsource.customer_id, 0) = nvl(fp_customerid, 0)
                        and    slpsource.customerowned = fp_customerowned
                        and    slpsource.active = 'Y'
                        and    sl.stockroom_id = fp_stockroomid) loop
              begin
                --insert into standardlocationperproduct
                gv_message := 'insert into standardlocationperproduct';
                insert into standardlocationperproduct
                  (standardlocationperproduct_id, stockroomlocation_id, product_id, priority,
                   customerowned, customer_id, allowedgrade, definepersize, active, systemuser_id,
                   timestamp, standardtruckload)
                values
                  (seq_standardlocationperproduct.nextval, slx.stockroomlocation_id,
                   fp_to_productid, slx.priority, fp_customerowned, fp_customerid, slx.allowedgrade,
                   slx.definepersize, slx.active, fp_systemuserid, sysdate /*timestamp*/,
                   slx.standardtruckload)
                returning standardlocationperproduct_id into lv_standardlocationperprodid;
                for sly in (select slps.sizedefinition_id, slps.standardtruckload
                            from   standardlocationpersize slps
                            where  slps.standardlocationperproduct_id =
                                   slx.standardlocationperproduct_id) loop
                  begin
                    --insert into standardlocationpersize
                    gv_message := 'insert into standardlocationpersize';
                    insert into standardlocationpersize
                      (standardlocationperproduct_id, sizedefinition_id, systemuser_id, timestamp,
                       standardtruckload)
                    values
                      (lv_standardlocationperprodid, sly.sizedefinition_id, fp_systemuserid,
                       sysdate /*timestamp*/, sly.standardtruckload);
                  end;
                end loop; --sly
              end;
            end loop; --slx
            --write log
            write_log('Created standard location(s) for stockroom code ' || fp_stockroomcode);
          end;
      end check_stdlocationperproduct;

      procedure update_stockquantity(fp_stockroomlocationid        in number,
                                     fp_stockreservationpergradeid in number,
                                     fp_qtyunique                  in number,
                                     fp_qtyuniquewithmodifications in number,
                                     fp_qtynonunique               in number) is
      begin
        --update_stockquantity
        gv_message := 'update_stockquantity create / update stockquantity, fp_stockroomlocationid ' ||
                      fp_stockroomlocationid || ' fp_stockreservationpergradeid ' ||
                      fp_stockreservationpergradeid;
        update stockquantity q
        set    q.qtyunique = q.qtyunique + fp_qtyunique,
               q.qtyuniquewithmodifications = q.qtyuniquewithmodifications +
                                               fp_qtyuniquewithmodifications,
               q.qtynonunique = q.qtynonunique + fp_qtynonunique, q.systemuser_id = fp_systemuserid,
               q.timestamp = sysdate
        where  q.stockroomlocation_id = fp_stockroomlocationid
        and    q.stockreservationpergrade_id = fp_stockreservationpergradeid;
        if sql%rowcount = 0 then
          begin
            insert into stockquantity
              (stockreservationpergrade_id, stockroomlocation_id, qtyunique,
               qtyuniquewithmodifications, systemuser_id, timestamp, qtycounted, datecounted,
               qtynonunique)
            values
              (fp_stockreservationpergradeid, fp_stockroomlocationid, fp_qtyunique,
               fp_qtyuniquewithmodifications, fp_systemuserid, sysdate, null, null, fp_qtynonunique);
          end;
        end if;
      end update_stockquantity;

      procedure create_stocktransaction(fp_stockreservationpergradeid in number,
                                        fp_uniquestock                in varchar2,
                                        fp_quantity                   in number,
                                        fp_from_stockroomlocationid   in number,
                                        fp_to_stockroomlocationid     in number,
                                        fp_uniqueitemid               in uniqueitem.uniqueitem_id%type default null) is
      begin
        --create_stocktransaction
        gv_message := 'create_stocktransaction fp_stockreservationpergradeid ' ||
                      fp_stockreservationpergradeid;
        insert into stocktransaction
          (stocktransaction_id, stockreservationpergrade_id, transactiondate, reasoncode_id,
           transactiontype_id, uniquestock, quantity, systemuser_id, timestamp, exported, delayed,
           transactiontimestamp, fromstockroomlocation_id, tostockroomlocation_id, remark,
           documenttype, documentnumber, documentnumberprefix, stockvaluationmethod,
           calculationprice, uniqueitem_link_id)
        values
          (seq_stocktransaction.nextval, fp_stockreservationpergradeid, sysdate, gv_reasoncodeid,
           gv_transactiontypeid, fp_uniquestock, fp_quantity, fp_systemuserid, sysdate, 'N', 'N',
           sysdate, fp_from_stockroomlocationid, fp_to_stockroomlocationid,
           'ProductConversionWizard', 0 /*documenttype*/, 0 /*documentnumber*/, null
           /*documentnumberprefix*/, 0 /*stockvaluationmethod*/, 0 /*calculationprice*/,
           fp_uniqueitemid /*uniqueitem_link_id*/);
      end create_stocktransaction;

      procedure set_stock_to_0(fp_stockroomlocationid        in number,
                               fp_stockreservationpergradeid in number) is
      begin
        --set_stock_to_0
        /*Stock quantities from the source product are set to 0.*/
        gv_message := 'set_stock_to_0 fp_stockreservationpergradeid ' ||
                      fp_stockreservationpergradeid;
        update stockquantity q
        set    q.qtynonunique = 0, q.qtyuniquewithmodifications = 0, q.qtyunique = 0,
               q.systemuser_id = fp_systemuserid, q.timestamp = sysdate
        where  q.stockroomlocation_id = fp_stockroomlocationid
        and    q.stockreservationpergrade_id = fp_stockreservationpergradeid;
      end set_stock_to_0;
    begin
      --convert_stockroom_product
      gv_message := 'convert_stockroom_product';
      if gv_from_prodrecordpassstock = 'Y' then
        begin
          for sx in (select sdisource.stockroom_id, sdisource.customer_id, sdisource.customerowned,
                            sr.code stockroomcode, sdisource.sizedefinition_id,
                            sdisource.stockdefinitionperitem_id
                     from   stockdefinitionperitem sdisource
                     join  (stockroom sr
                     join   businessunit bu
                     on     (bu.businessunit_id = sr.managedbybu_id and
                            (fp_businessunitid is null or bu.businessunit_id = fp_businessunitid))) on (sr.stockroom_id = sdisource.stockroom_id)
                     where  sdisource.product_id = fp_from_productid
                     and    ((fp_from_sizedefinitionid is null) or
                           (sdisource.sizedefinition_id = fp_from_sizedefinitionid))
                     and    exists (select 1
                             from   businessunitsperusergroup buug
                             where  buug.businessunit_id = sr.managedbybu_id
                             and    buug.usergroup_id = gv_usergroupid)) loop
            begin
              if gv_to_prodrecordpassstock = 'Y' then
                begin
                  /*Stock is moved from source to destination product,
                  stock quantities from the source product are added to the destination product */
                  check_stdlocationperproduct(sx.stockroom_id, sx.stockroomcode, sx.customer_id,
                                              sx.customerowned);
                  if fp_to_sizedefinitionid is null then
                    --get_stockdefinitionperitem
                    lv_dest_stockdefperitemid := get_stockdefinitionperitem(sx.stockroom_id,
                                                                            fp_to_productid,
                                                                            sx.sizedefinition_id,
                                                                            sx.customer_id,
                                                                            sx.customerowned);
                  else
                    --get_stockdefinitionperitem
                    lv_dest_stockdefperitemid := get_stockdefinitionperitem(sx.stockroom_id,
                                                                            fp_to_productid,
                                                                            fp_to_sizedefinitionid,
                                                                            sx.customer_id,
                                                                            sx.customerowned);
                  end if;
                end;
              else
                begin
                  lv_dest_stockdefperitemid := null;
                end;
              end if;
              --loop source stockreservationpergrade
              for sy in (select srg.qualitygrade_id, srg.stockreservationpergrade_id,
                                srg.qtyuniqueordered, srg.qtynonuniqueordered,
                                srg.qtyuniqueordereddirectissue, srg.qtynonuniqueordereddirectissue
                         from   stockreservationpergrade srg
                         where  srg.stockdefinitionperitem_id = sx.stockdefinitionperitem_id) loop
                begin
                  if gv_to_prodrecordpassstock = 'Y' then
                    begin
                      --get_stockreservationpergrade
                      lv_dest_stockrespergradeid := get_stockreservationpergrade(lv_dest_stockdefperitemid,
                                                                                 sy.qualitygrade_id);
                    end;
                  else
                    begin
                      lv_dest_stockrespergradeid := null;
                    end;
                  end if;
                  --loop source stockquantity
                  for sz in (select sq.stockroomlocation_id, sq.qtyunique,
                                    sq.qtyuniquewithmodifications, sq.qtynonunique, srl.rowcode,
                                    srl.locationcode
                             from   stockquantity sq
                             join   stockroomlocation srl
                             on     srl.stockroomlocation_id = sq.stockroomlocation_id
                             where  sq.stockreservationpergrade_id = sy.stockreservationpergrade_id
                             and    (sq.qtyunique + sq.qtyuniquewithmodifications + sq.qtynonunique) > 0) loop
                    begin
                      if gv_to_prodrecordpassstock = 'Y' then
                        begin
                          update_stockquantity(sz.stockroomlocation_id, lv_dest_stockrespergradeid,
                                               sz.qtyunique, sz.qtyuniquewithmodifications,
                                               sz.qtynonunique);
                          --create stocktransaciton
                          if (sz.qtyunique + sz.qtyuniquewithmodifications) > 0 then
                            begin
                              --create_stocktransaction unique TO
                              create_stocktransaction(lv_dest_stockrespergradeid, 'Y',
                                                      (sz.qtyunique + sz.qtyuniquewithmodifications),
                                                      null, sz.stockroomlocation_id, null);
                            end;
                          end if;
                          if sz.qtynonunique > 0 then
                            begin
                              --create_stocktransaction non unique TO
                              create_stocktransaction(lv_dest_stockrespergradeid, 'N',
                                                      sz.qtynonunique, null, sz.stockroomlocation_id,
                                                      null);
                            end;
                          end if;
                        end;
                      end if;
                      /*Stock quantities from the source product are set to 0.*/
                      set_stock_to_0(sz.stockroomlocation_id, sy.stockreservationpergrade_id);
                      --create stocktransaciton
                      if (sz.qtyunique + sz.qtyuniquewithmodifications) > 0 then
                        begin
                          --create_stocktransaction unique FROM
                          create_stocktransaction(sy.stockreservationpergrade_id, 'Y',
                                                  (sz.qtyunique + sz.qtyuniquewithmodifications) * -1,
                                                  sz.stockroomlocation_id, null, null);
                        end;
                      end if;
                      if sz.qtynonunique > 0 then
                        begin
                          --create_stocktransaction non unique FROM
                          create_stocktransaction(sy.stockreservationpergrade_id, 'N',
                                                  sz.qtynonunique * -1, sz.stockroomlocation_id,
                                                  null, null);
                        end;
                      end if;
                      --write_log
                      write_log('Moved stock ' || sx.stockroomcode || ' from Row/Location ' ||
                                sz.rowcode || '/' || sz.locationcode || ' Quantity ' ||
                                (sz.qtyunique + sz.qtyuniquewithmodifications + sz.qtynonunique));
                    end;
                  end loop; --sz
                  --check ordered qty's
                  if (sy.qtyuniqueordered <> 0 or sy.qtynonuniqueordered <> 0 or
                     sy.qtyuniqueordereddirectissue <> 0 or sy.qtynonuniqueordereddirectissue <> 0) then
                    begin
                      write_log('There is outstanding ordered stock for  Stockroom ' ||
                                sx.stockroomcode || ' Source Product ' || gv_from_productcode ||
                                ' Source Size ' || gv_from_sizecode || ' please check', 3);
                    end;
                  end if;
                end;
              end loop; --sy
            end;
          end loop; --sx
        end;
      end if;
    end convert_stockroom_product;

    procedure update_workorders(fp_customerid customer.customer_id%type default null) is
      lv_new_stockdefperitemid    number;
      lv_new_stockreserpergradeid stockreservationpergrade.stockreservationpergrade_id%type;
    begin
      /*3.2.2 Work Orders
      Only change work orders with status 'New' or 'Waiting for Approval'
      Or (Status.Code = '20') // In progress
      Or (Status.Code = '25') // In progress with priority
      */
      gv_message := 'update_workorders';
      for wx in (select wo.deliverfrom, wol.workorderline_id, wo.processingstockroom_id,
                        wol.sizedefinition_link_id, wo.workordernumber
                 from   workorder wo
                 join   workorderline wol
                 on     wol.workorder_id = wo.workorder_id
                 join   businessunit bu
                 on     bu.businessunit_id = wo.businessunit_id
                 join   status
                 on     (wo.status_id = status.status_id and status.statustype = 'WO' and
                        status.code in ('05', '10', '15', '20', '25'))
                 where  wol.product_link_id = fp_from_productid
                 and    (fp_from_sizedefinitionid is null or
                       wol.sizedefinition_link_id = fp_from_sizedefinitionid)
                 and    (fp_businessunitid is null or bu.businessunit_id = fp_businessunitid)
                 and    exists (select 1
                         from   businessunitsperusergroup buug
                         where  buug.businessunit_id = wo.businessunit_id
                         and    buug.usergroup_id = gv_usergroupid)
                 and   (wo.customer_link_id = fp_customerid or fp_customerid is null))  loop
        begin
          if wx.deliverfrom = 2 then
            begin
              --loop workorderline reservations
              for wly in (select wolr.stockreservationpergrade_id, wolr.quantity, wolr.stocktype,
                                 sti.customer_id, sti.customerowned, srg.qualitygrade_id,
                                 srg.qtynonuniquereserved, srg.qtyuniquereserved,
                                 srg.qtyuniquewiithmodifreserved, wolr.sequencenumber
                          from   workorderlinereservation wolr
                          join   stockreservationpergrade srg
                          on     srg.stockreservationpergrade_id = wolr.stockreservationpergrade_id
                          join   stockdefinitionperitem sti
                          on     sti.stockdefinitionperitem_id = srg.stockdefinitionperitem_id
                          where  wolr.workorderline_id = wx.workorderline_id) loop
                begin
                  --update stockreservationpergrade old
                  gv_message := 'update stockreservationpergrade old';
                  update stockreservationpergrade srg
                  set    srg.qtynonuniquereserved = srg.qtynonuniquereserved - case
                                                      when wly.stocktype = 1 then
                                                       wly.quantity
                                                      else
                                                       0
                                                    end,
                         srg.qtyuniquereserved = srg.qtyuniquereserved - case
                                                   when wly.stocktype = 2 then
                                                    wly.quantity
                                                   else
                                                    0
                                                 end,
                         srg.qtyuniquewiithmodifreserved = srg.qtyuniquewiithmodifreserved - case
                                                             when wly.stocktype = 3 then
                                                              wly.quantity
                                                             else
                                                              0
                                                           end, srg.systemuser_id = fp_systemuserid,
                         srg.timestamp = sysdate
                  where  srg.stockreservationpergrade_id = wly.stockreservationpergrade_id;
                  --get new stockdefinition per item
                  lv_new_stockdefperitemid := get_stockdefinitionperitem(wx.processingstockroom_id,
                                                                         fp_to_productid,
                                                                         wx.sizedefinition_link_id,
                                                                         wly.customer_id,
                                                                         wly.customerowned);
                  --get new stockreservationpergrade
                  lv_new_stockreserpergradeid := get_stockreservationpergrade(lv_new_stockdefperitemid,
                                                                              wly.qualitygrade_id);
                  --update stockreservationpergrade new
                  gv_message := 'update stockreservationpergrade new';
                  update stockreservationpergrade srg
                  set    srg.qtynonuniquereserved = srg.qtynonuniquereserved + case
                                                      when wly.stocktype = 1 then
                                                       wly.quantity
                                                      else
                                                       0
                                                    end,
                         srg.qtyuniquereserved = srg.qtyuniquereserved + case
                                                   when wly.stocktype = 2 then
                                                    wly.quantity
                                                   else
                                                    0
                                                 end,
                         srg.qtyuniquewiithmodifreserved = srg.qtyuniquewiithmodifreserved + case
                                                             when wly.stocktype = 3 then
                                                              wly.quantity
                                                             else
                                                              0
                                                           end, srg.systemuser_id = fp_systemuserid,
                         srg.timestamp = sysdate
                  where  srg.stockreservationpergrade_id = lv_new_stockreserpergradeid;
                  --update workorderlinereservation
                  gv_message := 'update workorderlinereservation with new srg';
                  update workorderlinereservation wolr
                  set    wolr.stockreservationpergrade_id = lv_new_stockreserpergradeid,
                         wolr.timestamp = sysdate, wolr.systemuser_id = fp_systemuserid
                  where  wolr.workorderline_id = wx.workorderline_id
                  and    wolr.stockreservationpergrade_id = wly.stockreservationpergrade_id
                  and    wolr.stocktype = wly.stocktype
                  and    wolr.sequencenumber = wly.sequencenumber;
                end;
              end loop; --wx
            end;
          end if;
          --update workorderline
          gv_message := 'update workorderline';
          update workorderline wol
          set    wol.product_link_id = fp_to_productid,
                 wol.sizedefinition_link_id = nvl(fp_to_sizedefinitionid, wol.sizedefinition_link_id),
                 wol.systemuser_id = fp_systemuserid, wol.timestamp = sysdate
          where  wol.workorderline_id = wx.workorderline_id
          and    wol.product_link_id = fp_from_productid;
          --write log
          write_log('Changed Work Order ' || to_char(wx.workordernumber) || ' from product ' ||
                    gv_from_productcode);
        end;
      end loop; --wx
    end update_workorders;

    procedure update_purchaseorders(fp_customerid customer.customer_id%type default null) is

      procedure update_purchaseorderline is
        lv_counter number := 0;
      begin
        --update_purchaseorderline, 3.2.3 Purchase Orders
        gv_message := 'update_purchaseorders';
        update purchaseorderline pol
                set    pol.product_link_id = fp_to_productid,
                       pol.sizedefinition_link_id = nvl(fp_to_sizedefinitionid,
                                                         pol.sizedefinition_link_id),
                       pol.systemuser_id = fp_systemuserid, pol.timestamp = sysdate
                where  pol.product_link_id = fp_from_productid
                and    nvl(fp_from_sizedefinitionid, pol.sizedefinition_link_id) = pol.sizedefinition_link_id
                and    exists
                    (select 1
                           from   workorder wo
                           join   workorderline wol
                           on     wol.workorder_id = wo.workorder_id
                           join   businessunit bu
                           on     bu.businessunit_id = wo.businessunit_id
                           join   status
                           on     (wo.status_id = status.status_id and status.statustype = 'WO' and
                                  status.code in ('10', '15'))
                           where  wol.purchaseorderline_id = pol.purchaseorderline_id
                           and    (fp_businessunitid is null or bu.businessunit_id = fp_businessunitid)
                           and    exists (select 1
                                   from   businessunitsperusergroup buug
                                   where  buug.businessunit_id = wo.businessunit_id
                                   and    buug.usergroup_id = gv_usergroupid)
                           and     wo.customer_link_id = fp_customerid or fp_customerid is null
                           or      exists (select 1
                                           from purchaseorderheader poh
                                           where poh.purchaseorderheader_id = pol.purchaseorderheader_id
                                           and poh.supplier_id = gv_productsupplierid
                                           and (poh.customer_link_id = fp_customerid or fp_customerid is null)))
                 and      exists (select 1
                                           from purchaseorderheader poh
                                           where poh.purchaseorderheader_id = pol.purchaseorderheader_id
                                           and poh.supplier_id = gv_productsupplierid);
        if sql%rowcount > 0 then
          begin
            --write log
            write_log('Number of purchaseorders converted ' || lv_counter);
          end;
        end if;
      end update_purchaseorderline;

      procedure update_purchaserequest is
        lv_counter number := 0;
      begin
        --update_purchaserequest, 3.2.4 Purchase request
        gv_message := 'update_purchaserequest';
        for yp in (select por.purchaserequest_id, por.supplier_id
                   from   purchaserequest por
                   where  por.product_id = fp_from_productid
                   and    (por.sizedefinition_id = fp_from_sizedefinitionid or
                         fp_from_sizedefinitionid is null)
                   and    exists
                    (select 1
                           from   workorder wo
                           join   workorderline wol
                           on     wol.workorder_id = wo.workorder_id
                           join   businessunit bu
                           on     bu.businessunit_id = wo.businessunit_id
                           join   status
                           on     (wo.status_id = status.status_id and status.statustype = 'WO' and
                                  status.code in ('10', '15'))
                           where  wol.purchaserequest_id = por.purchaserequest_id
                           and    (fp_businessunitid is null or bu.businessunit_id = fp_businessunitid)
                           and    exists (select 1
                                   from   businessunitsperusergroup buug
                                   where  buug.businessunit_id = wo.businessunit_id
                                   and    buug.usergroup_id = gv_usergroupid))
                           and    (por.customer_id = fp_customerid or fp_customerid is null)) loop
          begin
            if nvl(yp.supplier_id, gv_productsupplierid) = gv_productsupplierid then
              begin
                --update purchaserequest
                update purchaserequest por
                set    por.product_id = fp_to_productid,
                       por.sizedefinition_id = nvl(fp_to_sizedefinitionid, por.sizedefinition_id),
                       por.systemuser_id = fp_systemuserid, por.timestamp = sysdate
                where  por.purchaserequest_id = yp.purchaserequest_id;
                --count purchaserequest
                lv_counter := lv_counter + 1;
              end;
            else
              begin
                --write in log that the POH cannot be converted!
                write_log('Purchase request id ' || yp.purchaserequest_id ||
                          ' is for a non default supplier and cannot be converted!');
              end;
            end if;
          end;
        end loop; --yp
        if lv_counter > 0 then
          begin
            --write log
            write_log('Number of Purchase request lines converted ' || lv_counter);
          end;
        end if;
      end update_purchaserequest;

      procedure update_supplierproduct is
      begin
        --update_supplierproduct
        update productsizepersupproduct pspp
        set    pspp.product_id = fp_to_productid,
               pspp.sizedefinition_id = nvl(fp_to_sizedefinitionid, pspp.sizedefinition_id),
               pspp.systemuser_id = fp_systemuserid, pspp.timestamp = sysdate
        where  pspp.product_id = fp_from_productid
        and    (pspp.sizedefinition_id = fp_from_sizedefinitionid or
              fp_from_sizedefinitionid is null)
        and    not exists
         (select 1
                from   productsizepersupproduct psppx
                where  psppx.supplierproduct_id = pspp.supplierproduct_id
                and    psppx.product_id = fp_to_productid
                and    psppx.sizedefinition_id = nvl(fp_to_sizedefinitionid, pspp.sizedefinition_id))
         and fp_selection = 'N';
        if sql%rowcount > 0 then
          begin
            --write log
            write_log('Number of Product to Supplier lines: ' || sql%rowcount || ' converted');
          end;
        end if;
      end update_supplierproduct;

      procedure upd_prodsizeaggsupplprodsize is
      begin
        --upd_prodsizeaggsupplprodsize
        gv_message := 'upd_prodsizeaggsupplprodsize';
        update prodsizeaggsupplprodsize psapp
        set    psapp.product_id = fp_to_productid,
               psapp.sizedefinition_id = nvl(fp_to_sizedefinitionid, psapp.sizedefinition_id),
               psapp.systemuser_id = fp_systemuserid, psapp.timestamp = sysdate
        where  psapp.product_id = fp_from_productid
        and    (psapp.sizedefinition_id = fp_from_sizedefinitionid or
              fp_from_sizedefinitionid is null)
        and    not exists
         (select 1
                from   prodsizeaggsupplprodsize psappx
                where  psappx.aggsupplierproductsize_id = psapp.aggsupplierproductsize_id
                and    psappx.product_id = fp_to_productid
                and    psappx.sizedefinition_id =
                       nvl(fp_to_sizedefinitionid, psapp.sizedefinition_id))
         and fp_selection = 'N';
        if sql%rowcount > 0 then
          begin
            --write log
            write_log('Number of Product to AGGSupplier lines: ' || sql%rowcount || ' converted');
          end;
        end if;
      end upd_prodsizeaggsupplprodsize;

      procedure update_backorders is
        --update_backorders internal procedures

        procedure upd_backorderwol is
        begin
          --upd_backorderwol
          update backorderwol bow
          set    bow.stockreservationpergrade_id =
                  (select srpg_new.stockreservationpergrade_id
                   from   stockreservationpergrade srold
                   join   stockdefinitionperitem sdi_old
                   on     sdi_old.stockdefinitionperitem_id = srold.stockdefinitionperitem_id
                   join  (stockroom sr
                   join   businessunit bu
                   on     (bu.businessunit_id = sr.managedbybu_id and
                          (fp_businessunitid is null or bu.businessunit_id = fp_businessunitid))) on (sr.stockroom_id = sdi_old.stockroom_id)
                   join   stockreservationpergrade srpg_new
                   on     srpg_new.qualitygrade_id = srold.qualitygrade_id
                   join   stockdefinitionperitem sdi_new
                   on     sdi_new.stockdefinitionperitem_id = srpg_new.stockdefinitionperitem_id
                   and    sdi_new.stockroom_id = sdi_old.stockroom_id
                   and    sdi_new.customerowned = sdi_old.customerowned
                   and    ((sdi_new.customer_id is null and sdi_old.customer_id is null) or
                         (sdi_new.customer_id = sdi_old.customer_id))
                   where  srold.stockreservationpergrade_id = bow.stockreservationpergrade_id
                   and    sdi_old.product_id = fp_from_productid
                   and    (fp_from_sizedefinitionid = sdi_old.sizedefinition_id or
                         fp_from_sizedefinitionid is null)
                   and    sdi_new.product_id = fp_to_productid
                   and    (sdi_new.sizedefinition_id = fp_to_sizedefinitionid or
                         (fp_to_sizedefinitionid is null and
                         sdi_new.sizedefinition_id = sdi_old.sizedefinition_id))
                   and    exists (select 1
                           from   businessunitsperusergroup buug
                           where  buug.businessunit_id = sr.managedbybu_id
                           and    buug.usergroup_id = gv_usergroupid)),
                 bow.systemuser_id = fp_systemuserid, bow.timestamp = sysdate
          where  exists
           (select srpg_new.stockreservationpergrade_id
                  from   stockreservationpergrade srold
                  join   stockdefinitionperitem sdi_old
                  on     sdi_old.stockdefinitionperitem_id = srold.stockdefinitionperitem_id
                  join  (stockroom sr
                  join   businessunit bu
                  on     (bu.businessunit_id = sr.managedbybu_id and
                         (fp_businessunitid is null or bu.businessunit_id = fp_businessunitid))) on (sr.stockroom_id = sdi_old.stockroom_id)
                  join   stockreservationpergrade srpg_new
                  on     srpg_new.qualitygrade_id = srold.qualitygrade_id
                  join   stockdefinitionperitem sdi_new
                  on     sdi_new.stockdefinitionperitem_id = srpg_new.stockdefinitionperitem_id
                  and    sdi_new.stockroom_id = sdi_old.stockroom_id
                  and    sdi_new.customerowned = sdi_old.customerowned
                  and    ((sdi_new.customer_id is null and sdi_old.customer_id is null) or
                        (sdi_new.customer_id = sdi_old.customer_id))
                  where  srold.stockreservationpergrade_id = bow.stockreservationpergrade_id
                  and    sdi_old.product_id = fp_from_productid
                  and    (fp_from_sizedefinitionid = sdi_old.sizedefinition_id or
                        fp_from_sizedefinitionid is null)
                  and    sdi_new.product_id = fp_to_productid
                  and    (sdi_new.sizedefinition_id = fp_to_sizedefinitionid or
                        (fp_to_sizedefinitionid is null and
                        sdi_new.sizedefinition_id = sdi_old.sizedefinition_id))
                  and    exists (select 1
                          from   businessunitsperusergroup buug
                          where  buug.businessunit_id = sr.managedbybu_id
                          and    buug.usergroup_id = gv_usergroupid))
                  and   fp_selection = 'N';
          if sql%rowcount > 0 then
            begin
              --write log
              write_log('Number of Product of Back OrderWOL: ' || sql%rowcount || ' converted');
            end;
          end if;
        end upd_backorderwol;

        procedure upd_backorderwole is
        begin
          --upd_backorderwole
          update backorderwole bowe
          set    bowe.stockreservationpergrade_id =
                  (select srpg_new.stockreservationpergrade_id
                   from   stockreservationpergrade srold
                   join   stockdefinitionperitem sdi_old
                   on     sdi_old.stockdefinitionperitem_id = srold.stockdefinitionperitem_id
                   join  (stockroom sr
                   join   businessunit bu
                   on     (bu.businessunit_id = sr.managedbybu_id and
                          (fp_businessunitid is null or bu.businessunit_id = fp_businessunitid))) on (sr.stockroom_id = sdi_old.stockroom_id)
                   join   stockreservationpergrade srpg_new
                   on     srpg_new.qualitygrade_id = srold.qualitygrade_id
                   join   stockdefinitionperitem sdi_new
                   on     sdi_new.stockdefinitionperitem_id = srpg_new.stockdefinitionperitem_id
                   and    sdi_new.stockroom_id = sdi_old.stockroom_id
                   and    sdi_new.customerowned = sdi_old.customerowned
                   and    ((sdi_new.customer_id is null and sdi_old.customer_id is null) or
                         (sdi_new.customer_id = sdi_old.customer_id))
                   where  srold.stockreservationpergrade_id = bowe.stockreservationpergrade_id
                   and    sdi_old.product_id = fp_from_productid
                   and    (fp_from_sizedefinitionid = sdi_old.sizedefinition_id or
                         fp_from_sizedefinitionid is null)
                   and    sdi_new.product_id = fp_to_productid
                   and    (sdi_new.sizedefinition_id = fp_to_sizedefinitionid or
                         (fp_to_sizedefinitionid is null and
                         sdi_new.sizedefinition_id = sdi_old.sizedefinition_id))
                   and    exists (select 1
                           from   businessunitsperusergroup buug
                           where  buug.businessunit_id = sr.managedbybu_id
                           and    buug.usergroup_id = gv_usergroupid)),
                 bowe.systemuser_id = fp_systemuserid, bowe.timestamp = sysdate
          where  exists
           (select srpg_new.stockreservationpergrade_id
                  from   stockreservationpergrade srold
                  join   stockdefinitionperitem sdi_old
                  on     sdi_old.stockdefinitionperitem_id = srold.stockdefinitionperitem_id
                  join  (stockroom sr
                  join   businessunit bu
                  on     (bu.businessunit_id = sr.managedbybu_id and
                         (fp_businessunitid is null or bu.businessunit_id = fp_businessunitid))) on (sr.stockroom_id = sdi_old.stockroom_id)
                  join   stockreservationpergrade srpg_new
                  on     srpg_new.qualitygrade_id = srold.qualitygrade_id
                  join   stockdefinitionperitem sdi_new
                  on     sdi_new.stockdefinitionperitem_id = srpg_new.stockdefinitionperitem_id
                  and    sdi_new.stockroom_id = sdi_old.stockroom_id
                  and    sdi_new.customerowned = sdi_old.customerowned
                  and    ((sdi_new.customer_id is null and sdi_old.customer_id is null) or
                        (sdi_new.customer_id = sdi_old.customer_id))
                  where  srold.stockreservationpergrade_id = bowe.stockreservationpergrade_id
                  and    sdi_old.product_id = fp_from_productid
                  and    (fp_from_sizedefinitionid = sdi_old.sizedefinition_id or
                        fp_from_sizedefinitionid is null)
                  and    sdi_new.product_id = fp_to_productid
                  and    (sdi_new.sizedefinition_id = fp_to_sizedefinitionid or
                        (fp_to_sizedefinitionid is null and
                        sdi_new.sizedefinition_id = sdi_old.sizedefinition_id))
                  and    exists (select 1
                          from   businessunitsperusergroup buug
                          where  buug.businessunit_id = sr.managedbybu_id
                          and    buug.usergroup_id = gv_usergroupid))
                 and fp_selection = 'N';
          if sql%rowcount > 0 then
            begin
              --write log
              write_log('Number of Product of Back OrderWOLE: ' || sql%rowcount || ' converted');
            end;
          end if;
        end upd_backorderwole;

        procedure upd_backorderallocationwol is
        begin
          --upd_backorderallocationwol
          update backorderallocationwol bow
          set    bow.stockreservationpergrade_id =
                  (select srpg_new.stockreservationpergrade_id
                   from   stockreservationpergrade srold
                   join   stockdefinitionperitem sdi_old
                   on     sdi_old.stockdefinitionperitem_id = srold.stockdefinitionperitem_id
                   join  (stockroom sr
                   join   businessunit bu
                   on     (bu.businessunit_id = sr.managedbybu_id and
                          (fp_businessunitid is null or bu.businessunit_id = fp_businessunitid))) on (sr.stockroom_id = sdi_old.stockroom_id)
                   join   stockreservationpergrade srpg_new
                   on     srpg_new.qualitygrade_id = srold.qualitygrade_id
                   join   stockdefinitionperitem sdi_new
                   on     sdi_new.stockdefinitionperitem_id = srpg_new.stockdefinitionperitem_id
                   and    sdi_new.stockroom_id = sdi_old.stockroom_id
                   and    sdi_new.customerowned = sdi_old.customerowned
                   and    ((sdi_new.customer_id is null and sdi_old.customer_id is null) or
                         (sdi_new.customer_id = sdi_old.customer_id))
                   where  srold.stockreservationpergrade_id = bow.stockreservationpergrade_id
                   and    sdi_old.product_id = fp_from_productid
                   and    (fp_from_sizedefinitionid = sdi_old.sizedefinition_id or
                         fp_from_sizedefinitionid is null)
                   and    sdi_new.product_id = fp_to_productid
                   and    (sdi_new.sizedefinition_id = fp_to_sizedefinitionid or
                         (fp_to_sizedefinitionid is null and
                         sdi_new.sizedefinition_id = sdi_old.sizedefinition_id))
                   and    exists (select 1
                           from   businessunitsperusergroup buug
                           where  buug.businessunit_id = sr.managedbybu_id
                           and    buug.usergroup_id = gv_usergroupid)),
                 bow.systemuser_id = fp_systemuserid, bow.timestamp = sysdate
          where  exists
           (select srpg_new.stockreservationpergrade_id
                  from   stockreservationpergrade srold
                  join   stockdefinitionperitem sdi_old
                  on     sdi_old.stockdefinitionperitem_id = srold.stockdefinitionperitem_id
                  join  (stockroom sr
                  join   businessunit bu
                  on     (bu.businessunit_id = sr.managedbybu_id and
                         (fp_businessunitid is null or bu.businessunit_id = fp_businessunitid))) on (sr.stockroom_id = sdi_old.stockroom_id)
                  join   stockreservationpergrade srpg_new
                  on     srpg_new.qualitygrade_id = srold.qualitygrade_id
                  join   stockdefinitionperitem sdi_new
                  on     sdi_new.stockdefinitionperitem_id = srpg_new.stockdefinitionperitem_id
                  and    sdi_new.stockroom_id = sdi_old.stockroom_id
                  and    sdi_new.customerowned = sdi_old.customerowned
                  and    ((sdi_new.customer_id is null and sdi_old.customer_id is null) or
                        (sdi_new.customer_id = sdi_old.customer_id))
                  where  srold.stockreservationpergrade_id = bow.stockreservationpergrade_id
                  and    sdi_old.product_id = fp_from_productid
                  and    (fp_from_sizedefinitionid = sdi_old.sizedefinition_id or
                        fp_from_sizedefinitionid is null)
                  and    sdi_new.product_id = fp_to_productid
                  and    (sdi_new.sizedefinition_id = fp_to_sizedefinitionid or
                        (fp_to_sizedefinitionid is null and
                        sdi_new.sizedefinition_id = sdi_old.sizedefinition_id))
                  and    exists (select 1
                          from   businessunitsperusergroup buug
                          where  buug.businessunit_id = sr.managedbybu_id
                          and    buug.usergroup_id = gv_usergroupid))
                 and fp_selection = 'N';
          if sql%rowcount > 0 then
            begin
              --write log
              write_log('Number of Product of Back Order Allocation WOL:  ' || sql%rowcount ||
                        ' converted');
            end;
          end if;
        end upd_backorderallocationwol;

        procedure upd_backorderallocationwole is
        begin
          --upd_backorderallocationwole
          update backorderallocationwole bowe
          set    bowe.stockreservationpergrade_id =
                  (select srpg_new.stockreservationpergrade_id
                   from   stockreservationpergrade srold
                   join   stockdefinitionperitem sdi_old
                   on     sdi_old.stockdefinitionperitem_id = srold.stockdefinitionperitem_id
                   join  (stockroom sr
                   join   businessunit bu
                   on     (bu.businessunit_id = sr.managedbybu_id and
                          (fp_businessunitid is null or bu.businessunit_id = fp_businessunitid))) on (sr.stockroom_id = sdi_old.stockroom_id)
                   join   stockreservationpergrade srpg_new
                   on     srpg_new.qualitygrade_id = srold.qualitygrade_id
                   join   stockdefinitionperitem sdi_new
                   on     sdi_new.stockdefinitionperitem_id = srpg_new.stockdefinitionperitem_id
                   and    sdi_new.stockroom_id = sdi_old.stockroom_id
                   and    sdi_new.customerowned = sdi_old.customerowned
                   and    ((sdi_new.customer_id is null and sdi_old.customer_id is null) or
                         (sdi_new.customer_id = sdi_old.customer_id))
                   where  srold.stockreservationpergrade_id = bowe.stockreservationpergrade_id
                   and    sdi_old.product_id = fp_from_productid
                   and    (fp_from_sizedefinitionid = sdi_old.sizedefinition_id or
                         fp_from_sizedefinitionid is null)
                   and    sdi_new.product_id = fp_to_productid
                   and    (sdi_new.sizedefinition_id = fp_to_sizedefinitionid or
                         (fp_to_sizedefinitionid is null and
                         sdi_new.sizedefinition_id = sdi_old.sizedefinition_id))
                   and    exists (select 1
                           from   businessunitsperusergroup buug
                           where  buug.businessunit_id = sr.managedbybu_id
                           and    buug.usergroup_id = gv_usergroupid)),
                 bowe.systemuser_id = fp_systemuserid, bowe.timestamp = sysdate
          where  exists
           (select srpg_new.stockreservationpergrade_id
                  from   stockreservationpergrade srold
                  join   stockdefinitionperitem sdi_old
                  on     sdi_old.stockdefinitionperitem_id = srold.stockdefinitionperitem_id
                  join  (stockroom sr
                  join   businessunit bu
                  on     (bu.businessunit_id = sr.managedbybu_id and
                         (fp_businessunitid is null or bu.businessunit_id = fp_businessunitid))) on (sr.stockroom_id = sdi_old.stockroom_id)
                  join   stockreservationpergrade srpg_new
                  on     srpg_new.qualitygrade_id = srold.qualitygrade_id
                  join   stockdefinitionperitem sdi_new
                  on     sdi_new.stockdefinitionperitem_id = srpg_new.stockdefinitionperitem_id
                  and    sdi_new.stockroom_id = sdi_old.stockroom_id
                  and    sdi_new.customerowned = sdi_old.customerowned
                  and    ((sdi_new.customer_id is null and sdi_old.customer_id is null) or
                        (sdi_new.customer_id = sdi_old.customer_id))
                  where  srold.stockreservationpergrade_id = bowe.stockreservationpergrade_id
                  and    sdi_old.product_id = fp_from_productid
                  and    (fp_from_sizedefinitionid = sdi_old.sizedefinition_id or
                        fp_from_sizedefinitionid is null)
                  and    sdi_new.product_id = fp_to_productid
                  and    (sdi_new.sizedefinition_id = fp_to_sizedefinitionid or
                        (fp_to_sizedefinitionid is null and
                        sdi_new.sizedefinition_id = sdi_old.sizedefinition_id))
                  and    exists (select 1
                          from   businessunitsperusergroup buug
                          where  buug.businessunit_id = sr.managedbybu_id
                          and    buug.usergroup_id = gv_usergroupid))
                  and fp_selection = 'N';
          if sql%rowcount > 0 then
            begin
              --write log
              write_log('Number of Product of Back Order Allocation WOLE: ' || sql%rowcount ||
                        ' converted');
            end;
          end if;
        end upd_backorderallocationwole;

        procedure upd_purchaserequisition is
        begin
          --upd_purchaserequisition
          --upd_purchaserequisition
          update purchaserequisition prq
          set    prq.stockreservationpergrade_id =
                  (select srpg_new.stockreservationpergrade_id
                   from   stockreservationpergrade srold
                   join   stockdefinitionperitem sdi_old
                   on     sdi_old.stockdefinitionperitem_id = srold.stockdefinitionperitem_id
                   join  (stockroom sr
                   join   businessunit bu
                   on     (bu.businessunit_id = sr.managedbybu_id and
                          (fp_businessunitid is null or bu.businessunit_id = fp_businessunitid))) on (sr.stockroom_id = sdi_old.stockroom_id)
                   join   stockreservationpergrade srpg_new
                   on     srpg_new.qualitygrade_id = srold.qualitygrade_id
                   join   stockdefinitionperitem sdi_new
                   on     sdi_new.stockdefinitionperitem_id = srpg_new.stockdefinitionperitem_id
                   and    sdi_new.stockroom_id = sdi_old.stockroom_id
                   and    sdi_new.customerowned = sdi_old.customerowned
                   and    ((sdi_new.customer_id is null and sdi_old.customer_id is null) or
                         (sdi_new.customer_id = sdi_old.customer_id))
                   where  srold.stockreservationpergrade_id = prq.stockreservationpergrade_id
                   and    sdi_old.product_id = fp_from_productid
                   and    (fp_from_sizedefinitionid = sdi_old.sizedefinition_id or
                         fp_from_sizedefinitionid is null)
                   and    sdi_new.product_id = fp_to_productid
                   and    (sdi_new.sizedefinition_id = fp_to_sizedefinitionid or
                         (fp_to_sizedefinitionid is null and
                         sdi_new.sizedefinition_id = sdi_old.sizedefinition_id))
                   and    exists (select 1
                           from   businessunitsperusergroup buug
                           where  buug.businessunit_id = sr.managedbybu_id
                           and    buug.usergroup_id = gv_usergroupid)),
                 prq.systemuser_id = fp_systemuserid, prq.timestamp = sysdate
          where  exists
           (select srpg_new.stockreservationpergrade_id
                  from   stockreservationpergrade srold
                  join   stockdefinitionperitem sdi_old
                  on     sdi_old.stockdefinitionperitem_id = srold.stockdefinitionperitem_id
                  join  (stockroom sr
                  join   businessunit bu
                  on     (bu.businessunit_id = sr.managedbybu_id and
                         (fp_businessunitid is null or bu.businessunit_id = fp_businessunitid))) on (sr.stockroom_id = sdi_old.stockroom_id)
                  join   stockreservationpergrade srpg_new
                  on     srpg_new.qualitygrade_id = srold.qualitygrade_id
                  join   stockdefinitionperitem sdi_new
                  on     sdi_new.stockdefinitionperitem_id = srpg_new.stockdefinitionperitem_id
                  and    sdi_new.stockroom_id = sdi_old.stockroom_id
                  and    sdi_new.customerowned = sdi_old.customerowned
                  and    ((sdi_new.customer_id is null and sdi_old.customer_id is null) or
                        (sdi_new.customer_id = sdi_old.customer_id))
                  where  srold.stockreservationpergrade_id = prq.stockreservationpergrade_id
                  and    sdi_old.product_id = fp_from_productid
                  and    (fp_from_sizedefinitionid = sdi_old.sizedefinition_id or
                        fp_from_sizedefinitionid is null)
                  and    sdi_new.product_id = fp_to_productid
                  and    (sdi_new.sizedefinition_id = fp_to_sizedefinitionid or
                        (fp_to_sizedefinitionid is null and
                        sdi_new.sizedefinition_id = sdi_old.sizedefinition_id))
                  and    exists (select 1
                          from   businessunitsperusergroup buug
                          where  buug.businessunit_id = sr.managedbybu_id
                          and    buug.usergroup_id = gv_usergroupid))
                  and   (prq.customer_id = fp_customerid or fp_customerid is null);
          if sql%rowcount > 0 then
            begin
              --write log
              write_log('Number of Purchase Requisition Lines converted: ' || sql%rowcount ||
                        ' converted');
            end;
          end if;
        end upd_purchaserequisition;
      begin
        --update_backorders
        gv_message := 'update_backorders';
        --upd_backorderwol
        upd_backorderwol;
        --upd_backorderwole
        upd_backorderwole;
        --upd_backorderallocationwol
        upd_backorderallocationwol;
        --upd_backorderallocationwole
        upd_backorderallocationwole;
        --upd_purchaserequisition
        upd_purchaserequisition;
        --remark purchaserequestallocation is NOT needed 23-5-2017 (Phil, RVI).
      end update_backorders;
    begin
      --update_purchaseorderline, 3.2.3 Purchase Orders
      update_purchaseorderline;
      --update_purchaserequest, 3.2.4 Purchase request
      update_purchaserequest;
      --3.2.5 Product to Supplier Product Link
      update_supplierproduct;
      --upd_prodsizeaggsupplprodsize
      upd_prodsizeaggsupplprodsize;
      --3.2.6 Back Order tables (Advance Purchasing)
      update_backorders;
    end update_purchaseorders;

    procedure update_uniqueitems(fp_customerid customer.customer_id%type default null) is
    begin
      --create scans
      gv_message := 'create scans';
      insert into scan
        (scan_id, businessunit_id, scantimestamp, primaryid, customer_link_id,
         weareremployment_link_id, distributionpoint_link_id, product_link_id,
         sizedefinition_link_id, stay_id, status_id, scanstation, issuedate, route_id, reasoncode_id,
         customerowned, year, week, dayno, qualitygrade_id, systemuser_id, timestamp, prevstay_id,
         transactiontype_id, dayslate, uniqueitem_link_id, secondaryid, batchnumber, scandateoffset,
         qualitytesttype_id, washingprocess_id, treatmenttype_id, deliverynotenumber)
        select seq_scan.nextval, u.businessunit_id, sysdate /*scantimestamp*/, u.primaryid,
               coalesce(unwew.w_customer_id, dipdelp.delp_customer_id) /*customer_link_id*/,
               unwew.we_weareremployment_id, u.distributionpoint_id, fp_to_productid,
               nvl(fp_to_sizedefinitionid, u.sizedefinition_id) /*sizedefinition_link_id*/,
               u.stay_id, u.status_id, 'prodconvwiz' /*scanstation*/, uf.lastissuedate, null
               /*route_id*/, gv_reasoncodeid, u.customerowned, getyearofweek(sysdate) /*year*/,
               getisoweek(sysdate) /*week*/, getabsdaynumber(sysdate) /*dayno*/, uf.qualitygrade_id,
               fp_systemuserid, sysdate /*timestamp*/, u.prevstay_id, gv_transactiontypeid, 0
               /*dayslate*/, u.uniqueitem_id,
               (select su.secondaryid
                 from   secondaryuniqueitem su
                 where  su.uniqueitem_id = u.uniqueitem_id) /*secondaryid*/, null /*batchnumber*/, 0
               /*scandateoffset*/, null /*qualitytesttype_id*/, null /*washingprocess_id*/, null
               /*treatmenttype_id*/, null /*deliverynotenumber*/
        from   uniqueitem u
        join   uniqueitemfixedinfo uf
        on     uf.uniqueitem_id = u.uniqueitem_id
        left outer join (
                        select dip.distributionpoint_id, delp.customer_id AS delp_customer_id
                          from distributionpoint dip
                          join deliverypoint delp on delp.deliverypoint_id = dip.deliverypoint_id) dipdelp
                     on dipdelp.distributionpoint_id = u.distributionpoint_id
        left outer join (
                        select un.uniqueitem_id, we.weareremployment_id AS we_weareremployment_id, w.customer_id AS w_customer_id
                          from uniqueitemnonpool un
                          join weareremployment we on we.weareremployment_id = un.weareremployment_id
                          join wearer w on w.wearer_id = we.wearer_id) unwew
                     on unwew.uniqueitem_id = u.uniqueitem_id
        where  u.product_id = fp_from_productid
        and    (u.sizedefinition_id = fp_from_sizedefinitionid or fp_from_sizedefinitionid is null)
        and    exists (select 1
                from   businessunit bu
                where  bu.businessunit_id = u.businessunit_id
                and    (bu.businessunit_id = fp_businessunitid or fp_businessunitid is null))
        and    exists (select 1
                from   businessunitsperusergroup bug
                where  bug.businessunit_id = u.businessunit_id
                and    bug.usergroup_id = gv_usergroupid)
        and   ((coalesce(unwew.w_customer_id, dipdelp.delp_customer_id) = fp_customerid) or (fp_customerid is null));
      -- update_uniqueitems
      gv_message := 'update_uniqueitems';
      update uniqueitem u
      set    u.product_id = fp_to_productid,
             u.sizedefinition_id = nvl(fp_to_sizedefinitionid, u.sizedefinition_id),
             u.timestamp = sysdate, u.systemuser_id = fp_systemuserid
      where  u.product_id = fp_from_productid
      and    nvl(fp_from_sizedefinitionid, u.sizedefinition_id) = u.sizedefinition_id
      and    exists (select 1
              from   businessunit bu
              where  bu.businessunit_id = u.businessunit_id
              and    (bu.businessunit_id = fp_businessunitid or fp_businessunitid is null))
      and    exists (select 1
              from   businessunitsperusergroup bug
              where  bug.businessunit_id = u.businessunit_id
              and    bug.usergroup_id = gv_usergroupid)
      and    ((fp_customerid is null) or exists (select 1
                                                from uniqueitemfixedinfo uif
                                                left outer join (
                                                    select dip.distributionpoint_id, delp.customer_id AS delp_customer_id
                                                      from distributionpoint dip
                                                      join deliverypoint delp on delp.deliverypoint_id = dip.deliverypoint_id) dipdelp
                                                  on dipdelp.distributionpoint_id = u.distributionpoint_id
                                                left outer join (
                                                    select un.uniqueitem_id, w.customer_id AS w_customer_id
                                                      from uniqueitemnonpool un
                                                      join weareremployment we on we.weareremployment_id = un.weareremployment_id
                                                      join wearer w on w.wearer_id = we.wearer_id) unwew
                                                  on unwew.uniqueitem_id = u.uniqueitem_id
                                                where  (coalesce(unwew.w_customer_id, dipdelp.delp_customer_id) = fp_customerid)
                                                and uif.uniqueitem_id = u.uniqueitem_id));

      if sql%rowcount > 0 then
        begin
          --write log
          write_log('Number of unique items ' || sql%rowcount || ' converted ');
        end;
      end if;
    end update_uniqueitems;

    procedure update_deliveryscans(fp_customerid customer.customer_id%type default null) is
    begin
      --update_deliveryscans
      gv_message := 'update_deliveryscans';
      update deliveryscan ds
      set    ds.product_link_id = fp_to_productid,
             ds.sizedefinition_link_id = nvl(fp_to_sizedefinitionid, ds.sizedefinition_link_id),
             ds.timestamp = sysdate, ds.systemuser_id = fp_systemuserid
      where  ds.product_link_id = fp_from_productid
      and    (ds.sizedefinition_link_id = fp_from_sizedefinitionid or
            fp_from_sizedefinitionid is null)
      and    nvl(ds.packingnote_id, 0) in (select pkl.packingnote_id
                                           from   packingnoteline pkl
                                           where  nvl(pkl.invoiceheader_id, 0) = 0
                                           union
                                           select 0
                                           from   dual)
      and    (ds.businessunit_id = fp_businessunitid or fp_businessunitid is null)
      and    ds.scantimestamp >= trunc(sysdate - 30)
      and    exists (select 1
              from   businessunitsperusergroup bug
              where  bug.businessunit_id = ds.businessunit_id
              and    bug.usergroup_id = gv_usergroupid)
      and     (ds.customer_link_id = fp_customerid or fp_customerid is null) ;
      if sql%rowcount > 0 then
        begin
          --write log
          write_log('Number of delivery scans converted ' || sql%rowcount);
        end;
      end if;
    end update_deliveryscans;

    procedure copy_plpc_prices_discounts(fp_customernumber in customer.customernumber%type,
                                         fp_new_plpc_rec   in productlistpercustomer%rowtype,
                                         fp_old_plpc_rec   in productlistpercustomer%rowtype,
                                         fp_new_sizecode   in varchar2) is
      --PRICES
      procedure copy_customerwashprice is
      begin
        --WASH, copy_customerwashprice
        gv_message := 'Copy PLPC Wash prices for Customer ' || fp_customernumber;
        for cwz in (select case
                             when cwp.startdate < trunc(sysdate) then
                              trunc(sysdate)
                             else
                              cwp.startdate
                           end startdate, cwp.price, cwp.pricetype
                    from   customerwashprice cwp
                    where  cwp.productlistpercustomer_id = fp_old_plpc_rec.productlistpercustomer_id
                    and    cwp.startdate >=
                           coalesce((select max(cw.startdate) startdate
                                     from   customerwashprice cw
                                     where  cw.productlistpercustomer_id =
                                            cwp.productlistpercustomer_id
                                     and    cw.startdate <= trunc(sysdate)
                                     and    cw.pricetype = cwp.pricetype), trunc(sysdate))
                    and    not exists (select 1
                            from   customerwashprice x
                            where  x.productlistpercustomer_id =
                                   fp_new_plpc_rec.productlistpercustomer_id
                            and    x.pricetype = cwp.pricetype)) loop
          begin
            --copy actual Wash line
            insert into customerwashprice
              (customerwashprice_id, productlistpercustomer_id, timestamp, systemuser_id, price,
               startdate, pricetype)
            values
              (seq_customerwashprice.nextval, fp_new_plpc_rec.productlistpercustomer_id, sysdate,
               fp_systemuserid, cwz.price, cwz.startdate, cwz.pricetype);
            --write log
            write_log('Created Customer Wash Price, for Customer ' || fp_customernumber ||
                      ' for product ' || gv_to_productcode || ' size ' || fp_new_sizecode ||
                      ' startdate ' || to_char(cwz.startdate, 'DD-MON-YYYY'));
          end;
        end loop; --cwz wash
      end copy_customerwashprice;

      procedure copy_customerwashdiscount is
      begin
        --WASH,copy_customerwashdiscount
        gv_message := 'Copy PLPC Wash discounts for Customer ' || fp_customernumber;
        for cwz in (select case
                             when cwp.startdate < trunc(sysdate) then
                              trunc(sysdate)
                             else
                              cwp.startdate
                           end startdate, cwp.discount
                    from   customerwashdiscount cwp
                    where  cwp.productlistpercustomer_id = fp_old_plpc_rec.productlistpercustomer_id
                    and    cwp.startdate >=
                           coalesce((select max(cw.startdate) startdate
                                     from   customerwashdiscount cw
                                     where  cw.productlistpercustomer_id =
                                            cwp.productlistpercustomer_id
                                     and    cw.startdate <= trunc(sysdate)), trunc(sysdate))
                    and    not exists (select 1
                            from   customerwashdiscount x
                            where  x.productlistpercustomer_id =
                                   fp_new_plpc_rec.productlistpercustomer_id)) loop
          begin
            --copy Wash discount
            insert into customerwashdiscount
              (customerwashdiscount_id, productlistpercustomer_id, timestamp, systemuser_id,
               discount, startdate)
            values
              (seq_customerwashdiscount.nextval, fp_new_plpc_rec.productlistpercustomer_id, sysdate,
               fp_systemuserid, cwz.discount, cwz.startdate);
            --write log
            write_log('Created Customer Wash Discount, for Customer ' || fp_customernumber ||
                      ' for product ' || gv_to_productcode || ' size ' || fp_new_sizecode ||
                      ' startdate ' || to_char(cwz.startdate, 'DD-MON-YYYY'));
          end;
        end loop; --cwz wash
      end copy_customerwashdiscount;

      procedure copy_customerrentprice is
      begin
        --RENT
        gv_message := 'Copy PLPC Rent prices for Customer ' || fp_customernumber;
        ---PRODUCTLISTPERCUSTOMER_ID, STARTDATE, CHANGESPERWEEK, TYPEOFRENT, INVOICEFREQUENCYNUMBER
        for cwz in (select case
                             when cwp.startdate < trunc(sysdate) then
                              trunc(sysdate)
                             else
                              cwp.startdate
                           end startdate, cwp.price, cwp.changesperweek, cwp.typeofrent,
                           cwp.invoicefrequencynumber,
                           cwp.sizebillinggroup_id,
                           cwp.contractcoefficient,
                           cwp.maxinventory
                    from   customerrentprice cwp
                    where  cwp.productlistpercustomer_id = fp_old_plpc_rec.productlistpercustomer_id
                    and    cwp.startdate >=
                           coalesce((select max(cw.startdate) startdate
                                     from   customerrentprice cw
                                     where  cw.productlistpercustomer_id =
                                            cwp.productlistpercustomer_id
                                     and    cw.startdate <= trunc(sysdate)
                                     and    cw.changesperweek = cwp.changesperweek
                                     and    cw.typeofrent = cwp.typeofrent
                                     and    cw.invoicefrequencynumber = cwp.invoicefrequencynumber
                                     and    nvl(cw.sizebillinggroup_id,0) = nvl(cwp.sizebillinggroup_id,0)
                                     and    nvl(cw.maxinventory,0) = nvl(cwp.maxinventory,0)),
                                     trunc(sysdate))
                    and    not exists
                     (select 1
                            from   customerrentprice x
                            where  x.productlistpercustomer_id =
                                   fp_new_plpc_rec.productlistpercustomer_id
                            and    x.changesperweek = cwp.changesperweek
                            and    x.typeofrent = cwp.typeofrent
                            and    x.invoicefrequencynumber = cwp.invoicefrequencynumber
                            and    nvl(x.sizebillinggroup_id,0) = nvl(cwp.sizebillinggroup_id,0)
                            and    nvl(x.maxinventory,0) = nvl(cwp.maxinventory,0))) loop
          begin
            --copy actual rent line
            insert into customerrentprice
              (customerrentprice_id, productlistpercustomer_id, timestamp, systemuser_id, price,
               startdate, changesperweek, typeofrent, invoicefrequencynumber, sizebillinggroup_id, contractcoefficient, maxinventory)
            values
              (seq_customerrentprice.nextval, fp_new_plpc_rec.productlistpercustomer_id, sysdate
               /*timestamp*/, fp_systemuserid, cwz.price, cwz.startdate, cwz.changesperweek,
               cwz.typeofrent, cwz.invoicefrequencynumber, cwz.sizebillinggroup_id, cwz.contractcoefficient, cwz.maxinventory);
            --write log
            write_log('Created Customer Rent Price, for Customer ' || fp_customernumber ||
                      ' for product ' || gv_to_productcode || ' size ' || fp_new_sizecode ||
                      ' startdate ' || to_char(cwz.startdate, 'DD-MON-YYYY'));
          end;
        end loop;
      end copy_customerrentprice;

      procedure copy_customerrentdiscount is
      begin
        --Rent,copy_customerRentdiscount
        gv_message := 'Copy PLPC Rent discounts for Customer ' || fp_customernumber;
        for cwz in (select case
                             when cwp.startdate < trunc(sysdate) then
                              trunc(sysdate)
                             else
                              cwp.startdate
                           end startdate, cwp.discount, cwp.typeofrent
                    from   customerrentdiscount cwp
                    where  cwp.productlistpercustomer_id = fp_old_plpc_rec.productlistpercustomer_id
                    and    cwp.startdate >=
                           coalesce((select max(cw.startdate) startdate
                                     from   customerrentdiscount cw
                                     where  cw.productlistpercustomer_id =
                                            cwp.productlistpercustomer_id
                                     and    cw.typeofrent = cwp.typeofrent
                                     and    cw.startdate <= trunc(sysdate)), trunc(sysdate))
                    and    not exists (select 1
                            from   customerrentdiscount x
                            where  x.productlistpercustomer_id =
                                   fp_new_plpc_rec.productlistpercustomer_id)) loop
          begin
            --copy Rent discount
            insert into customerrentdiscount
              (customerrentdiscount_id, productlistpercustomer_id, timestamp, systemuser_id,
               discount, startdate, typeofrent)
            values
              (seq_customerrentdiscount.nextval, fp_new_plpc_rec.productlistpercustomer_id, sysdate,
               fp_systemuserid, cwz.discount, cwz.startdate, cwz.typeofrent);
            --write log
            write_log('Created Customer Rent Discount, for Customer ' || fp_customernumber ||
                      ' for product ' || gv_to_productcode || ' size ' || fp_new_sizecode ||
                      ' startdate ' || to_char(cwz.startdate, 'DD-MON-YYYY'));
          end;
        end loop; --cwz Rent
      end copy_customerrentdiscount;

      procedure copy_customersalesprice is
      begin
        --copy_CustomerSalesPrice
        gv_message := 'copy_CustomerSalesPrice for Customer ' || fp_customernumber;
        --CUSTOMER_ID, PRODUCT_ID, SIZEDEFINITION_ID, STARTDATE
        for cicpx in (select cicp.customer_id,
                             case
                               when cicp.startdate < trunc(sysdate) then
                                trunc(sysdate)
                               else
                                cicp.startdate
                             end startdate, cicp.price, cicp.volumeprice, cicp.sizebillinggroup_id
                      from   customersalesprice cicp
                      where  cicp.customer_id = fp_old_plpc_rec.customer_id
                      and    cicp.product_id = fp_from_productid
                      and    cicp.sizedefinition_id = fp_old_plpc_rec.sizedefinition_id
                      and    cicp.startdate >=
                             coalesce((select max(zz.startdate)
                                       from   customersalesprice zz
                                       where  zz.customer_id = cicp.customer_id
                                       and    zz.product_id = cicp.product_id
                                       and    zz.sizedefinition_id = cicp.sizedefinition_id
                                       and    nvl(zz.sizebillinggroup_id,0) = nvl(cicp.sizebillinggroup_id,0)
                                       and    zz.startdate <= trunc(sysdate)), trunc(sysdate))
                      and    not exists
                       (select 1
                              from   customersalesprice cicpy
                              where  cicpy.customer_id = cicp.customer_id
                              and    cicpy.product_id = fp_to_productid
                              and    cicpy.sizedefinition_id = fp_new_plpc_rec.sizedefinition_id
                              and    nvl(cicpy.sizebillinggroup_id,0) = nvl(cicp.sizebillinggroup_id,0)
                              )) loop
          begin
            insert into customersalesprice
              (customersalesprice_id, product_id, sizedefinition_id, timestamp, systemuser_id,
               price, startdate, customer_id, volumeprice, sizebillinggroup_id)
            values
              (seq_customersalesprice.nextval, fp_to_productid, fp_new_plpc_rec.sizedefinition_id,
               sysdate /*timestamp*/, fp_systemuserid, cicpx.price, cicpx.startdate,
               cicpx.customer_id, 1, cicpx.sizebillinggroup_id);
            --write log
            write_log('Created Customer Sales Price, for Customer ' || fp_customernumber ||
                      ' for product ' || gv_to_productcode || ' size ' || fp_new_sizecode ||
                      ' startdate ' || to_char(cicpx.startdate, 'DD-MON-YYYY'));
          end;
        end loop;
      end copy_customersalesprice;

      procedure copy_customerreplacementprice is
      begin
        --copy_customerReplacementprice
        gv_message := 'copy_customerReplacementprice for Customer ' || fp_customernumber;
        --CUSTOMER_ID, PRODUCT_ID, SIZEDEFINITION_ID, STARTDATE
        for crix in (select cri.customer_id, cri.sizedefinition_id,
                            case
                              when cri.startdate < trunc(sysdate) then
                               trunc(sysdate)
                              else
                               cri.startdate
                            end startdate, cri.price, cri.sizebillinggroup_id
                     from   customerreplacementprice cri
                     where  cri.customer_id = fp_old_plpc_rec.customer_id
                     and    cri.product_id = fp_from_productid
                     and    cri.sizedefinition_id = fp_old_plpc_rec.sizedefinition_id
                     and    cri.startdate >=
                            coalesce((select max(criy.startdate) startdate
                                      from   customerreplacementprice criy
                                      where  criy.customer_id = cri.customer_id
                                      and    criy.product_id = cri.product_id
                                      and    criy.sizedefinition_id = cri.sizedefinition_id
                                      and    nvl(criy.sizebillinggroup_id, 0) = nvl(cri.sizebillinggroup_id, 0)
                                      and    criy.startdate <= trunc(sysdate)), trunc(sysdate))
                     and    not exists
                      (select 1
                             from   customerreplacementprice criy
                             where  criy.customer_id = cri.customer_id
                             and    criy.product_id = fp_to_productid
                             and    criy.sizedefinition_id = fp_new_plpc_rec.sizedefinition_id
                             and    nvl(criy.sizebillinggroup_id, 0) = nvl(cri.sizebillinggroup_id, 0))) loop
          begin
            insert into customerreplacementprice
              (customerreplacementprice_id, product_id, sizedefinition_id, customer_id, startdate,
               price, systemuser_id, timestamp, sizebillinggroup_id)
            values
              (seq_customerreplacementprice.nextval, fp_to_productid,
               fp_new_plpc_rec.sizedefinition_id, crix.customer_id, crix.startdate, crix.price,
               fp_systemuserid, sysdate /*timestamp*/, crix.sizebillinggroup_id);
            --write log
            write_log('Created Customer Replacement Price, for Customer ' || fp_customernumber ||
                      ' for product ' || gv_to_productcode || ' size ' || fp_new_sizecode ||
                      ' startdate ' || to_char(crix.startdate, 'DD-MON-YYYY'));
          end;
        end loop; --crix
      end copy_customerreplacementprice;

      procedure copy_customerimagecareprice is
      begin
        --copy_CustomerImageCarePrice
        gv_message := 'copy_CustomerImageCarePrice for Customer ' || fp_customernumber;
        --CUSTOMER_ID, PRODUCT_ID, SIZEDEFINITION_ID, STARTDATE
        for cicpx in (select cicp.customer_id, cicp.sizedefinition_id,
                             case
                               when cicp.startdate < trunc(sysdate) then
                                trunc(sysdate)
                               else
                                cicp.startdate
                             end startdate, cicp.price
                      from   customerimagecareprice cicp
                      where  cicp.customer_id = fp_old_plpc_rec.customer_id
                      and    cicp.product_id = fp_from_productid
                      and    cicp.sizedefinition_id = fp_old_plpc_rec.sizedefinition_id
                      and    cicp.startdate >=
                             coalesce((select max(criy.startdate) startdate
                                       from   customerimagecareprice criy
                                       where  criy.customer_id = cicp.customer_id
                                       and    criy.product_id = cicp.product_id
                                       and    criy.sizedefinition_id = cicp.sizedefinition_id
                                       and    criy.startdate <= trunc(sysdate)), trunc(sysdate))
                      and    not exists
                       (select 1
                              from   customerimagecareprice cicpy
                              where  cicpy.customer_id = cicp.customer_id
                              and    cicpy.product_id = fp_to_productid
                              and    cicpy.sizedefinition_id = fp_new_plpc_rec.sizedefinition_id)) loop
          begin
            insert into customerimagecareprice
              (customerimagecareprice_id, customer_id, product_id, sizedefinition_id, startdate,
               price, systemuser_id, timestamp)
            values
              (seq_customerimagecareprice.nextval, cicpx.customer_id, fp_to_productid,
               fp_new_plpc_rec.sizedefinition_id, cicpx.startdate, cicpx.price, fp_systemuserid,
               sysdate /*timestamp*/);
            --write log
            write_log('Created Customer Imagecare Price, for Customer ' || fp_customernumber ||
                      ' for product ' || gv_to_productcode || ' size ' || fp_new_sizecode ||
                      ' startdate ' || to_char(cicpx.startdate, 'DD-MON-YYYY'));
          end;
        end loop;
      end copy_customerimagecareprice;

      procedure copy_customerproducttaxdef is
      begin
        --copy_customerproducttaxdef
        gv_message := 'copy_customerproducttaxdef for Customer ' || fp_customernumber;
        insert into customerproducttaxdef
          (customer_id, product_id, type, taxgroup_id, systemuser_id, timestamp)
          select ct.customer_id, fp_to_productid, ct.type, ct.taxgroup_id, fp_systemuserid, sysdate /*timestamp*/
          from   customerproducttaxdef ct
          where  ct.product_id = fp_from_productid
          and    ct.customer_id = fp_old_plpc_rec.customer_id
          and    not exists (select 1
                  from   customerproducttaxdef cpx
                  where  cpx.customer_id = ct.customer_id
                  and    cpx.product_id = fp_to_productid
                  and    cpx.type = ct.type);
        if sql%rowcount <> 0 then
          begin
            --write log
            write_log('Created ' || sql%rowcount ||
                      ' Customer Product TaxDef records for customer ' || fp_customernumber);
          end;
        end if;
      end copy_customerproducttaxdef;

      procedure copy_customerproducttogdef is
      begin
        --copy_customerproducttogdef
        gv_message := 'copy_customerproducttogdef for Customer ' || fp_customernumber;
        --unique key is CUSTOMER_ID, PRODUCT_ID, TURNOVERGROUP_ID, TYPE
        insert into customerproducttogdef
          (customer_id, product_id, turnovergroup_id, type, percentage, systemuser_id, timestamp)
          select ctf.customer_id, fp_to_productid, ctf.turnovergroup_id, ctf.type, ctf.percentage,
                 fp_systemuserid, sysdate /*timestamp*/
          from   customerproducttogdef ctf
          where  ctf.product_id = fp_from_productid
          and    ctf.customer_id = fp_old_plpc_rec.customer_id
          and    not exists (select 1
                  from   customerproducttogdef ctfx
                  where  ctfx.customer_id = ctf.customer_id
                  and    ctfx.product_id = fp_to_productid
                  and    ctfx.turnovergroup_id = ctf.turnovergroup_id
                  and    ctfx.type = ctf.type);
        if sql%rowcount <> 0 then
          begin
            --write log
            write_log('Created ' || sql%rowcount ||
                      ' Customer Product TogDef records for customer ' || fp_customernumber);
          end;
        end if;
      end copy_customerproducttogdef;

      procedure copy_customerreissueprice is
      begin
        --copy_customerreissueprice
        gv_message := 'copy_customerreissueprice for Customer ' || fp_customernumber;
        --CUSTOMER_ID, PRODUCT_ID, SIZEDEFINITION_ID, STARTDATE
        for crix in (select cri.customer_id, cri.sizedefinition_id,
                            case
                              when cri.startdate < trunc(sysdate) then
                               trunc(sysdate)
                              else
                               cri.startdate
                            end startdate, cri.price
                     from   customerreissueprice cri
                     where  cri.customer_id = fp_old_plpc_rec.customer_id
                     and    cri.product_id = fp_from_productid
                     and    cri.sizedefinition_id = fp_old_plpc_rec.sizedefinition_id
                     and    cri.startdate >=
                            coalesce((select max(criy.startdate) startdate
                                      from   customerreissueprice criy
                                      where  criy.customer_id = cri.customer_id
                                      and    criy.product_id = cri.product_id
                                      and    criy.sizedefinition_id = cri.sizedefinition_id
                                      and    criy.startdate <= trunc(sysdate)), trunc(sysdate))
                     and    not exists
                      (select 1
                             from   customerreissueprice criy
                             where  criy.customer_id = cri.customer_id
                             and    criy.product_id = fp_to_productid
                             and    criy.sizedefinition_id = fp_new_plpc_rec.sizedefinition_id)) loop
          begin
            --insert into customerreissueprice
            gv_message := 'insert into customerreissueprice';
            insert into customerreissueprice
              (customerreissueprice_id, product_id, sizedefinition_id, customer_id, startdate,
               price, systemuser_id, timestamp)
            values
              (seq_customerreissueprice.nextval, fp_to_productid, fp_new_plpc_rec.sizedefinition_id,
               crix.customer_id, crix.startdate, crix.price, fp_systemuserid, sysdate /*timestamp*/);
            --write log
            write_log('Created Customer ReIssue Price, for Customer ' || fp_customernumber ||
                      ' for product ' || gv_to_productcode || ' size ' || fp_new_sizecode ||
                      ' startdate ' || to_char(crix.startdate, 'DD-MON-YYYY'));
          end;
        end loop; --crix
      end copy_customerreissueprice;

      procedure copy_customerbgprotectionprice is
      begin
        --copy_CustomerBGProtectionPrice
        gv_message := 'copy_CustomerBGProtectionPrice for Customer ' || fp_customernumber;
        --CUSTOMER_ID, PRODUCT_ID, SIZEDEFINITION_ID, STARTDATE
        for cbgpx in (select cbgp.customer_id, cbgp.sizedefinition_id,
                             case
                               when cbgp.startdate < trunc(sysdate) then
                                trunc(sysdate)
                               else
                                cbgp.startdate
                             end startdate, cbgp.price, cbgp.pricecomponent
                      from   customerbgprotectionprice cbgp
                      where  cbgp.customer_id = fp_old_plpc_rec.customer_id
                      and    cbgp.product_id = fp_from_productid
                      and    cbgp.sizedefinition_id = fp_old_plpc_rec.sizedefinition_id
                      and    cbgp.startdate >=
                             coalesce((select max(cbgpy.startdate) startdate
                                       from   customerbgprotectionprice cbgpy
                                       where  cbgpy.customer_id = cbgp.customer_id
                                       and    cbgpy.product_id = cbgp.product_id
                                       and    cbgpy.sizedefinition_id = cbgp.sizedefinition_id
                                       and    cbgpy.startdate <= trunc(sysdate)), trunc(sysdate))
                      and    not exists
                       (select 1
                              from   customerbgprotectionprice cbgpy
                              where  cbgpy.customer_id = cbgp.customer_id
                              and    cbgpy.product_id = fp_to_productid
                              and    cbgpy.sizedefinition_id = fp_new_plpc_rec.sizedefinition_id)) loop
          begin
            insert into customerbgprotectionprice
              (customerbgprotectionprice_id, customer_id, product_id, sizedefinition_id, pricecomponent, startdate,
               price, systemuser_id, timestamp)
            values
              (seq_customerbgprotectionprice.nextval, cbgpx.customer_id, fp_to_productid,
               fp_new_plpc_rec.sizedefinition_id, cbgpx.pricecomponent, cbgpx.startdate, cbgpx.price, fp_systemuserid,
               sysdate /*timestamp*/);
            --write log
            write_log('Created Budget Protection Price, for Customer ' || fp_customernumber ||
                      ' for product ' || gv_to_productcode || ' size ' || fp_new_sizecode ||
                      ' startdate ' || to_char(cbgpx.startdate, 'DD-MON-YYYY'));
          end;
        end loop;
      end copy_customerbgprotectionprice;

      procedure copy_plpcchargepercentage is
      begin
        --copy_plpcchargepercentage
        gv_message := 'copy_plpcchargepercentage for Customer ' || fp_customernumber;
        insert into plpcchargepercentage
          (productlistpercustomer_id, losschargepercentage, srchargepercentage, systemuser_id, timestamp)
        select
          fp_new_plpc_rec.productlistpercustomer_id, plpccp.losschargepercentage, plpccp.srchargepercentage, fp_systemuserid, sysdate /*timestamp*/
        from plpcchargepercentage plpccp
        where plpccp.productlistpercustomer_id = fp_old_plpc_rec.productlistpercustomer_id;
        if sql%rowcount > 0 then
          begin
            --write log
            write_log('Created PLPC Charge Percentage, for Customer ' || fp_customernumber ||
                      ' for product ' || gv_to_productcode || ' size ' || fp_new_sizecode);
          end;
        end if;
      exception
        when dup_val_on_index then
            write_log('Already exists PLPC Charge Percentage, for Customer ' || fp_customernumber ||
                      ' for product ' || gv_to_productcode || ' size ' || fp_new_sizecode);
      end copy_plpcchargepercentage;
    begin
      --copy_plpc_prices_discounts
      gv_message := 'copy_plpc_prices_discounts';
      --copy_customerrentdiscount
      copy_customerrentdiscount;
      --copy_customerrentprice
      copy_customerrentprice;
      --copy_customerreplacementprice
      copy_customerreplacementprice;
      --copy_customersalesprice
      copy_customersalesprice;
      --copy_customerwashdiscount
      copy_customerwashdiscount;
      --copy_customerwashprice
      copy_customerwashprice;
      --copy_CustomerImageCarePrice
      copy_customerimagecareprice;
      --copy_customerproducttaxdef
      copy_customerproducttaxdef;
      --copy_customerproducttogdef
      copy_customerproducttogdef;
      --copy_customerreissueprice
      copy_customerreissueprice;
      --copy_plpcchargepercentage
      copy_plpcchargepercentage;
      --copy_customerbgprotectionprice
      copy_customerbgprotectionprice;
    end copy_plpc_prices_discounts;

    procedure update_productlistpercustomer(fp_customerid customer.customer_id%type default null) is
      lv_dest_sizecode        sizedefinition.code%type;
      lv_desc_finishingmethod finishingmethod.code%type;
      lv_customernumber       customer.customernumber%type;
      lv_dest_plpc            productlistpercustomer%rowtype;
      lv_rowcount             number;
      lv_dateactive           productlistpercustomer.dateactive%type;
	  lv_dateinactive         productlistpercustomer.dateinactive%type;
      lv_exist_from_product_size_star    varchar2(1);
	    lv_exist_to_product_size_star      varchar2(1);

      procedure create_productconversion(fp_source_plpcid in productlistpercustomer.productlistpercustomer_id%type) is
        lv_productconversionid productconversion.productconversion_id%type;
      begin
        --create_productconversion
        gv_message := 'insert into productconversion';
        insert into productconversion
          (productconversion_id, sourceproduct_id, startdate, status, systemuser_id, timestamp,
           customer_link_id, customerselection, destinationproduct_id, destinationemblemtemplate_id,
           productcategory)
        values
          (seq_productconversion.nextval, fp_from_productid, trunc(sysdate), 1, fp_systemuserid,
           sysdate, lv_dest_plpc.customer_id, 0, fp_to_productid, null,
           case when gv_from_product_tom = 2 then 0 else 1 end)
        returning productconversion_id into lv_productconversionid;
        --Create ProductConversionLine PCL
        gv_message := 'insert into productconversionline';
        insert into productconversionline
          (productconversionline_id, productconversion_id, sourceplpc_id, destinationplpc_id,
           systemuser_id, timestamp)
        values
          (seq_productconversionline.nextval, lv_productconversionid, fp_source_plpcid,
           lv_dest_plpc.productlistpercustomer_id, fp_systemuserid, sysdate);
      end create_productconversion;

      procedure create_contractproduct(fp_source_plpcid in productlistpercustomer.productlistpercustomer_id%type) is
        lv_cpnew_id                     contractproduct.contractproduct_id%type;
        lv_plpcsource_dateactive        productlistpercustomer.dateactive%type;
        lv_plpcsource_dateinactive      productlistpercustomer.dateinactive%type;
        lv_plpcsource_sizedefid         productlistpercustomer.sizedefinition_id%type;
        lv_plpcsource_fmid              productlistpercustomer.finishingmethod_id%type;

      begin
          select plpc.dateactive, plpc.dateinactive, plpc.sizedefinition_id, plpc.finishingmethod_id
            into lv_plpcsource_dateactive, lv_plpcsource_dateinactive, lv_plpcsource_sizedefid, lv_plpcsource_fmid
            from productlistpercustomer plpc
           where plpc.productlistpercustomer_id = fp_source_plpcid;

          if lv_plpcsource_dateactive > sysdate then
          lv_dateactive := lv_plpcsource_dateactive;
          else
            lv_dateactive := sysdate;
          end if;

          if lv_plpcsource_dateinactive < sysdate then
          lv_dateinactive := lv_plpcsource_dateinactive;
          else
            lv_dateinactive := sysdate;
          end if;

          for cp_source in (select cpx.contract_id, cpplpc.contractproduct_id, c.code contractcode, p.code productcode
                             from contractproductplpc cpplpc
                                  join contractproduct cpx on cpplpc.contractproduct_id = cpx.contractproduct_id
                                  join product p on cpx.product_id = p.product_id
                                  join contract c on cpx.contract_id = c.contract_id
                             where cpplpc.productlistpercustomer_id = fp_source_plpcid
                     ) loop
                 begin
                    select cp.contractproduct_id
                    into lv_cpnew_id
                    from contractproduct cp
                    where cp.contract_id = cp_source.contract_id
                    and cp.product_id = fp_to_productid
                    and cp.sizedefinition_id = nvl(fp_to_sizedefinitionid,lv_plpcsource_sizedefid)
                    and cp.finishingmethod_id = lv_plpcsource_fmid
                    and cp.startdate <= sysdate
                    and cp.enddate >= sysdate
                    and cp.startdate = (select max(cp2.startdate)
                                        from contractproduct cp2
                                        where cp2.contract_id = cp_source.contract_id
                                        and cp2.product_id= fp_to_productid
                                        and cp2.sizedefinition_id = nvl(fp_to_sizedefinitionid,lv_plpcsource_sizedefid)
                                        and cp2.finishingmethod_id = lv_plpcsource_fmid
                                        and cp2.startdate <= sysdate
                                        and cp2.enddate >= sysdate);
                  exception when no_data_found then
                  begin
                    --create_contractproduct
                    gv_message := 'insert into contractproduct';
                      insert into contractproduct
                      (contractproduct_id, contract_id, product_id, sizedefinition_id, finishingmethod_id, startdate, enddate, released, systemuser_id, timestamp)
                      values (seq_contractproduct.nextval,
                             cp_source.contract_id,
                             fp_to_productid,
                             nvl(fp_to_sizedefinitionid,lv_dest_plpc.sizedefinition_id),
                             lv_plpcsource_fmid,
                             lv_dateactive,
                             to_date('31-12-2099','dd-mm-yyyy'),
                             'Y',
                             fp_systemuserid,
                             sysdate)
                     returning contractproduct_id into lv_cpnew_id;
                  end;
                 end;
                     begin
                     --create_contractproductbilling
                      gv_message := 'insert into contractproductbilling';
                      insert into contractproductbilling
                           (contractproduct_id,billingmethod,changesperweek,chargeoveruse,rentpriceperfrequency,chargewashesonlyforcog
                           ,inventorybillingtype,minimumturnaround,minimumquantity,minimumfrequency,chargelossforpool_yn
                           ,chargelossuniquepooldays,priceusage,chargerentnoreturnpoolafterwks,chargerentnotreturned
                           ,percentageafterdepreciation,invoicefreqrelatedrentprice,invwashbasedonsoilcount,chargewashespack
                           ,returnstockallowed,systemuser_id,timestamp,compliancyrule,compliancyrulepricing)
                      select lv_cpnew_id,
                           cpb.billingmethod, cpb.changesperweek, cpb.chargeoveruse, cpb.rentpriceperfrequency, cpb.chargewashesonlyforcog
                           ,cpb.inventorybillingtype, cpb.minimumturnaround, cpb.minimumquantity, cpb.minimumfrequency, cpb.chargelossforpool_yn
                           , cpb.chargelossuniquepooldays, cpb.priceusage, cpb.chargerentnoreturnpoolafterwks, cpb.chargerentnotreturned
                           , cpb.percentageafterdepreciation, cpb.invoicefreqrelatedrentprice, cpb.invwashbasedonsoilcount, cpb.chargewashespack
                           , cpb.returnstockallowed, cpb.systemuser_id, cpb.timestamp, cpb.compliancyrule, cpb.compliancyrulepricing
                           from contractproductbilling cpb
                           where cpb.contractproduct_id = cp_source.contractproduct_id;

                      --create_contractproductaddbilling
                      gv_message := 'insert into contractproductaddbilling';
                      insert into contractproductaddbilling
                           (contractproduct_id,seasontype_id,seasonalrent,chargewashinactiveseason,residualvaluescheme_id
                           ,srcmethod,srcpercentagesoilcount,srcpercentageinventory,srcpercentagebilledqty,deliverreplacementqty
                           ,srcfrequency,srcchargerent,showfocrentoninvoice,resetrvuponreissue,systemuser_id,timestamp)
                           select lv_cpnew_id,
                           cpaddbill.seasontype_id, cpaddbill.seasonalrent, cpaddbill.chargewashinactiveseason, cpaddbill.residualvaluescheme_id
                           ,cpaddbill.srcmethod, cpaddbill.srcpercentagesoilcount, cpaddbill.srcpercentageinventory, cpaddbill.srcpercentagebilledqty, cpaddbill.deliverreplacementqty
                           , cpaddbill.srcfrequency, cpaddbill.srcchargerent, cpaddbill.showfocrentoninvoice, cpaddbill.resetrvuponreissue, cpaddbill.systemuser_id, cpaddbill.timestamp
                           from contractproductaddbilling cpaddbill
                           where cpaddbill.contractproduct_id = cp_source.contractproduct_id;


                      --create_contractproductorderdelivery
                      gv_message := 'insert into contractproductorderdelivery';
                      insert into contractproductorderdelivery
                           (contractproduct_id,delayedevenexchange,deedeliveryscheme,straightevenexchange
                           ,orderviaweb,soilcountmethod,cleancount,codeuniquely,onsiteinventorycount,automaticsales,customerrelated
                           ,autoreplafterlifetime,allowreturntostock,raggeditemaction,systemuser_id,timestamp,compliancyrule,autosoilpercentage,quantitycontrol)
                           select lv_cpnew_id,
                           cpod.delayedevenexchange, cpod.deedeliveryscheme, cpod.straightevenexchange
                           ,cpod.orderviaweb, cpod.soilcountmethod, cpod.cleancount, cpod.codeuniquely, cpod.onsiteinventorycount, cpod.automaticsales, cpod.customerrelated
                           ,cpod.autoreplafterlifetime, cpod.allowreturntostock, cpod.raggeditemaction, cpod.systemuser_id, cpod.timestamp, cpod.compliancyrule, cpod.autosoilpercentage, cpod.quantitycontrol
                           from contractproductorderdelivery cpod
                           where cpod.contractproduct_id = cp_source.contractproduct_id;

                      --create_contractproductmiscellaneous
                      gv_message := 'insert into contractproductmiscellaneous';
                      insert into contractproductmiscellaneous
                           (contractproduct_id,customcode,customdescription,eannumber,nannumber,salesemployee_id
                           ,commissionpayable,salesemployee2_id,contractpurchaseorder_id,contractpurchaseorderline_id
                           ,gainreason_id,gaincompetitor_id,lostreason_id,lostcompetitor_id,remark,systemuser_id,timestamp,compliancyrule,brandless)
                           select lv_cpnew_id,
                           cpm.customcode, cpm.customdescription, cpm.eannumber, cpm.nannumber, cpm.salesemployee_id
                           ,cpm.commissionpayable, cpm.salesemployee2_id, cpm.contractpurchaseorder_id, cpm.contractpurchaseorderline_id
                           , cpm.gainreason_id, cpm.gaincompetitor_id, cpm.lostreason_id, cpm.lostcompetitor_id, cpm.remark, cpm.systemuser_id, cpm.timestamp, cpm.compliancyrule, cpm.brandless
                           from contractproductmiscellaneous cpm
                           where cpm.contractproduct_id = cp_source.contractproduct_id;

                      --create_contractproductbgprotection
                      gv_message := 'insert into contractproductbgprotection';
                      insert into contractproductbgprotection(contractproduct_id, garmentsetup, garmentmaintenance, garmentloss
                           , garmentrepair, compliancyrule, systemuser_id, timestamp, mmpspecificpercentage, mbyoppercentage, garmentlosspercentage
                           , garmentemblem)
                           select lv_cpnew_id,
                           cpbgp.garmentsetup, cpbgp.garmentmaintenance, cpbgp.garmentloss
                           , cpbgp.garmentrepair, cpbgp.compliancyrule, cpbgp.systemuser_id, cpbgp.timestamp, cpbgp.mmpspecificpercentage
                           , cpbgp.mbyoppercentage, cpbgp.garmentlosspercentage
                           , cpbgp.garmentemblem
                           from contractproductbgprotection cpbgp
                           where cpbgp.contractproduct_id = cp_source.contractproduct_id;

                      --create_contractproductimagecare
                      gv_message := 'insert into contractproductimagecare';
                      insert into contractproductimagecare(contractproduct_id, compliancyrule, imagecare, systemuser_id, timestamp)
                           select lv_cpnew_id,
                           cpic.compliancyrule, cpic.imagecare, cpic.systemuser_id, cpic.timestamp
                           from contractproductimagecare cpic
                           where cpic.contractproduct_id = cp_source.contractproduct_id;

                      --create_contractproductbrand
                      gv_message := 'insert into contractproductbrand';
                      insert into contractproductbrand(contractproduct_id,contractbrand_id,systemuser_id,timestamp)
                           select lv_cpnew_id,
                           cpb.contractbrand_id, cpb.systemuser_id, cpb.timestamp
                           from contractproductbrand cpb
                           where cpb.contractproduct_id = cp_source.contractproduct_id;

                      --create_contractproductqmglimit
                      gv_message := 'insert into contractproductqmglimit';
                      insert into contractproductqmglimit(contractproductqmglimit_id, contractproduct_id, contractqmgroup_id, maxcirculatinginventory
                           , maxbillingquantity, maxdeliveryquantity, systemuser_id, timestamp)
                           select seq_contractproductqmglimit.nextval,
                           lv_cpnew_id, cpq.contractqmgroup_id, cpq.maxcirculatinginventory
                           , cpq.maxbillingquantity, cpq.maxdeliveryquantity, cpq.systemuser_id, cpq.timestamp
                           from contractproductqmglimit cpq
                           where cpq.contractproduct_id = cp_source.contractproduct_id;

                      --create_contractproductpricing
                      gv_message := 'insert into contractproductpricing';
                      insert into contractproductpricing(contractproduct_id, losschargepercentage, srchargepercentage, systemuser_id, timestamp)
                           select lv_cpnew_id,
                           cpp.losschargepercentage, cpp.srchargepercentage, cpp.systemuser_id, cpp.timestamp
                           from contractproductpricing cpp
                           where cpp.contractproduct_id = cp_source.contractproduct_id;

                      --create_contractproductdelfreq
                      gv_message := 'insert into contractproductdelfreq';
                      insert into contractproductdelfreq(contractproductdelfreq_id, contractproduct_id, deliveryfrequency, systemuser_id, timestamp)
                           select seq_contractproductdelfreq.nextval,
                           lv_cpnew_id, cpdf.deliveryfrequency, cpdf.systemuser_id, cpdf.timestamp
                           from contractproductdelfreq cpdf
                           where cpdf.contractproduct_id = cp_source.contractproduct_id;

                 exception
                   when dup_val_on_index then
                     write_log('Already exists contract product for contract code ' || cp_source.contractcode || ' and product ' || cp_source.productcode);
                   when others then
                   gv_message := 'Error on contract product: ' || cp_source.contract_id || ','|| fp_to_productid|| ',' || fp_to_sizedefinitionid
                    || ',' || lv_plpcsource_fmid || ',' || lv_dateactive || ',' || lv_dateinactive || ',' || fp_systemuserid || ' ' || sqlerrm;
                    if fp_selection = 'N' then
                      begin
                        raise gv_userexception;
                        write_log('Error on contract product: ' || cp_source.contract_id || ','|| fp_to_productid|| ',' || fp_to_sizedefinitionid
                         || ',' || lv_plpcsource_fmid || ',' || lv_dateactive || ',' || lv_dateinactive || ',' || fp_systemuserid || ' ' || sqlerrm);
                      end;
                    end if;
                 end;
                 begin
                 --create_contractproductplpc
                      gv_message := 'insert into contractproductplpc';
                      insert into contractproductplpc(contractproduct_id, productlistpercustomer_id, systemuser_id, timestamp)
                           values (lv_cpnew_id, lv_dest_plpc.productlistpercustomer_id, fp_systemuserid, sysdate);
                 exception
                   when dup_val_on_index then
                     write_log('Already exists contract productplpc for customer ' || lv_customernumber || ', ' || cp_source.contractcode || ' and product ' || cp_source.productcode);
                   when others then
                   gv_message := 'Error on contract productplpc for customer ' || lv_customernumber || ', ' || cp_source.contract_id || ','|| fp_to_productid|| ',' || fp_to_sizedefinitionid
                    || ',' || lv_plpcsource_fmid || ',' || lv_dateactive || ',' || lv_dateinactive || ',' || fp_systemuserid || ' ' || sqlerrm;
                    if fp_selection = 'N' then
                      begin
                         raise gv_userexception;
                         write_log('Error on contract productplpc for customer ' || lv_customernumber || ', ' || cp_source.contract_id || ','|| fp_to_productid|| ',' || fp_to_sizedefinitionid
                          || ',' || lv_plpcsource_fmid || ',' || lv_dateactive || ',' || lv_dateinactive || ',' || fp_systemuserid || ' ' || sqlerrm);
                       end;
                    end if;
                 end;
          update contractproduct cp
          set cp.enddate = lv_dateinactive
          where cp.contractproduct_id = cp_source.contractproduct_id
          and (fp_customerid is null or cp.contract_id in (select cc.contract_id
                                                     from contractcustomer cc
                                                     where cc.customer_link_id in (select cpc.customer_id
                                                                                   from customerproductconversion cpc
                                                                                   where cpc.filteron = 2/*contract*/
                                                                                   and cpc.processed = 'N'
                                                                                   and cpc.customer_id = fp_customerid)));

          end loop;
      end create_contractproduct;

      procedure check_size_star_for_product_plpc is
        lv_count     number;
        begin
          lv_exist_from_product_size_star := 'N';
          lv_exist_to_product_size_star := 'N';
          --check if from_product exist in PLPC with size *
          lv_count := 0;
          select count(1)
          into lv_count
          from productlistpercustomer l
          where l.product_id = fp_from_productid
          and l.sizedefinition_id = gv_sizestarid
          and l.customer_id = nvl(fp_customerid, l.customer_id);
          if lv_count > 0 then
            lv_exist_from_product_size_star := 'Y';
          end if;
          --check if to_product exist in PLPC with size *
          lv_count := 0;
          select count(1)
          into lv_count
          from productlistpercustomer l
          where l.product_id = fp_to_productid
          and l.sizedefinition_id = gv_sizestarid
          and l.customer_id = nvl(fp_customerid, l.customer_id);
          if lv_count > 0 then
            lv_exist_to_product_size_star := 'Y';
          end if;
      end check_size_star_for_product_plpc;

      begin
      --update_productlistpercustomer
      gv_message := 'update_productlistpercustomer';
      --3.4.1 Product List per Customer
      check_size_star_for_product_plpc();
      --we select all products, also quit products
      for plx in (select l.*
                  from   productlistpercustomer l
                  where  l.product_id = fp_from_productid
                  and    (l.sizedefinition_id = fp_from_sizedefinitionid or
                        fp_from_sizedefinitionid is null)
                  and   (l.customer_id = fp_customerid or fp_customerid is null)
                  and    exists (select 1
                          from   customeractivities ca
                          join   businessunit bu
                          on     bu.businessunit_id = ca.processbusinessunit_id
                          join   businessunitsperusergroup buug
                          on     buug.businessunit_id = ca.processbusinessunit_id
                          where  ca.customer_id = l.customer_id
                          and    ca.activity_id = gv_from_product_activityid
                          and    (bu.businessunit_id = fp_businessunitid or fp_businessunitid is null)
                          and    buug.usergroup_id = gv_usergroupid)) loop
        begin
          begin
            --get customer number for log
            gv_message := 'get customer number for log';
            select max(c.customernumber)
            into   lv_customernumber
            from   customer c
            where  c.customer_id = plx.customer_id;
            --check if destination product code already exists
            gv_message := 'check if destination product code already exists';
            select s.code, f.code, l.productlistpercustomer_id
            into   lv_dest_sizecode, lv_desc_finishingmethod, lv_dest_plpc.productlistpercustomer_id
            from   productlistpercustomer l
            join   sizedefinition s
            on     s.sizedefinition_id = l.sizedefinition_id
            join   finishingmethod f
            on     f.finishingmethod_id = l.finishingmethod_id
            where  l.customer_id = plx.customer_id
            and    l.product_id = fp_to_productid
            and    l.sizedefinition_id = nvl(fp_to_sizedefinitionid, plx.sizedefinition_id)
            and    l.finishingmethod_id = plx.finishingmethod_id;
            --
            select l.*
            into   lv_dest_plpc
            from   productlistpercustomer l
            where  l.productlistpercustomer_id = lv_dest_plpc.productlistpercustomer_id;
            --
            update productlistpercustomer l
            set    l.dateactive = least(l.dateactive, plx.dateactive),
                   l.dateinactive = greatest(l.dateinactive, plx.dateinactive),
                   l.systemuser_id = fp_systemuserid, l.timestamp = sysdate
            where  l.productlistpercustomer_id = lv_dest_plpc.productlistpercustomer_id
            and    (l.dateactive <> least(l.dateactive, plx.dateactive) or
                  l.dateinactive <> greatest(l.dateinactive, plx.dateinactive));
            --copy_plpc_prices_discounts
            copy_plpc_prices_discounts(lv_customernumber, lv_dest_plpc, plx, lv_dest_sizecode);
            --write log
            write_log('Already exists Product List per Customer for ' ||
                      to_char(lv_customernumber) || ', Product ' || gv_to_productcode || ', Size ' ||
                      lv_dest_sizecode || ', FinishingMethod ' || lv_desc_finishingmethod ||
                      ', please verify');
          exception
            when too_many_rows then
              begin
                gv_message := 'Error, more then 1 Product List per Customer already exists for ' ||
                              to_char(lv_customernumber) || ', Product ' || gv_to_productcode ||
                              ', Size ' || lv_dest_sizecode || ', FinishingMethod ' ||
                              lv_desc_finishingmethod || ' ! product conversion not possible ';
                raise gv_userexception;
              end;
            when no_data_found then
              begin
                --insert into customeractivities
                gv_message := 'insert into customeractivities';
                insert into customeractivities
                  (customer_id, processbusinessunit_id, activity_id, invoicebusinessunit_id,
                   systemuser_id, timestamp, cutoffdate, finalinvoicecreated, invoicefrequency_id,
                   separateinvoice, includenotactivityrelcharges, fromdateinadvance, todateinadvance,
                   salesemployee1_id, salesemployee2_id, activityreference, internalprocessingbu_id)
                  select plx.customer_id, ca.processbusinessunit_id, gv_to_product_activityid,
                         ca.invoicebusinessunit_id, fp_systemuserid, sysdate /*timestamp*/, null
                         /*cutoffdate*/, ca.finalinvoicecreated, ca.invoicefrequency_id,
                         ca.separateinvoice, ca.includenotactivityrelcharges, ca.fromdateinadvance,
                         ca.todateinadvance, ca.salesemployee1_id, ca.salesemployee2_id,
                         ca.activityreference, ca.internalprocessingbu_id
                  from   customeractivities ca
                  where  ca.customer_id = plx.customer_id
                  and    ca.activity_id = gv_from_product_activityid
                  and    not exists
                   (select 1
                          from   customeractivities cax
                          where  cax.customer_id = plx.customer_id
                          and    cax.activity_id = gv_to_product_activityid
                          and    cax.processbusinessunit_id = ca.processbusinessunit_id);
                --insert into productgrouppercustomer
                gv_message := 'insert into productgrouppercustomer';
                insert into productgrouppercustomer
                  (productgroup_id, customer_id, invoicegroupingcode, customcode, customdescritpion,
                   systemuser_id, timestamp, active, numbersoiltickets, defaultstockroom_id,
                   fixedstockroom)
                  select gv_to_product_groupid, pgc.customer_id, pgc.invoicegroupingcode,
                         pgc.customcode, pgc.customdescritpion, fp_systemuserid, sysdate
                         /*timestamp*/, pgc.active, pgc.numbersoiltickets, pgc.defaultstockroom_id,
                         pgc.fixedstockroom
                  from   productgrouppercustomer pgc
                  where  pgc.customer_id = plx.customer_id
                  and    pgc.productgroup_id = gv_from_product_groupid
                  and    not exists
                   (select 1
                          from   productgrouppercustomer pgx
                          where  pgx.customer_id = pgc.customer_id
                          and    pgx.productgroup_id = gv_to_product_groupid);
                --create new plpc
                gv_message   := 'Create the new productlistpercustomer record';
                lv_dest_plpc := plx;
                --set new values
                lv_dest_plpc.productlistpercustomer_id := seq_productlistpercustomer.nextval;
                lv_dest_plpc.product_id                := fp_to_productid;
                lv_dest_plpc.sizedefinition_id         := nvl(fp_to_sizedefinitionid,lv_dest_plpc.sizedefinition_id);
                --we take the original date active!
                lv_dest_plpc.timestamp     := sysdate;
                lv_dest_plpc.systemuser_id := fp_systemuserid;
                insert into productlistpercustomer values lv_dest_plpc;
                --get size code for log
                gv_message := 'get size for log';
                select s.code
                into   lv_dest_sizecode
                from   sizedefinition s
                where  s.sizedefinition_id = lv_dest_plpc.sizedefinition_id;
                --copy_plpc_prices_discounts
                copy_plpc_prices_discounts(lv_customernumber, lv_dest_plpc, plx, lv_dest_sizecode);
                --write log
                write_log('Created Product List per Customer for ' || to_char(lv_customernumber) ||
                          ', Product ' || gv_to_productcode || ', Size ' || lv_dest_sizecode);
              end;
          end;
          --copy plpc budgetprotection
          gv_message := 'insert into plpcbudgetprotection';
          insert into plpcbudgetprotection
            (productlistpercustomer_id,
             mmpspecificpercentage,
             garmentsetup,
             garmentmaintenance,
             garmentloss,
             garmentrepair,
             systemuser_id,
             timestamp,
             mbyoppercentage,
             garmentlosspercentage,
             garmentemblem)
            select lv_dest_plpc.productlistpercustomer_id,
                   plpcbp.mmpspecificpercentage,
                   plpcbp.garmentsetup,
                   plpcbp.garmentmaintenance,
                   plpcbp.garmentloss,
                   plpcbp.garmentrepair,
                   fp_systemuserid,
                   sysdate,
                   plpcbp.mbyoppercentage,
                   plpcbp.garmentlosspercentage,
                   plpcbp.garmentemblem
              from plpcbudgetprotection plpcbp
             where plpcbp.productlistpercustomer_id = plx.productlistpercustomer_id
               and not exists (select 1
                      from plpcbudgetprotection plpcbpx
                     where plpcbpx.productlistpercustomer_id = lv_dest_plpc.productlistpercustomer_id);
          --copy product deliverydays
          gv_message := 'insert into productlistpercustomer.productdeliveryday';
          insert into productdeliveryday
            (productlistpercustomer_id, day_id, timestamp, systemuser_id, deliverytype)
            select lv_dest_plpc.productlistpercustomer_id, pdd.day_id, sysdate, fp_systemuserid,
                   pdd.deliverytype
            from   productdeliveryday pdd
            where  pdd.productlistpercustomer_id = plx.productlistpercustomer_id
            and    not exists
             (select 1
                    from   productdeliveryday pddx
                    where  pddx.productlistpercustomer_id = lv_dest_plpc.productlistpercustomer_id
                    and    pddx.day_id = pdd.day_id);
          --get rows inserted for new PLPC
          lv_rowcount := sql%rowcount;
          --check if we need to create ProductConversion
          if (lv_dest_plpc.billingmethod = 2 and lv_dest_plpc.minimumfrequency = 1 and
             lv_rowcount > 1) then
            begin
              create_productconversion(plx.productlistpercustomer_id);
            end;
          end if;
          --create contractproduct
          create_contractproduct(plx.productlistpercustomer_id);

          --cut off old contractproduct
          gv_message := 'cut off old contractproduct id ' || to_char(plx.productlistpercustomer_id);


          --cut off old plpc
          gv_message := 'cut off old plpc id ' || to_char(plx.productlistpercustomer_id);
          update productlistpercustomer l
          set    l.dateinactive = trunc(sysdate), l.timestamp = sysdate,
                 l.systemuser_id = fp_systemuserid
          where  l.dateinactive > trunc(sysdate)
          and    l.productlistpercustomer_id = plx.productlistpercustomer_id;
        end;
      end loop; --plx
      if lv_rowcount is null then
        begin
           if (lv_exist_from_product_size_star = 'Y' and lv_exist_to_product_size_star = 'Y') then
             begin
               -- case when both "from_product" and "to_product" exist in PLPC only with size *
               write_log('No Product List per Customer found for ' || to_char(gv_customernumber) ||
                          ', Product ' || gv_from_productcode || ', Size ' || gv_from_sizecode || '. It exists only with size *');
             end;
           else
             begin
			         -- case when "from_product" exist in PLPC only with size * and "to_product" don't exist in PLPC at any size
               gv_message := 'No Product List per Customer found for ' || to_char(gv_customernumber) ||
                          ', Product ' || gv_from_productcode || ', Size ' || gv_from_sizecode || ' or *. The conversion will not continue';
               raise gv_userexception;
             end;
           end if;
         end;
      end if;
    end update_productlistpercustomer;

    procedure update_wearerinventories(fp_customerid customer.customer_id%type default null) is
      lv_desc_rec_wearerinv wearerinventory%rowtype;
      lv_customernumber     customer.customernumber%type;
      lv_wearernumber       wearer.wearernumber%type;
      lv_old_wearermplid    weareremployment.weareremployment_id%type;
      --update_wearerinventories

      procedure copy_wearerinvmodifications(fp_source_wearerinvid in wearerinventory.wearerinventory_id%type) is
      begin
        --copy_wearerinvmodifications
        gv_message := 'copy_wearerinvmodifications fp_source_wearerinvid ' || fp_source_wearerinvid;
        insert into wearerinventorymodification
          (wearerinventory_id, modification_id, sequencenumber, systemuser_id, timestamp)
          select lv_desc_rec_wearerinv.wearerinventory_id, wim.modification_id, wim.sequencenumber,
                 fp_systemuserid, sysdate /*timestamp*/
          from   wearerinventorymodification wim
          where  wim.wearerinventory_id = fp_source_wearerinvid
          and    not exists
           (select 1
                  from   wearerinventorymodification wimx
                  where  wimx.wearerinventory_id = lv_desc_rec_wearerinv.wearerinventory_id
                  and    wimx.sequencenumber = wim.sequencenumber)
          and    not exists
           (select 1
                  from   wearerinventorymodification wimx
                  where  wimx.wearerinventory_id = lv_desc_rec_wearerinv.wearerinventory_id
                  and    wimx.modification_id = wim.modification_id);
      end copy_wearerinvmodifications;

      procedure copy_wearerinvprice(fp_source_wearerinvid in wearerinventory.wearerinventory_id%type) is
      begin
        --copy_wearerinvprice
        gv_message := 'copy_wearerinvprice fp_source_wearerinvid ' || fp_source_wearerinvid;
        insert into wearerinvprice
          (wearerinvprice_id, wearerinventory_id, startdate, price, systemuser_id, timestamp)
          select seq_wearerinvprice.nextval, lv_desc_rec_wearerinv.wearerinventory_id, wip.startdate,
                 wip.price, fp_systemuserid, sysdate /*timestamp*/
          from   wearerinvprice wip
          where  wip.wearerinventory_id = fp_source_wearerinvid
          and    not exists
           (select 1
                  from   wearerinvprice wipx
                  where  wipx.wearerinventory_id = lv_desc_rec_wearerinv.wearerinventory_id);
      end copy_wearerinvprice;

      procedure move_uniqueitem(fp_source_wearerinvid in wearerinventory.wearerinventory_id%type) is
      begin
        --move_uniqueitem
        gv_message := 'move_uniqueitem ' || fp_source_wearerinvid;
        update uniqueitemnonpool un
        set    un.wearerinventory_id = lv_desc_rec_wearerinv.wearerinventory_id,
               un.systemuser_id = fp_systemuserid, un.timestamp = sysdate
        where  un.wearerinventory_id = fp_source_wearerinvid;
      end move_uniqueitem;

      procedure move_nonunique(fp_source_wearerinvid in wearerinventory.wearerinventory_id%type) is
      begin
        --move_nonunique
        gv_message := 'move_nonunique ' || fp_source_wearerinvid;
        update nonuniqueitem nu
        set    nu.wearerinventory_id = lv_desc_rec_wearerinv.wearerinventory_id,
               nu.systemuser_id = fp_systemuserid, nu.timestamp = sysdate
        where  nu.wearerinventory_id = fp_source_wearerinvid;
      end move_nonunique;
    begin
      --update_wearerinventories
      gv_message         := 'update_wearerinventories';
      lv_old_wearermplid := -1;
      for wisource in (select wi.*
                       from   wearerinventory wi
                       join   weareremployment we
                       on     we.weareremployment_id = wi.weareremployment_id
                       join   wearer wr
                       on     wr.wearer_id = we.wearer_id
                       where  wi.product_id = fp_from_productid
                       and    (fp_from_sizedefinitionid is null or
                             wi.sizedefinition_id = fp_from_sizedefinitionid)
                       and    wi.dateinactive > trunc(sysdate)
                       and    (fp_customerid is null or wr.customer_id = fp_customerid)
                       and    exists (select 1
                               from   customeractivities ca
                               join   businessunit bu
                               on     bu.businessunit_id = ca.processbusinessunit_id
                               join   businessunitsperusergroup buug
                               on     buug.businessunit_id = ca.processbusinessunit_id
                               where  ca.customer_id = wr.customer_id
                               and    ca.activity_id = gv_from_product_activityid
                               and    (bu.businessunit_id = fp_businessunitid or fp_businessunitid is null)
                               and    buug.usergroup_id = gv_usergroupid)
                       order  by wi.weareremployment_id) loop
        begin
          begin
            --check if new wearerinv already exists
            select wi.*
            into   lv_desc_rec_wearerinv
            from   wearerinventory wi
            where  wi.weareremployment_id = wisource.weareremployment_id
            and    wi.product_id = fp_to_productid
            and    ((wi.sizedefinition_id = wisource.sizedefinition_id and
                  fp_to_sizedefinitionid is null) or
                  (wi.sizedefinition_id = fp_to_sizedefinitionid));
            if lv_desc_rec_wearerinv.dateinactive < trunc(sysdate) then
              begin
                --Overwrite the inventory
                lv_desc_rec_wearerinv.dateactive      := trunc(sysdate);
                lv_desc_rec_wearerinv.dateinactive    := wisource.dateinactive;
                lv_desc_rec_wearerinv.maxinventory    := wisource.maxinventory;
                lv_desc_rec_wearerinv.maxfreeofcharge := wisource.maxfreeofcharge;
                lv_desc_rec_wearerinv.changesperweek  := wisource.changesperweek;
              end;
            else
              begin
                --Merge inventories
                lv_desc_rec_wearerinv.dateactive      := least(lv_desc_rec_wearerinv.dateactive,
                                                               wisource.dateactive);
                lv_desc_rec_wearerinv.dateinactive    := greatest(lv_desc_rec_wearerinv.dateinactive,
                                                                  wisource.dateinactive);
                lv_desc_rec_wearerinv.maxinventory    := lv_desc_rec_wearerinv.maxinventory +
                                                         wisource.maxinventory;
                lv_desc_rec_wearerinv.maxfreeofcharge := lv_desc_rec_wearerinv.maxfreeofcharge +
                                                         wisource.maxfreeofcharge;
                lv_desc_rec_wearerinv.changesperweek  := lv_desc_rec_wearerinv.changesperweek +
                                                         wisource.changesperweek;
              end;
            end if;
            lv_desc_rec_wearerinv.circinventory   := lv_desc_rec_wearerinv.circinventory +
                                                     wisource.circinventory;
            lv_desc_rec_wearerinv.freeofchargeqty := lv_desc_rec_wearerinv.freeofchargeqty +
                                                     wisource.freeofchargeqty;
            lv_desc_rec_wearerinv.systemuser_id   := fp_systemuserid;
            lv_desc_rec_wearerinv.timestamp       := sysdate;
            --update wearerinventory
            update wearerinventory wi
            set    row = lv_desc_rec_wearerinv
            where  wi.wearerinventory_id = lv_desc_rec_wearerinv.wearerinventory_id;
          exception
            when no_data_found then
              begin
                --new wearerinv did not already exists
                lv_desc_rec_wearerinv                    := wisource;
                lv_desc_rec_wearerinv.wearerinventory_id := seq_wearerinventory.nextval;
                lv_desc_rec_wearerinv.product_id         := fp_to_productid;
                lv_desc_rec_wearerinv.sizedefinition_id  := nvl(fp_to_sizedefinitionid,
                                                                lv_desc_rec_wearerinv.sizedefinition_id);
                --insert into wearerinventory
                insert into wearerinventory values lv_desc_rec_wearerinv;
              end;
          end; --check if new wearerinv already exists
          --copy_wearerinvmodifications
          copy_wearerinvmodifications(wisource.wearerinventory_id);
          --copy_wearerinvprice
          copy_wearerinvprice(wisource.wearerinventory_id);
          --move_uniqueitem
          move_uniqueitem(wisource.wearerinventory_id);
          --move_nonunique
          move_nonunique(wisource.wearerinventory_id);
          --cut off old wearerinventory
          update wearerinventory wi
          set    wi.dateinactive = trunc(sysdate),
                 wi.circinventory =
                  ((select count(nu.nonuniqueitem_id)
                    from   nonuniqueitem nu
                    where  nu.wearerinventory_id = wi.wearerinventory_id
                    and    nu.freeitem = 'N') +
                  (select count(un.uniqueitem_id)
                    from   uniqueitemnonpool un
                    where  un.wearerinventory_id = wi.wearerinventory_id
                    and    un.freeextragarment = 'N')),
	 wi.maxinventory = 0,
	 wi.systemuser_id = fp_systemuserid,
                 wi.timestamp = sysdate
          where  wi.wearerinventory_id = wisource.wearerinventory_id;
          --write log
          if lv_old_wearermplid <> wisource.weareremployment_id then
            begin
              select c.customernumber, w.wearernumber
              into   lv_customernumber, lv_wearernumber
              from   weareremployment we
              join   wearer w
              on     w.wearer_id = we.wearer_id
              join   customer c
              on     c.customer_id = w.customer_id
              where  we.weareremployment_id = wisource.weareremployment_id;
              write_log('Converted Customer ' || lv_customernumber || ' Wearer ' ||
                        lv_wearernumber);
              lv_old_wearermplid := wisource.weareremployment_id;
            end;
          end if;
        end;
      end loop; --wisource
    end update_wearerinventories;

    procedure update_wearerfunctions(fp_customerid customer.customer_id%type default null) is
    begin
      --update_wearerfunctions
      gv_message := 'update_wearerfunctions';
      --This step is only done for garments (TypeOfMerchandize = 2).
      for r in (select si.standardinventory_id,
                       (select c.customernumber from customer c where c.customer_id = wf.customer_id) customernumber,
                       wf.code wearerfunctioncode
                from   wearerfunction wf
                join   standardinventory si
                on     si.wearerfunction_id = wf.wearerfunction_id
                where  si.product_id = fp_from_productid
                and    exists (select 1
                        from   customeractivities ca
                        join   businessunit bu
                        on     bu.businessunit_id = ca.processbusinessunit_id
                        join   businessunitsperusergroup buug
                        on     buug.businessunit_id = ca.processbusinessunit_id
                        where  ca.customer_id = wf.customer_id
                        and    ca.activity_id = gv_from_product_activityid
                        and    (bu.businessunit_id = fp_businessunitid or fp_businessunitid is null)
                        and    buug.usergroup_id = gv_usergroupid)
                and    not exists (select 1
                        from   standardinventory six
                        where  six.wearerfunction_id = si.wearerfunction_id
                        and    six.product_id = fp_to_productid)
                and    (fp_customerid is null or wf.customer_id = fp_customerid)) loop
        begin
          update standardinventory si
          set    si.product_id = fp_to_productid, si.systemuser_id = fp_systemuserid,
                 si.timestamp = sysdate
          where  si.standardinventory_id = r.standardinventory_id;
          --write log
          write_log('Converted Wearer Function Code ' || r.wearerfunctioncode ||
                    ' For CustomerNumber ' || r.customernumber);
        end;
      end loop; --r
    end update_wearerfunctions;

    procedure update_contractstdinventory(fp_customerid customer.customer_id%type default null) is
        begin
          for csix in (select csi.contractstdinventory_id, csi.contractwearerfunction_id, csi.product_id,
                       csi.contractembtemp_id, ce.code
                       from contractstdinventory csi
                       join contractembtemp ce
                       on csi.contractembtemp_id = ce.contractembtemp_id
                       join contractwearerfunction cwf
                       on csi.contractwearerfunction_id = cwf.contractwearerfunction_id
                       join product p on csi.product_id = p.product_id
                       left outer join wearer w
                       on cwf.dummyforpoolwearer_id = w.wearer_id
                       where csi.product_id = fp_from_productid
                       and (fp_customerid is null or w.customer_id = fp_customerid)) loop
               begin
                 update contractstdinventory csi
                 set csi.product_id = fp_to_productid, csi.systemuser_id = fp_systemuserid, csi.timestamp = sysdate
                 where csi.contractstdinventory_id = csix.contractstdinventory_id;
                 --write log
                 write_log('Converted contract standard inventory for contract code: ' || csix.code
                 || 'for customer id: ' || nvl(fp_customerid, ''));
               end;
            end loop; --csix
     end update_contractstdinventory;


    procedure update_consumptionpoints(fp_customerid customer.customer_id%type default null) is
      lv_pldpdestination         productlistperdistribpoint%rowtype;
      lv_customerid              customer.customer_id%type;
      lv_customernumber          customer.customernumber%type;
      lv_departmentnumber        department.departmentnumber%type;
      lv_distributionpointnumber distributionpoint.distributionpointnumber%type;
      lv_desc_sizecode           sizedefinition.code%type;

      procedure copy_normstockammount(fp_sourc_plpdid in productlistperdistribpoint.productlistperdistribpoint_id%type) is
      begin
        --copy_normstockammount
        gv_message := 'copy_normstockammount';
        insert into normstockamount
          (productlistperdistribpoint_id, day_id, amount, systemuser_id, timestamp, previousamount)
          select lv_pldpdestination.productlistperdistribpoint_id, nsa.day_id, nsa.amount,
                 fp_systemuserid, sysdate /*timestamp*/, nsa.previousamount
          from   normstockamount nsa
          where  nsa.productlistperdistribpoint_id = fp_sourc_plpdid;
      end copy_normstockammount;

      procedure copy_standarddeliveries(fp_sourc_plpdid in productlistperdistribpoint.productlistperdistribpoint_id%type) is
        lv_desc_standdelline standarddeliveryline%rowtype;

        procedure copy_standarddeliveryamount(fp_src_stddellineid in standarddeliveryline.standarddeliveryline_id%type) is
        begin
          --copy_standarddeliveryamount
          gv_message := 'copy_standarddeliveryamount';
          insert into standarddeliveryamount
            (day_id, amount, systemuser_id, timestamp, standarddeliveryline_id, previousamount)
            select sta.day_id, sta.amount, fp_systemuserid, sysdate /*timestamp*/,
                   lv_desc_standdelline.standarddeliveryline_id, sta.previousamount
            from   standarddeliveryamount sta
            where  sta.standarddeliveryline_id = fp_src_stddellineid;
        end copy_standarddeliveryamount;

        procedure copy_temporarydelstops(fp_src_stddellineid in standarddeliveryline.standarddeliveryline_id%type) is
        begin
          --copy_temporarydelstops
          gv_message := 'copy_temporarydelstops';
          insert into temporarydeliverystop
            (temporarydeliverystop_id, standarddeliveryline_id, temporarystopstartweek,
             temporarystopendweek, tempstoprentforweek, tempstoprentforyearweek,
             tempstopstartweekforyear, tempstopendweekforyear, temporarystopstartyear,
             temporarystopendyear, yearlystopreturnweek, systemuser_id, timestamp,
             tempstoprentfordate, startdate, enddate)
            select seq_temporarydeliverystop.nextval, lv_desc_standdelline.standarddeliveryline_id,
                   tds.temporarystopstartweek, tds.temporarystopendweek, tds.tempstoprentforweek,
                   tds.tempstoprentforyearweek, tds.tempstopstartweekforyear,
                   tds.tempstopendweekforyear, tds.temporarystopstartyear, tds.temporarystopendyear,
                   tds.yearlystopreturnweek, fp_systemuserid, sysdate /*timestamp*/,
                   tds.tempstoprentfordate, tds.startdate, tds.enddate
            from   temporarydeliverystop tds
            where  tds.standarddeliveryline_id = fp_src_stddellineid;
        end copy_temporarydelstops;

        procedure inactivate_sdlsource(fp_src_stddellineid in standarddeliveryline.standarddeliveryline_id%type) is
        begin
          --inactivate_sdlsource
          gv_message := 'inactivate_sdlsource';
          update standarddeliveryline sdls
          set    sdls.dateinactive = trunc(sysdate), sdls.systemuser_id = fp_systemuserid,
                 sdls.timestamp = sysdate
          where  sdls.standarddeliveryline_id = fp_src_stddellineid;
        end inactivate_sdlsource;
      begin
        --copy_standarddeliveries
        gv_message := 'copy_standarddeliveries';
        /*
        Consumption Point Logistics: all past standard delivery lines are skipped.
        All current active standard delivery lines will be ended and started new for the new product.
        All future standard delivery lines are moved to the new product.
        if nothing does not yet exist for the new product, only then because if something exists we only give a message
        */
        for sdlsource in (select sdl.*
                          from   standarddeliveryline sdl
                          where  sdl.productlistperdistribpoint_id = fp_sourc_plpdid
                          and    sdl.dateinactive > trunc(sysdate)
                          and    sdl.dateactive >=
                                 coalesce((select max(sdlx.dateactive)
                                           from   standarddeliveryline sdlx
                                           where  sdlx.standarddelivery_id = sdl.standarddelivery_id
                                           and    sdlx.productlistperdistribpoint_id =
                                                  sdl.productlistperdistribpoint_id
                                           and    nvl(sdlx.deliveryscheme_id, 0) =
                                                  nvl(sdl.deliveryscheme_id, 0)
                                           and    nvl(sdlx.season_id, 0) = nvl(sdl.season_id, 0)
                                           and    sdlx.dateactive < trunc(sysdate)), trunc(sysdate))
                          order  by sdl.dateactive) loop
          begin
            --check if 1 or more exist that are still active
            select sdl.*
            into   lv_desc_standdelline
            from   standarddeliveryline sdl
            where  sdl.standarddeliveryline_id =
                   (select min(sdlx.standarddeliveryline_id)
                    from   standarddeliveryline sdlx
                    where  sdlx.standarddelivery_id = sdlsource.standarddelivery_id
                    and    sdlx.productlistperdistribpoint_id =
                           lv_pldpdestination.productlistperdistribpoint_id
                    and    nvl(sdlx.deliveryscheme_id, 0) = nvl(sdlsource.deliveryscheme_id, 0)
                    and    nvl(sdlx.season_id, 0) = nvl(sdlsource.season_id, 0)
                    and    sdlx.dateinactive > trunc(sysdate));
            --update old line cut it off anyway.
            --Inactivate StandardDeliveryLine SDLSource
            inactivate_sdlsource(sdlsource.standarddeliveryline_id);
            --write log
            write_log('There already exists a standard delivery line for customer ' ||
                      lv_customernumber || ' department ' || lv_departmentnumber ||
                      ' consumptionpoint ' || lv_distributionpointnumber || ' product ' ||
                      gv_to_productcode || ' size ' || lv_desc_sizecode || ' date active ' ||
                      to_char(lv_desc_standdelline.dateactive, 'DD-MM-YYYY') ||
                      ', please adjust manually');
          exception
            when no_data_found then
              begin
                --did not yet exist, so we create it, if it is from the past
                lv_desc_standdelline                               := sdlsource;
                lv_desc_standdelline.systemuser_id                 := fp_systemuserid;
                lv_desc_standdelline.timestamp                     := sysdate;
                lv_desc_standdelline.productlistperdistribpoint_id := lv_pldpdestination.productlistperdistribpoint_id;
                begin
                  --get destination productlistpercustomer
                  gv_message := 'get destination productlistpercustomer for source plpc ' ||
                                sdlsource.productlistpercustomer_id;
                  select ldest.productlistpercustomer_id
                  into   lv_desc_standdelline.productlistpercustomer_id
                  from   productlistpercustomer ldest
                  where  ldest.customer_id = lv_customerid
                  and    ldest.product_id = lv_pldpdestination.product_id
                  and    ldest.sizedefinition_id = lv_pldpdestination.sizedefinition_id
                  and    ldest.finishingmethod_id = lv_pldpdestination.finishingmethod_id;
                exception
                  when no_data_found then
                    begin
                      select ldest.productlistpercustomer_id
                      into   lv_desc_standdelline.productlistpercustomer_id
                      from   productlistpercustomer ldest
                      where  ldest.customer_id = lv_customerid
                      and    ldest.product_id = lv_pldpdestination.product_id
                      and    ldest.sizedefinition_id = gv_sizestarid
                      and    ldest.finishingmethod_id = lv_pldpdestination.finishingmethod_id;
                    end;
                  when too_many_rows then
                    begin
                      gv_message := 'Error, more then 1 Product List per Customer already exists for ' ||
                                    to_char(lv_customernumber) || ', Product ' || gv_to_productcode ||
                                    ', Size ' || lv_desc_sizecode ||
                                    ' ! product conversion not possible ';
                      raise gv_userexception;
                    end;
                end;
                if sdlsource.dateactive <= trunc(sysdate) then
                  begin
                    --we create a new standarddeliveryline
                    lv_desc_standdelline.dateactive := trunc(sysdate);
                    --insert into standarddeliveryline
                    lv_desc_standdelline.standarddeliveryline_id := seq_standarddeliveryline.nextval;
                    gv_message                                   := 'insert into standarddeliveryline';
                    insert into standarddeliveryline values lv_desc_standdelline;
                    --Copy all rows from StandardDeliveryAmount SDA
                    copy_standarddeliveryamount(sdlsource.standarddeliveryline_id);
                    --Copy all rows from TemporaryDeliveryStop TDS
                    copy_temporarydelstops(sdlsource.standarddeliveryline_id);
                    --Inactivate StandardDeliveryLine SDLSource
                    inactivate_sdlsource(sdlsource.standarddeliveryline_id);
                    --write_log
                    write_log('Copied CPL Distribution point for customer ' || lv_customernumber ||
                              ' department ' || lv_departmentnumber || ' consumptionpoint ' ||
                              lv_distributionpointnumber || ' product ' || gv_to_productcode ||
                              ' size ' || lv_desc_sizecode || ' date active ' ||
                              to_char(lv_desc_standdelline.dateactive, 'DD-MM-YYYY'));
                  end;
                else
                  begin
                    --We update the future stdl line  sdlsource.dateactive > trunc(sysdate)
                    --Update StandardDeliveryLine SDLSource
                    update standarddeliveryline stl
                    set    row = lv_desc_standdelline
                    where  stl.standarddeliveryline_id =
                           lv_desc_standdelline.standarddeliveryline_id;
                    --write_log
                    write_log('Moved CPL Distribution point for customer ' || lv_customernumber ||
                              ' department ' || lv_departmentnumber || ' consumptionpoint ' ||
                              lv_distributionpointnumber || ' product ' || gv_to_productcode ||
                              ' size ' || lv_desc_sizecode || ' date active ' ||
                              to_char(lv_desc_standdelline.dateactive, 'DD-MM-YYYY'));
                  end;
                end if;
              end;
          end;
        end loop;
      end copy_standarddeliveries;

      procedure copy_cirulatinginventory(fp_sourc_plpdid in productlistperdistribpoint.productlistperdistribpoint_id%type) is
        lv_circinventory      rentalqtyadjustment.quantity%type;
        lv_min_qualitygradeid qualitygrade.qualitygrade_id%type;
      begin
        --copy_cirulatinginventory
        gv_message := 'copy_cirulatinginventory';
        /*
        Circulating Inventory: the circulating for the old product must be set to 0
        and will be added for the new product. However loans are excluded,
        if there are outstanding loans these remain outstanding.
        */
        select sum(rqa.quantity), min(rqa.qualitygrade_id)
        into   lv_circinventory, lv_min_qualitygradeid
        from   rentalqtyadjustment rqa
        where  rqa.productlistperdistribpoint_id = fp_sourc_plpdid
        and    ((rqa.origin <> 2 /*Loan)*/
              and rqa.adjustmentdate <= trunc(sysdate)) or
              (rqa.endrentdate > trunc(sysdate) and rqa.origin = 2 /*Loan)*/
              ));
        if lv_circinventory > 0 then
          begin
            --Set the old product to 0:
            insert into rentalqtyadjustment
              (rentalqtyadjustment_id, productlistperdistribpoint_id, remark, quantity,
               adjustmentdate, reasoncode_id, origin, timestamp, systemuser_id, qualitygrade_id)
            values
              (seq_rentalqtyadjustment.nextval, fp_sourc_plpdid, 'Product conversion'
               /*remark*/, lv_circinventory * -1 /*quantity*/, trunc(sysdate) /*adjustmentdate*/,
               gv_reasoncodeid /*reasoncode_id->PhaseInOutProducts*/, 0 /*origin manual*/, sysdate
               /*timestamp*/, fp_systemuserid, lv_min_qualitygradeid);
            --Create circulating inventory for the new product:
            insert into rentalqtyadjustment
              (rentalqtyadjustment_id, productlistperdistribpoint_id, remark, quantity,
               adjustmentdate, reasoncode_id, origin, timestamp, systemuser_id, qualitygrade_id)
            values
              (seq_rentalqtyadjustment.nextval, lv_pldpdestination.productlistperdistribpoint_id,
               'Product conversion' /*remark*/, lv_circinventory /*quantity*/, trunc(sysdate)
               /*adjustmentdate*/, gv_reasoncodeid /*reasoncode_id->PhaseInOutProducts*/, 0
               /*origin manual*/, sysdate /*timestamp*/, fp_systemuserid, lv_min_qualitygradeid);
            --write_log
            write_log('Moved circulating inventory Distribution point for customer ' ||
                      lv_customernumber || ' department ' || lv_departmentnumber ||
                      ' consumptionpoint ' || lv_distributionpointnumber || ' product ' ||
                      gv_to_productcode || ' size ' || lv_desc_sizecode || ' Circ.inventory ' ||
                      to_char(lv_circinventory));
          end;
        end if; --lv_circinventory > 0
        /*
        All future rental quantity adjustments (except for outstanding loans) are moved to the new product.
        */
        update rentalqtyadjustment rqa
        set    rqa.productlistperdistribpoint_id = lv_pldpdestination.productlistperdistribpoint_id,
               rqa.systemuser_id = fp_systemuserid, rqa.timestamp = sysdate
        where  rqa.productlistperdistribpoint_id = fp_sourc_plpdid
        and    rqa.origin <> 2 /*Loan)*/
        and    rqa.adjustmentdate > trunc(sysdate);
      end copy_cirulatinginventory;

      procedure copy_onsiteinventory(fp_sourc_plpdid in productlistperdistribpoint.productlistperdistribpoint_id%type) is
        lv_onsiteinventory onsiteinventoryadjustment.quantity%type;
      begin
        --copy_onsiteinventory
        gv_message := 'copy_onsiteinventory fp_sourc_plpdid ' || fp_sourc_plpdid;
        /*
        Onsite Inventory: this is handled similar to the circulating inventory.
        */
        select sum(osia.quantity)
        into   lv_onsiteinventory
        from   onsiteinventoryadjustment osia
        where  osia.productlistperdistribpoint_id = fp_sourc_plpdid;
        if lv_onsiteinventory > 0 then
          begin
            --Set the old product to 0:
            insert into onsiteinventoryadjustment
              (onsiteinventoryadjustment_id, productlistperdistribpoint_id, origin, inventorydate,
               quantity, reference, systemuser_id, timestamp)
            values
              (seq_onsiteinventoryadjustment.nextval, fp_sourc_plpdid, 1
               /*origin, Manual correction*/, trunc(sysdate) /*inventorydate*/,
               lv_onsiteinventory * -1 /*quantity*/, 'Product conversion' /*reference*/,
               fp_systemuserid, sysdate /*timestamp*/);
            --Create onsite inventory for the new product:
            insert into onsiteinventoryadjustment
              (onsiteinventoryadjustment_id, productlistperdistribpoint_id, origin, inventorydate,
               quantity, reference, systemuser_id, timestamp)
            values
              (seq_onsiteinventoryadjustment.nextval,
               lv_pldpdestination.productlistperdistribpoint_id, 1 /*origin, Manual correction*/,
               trunc(sysdate) /*inventorydate*/, lv_onsiteinventory /*quantity*/,
               'Product conversion' /*reference*/, fp_systemuserid, sysdate /*timestamp*/);
            --write log
            write_log('Moved onsite inventory Distribution point for customer ' ||
                      lv_customernumber || ' department ' || lv_departmentnumber ||
                      ' consumptionpoint ' || lv_distributionpointnumber || ' product ' ||
                      gv_to_productcode || ' size ' || lv_desc_sizecode || ' onsite inventory ' ||
                      to_char(lv_onsiteinventory));
          end;
        end if; --lv_onsiteinventory > 0
      end copy_onsiteinventory;
    begin
      --update_consumptionpoints
      gv_message := 'update_consumptionpoints';
      for pldpsource in (select pld.*
                         from   productlistperdistribpoint pld
                         join   distributionpoint dp
                         on     dp.distributionpoint_id = pld.distributionpoint_id
                         join   department dep
                         on     dep.department_id = dp.department_id
                         where  pld.product_id = fp_from_productid
                         and    ((fp_from_sizedefinitionid is null) or
                               (pld.sizedefinition_id = fp_from_sizedefinitionid))
                         and    exists (select 1
                                 from   customeractivities ca
                                 join   businessunit bu
                                 on     bu.businessunit_id = ca.processbusinessunit_id
                                 join   businessunitsperusergroup buug
                                 on     buug.businessunit_id = ca.processbusinessunit_id
                                 where  ca.customer_id = dep.customer_id
                                 and    ca.activity_id = gv_from_product_activityid
                                 and    (bu.businessunit_id = fp_businessunitid or fp_businessunitid is null)
                                 and    buug.usergroup_id = gv_usergroupid
                                 and    (ca.customer_id = fp_customerid or fp_customerid is null))
                          and   (dep.customer_id = fp_customerid or fp_customerid is null)) loop
        begin
          --get data for logging.
          select c.customer_id, c.customernumber, t.departmentnumber, dip.distributionpointnumber
          into   lv_customerid, lv_customernumber, lv_departmentnumber, lv_distributionpointnumber
          from   distributionpoint dip
          join   department t
          on     t.department_id = dip.department_id
          join   customer c
          on     c.customer_id = t.customer_id
          where  dip.distributionpoint_id = pldpsource.distributionpoint_id;
          --get desc sizecode
          select s.code
          into   lv_desc_sizecode
          from   sizedefinition s
          where  s.sizedefinition_id = nvl(fp_to_sizedefinitionid, pldpsource.sizedefinition_id);
          begin
            --select if new plpd exists
            select pld.*
            into   lv_pldpdestination
            from   productlistperdistribpoint pld
            where  pld.distributionpoint_id = pldpsource.distributionpoint_id
            and    pld.product_id = fp_to_productid
            and    pld.sizedefinition_id =
                   nvl(fp_to_sizedefinitionid, pldpsource.sizedefinition_id)
            and    pld.finishingmethod_id = pldpsource.finishingmethod_id;
            --write log
            write_log('Already exists Consumption Point for for customer ' || lv_customernumber ||
                      ' department ' || lv_departmentnumber || ' consumptionpoint ' ||
                      lv_distributionpointnumber || ' product ' || gv_to_productcode || ' size ' ||
                      lv_desc_sizecode);
          exception
            when no_data_found then
              begin
                --insert into productlistperdistribpoint
                gv_message                                       := 'insert into productlistperdistribpoint';
                lv_pldpdestination                               := pldpsource;
                lv_pldpdestination.productlistperdistribpoint_id := seq_productlistperdistribpoint.nextval;
                lv_pldpdestination.product_id                    := fp_to_productid;
                lv_pldpdestination.sizedefinition_id             := nvl(fp_to_sizedefinitionid,
                                                                        pldpsource.sizedefinition_id);
                lv_pldpdestination.systemuser_id                 := fp_systemuserid;
                lv_pldpdestination.timestamp                     := sysdate;
                --determine the count sequence
                select nvl(max(plpd.countsequence), 0) + 1
                into   lv_pldpdestination.countsequence
                from   productlistperdistribpoint plpd
                where  distributionpoint_id = pldpsource.distributionpoint_id;
                insert into productlistperdistribpoint values lv_pldpdestination;
                --copy_normstockammount 3.4.5.2
                copy_normstockammount(pldpsource.productlistperdistribpoint_id);
                --write log
                write_log('Created Consumption Point for for customer ' || lv_customernumber ||
                          ' department ' || lv_departmentnumber || ' consumptionpoint ' ||
                          lv_distributionpointnumber || ' product ' || gv_to_productcode ||
                          ' size ' || lv_desc_sizecode);
              end;
          end;
          --copy_standarddeliveries 3.4.5.3
          copy_standarddeliveries(pldpsource.productlistperdistribpoint_id);
          --copy_cirulatinginventory 3.4.5.4 / 3.4.5.5
          copy_cirulatinginventory(pldpsource.productlistperdistribpoint_id);
          --copy_onsiteinventory 3.4.5.6
          copy_onsiteinventory(pldpsource.productlistperdistribpoint_id);
        end;
      end loop; --pldpsource
    end update_consumptionpoints;

    procedure update_deliveryvariations(fp_customerid customer.customer_id%type default null) is
    begin
      --update_deliveryvariations
      gv_message := 'update_deliveryvariations';
      for o in (select dv.deliveryvariations_id, c.customernumber, dep.departmentnumber,
                       dp.distributionpointnumber, dv.deliverydate, dv.distributionpoint_id,
                       dv.product_id, dv.sizedefinition_id, dv.finishingmethod_id, dv.origin,
                       dv.causenote_id, dv.updaterentqty, dv.soilcountsubtype, dv.weborderline_id,
                       dv.reference, dv.adjustmentreason_id, dv.reasoncode_id, dv.amount,
                       dv.stockcountqty
                from   deliveryvariations dv
                join   distributionpoint dp
                on     dp.distributionpoint_id = dv.distributionpoint_id
                join   department dep
                on     dep.department_id = dp.department_id
                join   customer c
                on     c.customer_id = dep.customer_id
                where  dv.product_id = fp_from_productid
                and    (fp_from_sizedefinitionid is null or
                      dv.sizedefinition_id = fp_from_sizedefinitionid)
                and    dv.processed = 'N'
                and    exists (select 1
                        from   customeractivities ca
                        join   businessunit bu
                        on     bu.businessunit_id = ca.processbusinessunit_id
                        join   businessunitsperusergroup buug
                        on     buug.businessunit_id = ca.processbusinessunit_id
                        where  ca.customer_id = dep.customer_id
                        and    ca.activity_id = gv_from_product_activityid
                        and    (bu.businessunit_id = fp_businessunitid or fp_businessunitid is null)
                        and    buug.usergroup_id = gv_usergroupid)
                and    (c.customer_id = fp_customerid or fp_customerid is null)
                order  by c.customernumber, dep.departmentnumber, dp.distributionpointnumber,
                          dv.deliverydate) loop
        begin
          --Update DeliveryVariations DV
          update deliveryvariations dv
          set    dv.product_id = fp_to_productid,
                 dv.sizedefinition_id = nvl(fp_to_sizedefinitionid, dv.sizedefinition_id),
                 dv.systemuser_id = fp_systemuserid, dv.timestamp = sysdate
          where  dv.deliveryvariations_id = o.deliveryvariations_id;
          --write_log
          write_log('Moved CPL Distribution point for customer ' || o.customernumber ||
                    ' department ' || o.departmentnumber || ' consumptionpoint ' ||
                    o.distributionpointnumber || ' to product ' || gv_to_productcode ||
                    ' date active ' || to_char(o.deliverydate, 'DD-MM-YYYY'));
        exception
          when dup_val_on_index then
            begin
              /*DISTRIBUTIONPOINT_ID,
              PRODUCT_ID, SIZEDEFINITION_ID, FINISHINGMETHOD_ID,
              PACKINGNOTE_ID, PROCESSED, DELIVERYDATE, ORIGIN,
              CAUSENOTE_ID, UPDATERENTQTY, SOILCOUNTSUBTYPE,
              WEBORDERLINE_ID, REFERENCE, ADJUSTMENTREASON_ID, REASONCODE_ID
              */
              update deliveryvariations dv
              set    dv.amount = dv.amount + o.amount,
                     dv.stockcountqty = nvl(dv.stockcountqty, 0) + nvl(o.stockcountqty, 0),
                     dv.systemuser_id = fp_systemuserid, dv.timestamp = sysdate
              where  dv.distributionpoint_id = o.distributionpoint_id
              and    dv.product_id = o.product_id
              and    dv.sizedefinition_id = o.sizedefinition_id
              and    dv.finishingmethod_id = o.finishingmethod_id
              and    dv.packingnote_id is null
              and    dv.processed = 'N'
              and    dv.deliverydate = o.deliverydate
              and    dv.origin = o.origin
              and    dv.causenote_id is null
              and    dv.updaterentqty = o.updaterentqty
              and    dv.soilcountsubtype = o.soilcountsubtype
              and    ((dv.weborderline_id is null and o.weborderline_id is null) or
                    dv.weborderline_id = o.weborderline_id)
              and    ((dv.reference is null and o.reference is null) or dv.reference = o.reference)
              and    ((dv.reasoncode_id is null and o.reasoncode_id is null) or
                    dv.reasoncode_id = o.reasoncode_id)
              and    ((dv.adjustmentreason_id is null and o.adjustmentreason_id is null) or
                    dv.adjustmentreason_id = o.adjustmentreason_id);
              --write_log
              write_log('Updated CPL Distribution point for customer ' || o.customernumber ||
                        ' department ' || o.departmentnumber || ' consumptionpoint ' ||
                        o.distributionpointnumber || ' to product ' || gv_to_productcode ||
                        ' date active ' || to_char(o.deliverydate, 'DD-MM-YYYY'));
              --delete original
              delete from deliveryvariations dv
              where  dv.deliveryvariations_id = o.deliveryvariations_id;
            end;
        end;
      end loop;
    end update_deliveryvariations;

    procedure update_soiltickets(fp_customerid customer.customer_id%type default null) is
      lv_counter number := 0;
    begin
      --update_soiltickets
      gv_message := 'update_soiltickets';
      for stx in (select stl.soilticketline_id, st.soilticket_id, stl.product_id,
                         stl.sizedefinition_id, stl.finishingmethod_id, stl.unrelatedloan,
                         stl.countlightframe, stl.countkeypad, stl.countconverted, stl.countabused,
                         stl.soilweight, stl.countloss
                  from   soilticket st
                  join   soilticketline stl
                  on     stl.soilticket_id = st.soilticket_id
                  where  st.processed = 'N'
                  and    exists (select 1
                          from   businessunit bu
                          where  bu.businessunit_id = st.processbusinessunit_id
                          and    (bu.businessunit_id = fp_businessunitid or fp_businessunitid is null))
                  and    exists (select 1
                          from   businessunitsperusergroup bug
                          where  bug.businessunit_id = st.processbusinessunit_id
                          and    bug.usergroup_id = gv_usergroupid)
                  and    stl.product_id = fp_from_productid
                  and    (fp_from_sizedefinitionid is null or
                        stl.sizedefinition_id = fp_from_sizedefinitionid)
                  and    (st.customer_id = fp_customerid or fp_customerid is null)) loop
        begin
          --update soilticketline
          update soilticketline stl
          set    stl.product_id = fp_to_productid,
                 stl.sizedefinition_id = nvl(fp_to_sizedefinitionid, stl.sizedefinition_id),
                 stl.systemuser_id = fp_systemuserid, stl.timestamp = sysdate
          where  stl.soilticketline_id = stx.soilticketline_id;
          lv_counter := lv_counter + 1;
        exception
          when dup_val_on_index then
            begin
              --update soilticketline
              update soilticketline stl
              set    stl.countlightframe = coalesce(stl.countlightframe, 0) +
                                            coalesce(stx.countlightframe, 0),
                     stl.countkeypad = coalesce(stl.countkeypad, 0) + coalesce(stx.countkeypad, 0),
                     stl.countconverted = coalesce(stl.countconverted, 0) +
                                           coalesce(stx.countconverted, 0),
                     stl.countabused = coalesce(stl.countabused, 0) + coalesce(stx.countabused, 0),
                     stl.soilweight = coalesce(stl.soilweight, 0) + coalesce(stx.soilweight, 0),
                     stl.countloss = coalesce(stl.countloss, 0) + coalesce(stx.countloss, 0),
                     stl.systemuser_id = fp_systemuserid, stl.timestamp = sysdate
              where  stl.soilticket_id = stx.soilticket_id
              and    stl.product_id = fp_to_productid
              and    stl.sizedefinition_id = nvl(fp_to_sizedefinitionid, stl.sizedefinition_id)
              and    stl.finishingmethod_id = stx.finishingmethod_id
              and    stl.unrelatedloan = stx.unrelatedloan;
              --delete old line
              delete from soilticketline stl where stl.soilticketline_id = stx.soilticketline_id;
              --count rows
              lv_counter := lv_counter + 1;
            end;
        end;
      end loop; --stx
      if lv_counter > 0 then
        begin
          --write log
          write_log('Number of soil ticket lines converted ' || lv_counter);
        end;
      end if;
    end update_soiltickets;

    procedure update_packingnote(fp_customerid customer.customer_id%type default null) is
      lv_counter number := 0;
    begin
      --update_packingnote
      gv_message := 'update_packingnote';
      for pkx in (select pkl.packingnoteline_id, pk.packingnote_id, pkl.product_id,
                         pkl.sizedefinition_id, pkl.finishingmethod_id, pkl.deliveredamount,
                         pkl.tobedeliveredamount, pkl.standardamount, pkl.variationamount, pkl.amount,
                         pkl.replacementqty, pkl.autoreplacementqty, pkl.updaterentqty,
                         pkl.nochargefirstissue, pkl.nochargeactiveseason, pkl.deliveredcogqty,
                         pkl.nochargefirstissuecog, pkl.nodeliveryamount, pkl.nochargeprevrejected,
                         pkl.nochargeprevshortage, pkl.stockcountqty, pkl.deliveredexclexcessqty,
                         pkl.heavysoilqty, pkl.qtysold, pkl.receivedqty, pkl.assembledquantity,
                         pkl.reducequantity, pkl.actualdelivery, pkl.replacementlossqty,
                         pkl.qtyfreecleanchange, pkl.chargereturnedfromcirc
                  from   packingnote pk
                  join   packingnoteline pkl
                  on     pkl.packingnote_id = pk.packingnote_id
                  where  pkl.invoiceheader_id is null
                  and    exists (select 1
                          from   businessunit bu
                          where  bu.businessunit_id = pk.processbusinessunit_id
                          and    (bu.businessunit_id = fp_businessunitid or fp_businessunitid is null))
                  and    exists (select 1
                          from   businessunitsperusergroup bug
                          where  bug.businessunit_id = pk.processbusinessunit_id
                          and    bug.usergroup_id = gv_usergroupid)
                  and    pkl.product_id = fp_from_productid
                  and    (fp_from_sizedefinitionid is null or
                        pkl.sizedefinition_id = fp_from_sizedefinitionid)
                  and   (pk.distributionpoint_id in (select dp.distributionpoint_id
                                                     from distributionpoint dp
                                                     join department dep
                                                     on dp.department_id = dep.department_id
                                                     join customer c
                                                     on c.customer_id = dep.customer_id
                                                     where c.customer_id = fp_customerid ) or fp_customerid is null)) loop
        begin
          --update packingnoteline
          update packingnoteline pkl
          set    pkl.product_id = fp_to_productid,
                 pkl.sizedefinition_id = nvl(fp_to_sizedefinitionid, pkl.sizedefinition_id),
                 pkl.systemuser_id = fp_systemuserid, pkl.timestamp = sysdate
          where  pkl.packingnoteline_id = pkx.packingnoteline_id;
          lv_counter := lv_counter + 1;
        exception
          when dup_val_on_index then
            begin
              --update packingnoteline
              update packingnoteline pkl
              set    pkl.deliveredamount = pkl.deliveredamount + pkx.deliveredamount,
                     pkl.variationamount = pkl.variationamount + pkx.variationamount,
                     pkl.standardamount = pkl.standardamount + pkx.standardamount,
                     pkl.tobedeliveredamount = pkl.tobedeliveredamount + pkx.tobedeliveredamount,
                     pkl.replacementqty = pkl.replacementqty + pkx.replacementqty,
                     pkl.autoreplacementqty = pkl.autoreplacementqty + pkx.autoreplacementqty,
                     pkl.updaterentqty = pkl.updaterentqty + pkx.updaterentqty,
                     pkl.nochargefirstissue = pkl.nochargefirstissue + pkx.nochargefirstissue,
                     pkl.nochargeactiveseason = pkl.nochargeactiveseason + pkx.nochargeactiveseason,
                     pkl.deliveredcogqty = pkl.deliveredcogqty + pkx.deliveredcogqty,
                     pkl.amount = pkl.amount + pkx.amount,
                     pkl.nochargefirstissuecog = pkl.nochargefirstissuecog +
                                                  pkx.nochargefirstissuecog,
                     pkl.nodeliveryamount = pkl.nodeliveryamount + pkx.nodeliveryamount,
                     pkl.nochargeprevrejected = pkl.nochargeprevrejected + pkx.nochargeprevrejected,
                     pkl.nochargeprevshortage = pkl.nochargeprevshortage + pkx.nochargeprevshortage,
                     pkl.stockcountqty = pkl.stockcountqty + pkx.stockcountqty,
                     pkl.deliveredexclexcessqty = pkl.deliveredexclexcessqty +
                                                   pkx.deliveredexclexcessqty,
                     pkl.heavysoilqty = pkl.heavysoilqty + pkx.heavysoilqty,
                     pkl.qtysold = pkl.qtysold + pkx.qtysold,
                     pkl.receivedqty = pkl.receivedqty + pkx.receivedqty,
                     pkl.assembledquantity = pkl.assembledquantity + pkx.assembledquantity,
                     pkl.reducequantity = pkl.reducequantity + pkx.reducequantity,
                     pkl.actualdelivery = pkl.actualdelivery + pkx.actualdelivery,
                     pkl.replacementlossqty = pkl.replacementlossqty + pkx.replacementlossqty,
                     pkl.qtyfreecleanchange = pkl.qtyfreecleanchange + pkx.qtyfreecleanchange,
                     pkl.chargereturnedfromcirc = pkl.chargereturnedfromcirc +
                                                   pkx.chargereturnedfromcirc,
                     pkl.systemuser_id = fp_systemuserid, pkl.timestamp = sysdate
              where  pkl.packingnote_id = pkx.packingnote_id
              and    pkl.product_id = fp_to_productid
              and    pkl.sizedefinition_id = nvl(fp_to_sizedefinitionid, pkl.sizedefinition_id)
              and    pkl.finishingmethod_id = pkx.finishingmethod_id;
              --delete old line
              delete from packingnoteline pkl
              where  pkl.packingnoteline_id = pkx.packingnoteline_id;
              --count rows
              lv_counter := lv_counter + 1;
            end;
        end;
      end loop; --pkx
      if lv_counter > 0 then
        begin
          --write log
          write_log('Number of packingnote lines converted ' || lv_counter || 'for customer id: ' || nvl(fp_customerid, ''));
        end;
      end if;
    end update_packingnote;

    procedure issue_history(fp_customerid customer.customer_id%type default null) is
    begin
      --issue_history
      gv_message := 'issue_history';
      update issuehistory ih
      set    ih.product_link_id = fp_to_productid,
             ih.sizedefinition_link_id = nvl(fp_to_sizedefinitionid, ih.sizedefinition_link_id),
             ih.timestamp = sysdate, ih.systemuser_id = fp_systemuserid
      where  ih.product_link_id = fp_from_productid
      and    nvl(fp_from_sizedefinitionid, ih.sizedefinition_link_id) = ih.sizedefinition_link_id
      and    ih.invoiceheader_id is null
      and    exists (select 1
              from   businessunit bu
              where  bu.businessunit_id = ih.processbusinessunit_id
              and    (bu.businessunit_id = fp_businessunitid or fp_businessunitid is null))
      and    exists (select 1
              from   businessunitsperusergroup bug
              where  bug.businessunit_id = ih.processbusinessunit_id
              and    bug.usergroup_id = gv_usergroupid)
      and    (ih.customer_link_id = fp_customerid or fp_customerid is null);
      if sql%rowcount > 0 then
        begin
          --write log
          write_log('Updated ' || sql%rowcount || ' issue history records from product ' ||
                    gv_from_productcode || ' to product ' || gv_to_productcode || 'for customer id: ' || nvl(fp_customerid, ''));
        end;
      end if;
    end issue_history;

    procedure repair_history(fp_customerid customer.customer_id%type default null) is
    begin
      --repair_history
      gv_message := 'repair_history';
      update repairhistory rh
      set    rh.product_link_id = fp_to_productid, rh.timestamp = sysdate,
             rh.systemuser_id = fp_systemuserid
      where  rh.product_link_id = fp_from_productid
      and    rh.invoiceheader_id is null
      and    exists (select 1
              from   businessunit bu
              where  bu.businessunit_id = rh.businessunit_id
              and    (bu.businessunit_id = fp_businessunitid or fp_businessunitid is null))
      and    exists (select 1
              from   businessunitsperusergroup bug
              where  bug.businessunit_id = rh.businessunit_id
              and    bug.usergroup_id = gv_usergroupid)
      and    (rh.customer_link_id = fp_customerid or fp_customerid is null);
      if sql%rowcount > 0 then
        begin
          --write log
          write_log('Updated ' || sql%rowcount || ' repair history records from product ' ||
                    gv_from_productcode || ' to product ' || gv_to_productcode || 'for customer id: ' || nvl(fp_customerid, ''));
        end;
      end if;
    end repair_history;

    procedure out_of_circulation_history(fp_customerid customer.customer_id%type default null) is
    begin
      --out_of_circulation_history
      gv_message := 'out_of_circulation_history';
      update outofcirculationhistory oh
      set    oh.product_link_id = fp_to_productid,
             oh.sizedefinition_link_id = nvl(fp_to_sizedefinitionid, oh.sizedefinition_link_id),
             oh.timestamp = sysdate, oh.systemuser_id = fp_systemuserid
      where  oh.product_link_id = fp_from_productid
      and    nvl(fp_from_sizedefinitionid, oh.sizedefinition_link_id) = oh.sizedefinition_link_id
      and    oh.invoiceheader_id is null
      and    exists (select 1
              from   businessunit bu
              where  bu.businessunit_id = oh.processbusinessunit_id
              and    (bu.businessunit_id = fp_businessunitid or fp_businessunitid is null))
      and    exists (select 1
              from   businessunitsperusergroup bug
              where  bug.businessunit_id = oh.processbusinessunit_id
              and    bug.usergroup_id = gv_usergroupid)
      and    (oh.customer_link_id = fp_customerid or fp_customerid is null);
      if sql%rowcount > 0 then
        begin
          --write log
          write_log('Updated ' || sql%rowcount ||
                    ' out of circulation history records from product ' || gv_from_productcode ||
                    ' to product ' || gv_to_productcode || 'for customer id: ' || nvl(fp_customerid, ''));
        end;
      end if;
    end out_of_circulation_history;

    procedure garment_sales_history(fp_customerid customer.customer_id%type default null) is
    begin
      --garment_sales_history
      gv_message := 'garment_sales_history';
      update garmentsaleshistory gsh
      set    gsh.product_link_id = fp_to_productid,
             gsh.sizedefinition_link_id = nvl(fp_to_sizedefinitionid, gsh.sizedefinition_link_id),
             gsh.timestamp = sysdate, gsh.systemuser_id = fp_systemuserid
      where  gsh.product_link_id = fp_from_productid
      and    (fp_from_sizedefinitionid is null or
            gsh.sizedefinition_link_id = fp_from_sizedefinitionid)
      and    gsh.invoiceheader_id is null
      and    exists (select 1
              from   businessunit bu
              where  bu.businessunit_id = gsh.processbusinessunit_id
              and    (bu.plant_id = businessunit_id or fp_businessunitid is null))
      and    exists (select 1
              from   businessunitsperusergroup bug
              where  bug.businessunit_id = gsh.processbusinessunit_id
              and    bug.usergroup_id = gv_usergroupid)
      and   (gsh.customer_link_id = fp_customerid or fp_customerid is null);
      if sql%rowcount > 0 then
        begin
          --write log
          write_log('Updated ' || sql%rowcount || ' garment sales history records from product ' ||
                    gv_from_productcode || ' to product ' || gv_to_productcode || 'for customer id:' || nvl(fp_customerid, ''));
        end;
      end if;
    end garment_sales_history;

    procedure unrelated_loans(fp_customerid customer.customer_id%type default null) is
    begin
      --unrelated_loans
      gv_message := 'unrelated_loans';
      for x in (select ul.unrelatedloan_id, ul.startdate,
                       (select c.customernumber from customer c where c.customer_id = ul.customer_id) customernumber
                from   unrelatedloan ul
                join   product p
                on     p.product_id = ul.product_id
                join   productgroup pg
                on     pg.productgroup_id = p.productgroup_id
                join   customeractivities ca
                on     (ca.customer_id = ul.customer_id and ca.activity_id = pg.activity_id)
                join   businessunit bu
                on     bu.businessunit_id = ca.processbusinessunit_id
                where  ul.product_id = fp_from_productid
                and    ((fp_from_sizedefinitionid is null) or
                      (ul.sizedefinition_id = fp_from_sizedefinitionid))
                and    ul.deliveredqty -
                       (ul.returnedqty + ul.correctedreturnedqty + ul.billedforlossqty) > 0
                and    ca.customer_id = ul.customer_id
                and    ca.activity_id = pg.activity_id
                and    bu.businessunit_id = ca.processbusinessunit_id
                and    ((fp_businessunitid is null) or (bu.businessunit_id = fp_businessunitid))
                and   (ul.customer_id = fp_customerid or fp_customerid is null)
                and    exists (select 1
                        from   businessunitsperusergroup buug
                        where  buug.businessunit_id = ca.processbusinessunit_id
                        and    buug.usergroup_id = gv_usergroupid)) loop
        begin
          --update unrelatedloan
          update unrelatedloan ul
          set    ul.product_id = fp_to_productid,
                 ul.sizedefinition_id = nvl(fp_to_sizedefinitionid, ul.sizedefinition_id),
                 ul.systemuser_id = fp_systemuserid, ul.timestamp = sysdate
          where  ul.unrelatedloan_id = x.unrelatedloan_id;
          --write log
          write_log('Converted Unrelated Loan for customer ' || to_char(x.customernumber) ||
                    ' start date ' || to_char(x.startdate, 'DD-MM-YYYY') || ' from product ' ||
                    gv_from_productcode || ' to procuct ' || gv_to_productcode);
        end;
      end loop;
    end unrelated_loans;

    procedure upd_customerproductconversion(fp_customerid customer.customer_id%type) is
      begin
        update customerproductconversion cpc
        set cpc.processed = 'Y',
        cpc.timestamp = sysdate
        where cpc.customer_id = fp_customerid;
    end upd_customerproductconversion;

    procedure delete_customerproductconversion is
    begin
      delete from customerproductconversion cpc
       where cpc.jobrun_id = fp_jobrunid;
      commit;
    end delete_customerproductconversion;

    procedure finalize is
  begin
    --finalize
    gv_message := 'finalize';
    if fp_testrun = 'Y' then
      begin
        rollback;
        fp_result_message := 'Test run OK, for BU(s) ' || gv_bucode;
        if fp_selection = 'Y' then
          delete_customerproductconversion;
         end if;
      end;
    else
      begin
        commit;
        fp_result_message := 'OK, for BU(s) ' || gv_bucode;
      end;
    end if;
    fp_result := 0; --Ok!
    write_log(fp_result_message, 1);
  end finalize;

  begin
    --convertproducts
    --x.x.x chapters from document ProductConversionWizardDlg.doc
    gv_message := 'convertproducts';
    if fp_selection = 'N' then
      begin
        initialize;
        --3.1.1 Product settings
        --create missing product sizes
        create_missing_productsizes;
        --create missing product finishingmethods
        create_missing_prodfinishmeth;
        --check_deactivate_product
        check_deactivate_product;
       end;
    end if;
    --3.2 Stockroom
    if fp_selection = 'N' then
      begin
        --3.1.2 General Price / Discount Lists
        --copy_generalpricelists
        copy_generalpricelists();
        convert_stockroom_product;
        --3.2.2 Work Orders
        update_workorders();
        --3.2.3 Purchase Orders
        update_purchaseorders();
        --3.3 Unique Items
        --3.3.1 Unique Items
        update_uniqueitems();
        --3.3.2 Delivery Scans
        update_deliveryscans();
        --3.4 Customer Product Entities
        --3.4.1 Product List per Customer
        update_productlistpercustomer();
        --3.4.2 Customer Specific Prices and Discounts
        --->see copy_plpc_prices_discounts as part of update_productlistpercustomer
        --3.4.3 Wearer Inventories
        update_wearerinventories();
        --3.4.4 Wearer Functions
        update_wearerfunctions();
        update_contractstdinventory();
        --3.4.5 Consumption Point Logistics, Circulating and Onsite Inventory
        update_consumptionpoints();
        --3.4.6 Delivery Variations
        update_deliveryvariations();
       --3.3.3 update soil tickets
        update_soiltickets();
        --3.3.4 update packingnote
        update_packingnote();
        --3.3.5 Issue History
        issue_history();
        --3.3.6 Repair History
        repair_history();
        --3.3.7 Out of Circulation History
        out_of_circulation_history();
        --3.3.8 Garment Sales History
        garment_sales_history();
        --3.4.7 Unrelated Loans
        unrelated_loans();
        finalize;
      end;
      else
        for x in (select cpc.customer_id, cpc.sourceproduct_id, cpc.sourcesize_id,
                  cpc.destinationproduct_id, cpc.destinationsize_id
                  from customerproductconversion cpc
                  where cpc.processed = 'N'
                  and cpc.jobrun_id = fp_jobrunid) loop
         begin
           fp_from_productid := x.sourceproduct_id;
           fp_from_sizedefinitionid := x.sourcesize_id;
           fp_to_productid := x.destinationproduct_id;
           fp_to_sizedefinitionid := x.destinationsize_id;
            --get customer number for log
            gv_message := 'get customer number for log';
            select max(c.customernumber)
            into   gv_customernumber
            from   customer c
            where  c.customer_id = x.customer_id;
           initialize;
            --get size code for log
            gv_message := 'get size for log';
            select s.code
            into   gv_from_sizecode
            from   sizedefinition s
            where  s.sizedefinition_id = fp_from_sizedefinitionid
            or     (fp_from_sizedefinitionid is null and s.sizedefinition_id = gv_sizestarid);
           --3.1.1 Product settings
           --create missing product sizes
           create_missing_productsizes;
           --create missing product finishingmethods
           create_missing_prodfinishmeth;
           --3.1.2 General Price / Discount Lists
           --copy_generalpricelists
           copy_generalpricelists(x.customer_id);
           --3.2.2 Work Orders
           update_workorders(x.customer_id);
           --3.2.3 Purchase Orders
           update_purchaseorders(x.customer_id);
           --3.3 Unique Items
           --3.3.1 Unique Items
           update_uniqueitems(x.customer_id);
           --3.3.2 Delivery Scans
           update_deliveryscans(x.customer_id);
           --3.4 Customer Product Entities
           --3.4.1 Product List per Customer
           update_productlistpercustomer(x.customer_id);
           --3.4.2 Customer Specific Prices and Discounts
           --->see copy_plpc_prices_discounts as part of update_productlistpercustomer
           --3.4.3 Wearer Inventories
           update_wearerinventories(x.customer_id);
           --3.4.4 Wearer Functions
           update_wearerfunctions(x.customer_id);
           update_contractstdinventory(x.customer_id);
           --3.4.5 Consumption Point Logistics, Circulating and Onsite Inventory
           update_consumptionpoints(x.customer_id);
           --3.4.6 Delivery Variations
           update_deliveryvariations(x.customer_id);
           --3.3.3 update soil tickets
           update_soiltickets(x.customer_id);
           --3.3.4 update packingnote
           update_packingnote(x.customer_id);
           --3.3.5 Issue History
           issue_history(x.customer_id);
           --3.3.6 Repair History
           repair_history(x.customer_id);
           --3.3.7 Out of Circulation History
           out_of_circulation_history(x.customer_id);
           --3.3.8 Garment Sales History
           garment_sales_history(x.customer_id);
           --3.4.7 Unrelated Loans
           unrelated_loans(x.customer_id);
           --update customer from customerproductconversion
           upd_customerproductconversion(x.customer_id);
           finalize;
           --exception handling for customers
         exception
           when gv_userexception then
             begin
                fp_result := 1;
                rollback;
                delete_customerproductconversion;
                fp_result_message := gv_message || ' for customer id: ' || x.customer_id;
                write_log(fp_result_message, 3);
             end;
           when no_data_found then
             begin
                fp_result := 2;
                rollback;
                delete_customerproductconversion;
                fp_result_message := 'Error No Data Found ' || gv_message || ' for customer id: ' || x.customer_id;
                write_log(fp_result_message, 3);
             end;
           when others then
             begin
                fp_result := 3;
                rollback;
                delete_customerproductconversion;
                fp_result_message := 'Error Others ' || gv_message || chr(10) || substr(sqlerrm, 1, 500) || ' for customer id: ' || x.customer_id ;
                write_log(fp_result_message, 3);
             end;
         end;
        end loop;
    end if;
  end convertproducts;
begin
  --convertproducts
  convertproducts;
exception
  --exception handling global
  when dup_val_on_index then
    begin
      fp_result := 2;
      rollback;
      fp_result_message := 'Data already exists ' || gv_message || chr(10) ||
                           substr(sqlerrm, 1, 500);
      write_log(fp_result_message, 3);
    end;
  when gv_userexception then
    begin
      fp_result := 1;
      rollback;
      fp_result_message := gv_message;
      write_log(fp_result_message, 3);
    end;
  when no_data_found then
    begin
      fp_result := 2;
      rollback;
      fp_result_message := 'Error No Data Found ' || gv_message;
      write_log(fp_result_message, 3);
    end;
  when others then
    begin
      fp_result := 3;
      rollback;
      fp_result_message := 'Error Others ' || gv_message || chr(10) || substr(sqlerrm, 1, 500);
      write_log(fp_result_message, 3);
    end;
end productconversionwizard;
/
create or replace procedure recalculatedelbillquantities(fp_plantcode    in varchar2,
                                                         fp_systemuserid in number,
                                                         fp_statusout    out nocopy number,
                                                         fp_message      out nocopy varchar2) is

  --recalculatedelbillquantities version 0.4
  --ABS-50995 CUS - ABS-56069 Del/bill % for non-garment items
  --Global variables
  gv_user_exception exception;
  gv_plantid     plant.plant_id%type;
  m_bufferperiod systemsetting.value%type;
  m_enddate      date;

  --internal procedures
  procedure write_log(fp_log_message in abslog.message%type,
                      fp_priority    in abslog.priority%type default 1) is
  begin
    fp_message := fp_log_message;
    abslogwrite.abslog_write(5, 'recalculatedelbillquantities', gv_plantid, fp_priority,
                             fp_log_message, fp_systemuserid);
  end write_log;

  procedure intialize is
  begin
    --intialize
    --1 As a first step determine if a plant is known.
    fp_statusout := 1; --error with parameters
    if fp_plantcode is null then
      begin
        fp_message := 'Parameter fp_plantcode cannot be left blank!';
        raise gv_user_exception;
      end;
    else
      begin
        --get plant id
        fp_message := 'Plant code (fp_plantcode) ' || fp_plantcode;
        select pt.plant_id into gv_plantid from plant pt where pt.code = fp_plantcode;
      end;
    end if;
    if fp_systemuserid is null then
      begin
        fp_message := 'Parameter fp_systemuserid cannot be left blank!';
        raise gv_user_exception;
      end;
    end if;
    --2 As a next step determine the value of system setting FIXEDDELBILLBUFFERPERIOD, must exist!
    fp_statusout := 2; --error with systemsetting
    fp_message   := 'System setting FIXEDDELBILLBUFFERPERIOD for Plant code ' || fp_plantcode;
    select st.value
    into   m_bufferperiod
    from   systemsetting st
    where  st.name = 'FIXEDDELBILLBUFFERPERIOD'
    and    st.plant_id = gv_plantid;
    --3 If the system setting was found, then calculate the end date
    fp_statusout := 3; --error with enddate determination
    fp_message   := 'Determine enddate with bufferperiod ' || m_bufferperiod;
    m_enddate    := sysdate + to_number(m_bufferperiod);
  end intialize;

  procedure recalculate is
    --recalculate
    lv_rec_plpd      productlistperdistribpoint%rowtype;
    m_totalcirc      rentalqtyadjustment.quantity%type;
    m_stddeliveryqty rentalqtyadjustment.quantity%type;
    m_deliverydays   number;
    m_remainder      number;
    m_deliveryperday number;

    procedure rqa_set_status_to(fp_recalcstatus in rentalqtyadjustment.recalcstatus%type) is
    begin
      --rqa_set_status_to
      fp_message := 'recalculate.rqa_set_status_to ' || fp_recalcstatus;
      --Mark the record as being recalculated, RQA.RecalcStatus = fp_recalcstatus
      update rentalqtyadjustment rqa
      set    rqa.recalcstatus = fp_recalcstatus, rqa.systemuser_id = fp_systemuserid,
             rqa.timestamp = sysdate
      where  rqa.adjustmentdate <= m_enddate
      and    rqa.recalcstatus = (fp_recalcstatus - 1);
    end rqa_set_status_to;

    procedure process_standarddellines(fp_productlistperdistribpoint in productlistperdistribpoint.productlistperdistribpoint_id%type) is
      procedure process_standarddelamount(fp_standarddeliverylineid in standarddeliveryline.standarddeliveryline_id%type) is
        m_lastdayid day.day_id%type;
      begin
        --process_standarddelamount
        fp_message := 'process_standarddelamount fp_standarddeliverylineid ' ||
                      fp_standarddeliverylineid;
        for z in (select sta.*
                  from   standarddeliveryamount sta
                  where  sta.standarddeliveryline_id = fp_standarddeliverylineid
                  order  by sta.day_id) loop
          begin
            update standarddeliveryamount sta
            set    sta.amount = m_deliveryperday, sta.systemuser_id = fp_systemuserid,
                   sta.timestamp = sysdate
            where  sta.standarddeliveryline_id = z.standarddeliveryline_id
            and    sta.day_id = z.day_id;
            m_lastdayid := z.day_id;
          end;
        end loop; --z
        --In case there was a remainder add it to the last delivery day
        if m_remainder > 0 then
          begin
            update standarddeliveryamount sta
            set    sta.amount = sta.amount + m_remainder, sta.systemuser_id = fp_systemuserid,
                   sta.timestamp = sysdate
            where  sta.standarddeliveryline_id = fp_standarddeliverylineid
            and    sta.day_id = m_lastdayid;
          end;
        end if;
      end process_standarddelamount;
    begin
      --Start processing all active StandardDeliveryLine (SDL) records that are linked to the current PLPDP
      for y in (select stl.*
                from   standarddeliveryline stl
                where  stl.productlistperdistribpoint_id = fp_productlistperdistribpoint
                and    stl.dateactive <= sysdate
                and    stl.dateinactive > m_enddate) loop
        begin
          --Recalculate fixed rent qty to be billed when a percentage is defined
          if lv_rec_plpd.billingpercentage > 0 then
            begin
              --Recalculate the fixed rent quantity
              fp_message := 'update standarddeliveryline id ' || y.standarddeliveryline_id;
              update standarddeliveryline stl
              set    stl.fixedrentquantity = ceil((m_totalcirc *
                                                   (lv_rec_plpd.billingpercentage / 100))),
                     stl.systemuser_id = fp_systemuserid, stl.timestamp = sysdate
              where  stl.standarddeliveryline_id = y.standarddeliveryline_id;
            end;
          end if;
          --Recalculate the standard delivery qty when a percentage is defined
          if lv_rec_plpd.deliverypercentage > 0 then
            begin
              --Recalculate the standard delivery quantity
              m_stddeliveryqty := ceil((m_totalcirc * (lv_rec_plpd.deliverypercentage / 100)));
              --Determine the number of delivery days for this SDL
              select count(1)
              into   m_deliverydays
              from   standarddeliveryamount sta
              where  sta.standarddeliveryline_id = y.standarddeliveryline_id;
              if m_deliverydays = 0 then
                begin
                  write_log('No delivery days defined for SDL with ID = ' ||
                            y.standarddeliveryline_id, 3);
                end;
              else
                begin
                  if m_deliverydays = 1 then
                    begin
                      --There is only 1 delivery day
                      m_remainder      := 0;
                      m_deliveryperday := m_stddeliveryqty;
                    end;
                  else
                    begin
                      --Calculate average per delivery day (whole number therefore truncated)
                      m_deliveryperday := trunc(m_stddeliveryqty / m_deliverydays);
                      m_remainder      := m_stddeliveryqty - (m_deliverydays * m_deliveryperday);
                    end;
                  end if;
                  --Start processing all StandardDeliveryAmount records of the current SDL
                  --process_standarddelamount
                  process_standarddelamount(y.standarddeliveryline_id);
                end;
              end if;
            end;
          end if;
        end;
      end loop; --y
    end process_standarddellines;
  begin
    --recalculate
    fp_message := 'recalculate';
    --4. Start processing all RentalQtyAdjustment records that are active and that require a recalculation
    fp_statusout := 4;
    rqa_set_status_to(2);
    --5. Start processing all active RentalQtyAdjustment (RQA2) records that are marked as `being recalculated`
    fp_statusout := 5;
    for x in (select rqa.productlistperdistribpoint_id
              from   rentalqtyadjustment rqa
              where  rqa.adjustmentdate <= m_enddate
              and    rqa.recalcstatus = 2
              and    rqa.systemuser_id = fp_systemuserid
              group  by rqa.productlistperdistribpoint_id) loop
      begin
        --Retrieve the corresponding ProductListPerDistriPoint record
        fp_message := 'productlistperdistribpoint_id ' || x.productlistperdistribpoint_id;
        select plpd.*
        into   lv_rec_plpd
        from   productlistperdistribpoint plpd
        where  plpd.productlistperdistribpoint_id = x.productlistperdistribpoint_id;
        --Calculate the total qty in circulation at end date
        fp_message := 'Calc total qty in circ at end date productlistperdistribpoint_id ' ||
                      x.productlistperdistribpoint_id;
        select sum(rq.quantity)
        into   m_totalcirc
        from   rentalqtyadjustment rq
        where  rq.productlistperdistribpoint_id = x.productlistperdistribpoint_id
        and    rq.adjustmentdate <= m_enddate;
        --do something when one of the percentages > 0
        if lv_rec_plpd.billingpercentage > 0 or lv_rec_plpd.deliverypercentage > 0 then
          begin
            --process_standarddellines
            process_standarddellines(x.productlistperdistribpoint_id);
          end;
        end if;
      end;
    end loop; --x
    --6.  Start processing all RentalQtyAdjustment records that are active and that have been used for recalculation
    fp_statusout := 6;
    rqa_set_status_to(3);
  end recalculate;

  procedure finalize is
  begin
    --finalize and commit
    fp_statusout := 0; --ok
    fp_message   := 'Process ran ok for plant ' || fp_plantcode || ' Process ended';
    commit;
  end finalize;
begin
  --Main program part for recalculatedelbillquantities
  --intialize
  intialize;
  --recalculate
  recalculate;
  --finalize
  finalize;
exception
  --All exception handling
  when gv_user_exception then
    begin
      rollback;
      if fp_statusout = 0 then
        fp_statusout := 99; --not ok
      end if;
      write_log(fp_message || ' Process ended', 3);
    end;
  when no_data_found then
    begin
      rollback;
      if fp_statusout = 0 then
        fp_statusout := 99; --not ok
      end if;
      write_log(fp_message || ' not found. Process ended', 3);
    end;
  when others then
    begin
      rollback;
      if fp_statusout = 0 then
        fp_statusout := 99; --not ok
      end if;
      write_log('Exception Others; ' || sqlerrm || ' ' || fp_message || ' for plant ' ||
                fp_plantcode || ' Process ended', 3);
    end;
end recalculatedelbillquantities;
/
create or replace procedure recreate_contract_cust_links(fp_contractcode in varchar2,
                                                         fp_systemuserid in number default 1,
                                                         fp_result       out nocopy number,
                                                         fp_message      out nocopy varchar2) is
  --Version 0.18 recreate_contract_cust_links
  --01-Oct-2021 ABS-125265 Create procedure to (re)create the contract customer links to the related tables.
  --26-Oct-2021 ABS-125265 Small adjustment sysdate < cc.endate for relinking.
  --23-Dec-2021 ABS-129264 Also do special charge links in table contractspecialchargecust
  --19-Apr-2022 ABS-133909 Active general price lists from old contracts should be end dated
  --15-Jun-2022 ABS-137867 AUS - issue with PLPC records not visible in client
  --07-Oct-2022 ABS-142676 Contract compliancy relink procedure not deleting special charge links
  --12-Jan-2023 ABS-144804 Reset compliancy links - end dating price lists per customer on new contract
  --16-Feb-2023 ABS-144804 Reset compliancy links - end dating price lists per customer on new contract - rework
  --12-Feb-2024 ABS-160882 Bulk linking of contract components that are not linked
  --26-Feb-2024 ABS-162038 Product emblem template lines not linking when recreate links procedure is run

  --Global variables
  gv_userexception exception;
  gv_contractid    contract.contract_id%type;
  gv_sizestarid    sizedefinition.sizedefinition_id%type;

  --Internal procedures
  procedure write_log(fp_priority in number) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'recreate_contract_cust_links', null, fp_priority, fp_message);
    begin
      dbms_output.put_line(fp_message);
    exception
      when others then
        null; --ok no output to screen
    end;
  end write_log;

  procedure initialize is
    procedure check_for_duplicates is
    begin
      --check_for_duplicates
      fp_message := 'check_for_duplicates';
      for z in (select c.customernumber, ct.code duplicate_contractcode
                from   (select (select max(cx.contract_id)
                                  from   contractcustomer cx
                                  where  cx.customer_link_id = cc.customer_link_id
                                  and    cx.contract_id <> cc.contract_id
                                  and    cx.enddate >= trunc(sysdate)) dup_contract_id, cc.contract_id,
                                cc.customer_link_id
                         from   contractcustomer cc
                         where  cc.enddate >= trunc(sysdate)
                         and    cc.contract_id = gv_contractid
                         and    exists (select 1
                                 from   contractcustomer cx
                                 where  cx.customer_link_id = cc.customer_link_id
                                 and    cx.contract_id <> cc.contract_id
                                 and    cx.enddate >= trunc(sysdate))) dc
                join   customer c
                on     c.customer_id = dc.customer_link_id
                join   contract ct
                on     ct.contract_id = dc.dup_contract_id) loop
        begin
          fp_message := 'Customer ' || to_char(z.customernumber) || ' linked to contract ' ||
                        fp_contractcode || ' and ' || z.duplicate_contractcode;
          raise gv_userexception;
        end;
      end loop; --x
    end check_for_duplicates;
  begin
    --initialize
    --check parameter fp_contractcode
    if fp_contractcode is null then
      begin
        fp_message := 'Parameter fp_contractcode cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        --get contract id
        fp_message := 'Parameter fp_contractcode ' || fp_contractcode;
        select cc.contract_id
        into   gv_contractid
        from   contract cc
        where  cc.code = fp_contractcode
        and    cc.enddate >= trunc(sysdate);
      end;
    end if;
    --check parameter  fp_systemuserid
    if fp_systemuserid is null then
      begin
        fp_message := 'Parameter fp_systemuserid cannot be left blank!';
        raise gv_userexception;
      end;
    end if;
    --get size star
    fp_message := 'size * (star)';
    select s.sizedefinition_id into gv_sizestarid from sizedefinition s where s.code = '*';
    --check for duplicates
    check_for_duplicates;
  end initialize;

  procedure delete_existing_links is
  begin
    --delete_existing_links
    fp_message := 'delete_existing_links';
    --contractproductplpc
    delete from contractproductplpc cpl
    where  exists (select 1
            from   contractcustomer cc
            join   contractproduct cp
            on     cp.contract_id = cc.contract_id
            join   contractproductbilling cpb
            on     cpb.contractproduct_id = cp.contractproduct_id
            join   productlistpercustomer l
            on     (l.customer_id = cc.customer_link_id and l.product_id = cp.product_id and
                   (l.sizedefinition_id = cp.sizedefinition_id or
                   cp.sizedefinition_id = gv_sizestarid) and
                   l.finishingmethod_id = cp.finishingmethod_id and
                   l.billingmethod = cpb.billingmethod)
            where  cc.contract_id = gv_contractid
            and    cc.enddate >= trunc(sysdate)
            and    l.productlistpercustomer_id = cpl.productlistpercustomer_id);
    --contractembtempcust
    delete from contractembtempcust cec
    where  exists (select 1
            from   emblemtemplate et
            join   contractcustomer cc
            on     cc.customer_link_id = et.customer_id
            where  et.emblemtemplate_id = cec.emblemtemplate_id
            and    cc.enddate >= trunc(sysdate)
            and    cc.contract_id = gv_contractid);
    --contractembtemplinecust
    delete from contractembtemplinecust celc
    where  exists (select 1
            from   emblemtemplateline etl
            join   emblemtemplate et
            on     et.emblemtemplate_id = etl.emblemtemplate_id
            join   contractcustomer cc
            on     cc.customer_link_id = et.customer_id
            where  etl.emblemtemplateline_id = celc.emblemtemplateline_id
            and    cc.enddate >= trunc(sysdate)
            and    cc.contract_id = gv_contractid);
    --contractwearerfunccust
    delete from contractwearerfunccust cwfc
    where  exists (select 1
            from   wearerfunction wf
            join   contractcustomer cc
            on     cc.customer_link_id = wf.customer_id
            where  wf.wearerfunction_id = cwfc.wearerfunction_id
            and    cc.enddate >= trunc(sysdate)
            and    cc.contract_id = gv_contractid);
    --contractspecialchargecust
    delete from contractspecialchargecust csc
    where  exists (select 1
            from   contractcustomer cc
            where  cc.enddate >= trunc(sysdate)
            and    csc.contract_id = gv_contractid
            and    cc.customer_link_id = csc.customer_id);
  end delete_existing_links;

  procedure recreate_links is
    procedure link_contractembtempcust is
    begin
      --link_contractembtempcust
      for x in (select ce.contractembtemp_id, et.emblemtemplate_id
                from   contractcustomer cc
                join   contractembtemp ce
                on     ce.contract_id = cc.contract_id
                join   emblemtemplate et
                on     (et.customer_id = cc.customer_link_id and et.code = ce.code)
                where  cc.enddate >= trunc(sysdate)
                and    cc.contract_id = gv_contractid) loop
        begin
          --create contractembtempcust
          insert into contractembtempcust
            (contractembtemp_id, emblemtemplate_id, systemuser_id, timestamp)
          values
            (x.contractembtemp_id, x.emblemtemplate_id, fp_systemuserid, sysdate);
          --loop lines
          for y in (select cel.*
                    from   contractembtempline cel
                    where  cel.contractembtemp_id = x.contractembtemp_id) loop
            begin
              --contractembtemplinecust
              insert into contractembtemplinecust
                (contractembtempline_id, emblemtemplateline_id, systemuser_id, timestamp)
                select y.contractembtempline_id, etl.emblemtemplateline_id, fp_systemuserid, sysdate
                from   emblemtemplateline etl
                where  etl.emblemtemplate_id = x.emblemtemplate_id
                and    (etl.product_id = y.product_id or
                      (etl.product_id is null and y.product_id is null))
                and    etl.sizedefinition_id = y.sizedefinition_id
                and    (etl.textcolor_id = y.textcolor_id or
                      (etl.textcolor_id is null and y.textcolor_id is null))
                and    (etl.bordercolor_id = y.bordercolor_id or
                      (etl.bordercolor_id is null and y.bordercolor_id is null))
                and    (etl.bkgcolor_id = y.bkgcolor_id or
                      (etl.bkgcolor_id is null and y.bkgcolor_id is null))
                and    etl.fabric_id = y.fabric_id
                and    (etl.placement_id = y.placement_id or
                      (etl.placement_id is null and y.placement_id is null))
                and    (etl.emblemfont_id = y.emblemfont_id or
                      (etl.emblemfont_id is null and y.emblemfont_id is null))
                and    etl.emblemtype = y.emblemtype
                and    not exists
                 (select 1
                        from   contractembtemplinecust zx
                        where  zx.emblemtemplateline_id = etl.emblemtemplateline_id);
              --link on all except for colors
              --ABS-119343 link emblemtemplate there were it did not work before not checking colors
              insert into contractembtemplinecust
                (contractembtempline_id, emblemtemplateline_id, systemuser_id, timestamp)
                select y.contractembtempline_id, etl.emblemtemplateline_id, fp_systemuserid, sysdate
                from   emblemtemplateline etl
                where  etl.emblemtemplate_id = x.emblemtemplate_id
                and    (etl.product_id = y.product_id or
                      (etl.product_id is null and y.product_id is null))
                and    etl.sizedefinition_id = y.sizedefinition_id
                and    etl.fabric_id = y.fabric_id
                and    (etl.placement_id = y.placement_id or
                      (etl.placement_id is null and y.placement_id is null))
                and    (etl.emblemfont_id = y.emblemfont_id or
                      (etl.emblemfont_id is null and y.emblemfont_id is null))
                and    etl.emblemtype = y.emblemtype
                and    not exists
                 (select 1
                        from   contractembtemplinecust zx
                        where  zx.emblemtemplateline_id = etl.emblemtemplateline_id);
              --link on product if only once on the template
              insert into contractembtemplinecust
                (contractembtempline_id, emblemtemplateline_id, systemuser_id, timestamp)
                select y.contractembtempline_id, etl.emblemtemplateline_id, fp_systemuserid, sysdate
                from   emblemtemplateline etl
                where  etl.emblemtemplate_id = x.emblemtemplate_id
                and    etl.product_id = y.product_id -- product emblems only
                and    not exists (select 1
                        from   contractembtemplinecust zx
                        where  zx.emblemtemplateline_id = etl.emblemtemplateline_id)
                and    (select count(1)
                        from   emblemtemplateline etl1
                        where  etl1.emblemtemplate_id = etl.emblemtemplate_id
                        and    etl1.product_id = etl.product_id) = 1
                and    (select count(1)
                        from   contractembtempline cetl
                        where  cetl.contractembtemp_id = y.contractembtemp_id
                        and    cetl.product_id = etl.product_id) = 1;
            end;
          end loop; --y
        end;
      end loop; --x
    end link_contractembtempcust;
  begin
    --recreate_links
    fp_message := 'recreate_links';
    --contractproductplpc
    insert into contractproductplpc
      (contractproduct_id, productlistpercustomer_id, systemuser_id, timestamp)
      select max(cp.contractproduct_id), l.productlistpercustomer_id, fp_systemuserid, sysdate
      from   contractcustomer cc
      join   contractproduct cp
      on     cp.contract_id = cc.contract_id
      join   contractproductbilling cpb
      on     cpb.contractproduct_id = cp.contractproduct_id
      join   productlistpercustomer l
      on     (l.customer_id = cc.customer_link_id and l.product_id = cp.product_id and
             (l.sizedefinition_id = cp.sizedefinition_id or cp.sizedefinition_id = gv_sizestarid) and
             l.finishingmethod_id = cp.finishingmethod_id and l.billingmethod = cpb.billingmethod)
      where  cp.enddate >= trunc(sysdate)
      and    cc.enddate >= trunc(sysdate)
      and    cc.contract_id = gv_contractid
      group  by l.productlistpercustomer_id;
    --add missing to contractplpc with diffferent BM
    insert into contractproductplpc
      (contractproduct_id, productlistpercustomer_id, systemuser_id, timestamp)
      select max(cp.contractproduct_id), l.productlistpercustomer_id, fp_systemuserid, sysdate
      from   contractcustomer cc
      join   contractproduct cp
      on     cp.contract_id = cc.contract_id
      join   contractproductbilling cpb
      on     cpb.contractproduct_id = cp.contractproduct_id
      join   productlistpercustomer l
      on     (l.customer_id = cc.customer_link_id and l.product_id = cp.product_id and
             (l.sizedefinition_id = cp.sizedefinition_id or cp.sizedefinition_id = gv_sizestarid) and
             l.finishingmethod_id = cp.finishingmethod_id)
      where  cc.contract_id = gv_contractid
      and    cp.enddate >= trunc(sysdate)
      and    cc.enddate >= trunc(sysdate)
      and    not exists
       (select 1
              from   contractproductplpc zz
              where  zz.productlistpercustomer_id = l.productlistpercustomer_id)
      group  by l.productlistpercustomer_id;
    --contractembtempcust+line
    link_contractembtempcust;
    --contractwearerfunccust
    insert into contractwearerfunccust
      (contractwearerfunction_id, wearerfunction_id, systemuser_id, timestamp)
      select cwf.contractwearerfunction_id, wf.wearerfunction_id, fp_systemuserid, sysdate
      from   contractcustomer cc
      join   wearerfunction wf
      on     wf.customer_id = cc.customer_link_id
      join   contractwearerfunction cwf
      on     (cwf.contract_id = cc.contract_id and cwf.code = wf.code)
      where  cc.enddate >= trunc(sysdate)
      and    cc.contract_id = gv_contractid;
    --contractspecialchargecust
    insert into contractspecialchargecust
      (customer_id, specialcharge_id, systemuser_id, timestamp, contract_id)
      select cs.customer_id, cs.specialcharge_id, fp_systemuserid, sysdate, cc.contract_id
      from   customerspecialcharge cs
      join   contractcustomer cc
      on     cc.customer_link_id = cs.customer_id
      where  cc.enddate >= trunc(sysdate)
      and    cc.contract_id = gv_contractid
      and    exists (select csc.specialcharge_id
              from   contractspecialcharge csc
              where  csc.contract_id = cc.contract_id
              and    csc.specialcharge_id = cs.specialcharge_id);
  end recreate_links;

  procedure cut_off_old_pricelists is
  begin
    --cut_off_old_pricelists
    fp_message := 'cut_off_old_pricelists';
    update pricelistpercustomer plc
    set    plc.dateinactive = trunc(sysdate) - 1, plc.systemuser_id = fp_systemuserid,
           plc.timestamp = sysdate
    where  plc.dateinactive > trunc(sysdate)
    and    plc.generalpricelist_id is not null --do not cut off customer specific price lists
    and    exists (select 1
            from   contractcustomer cc
            where  cc.customer_link_id = plc.customer_id
            and    cc.enddate >= trunc(sysdate)
            and    cc.contract_id = gv_contractid)
    and    not exists (select 1
            from   contractpricelist cpl
            where  cpl.generalpricelist_id = plc.generalpricelist_id
            and    cpl.contract_id = gv_contractid);
  end cut_off_old_pricelists;

  procedure finalize is
  begin
    --finalize
    commit;
    --return message
    fp_message := 'Ok contract ' || fp_contractcode;
    write_log(1);
    fp_result := 0;
  end finalize;
begin
  --initialize
  initialize;
  --delete existing links
  delete_existing_links;
  --recreate links
  recreate_links;
  --cut off old pricelists
  cut_off_old_pricelists;
  --finalize
  finalize;
exception
  --Exception handling
  when gv_userexception then
    begin
      rollback;
      write_log(3);
      fp_result := 1;
    end;
  when no_data_found then
    begin
      rollback;
      fp_message := 'Error, No Data Found ' || fp_message;
      write_log(3);
      fp_result := 2;
    end;
  when others then
    begin
      rollback;
      fp_message := 'Error ' || sqlerrm || ' ' || fp_message;
      write_log(3);
      fp_result := 3;
    end;
end recreate_contract_cust_links;
/
create or replace procedure reserverstocklocations(fp_routeid           in number,
                                                   fp_numberoflocations in number,
                                                   fp_systemuserid      in number,
                                                   fp_result            out nocopy number,
                                                   fp_message           out nocopy varchar2,
                                                   fp_method            in number default null) is
  --Version 1.2 reserverstocklocations
  --ABS-104448 Bulk packing assistant reserves too many location for certain routes
  --           We ignore parameter fp_numberoflocations and recalculate it using gv_numberoflocations
  --ABS-104959 Bulk Packing Assistant - cancelling of reservations if the hive is full
  --ABS-106042 Loading a hive with mats in a newly converted dataset
  --ABS-112331 Reservations procedure changes: bulk active stock locations should not be taken in account
  --ABS-128450 Update the procedure reserverstocklocations, with extra system setting check
  --ABS-134400 Update procedure getnumberoflocations needed for the hive storage process

  --Global variables
  gv_userexception exception;
  gv_plantid           plant.plant_id%type;
  gv_start_locationid  number;
  gv_numberoflocations number;
  gv_removecount       number;
  gv_billingtab        number; --0=No billing done with ABSSolute, 1=EU-style, 2=US-style

  --Internal procedures
  procedure write_log(fp_priority in number) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'reserverstocklocations', gv_plantid, fp_priority, fp_message);
    begin
      dbms_output.put_line(fp_message);
    exception
      when others then
        null; --ok no output to screen
    end;
  end write_log;

  procedure initialize is
    procedure get_start_location_routid is
    begin
      --get start location route
      fp_message := 'get_start_location_routid';
      for x in (select asl.activestocklocation_id,
                       round(sqrt(power(asl.xcoordinate - x.xcentre, 2) +
                                   power(((asl.ycoordinate - x.ycentre) * 2), 2)), 2) distance
                from   (select occupiedbyroute_id route_id,
                                round(sum(asl1.xcoordinate) / count(1), 2) xcentre,
                                round(sum(asl1.ycoordinate) / count(1), 2) as ycentre
                         from   activestocklocation asl1
                         where  asl1.occupiedbyroute_id = fp_routeid
                         group  by asl1.occupiedbyroute_id) x
                cross  join activestocklocation asl
                join   businessunit bu
                on     bu.businessunit_id = asl.businessunit_id
                where  bu.plant_id = gv_plantid
                order  by distance asc) loop
        begin
          gv_start_locationid := x.activestocklocation_id;
          exit;
        end;
      end loop;
      if gv_start_locationid is null then
        begin
          --get bpastartlocation for plant id from route
          fp_message := 'Get systemsetting BPASTARTLOCATION for plant id ' || to_char(gv_plantid) ||
                        ' from fp_routeid ' || to_char(fp_routeid);
          select to_number(st.value)
          into   gv_start_locationid
          from   systemsetting st
          where  st.name = 'BPASTARTLOCATION'
          and    st.plant_id = gv_plantid;
          --chek if the plant of the systemsetting is correct
          fp_message := 'Check if the start location id found is for the correct plant of route';
          select asl.activestocklocation_id
          into   gv_start_locationid
          from   activestocklocation asl
          join   businessunit bu
          on     bu.businessunit_id = asl.businessunit_id
          where  asl.activestocklocation_id = gv_start_locationid
          and    bu.plant_id = gv_plantid;
        exception
          when no_data_found then
            begin
              --system setting not found, or system setting value is wrong
              --get the min(asl.activestocklocation_id) for route plant id
              fp_message := 'Get the min location id for the plant of route';
              select min(asl.activestocklocation_id)
              into   gv_start_locationid
              from   activestocklocation asl
              join   businessunit bu
              on     bu.businessunit_id = asl.businessunit_id
              where  bu.plant_id = gv_plantid;
            end;
        end;
      end if;
    end get_start_location_routid;

    procedure get_billingtab is
    begin
      --get_billingtab, 0=No billing done with ABSSolute, 1=EU-style, 2=US-style
      fp_message := 'get systemsetting BILLINGTAB for plant id ' || to_char(gv_plantid);
      select to_number(st.value)
      into   gv_billingtab
      from   systemsetting st
      where  st.name = 'BILLINGTAB'
      and    st.plant_id = gv_plantid;
    exception
      when no_data_found then
        begin
          gv_billingtab := 0;
        end;
    end get_billingtab;
  begin
    --initialize
    fp_result      := 0;
    gv_removecount := 0;
    --check parameter fp_routeid
    if fp_routeid is null then
      begin
        fp_message := 'Parameter fp_routeid cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        --get route id, plant id
        fp_message := 'parameter fp_routeid ' || to_char(fp_routeid);
        select r.plant_id into gv_plantid from route r where r.route_id = fp_routeid;
        --get start location route
        get_start_location_routid;
      end;
    end if;
    --ignore parameter fp_numberoflocations
    gv_numberoflocations := fp_numberoflocations; --we will recalculate this value gv_numberoflocations
    --check parameter  fp_systemuserid
    if fp_systemuserid is null then
      begin
        fp_message := 'Parameter fp_systemuserid cannot be left blank!';
        raise gv_userexception;
      end;
    end if;
    --get_billingtab
    get_billingtab;
  end initialize;

  procedure getnumberoflocations is
  begin
    --getnumberoflocations
    fp_message := 'getnumberoflocations';
    if gv_billingtab = 1 then
      begin
        select sum(case sta.code
                      when '10' then
                       sr.qtyreturned
                      when '20' then
                       sr.qtyreturned
                      else
                       0
                    end) numberoflocations
        into   gv_numberoflocations
        from   straightevenreturn sr
        join   status sta
        on     sta.status_id = sr.status_id
        join   product p
        on     (p.product_id = sr.product_id and p.typeofmerchandise = 1 and
               p.bulkpackingactivestocktype in (1, 2))
        join   packingnoteline pkl
        on     pkl.packingnoteline_id = sr.packingnoteline_id
        join   packingnote pk
        on     pk.packingnote_id = pkl.packingnote_id
        join   stop st
        on     st.stop_id = pk.stop_id
        join   routecontrol rc
        on     rc.routecontrol_id = st.routecontrol_id
        join   distributionpoint dp
        on     dp.distributionpoint_id = sr.distributionpoint_id
        join   department t
        on     t.department_id = dp.department_id
        join   productlistpercustomer l
        on     (l.customer_id = t.customer_id and l.product_id = sr.product_id and
               l.sizedefinition_id = sr.sizedefinition_id and
               l.finishingmethod_id = sr.finishingmethod_id and
               rc.drivingdate between l.dateactive and l.dateinactive)
        left   outer join plpcextrainfo lx
        on     lx.productlistpercustomer_id = l.productlistpercustomer_id
        where  ((p.bulkpackingactivestocktype = 1 and nvl(lx.specificbulkpackingtype, 0) = 0) or
               (lx.specificbulkpackingtype = 1))
        and    sr.qtyreturned > 0
        and    rc.route_id = fp_routeid --get number of locations for route_id
        and    sr.pickupdate =
               (select max(rc2.drivingdate)
                 from   routecontrol rc2
                 where  rc2.route_id = rc.route_id
                 and    rc2.drivingdate between trunc(sysdate - 8) and trunc(sysdate - 1));
      end;
    else
      begin
        gv_numberoflocations := 0;
      end;
    end if;
    --no location found yet, look for standard deliveries
    if nvl(gv_numberoflocations, 0) <= 0 then
      begin
        select sum(sta.amount)
        into   gv_numberoflocations
        from   route r
        join   routestop rs
        on     (rs.route_id = r.route_id and trunc(sysdate) between rs.dateactive and
               rs.dateinactive)
        join   productlistpercustomer l
        on     l.customer_id = rs.customer_id
        left   outer join plpcextrainfo lx
        on     lx.productlistpercustomer_id = l.productlistpercustomer_id
        join   product p
        on     (p.product_id = l.product_id and p.typeofmerchandise = 1 and
               p.bulkpackingactivestocktype in (1, 2))
        join   standarddeliveryline stl
        on     (stl.productlistpercustomer_id = l.productlistpercustomer_id and
               trunc(sysdate) between stl.dateactive and stl.dateinactive)
        join   standarddeliveryamount sta
        on     (sta.standarddeliveryline_id = stl.standarddeliveryline_id and
               sta.day_id = r.drivingday_id)
        where  r.route_id = fp_routeid --get number of locations for route_id
        and    sta.amount > 0
        and    ((p.bulkpackingactivestocktype = 1 and nvl(lx.specificbulkpackingtype, 0) = 0) or
              (lx.specificbulkpackingtype = 1));
      end;
    end if;
    --max sure gv_numberoflocations is at least 1
    if nvl(gv_numberoflocations, 0) <= 0 then
      begin
        gv_numberoflocations := 1;
      end;
    end if;
  exception
    when no_data_found then
      begin
        gv_numberoflocations := 1;
      end;
  end getnumberoflocations;

  procedure reserve_locations is
  begin
    --reserve_locations_quick
    fp_message := 'reserve_locations_quick';
    for p in (select toloc.activestocklocation_id, asld.distance
              from   activestocklocationdist asld
              join   activestocklocation toloc
              on     toloc.activestocklocation_id = asld.activestocklocation_id
              where  asld.toactivestocklocation_id = gv_start_locationid
              and    toloc.occupiedbyroute_id is null -- so it is free
              and    toloc.multiplestorageallowed = 'N'
              and    not exists
               (select 1
                      from   activestocklocationreserve asr
                      where  asr.activestocklocation_id = toloc.activestocklocation_id)
              order  by 2 asc) loop
      begin
        --check if we are ready
        if gv_numberoflocations <= fp_result then
          begin
            exit;
          end;
        end if;
        --count reservations created
        fp_result := fp_result + 1;
        --insert into activestocklocationreserve
        fp_message := 'insert into activestocklocationreserve ' ||
                      to_char(p.activestocklocation_id);
        insert into activestocklocationreserve
          (activestocklocation_id, route_id, reserveddate, systemuser_id, timestamp)
        values
          (p.activestocklocation_id, fp_routeid, trunc(sysdate), fp_systemuserid, sysdate);
      end;
    end loop; --p
  end reserve_locations;

  procedure remove_old_reservations_route is
  begin
    --remove_old_reservations_route closest to route
    fp_message := 'remove_old_reservations_route close to route';
    for y in (select alr.activestocklocation_id, ald.distance
              from   activestocklocation al
              join   activestocklocationdist ald
              on     ald.toactivestocklocation_id = al.activestocklocation_id
              join   activestocklocationreserve alr
              on     alr.activestocklocation_id = ald.activestocklocation_id
              where  al.activestocklocation_id = gv_start_locationid
              order  by distance asc) loop
      begin
        --remove reservation, closest to route
        delete from activestocklocationreserve alr
        where  alr.activestocklocation_id = y.activestocklocation_id;
        --count removed reservations
        gv_removecount := gv_removecount + 1;
        --when removed enough stop
        if gv_removecount = gv_numberoflocations then
          exit;
        end if;
      end;
    end loop; --y
  end remove_old_reservations_route;

  procedure remove_old_reservations_others is
  begin
    --remove_old_reservations_others
    fp_message     := 'remove_old_reservations_others other routes';
    gv_removecount := 0;
    for x in (select asr.route_id, count(1) counter
              from   activestocklocationreserve asr
              join   activestocklocation sa
              on     sa.activestocklocation_id = asr.activestocklocation_id
              join   businessunit bu
              on     bu.businessunit_id = sa.businessunit_id
              where  bu.plant_id = gv_plantid
              group  by asr.route_id
              order  by counter desc) loop
      begin
        --delete rows from route with most reservations
        delete from activestocklocationreserve asx where asx.route_id = x.route_id;
        --Count number of rows removed
        gv_removecount := sql%rowcount;
        --we do this for one route only
        exit;
      end;
    end loop;
  end remove_old_reservations_others;

  procedure write_hivelog is
  begin
    --write_hivelog
    fp_message := 'write_hivelog';
    insert into hivelog
      (hivelog_id, route_id, type, locationsrequested, locationsreturned, locationsoccupied,
       optimisationmeasure, fragmentationmeasure, reservationsdeleted, alreadyoccupiedbyroute_id,
       distanceoutofplace, storedbyuser, shortedcustomer_link_id, plant_id, loggeddate,
       systemuser_id, timestamp)
      select seq_hivelog.nextval, fp_routeid, 1, gv_numberoflocations, fp_result,
             x.route_locationsoccupied, x.optimisationmeasure, x.fragmentationmeasure,
             gv_removecount, null, 0, fp_systemuserid, null, x.plant_id, trunc(sysdate),
             fp_systemuserid, sysdate
      from   (select y.plant_id,
                      sum(case
                            when occupiedbyroute_id = fp_routeid then
                             y.route_locationsoccupied
                            else
                             0
                          end) route_locationsoccupied, 0 optimisationmeasure, 0 fragmentationmeasure
               from   (select bu.plant_id, asl.occupiedbyroute_id,
                               count(distinct asl.activestocklocation_id) route_locationsoccupied
                        from   activestocklocation asl
                        join   activestocklocationdist asld
                        on     asl.activestocklocation_id = asld.activestocklocation_id
                        join   activestocklocation asl2
                        on     (asl2.activestocklocation_id = asld.toactivestocklocation_id and
                               asl2.occupiedbyroute_id = asl.occupiedbyroute_id)
                        join   businessunit bu
                        on     bu.businessunit_id = asl.businessunit_id
                        where  asld.distance > 0
                        and    bu.plant_id = gv_plantid
                        group  by bu.plant_id, asl.occupiedbyroute_id) y
               group  by y.plant_id) x;
  end write_hivelog;

  procedure finalize is
  begin
    --finalize
    commit;
    --return message
    fp_message := 'Ok';
  end finalize;
begin
  --fill_activestocklocationdist
  --initialize
  initialize;
  --getnumberoflocations
  getnumberoflocations;
  --reserve_locations
  reserve_locations;
  if fp_result = 0 then
    begin
      --Part 1 Remove old reservations older then 2 days
      delete from activestocklocationreserve alr where alr.reserveddate < trunc(sysdate - 2);
      gv_removecount := sql%rowcount;
      if gv_removecount >= 1 then
        begin
          --reserve_locations
          reserve_locations;
        end;
      end if;
    end;
  end if;
  if fp_result = 0 then
    begin
      --Part 2 Remove old reservations closest to route
      remove_old_reservations_route;
      if gv_removecount >= 1 then
        begin
          --reserve_locations
          reserve_locations;
        end;
      end if;
    end;
  end if;
  if fp_result = 0 then
    begin
      --Part 3 Remove old reservations other routes
      remove_old_reservations_others;
      if gv_removecount >= 1 then
        begin
          --reserve_locations
          reserve_locations;
        end;
      end if;
    end;
  end if;
  --write_hivelog
  write_hivelog;
  --finalize
  finalize;
exception
  --Exception handling
  when gv_userexception then
    begin
      rollback;
      write_log(3);
      fp_result := -1;
    end;
  when no_data_found then
    begin
      rollback;
      fp_message := 'Error, No Data Found ' || fp_message;
      write_log(3);
      fp_result := -1;
    end;
  when others then
    begin
      rollback;
      fp_message := 'Error ' || sqlerrm || ' ' || fp_message || ' fp_method ' ||
                    nvl(to_char(fp_method), 'NULL');
      write_log(3);
      fp_result := -1;
    end;
end reserverstocklocations;
/
create or replace procedure SendDeliveredQuantity(PlantCode  in Plant.Code%type,
		       OrderNumber       in packingnote.notenumber%type,
                                                  ProductCode       in product.code%type,
                                                  SizeCode          in sizedefinition.code%type,
                                                  QuantityDelivered in number,
                                                  StatusOut out integer) is
  productID            product.product_id%type;
  sizedefinitionID     sizedefinition.sizedefinition_id%type;
  packingnoteid        packingnote.packingnote_id%type;
  pnstatus             status.status_id%type;
  Statuscode           status.code%type;
  minpackingnotelineid packingnoteline.packingnoteline_id%type;
  gv_message abslog.message%type;

  procedure write_log(fp_priority in number default 1) is
  begin
    --write_log
    abslogwrite.abslog_write(5, 'SendDeliveredQuantity', null, fp_priority, gv_message);
  end write_log;

begin
  StatusOut := 0;
  begin
    select p.packingnote_id, p.status_id
      into packingnoteid, pnstatus
      from packingnote p
     where p.notenumber = ordernumber;
    select s.code
      into statuscode
      from status s
     where s.statustype = 'PN'
       and s.status_id = pnstatus;
    if statuscode = '30' then
      Statusout := 1;
        gv_message := '>!Error Deliverynote ' || OrderNumber ||'is already finalized! Quantity will not be linked this order!';
        write_log(3);
    elsif statuscode in ('40', '50') then
      Statusout := 2;
        gv_message := '>!Error Order ' || OrderNumber ||'is cancelled! Quantity will not be linked to this order!';
        write_log(3);
    elsif statuscode in ('5', '10', '20') then
      begin
        select p.product_id
          into productID
          from product p
         where p.code = ProductCode;
        select s.sizedefinition_id
          into sizedefinitionID
          from sizedefinition s
         where s.code = SizeCode;
      exception
        when no_data_found then
          Statusout := 4;
        gv_message := '>!Error Product/size not found ' || OrderNumber || '! Quantity will not be linked to this order!';
        write_log(3);
        end;
      if StatusOut = 0 then
        begin
          select min(pl.packingnoteline_id)
            into minpackingnotelineid
            from packingnoteline pl
           where pl.packingnote_id = packingnoteid
             and pl.product_id = productid
             and pl.sizedefinition_id = sizedefinitionid;
          if minpackingnotelineid is not null and QuantityDelivered > 0 then
            begin
              update packingnoteline p
                 set p.deliveredamount = p.deliveredamount +
                                         QuantityDelivered
               where p.packingnoteline_id = minpackingnotelineid;

            exception
              when no_data_found then
                Statusout := 4;
                 gv_message := '>!Error Product/size not found for order ' || OrderNumber || '! Quantity will not be linked to this order!' ;
                 write_log(3);
            end;
          elsif minpackingnotelineid is null then
            Statusout := 4;
             gv_message := '>!Error Product/size not found for order ' || OrderNumber || '! Quantity will not be linked to this order!' ;
             write_log(3);
          end if;
        end;
        If statusout = 0 then
          commit;
        else
          rollback;
        end if;
      end if;
    end if;
  exception
    when no_data_found then
      Statusout := 3;
             gv_message := '>!Error OrderNumber ' || OrderNumber || 'not found! Quantity will not be linked to this order!';
             write_log(3);
  end;
end SendDeliveredQuantity;
/
create or replace procedure sendrepairinfo(idcode       in uniqueitem.primaryid%type,
                                           unitcode     in out plant.code%type,
                                           datep        in number,
                                           timep        in varchar2,
                                           locationcode in varchar2,
                                           repaircode   in varchar2,
                                           quantity     in number,
                                           executed     in number, ---1=Repair done, 2=Repair cancelled, 3=Repair delayed
                                           status       out nocopy number,
                                           fp_message   out nocopy varchar2) is
  --global variables
  gv_userexception exception;
  gv_systemuser_id             systemuser.systemuser_id%type;
  gv_loglevel                  number;
  gv_uniqueitemid              uniqueitem.uniqueitem_id%type;
  gv_pool                      integer;
  gv_bucode                    businessunit.code%type;
  gv_businessunitid            businessunit.businessunit_id%type;
  gv_invoicebusinessunit_id    businessunit.businessunit_id%type;
  gv_defaultinvbusinessunit_id customer.defaultinvoicebusinessunit_id%type;
  gv_plantid_garment           plant.plant_id%type;
  gv_returnedplantcode         plant.code%type;
  gv_idprimary                 uniqueitem.primaryid%type;
  gv_plantid_param             plant.plant_id%type;
  gv_secondaryid               secondaryuniqueitem.secondaryid%type;
  gv_workstationid             workstation.workstation_id%type;
  gv_workstationcode           workstation.code%type;
  gv_scandate                  date;
  gv_timezonehrsdiff           number;
  gv_datep                     number;
  gv_timep                     varchar2(6);
  gv_repairtype_id             repairtype.repairtype_id%type;
  gv_defaulttime               repairtype.defaulttime%type;
  gv_selectablefor             repairtype.selectablefor%type;
  gv_flag_id                   flag.flag_id%type;
  gv_product_id                product.product_id%type;
  gv_sizedefinition_id         sizedefinition.sizedefinition_id%type;
  gv_weareremployment_id       weareremployment.weareremployment_id%type;
  gv_stay_id                   stay.stay_id%type;
  gv_prevstay_id               stay.stay_id%type;
  gv_status_id                 uniqueitem.status_id%type;
  gv_customerowned             uniqueitem.customerowned%type;
  gv_year                      number;
  gv_week                      number;
  gv_dayno                     number;
  gv_issuedate                 date;
  gv_distributionpoint_id      distributionpoint.distributionpoint_id%type;
  gv_customer_id               customer.customer_id%type;
  gv_activity_id               activity.activity_id%type;
  gv_supplier_id               supplier.supplier_id%type;
  gv_repairhistory_status      repairhistory.status%type;
  gv_chargerepairs             customer.chargerepairs%type;
  gv_chargerepaircog           customer.chargerepaircog%type;
  gv_counter                   number;
  gv_maxrepairsproduct         number;
  gv_maxrepairsplpc            number;
  gv_repairsotal               number;
  gv_maxrepflagattached        number;
  gv_maxrepairsflagid          number;

  -- procedure sendrepairinfo version 1.2
  --internal procedures/functions
  procedure write_logging(fp_message    in abslog.message%type,
                          fp_loglevel   in number,
                          fp_plantid    in plant.plant_id%type default null,
                          fp_priority   in number default 1,
                          fp_detailinfo in number default 0) is ---0=no detail 1=detail
  begin
    --write_logging
    if fp_priority > 1 then
      begin
        abslogwrite.abslog_write(5,
                                 'sendrepairinfo',
                                 fp_plantid,
                                 fp_priority,
                                 fp_message);
      end;
    else
      case fp_loglevel
        when 0 then
          null; --no logging other then errors, errors are not log level 0
        when 1 then
          if fp_detailinfo = 1 then
            --Log level 1 and detailinfo=1 write detail info
            abslogwrite.abslog_write(5,
                                     'sendrepairinfo',
                                     fp_plantid,
                                     fp_priority,
                                     fp_message);
          end if;
        when 2 then
          --write all logs
          abslogwrite.abslog_write(5,
                                   'sendrepairinfo',
                                   fp_plantid,
                                   fp_priority,
                                   fp_message);
        else
          null;
      end case;
    end if;
  end write_logging;
  --program code section sendrepairinfo
begin
  --initialize variables
  fp_message := 'initialize variables';
  status     := 0;
  gv_datep   := datep;
  gv_timep   := timep;
  --step 2 find uniqueitem
  fp_message := 'calling pack_sort.determinegarmentid';
  pack_sort.determinegarmentid('METRIC',
                               idcode,
                               unitcode,
                               gv_uniqueitemid,
                               gv_pool,
                               gv_bucode,
                               gv_businessunitid,
                               gv_plantid_garment,
                               gv_returnedplantcode,
                               status,
                               gv_idprimary,
                               gv_plantid_param,
                               gv_secondaryid);
  if status <> 0 then
    begin
      fp_message := ' NOT FOUND ';
      raise gv_userexception;
    end;
  end if;
  --get scan date/time
  fp_message  := 'get scan date/time';
  gv_scandate := to_timestamp(to_char(gv_datep) || to_char(gv_timep),
                              'YYYYMMDDHH24MISS');
  --check possible time difference
  begin
    fp_message := 'check possible time difference';
    select nvl(pt.timezonehrsdiff, 0)
      into gv_timezonehrsdiff
      from plant pt
     where pt.plant_id = gv_plantid_param;
  exception
    when others then
      gv_timezonehrsdiff := 0;
  end;
  if gv_timezonehrsdiff <> 0 then
    begin
      gv_scandate := gv_scandate + (gv_timezonehrsdiff / 24);
      gv_datep    := to_char(gv_scandate, 'YYYYMMDD');
      gv_timep    := to_char(gv_scandate, 'HH24MISS');
    end;
  end if;
  --step 1 find location
  fp_message := 'find location';
  begin
    --remark any station can perform a repair scan!
    select s.workstation_id, w.code
      into gv_workstationid, gv_workstationcode
      from sortingimportdefinition s, workstation w
     where s.plant_id = gv_plantid_param
       and s.location = locationcode
       and s.nextlocation is null
       and s.workstation_id = w.workstation_id;
  exception
    when no_data_found then
      begin
        status := 1;
        write_logging('Location definition is not found ' || unitcode || ' ' ||
                      idcode || ' ' || gv_datep || ' ' || gv_timep || ' ' ||
                      locationcode || ' ' || locationcode,
                      0,
                      gv_plantid_param,
                      2);
        raise gv_userexception;
      end;
    when others then
      begin
        status := 1;
        write_logging('Error finding location' || unitcode || ' ' ||
                      idcode || ' ' || gv_datep || ' ' || gv_timep || ' ' ||
                      locationcode || ' ' || locationcode,
                      0,
                      gv_plantid_param,
                      2);
        write_logging(sqlcode || ' ' || sqlerrm, 0, gv_plantid_param, 3);
        raise gv_userexception;
      end;
  end;
  --step 3 find repair type.
  fp_message := 'find repair type ' || nvl(repaircode, 'NULL');
  begin
    select prts.repairtype_id, rp.defaulttime, rp.selectablefor
      into gv_repairtype_id, gv_defaulttime, gv_selectablefor
      from plantrepairtypesettings prts
      join repairtype rp
        on rp.repairtype_id = prts.repairtype_id
     where prts.plant_id = gv_plantid_garment
       and prts.exportcode = repaircode;
    if (gv_selectablefor <> 0) then
      select ui.customerowned
        into gv_customerowned
        from uniqueitem ui
       where ui.uniqueitem_id = gv_uniqueitemid;
      if not ((gv_customerowned = 'N' and gv_selectablefor = 1) or
          (gv_customerowned = 'Y' and gv_selectablefor = 2)) then
        begin
          status := 3;
          raise gv_userexception;
        end;
      end if;
    end if;
  exception
    when no_data_found then
      begin
        select rp.repairtype_id, rp.defaulttime, rp.selectablefor
          into gv_repairtype_id, gv_defaulttime, gv_selectablefor
          from repairtype rp
         where rp.code = repaircode;
        if (gv_selectablefor <> 0) then
          select ui.customerowned
            into gv_customerowned
            from uniqueitem ui
           where ui.uniqueitem_id = gv_uniqueitemid;
          if not ((gv_customerowned = 'N' and gv_selectablefor = 1) or
              (gv_customerowned = 'Y' and gv_selectablefor = 2)) then
            begin
              status := 3;
              raise gv_userexception;
            end;
          end if;
        end if;
      exception
        when no_data_found then
          begin
            status     := 3;
            fp_message := 'Repair code ' || nvl(repaircode, 'NULL') ||
                          ' not found for ';
            raise gv_userexception;
          end;
      end;
  end;
  --systemuser
  begin
    select s.systemuser_id
      into gv_systemuser_id
      from systemuser s
     where s.username = 'SORT';
  exception
    when no_data_found then
      select min(systemuser_id) into gv_systemuser_id from systemuser;
  end;
  case executed
    when 1 then
      --1=Repair is done
      begin
        --update uniqueitem
        fp_message := 'update uniqueitem ';
        update uniqueitem u
           set u.prevstay_id    = u.stay_id,
               u.stay_id       =
               (select st.stay_id
                  from stay st
                 where st.staytype = 1
                   and st.staynr = 32),
               u.staychangedate = sysdate,
               u.lastscandate   = gv_scandate,
               u.repairstotal   = u.repairstotal + quantity,
               u.timestamp      = sysdate,
               u.systemuser_id  = gv_systemuser_id
         where u.uniqueitem_id = gv_uniqueitemid
        returning u.product_id, u.sizedefinition_id, u.stay_id, u.prevstay_id, u.status_id, u.customerowned, nvl(u.distributionpoint_id, u.lastdistributionpoint_link_id) into gv_product_id, gv_sizedefinition_id, gv_stay_id, gv_prevstay_id, gv_status_id, gv_customerowned, gv_distributionpoint_id;
        --update uniqueitemnonpool
        update uniqueitemnonpool un
           set un.repairsthisissue = un.repairsthisissue + quantity
         where un.uniqueitem_id = gv_uniqueitemid
        returning un.weareremployment_id into gv_weareremployment_id;
        --get other values
        fp_message := 'get other values';
        gv_year    := getyearofweek(gv_scandate);
        gv_week    := getisoweek(gv_scandate);
        gv_dayno   := getabsdaynumber(gv_scandate);
        --get customer info
        fp_message := 'get customer info ';
        if gv_distributionpoint_id is null then
          begin
            select w.customer_id,
                   we.distributionpoint_id,
                   c.chargerepairs,
                   c.chargerepaircog,
                   c.defaultinvoicebusinessunit_id
              into gv_customer_id,
                   gv_distributionpoint_id,
                   gv_chargerepairs,
                   gv_chargerepaircog,
                   gv_defaultinvbusinessunit_id
              from weareremployment we
              join wearer w
                on w.wearer_id = we.wearer_id
              join customer c
                on c.customer_id = w.customer_id
             where we.weareremployment_id = gv_weareremployment_id;
          exception
            when no_data_found then
              begin
                gv_customer_id          := null;
                gv_distributionpoint_id := null;
                gv_chargerepairs        := 0;
                gv_chargerepaircog      := 0;
              end;
          end;
        else
          begin
            select t.customer_id,
                   c.chargerepairs,
                   c.chargerepaircog,
                   c.defaultinvoicebusinessunit_id
              into gv_customer_id,
                   gv_chargerepairs,
                   gv_chargerepaircog,
                   gv_defaultinvbusinessunit_id
              from distributionpoint dp
              join department t
                on t.department_id = dp.department_id
              join customer c
                on c.customer_id = t.customer_id
             where dp.distributionpoint_id = gv_distributionpoint_id;
          end;
        end if;
        --get invoice business unit
        fp_message := 'get invoice business unit ';
        select g.activity_id
          into gv_activity_id
          from product p
          join productgroup g
            on g.productgroup_id = p.productgroup_id
         where p.product_id = gv_product_id;
        if gv_customer_id is not null then
          begin
            select coalesce(max(ca.invoicebusinessunit_id),
                            gv_defaultinvbusinessunit_id,
                            gv_businessunitid)
              into gv_invoicebusinessunit_id
              from customeractivities ca
             where ca.customer_id = gv_customer_id
               and ca.activity_id = gv_activity_id;
          end;
        else
          begin
            select coalesce(max(ba.invoicedbybusinessunit_id),
                            gv_businessunitid)
              into gv_invoicebusinessunit_id
              from businessunitactivities ba
             where ba.businessunit_id = gv_businessunitid
               and ba.activity_id = gv_activity_id;
          end;
        end if;
        --get repairhistory status
        fp_message := 'get repairhistory status ';
        if gv_customer_id is null then
          gv_repairhistory_status := 0;
        else
          begin
            if gv_customerowned = 'Y' then
              if gv_chargerepaircog in (0, 1) then
                gv_repairhistory_status := 1;
              else
                gv_repairhistory_status := 0;
              end if;
            else
              if gv_chargerepairs in (0, 1) then
                gv_repairhistory_status := 1;
              else
                gv_repairhistory_status := 0;
              end if;
            end if;
          end;
        end if;
        --get uniqueitemfixedinfo info
        fp_message := 'get uniqueitemfixedinfo info ';
        select uf.lastissuedate, uf.supplier_id
          into gv_issuedate, gv_supplier_id
          from uniqueitemfixedinfo uf
         where uf.uniqueitem_id = gv_uniqueitemid;
        begin
          --create scan
          fp_message := 'create scan ';
          insert into scan
            (scan_id,
             businessunit_id,
             scantimestamp,
             primaryid,
             customer_link_id,
             weareremployment_link_id,
             distributionpoint_link_id,
             product_link_id,
             sizedefinition_link_id,
             stay_id,
             status_id,
             scanstation,
             issuedate,
             route_id,
             reasoncode_id,
             customerowned,
             year,
             week,
             dayno,
             qualitygrade_id,
             systemuser_id,
             timestamp,
             prevstay_id,
             transactiontype_id,
             dayslate,
             uniqueitem_link_id,
             secondaryid,
             batchnumber,
             scandateoffset,
             qualitytesttype_id,
             washingprocess_id,
             treatmenttype_id)
          values
            (seq_scan.nextval,
             gv_businessunitid,
             gv_scandate,
             idcode,
             gv_customer_id,
             gv_weareremployment_id,
             gv_distributionpoint_id,
             gv_product_id,
             gv_sizedefinition_id,
             gv_stay_id,
             gv_status_id,
             gv_workstationcode,
             gv_issuedate,
             null,
             null,
             gv_customerowned,
             gv_year,
             gv_week,
             gv_dayno,
             null,
             gv_systemuser_id,
             sysdate,
             gv_prevstay_id,
             3,
             0,
             gv_uniqueitemid,
             gv_secondaryid,
             null,
             0,
             null,
             null,
             null);
        exception
          when dup_val_on_index then
            null;
            --no problem if scan is already there
        end;
        --create repair history
        fp_message := 'create repair history ';
        insert into repairhistory
          (repairhistory_id,
           supplier_id,
           currency_id,
           product_link_id,
           distributionpoint_link_id,
           weareremployment_link_id,
           customer_link_id,
           repairtype_id,
           uniqueitem_link_id,
           businessunit_id,
           repairdate,
           minutes,
           year,
           week,
           day,
           pool,
           unitprice,
           priceperminute,
           systemuser_id,
           timestamp,
           status,
           invoicebusinessunit_id,
           invoiceheader_id,
           primaryid,
           amount,
           quantity,
           customerowned)
        values
          (seq_repairhistory.nextval,
           gv_supplier_id,
           null,
           gv_product_id,
           gv_distributionpoint_id,
           gv_weareremployment_id,
           gv_customer_id,
           gv_repairtype_id,
           gv_uniqueitemid,
           gv_businessunitid,
           gv_scandate,
           gv_defaulttime * quantity,
           gv_year,
           gv_week,
           gv_dayno,
           case gv_pool when 1 then 'Y' else 'N' end,
           0,
           0,
           gv_systemuser_id,
           sysdate,
           gv_repairhistory_status,
           gv_invoicebusinessunit_id,
           null,
           idcode,
           0,
           quantity,
           gv_customerowned);
        --delete repair pointer
        fp_message := 'delete repair pointer ';
        delete from repairpointer rp
         where rp.uniqueitem_id = gv_uniqueitemid
           and rp.repairtype_id = gv_repairtype_id
           and rp.sequencenumber =
               (select max(rp2.sequencenumber)
                  from repairpointer rp2
                 where rp2.uniqueitem_id = rp.uniqueitem_id
                   and rp2.repairtype_id = rp.repairtype_id);
        --count repair pointer
        select count(1)
          into gv_counter
          from repairpointer rp
         where rp.uniqueitem_id = gv_uniqueitemid;
        if gv_counter = 0 then
          --check to delete flags
          delete from uniqueitemflag uif
           where uif.uniqueitem_id = gv_uniqueitemid
             and (((select max(pfo.remove)
                      from plantflagoptions pfo
                     where pfo.flag_id = uif.flag_id
                       and pfo.plant_id = gv_plantid_garment
                       and pfo.dialog_id =
                           (select dlg.dialog_id
                              from dialogs dlg
                             where dlg.code = 'RepairScan')) = 'Y') or
                 ((select max(fo.remove)
                      from flagoptions fo
                     where fo.flag_id = uif.flag_id
                       and fo.dialog_id =
                           (select dlg.dialog_id
                              from dialogs dlg
                             where dlg.code = 'RepairScan')
                       and not exists
                     (select 1
                              from plantflagoptions pfo2
                             where pfo2.flag_id = uif.flag_id
                               and pfo2.plant_id = gv_plantid_garment
                               and pfo2.dialog_id = fo.dialog_id)) = 'Y'));

        end if;
        -- if the max number of repairs has been exceeded, add flag

        select af.flag_id
          into gv_maxrepairsflagid
          from automaticflag af
         where af.automaticflag_id = 27;

        select count(*)
          into gv_maxrepflagattached
          from uniqueitemflag uif
         where uif.uniqueitem_id = gv_uniqueitemid
           and uif.flag_id = gv_maxrepairsflagid;

        if (gv_maxrepflagattached = 0 and gv_maxrepairsflagid is not null) then

          if (gv_pool <> 1) then
            select nvl(max(ui.repairstotal), 0),
                   nvl(max(plpc.maximumnumberofrepairs), 0),
                   nvl(max(p.maximumnumberofrepairs), 0)
              into gv_repairsotal, gv_maxrepairsplpc, gv_maxrepairsproduct
              from uniqueitem             ui,
                   productlistpercustomer plpc,
                   uniqueitemnonpool      uinp,
                   wearerinventory        wi,
                   weareremployment       we,
                   wearer                 w,
                   product                p
             where ui.primaryid = idcode
               and ui.product_id = plpc.product_id
               and (ui.sizedefinition_id = plpc.sizedefinition_id or
                   plpc.sizedefinition_id =
                   (select sd.sizedefinition_id
                       from sizedefinition sd
                      where sd.code = '*'))
               and ui.finishingmethod_id = plpc.finishingmethod_id
               and ui.uniqueitem_id = uinp.uniqueitem_id
               and uinp.wearerinventory_id = wi.wearerinventory_id
               and wi.weareremployment_id = we.weareremployment_id
               and we.wearer_id = w.wearer_id
               and w.customer_id = plpc.customer_id
               and ui.product_id = p.product_id
               and plpc.dateactive < gv_scandate
               and plpc.dateinactive > gv_scandate;

            if (gv_maxrepairsplpc > 0 and
               gv_repairsotal > gv_maxrepairsplpc) or
               (gv_maxrepairsproduct > 0 and
               gv_repairsotal > gv_maxrepairsproduct and
               gv_maxrepairsplpc = 0) then

              insert into uniqueitemflag
                (uniqueitem_id,
                 flag_id,
                 startdate,
                 systemuser_id,
                 timestamp)
              values
                (gv_uniqueitemid,
                 gv_maxrepairsflagid,
                 sysdate,
                 gv_systemuser_id,
                 sysdate);

            end if;

          else
            select nvl(max(ui.repairstotal), 0),
                   nvl(max(plpc.maximumnumberofrepairs), 0),
                   nvl(max(p.maximumnumberofrepairs), 0)
              into gv_repairsotal, gv_maxrepairsplpc, gv_maxrepairsproduct
              from uniqueitem             ui,
                   productlistpercustomer plpc,
                   distributionpoint      dp,
                   department             d,
                   product                p
             where ui.primaryid = idcode
               and ui.product_id = plpc.product_id
               and (ui.sizedefinition_id = plpc.sizedefinition_id or
                   plpc.sizedefinition_id =
                   (select sd.sizedefinition_id
                       from sizedefinition sd
                      where sd.code = '*'))
               and ui.finishingmethod_id = plpc.finishingmethod_id
               and ui.distributionpoint_id = dp.distributionpoint_id
               and dp.department_id = d.department_id
               and d.customer_id = plpc.customer_id
               and ui.product_id = p.product_id;

            if (gv_maxrepairsplpc > 0 and
               gv_repairsotal > gv_maxrepairsplpc) or
               (gv_maxrepairsproduct > 0 and
               gv_repairsotal > gv_maxrepairsproduct and
               gv_maxrepairsplpc = 0) then
              insert into uniqueitemflag
                (uniqueitem_id,
                 flag_id,
                 startdate,
                 systemuser_id,
                 timestamp)
              values
                (gv_uniqueitemid,
                 gv_maxrepairsflagid,
                 sysdate,
                 gv_systemuser_id,
                 sysdate);
            end if;

          end if;
        end if;
      end;
    when 2 then
      --2=Repair is cancelled
      begin
        --cancel repair
        fp_message := 'cancel repair ';
        delete from repairpointer rp
         where rp.uniqueitem_id = gv_uniqueitemid
           and rp.repairtype_id = gv_repairtype_id
           and rp.sequencenumber =
               (select max(rp2.sequencenumber)
                  from repairpointer rp2
                 where rp2.uniqueitem_id = rp.uniqueitem_id
                   and rp2.repairtype_id = rp.repairtype_id);
      end;
    when 3 then
      --3-Repair is delayed
      begin
        select af.flag_id
          into gv_flag_id
          from automaticflag af
         where af.event = 'Repair requested by repair pointer';
        if gv_flag_id is null then
          raise no_data_found;
        end if;
        fp_message := 'insert into uniqueitemflag ';
        insert into uniqueitemflag
          (uniqueitem_id,
           flag_id,
           startdate,
           freetextitem,
           systemuser_id,
           timestamp,
           treatmenttype_id)
        values
          (gv_uniqueitemid,
           gv_flag_id,
           trunc(gv_scandate),
           null,
           gv_systemuser_id,
           sysdate,
           null);
      exception
        when dup_val_on_index then
          begin
            fp_message := 'update uniqueitemflag startdate to scandate ';
            update uniqueitemflag uf
               set uf.startdate = trunc(gv_scandate)
             where uf.uniqueitem_id = gv_uniqueitemid
               and uf.flag_id = gv_flag_id
               and uf.startdate > trunc(gv_scandate);
            status := 0; --is ok
          end;
        when no_data_found then
          begin
            status     := 4;
            fp_message := 'Automatic flag ''Repair requested by repair pointer'' not found for ';
            raise gv_userexception;
          end;
      end;
    else
      begin
        status     := 5;
        fp_message := 'Wrong executed value ' ||
                      nvl(to_char(executed), 'NULL') ||
                      ' is not allowed for ';
        raise gv_userexception;
      end;
  end case; --executed
  --commit transactions
  fp_message := 'Ok';
  commit;
exception
  --error handling
  when gv_userexception then
    begin
      rollback;
      if (status = 0 or status is null) then
        begin
          status := 5; --user exception
        end;
      end if;
      fp_message := 'Error, status ' || status || '; ' || fp_message ||
                    ' ID code ' || nvl(idcode, 'NULL') || ' unit code ' ||
                    nvl(unitcode, 'NULL') || ' location ' ||
                    nvl(to_char(locationcode), 'NULL');
      pack_sort.write_logging(fp_message,
                              gv_loglevel,
                              'sendrepairinfo',
                              gv_plantid_param,
                              3,
                              0);
    end;
  when no_data_found then
    begin
      rollback;
      status     := 5; --no_data_found
      fp_message := 'No data found, status 5; ' || fp_message ||
                    ' no data found for ID code ' || nvl(idcode, 'NULL') ||
                    ' unit code ' || nvl(unitcode, 'NULL') || ' location ' ||
                    nvl(to_char(locationcode), 'NULL');
      pack_sort.write_logging(fp_message,
                              gv_loglevel,
                              'sendrepairinfo',
                              gv_plantid_param,
                              3,
                              0);
    end;
  when too_many_rows then
    begin
      rollback;
      status     := 6; --too many rows
      fp_message := 'Too many rows, status 6; ' || fp_message ||
                    ' ID code ' || nvl(idcode, 'NULL') || ' unit code ' ||
                    nvl(unitcode, 'NULL') || ' location ' ||
                    nvl(to_char(locationcode), 'NULL');
      pack_sort.write_logging(fp_message,
                              gv_loglevel,
                              'sendrepairinfo',
                              gv_plantid_param,
                              3,
                              0);
    end;
  when dup_val_on_index then
    begin
      rollback;
      status     := 7; --dup_val_on_index
      fp_message := 'Dup val on index, status 7; ' || fp_message ||
                    ' ID code ' || nvl(idcode, 'NULL') || ' unit code ' ||
                    nvl(unitcode, 'NULL') || ' location ' ||
                    nvl(to_char(locationcode), 'NULL') || ' ' || sqlerrm;
      pack_sort.write_logging(fp_message,
                              gv_loglevel,
                              'sendrepairinfo',
                              gv_plantid_param,
                              3,
                              0);
    end;
  when others then
    begin
      rollback;
      status := 9; --others
      pack_sort.write_logging('Error others, status 9; ' || fp_message ||
                              ' ID code ' || nvl(idcode, 'NULL') ||
                              ' unit code ' || nvl(unitcode, 'NULL') ||
                              ' location ' ||
                              nvl(to_char(locationcode), 'NULL') ||
                              ' see debug info!',
                              gv_loglevel,
                              'sendrepairinfo',
                              gv_plantid_param,
                              3,
                              0);
      fp_message := 'Error others, status 9; ' || sqlerrm || ' ID code ' ||
                    nvl(idcode, 'NULL') || ' unit code ' ||
                    nvl(unitcode, 'NULL') || ' location ' ||
                    nvl(to_char(locationcode), 'NULL');
      pack_sort.write_logging(fp_message,
                              gv_loglevel,
                              'sendrepairinfo',
                              gv_plantid_param,
                              3,
                              0);
    end;
end sendrepairinfo;
/
create or replace procedure sendreplacement_wmu(idcode          in uniqueitem.primaryid%type,
                                                unitcode        in out plant.code%type,
                                                datep           in number,
                                                timep           in varchar2,
                                                locationcode    in varchar2,
                                                replacementtype in number,
                                                systemusername  in varchar2,
                                                statusout       out nocopy number,
                                                messagep        out nocopy varchar2) is
  pragma autonomous_transaction;
  --sendreplacement_wmu version 1.3
  --ABS-49902  ABS-52789 Create replacement WO via sorting system interface
  --global variables
  gv_user_exception exception;
  gv_languageid            languages.language_id%type;
  gv_plantid_param         plant.plant_id%type;
  gv_plantid_garment       plant.plant_id%type;
  gv_scandate              date;
  gv_systemuserid          systemuser.systemuser_id%type;
  gv_debuglevel            integer;
  gv_uniqueitemid          uniqueitem.uniqueitem_id%type;
  gv_pool                  uniqueitem.poolitem%type;
  gv_bucode                businessunit.code%type;
  gv_businessunitid        businessunit.businessunit_id%type;
  gv_primaryid             uniqueitem.primaryid%type;
  gv_secondaryid           secondaryuniqueitem.secondaryid%type;
  gv_transactiontype       sortingimportdefinition.transactiontype%type;
  gv_workstationid         workstation.workstation_id%type;
  gv_workstationcode       workstation.code%type;
  gv_plantdepartmntid      plantdepartment.plantdepartment_id%type;
  gv_replacementflagid     flag.flag_id%type;
  gv_futurereplmflagid     flag.flag_id%type;
  gv_reference_remark      workorder.remark%type;
  gv_startrentfrom         workorder.startrentfrom%type;
  gv_startrentdate         workorder.startrentdate%type;
  gv_activatereplmflag     workorder.activatereplacementflag%type;
  gv_reasoncode_id         reasoncode.reasoncode_id%type;
  gv_firstissuereason      reasoncode.firstissue%type;
  gv_reasoncode            reasoncode.code%type;
  gv_statusid              status.status_id%type;
  gv_workorderid           workorder.workorder_id%type;
  gv_workordernumber       workorder.workordernumber%type;
  gv_workorderlineid       workorderline.workorderline_id%type;
  gv_weareremploymntid     weareremployment.weareremployment_id%type;
  gv_wearerinventoryid     wearerinventory.wearerinventory_id%type;
  gv_deliverypoint_id      deliverypoint.deliverypoint_id%type;
  gv_customerid            customer.customer_id%type;
  gv_defaultbuid           customer.defaultbusinessunit_id%type;
  gv_firstdaysgradeid      customer.firstdaysgrade_id%type;
  gv_firstissuegradeid     customer.firstissuegrade_id%type;
  gv_qualitygradeid        customer.qualitygrade_id%type;
  gv_startdate             date;
  gv_enddate               date;
  gv_orderstockroomid      customer.orderingstockroom_id%type;
  gv_wearerfunctionid      weareremployment.wearerfunction_id%type;
  gv_routeid               route.route_id%type;
  gv_visitdate             date;
  gv_orderpriorityid       orderpriority.orderpriority_id%type;
  gv_productid             product.product_id%type;
  gv_sizeid                sizedefinition.sizedefinition_id%type;
  gv_finishingmethodid     finishingmethod.finishingmethod_id%type;
  gv_wearerspecialgradeid  qualitygrade.qualitygrade_id%type;
  gv_remark                wearerinventory.remark%type;
  gv_emblemtemplateid      wearerinventory.emblemtemplate_id%type;
  gv_requestedgradeid      qualitygrade.qualitygrade_id%type;
  gv_defaultsupplierid     productlistpercustomer.defaultsupplier_id%type;
  gv_plpc_emblemtemplateid productlistpercustomer.emblemtemplate_id%type;
  gv_defreqdeldays        integer;

  --internal procedures
  procedure write_log(fp_messqage in varchar2, fp_priority in number) is
  begin
    --write_log using pack_sort write logging
    pack_sort.write_logging(fp_messqage, gv_debuglevel, 'sendreplacement_wmu', gv_plantid_param,
                            fp_priority);
  end write_log;

  procedure intialize is
    --intialize internal procdures
    procedure check_parameters is
      lvtimezonehrsdiff     number;
      lv_systemsettingvalue systemsetting.value%type;
    begin
      --check_parameters
      --Step 9: Find the system user to be used as creation user for the replacement work order
      --if not found then return status 14
      --get gv_systemuserid
      statusout := 14;
      if systemusername is null then
        begin
          messagep := 'get systemuser id';
          select s.systemuser_id into gv_systemuserid from systemuser s where s.username = 'SORT';
        exception
          when no_data_found then
            select min(systemuser_id) into gv_systemuserid from systemuser;
        end;
      else
        begin
          messagep := 'system user ' || upper(systemusername);
          select su.systemuser_id
          into   gv_systemuserid
          from   systemuser su
          where  su.username = upper(systemusername);
        end;
      end if;
      --get unqiueitem info, id code
      --Step 2: Find the UniqueItem, as described in SendTrackInfo.
      --If UniqueItem not found then return status 2.
      statusout := 2;
      messagep  := 'unitcode ' || nvl(unitcode, '(Left empty)') || ' idcode ' ||
                   nvl(idcode, 'Left empty!');
      pack_sort.determinegarmentid('KANNEGIESSER', idcode, unitcode, gv_uniqueitemid, gv_pool,
                                   gv_bucode, gv_businessunitid, gv_plantid_garment, unitcode,
                                   statusout, gv_primaryid, gv_plantid_param, gv_secondaryid);
      if statusout <> 0 then
        begin
          statusout := 2;
          messagep  := 'Unknown idcode ' || nvl(idcode, '(Left empty)') || ' for unitcode ' ||
                       nvl(unitcode, '(Left empty)');
          raise gv_user_exception;
        end;
      end if;
      --get scantimestamp gv_scandate
      statusout   := -1;
      messagep    := 'get scan date time format must be date YYYYMMDD time HH(24)MISS';
      gv_scandate := nvl(to_timestamp(to_char(datep) || to_char(timep), 'YYYYMMDDHH24MISS'), sysdate);
      --get plant info for timedif and language
      messagep := 'plant id ' || gv_plantid_param;
      select pt.timezonehrsdiff, pt.language_id
      into   lvtimezonehrsdiff, gv_languageid
      from   plant pt
      where  pt.plant_id = gv_plantid_param;
      if nvl(lvtimezonehrsdiff, 0) <> 0 then
        begin
          gv_scandate := gv_scandate + (lvtimezonehrsdiff / 24);
        end;
      end if;
      --get location
      --Step 1: Find the location, as described in SendTrackInfo.
      --If Location not found then return status 1
      statusout := 1;
      messagep  := 'locationcode ' || nvl(locationcode, '(Left empty)') || ' for plant ' ||
                   unitcode || ' (next location empty)';
      select s.transactiontype, s.workstation_id, w.code, w.plantdepartment_id
      into   gv_transactiontype, gv_workstationid, gv_workstationcode, gv_plantdepartmntid
      from   sortingimportdefinition s
      join   workstation w
      on     w.workstation_id = s.workstation_id
      where  s.plant_id = gv_plantid_param
      and    s.location = locationcode
      and    s.nextlocation is null;
      --check replacementtype
      --Step 3: Find the replacement type, if unknown value then return status 3
      if replacementtype not in (1, 2, 3) then
        begin
          statusout := 3;
          messagep  := 'replacementtype must be 1,2 or 3. But its ' ||
                       nvl(to_char(replacementtype), '(Left empty)');
          raise gv_user_exception;
        end;
      else
        begin
          --Step 15: Determine reference depending on replacement type
          --This reference should be used to determine which action to take
          --when doing a manual approval within the `Work Orders waiting for Approval` dialog
          --since they will all be created with status `Waiting for approval`
          case replacementtype
            when 1 then
              gv_reference_remark := 'REPLACEMENT AFTER ISSUE';
            when 2 then
              gv_reference_remark := 'REPLACEMENT DIRECT AND RAG';
            when 3 then
              gv_reference_remark := 'REPLACEMENT NO-STOCK ITEM';
            else
              begin
                statusout := 3;
                messagep  := 'replacementtype must be 1,2 or 3. But its ' ||
                             nvl(to_char(replacementtype), '(Left empty)');
                raise gv_user_exception;
              end;
          end case;
        end;
      end if;
      --Step 13: Determine the start rent attributes and replacement flag activation, based on replacement
      --Determine the value of system setting DETERMINESTARTRENT for current plant
      select nvl(max(trim(st.value)), '0')
      into   lv_systemsettingvalue
      from   systemsetting st
      where  st.name = 'DETERMINESTARTRENT'
      and    st.plant_id = gv_plantid_param;
      if (lv_systemsettingvalue = '0') then
        begin
          gv_startrentfrom := 0;
          gv_startrentdate := null;
        end;
      else
        begin
          gv_startrentfrom := 2; --Moment of delivery
          gv_startrentdate := null;
        end;
      end if;
      if (replacementtype in (1, 3)) then
        begin
          gv_activatereplmflag := 2; --At the moment the item is issued
        end;
      else
        begin
          gv_activatereplmflag := 1; --Now
        end;
      end if;
    end check_parameters;

    procedure get_defaults is
      --internal procedures from procedure get_defaults
      procedure get_automaticflags is
      begin
        --get_automaticflags
        --step 4 :find the automatic flag for replacement,
        --if not found then return status 4
        statusout := 4;
        messagep  := 'No automatic flag for replacement defined';
        begin
          select t.flag_id
          into   gv_replacementflagid
          from   automaticflag t
          where  t.event = 'Replacement requested using replacement button'
          and    t.flag_id is not null;
        exception
          when no_data_found then
            begin
              raise gv_user_exception;
            end;
        end;
        --Step 5: Find the automatic flag for replacement with future date if any
        statusout := 0;
        select max(t.flag_id)
        into   gv_futurereplmflagid
        from   automaticflag t
        where  t.event = 'Show on replaced item before replacement is active';
      end get_automaticflags;

      procedure get_reasoncode_info is
        lv_emblemcount number;
      begin
        --get_reasoncode_info
        --Step 8: Determine the reason code to use for the replacement work order
        select count(1)
        into   lv_emblemcount
        from   uniqueitememblem uim
        where  uim.uniqueitem_link_id = gv_uniqueitemid;
        if lv_emblemcount = 0 then
          begin
            --Step 6: Find the reason code for replacement without emblem
            statusout := 5;
            messagep  := 'No reason code for replacement without emblem defined';
            begin
              select rc.reasoncode_id, rc.firstissue, rc.code
              into   gv_reasoncode_id, gv_firstissuereason, gv_reasoncode
              from   reasoncode rc
              where  rc.code = '2'
              and    rc.inventorytrigger = 6;
            exception
              when no_data_found then
                raise gv_user_exception;
            end;
          end;
        else
          begin
            --Step 7: Find the reason code for replacement with emblem
            statusout := 6;
            messagep  := 'No reason code for replacement with emblem defined';
            begin
              select rc.reasoncode_id, rc.firstissue, rc.code
              into   gv_reasoncode_id, gv_firstissuereason, gv_reasoncode
              from   reasoncode rc
              where  rc.code = '52'
              and    rc.inventorytrigger = 6;
            exception
              when no_data_found then
                raise gv_user_exception;
            end;
          end;
        end if;
      end get_reasoncode_info;

      procedure get_plantdepartment is
      begin
        --Step 16: Determine the plant department
        --get_plantdepartment, first was workstation, then customer, if still null then
        if gv_plantdepartmntid is null then
          begin
            -- Use the plant department marked as the default
            select max(pl.plantdepartment_id)
            into   gv_plantdepartmntid
            from   plantdepartment pl
            where  pl.plant_id = gv_plantid_param
            and    pl.defaultplantdepartment = 'Y';
          end;
        end if;
      end get_plantdepartment;

      procedure get_orderpriority is
      begin
        --Step 17: Determine the order priority to be used, if not found return status 12
        --Use the order priority marked as defaultforreplacement and then for standard priority
        select opr.orderpriority_id
        into   gv_orderpriorityid
        from   orderpriority opr
        where  opr.ordertype = 1
        and    opr.defaultforreplacement = 'Y';
      exception
        when no_data_found then
          begin
            --get default priority
            select opr.orderpriority_id
            into   gv_orderpriorityid
            from   orderpriority opr
            where  opr.ordertype = 1
            and    opr.standardpriority = 'Y';
          exception
            when no_data_found then
              begin
                statusout := 12;
                messagep  := 'No order priority found';
                raise gv_user_exception;
              end;
          end;
      end get_orderpriority;
    begin
      --get_defaults
      --get_automaticflags step 4 and 5
      get_automaticflags;
      --Step 14: Determine the status of the work order regardless of the replacement type
      messagep := 'get status type WO, code 05';
      select st.status_id
      into   gv_statusid
      from   status st
      where  st.statustype = 'WO'
      and    st.code = '05'; --Waiting for Approval
      --Step 8: Determine the reason code to use for the replacement work order
      get_reasoncode_info;
      --Step 10: Find additional unique item records,
      --if already linked to replacement work order then return status 8
      begin
        select un.replacementworkorderline_id, un.weareremployment_id, un.wearerinventory_id
        into   gv_workorderlineid, gv_weareremploymntid, gv_wearerinventoryid
        from   uniqueitemnonpool un
        where  un.uniqueitem_id = gv_uniqueitemid;
        if gv_workorderlineid is not null then
          begin
            statusout := 8;
            messagep  := 'Item is already being replaced';
            raise gv_user_exception;
          end;
        end if;
        --Step 11: Determine wearer and customer, if not found then return status 9
        select we.deliverypoint_id, w.customer_id, c.defaultbusinessunit_id, we.wearerfunction_id,
               nvl(gv_plantdepartmntid, c.plantdepartment_id), c.orderingstockroom_id, c.dateactive,
               c.dateactive + c.daysspecialgrade, c.firstdaysgrade_id, c.firstissuegrade_id,
               c.qualitygrade_id
        into   gv_deliverypoint_id, gv_customerid, gv_defaultbuid, gv_wearerfunctionid,
               gv_plantdepartmntid, gv_orderstockroomid, gv_startdate, gv_enddate,
               gv_firstdaysgradeid, gv_firstissuegradeid, gv_qualitygradeid
        from   weareremployment we
        join   wearer w
        on     w.wearer_id = we.wearer_id
        join   customer c
        on     c.customer_id = w.customer_id
        where  we.weareremployment_id = gv_weareremploymntid;
        if gv_customerid is null then
          begin
            statusout := 11;
            messagep  := 'No customer found';
            raise gv_user_exception;
          end;
        end if;
      exception
        when no_data_found then
          begin
            statusout := 9;
            messagep  := 'No wearer employment found';
            raise gv_user_exception;
          end;
      end;
      --Step 12: Determine the next delivery date and route for the customer
      --out parameters gv_routeid, gv_visitdate
      select nvl(max(trim(st.value)), 0)
      into   gv_defreqdeldays
      from   systemsetting st
      where  st.name = 'DEFAULTREQUESTEDDELDAYS'
      and    st.plant_id = gv_plantid_param;
      pack_sort.getnextdeliverydatewithstop(sysdate + gv_defreqdeldays, gv_plantid_param, gv_customerid, 2,
                                            gv_deliverypoint_id, gv_visitdate, gv_routeid);
      if gv_visitdate is null then
        begin
          statusout := -1;
          messagep  := 'No deliveryday found';
          raise gv_user_exception;
        end;
      end if;
      --Step 16: Determine the plant department
      get_plantdepartment;
      --Step 17: Determine the order priority to be used, if not found return status 12
      get_orderpriority;
    end get_defaults;
  begin
    --intialize
    --check_parameters
    check_parameters;
    --get_defaults
    get_defaults;
    --reset error code
    statusout := -1;
  end intialize;

  procedure process_scan is
    --internal procedures from process_scan
    procedure get_orderstockroomid is
    begin
      --Step 18: Determine the processing stockroom for the work order,
      --if not found then return status 13
      --get_orderstockroomid, gv_orderstockroomid when not null is from customer
      if gv_orderstockroomid is null then
        begin
          --Take the stockroom from the default business unit of the customer with the highest priority
          select ssbu.stockroom_id
          into   gv_orderstockroomid
          from   stockroomsservicingbu ssbu
          where  ssbu.businessunit_id = gv_defaultbuid
          and    ssbu.priority =
                 (select min(sbux.priority)
                   from   stockroomsservicingbu sbux
                   where  sbux.businessunit_id = ssbu.businessunit_id);
        exception
          when no_data_found then
            begin
              statusout := 13;
              messagep  := 'No stockroom found';
              raise gv_user_exception;
            end;
        end;
      end if;
    end get_orderstockroomid;

    procedure create_replcm_wo is
    begin
      --Step 19: Create a Replacement WO
      --create_replcm_wo
      --get workorder number
      messagep := 'create_workorder get workorder number for businessunit ' || gv_bucode;
      execute immediate 'select seq_workorder_' || gv_bucode || '.nextval from dual'
        into gv_workordernumber;
      --insert into workorder
      messagep := 'Create a Replacement WO for businessunit ' || gv_bucode;
      insert into workorder
        (workorder_id, workordernumber, weareremployment_link_id, status_id, businessunit_id,
         route_id, requestdate, entrydate, neededdate, expectedcompletedate, completiondate,
         referencenumber, remark, customerowned, billtocustomerrelated, deliverfrom, systemuser_id,
         timestamp, allowphasedelivery, labelsprinted, emblempicklistprinted, picklistprinted,
         customer_link_id, ordered, origin, pickdate, pickuser_id, availability, creditworkorder_id,
         invoiceheader_id, directinvoice, invoicebusinessunit_id, distributionpoint_link_id,
         exported, exportdate, sladeliverydate, axaptavkonr, reasoncode_id, startrentfrom,
         startrentdate, plantdepartment_id, creationuser_id, webuser, replacement, workorderprinted,
         activatereplacementflag, salespricedefined, creationtimestamp, inprocessstarted,
         inprocessatworkstation_id, dialog_id, processingstockroom_id, workorderpicked, driversales,
         truck_id, driveremployee_id, routecontrol_id, stop_id, routestop_id, expectedmountingdate,
         mountingdate, confirmationdate, mountingorder_id, mountingordersales, reservationtimestamp,
         stopnumber, salesemployee1_id, salesemployee2_id, lastprinted_date,
         lastprintedsystemuser_id, fixedstockroom, expressorder, availabilitytimestamp,
         movedweareremploymentlink_id, websalesnote, orderpriority_id, woreferencenumber_id,
         salesnotereadyforinvoicing, internalprocessingbu_id, externalprinttimestamp, subtype)
      values
        (seq_workorder.nextval, gv_workordernumber, gv_weareremploymntid, gv_statusid,
         gv_defaultbuid, gv_routeid, sysdate, sysdate, gv_visitdate, gv_visitdate,
         to_date('31-12-2099', 'dd-mm-yyyy'), null, gv_reference_remark, 'N', 'N', 0,
         gv_systemuserid, sysdate, 'N', 'N', 'N', 'N', gv_customerid, 'N', 1,
         to_date('31-12-2099', 'dd-mm-yyyy'), 0, 0, null, null, 'N', null, null, 'N', null, null,
         null, gv_reasoncode_id, gv_startrentfrom, gv_startrentdate, gv_plantdepartmntid,
         gv_systemuserid, null, 'Y', 'N', gv_activatereplmflag, 'N', sysdate, null, null, null,
         gv_orderstockroomid, 'N', 'N', null, null, null, null, null,
         to_date('31-12-2099', 'dd-mm-yyyy'), to_date('31-12-2099', 'dd-mm-yyyy'),
         to_date('31-12-2099', 'dd-mm-yyyy'), null, 'N', null, null, null, null, null, null, 'N',
         'N', null, null, 0, gv_orderpriorityid, null, 0, null, null, 0)
      returning workorder_id into gv_workorderid;
    end create_replcm_wo;

    procedure get_prod_size_fin_new_item is
    begin
      --Step 20: Determine the product, size, finishing method for the new item
      --get_prod_size_fin_new_item
      if gv_wearerinventoryid is not null then
        begin
          --get wearerinventory
          messagep := 'get_prod_size_fin_new_item wearerinventory_id ' || gv_wearerinventoryid;
          select wi.product_id, wi.sizedefinition_id, wi.finishingmethod_id, wi.specialgrade_id,
                 wi.remark, wi.emblemtemplate_id
          into   gv_productid, gv_sizeid, gv_finishingmethodid, gv_wearerspecialgradeid, gv_remark,
                 gv_emblemtemplateid
          from   wearerinventory wi
          where  wi.wearerinventory_id = gv_wearerinventoryid;
        end;
      else
        begin
          --get uniqueitem
          messagep := 'get_prod_size_fin_new_item uniqueitem ' || gv_uniqueitemid;
          select u.product_id, u.sizedefinition_id, u.finishingmethod_id
          into   gv_productid, gv_sizeid, gv_finishingmethodid
          from   uniqueitem u
          where  u.uniqueitem_id = gv_uniqueitemid;
          --set defaults
          gv_wearerspecialgradeid := null;
          gv_remark               := null;
          gv_emblemtemplateid     := null;
        end;
      end if;
    end get_prod_size_fin_new_item;

    procedure get_requested_grade is
      m_grade1_id          qualitygrade.qualitygrade_id%type;
      m_specialmingrade_id qualitygrade.qualitygrade_id%type;
      m_specialmaxgrade_id qualitygrade.qualitygrade_id%type;
      m_calc_priority      qualitygrade.priority%type;
      m_max_priority       qualitygrade.priority%type;
    begin
      --Step 21: Determine the requested grade based on customer settings
      --get_requested_grade
      messagep            := 'get_requested_grade';
      gv_requestedgradeid := null;
      if (gv_startdate < sysdate) and (sysdate < gv_enddate) then
        if (gv_firstdaysgradeid is not null) then
          gv_requestedgradeid := gv_firstdaysgradeid;
        end if;
      end if;
      if (gv_requestedgradeid is null) and (gv_weareremploymntid is not null) then
        begin
          if (gv_firstissuereason = 'Y') then
            m_grade1_id := gv_firstissuegradeid;
          else
            m_grade1_id := null;
          end if;
          --Fetch wearer function special grade settings
          if (gv_wearerfunctionid is not null) then
            begin
              --Search for WearerFunction (WF)
              select wf.specialminimumgrade_id, wf.specialmaximumgrade_id
              into   m_specialmingrade_id, m_specialmaxgrade_id
              from   wearerfunction wf
              where  wf.wearerfunction_id = gv_wearerfunctionid;
            end;
          else
            begin
              m_specialmingrade_id := null;
              m_specialmaxgrade_id := null;
            end;
          end if;
          begin
            --Compare the priorities of the all possible grades
            select q.qualitygrade_id, q.priority
            into   gv_requestedgradeid, m_calc_priority
            from   qualitygrade q
            where  q.qualitygrade_id in
                   (m_grade1_id, m_specialmingrade_id, gv_wearerspecialgradeid)
            and    q.priority =
                   (select min(qx.priority)
                     from   qualitygrade qx
                     where  qx.qualitygrade_id in
                            (m_grade1_id, m_specialmingrade_id, gv_wearerspecialgradeid));
            if m_specialmaxgrade_id is not null then
              begin
                --check if it is not above the max grade for the wearerfunction
                select q.priority
                into   m_max_priority
                from   qualitygrade q
                where  q.qualitygrade_id = m_specialmaxgrade_id;
                if m_calc_priority < m_max_priority then
                  begin
                    gv_requestedgradeid := m_specialmaxgrade_id;
                  end;
                end if;
              end;
            end if;
          exception
            when no_data_found then
              begin
                gv_requestedgradeid := gv_qualitygradeid;
              end;
          end;
        end;
      end if;
    end get_requested_grade;

    procedure determine_plpc is
    begin
      --Step 22: Determine the PLPC for the current product/size/finishing method combination
      --determine_plpc
      messagep := 'determine_plpc';
      --We need (at least) the following PLPC attributes:
      --PLPC.DefaultSupplier_ID, PLPC.AllowPreWash and PLPC.EmblemTemplate_ID
      --find plpc for right size
      select plpc.defaultsupplier_id, plpc.emblemtemplate_id
      into   gv_defaultsupplierid, gv_plpc_emblemtemplateid
      from   productlistpercustomer plpc
      where  plpc.customer_id = gv_customerid
      and    plpc.product_id = gv_productid
      and    plpc.sizedefinition_id = gv_sizeid
      and    plpc.finishingmethod_id = gv_finishingmethodid
      and    gv_scandate between plpc.dateactive and plpc.dateinactive;
    exception
      when no_data_found then
        begin
          --when not found find for size *
          select plpc.defaultsupplier_id, plpc.emblemtemplate_id
          into   gv_defaultsupplierid, gv_plpc_emblemtemplateid
          from   productlistpercustomer plpc
          where  plpc.customer_id = gv_customerid
          and    plpc.product_id = gv_productid
          and    plpc.sizedefinition_id =
                 (select s.sizedefinition_id from sizedefinition s where s.code = '*')
          and    plpc.finishingmethod_id = gv_finishingmethodid
          and    gv_scandate between plpc.dateactive and plpc.dateinactive;
        exception
          when no_data_found then
            begin
              gv_defaultsupplierid     := null;
              gv_plpc_emblemtemplateid := null;
            end;
        end;
    end determine_plpc;

    procedure determine_supplier is
      lv_systemsettingvalue systemsetting.value%type;
    begin
      --Step 23: Determine the default supplier at PLPC level when applicable
      --determine_supplier
      messagep := 'determine_supplier';
      select nvl(max(trim(st.value)), '0')
      into   lv_systemsettingvalue
      from   systemsetting st
      where  st.name = 'DEFINEDEFAULTSUPPLIERPLPC'
      and    st.plant_id = gv_plantid_param;
      if (lv_systemsettingvalue = '0') then
        begin
          gv_defaultsupplierid := null;
        end;
      end if;
    end determine_supplier;

    procedure determine_emblem_template is
    begin
      --Step 24: Determine if an emblem template is needed
      --determine_emblem_template
      messagep            := 'determine_emblem_template';
      gv_emblemtemplateid := nvl(gv_emblemtemplateid, gv_plpc_emblemtemplateid);
    end determine_emblem_template;

    procedure create_replcm_wo_line is
      lv_workorderlineid workorderline.workorderline_id%type;
    begin
      --Step 25: Create a Replacement work order line
      --create_replcm_wo_line
      messagep := 'create_replcm_wo_line';
      insert into workorderline
        (workorderline_id, workorder_id, product_link_id, sizedefinition_link_id,
         finishingmethod_id, requestedgrade_id, reasoncode_id, quantityordered, completiondate,
         codeuniquely, instructions, systemuser_id, timestamp, quantityfilled, quantitypendingorder,
         quantitycancelled, emblemtemplate_id, quantitypicked, expecteddate, quantitysubstitute,
         salesprice, quantitytobecredited, quantityreturned, wearergarmentsbudgetvalue,
         discountpercentage, salesitem, startservice, tobemounted, quantityfirstdelivery,
         quantitymounted, rentalqtyadjustment_id, salesemployee1_id, salesemployee2_id,
         replaceoption, availability, salespriceorigin, manualpricechange, internalcalcprice,
         fixedinternalcalcprice, quantityphasein, phaseinwearerinventory_id, executedby,
         defaultsupplier_id, initialissued, internalshippingdate, startrentdate)
      values
        (seq_workorderline.nextval, gv_workorderid, gv_productid, gv_sizeid, gv_finishingmethodid,
         gv_requestedgradeid, gv_reasoncode_id, 1, to_date('31-12-2099', 'dd-mm-yyyy'), 'Y',
         gv_remark, gv_systemuserid, sysdate, 0, 0, 0, gv_emblemtemplateid, 0,
         to_date('31-12-2099', 'dd-mm-yyyy'), 0, 0, 0, 0, 0, 0, 'N', 'N', 'N', 0, 0, null, null,
         null, 0, 0, 0, 0, 0, 'N', 0, null, 1, gv_defaultsupplierid, 0,
         to_date('31-12-2099', 'dd-mm-yyyy'), gv_startrentdate)
      returning workorderline_id into lv_workorderlineid;
      --Step 26: Create any modifications when applicable
      for y in (select wim.modification_id, wim.sequencenumber
                from   wearerinventorymodification wim
                where  wim.wearerinventory_id = gv_wearerinventoryid
                order  by wim.sequencenumber) loop
        begin
          messagep := 'create_replcm_wo_line modification';
          insert into workorderlinemodification
            (workorderline_id, modification_id, sequencenumber, systemuser_id, timestamp)
          values
            (lv_workorderlineid, y.modification_id, y.sequencenumber, gv_systemuserid, sysdate);
        end;
      end loop; --y
      --Step 27: Create any emblem lines based on emblem template when applicable
      for z in (select etl.*
                from   emblemtemplateline etl
                where  etl.emblemtemplate_id = gv_emblemtemplateid) loop
        begin
          insert into workorderlineemblem
            (workorderlineemblem_id, emblemtemplateline_id, workorderline_id, product_id,
             sizedefinition_id, attachmentby, qtyrequested, qtyissued, systemuser_id, timestamp,
             placement_id, purchaserequest_id, purchaseorderline_id, embroiderylettering,
             embroideryletteringline1, embroideryletteringline2, embroideryletteringline3,
             salesprice)
          values
            (seq_workorderlineemblem.nextval, z.emblemtemplateline_id, lv_workorderlineid, null,
             null, 0, z.qtypergarment, 0, gv_systemuserid, sysdate, z.placement_id, null, null,
             z.embroiderylettering,
             case when z.emblemtype <> 2 then z.embroideryletteringline1 else null end,
             case when z.emblemtype <> 2 then z.embroideryletteringline2 else null end,
             case when z.emblemtype <> 2 then z.embroideryletteringline3 else null end, 0);
        end;
      end loop; --z
      --Step 28: Link the work order to the unique item
      update uniqueitemnonpool un
      set    un.replacementworkorderline_id = lv_workorderlineid, un.timestamp = sysdate,
             un.systemuser_id = gv_systemuserid
      where  un.uniqueitem_id = gv_uniqueitemid;
    end create_replcm_wo_line;

    procedure active_replcm_flag is
      lv_startdate       date;
      lv_reasoncode_desc reasoncode_desc.description%type;
      lv_freetext        uniqueitemflag.freetextitem%type;
    begin
      --Step 29: Activate the replacement flags depending on replacement type
      --active_replcm_flag
      messagep := 'active_replcm_flag';
      if gv_activatereplmflag = 1 then
        begin
          lv_startdate := sysdate;
        end;
      else
        begin
          lv_startdate := to_date('31-12-2099', 'dd-mm-yyyy');
        end;
      end if;
      --get reasoncode desc
      messagep := 'reasoncode desc for reasoncode ' || gv_reasoncode;
      select nvl(max(rcd.description), '-')
      into   lv_reasoncode_desc
      from   reasoncode_desc rcd
      where  rcd.reasoncode_id = gv_reasoncode_id
      and    rcd.language_id = gv_languageid;
      --free text
      lv_freetext := gv_workordernumber || ',' || gv_reasoncode || ' ' || lv_reasoncode_desc || ' ' ||
                     to_char(sysdate, 'YYYY-MM-DD');
      --
      messagep := 'merge into uniqueitemflag automatic replacementflag';
      merge into uniqueitemflag uif
      using (select gv_uniqueitemid as uniqueitem_id, gv_replacementflagid as flag_id from dual x) z
      on (z.uniqueitem_id = uif.uniqueitem_id and z.flag_id = uif.flag_id)
      when matched then
        update
        set    uif.startdate = lv_startdate, uif.freetextitem = lv_freetext,
               uif.systemuser_id = gv_systemuserid, uif.timestamp = sysdate
      when not matched then
        insert
          (uif.uniqueitem_id, uif.flag_id, uif.startdate, uif.freetextitem, uif.systemuser_id,
           uif.timestamp)
        values
          (gv_uniqueitemid, gv_replacementflagid, lv_startdate, lv_freetext, gv_systemuserid,
           sysdate);
      --future replacement flag
      if gv_futurereplmflagid is not null and gv_activatereplmflag = 2 then
        begin
          messagep := 'merge into uniqueitemflag future replacement flag';
          merge into uniqueitemflag uif
          using (select gv_uniqueitemid as uniqueitem_id, gv_futurereplmflagid as flag_id
                 from   dual x) z
          on (z.uniqueitem_id = uif.uniqueitem_id and z.flag_id = uif.flag_id)
          when matched then
            update
            set    uif.startdate = lv_startdate, uif.freetextitem = lv_freetext,
                   uif.systemuser_id = gv_systemuserid, uif.timestamp = sysdate
          when not matched then
            insert
              (uif.uniqueitem_id, uif.flag_id, uif.startdate, uif.freetextitem, uif.systemuser_id,
               uif.timestamp)
            values
              (gv_uniqueitemid, gv_futurereplmflagid, lv_startdate, lv_freetext, gv_systemuserid,
               sysdate);
        end;
      end if;
    end active_replcm_flag;

    procedure upd_wearerinv_item_returned is
    begin
      --Step 30: Update the the number of items to be returned due to replacement for the wearerinventory
      --upd_wearerinv_item_returned
      messagep := 'upd_wearerinv_item_returned';
      if gv_activatereplmflag = 1 then
        begin
          update wearerinventory wi
          set    wi.qtytobereturnedreplacement = wi.qtytobereturnedreplacement + 1,
                 wi.systemuser_id = gv_systemuserid, wi.timestamp = sysdate
          where  wi.wearerinventory_id = gv_wearerinventoryid;
        end;
      end if;
    end upd_wearerinv_item_returned;
  begin
    --Step 18: Determine the processing stockroom for the work order, if not found then return status 13
    get_orderstockroomid;
    --Step 19: Create a Replacement WO
    create_replcm_wo;
    --Step 20: Determine the product, size, finishing method for the new item
    get_prod_size_fin_new_item;
    --Step 21: Determine the requested grade based on customer settings
    get_requested_grade;
    --Step 22: Determine the PLPC for the current product/size/finishing method combination
    determine_plpc;
    --Step 23: Determine the default supplier at PLPC level when applicable
    determine_supplier;
    --Step 24: Determine if an emblem template is needed
    determine_emblem_template;
    --Step 25: Create a Replacement work order line
    create_replcm_wo_line;
    --Step 29: Activate the replacement flags depending on replacement type
    active_replcm_flag;
    --Step 30: Update the the number of items to be returned due to replacement for the wearerinventory
    upd_wearerinv_item_returned;
  end process_scan;

  procedure finalize is
  begin
    --finalize and commit
    statusout := 0;
    messagep  := 'all ok, before doing commit, for Workorder ' || gv_workordernumber;
    commit;
    messagep := 'Processed ok, Workorder ' || gv_workordernumber || ' created';
  end finalize;
begin
  --Main program part for sendreplacement_wmu
  --intialize
  intialize;
  --process_scan
  process_scan;
  --finalize
  finalize;
exception
  --All exception handling
  when gv_user_exception then
    begin
      rollback;
      write_log(messagep, 3);
      if statusout = 0 then
        statusout := -1;
      end if;
    end;
  when no_data_found then
    begin
      rollback;
      write_log('unitcode ' || unitcode || ' idcode ' || idcode || ' datep ' || datep || ' timep ' ||
                timep || ' locationcode ' || locationcode || ' replacementtype ' ||
                replacementtype || ' systemusername' || systemusername || ' No data found ' ||
                messagep, 3);
      messagep := 'No data found ' || messagep;
      if statusout = 0 then
        statusout := -1;
      end if;
    end;
  when others then
    begin
      rollback;
      if statusout = 0 then
        statusout := -1;
      end if;
      messagep := 'unitcode ' || unitcode || ' idcode ' || idcode || ' datep ' || datep ||
                  ' timep ' || timep || ' locationcode ' || locationcode || ' replacementtype ' ||
                  replacementtype || ' systemusername' || systemusername || ' Exception Others; ' ||
                  sqlerrm || ' ' || messagep;
      write_log(messagep, 3);
      if replace(sqlerrm, 'ORA-04068') <> sqlerrm then
        raise; -->recompile ora ORA-04068 related - only raise related ORA-04068
      end if;
    end;
end sendreplacement_wmu;
/
create or replace procedure sendtrackinfo(idcode           in uniqueitem.primaryid%type,
                                          unitcode         in out plant.code%type,
                                          datep            in number,
                                          timep            in varchar2, --number,
                                          locationcode     in varchar2,
                                          nextlocationcode in varchar2,
                                          flagcode1        in sortaddressperflag.sortaddress%type,
                                          flagcode2        in sortaddressperflag.sortaddress%type,
                                          flagcode3        in sortaddressperflag.sortaddress%type,
                                          flagcode4        in sortaddressperflag.sortaddress%type,
                                          batchnumber      in number,
                                          routenumber      in route.routenumber%type,
                                          routeday         in day.daynumber%type,
                                          repairsdone      in varchar2,
                                          statusout        in out number,
                                          --502595
                                          fppickupdate   in number default null,
                                          fpretransferyn in varchar2 default 'N',
                                          metricon       in varchar2 default 'N',
                                          fpbatchnumber  in varchar2 default null) is
  --version 2.0
  plantid_param             plant.plant_id%type;
  plantid_garment           plant.plant_id%type;
  sortingimportdefinitionid sortingimportdefinition.sortingimportdefinition_id%type;
  uniqueitemid              uniqueitem.uniqueitem_id%type;
  workstationid             workstation.workstation_id%type;
  gv_workstationcode        workstation.code%type;
  transactiontp             sortingimportdefinition.transactiontype%type;
  businessunitid            businessunit.businessunit_id%type;
  wsbusinessunitid          workstation.businessunit_id%type;
  pool                      integer;
  countwashesat             varchar2(1);
  scanbyroute               varchar2(1);
  gv_systemuserid           systemuser.systemuser_id%type;
  secondaryid               secondaryuniqueitem.secondaryid%type;
  gv_relatedcustomerid      uniqueitem.relatedcustomer_id%type;
  accept                    varchar2(1);
  utldir                    varchar2(50); --:= 'D:\output';-- please see ABS-92804 variable needs the name of an existing oracle directory
  utldiroff                 varchar2(50); --:= 'D:\output\OFFLINE';-- 501534
  fpsfilenameoff            varchar2(50); --:= 'Offline.txt';-- 501534
  sqlfileoff                utl_file.file_type; -- 501534
  sqlfileoffyes             utl_file.file_type; -- 501534
  offline                   varchar2(1); -- 501534
  gv_lastscandatetime       date;
  debuglevel                integer;
  sessionsid                integer;
  sessionserialnr           integer;
  bucode                    businessunit.code%type;
  returnedplantcode         plant.code%type;
  scaninterval              varchar2(1);
  plantcodein               plant.code%type;
  gv_ui_batchnumber         uniqueitem.batchnumber%type;
  sortbatchstatus           sortbatch.status%type;
  sortbatchnumber           sortbatch.sortbatch_id%type;
  ordernumber               packingnote.notenumber%type;
  packingnoteid             packingnote.packingnote_id%type;
  pnstatus                  status.status_id%type;
  statuscode                status.code%type;
  overrulledstatusout       integer := 0;
  --todo 6660
  idprimary uniqueitem.primaryid%type;
  --order 502305
  exceptionnonunique exception;
  lvnproductid         product.product_id%type;
  lvsproductlegacycode product.legacyproductcode%type;
  lvnsizeid            sizedefinition.sizedefinition_id%type;
  lvnfinmetid          finishingmethod.finishingmethod_id%type;
  lvncustomerid        customer.customer_id%type;
  lvncustomernumber    customer.customernumber%type;
  lvndistributionid    distributionpoint.distributionpoint_id%type;
  lvdnextdeldate       date;
  lvssizecode          sizedefinition.code%type;
  --502595
  lvpickupdate           date := null;
  lvtimezonehrsdiff      number;
  lvdatep                number;
  lvtimep                varchar2(6);
  m_deliveryscan         varchar2(1);
  m_noregularoutscan     customergarmentdispenser.noregularoutscan%type;
  m_message              varchar2(1000);
  lv_databasecode        databasesettings.code%type;
  lv_prodprocessbufferid workstation.productionprocessbuffer_id%type;
  lv_prevstayid          uniqueitem.prevstay_id%type;
  lv_lastinscandate      uniqueitem.lastinscandate%type;
  ---------------------------------------------
  procedure support_uhf_buffer is
    /*
    UHF buffer processing
    In case of inscan/rewashscan/repair/checkpointscan/sort scan:
    add the following logic after sucessfully creating the scan record (and scanflags)
    if workstation.laundryprocessbuffer_id <> null and length of IDCode = 24 (UHF Tag)  then
       1 save prev. values of uniqueitembufferinfo
       2 create/update uniqueitembufferinfo
       3 create productionprocesscan
       4 create/update prodprocessscanaggr
       5 delete uniqueitembufferinfo---> only be done for outscan transactions!!
     */
    lv_new_uniqueitembufferinfoid uniqueitembufferinfo.uniqueitembufferinfo_id%type;
    lv_prev_prodprocessbufferid   uniqueitembufferinfo.productionprocessbuffer_id%type;
    lv_lastscantimestamp          uniqueitembufferinfo.lastscantimestamp%type;
    lv_lastinscantimestamp        uniqueitembufferinfo.inscantimestamp%type;
    lv_found_ubf                  boolean;

    procedure load_uniqueitem_buffer_info is
      --1 save prev. values of uniqueitembufferinfo
      -- to store previous values that are later needed when creating buffer scans
    begin
      /*
        save previous values from uniqueitembufferinfo
        read uniqueitembufferinfo based on uniqueitem_id
        store in variables:
        prev_productionprocessbuffer_id
        prev_lastscantimestamp
        prev_lastinscantimestamp
      */
      m_message := 'Load buffer Info';
      select ubf.productionprocessbuffer_id, ubf.lastscantimestamp, ubf.inscantimestamp,
             ubf.uniqueitembufferinfo_id
      into   lv_prev_prodprocessbufferid, lv_lastscantimestamp, lv_lastinscantimestamp,
             lv_new_uniqueitembufferinfoid
      from   uniqueitembufferinfo ubf
      where  ubf.uniqueitem_id = uniqueitemid;
      lv_found_ubf := true;
    exception
      when no_data_found then
        begin
          -- not found then null for all 3.
          lv_prev_prodprocessbufferid := null;
          lv_lastscantimestamp        := null;
          lv_lastinscantimestamp      := null;
          lv_found_ubf                := false;
        end;
    end load_uniqueitem_buffer_info;

    procedure insertupdate_uniqueitembufinfo is
      lv_stayoutscancustomerid stay.stay_id%type;
    begin
      if lv_found_ubf then
        begin
          --insertupdate_uniqueitembufinfo
          m_message := 'Update Unique Item Buffer Info';
          update uniqueitembufferinfo ubf
          set    ubf.plant_id = plantid_param, ubf.businessunit_id = wsbusinessunitid,
                 ubf.lastscandate = trunc(gv_lastscandatetime),
                 ubf.lastscantimestamp = gv_lastscandatetime, ubf.idcode = idcode,
                 ubf.relatedcustomer_link_id = gv_relatedcustomerid,
                 ubf.product_link_id = lvnproductid, ubf.sizedefinition_link_id = lvnsizeid,
                 ubf.productionprocessbuffer_id = lv_prodprocessbufferid,
                 ubf.prevprodprocessbuffer_id = ubf.productionprocessbuffer_id,
                 ubf.batchnumber = gv_ui_batchnumber, ubf.lastscanstation = gv_workstationcode,
                 ubf.systemuser_id = gv_systemuserid, ubf.timestamp = sysdate
          where  ubf.uniqueitem_id = uniqueitemid;
        end;
      else
        begin
          if transactiontp = 1 then
            lv_lastinscantimestamp := gv_lastscandatetime;
          elsif lv_lastinscantimestamp is null then
            begin
              m_message := 'Get stay nr 1 / 20 outscan customer';
              select st.stay_id
              into   lv_stayoutscancustomerid
              from   stay st
              where  st.staytype = 1
              and    st.staynr = 20;
              if lv_stayoutscancustomerid = lv_prevstayid then
                lv_lastinscantimestamp := gv_lastscandatetime;
              else
                lv_lastinscantimestamp := nvl(lv_lastinscandate, gv_lastscandatetime);
              end if;
            end;
          end if;
          m_message := 'Insert Unique Item Buffer Info';
          insert into uniqueitembufferinfo
            (uniqueitembufferinfo_id, uniqueitem_id, plant_id, businessunit_id, lastscandate,
             lastscantimestamp, inscantimestamp, idcode, relatedcustomer_link_id, product_link_id,
             sizedefinition_link_id, productionprocessbuffer_id, prevprodprocessbuffer_id,
             batchnumber, lastscanstation, systemuser_id, timestamp)
          values
            (seq_uniqueitembufferinfo.nextval, uniqueitemid, plantid_param, wsbusinessunitid,
             trunc(gv_lastscandatetime), gv_lastscandatetime, lv_lastinscantimestamp, idcode,
             gv_relatedcustomerid, lvnproductid, lvnsizeid, lv_prodprocessbufferid,
             lv_prev_prodprocessbufferid, gv_ui_batchnumber, gv_workstationcode, gv_systemuserid,
             sysdate)
          returning uniqueitembufferinfo_id into lv_new_uniqueitembufferinfoid;
        end;
      end if;
    end insertupdate_uniqueitembufinfo;

    procedure create_prodprocessbufscans is
      lv_productionprocessscanid productionprocessscan.productionprocessscan_id%type;
    begin
      --create_prodprocessbufscans
      m_message := 'Create Production Process Buffer Scans';
      insert into productionprocessscan
        (productionprocessscan_id, plant_id, businessunit_id, scandate, scantimestamp,
         uniqueitem_link_id, uniqueitembufferinfo_id, idcode, relatedcustomer_link_id,
         product_link_id, sizedefinition_link_id, toprodprocessbuffer_id, fromprodprocessbuffer_id,
         minutesinpreviousbuffer, minutessinceinscan, batchnumber, scanstation, systemuser_id,
         timestamp)
      values
        (seq_productionprocessscan.nextval, plantid_param, wsbusinessunitid,
         trunc(gv_lastscandatetime), gv_lastscandatetime, uniqueitemid,
         lv_new_uniqueitembufferinfoid, idcode, gv_relatedcustomerid, lvnproductid, lvnsizeid,
         lv_prodprocessbufferid, lv_prev_prodprocessbufferid,
         case when lv_lastscantimestamp is null then 0 else
          pack_multiread.plantoperatingtimeoverlap(plantid_param, lv_lastscantimestamp,
                                                   gv_lastscandatetime) end,
         case when lv_lastinscantimestamp is null then 0 else
          pack_multiread.plantoperatingtimeoverlap(plantid_param, lv_lastinscantimestamp,
                                                   gv_lastscandatetime) end, gv_ui_batchnumber,
         gv_workstationcode, gv_systemuserid, sysdate)
      returning productionprocessscan_id into lv_productionprocessscanid;
      ---merge into productionprocessscanaggr
      --BUSINESSUNIT_ID, SCANDATE, NVL(RELATEDCUSTOMER_LINK_ID,(-1)),
      --PRODUCT_LINK_ID, SIZEDEFINITION_LINK_ID, NVL(TOPRODPROCESSBUFFER_ID,(-1)),
      --NVL(FROMPRODPROCESSBUFFER_ID,(-1)), NVL(BATCHNUMBER,'-1'), SCANSTATION
      m_message := 'Merge Production Process Buffer Scan Aggregation';
      merge into productionprocessscanaggr ppsa
      using (select ps.businessunit_id, ps.scandate, ps.relatedcustomer_link_id, ps.product_link_id,
                    ps.sizedefinition_link_id, ps.toprodprocessbuffer_id, ps.fromprodprocessbuffer_id,
                    ps.batchnumber, ps.scanstation, 1 number_of_scans,
                    ps.minutesinpreviousbuffer minutesinprevbuffer,
                    ps.minutessinceinscan minutessinceinscan
             from   productionprocessscan ps
             where  ps.productionprocessscan_id = lv_productionprocessscanid) merge_subquery
      on (ppsa.businessunit_id = merge_subquery.businessunit_id and ppsa.scandate = merge_subquery.scandate and nvl(ppsa.relatedcustomer_link_id, -1) = nvl(merge_subquery.relatedcustomer_link_id, -1) and ppsa.product_link_id = merge_subquery.product_link_id and ppsa.sizedefinition_link_id = merge_subquery.sizedefinition_link_id and nvl(ppsa.toprodprocessbuffer_id, -1) = nvl(merge_subquery.toprodprocessbuffer_id, -1) and nvl(ppsa.fromprodprocessbuffer_id, -1) = nvl(merge_subquery.fromprodprocessbuffer_id, -1) and nvl(ppsa.batchnumber, -1) = nvl(merge_subquery.batchnumber, -1) and ppsa.scanstation = merge_subquery.scanstation)
      when matched then
        update
        set    ppsa.numberofscans = ppsa.numberofscans + merge_subquery.number_of_scans,
               ppsa.totalminutesinprevbuffer = ppsa.totalminutesinprevbuffer +
                                                merge_subquery.minutesinprevbuffer,
               ppsa.totalminutessinceinscan = ppsa.totalminutessinceinscan +
                                               merge_subquery.minutessinceinscan,
               ppsa.systemuser_id = gv_systemuserid, ppsa.timestamp = sysdate
      when not matched then
        insert
          (productionprocessscanaggr_id, businessunit_id, scandate, relatedcustomer_link_id,
           product_link_id, sizedefinition_link_id, toprodprocessbuffer_id, fromprodprocessbuffer_id,
           batchnumber, scanstation, numberofscans, totalminutesinprevbuffer,
           totalminutessinceinscan, systemuser_id, timestamp)
        values
          (seq_productionprocessscanaggr.nextval, merge_subquery.businessunit_id,
           merge_subquery.scandate, merge_subquery.relatedcustomer_link_id,
           merge_subquery.product_link_id, merge_subquery.sizedefinition_link_id,
           merge_subquery.toprodprocessbuffer_id, merge_subquery.fromprodprocessbuffer_id,
           merge_subquery.batchnumber, merge_subquery.scanstation, merge_subquery.number_of_scans,
           merge_subquery.minutesinprevbuffer, merge_subquery.minutessinceinscan, gv_systemuserid,
           sysdate);
    end create_prodprocessbufscans;

    procedure delete_uniqueitem_buffer_info is
    begin
      --delete_uniqueitem_buffer_info
      m_message := 'Delete Unique Item Buffer Info';
      delete from uniqueitembufferinfo u where u.uniqueitem_id = uniqueitemid;
    end delete_uniqueitem_buffer_info;
  begin
    --support_uhf_buffer
    if (accept = 'Y' and nvl(scaninterval, 'Y') = 'Y' and length(idcode) = 24 and
       (lv_prodprocessbufferid is not null or transactiontp = 2)) then
      begin
        --Step 1 load_uniqueitem_buffer_info
        load_uniqueitem_buffer_info;
        --Check if it is not already in the buffer if so skip step 2 and 3
        if (nvl(lv_prodprocessbufferid, -1) <> nvl(lv_prev_prodprocessbufferid, -1) and
           nvl(lv_lastscantimestamp, to_date('1-1-2000', 'dd-mm-yyyy')) <= gv_lastscandatetime) then
          begin
            --Step 2 insertupdate_uniqueitembufinfo
            insertupdate_uniqueitembufinfo;
            --Step 3/4 create_prodprocessbufscans and productionprocessscanaggr
            create_prodprocessbufscans;
          end;
        end if;
        if transactiontp = 2 then
          begin
            --Step 5, if Outscan, remove buffer info
            delete_uniqueitem_buffer_info;
          end;
        end if;
        commit;
      end;
    end if;
  end support_uhf_buffer;
begin
  m_message := 'sendtrackinfo';
  lvdatep   := datep;
  lvtimep   := timep;
  --get database code
  select max(t.code) into lv_databasecode from databasesettings t;
  -------step 1
  plantcodein := unitcode;
  --order 501875
  ordernumber         := statusout;
  statusout           := 0;
  gv_lastscandatetime := to_timestamp(to_char(lvdatep) || to_char(lvtimep), 'YYYYMMDDHH24MISS');
  --systemuser
  begin
    select s.systemuser_id into gv_systemuserid from systemuser s where s.username = 'SORT';
  exception
    when no_data_found then
      select min(systemuser_id) into gv_systemuserid from systemuser;
  end;
  --502595
  if fppickupdate is not null then
    begin
      lvpickupdate := to_date(fppickupdate, 'YYYYMMDD');
    end;
  end if; --if fpPickupDate is not null then
  --order 502305 extra check
  if idcode = 'FFFF0001' then
    begin
      lvsproductlegacycode := routenumber;
      lvncustomernumber    := batchnumber;
      select p.plant_id into plantid_param from plant p where p.code = unitcode;
    exception
      when no_data_found then
        begin
          select min(p.plant_id) into plantid_param from plant p;
        end;
    end;
  else
    begin
      m_message := 'pack_sort.determinegarmentid';
      if flagcode1 = '-Kann-' then
        pack_sort.determinegarmentid2('KANNEGIESSER', idcode, unitcode, uniqueitemid, pool, bucode,
                                      businessunitid, plantid_garment, returnedplantcode, statusout,
                                      idprimary, plantid_param, secondaryid, gv_relatedcustomerid,
                                      lvnproductid, lvnsizeid, gv_ui_batchnumber, lv_prevstayid,
                                      lv_lastinscandate);
      else
        pack_sort.determinegarmentid2('METRIC', idcode, unitcode, uniqueitemid, pool, bucode,
                                      businessunitid, plantid_garment, returnedplantcode,
                                      --not used for metric
                                      statusout, idprimary, plantid_param, secondaryid,
                                      gv_relatedcustomerid, lvnproductid, lvnsizeid,
                                      gv_ui_batchnumber, lv_prevstayid, lv_lastinscandate);
      end if;
    end; --end extra check order 502305
  end if;
  pack_sort.getsystemsettings(plantid_param, debuglevel, utldir, sessionsid, 1); --misuse sessionid, reloaded anyway
  --502595
  begin
    select nvl(pt.timezonehrsdiff, 0)
    into   lvtimezonehrsdiff
    from   plant pt
    where  pt.plant_id = plantid_param;
  exception
    when others then
      lvtimezonehrsdiff := 0;
  end;
  if lvtimezonehrsdiff <> 0 then
    begin
      gv_lastscandatetime := gv_lastscandatetime + (lvtimezonehrsdiff / 24);
      lvdatep             := to_char(gv_lastscandatetime, 'YYYYMMDD');
      lvtimep             := to_char(gv_lastscandatetime, 'HH24MISS');
    end;
  end if;
  --
  select a.sid, a.serial#
  into   sessionsid, sessionserialnr
  from   sys.v_$session a
  where  a.audsid = (select sys_context('USERENV', 'SESSIONID') from dual);
  if debuglevel > 0 then
    pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' || lvtimep || ' ' ||
                            locationcode || ' ' || nextlocationcode, debuglevel, 'SENDTRACKINFO',
                            plantid_param, 1, 1);
  end if;
  if statusout = 1 then
    if uniqueitemid is null then
      pack_sort.write_logging('Uniqueitemid for IDCODE ' || idcode || ' plant code ' ||
                              plantcodein || ' is not found...', debuglevel, 'SENDTRACKINFO',
                              plantid_param, 3, 1);
    end if;
    if debuglevel > 0 then
      if businessunitid is null then
        pack_sort.write_logging('BusinessunitID for IDCODE ' || idcode || ' plant ' || plantcodein ||
                                ' is not found...', debuglevel, 'SENDTRACKINFO', plantid_param, 3, 1);
      end if;
      if plantid_param is null then
        pack_sort.write_logging('PlantID for IDCODE ' || idcode || ' plant ' || plantcodein ||
                                ' is not found...', debuglevel, 'SENDTRACKINFO', plantid_param, 3, 1);
      end if;
    end if;
  end if;
  --502595
  if fppickupdate is null and fpretransferyn = 'Y' then
    begin
      statusout := 5; --retransfer Y with no pickup date=status out 5
      pack_sort.write_logging('Error for IDCODE ' || idcode ||
                              ' not allowed NULL pickupdate when retransfer = Y', debuglevel,
                              'SENDTRACKINFO', plantid_param, 3, 1);
    end;
  end if;
  --
  if statusout = 2 then
    pack_sort.write_logging('Error (statusout=2) for IDCODE ' || idcode || 'plant code ' ||
                            plantcodein, debuglevel, 'SENDTRACKINFO', plantid_param, 3, 1);
  end if;
  --statusout = 0 and nextlocation null/ or not null
  if statusout = 0 and nextlocationcode is null then
    --or nextlocationcode='' then
    begin
      select s.sortingimportdefinition_id, s.transactiontype, s.workstation_id, w.code,
             w.productionprocessbuffer_id, w.businessunit_id
      into   sortingimportdefinitionid, transactiontp, workstationid, gv_workstationcode,
             lv_prodprocessbufferid, wsbusinessunitid
      from   sortingimportdefinition s, workstation w
      where  s.plant_id = plantid_param
      and    s.location = locationcode
      and    s.nextlocation is null
      and    s.workstation_id = w.workstation_id;
    exception
      when no_data_found then
        begin
          statusout := 1;
          pack_sort.write_logging('Location definition is not found ' || unitcode || ' ' || idcode || ' ' ||
                                  lvdatep || ' ' || lvtimep || ' ' || locationcode || ' ' ||
                                  nextlocationcode, debuglevel, 'SENDTRACKINFO', plantid_param, 3, 1);
        end;
      when others then
        begin
          statusout := 1;
          pack_sort.write_logging('Error (other) finding location' || unitcode || ' ' || idcode || ' ' ||
                                  lvdatep || ' ' || lvtimep || ' ' || locationcode || ' ' ||
                                  nextlocationcode || ' Sqlerror ' || sqlerrm, debuglevel,
                                  'SENDTRACKINFO', plantid_param, 3, 1);
        end;
    end;
  elsif statusout = 0 and nextlocationcode is not null then
    begin
      select s.sortingimportdefinition_id, s.transactiontype, s.workstation_id, w.code,
             w.productionprocessbuffer_id, w.businessunit_id
      into   sortingimportdefinitionid, transactiontp, workstationid, gv_workstationcode,
             lv_prodprocessbufferid, wsbusinessunitid
      from   sortingimportdefinition s, workstation w
      where  s.plant_id = plantid_param
      and    s.location = locationcode
      and    s.nextlocation = nextlocationcode
      and    s.workstation_id = w.workstation_id;
    exception
      when no_data_found then
        begin
          statusout := 1;
          pack_sort.write_logging('Location definition is not found' || unitcode || ' ' || idcode || ' ' ||
                                  lvdatep || ' ' || lvtimep || ' ' || locationcode || ' ' ||
                                  nextlocationcode, debuglevel, 'SENDTRACKINFO', plantid_param, 3, 1);
        end;
      when others then
        begin
          statusout := 1;
          pack_sort.write_logging('Error (other) finding location' || unitcode || ' ' || idcode || ' ' ||
                                  lvdatep || ' ' || lvtimep || ' ' || locationcode || ' ' ||
                                  nextlocationcode || ' Sqlerror ' || sqlerrm, debuglevel,
                                  'SENDTRACKINFO', plantid_param, 3, 1);
        end;
    end;
  end if;
  --end step2
  --order 502305 extra check
  if idcode = 'FFFF0001' and statusout = 0 then
    begin
      raise exceptionnonunique;
    end;
  end if; --end 502305
  --------step 3
  --if stock = pool=0 then skip step U3 order#20014462
  if statusout = 0 and nvl(pool, -1) <> 0 then
    begin
      --system settings
      select s.value
      into   countwashesat
      from   systemsetting s
      where  s.name = 'COUNTWASHESAT'
      and    s.plant_id = plantid_param;
      select s.value
      into   scanbyroute
      from   systemsetting s
      where  s.plant_id = plantid_param
      and    s.name = 'SCANBYROUTE';
    exception
      when others then
        null;
    end;
    if transactiontp = 2 and uniqueitemid is not null and nvl(pool, 1) <> 1 then
      begin
        select nvl((case cgd.processtrans2asoutscan
                      when 'Y' then
                       'N'
                      else
                       'Y'
                    end), 'Y'), nvl(cgd.noregularoutscan, 0)
        into   m_deliveryscan, m_noregularoutscan
        from   uniqueitemnonpool n, weareremployment e
        left   outer join(garmentdispenser gd
        join   customergarmentdispenser cgd
        on     gd.customer_id = cgd.customer_id) on gd.garmentdispenser_id = e.garmentdispenser_id
        where  n.uniqueitem_id = uniqueitemid
        and    n.weareremployment_id = e.weareremployment_id;
        if m_noregularoutscan = 1 then
          m_deliveryscan := 'F'; --free of charge deliveryscan
        elsif nvl(metricon, 'N') <> 'Y' and m_deliveryscan <> 'Y' then
          m_deliveryscan := 'Y';
        end if;
      exception
        when others then
          m_deliveryscan := 'Y';
      end;
    end if;
    case transactiontp
      when 1 then
        begin
          --Inscan
          m_message := 'pack_sort.processinscan';
          pack_sort.processinscan(transactiontp, idprimary, pool, secondaryid, plantid_garment,
                                  plantid_param, businessunitid, uniqueitemid, gv_workstationcode,
                                  lvdatep, lvtimep, countwashesat, scanbyroute, gv_systemuserid,
                                  debuglevel, accept, scaninterval, lvpickupdate, fpretransferyn,
                                  flagcode1, flagcode2, flagcode3, flagcode4, fpbatchnumber);
          if accept = 'Y' and scaninterval = 'Y' then
            begin
              commit;
              if debuglevel > 0 then
                pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                        lvtimep || ' ' || locationcode || ' ' || nextlocationcode || ' ' ||
                                        'InScan OK', debuglevel, 'SENDTRACKINFO', plantid_param, 1,
                                        1);
              end if;
            end;
          else
            begin
              rollback;
              if accept = 'N' then
                statusout := 1;
              end if;
              pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                      lvtimep || ' ' || locationcode || ' ' || nextlocationcode ||
                                      ' InScan NOT accepted, scaninterval ' || scaninterval || ' ' ||
                                      m_message, debuglevel, 'SENDTRACKINFO', plantid_param, 3, 1);
            end;
          end if;
        end;
      when 2 then
        begin
          --Outscan
          accept := 'Y';
          if pool in (1, 2) then
            --501875
            begin
              overrulledstatusout := 0;
              if ordernumber > 10 then
                select p.packingnote_id, p.status_id
                into   packingnoteid, pnstatus
                from   packingnote p
                where  p.notenumber = ordernumber;
                select s.code
                into   statuscode
                from   status s
                where  s.statustype = 'PN'
                and    s.status_id = pnstatus;
                if statuscode in ('30', '40') then
                  begin
                    if pool = 2 -- personalized garments non pool.
                      then
                        ---we still accept the scan, pass empty packingnote to pack_sort.process)_outscan!
                        packingnoteid := null; -- HVH 17/2/2009 todo 8511
                      else ---we don't accept the scan
                        accept              := 'N';
                    end if;
                        overrulledstatusout := 1;
                        m_message           := 'order number ' || ordernumber || ' has status ' ||
                                               statuscode || ' which is not allowed';

                  end;
                end if;
              elsif (pool = 1 and nvl(ordernumber, 1) <= 10) then
                begin
                  packingnoteid       := null; -- HVH 17/2/2009 Todo 8511
                  overrulledstatusout := 5;
                  m_message           := 'order number must be > 10, but order number ' ||
                                         nvl(to_char(ordernumber), 'IS NULL') ||
                                         ' which is not allowed for pool items';
                  accept              := 'N';
                end;
              end if;
            exception
              when no_data_found then
                overrulledstatusout := 3;
                m_message           := 'order number ' || ordernumber || ' not found';
                accept              := 'N';
            end;
            if statusout = 0 then
              begin
                --order 501534 Offline sorting
                offline        := 'Y';
                utldiroff      := utldir || '\offline\';
                fpsfilenameoff := 'Offline_' || to_char(sysdate, 'YYYYMMDD') || '_' || sessionsid ||
                                  sessionserialnr || '.txt';
                sqlfileoffyes  := utl_file.fopen(utldiroff, 'OFFLINE.YES', 'r');
                sqlfileoff     := utl_file.fopen(utldiroff, fpsfilenameoff, 'a');
              exception
                when others then
                  offline := 'N';
              end; --order 501534 Offline sorting
              if offline = 'Y' then
                --501534
                utl_file.put_line(sqlfileoff,
                                  gv_workstationcode || ',' || idcode || ',' || lvdatep || ',' ||
                                   lvtimep);
                utl_file.fclose_all; --(SqlFile);
              else
                if accept = 'Y' then
                  m_message := 'pack_sort.processoutscan';
                  pack_sort.processoutscan(transactiontp, idprimary, secondaryid, plantid_garment,
                                           plantid_param, businessunitid, uniqueitemid,
                                           workstationid, gv_workstationcode, lvdatep, lvtimep,
                                           countwashesat, scanbyroute, gv_systemuserid, debuglevel,
                                           accept, scaninterval, packingnoteid, statusout, flagcode1,
                                           flagcode2, flagcode3, flagcode4, m_deliveryscan, fpbatchnumber);
                   end if;
                  --- HVH 5-3-2007
                  if overrulledstatusout <> 0 then
                    statusout := overrulledstatusout;
                  end if;
                 end if; --offline
            end if; --if statusout=0
          else
            accept := 'N';
          end if;
          if (accept = 'Y' and scaninterval = 'Y') --and Statusout = 0 --or (Offline = 'Y' and validdate = 'Y')
           then
            begin
              commit;
              if debuglevel > 0 then
                pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                        lvtimep || ' ' || locationcode || ' ' || nextlocationcode || ' ' ||
                                        'OutScan OK', debuglevel, 'SENDTRACKINFO', plantid_param, 1,
                                        1);
              end if;
            end;
          else
            begin
              rollback;
              if accept = 'N' --and Statusout = 0
               then
                statusout := 1;
              end if;
              pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                      lvtimep || ' ' || locationcode || ' ' || nextlocationcode ||
                                      ' OutScan NOT accepted, scaninterval ' || scaninterval || ' ' ||
                                      m_message, debuglevel, 'SENDTRACKINFO', plantid_param, 3, 1);
            end;
          end if;
        end;
      when 3 then
        begin
          --Repair Scan
          --added for order501044 Kannegiesser
          m_message := 'sendtrackinfo';
          if flagcode1 = '-Kann-' then
            pack_sort.processrepairscan(transactiontp, idprimary, pool, secondaryid, businessunitid,
                                        uniqueitemid, gv_workstationcode, lvdatep, lvtimep, '',
                                        gv_systemuserid, debuglevel, accept, flagcode1, flagcode2,
                                        flagcode3, flagcode4);
          else
            pack_sort.processrepairscan(transactiontp, idprimary, pool, secondaryid, businessunitid,
                                        uniqueitemid, gv_workstationcode, lvdatep, lvtimep,
                                        repairsdone, gv_systemuserid, debuglevel, accept, flagcode1,
                                        flagcode2, flagcode3, flagcode4);
          end if;
          if accept = 'Y' then
            begin
              commit;
              if debuglevel > 0 then
                pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                        lvtimep || ' ' || locationcode || ' ' || nextlocationcode || ' ' ||
                                        'RepairScan OK', debuglevel, 'SENDTRACKINFO', plantid_param,
                                        1, 1);
              end if;
            end;
          else
            begin
              rollback;
              statusout := 1;
              pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                      lvtimep || ' ' || locationcode || ' ' || nextlocationcode || ' ' ||
                                      'RepairScan Not accepted ' || m_message, debuglevel,
                                      'SENDTRACKINFO', plantid_param, 3, 1);
            end;
          end if;
        end;
      when 4 then
        begin
          --Rewash scan
          m_message := 'pack_sort.processrewash';
          pack_sort.processrewash(transactiontp, idprimary, pool, secondaryid, plantid_garment,
                                  plantid_param, businessunitid, uniqueitemid, gv_workstationcode,
                                  lvdatep, lvtimep, scanbyroute, gv_systemuserid, debuglevel, accept,
                                  flagcode1, flagcode2, flagcode3, flagcode4);
          if accept = 'Y' then
            begin
              commit;
              if debuglevel > 0 then
                pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                        lvtimep || ' ' || locationcode || ' ' || nextlocationcode || ' ' ||
                                        'RewashScan OK', debuglevel, 'SENDTRACKINFO', plantid_param,
                                        1, 1);
              end if;
            end;
          else
            begin
              rollback;
              statusout := 1;
              pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                      lvtimep || ' ' || locationcode || ' ' || nextlocationcode ||
                                      ' RewashScan NOT accepted ' || m_message, debuglevel,
                                      'SENDTRACKINFO', plantid_param, 3, 1);
            end;
          end if;
        end;
      when 6 then
        begin
          --Checkpoint scan
          m_message := 'pack_sort.processcheckpointscan';
          pack_sort.processcheckpointscan(transactiontp, idprimary, pool, secondaryid,
                                          businessunitid, uniqueitemid, gv_workstationcode, lvdatep,
                                          lvtimep, gv_systemuserid, debuglevel, accept, scanbyroute,
                                          plantid_garment, flagcode1, flagcode2, flagcode3,
                                          flagcode4, fpbatchnumber);
          if accept = 'Y' then
            begin
              commit;
              if debuglevel > 0 then
                pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                        lvtimep || ' ' || locationcode || ' ' || nextlocationcode || ' ' ||
                                        'CheckPointScan OK', debuglevel, 'SENDTRACKINFO',
                                        plantid_param, 1, 1);
              end if;
            end;
          else
            begin
              rollback;
              statusout := 1;
              pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                      lvtimep || ' ' || locationcode || ' ' || nextlocationcode || ' ' ||
                                      'CheckPointScan NOT accepted ' || m_message, debuglevel,
                                      'SENDTRACKINFO', plantid_param, 3, 1);
            end;
          end if;
        end;
      when 7 ---60 --7 is for storage scan - changed from todo4873
       then
        begin
          --Sort scan
          m_message := 'pack_sort.processsortscan';
          pack_sort.processsortscan(60, idprimary, pool, secondaryid, businessunitid, uniqueitemid,
                                    gv_workstationcode, lvdatep, lvtimep, gv_systemuserid,
                                    debuglevel, accept, flagcode1, flagcode2, flagcode3, flagcode4,
                                    fpbatchnumber);
          if accept = 'Y' then
            begin
              commit;
              if debuglevel > 0 then
                pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                        lvtimep || ' ' || locationcode || ' ' || nextlocationcode || ' ' ||
                                        'SortScan OK', debuglevel, 'SENDTRACKINFO', plantid_param, 1,
                                        1);
              end if;
            end;
          else
            begin
              rollback;
              statusout := 1;
              pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                      lvtimep || ' ' || locationcode || ' ' || nextlocationcode || ' ' ||
                                      'SortScan NOT accepted ' || m_message, debuglevel,
                                      'SENDTRACKINFO', plantid_param, 3, 1);
            end;
          end if;
        end;
       when 76 then
         begin
          --Sort scan
          m_message := 'pack_sort.processonsiteinvetoryscan';
          pack_sort.processonsiteinvetoryscan(transactiontp, idprimary, businessunitid, plantid_param, uniqueitemid,gv_workstationcode,
                                    gv_lastscandatetime , gv_systemuserid,
                                    debuglevel, accept);
          if accept = 'Y' then
            begin
              commit;
              if debuglevel > 0 then
                pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                        lvtimep || ' ' || locationcode || ' ' || nextlocationcode || ' ' ||
                                        'OnSiteInventotryScan OK', debuglevel, 'SENDTRACKINFO', plantid_param, 1,
                                        1);
              end if;
            end;
          else
            begin
              rollback;
              statusout := 1;
              pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                      lvtimep || ' ' || locationcode || ' ' || nextlocationcode || ' ' ||
                                      'OnSiteInventotryScan NOT accepted ' || m_message, debuglevel,
                                      'SENDTRACKINFO', plantid_param, 3, 1);
            end;
          end if;
        end;
      else
        begin
          rollback;
          accept    := 'N';
          statusout := 1;
          pack_sort.write_logging('Error Unknown transactiontp ' || transactiontp || ' for ' ||
                                  unitcode || ' ' || idcode || ' ' || lvdatep || ' ' || lvtimep || ' ' ||
                                  locationcode || ' ' || nextlocationcode, debuglevel,
                                  'SENDTRACKINFO', plantid_param, 3, 1);
        end;
    end case;
    --support_uhf_buffer
    support_uhf_buffer;
    --update flags
    begin
      m_message := 'sendtrackinfo update flags';
      if accept = 'Y' then
        --added for order501044 Kannegiesser
        if flagcode1 = '-Kann-' then
          statusout := pack_sort.updateflags(repairsdone,
                                             --filled for Kannegiesser with flags,
                                             uniqueitemid, gv_lastscandatetime, gv_systemuserid,
                                             debuglevel);

        else
          if lv_databasecode = 'VEN' and flagcode1 = 'K' then
            begin
              --special VEN add flag ONH
              insert into uniqueitemflag
                (uniqueitem_id, flag_id, startdate, systemuser_id, timestamp)
                select uniqueitemid, fg.flag_id, trunc(gv_lastscandatetime), gv_systemuserid,
                       sysdate
                from   flag fg, uniqueitem u
                join   finishingmethod f
                on     f.finishingmethod_id = u.finishingmethod_id
                where  fg.code = 'ONH'
                and    fg.flagtype = 1
                and    f.code in ('04', '05')
                and    u.uniqueitem_id = uniqueitemid;
            end;
          else
            for vcursor in (select f.flag_id
                            from   flag f, sortaddressperflag s
                            where  f.flag_id = s.flag_id
                            and    s.plant_id = plantid_param
                            and    s.sortaddress in (flagcode1, flagcode2, flagcode3, flagcode4)
                            and    not exists (select u.flag_id
                                    from   uniqueitemflag u
                                    where  u.uniqueitem_id = uniqueitemid
                                    and    u.flag_id = f.flag_id)) loop
              begin
                insert into uniqueitemflag
                  (uniqueitem_id, flag_id, startdate, freetextitem, systemuser_id, timestamp)
                values
                  (uniqueitemid, vcursor.flag_id, trunc(gv_lastscandatetime), null, gv_systemuserid,
                   sysdate);
                if debuglevel > 0 then
                  pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                          lvtimep || ' ' || locationcode || ' ' ||
                                          nextlocationcode || ' insert uniqueitemflag' ||
                                          uniqueitemid || ' ' || vcursor.flag_id, debuglevel,
                                          'SENDTRACKINFO', plantid_param, 1, 1);
                end if;
              exception
                when others then
                  begin
                    accept    := 'N';
                    statusout := 1;
                    pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' ||
                                            lvtimep || ' ' || locationcode || ' ' ||
                                            nextlocationcode ||
                                            'NOT insert uniqueitemflag - scanflag for uniqueitemID/flagID' ||
                                            uniqueitemid || '/' || vcursor.flag_id || ' ' ||
                                            sqlerrm, debuglevel, 'SENDTRACKINFO', plantid_param, 3,
                                            1);
                  end;
              end;
            end loop;
          end if;
        end if;
        if accept = 'Y' and statusout = 0 then
          commit;
        else
          rollback;
        end if;
      end if; --update flags
    end; --update flags
  end if; ---step 3
  --added for sortbatch
  sortbatchnumber := batchnumber;
  if flagcode4 = 'SBN' then
    begin
      m_message := 'sendtrackinfo flagcode4 = SBN';
      select sortbatch.status
      into   sortbatchstatus
      from   sortbatch
      where  sortbatch.sortbatch_id = sortbatchnumber;
      if statusout = 0 and sortbatchstatus = 2 then
        update sortbatch s
        set    s.status = 3, s.closingtime = gv_lastscandatetime
        where  s.sortbatch_id = sortbatchnumber;
        commit;
      elsif statusout = 0 and sortbatchstatus = 3 and transactiontp = 2 then
        update sortbatch s
        set    s.status = 4, s.outscantime = gv_lastscandatetime
        where  s.sortbatch_id = sortbatchnumber;
        commit;
      end if;
    exception
      when others then
        rollback;
        pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' || lvtimep || ' ' ||
                                locationcode || ' ' || nextlocationcode || ' Sortbatch_id ' ||
                                sortbatchnumber || ' not updated for IDCode' || idcode || ' ' ||
                                sqlerrm, debuglevel, 'SENDTRACKINFO', plantid_param, 3, 1);
    end;
  end if;
  --order 502305
exception
  when exceptionnonunique then
    begin
      statusout := 0;
      ---ONLY for outscan NON unique
      if transactiontp = 2 then
        begin
          --N2 get customer/distributionpoint
          m_message := sysdate || ' customer ' || nvl(to_char(lvncustomernumber), 'NULL') ||
                       ' not found for notuniqueitem product ' ||
                       nvl(to_char(lvsproductlegacycode), 'NULL');
          select c.customer_id
          into   lvncustomerid
          from   customer c
          where  c.customernumber = lvncustomernumber;
          select min(t.distributionpoint_id)
          into   lvndistributionid
          from   distributionpoint t, department d
          where  t.department_id = d.department_id
          and    d.customer_id = lvncustomerid;
          --N3 get product/size/finishingmethod
          m_message := sysdate || ' product ' || nvl(to_char(lvsproductlegacycode), 'NULL') ||
                       ' not found for notuniqueitem customer ' ||
                       nvl(to_char(lvncustomernumber), 'NULL');
          select p.product_id
          into   lvnproductid
          from   product p
          where  p.legacyproductcode = lvsproductlegacycode;
          --N3 get product/size/finishingmethod
          m_message := sysdate || ' error retrieving PLPC notuniqueitem customer ' ||
                       nvl(to_char(lvncustomernumber), 'NULL') || ' legacy product ' ||
                       nvl(to_char(lvsproductlegacycode), 'NULL');
          select min(l.sizedefinition_id), min(l.finishingmethod_id)
          into   lvnsizeid, lvnfinmetid
          from   productlistpercustomer l
          where  l.customer_id = lvncustomerid
          and    l.product_id = lvnproductid
          and    sysdate between l.dateactive and l.dateinactive;
          --size star check
          select s.code
          into   lvssizecode
          from   sizedefinition s
          where  s.sizedefinition_id = lvnsizeid;
          if (lvssizecode = '*') then
            begin
              select min(ps.sizedefinition_id)
              into   lvnsizeid
              from   productsize ps
              where  ps.product_id = lvnproductid
              and    ps.sizedefinition_id <> lvnsizeid;
            end;
          end if;
          --N4 get next deliverydate
          m_message      := sysdate || ' error getnextdeliverydate for notuniqueitem customer ' ||
                            lvncustomernumber || ' legacy product ' || lvsproductlegacycode;
          lvdnextdeldate := pack_sort.getnextdeliverydate(sysdate, lvncustomerid, 2);
          begin
            --N5 insert/update cleancountdel record
            m_message := sysdate ||
                         ' error insert/update into cleancountdelivery for notuniqueitem customer ' ||
                         lvncustomernumber || ' legacy product ' || lvsproductlegacycode;
            insert into cleancountdelivery
              (cleancountdelivery_id, distributionpoint_id, product_id, sizedefinition_id,
               finishingmethod_id, packingnote_id, quantity, deliverydate, systemuser_id, timestamp)
            values
              (seq_cleancountdelivery.nextval, lvndistributionid, lvnproductid, lvnsizeid,
               lvnfinmetid, null, 1, lvdnextdeldate, gv_systemuserid, sysdate);
          exception
            when dup_val_on_index then
              begin
                update cleancountdelivery cd
                set    cd.quantity = cd.quantity + 1
                where  cd.distributionpoint_id = lvndistributionid
                and    cd.product_id = lvnproductid
                and    cd.sizedefinition_id = lvnsizeid
                and    cd.finishingmethod_id = lvnfinmetid
                and    cd.deliverydate = lvdnextdeldate
                and    cd.packingnote_id is null;
              end;
          end; --N5
        end;
      end if; --transactiontp = 2 outscan
      commit;
    exception
      when others then
        begin
          rollback;
          statusout := 1;
          pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' || lvtimep || ' ' ||
                                  locationcode || ' ' || nextlocationcode ||
                                  ' Exception Others; not updated for IDCode ' || idcode || ' ' ||
                                  m_message || ' ' || sqlerrm, debuglevel, 'SENDTRACKINFO',
                                  plantid_param, 3, 1);
        end;
    end;
    --end order 502305
  when others then
    begin
      rollback;
      statusout := 1;
      pack_sort.write_logging(unitcode || ' ' || idcode || ' ' || lvdatep || ' ' || lvtimep || ' ' ||
                              locationcode || ' ' || nextlocationcode ||
                              ' Exception Others; not updated for IDCode ' || idcode || ' ' ||
                              m_message || ' ' || sqlerrm, debuglevel, 'SENDTRACKINFO',
                              plantid_param, 3, 1);
      if replace(sqlerrm, 'ORA-04068') <> sqlerrm then
        raise; -->recompile ora ORA-04068 related - only raise related ORA-04068
      end if;
    end;
end sendtrackinfo;
/
create or replace procedure sendtrackinfocontainer(fp_idcode           in container.primaryid%type,
                                                   fp_unitcode         in businessunit.code%type,
                                                   fp_date             in number, --YYYYMMDD 20120829
                                                   fp_time             in number, --HH24MISS 084912
                                                   fp_scantype         in varchar2,
                                                   fp_customernumber   in customer.customernumber%type,
                                                   fp_departmentnumber in department.departmentnumber%type,
                                                   fp_scanlocation     in varchar2,
                                                   fp_systemusername   in varchar2,
                                                   fp_status           out varchar2,
                                                   fp_errormessage     out nocopy varchar2) is

  /*procedure sendtrackinfocontainer version 1.0 */
  gv_distributionpoint    distributionpoint.distributionpoint_id%type;
  gv_plantid              plant.plant_id%type;
  gv_businessunit         businessunit.businessunit_id%type;
  gv_containerid          container.container_id%type;
  gv_containerbu          container.ownerbusinessunit_id%type;
  gv_containercustid      container.ownercustomer_id%type;
  gv_containerprimaryid   containerscan.primaryid%type;
  gv_containersecondaryid secondarycontainer.secondaryid%type;
  gv_containerlastdistrib container.lastdistributionpoint_link_id%type;
  gv_containerdistrib     container.distributionpoint_id%type;
  gv_containertype        container.containertype_id%type;
  gv_containerstay        container.stay_id%type;
  gv_containerprevstay    container.prevstay_id%type;
  gv_containertare        container.tareweight%type;
  gv_scandate             date;
  gv_systemuserid         systemuser.systemuser_id%type;
  gv_message              varchar2(1000);
  gv_userexception        exception;
  gv_loglevel             number := 0;
  gv_logname              abslog.logsource%type := 'SENDTRACKINFOCONTAINER';

  procedure initialize is
    lv_containerdateinactive container.dateinactive%type;
    lv_customerid            customer.customer_id%type;
    lv_containerused         container.usedbyotherbu%type;

    procedure check_customer_info_outscan is
      lv_departmentid     department.department_id%type;
      lv_departmentnr     department.departmentnumber%type;
      lv_custdateactive   customer.dateactive%type;
      lv_custdateinactive customer.dateinactive%type;
      lv_customeractive   customer.active%type;
    begin
      --check_customer_info_outscan
      gv_message := 'check_customer_info_outscan';
      --outscan
      if fp_scantype = 'O' then
        begin
          --outscan.
          -- check Customer Number - obligated for Outscan
          if fp_customernumber is null then
            begin
              fp_errormessage := 'Parameter fp_customernumber cannot be left blank ';
              raise gv_userexception;
            end;
          else
            begin
              gv_message := 'Cusotmer ' || to_char(fp_customernumber);
              select c.customer_id, c.dateactive, c.dateinactive, c.active
              into   lv_customerid, lv_custdateactive, lv_custdateinactive, lv_customeractive
              from   customer c
              where  c.customernumber = fp_customernumber;
            end;
          end if;
          -- check customer active
          if (lv_custdateinactive < gv_scandate and lv_custdateactive > gv_scandate) or
             lv_customeractive = 'N' then
            begin
              fp_status       := 5;
              fp_errormessage := 'Customer ' || to_char(fp_customernumber) || ' is inactive. ';
              raise gv_userexception;
            end;
          end if;
          -- set department number
          gv_message      := 'set department number';
          lv_departmentnr := fp_departmentnumber;
          select d.department_id
          into   lv_departmentid
          from   department d
          join   customer c
          on     c.customer_id = d.customer_id
          where  c.customer_id = lv_customerid
          and    d.departmentnumber = fp_departmentnumber;
        exception
          when no_data_found then
            if lv_departmentid is null or fp_departmentnumber is null then
              begin
                select max(d.departmentnumber)
                into   lv_departmentnr
                from   department d
                join   customer c
                on     c.customer_id = d.customer_id
                where  c.customer_id = lv_customerid
                and    d.active = 'Y';
                --
                select d.department_id
                into   lv_departmentid
                from   department d
                join   customer c
                on     c.customer_id = d.customer_id
                where  d.departmentnumber = lv_departmentnr;
              end;
            end if;
        end;
        --sget distributionpoint
        gv_message := 'get distributionpoint';
        begin
          select dp.distributionpoint_id
          into   gv_distributionpoint
          from   distributionpoint dp
          where  dp.distributionpointnumber =
                 (select max(dp2.distributionpointnumber)
                  from   distributionpoint dp2
                  where  dp.department_id = lv_departmentid);
        exception
          when no_data_found then
            fp_status       := 5;
            fp_errormessage := 'No active consumption point. ';
            raise gv_userexception;
        end;
      end if;
    end check_customer_info_outscan;
  begin
    -- initialize
    fp_errormessage := 'Ok';
    fp_status       := 0;
    -- check Unit Code
    if fp_unitcode is null then
      begin
        fp_errormessage := 'Parameter fp_unitcode cannot be left blank ';
        raise gv_userexception;
      end;
    else
      -- get business unit id
      begin
        gv_message := 'Business unit ' || fp_unitcode;
        select bu.businessunit_id, bu.plant_id
        into   gv_businessunit, gv_plantid
        from   businessunit bu
        where  bu.code = fp_unitcode;
      end;
    end if;
    -- check container ID Code parameter
    if fp_idcode is null then
      begin
        fp_errormessage := 'Parameter fp_idcode cannot be left blank ';
        raise gv_userexception;
      end;
    else
      begin
        --get container for id code
        gv_message := 'fp_idcode ' || fp_idcode;
        select ct.primaryid, ct.container_id, ct.dateinactive, ct.ownerbusinessunit_id,
               ct.usedbyotherbu, ct.ownercustomer_id, ct.containertype_id, ct.stay_id,
               ct.prevstay_id, ct.tareweight, sct.secondaryid
        into   gv_containerprimaryid, gv_containerid, lv_containerdateinactive, gv_containerbu,
               lv_containerused, gv_containercustid, gv_containertype, gv_containerstay,
               gv_containerprevstay, gv_containertare, gv_containersecondaryid
        from   container ct
        left   outer join secondarycontainer sct
        on     sct.container_id = ct.container_id
        where  ct.primaryid = fp_idcode;
      exception
        when no_data_found then
          begin
            select sct.container_id, sct.secondaryid, ct.dateinactive, ct.ownerbusinessunit_id,
                   ct.usedbyotherbu, ct.ownercustomer_id
            into   gv_containerid, gv_containersecondaryid, lv_containerdateinactive, gv_containerbu,
                   lv_containerused, gv_containercustid
            from   secondarycontainer sct
            join   container ct
            on     ct.container_id = sct.container_id
            where  sct.secondaryid = fp_idcode;
          end;
      end;
    end if;
    -- check Date
    if fp_date is null then
      begin
        fp_errormessage := 'Parameter fp_date cannot be left blank';
        raise gv_userexception;
      end;
    end if;
    -- check Time
    if fp_time is null then
      begin
        fp_errormessage := 'Parameter fp_time cannot be left blank';
        raise gv_userexception;
      end;
    end if;
    -- set scandate
    gv_scandate := to_timestamp(fp_date || fp_time, 'YYYYMMDDHH24MISS');
    -- check ScanType
    if fp_scantype is null then
      begin
        fp_errormessage := 'Parameter fp_scantype cannot be left blank ';
        raise gv_userexception;
      end;
    else
      begin
        if fp_scantype not in ('I', 'O') then
          begin
            fp_errormessage := 'Invalid scan type ' || fp_scantype;
            raise gv_userexception;
          end;
        end if;
      end;
    end if;
    --check_customer_info_outscan
    check_customer_info_outscan;
    -- check container active
    if lv_containerdateinactive < gv_scandate then
      begin
        fp_errormessage := 'Container is not active. ';
        raise gv_userexception;
      end;
    end if;
    -- check container owner BU
    if gv_containerbu <> gv_businessunit and lv_containerused = 'N' then
      begin
        fp_errormessage := 'Container belongs to other business unit. ';
        raise gv_userexception;
      end;
    end if;
    -- check container owner customer
    if gv_containercustid is not null and gv_containercustid <> lv_customerid and fp_scantype = 'O' then
      begin
        fp_errormessage := 'Container belongs to another customer. ';
        raise gv_userexception;
      end;
    end if;
    -- get systemuser id
    begin
      select s.systemuser_id
      into   gv_systemuserid
      from   systemuser s
      where  s.username = coalesce(upper(trim(fp_systemusername)), 'CONTAINERSCAN');
    exception
      when no_data_found then
        begin
          select min(systemuser_id) into gv_systemuserid from systemuser;
        end;
    end;
  end initialize;

  procedure update_container is
    lv_stayid stay.stay_id%type;
  begin
    --update_container
    gv_message := 'update container';
    case fp_scantype
      when 'I' then
        begin
          -- get stay for inscan
          select s.stay_id
          into   lv_stayid
          from   stay s
          where  s.staytype = 2
          and    s.staynr = 10;
          --
          update container c
          set    c.lastbusinessunit_id = gv_containerbu, c.businessunit_id = gv_businessunit,
                 c.lastdistributionpoint_link_id = case
                                                     when c.distributionpoint_id is not null then
                                                      c.distributionpoint_id
                                                     else
                                                      c.lastdistributionpoint_link_id
                                                   end,
                 c.numberofdaysatcustprev = case
                                              when c.distributionpoint_id is not null then
                                               c.numberofdaysatcustprev +
                                               (select to_date(sysdate, 'YYYY-MM-DD') -
                                                        to_date(c.lastoutscandate, 'YYYY-MM-DD')
                                                from   dual)
                                              else
                                               c.numberofdaysatcustprev
                                            end, c.distributionpoint_id = null,
                 c.prevstay_id = c.stay_id, c.stay_id = lv_stayid, c.staychangedate = gv_scandate,
                 c.lastinscandate = gv_scandate, c.systemuser_id = gv_systemuserid,
                 c.timestamp = sysdate
          where  c.container_id = gv_containerid;
        end;
      when 'O' then
        begin
          -- get stay for outscan
          select s.stay_id
          into   lv_stayid
          from   stay s
          where  s.staytype = 2
          and    s.staynr = 20;
          --
          update container c
          set    c.prevstay_id = c.stay_id, c.stay_id = lv_stayid, c.staychangedate = gv_scandate,
                 c.lastoutscandate = gv_scandate, c.lastnotenumber = 0,
                 c.lastbusinessunit_id = c.businessunit_id,
                 c.lastdistributionpoint_link_id = c.distributionpoint_id,
                 c.distributionpoint_id = gv_distributionpoint,
                 c.numberofshipments = c.numberofshipments + 1, c.systemuser_id = gv_systemuserid,
                 c.timestamp = sysdate
          where  c.container_id = gv_containerid;
        end;
      else
        begin
          fp_errormessage := 'Invalid scan type ' || fp_scantype;
          raise gv_userexception;
        end;
    end case; --fp_scantype
  end update_container;

  procedure create_container_scan is
    lv_containerscanid containerscan.containerscan_id%type;
  begin
    --knoei
    select c.lastdistributionpoint_link_id, c.distributionpoint_id
    into   gv_containerlastdistrib, gv_containerdistrib
    from   container c
    where  c.container_id = gv_containerid;
    --create_container_scan
    gv_message := 'create_container_scan';
    select seq_containerscan.nextval into lv_containerscanid from dual;
    insert into containerscan
      (containerscan_id, scantimestamp, businessunit_id, primaryid, secondaryid,
       distributionpoint_link_id, containertype_id, stay_id, prevstay_id, transactiontype_id,
       scanstation, customerowned, year, week, dayno, container_id, tareweight, systemuser_id,
       timestamp, markdelete, routecontrol_id)
    values
      (lv_containerscanid, gv_scandate, gv_businessunit,
       coalesce(gv_containerprimaryid, gv_containersecondaryid), gv_containersecondaryid,
       case when fp_scantype = 'I' then gv_containerlastdistrib else gv_containerdistrib end,
       gv_containertype, gv_containerstay, gv_containerprevstay,
       case when fp_scantype = 'I' then 511 else 542 end,
       case when fp_scanlocation is not null then fp_scanlocation else 'STIC' end,
       case when gv_containercustid is not null then 'Y' else 'N' end, year(gv_scandate),
       getisoweek(gv_scandate), to_char(to_date(gv_scandate, 'YYYY-MM-DD'), 'D'), gv_containerid,
       gv_containertare, gv_systemuserid, sysdate, null, null);
  end create_container_scan;

begin
  --initialize
  initialize;
  --update_container
  update_container;
  --create_container_scan
  create_container_scan;
  --commit
  commit;
exception
  --error handling
  when gv_userexception then
    begin
      rollback;
      fp_status := 5;
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, gv_logname, gv_plantid, 3, 0);
    end;
  when no_data_found then
    begin
      rollback;
      fp_status       := 1; --no_data_found
      fp_errormessage := 'Status 1; No data found ' || gv_message;
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, gv_logname, gv_plantid, 3, 0);
    end;
  when too_many_rows then
    begin
      rollback;
      fp_status       := 2; --too many rows
      fp_errormessage := 'Status 2; Too many rows ' || sqlerrm || ' ' || gv_message;
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, gv_logname, gv_plantid, 3, 0);
    end;
  when dup_val_on_index then
    begin
      rollback;
      fp_status       := 3; --dup_val_on_index
      fp_errormessage := 'Status 3; Dup.val.on index (did already exist), ' || sqlerrm || ' ' ||
                         gv_message;
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, gv_logname, gv_plantid, 3, 0);
    end;
  when others then
    begin
      rollback;
      if (fp_status is null) then
        begin
          fp_status := 4; --others
        end;
      end if;
      fp_errormessage := 'Status 4; Error others, ' || sqlerrm || ' ' || gv_message;
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, gv_logname, gv_plantid, 3, 0);
    end;
end sendtrackinfocontainer;
/
create or replace procedure sendtrackinfoinwatec(idcode           in uniqueitem.primaryid%type,
                                                 plantcode        in out plant.code%type,
                                                 datep            in number,
                                                 timep            in varchar2, --number,
                                                 locationcode     in varchar2,
                                                 nextlocationcode in varchar2 default null,
                                                 flagcode1        in sortaddressperflag.sortaddress%type,
                                                 flagcode2        in sortaddressperflag.sortaddress%type,
                                                 flagcode3        in sortaddressperflag.sortaddress%type,
                                                 flagcode4        in sortaddressperflag.sortaddress%type,
                                                 currentweight    in number, /*for now ignored*/
                                                 xrayfilename     in blob, /*for now ignored*/
                                                 xrayremark       in clob, /*for now ignored*/
                                                 uhfbundleid      in number,
                                                 batchtype        in number,
                                                 statusout        out number) is
  lv_batchnumber  scan.batchnumber%type;
  lv_bundlesize   uhfbundle.bundlesize%type;
  lv_bunproductid product.product_id%type;
  lv_bunsizeid    sizedefinition.sizedefinition_id%type;
  lv_uniqueitemid uniqueitem.uniqueitem_id%type;
  lv_productid    product.product_id%type;
  lv_sizeid       sizedefinition.sizedefinition_id%type;
begin
  /*sendtrackinfoinwatec  version 1.1*/
  --15-12-2020 ABS-108106 Add option to create UHFBundles to the Inwatec Interface
  if uhfbundleid is not null and batchtype in (1, 2) then
    begin
      lv_batchnumber := to_char(uhfbundleid);
      if batchtype = 2 then
        begin
          begin
            select uf.bundlesize, uf.product_link_id, uf.sizedefinition_link_id
            into   lv_bundlesize, lv_bunproductid, lv_bunsizeid
            from   uhfbundle uf
            where  uf.uhfbundle_id = uhfbundleid;
          exception
            when no_data_found then
              begin
                lv_batchnumber := 'BROKEN';
              end;
          end;
          if lv_batchnumber = 'BROKEN' then
            begin
              lv_batchnumber := lv_batchnumber || '_' || to_char(uhfbundleid);
            end;
          else
            begin
              select u.uniqueitem_id, u.product_id, u.sizedefinition_id
              into   lv_uniqueitemid, lv_productid, lv_sizeid
              from   uniqueitem u
              where  u.primaryid = idcode;
              if lv_bundlesize = 0 then
                begin
                  update uhfbundle uf
                  set    uf.product_link_id = lv_productid, uf.sizedefinition_link_id = lv_sizeid,
                         uf.bundlesize = uf.bundlesize + 1, uf.timestamp = sysdate
                  where  uf.uhfbundle_id = uhfbundleid;
                end;
              elsif lv_productid = lv_bunproductid and lv_sizeid = lv_bunsizeid then
                begin
                  update uhfbundle uf
                  set    uf.bundlesize = uf.bundlesize + 1, uf.timestamp = sysdate
                  where  uf.uhfbundle_id = uhfbundleid;
                end;
              else
                begin
                  update uhfbundle uf
                  set    uf.product_link_id = null, uf.sizedefinition_link_id = null,
                         uf.bundlesize = uf.bundlesize + 1, uf.timestamp = sysdate
                  where  uf.uhfbundle_id = uhfbundleid;
                end;
              end if;
              update uniqueitem u
              set    u.uhfbundle_id = uhfbundleid
              where  u.uniqueitem_id = lv_uniqueitemid;
              commit;
            end;
          end if;
        end;
      end if;
      sendtrackinfo(idcode, plantcode, datep, timep, locationcode, nextlocationcode, flagcode1,
                    flagcode2, flagcode3, flagcode4, 0, 0, 0, null, statusout, null, 'N', 'N',
                    lv_batchnumber);
    end;
  else
    begin
      --same as before
      sendtrackinfo(idcode, plantcode, datep, timep, locationcode, nextlocationcode, flagcode1,
                    flagcode2, flagcode3, flagcode4, 0, 0, 0, null, statusout);
    end;
  end if;
exception
  when others then
    begin
      rollback;
      statusout := 9; --others, invalid date/time
      pack_sort.write_logging('Error ID Code ' || nvl(idcode, 'NULL') || ' plant code ' ||
                              nvl(plantcode, 'NULL') || ' location ' ||
                              nvl(to_char(locationcode), 'NULL') || ' sqlerm ' || sqlerrm ||
                              ' currentweight (not used) ' || to_char(currentweight), 1,
                              'SENDTRACKINFOINWATEC', null, 3, 0);
    end;
end sendtrackinfoinwatec;
/
create or replace procedure SendTrackInfoKannegiesser(IDCode       in UNIQUEITEM.PRIMARYID%type,
                                                      UnitCode     in out PLANT.CODE%type,
                                                      Datep        in number,
                                                      Timep        in varchar2,
                                                      LocationCode in varchar2,
                                                      Flags        in varchar2,
                                                      Statusout    out number) is

begin
  sendtrackinfo(IDCode,
                UnitCode,
                Datep,
                Timep,
                LocationCode,
                '',
                '-Kann-',
                '',
                '',
                '',
                0,
                0,
                0,
                Flags, --        in varchar2,
                Statusout);

end SendTrackInfoKannegiesser;
/
create or replace procedure sendtrackinfokannegiesser_wmu(idcode       in uniqueitem.primaryid%type,
                                                          unitcode     in out plant.code%type,
                                                          datep        in number,
                                                          timep        in varchar2,
                                                          locationcode in varchar2,
                                                          flags        in varchar2,
                                                          flagcode     in varchar2,
                                                          statusout    out number) is
  --------Internal procedures/functions
  procedure write_log(fp_message in abslog.message%type, fp_priority in abslog.priority%type) is
  begin
    abslogwrite.abslog_write(5, 'sendtrackinfokannegiesser_wmu', null, fp_priority, fp_message);
  end write_log;
begin
  --Version 0.3 SendTrackInfoKannegiesser_wmu
  -- ABS-64289 sent flags from Kannegieser to ABS
  sendtrackinfo(idcode, unitcode, datep, timep, locationcode, '', '-Kann-', '', '', '', 0, 0, 0,
                flags,
                --reapairs done!
                statusout);
  if statusout = 0 and flagcode is not null then
    begin
      insert into uniqueitemflag
        (uniqueitem_id, flag_id, startdate, systemuser_id, timestamp)
        select u.uniqueitem_id, f.flag_id, trunc(sysdate), 0, sysdate
        from   uniqueitem u, flag f
        where  f.code = flagcode
        and    f.flagtype = 1
        and    u.primaryid = idcode;
      commit;
    exception
      when others then
        begin
          write_log(sqlerrm || ' flagcode ' || flagcode, 3);
          rollback; --ok could not add flag..we do not want an error!
        end;
    end;
  end if;
end sendtrackinfokannegiesser_wmu;
/
create or replace procedure sendtrackinfometricon(idcode           in uniqueitem.primaryid%type,
                                                  unitcode         in out plant.code%type,
                                                  datep            in number,
                                                  timep            in varchar2, --number,
                                                  locationcode     in varchar2,
                                                  nextlocationcode in varchar2,
                                                  flagcode1        in sortaddressperflag.sortaddress%type,
                                                  flagcode2        in sortaddressperflag.sortaddress%type,
                                                  flagcode3        in sortaddressperflag.sortaddress%type,
                                                  flagcode4        in sortaddressperflag.sortaddress%type,
                                                  batchnumber      in number,
                                                  routenumber      in route.routenumber%type,
                                                  routeday         in day.daynumber%type,
                                                  repairsdone      in varchar2,
                                                  statusout        in out number,
                                                  --502595
                                                  fppickupdate   in number default null,
                                                  fpretransferyn in varchar2 default 'N')
                                                  is
  pragma autonomous_transaction;
  lv_databasecode        databasesettings.code%type;
  lv_customerranking     customerranking.ranking%type;
  lv_poolitem            uniqueitem.poolitem%type;
  lv_uniqueitemid        uniqueitem.uniqueitem_id%type;
  lv_customerid          customer.customer_id%type;
  lv_distributionpointid distributionpoint.distributionpoint_id%type;
  lv_do_sendtrack        boolean := true;
  lv_plandid             plant.plant_id%type;
begin
  select t.code into lv_databasecode from databasesettings t;
  if lv_databasecode = 'SMG' then
    begin
      --initialize variables
      statusout := 0;
      if idcode in ('020', '101') then
        lv_do_sendtrack := false;
      else
        begin
          begin
            --get uniqueitem
            select u.poolitem, u.uniqueitem_id, u.relatedcustomer_id,
                   nvl(u.distributionpoint_id, u.lastdistributionpoint_link_id)
            into   lv_poolitem, lv_uniqueitemid, lv_customerid, lv_distributionpointid
            from   uniqueitem u
            where  u.primaryid = idcode;
          exception
            when no_data_found then
              begin
                lv_customerid := null;
              end;
          end;
          --get customer id
          if lv_poolitem = 2 then
            select w.customer_id
            into   lv_customerid
            from   uniqueitemnonpool n, weareremployment e, wearer w
            where  n.uniqueitem_id = lv_uniqueitemid
            and    n.weareremployment_id = e.weareremployment_id
            and    e.wearer_id = w.wearer_id;
          else
            if lv_customerid is null and lv_distributionpointid is not null then
              select t.customer_id
              into   lv_customerid
              from   distributionpoint d, department t
              where  lv_distributionpointid = d.distributionpoint_id
              and    d.department_id = t.department_id;
            end if;
          end if;
          if lv_customerid is null then
            lv_customerranking := '-';
          else
            --get customer ranking
            select max(cr.ranking)
            into   lv_customerranking
            from   customer c, customerranking cr
            where  c.customer_id = lv_customerid
            and    c.customerranking_id = cr.customerranking_id;
          end if;
          --check send track itm
          if lv_customerranking = 'ITM' then
            begin
              --no send track info, it is a ITM customer
              lv_do_sendtrack := false;
              begin
                insert into externalgarmenttrackdata
                  (trackid, plantcode, timestamp, tracklocation)
                values
                  (idcode, unitcode, to_timestamp(to_char(datep) || timep, 'YYYYMMDDHH24MISS'),
                   substr(locationcode, 1, 3));
                commit;
              exception
                when dup_val_on_index then
                  statusout := 1;
              end;
            end;
          else
            begin
              --check to delete flags
              if locationcode in ('K1', 'K2', 'K3') then
                begin
                  lv_do_sendtrack := false;
                  --get unique item info
                  select bu.plant_id
                  into lv_plandid
                  from businessunit bu
                  where bu.code = unitcode;
                  --special case, no send track info now, just delete special flags
                  for x in (select ufg.flag_id
                            from   uniqueitemflag ufg, sortaddressperflag sf
                            where  ufg.uniqueitem_id = lv_uniqueitemid
                            and    ufg.flag_id = sf.flag_id
                            and    sf.plant_id = lv_plandid
                            and    sf.sortaddress = 'P'
                            group  by ufg.flag_id) loop
                    begin
                      delete from uniqueitemflag uif
                      where  uif.flag_id = x.flag_id
                      and    uif.uniqueitem_id = lv_uniqueitemid;
                      commit;
                    end;
                  end loop;
                end;
              end if;
            end;
          end if;
        exception
          when no_data_found then
            statusout := 1;
        end;
      end if;
    end;
  end if;
  if lv_do_sendtrack then
    begin
      statusout := null;
      sendtrackinfo(idcode, unitcode, datep, timep, locationcode, nextlocationcode, flagcode1,
                    flagcode2, flagcode3, flagcode4, batchnumber, routenumber, routeday, repairsdone,
                    statusout, fppickupdate, fpretransferyn, 'Y');
    end;
  end if; --lv_do_sendtrack
end sendtrackinfometricon;
/
create or replace procedure sendtrackinfors(fp_idcode              in uniqueresidentialitem.primaryid%type,
                                            fp_plantcode           in plant.code%type,
                                            fp_scandate            in number, --YYYYMMDD 20120829
                                            fp_scantime            in varchar2, --HH24MISS 084912
                                            fp_locationcode        in varchar2,
                                            fp_nextlocationcode    in varchar2,
                                            fp_status              out nocopy number,
                                            fp_errormessage        out nocopy varchar2,
                                            fp_productcode         in product.code%type default null,
                                            fp_finishingmethodcode in finishingmethod.code%type default null,
                                            fp_hangsorting         in number default 0) is
  pragma autonomous_transaction;
  ---sendtrackinfors version 4.1
  ---internal variables
  gv_userexception exception;
  gv_systemuserid             systemuser.systemuser_id%type;
  gv_plantid_paramater        plant.plant_id%type;
  gv_plantid_garment          plant.plant_id%type;
  gv_plantlanguageid          plant.language_id%type;
  gv_businessunitid           businessunit.businessunit_id%type;
  gv_unitcode                 businessunit.code%type;
  gv_uniqueresidentialitemid  uniqueresidentialitem.uniqueresidentialitem_id%type;
  gv_message                  abslog.message%type;
  gv_clientid                 client.client_id%type;
  gv_customerid               customer.customer_id%type;
  gv_customernumber           customer.customernumber%type;
  gv_customername             customer.name%type;
  gv_clientnumber             client.clientnumber%type;
  gv_clientsearchname         client.searchname%type;
  gv_roomnumber               departmentroom.roomnumber%type;
  gv_departmentroomid         departmentroom.departmentroom_id%type;
  gv_departmentroomseq        departmentroom.sequencenumber%type;
  gv_departmentnumber         department.departmentnumber%type;
  gv_clientadminnumber        client.adminnumber%type;
  gv_gender                   client.gender%type;
  gv_deliverypointcode        deliverypoint.code%type;
  gv_productcode              product.code%type;
  gv_productdescription       product_desc.description%type;
  gv_sizecode                 sizedefinition.code%type;
  gv_productsortgroup         productsortgroup.code%type;
  gv_serviceteamid            customer.serviceteam_id%type;
  gv_productid                product.product_id%type;
  gv_productgroupid           product.productgroup_id%type;
  gv_colorid                  color.color_id%type;
  gv_sizeid                   sizedefinition.sizedefinition_id%type;
  gv_finishingmethodid        finishingmethod.finishingmethod_id%type;
  gv_deliverypointid          deliverypoint.deliverypoint_id%type;
  gv_productsortgroupid       product.productsortgroup_id%type;
  gv_infotext                 client.remark%type;
  gv_scandate                 date;
  gv_timezonehrsdiff          plant.timezonehrsdiff%type;
  gv_transactiontype          sortingimportdefinition.transactiontype%type;
  gv_workstationid            workstation.workstation_id%type;
  gv_workstationcode          workstation.code%type;
  gv_routenumber              route.routenumber%type;
  gv_routeid                  route.route_id%type;
  gv_routeday                 route.drivingday_id%type;
  gv_depot                    depot.code%type;
  gv_stopnumber               clientdeliverynote.stopnumber%type;
  gv_clientdeliverynote       clientdeliverynote.clientdeliverynotenumber%type;
  gv_clientdeliverynoteid     clientdeliverynote.clientdeliverynote_id%type;
  gv_clientdeliverynotelineid clientdeliverynoteline.clientdeliverynoteline_id%type;
  gv_clientdelnotlinescanid   clientdelnotelinescan.clientdelnotelinescan_id%type;
  gv_batchid                  batch.batch_id%type;
  gv_statusid                 status.status_id%type;
  gv_pwboutscanhours          number;
  gv_lastinscandate           uniqueresidentialitem.lastinscandate%type;
  gv_lastoutscandate          uniqueresidentialitem.lastoutscandate%type;
  gv_lastrewashdate           uniqueresidentialitem.lastrewashdate%type;
  gv_lastrepairdate           uniqueresidentialitem.lastrepairdate%type;
  gv_autoflagid               flag.flag_id%type;
  gv_loglevel                 number;
  gv_departmentid             department.department_id%type;
  gv_department_desc          department.description%type;
  gv_clientfirstlastname      varchar2(256);
  gv_productvolume            product.volumeunits%type;
  gv_create_assignproductscan boolean;
  gv_databasecode             databasesettings.code%type;
  gv_logmessage               varchar2(32);

  procedure remove_outscanflag is
  begin
    --remove_outscanflag
    gv_message := 'remove_outscanflag';
    delete from uniqueresidentialitemflag urf
    where  exists (select 1
            from   flag f
            join   flagoptions fop
            on     fop.flag_id = f.flag_id
            where  urf.flag_id = f.flag_id
            and    urf.uniqueresidentialitem_id = gv_uniqueresidentialitemid
            and    urf.startdate <= sysdate
            and    fop.remove = 'Y'
            and    exists (select 1
                    from   dialogs dg
                    where  dg.code = 'OutscanSort'
                    and    dg.dialog_id = fop.dialog_id));
  end remove_outscanflag;

  procedure check_autoflag(fp_transactiontype_id in sortingimportdefinition.transactiontype%type) is
    lv_flagcode flag.code%type;
  begin
    --check_autoflag
    gv_message := 'check_autoflag';
    case fp_transactiontype_id
      when 11 then
        --check_autoflag_rewash
        select max(af.flag_id)
        into   gv_autoflagid
        from   automaticflag af
        join   flag f
        on     (f.flag_id = af.flag_id and f.flagtype = 4)
        where  af.event = 'Rewash';
      else
        gv_autoflagid := null;
    end case;
    if gv_autoflagid is not null then
      begin
        insert into uniqueresidentialitemflag
          (uniqueresidentialitem_id, flag_id, startdate, freetextitem, systemuser_id, timestamp)
        values
          (gv_uniqueresidentialitemid, gv_autoflagid, sysdate, null, gv_systemuserid, sysdate);
        if gv_loglevel > 1 then
          begin
            select f.code into lv_flagcode from flag f where f.flag_id = gv_autoflagid;
            pack_sort_rs.write_logging('inserted residentialitemscanflag for ID code ' ||
                                       fp_idcode || ' flag ' || lv_flagcode, gv_loglevel,
                                       gv_logmessage, gv_plantid_paramater, 1, 1);
          end;
        end if;
      end;
    end if;
  end check_autoflag;

  procedure create_residentialitemscan(fp_transactiontype_id in sortingimportdefinition.transactiontype%type) is
    lv_stayid                stay.stay_id%type;
    lv_batchnumber           batch.batchnumber%type;
    lv_residentialitemscanid residentialitemscan.residentialitemscan_id%type;
  begin
    --create_residentialitemscan
    gv_message := 'create_residentialitemscan';
    case gv_transactiontype
      when 10 then
        begin
          --outscan
          select st.stay_id
          into   lv_stayid
          from   stay st
          where  st.staytype = 5
          and    st.staynr = 20;
          --update uniqueresidentialitem
          update uniqueresidentialitem ur
          set    ur.laststay_id = ur.stay_id, ur.laststaydate = gv_scandate,
                 ur.numberofwashes = ur.numberofwashes + 1, ur.lastoutscandate = gv_scandate,
                 ur.stay_id = lv_stayid, ur.timestamp = sysdate, ur.systemuser_id=gv_systemuserid
          where  ur.uniqueresidentialitem_id = gv_uniqueresidentialitemid;
        end;
      when 11 then
        begin
          --rewash
          select st.stay_id
          into   lv_stayid
          from   stay st
          where  st.staytype = 5
          and    st.staynr = 50;
          --update uniqueresidentialitem
          update uniqueresidentialitem ur
          set    ur.laststay_id = ur.stay_id, ur.laststaydate = gv_scandate,
                 ur.numberofrewashes = ur.numberofrewashes + 1, ur.lastrewashdate = gv_scandate,
                 ur.stay_id = lv_stayid, ur.timestamp = sysdate, ur.systemuser_id=gv_systemuserid
          where  ur.uniqueresidentialitem_id = gv_uniqueresidentialitemid;
        end;
      when 12 then
        begin
          --checkpoint / presort
          select st.stay_id
          into   lv_stayid
          from   stay st
          where  st.staytype = 5
          and    st.staynr = 30;
          --update uniqueresidentialitem
          update uniqueresidentialitem ur
          set    ur.laststay_id = ur.stay_id, ur.laststaydate = gv_scandate, ur.stay_id = lv_stayid, ur.timestamp = sysdate, ur.systemuser_id=gv_systemuserid
          where  ur.uniqueresidentialitem_id = gv_uniqueresidentialitemid;
        end;
      when 34 then
        begin
          --inscan for assign product..NOT an inscan!
          --we do not update the stay, it is already ok, real scan done before this scan!
          select st.stay_id
          into   lv_stayid
          from   stay st
          where  st.staytype = 5
          and    st.staynr = 10;
        end;
      else
        lv_stayid := null;
    end case;
    --get batch number
    select max(bt.batchnumber) into lv_batchnumber from batch bt where bt.batch_id = gv_batchid;
    --create_residentialitemscan
    insert into residentialitemscan
      (residentialitemscan_id, scantimestamp, businessunit_id, primaryid, customer_link_id,
       client_id, departmentroom_id, product_link_id, sizedefinition_link_id, finishingmethod_id,
       status_id, stay_id, scanstation, route_id, year, week, daynumber, employeenumber,
       uniqueresidentialitem_link_id, transactiontype_id, systemuser_id, timestamp, batchnumber,
       clientdeliverynotenumber, batch_id, clientdeliverynoteline_id)
    values
      (seq_residentialitemscan.nextval, gv_scandate, gv_businessunitid, fp_idcode, gv_customerid,
       gv_clientid, gv_departmentroomid, gv_productid, gv_sizeid, gv_finishingmethodid, gv_statusid,
       lv_stayid, gv_workstationcode, gv_routeid, getyearofweek(gv_scandate),
       getisoweek(gv_scandate), getabsdaynumber(gv_scandate), 0, gv_uniqueresidentialitemid,
       fp_transactiontype_id, gv_systemuserid, sysdate, lv_batchnumber, gv_clientdeliverynote,
       gv_batchid, gv_clientdeliverynotelineid)
    returning residentialitemscan_id into lv_residentialitemscanid;
    pack_sort_rs.write_logging('For ID code ' || nvl(fp_idcode, 'NULL') ||
                               ' inserted residentialitemscan ID ' ||
                               to_char(lv_residentialitemscanid) || ' for businessunit ' ||
                               gv_unitcode, gv_loglevel, gv_logmessage, gv_plantid_paramater, 1, 1);
  exception
    when dup_val_on_index then
      begin
        fp_status       := 5;
        fp_errormessage := 'Error, this ID code ' || nvl(fp_idcode, 'NULL') ||
                           ' was already scanned on the very same date/time, plant code ' ||
                           nvl(fp_plantcode, 'NULL') || ' location ' ||
                           nvl(to_char(fp_locationcode), 'NULL') || ' parameter next location ' ||
                           nvl(to_char(fp_nextlocationcode), 'NULL') || ' for unit code ' ||
                           nvl(gv_unitcode, 'NULL');
        raise gv_userexception;
      end;
  end create_residentialitemscan;

  procedure get_uniqueitem_rs_info is
  begin
    --get_uniqueitem_rs_info
    pack_sort_rs.get_uniqueitem_rs(fp_idcode, fp_plantcode, 1, gv_plantlanguageid,
                                   gv_uniqueresidentialitemid, gv_plantid_paramater,
                                   gv_plantid_garment, gv_unitcode, gv_businessunitid, fp_status,
                                   gv_message, gv_customernumber, gv_customerid, gv_customername,
                                   gv_serviceteamid, gv_clientnumber, gv_clientid,
                                   gv_clientsearchname, gv_roomnumber, gv_departmentroomid,
                                   gv_departmentroomseq, gv_departmentnumber, gv_clientadminnumber,
                                   gv_gender, gv_deliverypointcode, gv_deliverypointid,
                                   gv_productcode, gv_productid, gv_productgroupid,
                                   gv_productdescription, gv_colorid, gv_sizecode,
                                   gv_productsortgroup, gv_productsortgroupid, gv_sizeid,
                                   gv_finishingmethodid, gv_infotext, gv_timezonehrsdiff,
                                   gv_statusid, gv_lastinscandate, gv_lastoutscandate,
                                   gv_lastrewashdate, gv_lastrepairdate, gv_loglevel,
                                   gv_departmentid, gv_department_desc, gv_clientfirstlastname,
                                   gv_productvolume, gv_databasecode);
  end get_uniqueitem_rs_info;

  procedure intialize is
    --internal procedure create_uniqueresiditemproduct
    procedure create_uniqueresiditemproduct is
      lv_overalluniqueresidentialid databasesettings.overalluniquegarmentid%type;
    begin
      --get info overalluniquegarmentid
      select nvl(max(d.overalluniqueresidentialid), 'N')
      into   lv_overalluniqueresidentialid
      from   databasesettings d;
      --get product id
      gv_message := 'get residential product code ' || fp_productcode;
      select p.product_id
      into   gv_productid
      from   product p
      where  p.code = fp_productcode
      and    p.typeofmerchandise = 5;
      --get min size id for product is
      gv_message := 'get min(size) for product code ' || fp_productcode;
      select min(ps.sizedefinition_id)
      into   gv_sizeid
      from   productsize ps
      where  ps.product_id = gv_productid;
      --get finishingmethod id
      gv_message := 'get finishingmethod code ' || fp_finishingmethodcode;
      select f.finishingmethod_id
      into   gv_finishingmethodid
      from   finishingmethod f
      where  f.code = fp_finishingmethodcode;
      --lookup the barcode
      gv_message := 'ID code ';
      select ur.uniqueresidentialitem_id
      into   gv_uniqueresidentialitemid
      from   uniqueresidentialitem ur
      join   businessunit bu
      on     bu.businessunit_id = ur.businessunit_id
      where  ur.primaryid = fp_idcode
      and    ur.sequencenumber = 1
      and    (lv_overalluniqueresidentialid = 'Y' or bu.plant_id = gv_plantid_paramater);
      --create uniqueresidentialitemproduct
      gv_message := 'create uniqueresidentialitemproduct record for idcode ' || fp_idcode;
      insert into uniqueresidentialitemproduct
        (uniqueresidentialitem_id, product_id, sizedefinition_id, finishingmethod_id, assigndate,
         systemuser_id, timestamp)
      values
        (gv_uniqueresidentialitemid, gv_productid, gv_sizeid, gv_finishingmethodid, gv_scandate,
         gv_systemuserid, sysdate);
    end create_uniqueresiditemproduct;
  begin
    --intialize
    gv_create_assignproductscan := false;
    --Check special sendtrack call YES (fp_hangsorting=1)  or NO fp_hangsorting=0 defalt
    if nvl(fp_hangsorting, 0) = 0 then
      gv_logmessage := 'SENDTRACKINFORS';
    else
      gv_logmessage := 'SENDTRACKINFORSX';
    end if;
    --get systemuser
    begin
      select s.systemuser_id into gv_systemuserid from systemuser s where s.username = 'SORT';
    exception
      when no_data_found then
        select min(systemuser_id) into gv_systemuserid from systemuser;
    end;
    --get scan date / time
    gv_scandate := to_timestamp(fp_scandate || fp_scantime, 'YYYYMMDDHH24MISS');
    begin
      --get get_uniqueitem_rs info
      get_uniqueitem_rs_info;
    exception
      when no_data_found then
        begin
          if fp_productcode is not null and fp_finishingmethodcode is not null then
            begin
              --unknown barcode, check if it is missing uniqueresidentialitemproduct
              --and if so we will create it with the fp_productcode and fp_finishingmethodcode
              create_uniqueresiditemproduct;
              gv_create_assignproductscan := true;
              --get the info again
              --get get_uniqueitem_rs info
              get_uniqueitem_rs_info;
              --status of the uniqueitem is different
              select st.status_id
              into   gv_statusid
              from   status st
              where  st.statustype = 'UR'
              and    st.code = '10';
            end;
          else
            raise no_data_found;
          end if;
        end;
    end;
    --check time difference
    if gv_timezonehrsdiff <> 0 then
      begin
        gv_scandate := gv_scandate + (gv_timezonehrsdiff / 24);
      end;
    end if;
  end intialize;

  procedure get_sortingimportdefinition is
  begin
    --get_sortingimportdefinition
    gv_message := 'get sortingimportdefinition';
    select s.transactiontype, s.workstation_id, w.code
    into   gv_transactiontype, gv_workstationid, gv_workstationcode
    from   sortingimportdefinition s, workstation w
    where  s.plant_id = gv_plantid_paramater
    and    s.location = fp_locationcode
    and    ((s.nextlocation = fp_nextlocationcode) or
          (s.nextlocation is null and fp_nextlocationcode is null))
    and    s.workstation_id = w.workstation_id;
  end get_sortingimportdefinition;

  procedure process_transactiontype is
    lv_deliverydate date;
  begin
    --process transaction
    gv_autoflagid               := null;
    gv_clientdeliverynotelineid := null;
    if gv_transactiontype <> 10 then
      begin
        --get_clientdelnotescan
        gv_message := 'pack_sort_rs.get_clientdelnotescan';
        pack_sort_rs.get_clientdelnotescan(gv_uniqueresidentialitemid, gv_businessunitid, 1,
                                           gv_batchid, gv_clientdelnotlinescanid,
                                           gv_clientdeliverynote, gv_routeid, gv_stopnumber,
                                           gv_clientdeliverynoteid, lv_deliverydate,
                                           gv_clientdeliverynotelineid);
      end;
    end if;
    gv_message := 'process_transactiontype ' || to_char(gv_transactiontype);
    case gv_transactiontype
      when 9 then
        begin
          --soil receiving
          fp_status       := 5;
          fp_errormessage := 'Error status 5; Transaction type 9 Soil receiving not yet implemented, ID code ' ||
                             nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL') ||
                             ' location ' || nvl(to_char(fp_locationcode), 'NULL') ||
                             ' parameter next location ' ||
                             nvl(to_char(fp_nextlocationcode), 'NULL') || ' for unit code ' ||
                             nvl(gv_unitcode, 'NULL');
          raise gv_userexception;
        end;
      when 10 then
        begin
          --outscan / sort
          --check out scan hours
          gv_pwboutscanhours := nvl(to_number(pack_sort_rs.get_systemsettting(gv_plantid_paramater,
                                                                              'PWBOUTSCANHOURS')), 0);
          if gv_pwboutscanhours > 0 and gv_lastoutscandate is not null and
             gv_lastoutscandate > nvl(to_date('01-01-01', 'DD-MM-YYYY'), sysdate) then
            begin
              --check interval
              if gv_lastoutscandate - gv_scandate + gv_pwboutscanhours / 24 > 0 then
                begin
                  gv_message := 'ID code was scanned out less then ' || gv_pwboutscanhours ||
                                ' before';
                  raise gv_userexception;
                end;
              end if;
            end;
          end if;
          --outscan / sort
          pack_sort_rs.get_create_clientdelnote(gv_uniqueresidentialitemid, gv_businessunitid,
                                                gv_unitcode, gv_plantid_paramater, gv_customerid,
                                                gv_clientid, gv_productgroupid, gv_deliverypointid,
                                                gv_routenumber, gv_routeid, gv_routeday, gv_depot,
                                                gv_stopnumber, gv_clientdeliverynote,
                                                gv_clientdeliverynoteid, gv_clientdelnotlinescanid,
                                                gv_batchid, fp_status, gv_message, 1, gv_loglevel,
                                                gv_logmessage, gv_systemuserid, gv_departmentid,
                                                fp_idcode, gv_productid, gv_sizeid,
                                                gv_finishingmethodid, gv_scandate, gv_databasecode);
          gv_clientdeliverynotelineid := pack_sort_rs.create_cliendelnoteline(fp_idcode,
                                                                              gv_clientdeliverynote,
                                                                              gv_clientdeliverynoteid,
                                                                              gv_plantid_paramater,
                                                                              gv_unitcode,
                                                                              gv_businessunitid,
                                                                              gv_customerid,
                                                                              gv_productgroupid,
                                                                              gv_productid, gv_sizeid,
                                                                              gv_finishingmethodid,
                                                                              gv_systemuserid,
                                                                              gv_loglevel,
                                                                              nvl(gv_logmessage,
                                                                                   'SENDTRACKINFORS'),
                                                                              4);
          -- Call the procedure
          pack_sort_rs.create_clientdelnotescan(gv_clientdelnotlinescanid, fp_idcode,
                                                gv_clientdeliverynote, gv_clientdeliverynotelineid,
                                                gv_plantid_paramater, gv_unitcode, gv_loglevel,
                                                gv_logmessage, gv_systemuserid,
                                                gv_uniqueresidentialitemid, 'OUT', gv_scandate);
          check_autoflag(gv_transactiontype);
          create_residentialitemscan(2);
          remove_outscanflag;
        end;
      when 11 then
        begin
          --rewash
          check_autoflag(gv_transactiontype);
          create_residentialitemscan(4);
        end;
      when 12 then
        begin
          --pre sort
          create_residentialitemscan(6);
        end;
      when 34 then
        begin
          --assign product scan
          create_residentialitemscan(34);
          --update uniqueresidentialitem status
          update uniqueresidentialitem ur
          set    ur.status_id =
                  (select st.status_id
                   from   status st
                   where  st.statustype = 'UR'
                   and    st.code = '10'), ur.statuschangedate = gv_scandate
          where  ur.uniqueresidentialitem_id = gv_uniqueresidentialitemid
          and    ur.status_id = (select st.status_id
                                 from   status st
                                 where  st.statustype = 'UR'
                                 and    st.code = '20');
        end;
      else
        begin
          --other
          fp_status       := 7;
          fp_errormessage := 'Error, status 7; Unknown Transaction type ' ||
                             nvl(to_char(gv_transactiontype), 'NULL') || ' ID code ' ||
                             nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL') ||
                             ' location ' || nvl(to_char(fp_locationcode), 'NULL') ||
                             ' next location ' || nvl(to_char(fp_nextlocationcode), 'NULL') ||
                             ' for unit code ' || nvl(gv_unitcode, 'NULL');
          raise gv_userexception;
        end;
    end case; --gv_transactiontype
  end process_transactiontype;
begin
  --intialize
  intialize;
  --get location
  get_sortingimportdefinition;
  --process_transactiontype
  process_transactiontype;
  --if need be create Assign Product scan!
  if gv_create_assignproductscan then
    begin
      gv_scandate        := gv_scandate - 1 / 86400;
      gv_transactiontype := 34; --Assign Product
      process_transactiontype;
    end;
  end if;
  --commit;
  commit;
  --logging
  fp_status       := 0;
  fp_errormessage := null;
  pack_sort_rs.write_logging('Ok, status 0; ID code ' || nvl(fp_idcode, 'NULL') || ' plant code ' ||
                             nvl(fp_plantcode, 'NULL') || ' location ' ||
                             nvl(to_char(fp_locationcode), 'NULL') || ' next location ' ||
                             nvl(to_char(fp_nextlocationcode), 'NULL'), gv_loglevel, gv_logmessage,
                             gv_plantid_paramater, 1, 0);
exception
  --error handling
  when gv_userexception then
    begin
      rollback;
      if (fp_status = 0 or fp_status is null) then
        begin
          fp_status       := 5; --user exception
          fp_errormessage := 'Error, status 5; ' || gv_message || ' ID code ' ||
                             nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL') ||
                             ' location ' || nvl(to_char(fp_locationcode), 'NULL') ||
                             ' next location ' || nvl(to_char(fp_nextlocationcode), 'NULL') ||
                             ' for unit code ' || nvl(gv_unitcode, 'NULL');
        end;
      end if;
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel,
                                 nvl(gv_logmessage, 'SENDTRACKINFORS'), gv_plantid_paramater, 3, 0);
    end;
  when no_data_found then
    begin
      rollback;
      fp_status       := 1; --no_data_found
      fp_errormessage := 'No data found, status 1; ' || gv_message || ' no data found for ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL') ||
                         ' location ' || nvl(to_char(fp_locationcode), 'NULL') || ' next location ' ||
                         nvl(to_char(fp_nextlocationcode), 'NULL') || ' for unit code ' ||
                         nvl(gv_unitcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel,
                                 nvl(gv_logmessage, 'SENDTRACKINFORS'), gv_plantid_paramater, 3, 0);
    end;
  when too_many_rows then
    begin
      rollback;
      fp_status       := 2; --too many rows
      fp_errormessage := 'Too many rows, status 2; ' || gv_message || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL') ||
                         ' location ' || nvl(to_char(fp_locationcode), 'NULL') || ' next location ' ||
                         nvl(to_char(fp_nextlocationcode), 'NULL') || ' for unit code ' ||
                         nvl(gv_unitcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel,
                                 nvl(gv_logmessage, 'SENDTRACKINFORS'), gv_plantid_paramater, 3, 0);
    end;
  when dup_val_on_index then
    begin
      rollback;
      fp_status       := 3; --dup_val_on_index
      fp_errormessage := 'Dup val on index, status 3; ' || gv_message || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL') ||
                         ' location ' || nvl(to_char(fp_locationcode), 'NULL') || ' next location ' ||
                         nvl(to_char(fp_nextlocationcode), 'NULL') || ' for unit code ' ||
                         nvl(gv_unitcode, 'NULL') || ' ' || sqlerrm;
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel,
                                 nvl(gv_logmessage, 'SENDTRACKINFORS'), gv_plantid_paramater, 3, 0);
    end;
  when others then
    begin
      rollback;
      fp_status := 4; --others
      pack_sort_rs.write_logging('Error others, status 4; ' || gv_message || ' ID code ' ||
                                 nvl(fp_idcode, 'NULL') || ' plant code ' ||
                                 nvl(fp_plantcode, 'NULL') || ' location ' ||
                                 nvl(to_char(fp_locationcode), 'NULL') || ' next location ' ||
                                 nvl(to_char(fp_nextlocationcode), 'NULL') || ' for unit code ' ||
                                 nvl(gv_unitcode, 'NULL') || ' see debug info!', gv_loglevel,
                                 nvl(gv_logmessage, 'SENDTRACKINFORS'), gv_plantid_paramater, 3, 0);
      fp_errormessage := 'Error others, status 4; ' || sqlerrm || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(fp_plantcode, 'NULL') ||
                         ' location ' || nvl(to_char(fp_locationcode), 'NULL') || ' next location ' ||
                         nvl(to_char(fp_nextlocationcode), 'NULL') || ' for unit code ' ||
                         nvl(gv_unitcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel,
                                 nvl(gv_logmessage, 'SENDTRACKINFORS'), gv_plantid_paramater, 3, 0);
    end;
end sendtrackinfors;
/
create or replace procedure sendtrackinfosmartline(garmentid      in uniqueitem.primaryid%type,
                                                   plantcode      in out plant.code%type,
                                                   datetime       in date,
                                                   locationcode   in varchar2,
                                                   packageid      in varchar2, /*for now ignored*/
                                                   repairtypecode in varchar2 default null,
                                                   defaulttime    in number default null, /*stored as minutes*/
                                                   chargerepairs  in number default 0,
                                                   statusout      out number) is
  /*sendtrackinfosmartline version 2.7*/
  lv_user_exception exception;
  lv_datep          number;
  lv_timep          varchar2(12);
  lv_plantid_param  plant.plant_id%type;
  lv_uniqueitemid   uniqueitem.uniqueitem_id%type;
  lv_businessunitid businessunit.businessunit_id%type;
  lv_pool           integer;
  lv_systemuserid   systemuser.systemuser_id%type;

  procedure get_systemuser is
  begin
    --systemuser
    begin
      select s.systemuser_id into lv_systemuserid from systemuser s where s.username = 'SORT';
    exception
      when no_data_found then
        select min(systemuser_id) into lv_systemuserid from systemuser;
    end;
  end get_systemuser;

  procedure check_parameters is

    procedure getgarment_id is
    begin
      --getgarment_id
      --check if garmentid exists as primary id
      select u.uniqueitem_id, u.businessunit_id, u.poolitem
      into   lv_uniqueitemid, lv_businessunitid, lv_pool
      from   uniqueitem u
      where  u.poolitem <> 0 --not stock
      and    u.primaryid = garmentid
      and    exists (select 1
              from   businessunit bu
              where  bu.businessunit_id = u.businessunit_id
              and    bu.plant_id = lv_plantid_param);
    exception
      when no_data_found then
        begin
          select u.uniqueitem_id, u.businessunit_id, u.poolitem
          into   lv_uniqueitemid, lv_businessunitid, lv_pool
          from   secondaryuniqueitem s
          join   uniqueitem u
          on     u.uniqueitem_id = s.uniqueitem_id
          where  u.poolitem <> 0 --not stock
          and    s.secondaryid = garmentid
          and    exists (select 1
                  from   businessunit bu
                  where  bu.businessunit_id = u.businessunit_id
                  and    bu.plant_id = lv_plantid_param);
        exception
          when no_data_found then
            begin
              statusout := 6;
              pack_sort.write_logging('Error input garmentid  ' || nvl(garmentid, 'NULL') ||
                                      ' plant code ' || nvl(plantcode, 'NULL') ||
                                      ' does not exist (or is on STOCK)!', 5,
                                      'SENDTRACKINFOSMARTLINE', null, 3, 0);
              raise lv_user_exception;
            end;
        end;
    end getgarment_id;
  begin
    --check_parameters
    statusout := 0;
    --check garmentid
    if garmentid is null then
      begin
        statusout := 1;
        pack_sort.write_logging('Error input garmentid cannot be left blank!', 5,
                                'SENDTRACKINFOSMARTLINE', null, 3, 0);
        raise lv_user_exception;
      end;
    end if;
    --check plantcode
    if plantcode is null then
      begin
        statusout := 1;
        pack_sort.write_logging('Error input plantcode cannot be left blank!', 5,
                                'SENDTRACKINFOSMARTLINE', null, 3, 0);
        raise lv_user_exception;
      end;
    else
      begin
        select pt.plant_id into lv_plantid_param from plant pt where pt.code = plantcode;
      exception
        when no_data_found then
          begin
            pack_sort.write_logging('Error input plantcode ' || plantcode || ' does not exist', 5,
                                    'SENDTRACKINFOSMARTLINE', null, 3, 0);
            raise lv_user_exception;
          end;
      end;
    end if;
    --check date/time
    if (datetime is null and nvl(locationcode, '0') <> '045001') then
      begin
        statusout := 2;
        pack_sort.write_logging('Error input datetime cannot be left blank! locationcode ' ||
                                nvl(locationcode, 'NULL'), 5, 'SENDTRACKINFOSMARTLINE', null, 3, 0);
        raise lv_user_exception;
      end;
    else
      begin
        lv_datep := to_number(to_char(datetime, 'YYYYMMDD'));
        lv_timep := to_char(datetime, 'HH24MISS');
      exception
        when others then
          begin
            statusout := 2; --Erro others, invalid date/time, Status 2 - Wrong input
            pack_sort.write_logging('Error (invalid date/time), status 2; Garment ID ' ||
                                    nvl(garmentid, 'NULL') || ' plant code ' ||
                                    nvl(plantcode, 'NULL') || ' location ' ||
                                    nvl(to_char(locationcode), 'NULL'), 5, 'SENDTRACKINFOSMARTLINE',
                                    null, 3, 0);
            raise lv_user_exception;
          end;
      end;
    end if;
    --check on location codes that are not supported
    if locationcode in ('045005', '045006', '045007', '131101', '131104') then
      begin
        statusout := 1; --does not support a location code which is in the list of supported location codes
        pack_sort.write_logging('Error location code / processing is NOT supported, status 1; Garment ID ' ||
                                nvl(garmentid, 'NULL') || ' plant code ' || nvl(plantcode, 'NULL') ||
                                ' location ' || nvl(to_char(locationcode), 'NULL'), 5,
                                'SENDTRACKINFOSMARTLINE', null, 3, 0);
        raise lv_user_exception;
      end;
    end if;
    if locationcode is null and repairtypecode is null then
      begin
        statusout := 1;
        pack_sort.write_logging('Error input variables locationcode and repairtype code are blank, status 1; Garment ID ' ||
                                nvl(garmentid, 'NULL') || ' plant code ' || nvl(plantcode, 'NULL'),
                                5, 'SENDTRACKINFOSMARTLINE', null, 3, 0);
        raise lv_user_exception;
      end;
    end if;
    --getgarment_id
    getgarment_id;
  end check_parameters;

  procedure only_update_repaircounter is
  begin
    --get_systemuser
    get_systemuser;
    --update repair count only
    update uniqueitem u
    set    u.repairstotal = u.repairstotal + 1, u.systemuser_id = lv_systemuserid,
           u.timestamp = sysdate
    where  u.uniqueitem_id = lv_uniqueitemid;
  end only_update_repaircounter;

  procedure register_repair is
    --register_repair, remark we register NOT a scan!
    lv_repairtypeid repairtype.repairtype_id%type;
    lv_defaulttime  repairtype.defaulttime%type;

    procedure get_repairtypeid is
    begin
      --get_repairtypeid
      select rt.repairtype_id, rt.defaulttime
      into   lv_repairtypeid, lv_defaulttime
      from   repairtype rt
      where  rt.code = repairtypecode;
    exception
      when no_data_found then
        begin
          statusout := 2; --others, invalid repairtypecode parameter
          pack_sort.write_logging('Parameter repairtypecode ' || repairtypecode ||
                                  ' does not exist!', 5, 'SENDTRACKINFOSMARTLINE', lv_plantid_param,
                                  3, 0);
          lv_repairtypeid := null;
          raise lv_user_exception;
        end;
    end get_repairtypeid;

    procedure create_repairhistory is
    begin
      if nvl(chargerepairs, 0) not in (0, 1, 2, 3) then
        begin
          statusout := 2; --others, invalid chargerepairs parameter
          pack_sort.write_logging('Parameter chargerepairs should be 0 = Charge, 1 = Free of Charge, 2 = Charge Cancelled or 3 = No repair charge',
                                  5, 'SENDTRACKINFOSMARTLINE', lv_plantid_param, 3, 0);
          raise lv_user_exception;
        end;
      elsif lv_repairtypeid is not null then
        begin
          --insert into repairhistory
          insert into repairhistory
            (repairhistory_id, supplier_id, currency_id, product_link_id, distributionpoint_link_id,
             weareremployment_link_id, customer_link_id, repairtype_id, uniqueitem_link_id,
             businessunit_id, repairdate, minutes, year, week, day, pool, unitprice, priceperminute,
             systemuser_id, timestamp, status, invoicebusinessunit_id, invoiceheader_id, primaryid,
             amount, quantity, customerowned)
            select seq_repairhistory.nextval /*repairhistory_id*/, null /*supplier_id*/, null
                   /*currency_id*/, u.product_id /*product_link_id*/, u.distributionpoint_id
                   /*distributionpoint_link_id*/, un.weareremployment_id
                   /*weareremployment_link_id*/, w.customer_id /*customer_link_id*/, lv_repairtypeid
                   /*repairtype_id*/, lv_uniqueitemid /*uniqueitem_link_id*/, lv_businessunitid
                   /*businessunit_id*/, trunc(datetime) /*repairdate*/,
                   coalesce(defaulttime, lv_defaulttime, 0) /*minutes*/, getyearofweek(datetime)
                   /*year*/, getisoweek(datetime) /*week*/, getabsdaynumber(datetime) /*day*/,
                   case lv_pool
                     when 1 then
                      'Y'
                     else
                      'N'
                   end /*pool*/, null /*unitprice*/, null /*priceperminute*/, lv_systemuserid
                   /*systemuser_id*/, sysdate /*timestamp*/, nvl(chargerepairs, 0) /*status*/,
                   lv_businessunitid /*invoicebusinessunit_id*/, null /*invoiceheader_id*/,
                   garmentid /*primaryid*/, 1 /*amount*/, 1 /*quantity*/, u.customerowned /*customerowned*/
            from   uniqueitem u
            left   outer join(uniqueitemnonpool un
            join   weareremployment we
            on     we.weareremployment_id = un.weareremployment_id
            join   wearer w
            on     w.wearer_id = we.wearer_id) on un.uniqueitem_id = u.uniqueitem_id
            where  u.uniqueitem_id = lv_uniqueitemid;
        end;
      end if;
    end create_repairhistory;

    procedure update_uniqueitem is
    begin
      if statusout = 0 then
        begin
          --update_uniqueitem
          update uniqueitem u
          set    u.repairstotal = u.repairstotal + 1, u.timestamp = sysdate,
                 u.systemuser_id = lv_systemuserid
          where  u.uniqueitem_id = lv_uniqueitemid;
          --update uniqueitemnonpool
          update uniqueitemnonpool un
          set    un.repairsthisissue = un.repairsthisissue + 1, un.timestamp = sysdate,
                 un.systemuser_id = lv_systemuserid
          where  un.uniqueitem_id = lv_uniqueitemid;
        end;
      end if;
    end update_uniqueitem;

    procedure add_max_repair_flag is
      lv_maxrepairsproduct  number;
      lv_maxrepairsplpc     number;
      lv_repairsotal        number;
      lv_maxrepflagattached number;
      lv_maxrepairsflagid   number;
      lv_scandate           timestamp;
    begin
      --get automaticflag
      select max(af.flag_id)
      into   lv_maxrepairsflagid
      from   automaticflag af
      where  af.event = 'Maximum Number of Repairs';
      --count repairs
      select count(*)
      into   lv_maxrepflagattached
      from   uniqueitemflag uif
      where  uif.uniqueitem_id = garmentid
      and    uif.flag_id = lv_maxrepairsflagid;
      --check if we need to add the flag
      if (lv_maxrepflagattached = 0 and lv_maxrepairsflagid is not null) then
        begin
          --get scandatetime
          lv_scandate := to_timestamp(to_char(lv_datep) || to_char(lv_timep), 'YYYYMMDDHH24MISS');
          if (lv_pool <> 1) then
            begin
              --check non-pool for repair flag
              select nvl(max(ui.repairstotal), 0), nvl(max(plpc.maximumnumberofrepairs), 0),
                     nvl(max(p.maximumnumberofrepairs), 0)
              into   lv_repairsotal, lv_maxrepairsplpc, lv_maxrepairsproduct
              from   uniqueitem ui, productlistpercustomer plpc, uniqueitemnonpool uinp,
                     wearerinventory wi, weareremployment we, wearer w, product p
              where  ui.primaryid = garmentid
              and    ui.product_id = plpc.product_id
              and    (ui.sizedefinition_id = plpc.sizedefinition_id or
                    plpc.sizedefinition_id =
                    (select sd.sizedefinition_id from sizedefinition sd where sd.code = '*'))
              and    ui.finishingmethod_id = plpc.finishingmethod_id
              and    ui.uniqueitem_id = uinp.uniqueitem_id
              and    uinp.wearerinventory_id = wi.wearerinventory_id
              and    wi.weareremployment_id = we.weareremployment_id
              and    we.wearer_id = w.wearer_id
              and    w.customer_id = plpc.customer_id
              and    ui.product_id = p.product_id
              and    plpc.dateactive < lv_scandate
              and    plpc.dateinactive > lv_scandate;
              --check if flag needs to be added
              if (lv_maxrepairsplpc > 0 and lv_repairsotal > lv_maxrepairsplpc) or
                 (lv_maxrepairsproduct > 0 and lv_repairsotal > lv_maxrepairsproduct and
                 lv_maxrepairsplpc = 0) then
                begin
                  insert into uniqueitemflag
                    (uniqueitem_id, flag_id, startdate, systemuser_id, timestamp)
                  values
                    (lv_uniqueitemid, lv_maxrepairsflagid, sysdate, lv_systemuserid, sysdate);
                end;
              end if;
            end;
          else
            begin
              --check pool for repair flag
              select nvl(max(ui.repairstotal), 0), nvl(max(plpc.maximumnumberofrepairs), 0),
                     nvl(max(p.maximumnumberofrepairs), 0)
              into   lv_repairsotal, lv_maxrepairsplpc, lv_maxrepairsproduct
              from   uniqueitem ui, productlistpercustomer plpc, distributionpoint dp, department d,
                     product p
              where  ui.primaryid = garmentid
              and    ui.product_id = plpc.product_id
              and    (ui.sizedefinition_id = plpc.sizedefinition_id or
                    plpc.sizedefinition_id =
                    (select sd.sizedefinition_id from sizedefinition sd where sd.code = '*'))
              and    ui.finishingmethod_id = plpc.finishingmethod_id
              and    ui.distributionpoint_id = dp.distributionpoint_id
              and    dp.department_id = d.department_id
              and    d.customer_id = plpc.customer_id
              and    ui.product_id = p.product_id
              and    plpc.dateactive < lv_scandate
              and    plpc.dateinactive > lv_scandate;
              --check if flag needs to be added
              if (lv_maxrepairsplpc > 0 and lv_repairsotal > lv_maxrepairsplpc) or
                 (lv_maxrepairsproduct > 0 and lv_repairsotal > lv_maxrepairsproduct and
                 lv_maxrepairsplpc = 0) then
                begin
                  insert into uniqueitemflag
                    (uniqueitem_id, flag_id, startdate, systemuser_id, timestamp)
                  values
                    (lv_uniqueitemid, lv_maxrepairsflagid, sysdate, lv_systemuserid, sysdate);
                end;
              end if;
            end;
          end if;
        end;
      end if;
    end add_max_repair_flag;

  begin
    --get_repairtypeid
    get_repairtypeid;
    if lv_repairtypeid is not null then
      begin
        --get sysetmuser
        get_systemuser;
        --create repair history
        create_repairhistory;
        --update uniqueitem
        update_uniqueitem;
        --add_max_repair_flag
        add_max_repair_flag;
      end;
    end if;
  end register_repair;

  procedure confirm_flag is
  begin
    --confirm_flag
    delete from uniqueitemflag uf
    where  uf.uniqueitem_id = lv_uniqueitemid
    and    exists (select 1
            from   flag f
            where  f.flag_id = uf.flag_id
            and    f.code = repairtypecode);
    if sql%rowcount = 0 then
      begin
        statusout := 6;
        pack_sort.write_logging('Error input flagcode(repairtypecode) ' ||
                                nvl(repairtypecode, 'NULL') || ' did not exist on garmentid  ' ||
                                nvl(garmentid, 'NULL') || ' plant code ' || nvl(plantcode, 'NULL'),
                                5, 'SENDTRACKINFOSMARTLINE', null, 3, 0);
        raise lv_user_exception;
      end;
    end if;
  end confirm_flag;
begin
  --check_parameters
  check_parameters;
  --process_data
  case locationcode
    when '001001' then
      begin
        /*
        Inbound registration
        Register that garment was scanned for inbound in the plant at the specified date and time.
        Mandatory input parameters:
        • Garment ID
        • Plant
        • Location code
        • Datetime
        */
        --register scan (must be setup in ABS as inscan for this location code)
        sendtrackinfo(garmentid, plantcode, lv_datep, lv_timep, locationcode, '', '', '', '', '', 0,
                      0, 0, null, statusout);
      end;
    when '045001' then
      begin
        /*
        Increase repair count A repair was done.
        Increase the repair counter in the unique item.
        Mandatory input parameters:
        • Garment ID
        • Plant
        • Location code
        */
        --only_update_repaircounter
        only_update_repaircounter;
      end;
    when '045002' then
      begin
        /*
        Create a repair Create an entry in the repair history.
        Does not increase the repair count in the unique item.
        Mandatory input parameters:
        • Garment ID
        • Plant
        • Location code
        • Repairtype
        • Datetime
        */
        --register_repair, remark we register NOT a scan!
        register_repair;
      end;
    when '045004' then
      begin
        /*
        Confirm flag  Confirm a flag that the flag is done.
        Mandatory input parameters:
        • Garment ID
        • Plant
        • Location code
        • Repairtype (type of flag)
        • Datetime
        */
        --confirm_flag
        confirm_flag;
      end;
    when '117001' then
      begin
        /*
        Outbound registration
        Register that garment was scanned for outbound in the plant at the specified date and time.
        Mandatory input parameters:
        • Garment ID
        • Plant
        • Location code
        • Datetime
        */
        --register scan (must be setup in ABS as outscan for this location code)
        sendtrackinfo(garmentid, plantcode, lv_datep, lv_timep, locationcode, '', '', '', '', '', 0,
                      0, 0, null, statusout);
      end;
    else
      begin
        statusout := 1; --does not support a location code which is in the list of supported location codes
        pack_sort.write_logging('Unknown location code / processing is NOT supported, status 1; Garment ID ' ||
                                nvl(garmentid, 'NULL') || ' plant code ' || nvl(plantcode, 'NULL') ||
                                ' location ' || nvl(to_char(locationcode), 'NULL'), 5,
                                'SENDTRACKINFOSMARTLINE', null, 3, 0);
        raise lv_user_exception;
      end;
  end case;
  commit;
exception
  when lv_user_exception then
    begin
      --message and status already done
      statusout := nvl(statusout, 9);
      rollback;
    end;
  when others then
    begin
      rollback;
      statusout := 9; --error others
      pack_sort.write_logging('Error others, status 12; Garment ID ' || nvl(garmentid, 'NULL') ||
                              ' plant code ' || nvl(plantcode, 'NULL') || ' location ' ||
                              nvl(to_char(locationcode), 'NULL') || ' sqlerm ' || sqlerrm ||
                              ' packageid (not used) ' || packageid, 5, 'SENDTRACKINFOSMARTLINE',
                              null, 3, 0);
    end;
end sendtrackinfosmartline;
/
create or replace procedure Sendtrackinfosortbatch(IDCode           in UNIQUEITEM.PRIMARYID%type,
                                                   PlantCode        in out PLANT.CODE%type,
                                                   Datep            in number,
                                                   Timep            in varchar2, --number,
                                                   LocationCode     in varchar2,
                                                   NextLocationCode in varchar2,
                                                   Flagcode         in SORTADDRESSPERFLAG.SORTADDRESS%type,
                                                   SortBatchNumber  in number,
                                                   SystemNumber     in number,
                                                   Status           out number) is

begin
  sendtrackinfo(IDCode,
                PlantCode,
                Datep,
                Timep,
                LocationCode,
                NextLocationCode,
                Flagcode,
                '',
                '',
                'SBN',
                SortBatchNumber, --501642
                0,
                0,
                '',
                Status);
  --added for sortbatch
  /* begin
    select sortbatch.status into sortbachstatus
    from sortbatch
    where sortbatch.sortbatch_id = SortBatchNumber;
    if Status = 0 and sortbachstatus=2 then
      --delete from sortbatch s where s. sortbatch_id = SortBatchNumber;
      update sortbatch s
      set s.status=3,
      s.closingtime = sysdate
      where s.sortbatch_id = SortBatchNumber;
      --SystemNumber := 1; should be always 1
      commit;
      elsif Status = 0 and sortbachstatus = 3 and ...then
      update sortbatch s
      set s.status=4,
      s.outscantime = sysdate
      where s.sortbatch_id = SortBatchNumber;
      commit;
    end if;
  exception
    when others then
      rollback;
  end;*/
end SendTrackInfoSortbatch;
/
create or replace procedure SendTrackInfoWithOrder(IDCode           in UNIQUEITEM.PRIMARYID%type,
                                          UnitCode         in out PLANT.CODE%type,
                                          Datep            in number,
                                          Timep            in varchar2, --number,
                                          LocationCode     in varchar2,
                                          NextLocationCode in varchar2,
                                          Flagcode1        in SORTADDRESSPERFLAG.SORTADDRESS%type,
                                          Flagcode2        in SORTADDRESSPERFLAG.SORTADDRESS%type,
                                          Flagcode3        in SORTADDRESSPERFLAG.SORTADDRESS%type,
                                          Flagcode4        in SORTADDRESSPERFLAG.SORTADDRESS%type,
                                          BatchNumber      in number,
                                          RouteNumber      in ROUTE.ROUTENUMBER%type,
                                          RouteDay         in DAY.DAYNUMBER%type,
                                          RepairsDone      in varchar2,
                                          Statusout        out number,
                                          OrderNumber in    packingnote.notenumber%type) is
Status   integer;
begin
 Status:= OrderNumber;
 sendtrackinfo(IDCode,
                UnitCode,
                Datep,
                Timep,
                LocationCode,
                NextLocationCode,
                Flagcode1,
                Flagcode2,
                Flagcode3,
                Flagcode4,
                BatchNumber,
                RouteNumber,
                RouteDay,
                RepairsDone,
                Status);
                Statusout:= Status;
end SendTrackInfoWithOrder;
/
create or replace procedure SetRouteToClosed(nRouteDay    in number,
                                             nRouteNumber in number,
                                             sPlantCode   in plant.code%type,
                                             sStatus      out integer) is
  plantid plant.plant_id%type;
  gv_message abslog.message%type;
  nroutecontrolid routecontrol.routecontrol_id%type;

  procedure write_log(fp_priority in number default 1) is
  begin
    --write_log
    abslogwrite.abslog_write(5, 'SetRouteToClosed', null, fp_priority, gv_message);
  end write_log;

begin
  sStatus := 0;
  begin
    select p.plant_id into plantid from plant p where p.code = splantcode;
  exception
    when no_data_found then
      sStatus := 1;
      begin
      gv_message := '>!Error Plant ' || sPlantCode || ' not found!';
      write_log(3);
      end;
  end;
  if sStatus = 0 then
    begin
      select min(rc.routecontrol_id)
        into nroutecontrolid
        from routecontrol rc, route r
       where rc.route_id = r.route_id and rc.drivingdate >= trunc(sysdate) and
             r.routenumber = nRouteNumber and
             r.drivingday_id = nRouteDay and r.plant_id = plantid
       order by rc.drivingdate;
      if nroutecontrolid is not null then
        for x in (select rc.sortingstatus,
                         rc.drivingdate,
                         rc.routecontrol_id
                    from routecontrol rc, route r
                   where rc.route_id = r.route_id and
                         rc.drivingdate >= trunc(sysdate) and
                         r.routenumber = nRouteNumber and
                         r.drivingday_id = nRouteDay and
                         r.plant_id = plantid
                   order by rc.drivingdate) loop
          if x.sortingstatus < 2 then
            update routecontrol
               set sortingstatus = 2
             where routecontrol_id = x.routecontrol_id;
            exit;
          elsif x.sortingstatus = 2 then
            sStatus := 2;
            gv_message:=to_char(sysdate, 'HH24:MI:SS') || ' Error Route ' || nRouteNumber ||
                              ' was already closed!';
                              write_log(3);
            exit;
          end if;
        end loop;
      else
        sStatus := 1;
        gv_message := to_char(sysdate, 'HH24:MI:SS') ||' Error Route ' || nRouteNumber || ' not found!';
        write_log(3);
      end if;
    exception
      when no_data_found then
        sStatus := 1;
        gv_message := to_char(sysdate, 'HH24:MI:SS') ||' Error Route ' || nRouteNumber || ' not found!';
        write_log(3);
    end;
  end if;
  If sstatus = 0 then
    commit;
  else
    rollback;
  end if;
end SetRouteToClosed;
/
create or replace procedure SORTBATCHPREPARATION (
	plantID								plant.plant_id%type,
	forecastCorrection		number
) is

	cursor c_SortBatchDef is
		select sbd.sortbatchdefinition_id, sbd.day_id, sbd.batchnumber, sbd.description,
						sbd.sharedbufferrail, sbd.bypasssorting,
						trunc(sysdate) + mod(7 + sbd.day_id - getabsdaynumber(trunc(sysdate)), 7) batchDate
		from sortbatchdefinition sbd, route r
		where sbd.sortbatchdefinition_id = r.sortbatchdefinition_id and
					sbd.day_id = r.drivingday_id and
					sbd.plant_id = plantID
		union
		select sbd.sortbatchdefinition_id, sbd.day_id, sbd.batchnumber, sbd.description,
						sbd.sharedbufferrail, sbd.bypasssorting,
						trunc(sysdate) + mod(7 + sbd.day_id - getabsdaynumber(trunc(sysdate)), 7) batchDate
			from sortbatchdefinition sbd, route r, routestop rs
			where sbd.sortbatchdefinition_id = rs.specificsortbatchdefinition_id and
						rs.route_id = r.route_id and
						sbd.day_id = r.drivingday_id and
						sbd.plant_id = plantID;

		cursor c_NumberOfGarments (sortBatchDefID sortbatchdefinition.sortbatchdefinition_id%type) is
			select coalesce(sum(wi.circinventory), 0) totalCirc,
						 round(coalesce(sum(((wi.circinventory*rs.expectedsortpercentage)/100)*forecastCorrection/100), 0)) custGarments
			from route r, routestop rs, customer c, department dep, distributionpoint dip, weareremployment we, wearerinventory wi
			where
						r.route_id = rs.route_id and
						rs.customer_id = c.customer_id and
						c.customer_id = dep.customer_id and
						dep.department_id = dip.department_id and
						dip.distributionpoint_id = we.distributionpoint_id and
						we.weareremployment_id = wi.weareremployment_id and
						c.inscanbasedforecast = 'N' and
						rs.stoptype != 2 and
						(rs.specificsortbatchdefinition_id = sortBatchDefID  or
							(rs.specificsortbatchdefinition_id is null and r.sortbatchdefinition_id = sortBatchDefID)
						) and
						(rs.deliverypoint_id is null or
							(we.deliverypoint_id = rs.deliverypoint_id) or
							(we.locker_id is not null and exists (select l.locker_id from locker l where l.deliverypoint_id = rs.deliverypoint_id and we.locker_id = l.locker_id)) or
							(we.garmentdispenser_id is not null and exists (select gd.garmentdispenser_id from garmentdispenser gd where gd.deliverypoint_id = rs.deliverypoint_id and we.garmentdispenser_id = gd.garmentdispenser_id))
						);

	noGarmentTotal			number;
	noGarmentNoInscan		number;
	sortBatchID					sortbatch.sortbatch_id%type;
	systemUserID				systemuser.systemuser_id%type;
	newBatch						boolean;
	countUI							integer:=0;

begin

	systemUserID:=getminsystemuser();

	for r_SortBatchDef in c_SortBatchDef loop

		-- get NumberOfGarmentsTotal, MunberOfGarmentsNoInscan
		open c_NumberOfGarments(r_SortBatchDef.sortbatchdefinition_id);
		fetch c_NumberOfGarments into noGarmentTotal, noGarmentNoInscan;
		close c_NumberOfGarments;
		-- create or update SORTBATCH
		begin
			select sb.sortbatch_id into sortBatchID
				from sortbatch sb
				where sb.plant_id = plantID and
							sb.batchnumber = r_SortBatchDef.batchnumber and
							sb.batchdate = r_SortBatchDef.batchdate;
			newBatch:=false;
			update sortbatch
				set numberofgarmentstotal = noGarmentTotal,
						numberofgarmentsnoinscan = noGarmentNoInscan,
						systemuser_id = systemUserID,
						timestamp = sysdate
				where sortbatch_id = sortBatchID;
		exception
		when no_data_found then
			newBatch:=true;
			insert into sortbatch (
						sortbatch_id, status, batchdate, plant_id,
						day_id, batchnumber, description, sharebufferrail, bypasssorting,
						numberofgarmentstotal, numberofgarmentsnoinscan, numberofgarmentsinscan,
						exporttime, systemuser_id, timestamp, closingtime, outscantime)
			values (
						seq_sortbatch.nextval, 0, r_SortBatchDef.batchdate, plantID,
						r_SortBatchDef.day_id, r_SortBatchDef.batchnumber, r_SortBatchDef.description,
						r_SortBatchDef.sharedbufferrail, r_SortBatchDef.bypasssorting,
						noGarmentTotal, noGarmentNoInscan, 0, null, systemUserID, sysdate, null, null)
			returning sortbatch_id into sortBatchID;
		end;

		-- fill SORTBATCHCONTENTS
		if (newBatch) then
			insert into sortbatchcontents(sortbatchcontents_id, sortbatch_id, idcode, uniqueitem_id, sequencenumber,
																		sortstring, altsortpackingsequence, expectationlevel,
																		routestop_id, customer_id, systemuser_id, timestamp)
			select seq_sortbatchcontents.nextval, sortBatchID, v.primaryid, v.uniqueitem_id, 0,
							pack_sort.getsortstring(plantID, v.customer_id, v.routestop_id, v.uniqueitem_id),
							0, v.expectationlevel, v.routestop_id, v.customer_id, systemUserID, sysdate
			from v_sortbatchpreparation v
			where v.sortbatchdefinition_id = r_SortBatchDef.sortbatchdefinition_id and
						v.plant_id = plantID;
		else
			insert into sortbatchcontents(sortbatchcontents_id, sortbatch_id, idcode, uniqueitem_id, sequencenumber,
																		sortstring, altsortpackingsequence, expectationlevel,
																		routestop_id, customer_id, systemuser_id, timestamp)
			select seq_sortbatchcontents.nextval, sortBatchID, v.primaryid, v.uniqueitem_id, 0,
							pack_sort.getsortstring(plantID, v.customer_id, v.routestop_id, v.uniqueitem_id),
							0, v.expectationlevel, v.routestop_id, v.customer_id, systemUserID, sysdate
			from v_sortbatchpreparation v
			where sortbatchdefinition_id = r_SortBatchDef.sortbatchdefinition_id and
						v.plant_id = plantID and
						not exists (select sbc.sortbatchcontents_id from sortbatchcontents sbc
												where sbc.sortbatch_id = sortBatchID and sbc.uniqueitem_id = v.uniqueitem_id);
		end if;
		countUI:=countUI+sql%rowcount;
	end loop;

	-- delete SORTBATCH
	delete from sortbatch
	where status = 4 and
				outscantime is not null and
				trunc(sysdate) - outscantime > 7;

	dbms_output.put_line(countUI);

end SORTBATCHPREPARATION;
/
create or replace procedure sp_adddvtoexistingpn(fp_plantid      in plant.plant_id%type,
                                                 fp_systemuserid in systemuser.systemuser_id%type default 0) is
  /* sp_adddvtoexistingpn version 1.0 */
  gv_message abslog.message%type;
  gv_counter number;
  procedure write_log(fp_message in varchar2, fp_priority in number default 3) is
  begin
    --write log
    abslogwrite.abslog_write(5, 'sp_adddvtoexistingpn', null, fp_priority, fp_message,
                             fp_systemuserid);
  end write_log;
begin
  gv_counter := 0;
  --start selecting the del vars to be processed
  gv_message := 'plant id ' || to_char(fp_plantid);
  for x in (select dv.deliveryvariations_id, dv.deliverydate, ca.processbusinessunit_id,
                   ordel.orplantdepartment_id
            from   deliveryvariations dv
            join   product p
            on     p.product_id = dv.product_id
            join   productgroup pg
            on     pg.productgroup_id = p.productgroup_id
            join   distributionpoint dp
            on     dp.distributionpoint_id = dv.distributionpoint_id
            join   department d
            on     d.department_id = dp.department_id
            join   customer c
            on     c.customer_id = d.customer_id
            join   customeractivities ca
            on     (ca.activity_id = pg.activity_id and ca.customer_id = c.customer_id)
            join   ordeliverbusinessunit ordel
            on     (ordel.delivertobusinessunit_id = ca.processbusinessunit_id and
                   ordel.orbusinessunit_id = ca.internalprocessingbu_id)
            join   businessunit bu
            on     bu.businessunit_id = ca.processbusinessunit_id
            where  dv.processed = 'N'
            and    dv.addtoexistingpn = 'Y'
            and    bu.plant_id = fp_plantid
            and    exists
             (select 1
                    from   packingnote pn
                    where  pn.processbusinessunit_id = ordel.delivertobusinessunit_id
                    and    pn.internalprocessingbu_id = ordel.orbusinessunit_id
                    and    pn.plantdepartment_id = ordel.orplantdepartment_id
                    and    pn.deliverydate = dv.deliverydate
                    and    pn. status_id = (select st.status_id
                                        from   status st
                                        where  st.code = '10'
                                        and    st.statustype = 'PN'))) loop
    begin
      add_dv_to_existing_pn(x.deliveryvariations_id, x.processbusinessunit_id,
                            x.orplantdepartment_id, fp_systemuserid);
      gv_counter := gv_counter + 1;
    end;
  end loop;
  commit;
  write_log('Processed ' || to_char(gv_counter) || ' deliveryvariations', 1);
exception
  when others then
    begin
      --others error handling
      rollback;
      write_log(sqlerrm || gv_message);
    end;
end sp_adddvtoexistingpn;
/
create or replace procedure sp_getgarmentdetails(fp_plantcode       in varchar2,
                                                 fp_primaryid       in varchar2,
                                                 fp_date            in date default trunc(sysdate + 1),
                                                 fp_deliverydate_dc in varchar2 default 'D',
                                                 out_table          out sys_refcursor) is
  --Procedure sp_getgarmentdetails version 5.3
  --31-08-2021  ABS-123927 store cleandate in uniqueitemroute
  --10-12-2021  ABS-128653 Error message sp_getgarmentdata (scanola)
  --08-04-2022  ABS-133915 Also provide customer number
  --12-04-2022  ABS-134025 Change Customer name into Department descr
  --22-07-2022  ABS-137231 skip flag code 42
  --23-11-2022  ABS-141007 Delivery date determination through sp_getgarments (including case when delivery day is sysdate)
  --20-12-2022  ABS-141007 Delivery date determination through sp_getgarments (including case when delivery day is sysdate)
  --19-01-2023  ABS-145625 [Fwd: ##RE-29538## : Lane set up failure - URGENT.]
  --24-07-2023  ABS-153336 Sort Address 1. bank/locker, 2. flex field on DP, 3. sort address on route stop/ delivery point
  --25-10-2023  ABS-156969 Reject primary_id if BU code doesn't match

  gv_user__exception   exception;
  gv_plantid_paramet   plant.plant_id%type;
  gv_ui_bucode         businessunit.code%type;
  gv_rec_uniqueitem    uniqueitem%rowtype;
  gv_secondaryid       secondaryuniqueitem.secondaryid%type;
  gv_timezonehrsdiff   plant.timezonehrsdiff%type;
  gv_languageid        languages.language_id%type;
  gv_p_collection_date date;
  gv_p_delivery_date   date;
  st_deliverypoint     deliverypoint.code%type;
  st_customerno        customer.customernumber%type;
  st_stopnam           department.description%type;
  st_add1              address.street%type;
  st_add2              address.street2%type;
  st_add3              address.city%type;
  st_add4              address.state%type;
  st_pst1              address.zipcode%type;
  fp_routenumber       number;
  fp_stopnumber        number;
  fp_routeday          number;
  st_laneno            varchar2(255);
  st_gst               finishingmethod.code%type;
  fp_productcode       product.code%type;
  fp_sizecode          sizedefinition.code%type;
  vg_wearnum           wearer.wearernumber%type;
  vg_wearnam           wearer.fullname%type;
  vg_locknum           locker.bank%type;
  vg_lockcde           locker.locker%type;
  vg_osact             flag.code%type;
  lc_lcklocn           flag.code%type;
  gm_ptype             stay.staynr%type;
  gm_psts              status.code%type;
  dnrtnd               varchar2(1);
  eclin1               flag_desc.description%type;
  eclin2               flag_desc.description%type;
  eclin3               flag_desc.description%type;
  col_date             date;
  fp_message           varchar2(1000);
  lv_cleandate         date;
  lc_ldklocn           locker.remark%type;
  lc_lcklane           locker.sortaddress%type;
  ---internal procedures/functions
  procedure write_log(fp_priority in number) is
  begin
    abslogwrite.abslog_write(5,
                             'sp_getgarmentdetails',
                             gv_plantid_paramet,
                             fp_priority,
                             fp_message);
  end write_log;

  procedure initialization is
  begin
    fp_message := 'initialization';
    --get info for fp_plantcode
    if fp_plantcode is null then
      begin
        fp_message := 'parameter fp_plantcode cannot be left blank!';
        raise gv_user__exception;
      end;
    else
      begin
        fp_message := 'Retrieving plant code ' || fp_plantcode;
        select p.plant_id, p.timezonehrsdiff, p.language_id
          into gv_plantid_paramet, gv_timezonehrsdiff, gv_languageid
          from plant p
         where p.code = fp_plantcode;
      end;
    end if;
    if fp_primaryid is null then
      begin
        fp_message := 'parameter fp_primaryid cannot be left blank!';
        raise gv_user__exception;
      end;
    end if;
    if fp_date is not null then
      begin
        if upper(fp_deliverydate_dc) = 'C' then
          gv_p_collection_date := least(trunc(fp_date), trunc(sysdate));
        else
          gv_p_delivery_date := greatest(trunc(fp_date), trunc(sysdate) + 1);
        end if;
      end;
    else
      begin
        gv_p_collection_date := trunc(sysdate);
        gv_p_delivery_date   := trunc(sysdate + 1);
      end;
    end if;
  end initialization;

  procedure get_uniqueiteminfo is
    lv_businessunitcode           businessunit.code%type;
    lv_customerid                 customer.customer_id%type;
    lv_customername               customer.name%type;
    lv_sortcustomerid             customer.sortcustomer_id%type;
    lv_chargerepaircog            customer.chargerepaircog%type;
    lv_chargerepairs              customer.chargerepairs%type;
    lv_checkpointselection        serviceteam.sortaddress%type; --fp_checkpointselection
    lv_departmentnumber           department.departmentnumber%type;
    lv_departmentid               department.department_id%type;
    lv_deliverypointdesc          deliverypoint.description%type;
    lv_deliverypointid            deliverypoint.deliverypoint_id%type;
    lv_deliverypoint_eutid        deliverypoint.deliverypoint_id%type;
    lv_visitaddressid             address.address_id%type;
    lv_distributionpointnumber    distributionpoint.distributionpointnumber%type;
    lv_distributionpointid        distributionpoint.distributionpoint_id%type;
    lv_wearersearchname           wearer.searchname%type;
    lv_wearerremark               wearer.remark%type; /*infotext*/
    lv_gender                     wearer.sex%type;
    lv_garmentdispensercode       garmentdispenser.code%type;
    lv_wearer_flagid              wearer.flag_id%type;
    lv_wearer_flagstartdate       wearer.flagstartdate%type;
    lv_employ_flagid              weareremployment.flag_id%type;
    lv_employ_flagstartdate       weareremployment.flagstartdate%type;
    lv_customeremployeenumber     wearer.customeremployeenumber%type;
    lv_productdescription         product_desc.description%type;
    lv_productimagename           image.imagename%type;
    lv_finishingcodeid            product.finishingcode_id%type;
    lv_productsortgroup           productsortgroup.code%type;
    lv_packingsequence            product.packingsequence%type;
    lv_typeofmerchandise          product.typeofmerchandise%type;
    lv_alternatesortstring        customer.alternatesorting%type;
    lv_destination                sortaddressperfinishingmeth.sortaddress%type;
    lv_foldprogram                foldingprogramdefinition.foldingprogram%type;
    lv_maxwashes                  product.maxwashes%type;
    lv_seasoncode                 season.code%type;
    lv_residualvalueamount        residualvaluehistory.residualvalueamount%type;
    lv_residualvaluepercentage    residualvaluehistory.residualvaluepercentage%type;
    lv_weareremploymentid         weareremployment.weareremployment_id%type;
    lv_lockerid                   locker.locker_id%type;
    lv_garmentdispenserid         garmentdispenser.garmentdispenser_id%type;
    lv_legacyproductcode          product.legacyproductcode%type;
    lv_productlongdescription     product_desc.longdescription%type;
    lv_productgroupdescription    productgroup_desc.description%type;
    lv_productgroupcode           productgroup.code%type;
    lv_shortdescription           product.shortdescription%type;
    lv_fabriccode                 fabric.code%type;
    lv_fabricdescription          fabric_desc.description%type;
    lv_colorcode                  color.code%type;
    lv_colordescription           color_desc.description%type;
    lv_theoreticalweight          product.theoreticalweight%type;
    lv_weighingcategoryid         product.weighingcategory_id%type;
    lv_plpcid                     productlistpercustomer.productlistpercustomer_id%type;
    lv_billingmethod              productlistpercustomer.billingmethod%type;
    lv_chargewashesonlyforcog     productlistpercustomer.chargewashesonlyforcog%type;
    lv_numwashesspecialtreatment  productlistpercustomer.numberwashesspecialtreatment%type;
    lv_qtytobereturneddecreasemax wearerinventory.qtytobereturneddecreasemax%type;
    lv_product_washingprocessid   product.washingprocess_id%type;
    lv_plpc_washingprocessid      productlistpercustomer.washingprocess_id%type;
    lv_plpc_soilcountmethod       productlistpercustomer.soilcountmethod%type;

    procedure get_extrainfo is
    begin
      --get_extrainfo
      fp_message := 'get_extrainfo finishingmethod';
      select max(f.code)
        into st_gst
        from finishingmethod f
       where f.finishingmethod_id = gv_rec_uniqueitem.finishingmethod_id;
      if lv_visitaddressid is not null then
        begin
          --get visit address
          fp_message := 'get_extrainfo visit address';
          select ad.street, ad.street2, ad.city, ad.state, ad.zipcode
            into st_add1, st_add2, st_add3, st_add4, st_pst1
            from address ad
           where ad.address_id = lv_visitaddressid;
        end;
      end if;
      --get stay
      select to_char(max(st.staynr))
        into gm_ptype
        from stay st
       where st.stay_id = gv_rec_uniqueitem.stay_id;
      --get status
      select max(st.code)
        into gm_psts
        from status st
       where st.status_id = gv_rec_uniqueitem.status_id;
      --get locker info
      begin
        select l.locker, l.sortaddress
          into lc_ldklocn, lc_lcklane
          from locker l
         where l.locker_id = lv_lockerid;
      exception
        when no_data_found then
          begin
            lc_ldklocn := null;
            lc_lcklane := null;
          end;
      end;
    end get_extrainfo;

    procedure get_sortstring is
    begin
      --get_sortstring
      fp_message := 'get_sortstring for deliverypoint id ' ||
                    to_char(lv_deliverypointid);
      select delp.sortaddress
        into st_laneno
        from deliverypoint delp
       where delp.deliverypoint_id = lv_deliverypointid;
    end get_sortstring;

    procedure determine_route is
      lv_routeid           route.route_id%type;
      lv_stopid            stop.stop_id%type;
      lv_routestopid       routestop.routestop_id%type;
      lv_routecontrolid    routecontrol.routecontrol_id%type;
      lv_in_routeid        route.route_id%type;
      lv_in_routestopid    routestop.routestop_id%type;
      lv_in_routecontrolid routecontrol.routecontrol_id%type;
      lv_in_stopid         stop.stop_id%type;
      --  lv_nextvisit         date;

      procedure no_routeinfo is
      begin
        fp_routenumber := null;
        fp_routeday    := null;
        fp_stopnumber  := null;
      end no_routeinfo;

      procedure get_collectiondate(lv_date in date) is
      begin
        select max(dyw.date_)
          into gv_p_collection_date
          from route rr
          join routestop rrs
            on rrs.route_id = rr.route_id
          join routestop rs
            on rs.returnroute_id = rr.route_id
           and rs.deliverypoint_id = rrs.deliverypoint_id
          join route x
            on x.route_id = rs.route_id
          join date_yearweekday dyw
            on dyw.day = x.drivingday_id
           and dyw.date_ between trunc(sysdate - 6) and trunc(sysdate)
         where rrs.customer_id = lv_customerid
           and rrs.deliverypoint_id = lv_deliverypointid
           and rr.drivingday_id = getabsdaynumber(lv_date)
           and trunc(fp_date) between rrs.dateactive and rrs.dateinactive;
        if gv_p_collection_date is null then
          begin
            --not found we go 1 week back..
            gv_p_collection_date := trunc(fp_date - 6);
          end;
        end if;

      end get_collectiondate;

      procedure update_plannedroute_date is
      begin
        --update_plannedroute_date
        fp_message := 'store plannedroute_date';
        update uniqueitemroute ur
           set ur.plannedoutdate     = lv_cleandate,
               ur.plannedoutstop_id  = lv_stopid,
               ur.plannedoutroute_id = lv_routeid,
               ur.timestamp          = sysdate,
               ur.systemuser_id      = 1
         where ur.uniqueitem_id = gv_rec_uniqueitem.uniqueitem_id;
        if sql%rowcount = 0 then
          begin
            insert into uniqueitemroute
              (uniqueitem_id,
               lastinroute_id,
               lastoutroute_id,
               plannedoutroute_id,
               lastindate,
               lastoutdate,
               plannedoutdate,
               systemuser_id,
               timestamp,
               lastinstop_id,
               lastoutstop_id,
               plannedoutstop_id)
            values
              (gv_rec_uniqueitem.uniqueitem_id,
               lv_in_routeid,
               lv_routeid,
               lv_routeid,
               col_date,
               lv_cleandate,
               lv_cleandate,
               1,
               sysdate,
               lv_in_stopid,
               lv_stopid,
               lv_stopid);
          end;
        end if;
      end update_plannedroute_date;
    begin
      --determine_route
      fp_message := 'determine_route';
      if lv_customerid is null then
        begin
          no_routeinfo;
        end;
      else
        begin
          --pack_sort2.get_plpcid_info
          fp_message := 'pack_sort2.get_plpcid_info';
          lv_plpcid  := pack_sort2.get_plpcid_info(lv_customerid,
                                                   gv_rec_uniqueitem.product_id,
                                                   gv_rec_uniqueitem.sizedefinition_id,
                                                   gv_rec_uniqueitem.finishingmethod_id,
                                                   trunc(sysdate),
                                                   lv_maxwashes,
                                                   lv_billingmethod,
                                                   lv_chargewashesonlyforcog,
                                                   lv_numwashesspecialtreatment,
                                                   lv_plpc_washingprocessid,
                                                   lv_plpc_soilcountmethod);
          if upper(fp_deliverydate_dc) = 'C' then
            begin
              pack_deliverybasics.determinedeldateroutesoil(gv_plantid_paramet,
                                                            lv_customerid,
                                                            lv_deliverypointid,
                                                            lv_departmentid,
                                                            lv_typeofmerchandise,
                                                            gv_p_collection_date,
                                                            lv_plpcid,
                                                            lv_distributionpointid,
                                                            'N',
                                                            lv_in_routeid,
                                                            lv_in_routestopid,
                                                            lv_in_routecontrolid,
                                                            lv_in_stopid,
                                                            col_date,
                                                            lv_routeid,
                                                            lv_routestopid,
                                                            lv_routecontrolid,
                                                            lv_stopid,
                                                            lv_cleandate);
              if lv_cleandate <= trunc(sysdate) or lv_cleandate is null then
                pack_deliverybasics.determinedeldaterouteclean(gv_plantid_paramet,
                                                               lv_customerid,
                                                               lv_deliverypointid,
                                                               lv_departmentid,
                                                               lv_typeofmerchandise,
                                                               trunc(sysdate) + 1,
                                                               lv_plpcid,
                                                               lv_distributionpointid,
                                                               'N',
                                                               lv_routestopid,
                                                               lv_routeid,
                                                               lv_stopid,
                                                               lv_routecontrolid,
                                                               lv_cleandate);
              end if;

            end;
          else
            pack_deliverybasics.determinedeldateroutesoil(gv_plantid_paramet,
                                                          lv_customerid,
                                                          lv_deliverypointid,
                                                          lv_departmentid,
                                                          lv_typeofmerchandise,
                                                          gv_p_collection_date,
                                                          lv_plpcid,
                                                          lv_distributionpointid,
                                                         'N',
                                                          lv_in_routeid,
                                                          lv_in_routestopid,
                                                          lv_in_routecontrolid,
                                                          lv_in_stopid,
                                                          col_date,
                                                          lv_routeid,
                                                          lv_routestopid,
                                                          lv_routecontrolid,
                                                          lv_stopid,
                                                          lv_cleandate);
            pack_deliverybasics.determinedeldaterouteclean(gv_plantid_paramet,
                                                           lv_customerid,
                                                           lv_deliverypointid,
                                                           lv_departmentid,
                                                           lv_typeofmerchandise,
                                                           gv_p_delivery_date,
                                                           lv_plpcid,
                                                           lv_distributionpointid,
                                                           'N',
                                                           lv_routestopid,
                                                           lv_routeid,
                                                           lv_stopid,
                                                           lv_routecontrolid,
                                                           lv_cleandate);
            get_collectiondate(lv_cleandate);
            col_date := gv_p_collection_date;
          end if;
          --get routeinfo
          fp_message  := 'get route number ' || to_char(lv_routeid);
          fp_routeday := getabsdaynumber(lv_cleandate);
          begin
            select r.routenumber
              into fp_routenumber
              from route r
             where r.route_id = lv_routeid;
          exception
            when no_data_found then
              begin
                fp_routenumber := null;
              end;
          end;

          --get stopnumber
          fp_message := 'get stopnumber for stop id ' || to_char(lv_stopid);
          if lv_stopid is not null then
            begin
              select max(s.stopnumber)
                into fp_stopnumber
                from stop s
               where s.stop_id = lv_stopid;
            end;
          else
            begin
              if fp_stopnumber is null then
                select max(rs.stopnumber)
                  into fp_stopnumber
                  from routestop rs
                 where rs.routestop_id = lv_routestopid;
              end if;
            end;
          end if;
        exception
          when no_data_found then
            begin
              no_routeinfo;
            end;
        end;
      end if;
      --update_plannedroute_date
      update_plannedroute_date;
    end determine_route;

    procedure process_flag_info is
    begin
      --process_flag_info
      fp_message := 'process_flag_info';
      select f.code,
             coalesce((select fd.description
                        from flag_desc fd
                       where fd.flag_id = f.flag_id
                         and fd.language_id = gv_languageid),
                      (select max(uf.freetextitem)
                         from uniqueitemflag uf
                        where uf.flag_id = f.flag_id
                          and uf.uniqueitem_id =
                              gv_rec_uniqueitem.uniqueitem_id
                          and uf.startdate <= sysdate))
        into vg_osact, eclin1
        from flag f
      --join flag_desc fd on fd.flag_id = f.flag_id
       where f.flag_id =
             (select max(fm.flag_id)
                from flag fm
               where fm.prohibitdelivery = 'Y'
                 and fm.code <> '42'
                 and ((fm.flag_id in (lv_wearer_flagid, lv_employ_flagid) or
                     exists (select 1
                                from uniqueitemflag uf
                               where uf.flag_id = fm.flag_id
                                 and uf.uniqueitem_id =
                                     gv_rec_uniqueitem.uniqueitem_id
                                 and uf.startdate <= sysdate))));
      --set field dnrtnd
      if vg_osact is not null then
        dnrtnd := 'Y';
      else
        dnrtnd := 'N';
      end if;
    exception
      when others then
        begin
          dnrtnd := 'N';
        end;
    end process_flag_info;

    procedure get_flags(fp_wearer_flagid        in wearer.flag_id%type,
                        fp_wearer_flagstartdate in wearer.flagstartdate%type,
                        fp_employ_flagid        in weareremployment.flag_id%type,
                        fp_employ_flagstartdate in weareremployment.flagstartdate%type,
                        fp_flagdescription1     out nocopy flag_desc.description%type,
                        fp_flagdescription2     out nocopy flag_desc.description%type) is
      lv_counter number := 1;
    begin
      --get_flags
      for xf in (select f.flag_id,
                        f.code,
                        coalesce((select max(uf.freetextitem)
                                   from uniqueitemflag uf
                                  where uf.flag_id = f.flag_id
                                    and uf.uniqueitem_id =
                                        gv_rec_uniqueitem.uniqueitem_id
                                    and uf.startdate <= sysdate),
                                 (select fd.description
                                    from flag_desc fd
                                   where fd.flag_id = f.flag_id
                                     and fd.language_id = gv_languageid)) description
                   from flag f
                  where f.prohibitdelivery <> 'Y'
                    and f.code <> '42'
                    and ((f.flag_id in
                        (case when
                           fp_wearer_flagstartdate <= trunc(sysdate) then
                           fp_wearer_flagid else null end,
                           case when
                           fp_employ_flagstartdate <= trunc(sysdate) then
                           fp_employ_flagid else null end)) or exists
                         (select uf.flag_id
                            from uniqueitemflag uf
                           where uf.uniqueitem_id =
                                 gv_rec_uniqueitem.uniqueitem_id
                             and uf.flag_id = f.flag_id
                             and uf.startdate <= trunc(sysdate)))
                  order by f.showalways desc, f.priority) loop
        begin
          case lv_counter
            when 1 then
              fp_flagdescription1 := substr(xf.description, 1, 50);
            when 2 then
              fp_flagdescription2 := substr(xf.description, 1, 50);
            else
              exit;
          end case;
          lv_counter := lv_counter + 1;
        end;
      end loop;
    end get_flags;
  begin
    --pack_sort2.get_uniqueitem
    fp_message := 'pack_sort2.get_uniqueitem_info';
    pack_sort2.get_uniqueitem_info(gv_plantid_paramet,
                                   gv_rec_uniqueitem,
                                   gv_languageid,
                                   'N',
                                   lv_businessunitcode,
                                   st_customerno,
                                   lv_customerid,
                                   lv_sortcustomerid,
                                   lv_customername,
                                   lv_chargerepaircog,
                                   lv_chargerepairs,
                                   lv_checkpointselection,
                                   lv_departmentnumber,
                                   st_stopnam,
                                   lv_departmentid,
                                   st_deliverypoint,
                                   lv_deliverypointdesc,
                                   lv_deliverypointid,
                                   lv_deliverypoint_eutid,
                                   lv_visitaddressid,
                                   lv_distributionpointnumber,
                                   lv_distributionpointid,
                                   vg_wearnum,
                                   vg_wearnam,
                                   lv_wearersearchname,
                                   lv_wearerremark,
                                   lv_gender,
                                   vg_lockcde,
                                   vg_locknum,
                                   lv_garmentdispensercode,
                                   lv_wearer_flagid,
                                   lv_wearer_flagstartdate,
                                   lv_employ_flagid,
                                   lv_employ_flagstartdate,
                                   lv_customeremployeenumber,
                                   fp_productcode,
                                   lv_productdescription,
                                   lv_legacyproductcode,
                                   lv_shortdescription,
                                   lv_productlongdescription,
                                   lv_product_washingprocessid,
                                   lv_productimagename,
                                   lv_finishingcodeid,
                                   lv_productsortgroup,
                                   lv_productgroupcode,
                                   lv_productgroupdescription,
                                   lv_packingsequence,
                                   lv_typeofmerchandise,
                                   lv_theoreticalweight,
                                   fp_sizecode,
                                   lc_lcklocn,
                                   lv_alternatesortstring,
                                   lv_destination,
                                   lv_foldprogram,
                                   lv_maxwashes,
                                   lv_seasoncode,
                                   lv_residualvalueamount,
                                   lv_residualvaluepercentage,
                                   lv_weareremploymentid,
                                   lv_lockerid,
                                   lv_garmentdispenserid,
                                   lv_qtytobereturneddecreasemax,
                                   lv_fabriccode,
                                   lv_fabricdescription,
                                   lv_colorcode,
                                   lv_colordescription,
                                   lv_weighingcategoryid);
    --get sortstring
    get_sortstring;
    --get_extrainfo
    get_extrainfo;
    --determine_route
    determine_route;
    --process flag info
    process_flag_info;
    --get_flags
    get_flags(lv_wearer_flagid,
              lv_wearer_flagstartdate,
              lv_employ_flagid,
              lv_employ_flagstartdate,
              eclin2,
              eclin3);
  end get_uniqueiteminfo;

  procedure finalize is
  begin
    --finalize
    commit;
    fp_message := 'Ok';
  end finalize;

  procedure output_table is
  begin
    --output_table
    open out_table for
      select st_customerno st_customerno,
             st_deliverypoint deliverypoint,
             st_stopnam stopnam,
             st_add1 st_add1,
             st_add2 st_add2,
             st_add3 st_add3,
             st_add4 st_add4,
             st_pst1 st_pst1,
             fp_routenumber fp_routenumber,
             fp_stopnumber fp_stopnumber,
             fp_routeday fp_routeday,
             st_laneno st_laneno,
             st_gst st_gst,
             fp_productcode || fp_sizecode productsizecode,
             vg_wearnum vg_wearnum,
             vg_wearnam vg_wearnam,
             vg_locknum vg_locknum,
             vg_lockcde vg_lockcde,
             vg_osact vg_osact,
             gm_ptype gm_ptype,
             gm_psts gm_psts,
             fp_primaryid fp_primaryid,
             dnrtnd dnrtnd,
             eclin1 eclin1,
             eclin2 eclin2,
             eclin3 eclin3,
             col_date col_date,
             lv_cleandate lv_cleandate,
             fp_message fp_message,
             lc_ldklocn lc_ldklocn,
             lc_lcklane lc_lcklane
        from dual;
  end output_table;
begin
  --initialization
  initialization;
  --check primaryID for BU code
  fp_message := 'get_uniqueitem: ' || fp_primaryid || 'and BU code ' || gv_ui_bucode;
  select bu.code
  into   gv_ui_bucode
  from   uniqueitem u
  join   businessunit bu
         on bu.businessunit_id = u.businessunit_id
  where  u.primaryid = fp_primaryid
  and    bu.plant_id = gv_plantid_paramet;
  --pack_sort2.get_uniqueitem
  pack_sort2.get_uniqueitem(fp_primaryid,
                            fp_plantcode,
                            gv_plantid_paramet,
                            gv_rec_uniqueitem,
                            gv_secondaryid);
  --get_uniqueiteminfo
  fp_message := 'get_uniqueiteminfo: ' || fp_primaryid;
  get_uniqueiteminfo;
  --finalize
  finalize;
  --output_table
  output_table;
exception
  when gv_user__exception then
    begin
      rollback;
      write_log(3);
      output_table;
    end;
  when no_data_found then
    begin
      rollback;
      fp_message := 'No data found ' || fp_message;
      write_log(3);
      output_table;
    end;
  when others then
    begin
      rollback;
      fp_message := 'Error others fp_idcode ' || fp_primaryid ||
                    ' fp_plantcode ' || fp_plantcode || ' ' || sqlerrm;
      write_log(3);
      output_table;
    end;
end sp_getgarmentdetails;
/
create or replace procedure sp_sendtrackinfo(idcode       in uniqueitem.primaryid%type,
                                             unitcode     in out plant.code%type,
                                             datep        in number, --format YYYYMMDD
                                             timep        in varchar2, --number 'HH24MISS' 091313, or 131313
                                             locationcode in varchar2,
                                             statusout    in out number) is
  --procedure sp_sendtrackinfo version 1.3
  --flags and other paremeter just not used
  --31-08-2021  ABS-123927 store cleandate in uniqueitemroute
  --07-10-2021  ABS-123927 added checkpoint scan as well to
  --15-11-2021  ABS-127284 JSG Scanola interface timestamps

   lv_datep        number;
   lv_timep        varchar2(8);
begin
  if datep is not null then
     lv_datep :=  datep;
  else
     select to_number(to_char(sysdate, 'YYYYMMDD')) into lv_datep from dual;
  end if;
  if timep is not null then
    lv_timep := timep;
   else
     select to_char(sysdate, 'HH24MISS') into lv_timep from dual;
  end if;
  sendtrackinfo(idcode, unitcode, lv_datep, lv_timep,
                locationcode, null, null, null, null, null, 0, 0, 0, null, statusout);
end sp_sendtrackinfo;
/
create or replace procedure SqlScriptInsert(
			FPscriptName varchar2
) is
begin
	begin
	  insert into sqlscript (scriptname, issuccessful, createddate)
		values (FPscriptName, 'N', sysdate);
	exception when dup_val_on_index then
  	update sqlscript
			set issuccessful = 'N', modifieddate = sysdate
			where scriptname = FPscriptName;
	end;
	commit;
end SqlScriptInsert;
/
create or replace procedure SqlScriptUpdate(
			FPscriptName varchar2
) is
begin
	update sqlscript set issuccessful = 'Y' where scriptname = FPscriptName;
	commit;
end SqlScriptUpdate;
/
create or replace procedure TestGetGarmentData(

--pool      in integer,
maxrun       in integer--,

) is


cnt          integer;
plantcode                         plant.code%type;
UnitCode                          BUSINESSUNIT.CODE%type;
Status                            Integer;
FinishSelection                   Varchar2(6);--(6);
CheckpointSelection               Varchar2(6);--(6);
RepairSelection                   Varchar2(6);--(6);
Destination                       Varchar2(6);--(6);
FoldProgram                       Varchar2(6);--(6);
StackChangeInfo                   Varchar2(60);--(60);
RouteNumber                       ROUTE.ROUTENUMBER%type;
RouteDay                          ROUTE.DRIVINGDAY_ID%type;
Depotx                             DEPOT.CODE%type;
SortString                        Varchar2(100);
AlternateSortString               Varchar2(100);
StopNumber                        ROUTESTOP.STOPNUMBER%type;
CustomerNumber                    CUSTOMER.CUSTOMERNUMBER%type;
CustomerName                      CUSTOMER.NAME%type;
WearerNumber                      WEARER.WEARERNUMBER%type;
WearerName                        WEARER.SEARCHNAME%type;
BankLocker                        Varchar2(16);
Departmentx                        DEPARTMENT.DEPARTMENTNUMBER%type;
CustomerEmployeeNumber            WEARER.CUSTOMEREMPLOYEENUMBER%type;
Gender                            WEARER.SEX%type;
GarmentDispenserCode              GARMENTDISPENSER.CODE%type;
DeliveryPointCode                 DELIVERYPOINT.CODE%type;
ProductCode                       PRODUCT.CODE%type;
ProductDescription                PRODUCT_DESC.DESCRIPTION%type;
SizeCode                          SIZEDEFINITION.CODE%type;
ProductPictureCode                IMAGE.CODE%type;
DeliveryDayMask                   Varchar2(7);
SecondaryID                       SECONDARYUNIQUEITEM.SECONDARYID%type;
FlagCode1                         SORTADDRESSPERFLAG.SORTADDRESS%type;
FlagCode2                         SORTADDRESSPERFLAG.SORTADDRESS%type;
FlagCode3                         SORTADDRESSPERFLAG.SORTADDRESS%type;
FlagCode4                         SORTADDRESSPERFLAG.SORTADDRESS%type;
FlagDescription1                  FLAG_DESC.DESCRIPTION%type;
FlagDescription2                  FLAG_DESC.DESCRIPTION%type;
FlagDescription3                  FLAG_DESC.DESCRIPTION%type;
FlagDescription4                  FLAG_DESC.DESCRIPTION%type;
Infotext                          WEARER.REMARK%type;
RequiredRepairs                   Varchar2(12);
Spare1                            Varchar2(10);
Spare2                            Varchar2(10);
SQLfile                          utl_file.file_type;
UTLDIR                           varchar2 (20) := 'D:\output';-- d:\output\ D:\out_put\testgarment.txt -- please see ABS-92804 variable needs the name of an existing oracle directory
FPsFilename                      varchar2(20):= 'getgarmentdata.txt';
x      timestamp;
y      timestamp;
z      interval day to second;
x1     timestamp;
y1     timestamp;
z1     interval day to second;
staycode stay.staynr%type;
sortbatchnumber           sortbatch.batchnumber%type;
alphaspare1 Varchar2(10);
alphaspare2 Varchar2(10);
alphaspare3 Varchar2(10);
alphaspare4 Varchar2(10);
alphaspare5 Varchar2(10);
numberspare1 Number;
numberspare2 Number;
numberspare3 Number;
numberspare4 Number;
numberspare5 Number;
begin
cnt:=0;
 x:=current_timestamp;
SqlFile := UTL_FILE.FOPEN(UTLDIR, FPsFilename, 'w');
  for vCursor in ( select u.uniqueitem_id, u.primaryid, u.poolitem from uniqueitem u
                   where u.uniqueitem_id=round(u.uniqueitem_id / 100) *100
                   --where --u.poolitem=pool
                   --and
                   --u.uniqueitem_id>UI
                   )loop
                   begin
                   cnt:=cnt+1;
                  -- dbms_output.put_line('start'||' '||cnt||' '||vcursor.primaryID||' '||current_timestamp);
 --                  utl_file.put_line(SQLfile,'start'||' '||cnt||' '||vcursor.primaryID||' '||vcursor.uniqueitem_ID||' '||current_timestamp);
                   x1:=current_timestamp;
                  /* getgarmentdata(vCursor.primaryid ,PlantCode,UnitCode ,Status ,FinishSelection ,CheckpointSelection ,
                   RepairSelection,Destination,FoldProgram,StackChangeInfo,RouteNumber,RouteDay,Depotx,SortString,AlternateSortString,
                   StopNumber,CustomerNumber,CustomerName,WearerNumber,WearerName,BankLocker,Departmentx,CustomerEmployeeNumber,
                   Gender,GarmentDispenserCode,DeliveryPointCode,ProductCode,ProductDescription,SizeCode,ProductPictureCode,DeliveryDayMask,
                   SecondaryID,FlagCode1,FlagCode2,FlagCode3,FlagCode4,FlagDescription1,FlagDescription2,FlagDescription3,FlagDescription4,
                   Infotext,RequiredRepairs,Spare1,Spare2);*/
                   getgarmentdatasortbatch(vCursor.primaryid,
                          plantcode,
                          unitcode,
                          status,
                          finishselection,
                          checkpointselection,
                          repairselection,
                          destination,
                          foldprogram,
                          stackchangeinfo,
                          routenumber,
                          routeday,
                          depotx,
                          sortstring,
                          alternatesortstring,
                          stopnumber,
                          customernumber,
                          customername,
                          wearernumber,
                          wearername,
                          banklocker,
                          departmentx,
                          customeremployeenumber,
                          gender,
                          garmentdispensercode,
                          deliverypointcode,
                          productcode,
                          productdescription,
                          sizecode,
                          productpicturecode,
                          deliverydaymask,
                          secondaryid,
                          flagcode1,
                          flagcode2,
                          flagcode3,
                          flagcode4,
                          flagdescription1,
                          flagdescription2,
                          flagdescription3,
                          flagdescription4,
                          infotext,
                          staycode,
                          sortbatchnumber,
                          alphaspare1,
                          alphaspare2,
                          alphaspare3,
                          alphaspare4,
                          alphaspare5,
                          numberspare1,
                          numberspare2,
                          numberspare3,
                          numberspare4,
                          numberspare5);
                   y1:= current_timestamp;
                   z1:= y1 - x1;
                   utl_file.put_line(SQLfile,'PlantCode'||PlantCode||'Status '||Status||' '||vcursor.primaryID||' '||vcursor.poolitem||' '||RouteNumber||' '||RouteDay||' '||
                   CustomerNumber||' '||SortString||'total time:'||z1);
                   exit when cnt=maxrun;
                   end;
                   end loop;
  y:= current_timestamp;
  z:= y - x;
  utl_file.put_line(SQLfile,'stop'||'total time:'||z);
 UTL_FILE.FCLOSE(SqlFile);
 dbms_output.put_line('OK');
end TestGetGarmentData;
/
create or replace procedure TestGetGarmentDataSortBach(

                                                       --pool      in integer,
                                                       maxrun in integer --,

                                                       ) is

  cnt                    integer;
  plantcode              plant.code%type;
  UnitCode               BUSINESSUNIT.CODE%type;
  Status                 Integer;
  FinishSelection        Varchar2(6); --(6);
  CheckpointSelection    Varchar2(6); --(6);
  RepairSelection        Varchar2(6); --(6);
  Destination            Varchar2(6); --(6);
  FoldProgram            Varchar2(6); --(6);
  StackChangeInfo        Varchar2(60); --(60);
  RouteNumber            ROUTE.ROUTENUMBER%type;
  RouteDay               ROUTE.DRIVINGDAY_ID%type;
  Depotx                 DEPOT.CODE%type;
  SortString             Varchar2(100);
  AlternateSortString    Varchar2(100);
  StopNumber             ROUTESTOP.STOPNUMBER%type;
  CustomerNumber         CUSTOMER.CUSTOMERNUMBER%type;
  CustomerName           CUSTOMER.NAME%type;
  WearerNumber           WEARER.WEARERNUMBER%type;
  WearerName             WEARER.SEARCHNAME%type;
  BankLocker             Varchar2(16);
  Departmentx            DEPARTMENT.DEPARTMENTNUMBER%type;
  CustomerEmployeeNumber WEARER.CUSTOMEREMPLOYEENUMBER%type;
  Gender                 WEARER.SEX%type;
  GarmentDispenserCode   GARMENTDISPENSER.CODE%type;
  DeliveryPointCode      DELIVERYPOINT.CODE%type;
  ProductCode            PRODUCT.CODE%type;
  ProductDescription     PRODUCT_DESC.DESCRIPTION%type;
  SizeCode               SIZEDEFINITION.CODE%type;
  ProductPictureCode     IMAGE.CODE%type;
  DeliveryDayMask        Varchar2(7);
  SecondaryID            SECONDARYUNIQUEITEM.SECONDARYID%type;
  FlagCode1              SORTADDRESSPERFLAG.SORTADDRESS%type;
  FlagCode2              SORTADDRESSPERFLAG.SORTADDRESS%type;
  FlagCode3              SORTADDRESSPERFLAG.SORTADDRESS%type;
  FlagCode4              SORTADDRESSPERFLAG.SORTADDRESS%type;
  FlagDescription1       FLAG_DESC.DESCRIPTION%type;
  FlagDescription2       FLAG_DESC.DESCRIPTION%type;
  FlagDescription3       FLAG_DESC.DESCRIPTION%type;
  FlagDescription4       FLAG_DESC.DESCRIPTION%type;
  Infotext               WEARER.REMARK%type;
  SQLfile                utl_file.file_type;
  UTLDIR                 varchar2(20) := 'D:\output'; -- d:\output\ D:\out_put\testgarment.txt -- please see ABS-92804 variable needs the name of an existing oracle directory
  FPsFilename            varchar2(20) := 'getgarmentdata.txt';
  x                      timestamp;
  y                      timestamp;
  z                      interval day to second;
  x1                     timestamp;
  y1                     timestamp;
  z1                     interval day to second;
  staycode               stay.staynr%type;
  sortbatchnumber        sortbatch.batchnumber%type;
  alphaspare1            Varchar2(10);
  alphaspare2            Varchar2(10);
  alphaspare3            Varchar2(10);
  alphaspare4            Varchar2(10);
  alphaspare5            Varchar2(10);
  numberspare1           Number;
  numberspare2           Number;
  numberspare3           Number;
  numberspare4           Number;
  numberspare5           Number;
begin
  cnt     := 0;
  x       := current_timestamp;
  SqlFile := UTL_FILE.FOPEN(UTLDIR, FPsFilename, 'w');
  for vCursor in (select u.uniqueitem_id, u.primaryid, u.poolitem
                    from uniqueitem u
                   where u.uniqueitem_id =
                         round(u.uniqueitem_id / 100) * 100) loop
    begin
      cnt := cnt + 1;
      x1  := current_timestamp;
      getgarmentdatasortbatch(vCursor.primaryid,
                              plantcode,
                              unitcode,
                              status,
                              finishselection,
                              checkpointselection,
                              repairselection,
                              destination,
                              foldprogram,
                              stackchangeinfo,
                              routenumber,
                              routeday,
                              depotx,
                              sortstring,
                              alternatesortstring,
                              stopnumber,
                              customernumber,
                              customername,
                              wearernumber,
                              wearername,
                              banklocker,
                              departmentx,
                              customeremployeenumber,
                              gender,
                              garmentdispensercode,
                              deliverypointcode,
                              productcode,
                              productdescription,
                              sizecode,
                              productpicturecode,
                              deliverydaymask,
                              secondaryid,
                              flagcode1,
                              flagcode2,
                              flagcode3,
                              flagcode4,
                              flagdescription1,
                              flagdescription2,
                              flagdescription3,
                              flagdescription4,
                              infotext,
                              staycode,
                              sortbatchnumber,
                              alphaspare1,
                              alphaspare2,
                              alphaspare3,
                              alphaspare4,
                              alphaspare5,
                              numberspare1,
                              numberspare2,
                              numberspare3,
                              numberspare4,
                              numberspare5);
      y1 := current_timestamp;
      z1 := y1 - x1;
      utl_file.put_line(SQLfile,
                        'PlantCode' || PlantCode || 'Status ' || Status || ' ' ||
                        vcursor.primaryID || ' ' || vcursor.poolitem || ' ' ||
                        RouteNumber || ' ' || RouteDay || ' ' ||
                        CustomerNumber || ' ' || SortString ||
                        'total time:' || z1);
      exit when cnt = maxrun;
    end;
  end loop;
  y := current_timestamp;
  z := y - x;
  utl_file.put_line(SQLfile, 'stop' || 'total time:' || z);
  UTL_FILE.FCLOSE(SqlFile);
  dbms_output.put_line('OK');
end TestGetGarmentDataSortBach;
/
create or replace procedure undstransfersoil(customerid               in integer,
                                             productid                in number,
                                             sizedefinitionid         in number,
                                             finishingmethodid        in number,
                                             distributionpointid      in number,
                                             deliverypointid          in number,
                                             plpcid                   in number,
                                             plpdid                   in number,
                                             delayedevenexchangevalue in number,
                                             deedeliveryschemeid      in number,
                                             typeofmerchandisevalue   in number,
                                             lightframecount          in number,
                                             keypadcount              in number,
                                             abusedcount              in number,
                                             systemuserid             in number,
                                             currentdate              in number,
                                             currenttime              in varchar2,
                                             status                   in out integer) is
  -- Updated : 30-09-2020 DLA ABS-108518 Delivery variations processbusinessunit_id and internalprocessingbu_id are not filled when creating DV from Pack_multiread

  -- LOCAL VARIABLES
  processbuid number(28, 0);
  plantid     number(28, 0);
  debuglevel  varchar2(100);
  plantcode   varchar2(6);
  soilcountid          number(28, 0);
  deliveryvariationsid number(28, 0);
  vdeliverydate        date;
  lastinroute          route.route_id%type;
  routestopin          routestop.routestop_id%type;
  lastindate           date;
  amount               number(28, 6); --deliveryvariations
  recordonsiteinv      varchar2(10);
  routestopid   routestop.routestop_id%type;
  plannedroute  route.route_id%type;
  scanbyroute   varchar2(1);
  mycurrentdate date;
  logsource     varchar2(30);
  customernumber customer.customernumber%type;
  productcode   product.code%type;
begin
  mycurrentdate := to_timestamp(to_char(currentdate) || to_char(currenttime), 'YYYYMMDDHH24MISS');
  status        := 0;
  logsource     := 'Transfer Soil';
  begin
    select c.defaultbusinessunit_id, c.customernumber
    into   processbuid, customernumber
    from   customer c
    where  c.customer_id = customerid;
    select bu.plant_id into plantid from businessunit bu where bu.businessunit_id = processbuid;
    select p.code into plantcode from plant p where p.plant_id = plantid;
    select pr.code into productcode from product pr where pr.product_id=productid;
    begin
      select s.value
      into   debuglevel
      from   systemsetting s
      where  s.name = 'DEBUG_LEVEL'
      and    s.plant_id = plantid;
    exception
      when no_data_found then
        debuglevel := 0;
    end;
    -- SOILCOUNT
    if status = 0 then
      begin
        select s.soilcount_id
        into   soilcountid
        from   soilcount s
        where  s.distributionpoint_link_id = distributionpointid
        and    s.processbusinessunit_id = processbuid
        and    s.countdate = trunc(mycurrentdate);
        update soilcount s
        set    s.systemuser_id = systemuserid, s.timestamp = sysdate
        where  s.soilcount_id = soilcountid;
        if soilcountid is not null and debuglevel > 0 then
          abslogwrite.abslog_write(5, logsource, plantid, 5,
                                   'Update soilcount for product/customer ' || productcode || '/' ||
                                    customernumber, systemuserid);
        end if;
      exception
        when no_data_found then
          insert into soilcount
            (soilcount_id, distributionpoint_link_id, processbusinessunit_id, countdate,
             systemuser_id, timestamp)
          values
            (seq_soilcount.nextval, distributionpointid, processbuid, trunc(mycurrentdate),
             systemuserid, sysdate);
          if debuglevel > 0 then
            abslogwrite.abslog_write(5, logsource, plantid, 5,
                                     'Insert soilcount for product/customer ' || productcode || '/' ||
                                      customernumber, systemuserid);
          end if;
      end;

      begin
        if soilcountid is not null then
          begin
            insert into soilcountline
              (soilcountline_id, soilcount_id, product_link_id, sizedefinition_link_id,
               finishingmethod_id, countconverted, countkeypad, countlightframe, countabused,
               soilweight, delayevenexchange, unrelatedloan, systemuser_id, timestamp)
            values
              (seq_soilcountline.nextval, soilcountid, productid, sizedefinitionid,
               finishingmethodid, null, keypadcount, lightframecount, abusedcount, 0,
               delayedevenexchangevalue, 'N', systemuserid, sysdate);
            if debuglevel > 0 then
              abslogwrite.abslog_write(5, logsource, plantid, 5,
                                       'Insert soilcountline for product/customer ' || productcode || '/' ||
                                        customernumber, systemuserid);
            end if;
          exception
            when dup_val_on_index then
              update soilcountline
              set    countlightframe = nvl(countlightframe, 0) + lightframecount,
                     countkeypad = nvl(countkeypad, 0) + keypadcount,
                     countabused = nvl(countabused, 0) + abusedcount, systemuser_id = systemuserid,
                     timestamp = mycurrentdate
              where  soilcount_id = soilcountid
              and    product_link_id = productid
              and    sizedefinition_link_id = sizedefinitionid
              and    finishingmethod_id = finishingmethodid;
              if debuglevel > 0 then
                abslogwrite.abslog_write(5, logsource, plantid, 5,
                                         'Update soilcountline for product/customer' || productcode || '/' ||
                                          customernumber,  systemuserid);
              end if;
            when others then
              status := 1;
              abslogwrite.abslog_write(5, logsource, plantid, 3,
                                         'Error A for customer/product ' || customernumber || '/' ||
                                          productcode || ' ' || sqlcode || ' ' || SQLERRM,
                                         systemuserid);
          end;
        else
          insert into soilcountline
            (soilcountline_id, soilcount_id, product_link_id, sizedefinition_link_id,
             finishingmethod_id, countconverted, countkeypad, countlightframe, countabused,
             soilweight, delayevenexchange, unrelatedloan, systemuser_id, timestamp)
          values
            (seq_soilcountline.nextval, seq_soilcount.currval, productid, sizedefinitionid,
             finishingmethodid, null, keypadcount, lightframecount, abusedcount, 0,
             delayedevenexchangevalue, 'N', systemuserid, sysdate);
          if debuglevel > 0 then
            abslogwrite.abslog_write(5, logsource, plantid, 5,
                                     'Insert soilcountline for product/customer ' || productcode || '/' ||
                                      customernumber,  systemuserid);
          end if;
        end if;
      exception
        when others then
          status := 2;
          abslogwrite.abslog_write(5, logsource, plantid, 3,
                                     'Error B for customer/product ' || customernumber || '/' ||
                                      productcode || ' ' || sqlcode || ' ' || SQLERRM,
                                     systemuserid);
      end;
    end if;
    -- SOILHISTORY
    if status = 0 then
      begin
        insert into soilhistory
          (soilhistory_id, customer_link_id, product_link_id, sizedefinition_link_id,
           processbusinessunit_id, quantityabused, quantitysoil, daynumber, week, year,
           receivingdate, systemuser_id, timestamp, distributionpoint_link_id, invoiceheader_id,
           invoicebusinessunit_id)
        values
          (seq_soilhistory.nextval, customerid, productid, sizedefinitionid, processbuid,
           abusedcount, (keypadcount + lightframecount), getabsdaynumber(mycurrentdate),
           getisoweek(mycurrentdate), getyearofweek(mycurrentdate), trunc(mycurrentdate),
           systemuserid, sysdate, distributionpointid, null, processbuid);
        if debuglevel > 0 then
          abslogwrite.abslog_write(5, logsource, plantid, 5,
                                   'Insert soilhistory for product/customer ' || productcode || '/' ||
                                    customernumber, systemuserid);
        end if;
      exception
        when dup_val_on_index then
          update soilhistory
          set    quantitysoil = nvl(quantitysoil, 0) + (keypadcount + lightframecount),
                 quantityabused = nvl(quantityabused, 0) + abusedcount, systemuser_id = systemuserid,
                 timestamp = mycurrentdate
          where  customer_link_id = customerid
          and    product_link_id = productid
          and    sizedefinition_link_id = sizedefinitionid
          and    processbusinessunit_id = processbuid
          and    distributionpoint_link_id = distributionpointid
          and    receivingdate = trunc(mycurrentdate);
          if debuglevel > 0 then
            abslogwrite.abslog_write(5, logsource, plantid, 5,
                                     'Update soilhistory for product/customer ' || productcode || '/' ||
                                      customernumber, systemuserid);
          end if;
        when others then
          status := 3;
          abslogwrite.abslog_write(5, logsource, plantid, 3,
                                     'Error C for customer/product ' || customernumber || '/' ||
                                      productcode || ' ' || sqlcode || ' ' || SQLERRM,
                                     systemuserid);
      end;
    end if;
    -- DELIVERY VARIATIONS
    if status = 0 then
      pack_sort.getlastinroute(customerid, mycurrentdate, deliverypointid, typeofmerchandisevalue,
                               lastinroute, routestopin, lastindate);
      pack_sort.fillplannedoutroute(plantid, mycurrentdate, typeofmerchandisevalue,
                                    delayedevenexchangevalue,
                                     deedeliveryschemeid, plpcid, customerid, deliverypointid,
                                    lastinroute, lastindate, routestopin, routestopid, plannedroute,
                                    vdeliverydate,
                                    scanbyroute);
      if vdeliverydate is null then
        vdeliverydate := mycurrentdate + 7;
      end if;
      -- SOILCOUNT
      if delayedevenexchangevalue > 0 then
        begin
          select deliveryvariations_id, amount
          into   deliveryvariationsid, amount
          from   deliveryvariations
          where  product_id = productid
          and    sizedefinition_id = sizedefinitionid
          and    finishingmethod_id = finishingmethodid
          and    packingnote_id is null
          and    processed = 'N'
          and    causenote_id is null
          and    updaterentqty = 'N'
          and    origin = 1
          and    trunc(deliverydate) = trunc(vdeliverydate)
          and    distributionpoint_id = distributionpointid;
          update deliveryvariations
          set    amount = nvl(amount, 0) + (keypadcount + lightframecount + abusedcount),
                 systemuser_id = systemuserid, timestamp = sysdate
          where  deliveryvariations.deliveryvariations_id = deliveryvariationsid;
          if debuglevel > 0 then
            abslogwrite.abslog_write(5, logsource, plantid, 5,
                                     'Update deliveryvariations for customer/product ' ||
                                      customernumber || '/' || productcode,  systemuserid);
          end if;
        exception
          when no_data_found then
            insert into deliveryvariations
              (deliveryvariations_id, product_id, packingnote_id, causenote_id, deliverydate,
               origin, amount, finishingmethod_id, fixedamount, distributionpoint_id,
               sizedefinition_id, reference, systemuser_id, processed, timestamp, updaterentqty,
               adjustmentreason_id, processbusinessunit_id, internalprocessingbu_id)
            values
              (seq_deliveryvariations.nextval, productid, null, null, vdeliverydate, 1,
               (keypadcount + lightframecount + abusedcount), finishingmethodid, 'N',
               distributionpointid, sizedefinitionid, null, systemuserid, 'N', sysdate, 'N', null, processbuid, processbuid);
            if debuglevel > 0 then
              abslogwrite.abslog_write(5, logsource, plantid, 5,
                                       'Insert deliveryvariations for product ' || productcode,
                                       systemuserid);
            end if;
          when others then
            status := 4;
            abslogwrite.abslog_write(5, logsource, plantid, 3,
                                       'Error D for customer/product ' || customernumber || '/' ||
                                        productcode || ' ' || sqlcode || ' ' || SQLERRM,
                                       systemuserid);
        end;
      end if; --delayedevenexchangeVALUE > 0
      -- REPLACEMENT
      if abusedcount > 0 then
        begin
          if delayedevenexchangevalue = 0 then
            vdeliverydate := sysdate;
          end if;
          select deliveryvariations_id, amount
          into   deliveryvariationsid, amount
          from   deliveryvariations
          where  product_id = productid
          and    sizedefinition_id = sizedefinitionid
          and    finishingmethod_id = finishingmethodid
          and    packingnote_id is null
          and    processed = 'N'
          and    causenote_id is null
          and    updaterentqty = 'N'
          and    origin = 7
          and    trunc(deliverydate) = trunc(vdeliverydate)
          and    distributionpoint_id = distributionpointid;
          update deliveryvariations
          set    amount = nvl(amount, 0) + (abusedcount), systemuser_id = systemuserid,
                 timestamp = sysdate
          where  deliveryvariations.deliveryvariations_id = deliveryvariationsid;
          if debuglevel > 0 then
            abslogwrite.abslog_write(5, logsource, plantid, 5,
                                     'Update deliveryvariations for product ' || productcode,
                                     systemuserid);
          end if;
        exception
          when no_data_found then
            insert into deliveryvariations
              (deliveryvariations_id, product_id, packingnote_id, causenote_id, deliverydate,
               origin, amount, finishingmethod_id, fixedamount, distributionpoint_id,
               sizedefinition_id, reference, systemuser_id, processed, timestamp, updaterentqty,
               adjustmentreason_id, processbusinessunit_id, internalprocessingbu_id)
            values
              (seq_deliveryvariations.nextval, productid, null, null, vdeliverydate, 7,
               (abusedcount), finishingmethodid, 'N', distributionpointid, sizedefinitionid, null,
               systemuserid, 'N', sysdate, 'N', null, processbuid, processbuid);
            if debuglevel > 0 then
              abslogwrite.abslog_write(5, logsource, plantid, 5,
                                       'Insert deliveryvariations for product ' || productcode,
                                       systemuserid);
            end if;
          when others then
            status := 5;
            abslogwrite.abslog_write(5, logsource, plantid, 3,
                                       'Error E for customer/product ' || customernumber || '/' ||
                                        productcode || ' ' || sqlcode || ' ' || SQLERRM,
                                       systemuserid);
        end;
      end if; -- abusedcount > 0
    end if; --for status = 0

    --ONSITEINVENTORYADJUSTMENT
    if status = 0 then
      begin
        select value
        into   recordonsiteinv
        from   systemsetting
        where  name = 'RECORDONSITEINVENTORY'
        and    plant_id = plantid;
        if recordonsiteinv = 'Y' and status = 0 then
          begin
            insert into onsiteinventoryadjustment
              (onsiteinventoryadjustment_id, productlistperdistribpoint_id, origin, inventorydate,
               quantity, reference, systemuser_id, timestamp)
            values
              (seq_onsiteinventoryadjustment.nextval, plpdid, 4, trunc(mycurrentdate),
               (keypadcount + lightframecount + abusedcount) * (-1), 'und', systemuserid, sysdate);
            if debuglevel > 0 then
              abslogwrite.abslog_write(5, logsource, plantid, 5,
                                       'Insert onsiteinventoryadjustment for productcode ' ||
                                        productcode, systemuserid);
            end if;
          exception
            when dup_val_on_index then
              update onsiteinventoryadjustment
              set    quantity = nvl(quantity, 0) +
                                 (-1) * (keypadcount + lightframecount + abusedcount),
                     systemuser_id = systemuserid, timestamp = sysdate
              where  --ONSITEINVENTORYADJUSTMENT_ID = --onsiteinventoryadjustmentid;
               productlistperdistribpoint_id = plpdid
               and    origin = 4
               and    inventorydate = trunc(mycurrentdate);
              if debuglevel > 0 then
                abslogwrite.abslog_write(5, logsource, plantid, 5,
                                         'Update onsiteinventoryadjustment for productcode ' ||
                                          productcode, systemuserid);
              end if;
            when others then
              status := 6;
              abslogwrite.abslog_write(5, logsource, plantid, 3,
                                         'Error F for customer/product ' || customernumber || '/' ||
                                          productcode || ' ' || sqlcode || ' ' || sqlerrm,
                                         systemuserid);
          end; --FOR UPDATE/INSERT ONSITEINVENTORY
        end if;
      exception
        when others then
          status := 7;
          abslogwrite.abslog_write(5, logsource, plantid, 3,
                                     'Error G for customer/product ' || customernumber || '/' ||
                                      productcode || ' ' || sqlcode || ' ' || sqlerrm,
                                     systemuserid);
      end;
    end if;
  exception
    when others then
      status := 8;
      abslogwrite.abslog_write(5, logsource, plantid, 3,
                                 'Error H for customer/product ' || customernumber || '/' ||
                                  productcode || ' ' || sqlcode || ' ' || sqlerrm, systemuserid);
  end;

  if status = 0 then
    commit;
  else
    rollback;
  end if;
end undstransfersoil;
/
create or replace procedure UpdateDeliveryVariationsLLG(plantProcessId in Plantprocess.Plantprocess_Id%type) is
  vDistributionpointid   deliveryvariations.distributionpoint_id%type;
  vdeliverydateTemp      deliveryvariations.deliverydate%type;
  vDeliverydate2         routecontrol.drivingdate%type;
  vsystemuserid          systemuser.systemuser_id%type;
  vStep                  number;
  vReference             deliveryvariations.reference%type;
  nr                    number;

 cursor cSystemuser is
    select sys.systemuser_id
    from systemuser sys
     where sys.username = 'ABSADM';

 cursor cDeliveryVariations is
    select dv.deliveryvariations_id, dv.distributionpoint_id, dv.deliverydate
    from deliveryvariations dv, soilcount sc, soilcountline scl, plantprocess pl, businessunit bu
     where dv.distributionpoint_id = sc.distributionpoint_link_id
     and sc.soilcount_id = scl.soilcount_id
     and scl.product_link_id = dv.product_id
     and scl.sizedefinition_link_id = dv.sizedefinition_id
     and scl.finishingmethod_id = dv.finishingmethod_id
     and dv.soilcountdate = sc.countdate
     and sc.processbusinessunit_id = bu.businessunit_id
     and bu.plant_id = pl.plant_id
     and pl.plantprocess_id = plantProcessId
     and dv.origin = 1
     and nvl(dv.packingnote_id, 0) = 0
     and dv.processed = 'N'
     order by dv.distributionpoint_id, dv.deliverydate;

 cursor cStops(c_distributionpointid in deliveryvariations.distributionpoint_id%type, c_deliverydate1 in deliveryvariations.deliverydate%type) is
    select
   (select distinct rc1.drivingdate from stop s1, routecontrol rc1 where rc1.routecontrol_id = s1.routecontrol_id and s1.movedtostop_id = s.stop_id)
   from routecontrol rc, stop s, distributionpoint dp, department dt
   where rc.routecontrol_id  = s.routecontrol_id
   and s.customer_link_id = dt.customer_id
   and dt.department_id = dp.department_id
   and s.status = 3
   and dp.distributionpoint_id = c_distributionpointid
   and rc.drivingdate = c_deliverydate1;

   begin
     open cSystemuser;
     fetch cSystemuser into vsystemuserid;
     close cSystemuser;
     vStep := 1;
    for deliveryvariations_rec in cDeliveryVariations
    loop
     if( vStep = 1 or vDistributionpointid <> deliveryvariations_rec.distributionpoint_id or vdeliverydateTemp <> deliveryvariations_rec.deliverydate) then
       vStep := 2;
       vDistributionpointid := deliveryvariations_rec.distributionpoint_id;
       vdeliverydateTemp := deliveryvariations_rec.deliverydate;
       vDeliverydate2 := null;
       open cStops(vDistributionpointid, vdeliverydateTemp);
            fetch cStops into vDeliverydate2;
       close cStops;
     end if;
     if(vDeliverydate2 is not null) then
      begin
        update deliveryvariations dv
        set dv.deliverydate = vDeliverydate2 ,
        dv.systemuser_id = vsystemuserid,
        dv.timestamp = sysdate
        where dv.deliveryvariations_id = deliveryvariations_rec.deliveryvariations_id;
      exception
      when DUP_VAL_ON_INDEX then
       begin
         execute immediate
            'select dvv.reference from deliveryvariations dvv where dvv.deliveryvariations_id =: dvID' into vReference
            using deliveryvariations_rec.deliveryvariations_id;
            if length(vReference) = 15 then
             vReference := substr(rtrim(vReference, '.'), 1, length(rtrim(vReference, '.')) - 1) || '.' || substr(vReference, length(rtrim(vReference, '.')) + 1);
            else
              begin
                nr := 3;
                if(nr > 15 - length(vReference)) then
                      nr := 15 - length(vReference);
                end if;
              vReference := Rpad(vReference, length(vReference) + nr, '.');
              end;
            end if;
           begin
            update deliveryvariations dv
            set dv.deliverydate = vDeliverydate2 ,
            dv.systemuser_id = vsystemuserid,
            dv.reference = vReference,
            dv.timestamp = sysdate
            where dv.deliveryvariations_id = deliveryvariations_rec.deliveryvariations_id;
          exception
             when others then
                dbms_output.enable();
                dbms_output.put_line(SQLERRM );
              end;
          end;
      when others then
        dbms_output.enable();
        dbms_output.put_line(SQLERRM );
      end;

     end if;
    end loop;

 commit;
end UpdateDeliveryVariationsLLG;
/
create or replace procedure update_initialissued (p_workorder_id workorder.workorder_id%type)
AS
pragma autonomous_transaction;
BEGIN
  UPDATE WORKORDERLINE WOL SET WOL.INITIALISSUED = WOL.QUANTITYFILLED
  WHERE WOL.WORKORDER_ID = p_workorder_id;
  COMMIT;
END update_initialissued;
/
create or replace procedure update_overflow_locations(fp_productid         in product.product_id%type,
                                                      fp_defaultsupplierid in supplier.supplier_id%type,
                                                      fp_sizeid            in sizedefinition.sizedefinition_id%type) is
  gv_defaultuserid systemuser.systemuser_id%type := 0;
  gv_message       abslog.message%type;

  procedure write_log is
  begin
    -- Logging: write message in ABSLOG with errors only, 3 = Error
    abslogwrite.abslog_write(5, 'update_overflow_locations', null, 3, gv_message || ' ' || sqlerrm,
                             gv_defaultuserid);
  end write_log;

begin
  --only call this procedure for products with product.recordpassivestock = 'Y'  !!
  for x in (select sl.stockroomlocation_id from stockroomlocation sl where sl.overflowlocation = 'Y') loop
    begin
      --add_product_stockroom passive/overflow stockroom
      gv_message := 'add product id ' || fp_productid || ' to overflow stocklocation_id ' ||
                    x.stockroomlocation_id;
      add_product_stockroom(x.stockroomlocation_id, fp_productid, 'N', null, 'B',
                            case when fp_sizeid is null then 'N' else 'Y' end, fp_sizeid,
                            fp_defaultsupplierid);
    end;
  end loop; --x
exception
  when others then
    begin
      write_log;
    end;
end update_overflow_locations;
/
create or replace PROCEDURE update_stocktransdocinfo IS
  --cursors
  CURSOR stocktrans IS
    SELECT st.stocktransaction_id
      FROM stocktransaction st
     WHERE st.documentnumber = 0
       AND st.transactiontype_id <> 99;

  CURSOR stocktransact(stocktrans_id stocktransaction.stocktransaction_id%TYPE) IS
    SELECT st.stocktransaction_id, st.transactiontype_id
      FROM stocktransaction st
     WHERE st.stocktransaction_id = stocktrans_id
       AND st.documentnumber = 0
       AND st.transactiontype_id <> 99;

  --variables
  stockevalmethod stocktransaction.stockvaluationmethod%TYPE;
  priceeval0      NUMBER;
  priceeval1      NUMBER;
  priceeval2      NUMBER;
  priceeval3      NUMBER;
  docnrintext     NUMBER;
  potype          NUMBER;
  docnrwo         workorder.workordernumber%TYPE;
  woorigin        workorder.origin%TYPE;
  docnopn         packingnote.notenumber%TYPE;
  status          NUMBER;
  -- utl_file
  dir      VARCHAR2(60);
  filename VARCHAR2(60);
  file     utl_file.file_type;

BEGIN
  dir      := 'D:\LCO\';
  filename := 'stocktransdocinfo.txt';
  status   := 1; --ok
  -- open the file
  IF NOT utl_file.is_open(file) THEN
    file := utl_file.fopen(dir, filename, 'a');
  END IF;

  FOR str IN stocktrans LOOP
    status := 1; --ok
    -- update StockValuationMethod
    SELECT q.stockvaluationmethod
      INTO stockevalmethod
      FROM stockreservationpergrade srg,
           qualitygrade             q,
           stocktransaction         st
     WHERE srg.qualitygrade_id = q.qualitygrade_id
       AND srg.stockreservationpergrade_id = st.stockreservationpergrade_id
       AND st.stocktransaction_id = str.stocktransaction_id;

    FOR strt IN stocktransact(str.stocktransaction_id) LOOP

      UPDATE stocktransaction st
         SET st.stockvaluationmethod = stockevalmethod
       WHERE st.stocktransaction_id = strt.stocktransaction_id;

      -- update CalculationPrice
      -- price for StockValuationMethod 0 (Standard)
      BEGIN
        IF stockevalmethod = 0 THEN
          BEGIN
            SELECT f_purchaseprice(sdi.defaultsupplier_id,
                                   sdi.product_id,
                                   sdi.sizedefinition_id,
                                   st.transactiontimestamp)
              INTO priceeval0
              FROM stockdefinitionperitem   sdi,
                   stockreservationpergrade srg,
                   stocktransaction         st
             WHERE srg.stockreservationpergrade_id =
                   st.stockreservationpergrade_id
               AND srg.stockdefinitionperitem_id =
                   sdi.stockdefinitionperitem_id
               AND st.stocktransaction_id = strt.stocktransaction_id;
          EXCEPTION
            WHEN OTHERS THEN
              priceeval0 := 0;
              utl_file.put_line(file,
                                'Stocktransaction_id ' ||
                                str.stocktransaction_id || ': ' ||
                                ' stockValuationMethod: ' ||
                                stockevalmethod ||
                                ' has no calculation price.');
          END;

          UPDATE stocktransaction st
             SET st.calculationprice = priceeval0
           WHERE st.stocktransaction_id = strt.stocktransaction_id;

        ELSIF stockevalmethod = 1 THEN
          -- price for StockValuationMethod 1 (FIFO)
          BEGIN
            SELECT SUM(s.qtyactualstock * s.piecevalue) /
                   SUM(s.qtyactualstock)
              INTO priceeval1
              FROM stockvaluefifo s, stocktransaction st
             WHERE s.stockreservationpergrade_id =
                   st.stockreservationpergrade_id
               AND st.stocktransaction_id = strt.stocktransaction_id;
          EXCEPTION
            WHEN OTHERS THEN
              priceeval1 := 0;
              utl_file.put_line(file,
                                'Stocktransaction_id ' ||
                                str.stocktransaction_id || ': ' ||
                                ' stockValuationMethod: ' ||
                                stockevalmethod ||
                                ' has no calculation price.');
          END;

          UPDATE stocktransaction st
             SET st.calculationprice = priceeval1
           WHERE st.stocktransaction_id = strt.stocktransaction_id;

        ELSIF stockevalmethod = 2 THEN
          --price for StockValuationMethod 2 (AVGPP)
          BEGIN
            SELECT f_getavgpurchasepricesatdate(st.stockreservationpergrade_id,
                                                st.transactiondate)
              INTO priceeval2
              FROM stocktransaction st
             WHERE st.stocktransaction_id = strt.stocktransaction_id;
          EXCEPTION
            WHEN OTHERS THEN
              priceeval2 := 0;
              utl_file.put_line(file,
                                'Stocktransaction_id ' ||
                                str.stocktransaction_id || ': ' ||
                                ' stockValuationMethod: ' ||
                                stockevalmethod ||
                                ' has no calculation price.');
          END;

          UPDATE stocktransaction st
             SET st.calculationprice = priceeval2
           WHERE st.stocktransaction_id = strt.stocktransaction_id;

        ELSE
          -- price for StockValuationMethod 3 (FSP)
          BEGIN
            SELECT f_getfixedsettlepriceatdate(st.stockreservationpergrade_id,
                                               st.transactiondate)
              INTO priceeval3
              FROM stocktransaction st
             WHERE st.stocktransaction_id = strt.stocktransaction_id;
          EXCEPTION
            WHEN OTHERS THEN
              priceeval3 := 0;
              utl_file.put_line(file,
                                'Stocktransaction_id ' ||
                                str.stocktransaction_id || ': ' ||
                                ' stockValuationMethod: ' ||
                                stockevalmethod ||
                                ' has no calculation price.');
          END;

          UPDATE stocktransaction st
             SET st.calculationprice = priceeval3
           WHERE st.stocktransaction_id = strt.stocktransaction_id;

        END IF;
      EXCEPTION
        WHEN OTHERS THEN
          status := 0; --commit will not be done
          utl_file.put_line(file,
                            'Stocktransaction_id ' ||
                            str.stocktransaction_id || ': ' ||
                            'Calculation price cannot be determined.');
          EXIT;
      END;

      -- update document type, document number prefix, document number
      BEGIN
        -- DOCUMENTTYPE_STOCKTRANSACTION = 0
        IF strt.transactiontype_id IN (10, 401, 402) THEN
          UPDATE stocktransaction st
             SET st.documenttype         = 0,
                 st.documentnumberprefix = 'B',
                 st.documentnumber       = st.stocktransaction_id
           WHERE st.stocktransaction_id = strt.stocktransaction_id;
        ELSIF strt.transactiontype_id IN (23, 33, 44, 84, 414, 444) THEN
          UPDATE stocktransaction st
             SET st.documenttype         = 0,
                 st.documentnumberprefix = 'S',
                 st.documentnumber       = st.stocktransaction_id
           WHERE st.stocktransaction_id = strt.stocktransaction_id;
        ELSIF strt.transactiontype_id IN (13, 80, 81, 82,493) THEN
          UPDATE stocktransaction st
             SET st.documenttype   = 0,
                 st.documentnumber = st.stocktransaction_id
           WHERE st.stocktransaction_id = strt.stocktransaction_id;
        ELSIF strt.transactiontype_id IN (415, 416) THEN
          UPDATE stocktransaction st
             SET st.documenttype         = 0,
                 st.documentnumberprefix = 'T',
                 st.documentnumber       = st.stocktransaction_id
           WHERE st.stocktransaction_id = strt.stocktransaction_id;
        ELSIF strt.transactiontype_id IN (40, 41) THEN
          UPDATE stocktransaction st
             SET st.documenttype         = 0,
                 st.documentnumberprefix = 'R',
                 st.documentnumber       = st.stocktransaction_id
           WHERE st.stocktransaction_id = strt.stocktransaction_id;
        ELSIF strt.transactiontype_id = 16 THEN
          UPDATE stocktransaction st
             SET st.documenttype         = 0,
                 st.documentnumberprefix = 'G',
                 st.documentnumber       = st.stocktransaction_id
           WHERE st.stocktransaction_id = strt.stocktransaction_id;
        ELSIF strt.transactiontype_id = 93 THEN
          UPDATE stocktransaction st
             SET st.documenttype         = 0,
                 st.documentnumberprefix = 'L',
                 st.documentnumber       = st.stocktransaction_id
           WHERE st.stocktransaction_id = strt.stocktransaction_id;
        ELSIF strt.transactiontype_id IN (12, 400) THEN
          BEGIN
            SELECT po.purchaseordernumber, po.purchaseordertype
              INTO docnrintext, potype
              FROM purchaseorderheader           po,
                   purchaseorderstocktransaction pst,
                   purchaseorderline             pol,
                   stocktransaction              st
             WHERE po.purchaseorderheader_id = pol.purchaseorderheader_id
               AND pol.purchaseorderline_id = pst.purchaseorderline_id
               AND pst.stocktransaction_id = st.stocktransaction_id
               AND st.stocktransaction_id = strt.stocktransaction_id;
          EXCEPTION
            WHEN no_data_found THEN
              status := 0; --commit will not be done
              utl_file.put_line(file,
                                'Stocktransaction_id ' ||
                                str.stocktransaction_id || ': ' ||
                                'There is no purchase order number for transactiontype_id ' ||
                                strt.transactiontype_id);
              EXIT;
          END;
          --DOCUMENTTYPE_INTERNAL_PURCHASE_ORDER = 1
          IF potype = 1 THEN
            UPDATE stocktransaction st
               SET st.documenttype         = 1,
                   st.documentnumberprefix = 'E',
                   st.documentnumber       = docnrintext
             WHERE st.stocktransaction_id = strt.stocktransaction_id;
          ELSE
            --DOCUMENTTYPE_EXTERNAL_PURCHASE_ORDER = 2
            UPDATE stocktransaction st
               SET st.documenttype         = 2,
                   st.documentnumberprefix = 'Z',
                   st.documentnumber       = docnrintext
             WHERE st.stocktransaction_id = strt.stocktransaction_id;
          END IF;
          --DOCUMENTTYPE_WORK_ORDER = 3
        ELSIF strt.transactiontype_id = 32 THEN
          BEGIN
            SELECT wo.workordernumber
              INTO docnrwo
              FROM workorder                 wo,
                   workorderline             wol,
                   workorderstocktransaction wst,
                   stocktransaction          st
             WHERE st.stocktransaction_id = wst.stocktransaction_id
               AND wol.workorderline_id = wst.workorderline_id
               AND wo.workorder_id = wol.workorder_id
               AND wo.origin = 1
               AND st.stocktransaction_id = strt.stocktransaction_id;
          EXCEPTION
            WHEN no_data_found THEN
              status := 0; --commit will not be done
              utl_file.put_line(file,
                                'Stocktransaction_id ' ||
                                str.stocktransaction_id || ': ' ||
                                'There is no work order number for transactiontype_id ' ||
                                strt.transactiontype_id);
              EXIT;
          END;

          UPDATE stocktransaction st
             SET st.documenttype         = 3,
                 st.documentnumberprefix = 'W',
                 st.documentnumber       = docnrwo
           WHERE st.stocktransaction_id = strt.stocktransaction_id;

          -- DOCUMENTTYPE_PICK_LIST_INTERNAL_MOVEMENTS = 4
        ELSIF strt.transactiontype_id = 410 THEN
          UPDATE stocktransaction st
             SET st.documenttype         = 4,
                 st.documentnumberprefix = 'C',
                 st.documentnumber       = st.stocktransaction_id
           WHERE st.stocktransaction_id = strt.stocktransaction_id;
          --DOCUMENTTYPE_TRUCK_LOAD_LIST = 5
        ELSIF strt.transactiontype_id IN (405, 406) THEN
          UPDATE stocktransaction st
             SET st.documenttype         = 5,
                 st.documentnumberprefix = 'U',
                 st.documentnumber       = st.stocktransaction_id
           WHERE st.stocktransaction_id = strt.stocktransaction_id;
          -- DOCUMENTTYPE_SALES_NOTE = 6
        ELSIF strt.transactiontype_id = 450 THEN
          BEGIN
            SELECT wo.workordernumber
              INTO docnrwo
              FROM workorder                 wo,
                   workorderline             wol,
                   workorderstocktransaction wst,
                   stocktransaction          st
             WHERE st.stocktransaction_id = wst.stocktransaction_id
               AND wol.workorderline_id = wst.workorderline_id
               AND wo.workorder_id = wol.workorder_id
               AND wo.origin = 6
               AND st.stocktransaction_id = strt.stocktransaction_id;
          EXCEPTION
            WHEN no_data_found THEN
              status := 0; --commit will not be done
              utl_file.put_line(file,
                                'Stocktransaction_id ' ||
                                str.stocktransaction_id || ': ' ||
                                'There is no work order number for transactiontype_id ' ||
                                strt.transactiontype_id);
              EXIT;
          END;

          UPDATE stocktransaction st
             SET st.documenttype         = 6,
                 st.documentnumberprefix = 'V',
                 st.documentnumber       = docnrwo
           WHERE st.stocktransaction_id = strt.stocktransaction_id;

          -- DOCUMENTTYPE_CREDIT_NOTE = 7
        ELSIF strt.transactiontype_id = 53 THEN
          BEGIN
            SELECT wo.workordernumber
              INTO docnrwo
              FROM workorder                 wo,
                   workorderline             wol,
                   workorderstocktransaction wst,
                   stocktransaction          st
             WHERE st.stocktransaction_id = wst.stocktransaction_id
               AND wol.workorderline_id = wst.workorderline_id
               AND wo.workorder_id = wol.workorder_id
               AND wo.origin = 7
               AND st.stocktransaction_id = strt.stocktransaction_id;
          EXCEPTION
            WHEN no_data_found THEN
              status := 0; --commit will not be done
              utl_file.put_line(file,
                                'Stocktransaction_id ' ||
                                str.stocktransaction_id || ': ' ||
                                'There is no work order number for transactiontype_id ' ||
                                strt.transactiontype_id);
              EXIT;

          END;

          UPDATE stocktransaction st
             SET st.documenttype         = 7,
                 st.documentnumberprefix = 'V',
                 st.documentnumber       = docnrwo
           WHERE st.stocktransaction_id = strt.stocktransaction_id;

          -- DOCUMENTTYPE_STOCK_DELIVERY_INTERNAL_PO = 8 / DOCUMENTTYPE_STOCK_DELIVERY_DIRECT = 9
        ELSIF strt.transactiontype_id = 409 THEN
          BEGIN
            SELECT wo.workordernumber, wo.origin
              INTO docnrwo, woorigin
              FROM workorder                 wo,
                   workorderline             wol,
                   workorderstocktransaction wst,
                   stocktransaction          st
             WHERE st.stocktransaction_id = wst.stocktransaction_id
               AND wol.workorderline_id = wst.workorderline_id
               AND wo.workorder_id = wol.workorder_id
               AND st.stocktransaction_id = strt.stocktransaction_id;
          EXCEPTION
            WHEN no_data_found THEN
              status := 0; --commit will not be done
              utl_file.put_line(file,
                                'Stocktransaction_id ' ||
                                str.stocktransaction_id || ': ' ||
                                'There is no work order number for transactiontype_id ' ||
                                strt.transactiontype_id);
              EXIT;
          END;
          IF woorigin = 8 THEN
            UPDATE stocktransaction st
               SET st.documenttype         = 8,
                   st.documentnumberprefix = 'C',
                   st.documentnumber       = docnrwo
             WHERE st.stocktransaction_id = strt.stocktransaction_id;
          ELSE
            --woOrigin=9
            UPDATE stocktransaction st
               SET st.documenttype         = 9,
                   st.documentnumberprefix = 'C',
                   st.documentnumber       = docnrwo
             WHERE st.stocktransaction_id = strt.stocktransaction_id;
          END IF;
          --DOCUMENTTYPE_MOUNTING_ORDER = 10
        ELSIF strt.transactiontype_id IN (423, 453) THEN
          BEGIN
            SELECT wo.workordernumber
              INTO docnrwo
              FROM workorder                 wo,
                   workorderline             wol,
                   workorderstocktransaction wst,
                   stocktransaction          st
             WHERE st.stocktransaction_id = wst.stocktransaction_id
               AND wol.workorderline_id = wst.workorderline_id
               AND wo.workorder_id = wol.workorder_id
               AND wo.origin = 10
               AND st.stocktransaction_id = strt.stocktransaction_id;
          EXCEPTION
            WHEN no_data_found THEN
              status := 0; --commit will not be done
              utl_file.put_line(file,
                                'Stocktransaction_id ' ||
                                str.stocktransaction_id || ': ' ||
                                'There is no work order number for transactiontype_id ' ||
                                strt.transactiontype_id);
              EXIT;
          END;

          UPDATE stocktransaction st
             SET st.documenttype         = 10,
                 st.documentnumberprefix = 'M',
                 st.documentnumber       = docnrwo
           WHERE st.stocktransaction_id = strt.stocktransaction_id;

          -- DOCUMENTTYPE_DISMOUNTING_ORDER = 11
        ELSIF strt.transactiontype_id = 15 THEN
          BEGIN
            SELECT wo.workordernumber
              INTO docnrwo
              FROM workorder                 wo,
                   workorderline             wol,
                   workorderstocktransaction wst,
                   stocktransaction          st
             WHERE st.stocktransaction_id = wst.stocktransaction_id
               AND wol.workorderline_id = wst.workorderline_id
               AND wo.workorder_id = wol.workorder_id
               AND wo.origin = 11
               AND st.stocktransaction_id = strt.stocktransaction_id;
          EXCEPTION
            WHEN no_data_found THEN
              UPDATE stocktransaction st
                 SET st.documenttype         = 0,
                     st.documentnumberprefix = 'G',
                     st.documentnumber       = st.stocktransaction_id
               WHERE st.stocktransaction_id = strt.stocktransaction_id;
          END;

          UPDATE stocktransaction st
             SET st.documenttype         = 11,
                 st.documentnumberprefix = 'M',
                 st.documentnumber       = docnrwo
           WHERE st.stocktransaction_id = strt.stocktransaction_id;

          --DOCUMENTTYPE_DELIVERY_NOTE = 12
        ELSIF strt.transactiontype_id IN (424, 454) THEN
          BEGIN
            SELECT pn.notenumber
              INTO docnopn
              FROM packingnote                 pn,
                   packingnotestocktransaction pst,
                   packingnoteline             pnl,
                   stocktransaction            st
             WHERE pn.packingnote_id = pnl.packingnote_id
               AND pnl.packingnoteline_id = pst.packingnoteline_id
               AND pst.stocktransaction_id = st.stocktransaction_id
               AND pn.notenumber IS NOT NULL
               AND st.stocktransaction_id = strt.stocktransaction_id;
          EXCEPTION
            WHEN no_data_found THEN
              status := 0; --commit will not be done
              utl_file.put_line(file,
                                'Stocktransaction_id ' ||
                                str.stocktransaction_id || ': ' ||
                                'There is no packing note number for transactiontype_id ' ||
                                strt.transactiontype_id);
              EXIT;
          END;

          UPDATE stocktransaction st
             SET st.documenttype = 12, st.documentnumber = docnopn
           WHERE st.stocktransaction_id = strt.stocktransaction_id;

          --duplicate transactiontype_id
        ELSIF strt.transactiontype_id = 22 THEN
          BEGIN
            SELECT wo.workordernumber
              INTO docnrwo
              FROM workorder                 wo,
                   workorderline             wol,
                   workorderstocktransaction wst,
                   stocktransaction          st
             WHERE st.stocktransaction_id = wst.stocktransaction_id
               AND wol.workorderline_id = wst.workorderline_id
               AND wo.workorder_id = wol.workorder_id
               AND wo.origin = 1
               AND st.stocktransaction_id = strt.stocktransaction_id;
          EXCEPTION
            WHEN no_data_found THEN
              UPDATE stocktransaction st
                 SET st.documenttype         = 0,
                     st.documentnumberprefix = 'A',
                     st.documentnumber       = st.stocktransaction_id
               WHERE st.stocktransaction_id = strt.stocktransaction_id;

          END;

          UPDATE stocktransaction st
             SET st.documenttype         = 3,
                 st.documentnumberprefix = 'W',
                 st.documentnumber       = docnrwo
           WHERE st.stocktransaction_id = strt.stocktransaction_id;

        ELSIF strt.transactiontype_id = 50 THEN
          BEGIN
            SELECT wo.workordernumber, wo.origin
              INTO docnrwo, woorigin
              FROM workorder                 wo,
                   workorderline             wol,
                   workorderstocktransaction wst,
                   stocktransaction          st
             WHERE st.stocktransaction_id = wst.stocktransaction_id
               AND wol.workorderline_id = wst.workorderline_id
               AND wo.workorder_id = wol.workorder_id
               AND st.stocktransaction_id = strt.stocktransaction_id;
          EXCEPTION
            WHEN no_data_found THEN
              UPDATE stocktransaction st
                 SET st.documenttype         = 0,
                     st.documentnumberprefix = 'S',
                     st.documentnumber       = st.stocktransaction_id
               WHERE st.stocktransaction_id = strt.stocktransaction_id;
          END;
          IF woorigin = 6 THEN
            UPDATE stocktransaction st
               SET st.documenttype         = 6,
                   st.documentnumberprefix = 'V',
                   st.documentnumber       = docnrwo
             WHERE st.stocktransaction_id = strt.stocktransaction_id;
          ELSIF woorigin <= 3 THEN
            UPDATE stocktransaction st
               SET st.documenttype         = 3,
                   st.documentnumberprefix = 'W',
                   st.documentnumber       = docnrwo
             WHERE st.stocktransaction_id = strt.stocktransaction_id;
          END IF;
        END IF;
      EXCEPTION
        WHEN OTHERS THEN
          status := 0;
          utl_file.put_line(file,
                            'ERROR! ' || 'Stocktransaction_id ' ||
                            str.stocktransaction_id || ': ' ||
                            'Document type, document number or document number prefix cannot be updated.');
          EXIT;
      END;
    END LOOP;

    IF status = 1 THEN
      COMMIT; --
    ELSE
      --status=0
      ROLLBACK;
    END IF;

  END LOOP;
  --close the file
  utl_file.fclose(file);

EXCEPTION
  -- error handling
  WHEN OTHERS THEN
    BEGIN
      IF utl_file.is_open(file) = TRUE THEN
        utl_file.fclose(file);
      END IF;
      dbms_output.put_line('Error: ' || substr(SQLERRM, 1, 200));
    END;

END update_stocktransdocinfo;
/
create or replace procedure wgid_getgarmentdatars(fp_idcode              in uniqueresidentialitem.primaryid%type,
                                                  fp_plantcode           in businessunit.code%type,
                                                  fp_in_batchid          in batch.batch_id%type,
                                                  fp_carouselnumber      in batch.batchcode%type,
                                                  fp_unitcode            out nocopy businessunit.code%type,
                                                  fp_status              out nocopy number,
                                                  fp_errormessage        out nocopy varchar2,
                                                  fp_finishingcode       out nocopy sortaddressperfinishingcode.sortaddress%type,
                                                  fp_destination         out nocopy sortaddressperfinishingmeth.sortaddress%type,
                                                  fp_foldprogram         out nocopy foldingprogramdefinition.foldingprogram%type,
                                                  fp_stackchangeinfo     out nocopy varchar2,
                                                  fp_routenumber         out nocopy route.routenumber%type,
                                                  fp_routeday            out nocopy route.drivingday_id%type,
                                                  fp_depot               out nocopy depot.code%type,
                                                  fp_sortstring          out nocopy varchar2,
                                                  fp_stopnumber          out nocopy clientdeliverynote.stopnumber%type,
                                                  fp_customernumber      out nocopy customer.customernumber%type,
                                                  fp_customername        out nocopy customer.name%type,
                                                  fp_clientnumber        out nocopy client.clientnumber%type,
                                                  fp_clientsearchname    out nocopy client.searchname%type,
                                                  fp_roomnumber          out nocopy departmentroom.roomnumber%type,
                                                  fp_departmentnumber    out nocopy department.departmentnumber%type,
                                                  fp_clientadminnumber   out nocopy client.adminnumber%type,
                                                  fp_gender              out nocopy client.gender%type,
                                                  fp_deliverypointcode   out nocopy deliverypoint.code%type,
                                                  fp_productcode         out nocopy product.code%type,
                                                  fp_productdescription  out nocopy product_desc.description%type,
                                                  fp_sizecode            out nocopy sizedefinition.code%type,
                                                  fp_productsortgroup    out nocopy productsortgroup.code%type,
                                                  fp_deliverydaymask     out nocopy varchar2, --varchar2(7)
                                                  fp_flagcode1           out nocopy sortaddressperflag.sortaddress%type,
                                                  fp_flagcode2           out nocopy sortaddressperflag.sortaddress%type,
                                                  fp_flagcode3           out nocopy sortaddressperflag.sortaddress%type,
                                                  fp_flagcode4           out nocopy sortaddressperflag.sortaddress%type,
                                                  fp_flagdescription1    out nocopy varchar2,
                                                  fp_flagdescription2    out nocopy varchar2,
                                                  fp_flagdescription3    out nocopy varchar2,
                                                  fp_flagdescription4    out nocopy varchar2,
                                                  fp_infotext            out nocopy client.remark%type,
                                                  fp_clientdeliverynote  out nocopy clientdeliverynote.clientdeliverynotenumber%type,
                                                  fp_department_desc     out nocopy department.description%type,
                                                  fp_clientfirstlastname out nocopy varchar2,
                                                  fp_productvolume       out nocopy product.volumeunits%type,
                                                  fp_finishingmethodcode out nocopy varchar2,
                                                  fp_finishingmethoddesc out nocopy varchar2) is
  --procedure wgid_getgarmentdatars version 0.7
  --20211108 HVL overwrite client name with last name only
  --20240809 EBR ABS-167913 Add join to secondaryidresidentialitem
  --20240812 RDH ABS-167913 Performance improvement
  pragma autonomous_transaction;
  gv_batchexception          exception;
  gv_clientinactive          exception;
  gv_idnotassgined           exception;
  gv_fmnotallowed            exception;
  gv_systemuserid            systemuser.systemuser_id%type;
  gv_plantid_paramater       plant.plant_id%type;
  gv_plantid_garment         plant.plant_id%type;
  gv_plantlanguageid         plant.language_id%type;
  gv_businessunitid          businessunit.businessunit_id%type;
  gv_uniqueresidentialitemid uniqueresidentialitem.uniqueresidentialitem_id%type;
  gv_message                 abslog.message%type;
  gv_clientid                client.client_id%type;
  gv_customerid              customer.customer_id%type;
  gv_routeid                 route.route_id%type;
  gv_serviceteamid           customer.serviceteam_id%type;
  gv_departmentroomid        departmentroom.departmentroom_id%type;
  gv_departmentroomseq       departmentroom.sequencenumber%type;
  gv_productid               product.product_id%type;
  gv_productgroupid          product.productgroup_id%type;
  gv_colorid                 color.color_id%type;
  gv_sizeid                  sizedefinition.sizedefinition_id%type;
  gv_finishingmethodid       finishingmethod.finishingmethod_id%type;
  gv_deliverypointid         deliverypoint.deliverypoint_id%type;
  gv_productsortgroupid      product.productsortgroup_id%type;
  gv_productsortgroupseq     productsortgroupperplant.sequencenumber%type;
  gv_timezonehrsdiff         plant.timezonehrsdiff%type;
  gv_clientdeliverynoteid    clientdeliverynote.clientdeliverynote_id%type;
  gv_clientdelnotlinescanid  clientdelnotelinescan.clientdelnotelinescan_id%type;
  gv_batchid                 batch.batch_id%type;
  gv_statusid                status.status_id%type;
  gv_lastinscandate          uniqueresidentialitem.lastinscandate%type;
  gv_lastoutscandate         uniqueresidentialitem.lastoutscandate%type;
  gv_lastrewashdate          uniqueresidentialitem.lastrewashdate%type;
  gv_lastrepairdate          uniqueresidentialitem.lastrepairdate%type;
  gv_loglevel                number;
  gv_departmentid            department.department_id%type;
  gv_databasecode            databasesettings.code%type;
  gv_plantcode               plant.code%type;

  procedure check_parameters is
    lv_batchstatus        batch.status%type;
    lv_counter            number;
    lv_clientdateinactive client.dateinactive%type;
    lv_clientdateactive   client.dateactive%type;
    lv_batchcode          batch.batchcode%type;
  begin
    --check_parameters
    gv_message := 'BU code should exist in the DB; ';
    select p.code
    into   gv_plantcode
    from   businessunit bu
    join   plant p
    on     bu.plant_id = p.plant_id
    where  bu.code = fp_plantcode;
    --check fp_in_batchid
    if (fp_in_batchid is not null) then
      gv_message := 'Batch id should exist for the BU; ' || fp_plantcode;
      select b.status, b.batchcode
      into   lv_batchstatus, lv_batchcode
      from   batch b
      join   businessunit bu
      on     b.businessunit_id = bu.businessunit_id
      where  bu.code = fp_plantcode
      and    b.batch_id = fp_in_batchid;
      if (lv_batchstatus = 4) then
        gv_message := 'Batch is closed;';
        raise gv_batchexception;
      end if;
      if (lv_batchcode is not null and lv_batchcode <> fp_carouselnumber) then
        gv_message := 'Carousel number mismatch between the one already set on the provided batch and  ' ||
                      fp_carouselnumber;
        raise gv_batchexception;
      end if;
    end if;
    if (fp_carouselnumber is null) then
      gv_message := 'Carrousel number should not be empty; ';
      raise no_data_found;
    else
      if (not regexp_like(fp_carouselnumber, '^C(*\d)')) then
        gv_message := 'Carrousel number must match pattern C123;';
        raise gv_batchexception;
      end if;
    end if;
    gv_message := 'ID code should exist in the DB; ';
        select sum(x.cnt), max(max_date_act), max(max_date_dec)
     into   lv_counter, lv_clientdateactive, lv_clientdateinactive
    from
    (select count(1) cnt, max(cl.dateactive) max_date_act, max(cr.deceaseddate) max_date_dec
        from   uniqueresidentialitem uri
        join   businessunit bu
        on     uri.businessunit_id = bu.businessunit_id
        join   client cl
        on     uri.client_id = cl.client_id
        join   clientresident cr
        on     uri.client_id = cr.client_id ---- HVL 20211011 use endservicedate
        where  bu.code = fp_plantcode
        and    uri.primaryid = fp_idcode
    union all
    select count(1), max(cl.dateactive), max(cr.deceaseddate)
    from   uniqueresidentialitem uri
    left join secondaryidresidentialitem suri
    on suri.uniqueresidentialitem_id = uri.uniqueresidentialitem_id
    join   businessunit bu
    on     uri.businessunit_id = bu.businessunit_id
    join   client cl
    on     uri.client_id = cl.client_id
    join   clientresident cr
    on     uri.client_id = cr.client_id
    where  bu.code = fp_plantcode
    and  suri.secondaryid = fp_idcode) x;
    if (lv_counter = 0) then
      gv_message := 'ID code does not exist in the current BU; ';
      raise no_data_found;
    end if;
    if (lv_counter > 1) then
      gv_message := 'ID code exists multiple times; ';
      raise too_many_rows;
    end if;
    if not (sysdate between lv_clientdateactive and lv_clientdateinactive) then
      gv_message := 'Client is inactive; ';
      raise gv_clientinactive;
    end if;
  end check_parameters;

  procedure get_extra_information is
    lv_statuscode status.code%type;
    procedure fill_flags is
      lv_counter number := 0;
    begin
      gv_message := 'fill_flags';
      for x_fd in (select saf.sortaddress, fd.description || urf.freetextitem description
                   from   uniqueresidentialitemflag urf
                   join   flag f
                   on     urf.flag_id = f.flag_id
                   join   flagoptions fop
                   on     fop.flag_id = urf.flag_id
                   join   sortaddressperflag saf
                   on     (saf.flag_id = f.flag_id and saf.plant_id = gv_plantid_paramater)
                   join   flag_desc fd
                   on     (fd.flag_id = urf.flag_id and fd.language_id = gv_plantlanguageid)
                   where  urf.uniqueresidentialitem_id = gv_uniqueresidentialitemid
                   and    urf.startdate <= sysdate
                   and    exists (select 1
                           from   dialogs dg
                           where  dg.code in ('OutscanSort', 'CheckPointScan')
                           and    dg.dialog_id = fop.dialog_id)
                   and    saf.sortaddress is not null
                   order  by fop.confirm desc, f.priority asc, urf.startdate desc) loop
        begin
          lv_counter := lv_counter + 1;
          case lv_counter
            when 1 then
              fp_flagcode1        := x_fd.sortaddress;
              fp_flagdescription1 := x_fd.description;
            when 2 then
              fp_flagcode2        := x_fd.sortaddress;
              fp_flagdescription2 := x_fd.description;
            when 3 then
              fp_flagcode3        := x_fd.sortaddress;
              fp_flagdescription3 := x_fd.description;
            when 4 then
              fp_flagcode4        := x_fd.sortaddress;
              fp_flagdescription4 := x_fd.description;
            else
              exit;
          end case;
        end;
      end loop;
    end fill_flags;
  begin
    gv_message := 'get_extra_information';
    --get fp_destination / fp_foldprogram
    if gv_finishingmethodid is null then
      fp_destination := null;
      fp_foldprogram := null;
    else
      begin
        --get finishingmethod
        gv_message := 'get finishingmethod id ' || to_char(gv_finishingmethodid);
        begin
          select f.code,
                 (select fd.description
                   from   finishingmethod_desc fd
                   where  fd.finishingmethod_id = f.finishingmethod_id
                   and    fd.language_id = gv_plantlanguageid)
          into   fp_finishingmethodcode, fp_finishingmethoddesc
          from   finishingmethod f
          where  f.finishingmethod_id = gv_finishingmethodid
          and    ((exists (select 1
                           from   plantdepartmentfinmethod pdf
                           join   workstation ws
                           on     ws.plantdepartment_id = pdf.plantdepartment_id
                           join   sortingimportdefinition si
                           on     si.workstation_id = ws.workstation_id
                           and    si.location = fp_carouselnumber
                           where  pdf.finishingmethod_id = f.finishingmethod_id)) or
                (not exists (select 1
                               from   plantdepartmentfinmethod pdf
                               join   workstation ws
                               on     ws.plantdepartment_id = pdf.plantdepartment_id
                               join   sortingimportdefinition si
                               on     si.workstation_id = ws.workstation_id
                               and    si.location = fp_carouselnumber)));
        exception
          when no_data_found then
            raise gv_fmnotallowed;
        end;
        --get fp_destination
        select max(saf.sortaddress)
        into   fp_destination
        from   sortaddressperfinishingmeth saf
        where  saf.finishingmethod_id = gv_finishingmethodid
        and    saf.plant_id = gv_plantid_paramater;
        --get fp_foldprogram
        select max(fpd.foldingprogram)
        into   fp_foldprogram
        from   foldingprogramdefinition fpd
        where  fpd.product_id = gv_productid
        and    fpd.finishingmethod_id = gv_finishingmethodid
        and    fpd.plant_id = gv_plantid_paramater;
      end;
    end if;
    --get productsort group seq
    select nvl(max(psgp.sequencenumber), 0)
    into   gv_productsortgroupseq
    from   productsortgroupperplant psgp
    where  psgp.productsortgroup_id = gv_productsortgroupid
    and    psgp.plant_id = gv_plantid_paramater;
    --get fp_deliverydaymask
    pack_sort_rs.get_deliverydaysmask(gv_customerid, fp_deliverydaymask);
    --fill_flags
    fill_flags;
    --get status code
    gv_message := 'get status id ' || to_char(gv_statusid);
    select st.code into lv_statuscode from status st where st.status_id = gv_statusid;
    --check status
    if (lv_statuscode = '20') then
      begin
        gv_message := 'ID code has no product assigned; ';
        raise gv_idnotassgined;
      end;
    end if;
  end get_extra_information;
begin
  check_parameters;
  --get systemuser
  begin
    select s.systemuser_id into gv_systemuserid from systemuser s where s.username = 'SORT';
  exception
    when no_data_found then
      select min(systemuser_id) into gv_systemuserid from systemuser;
  end;
  --get get_uniqueitem_rs info
  gv_message := 'pack_sort_rs.get_uniqueitem_rs';
  pack_sort_rs.get_uniqueitem_rs(fp_idcode, gv_plantcode, 0, gv_plantlanguageid,
                                 gv_uniqueresidentialitemid, gv_plantid_paramater,
                                 gv_plantid_garment, fp_unitcode, gv_businessunitid, fp_status,
                                 gv_message, fp_customernumber, gv_customerid, fp_customername,
                                 gv_serviceteamid, fp_clientnumber, gv_clientid, fp_clientsearchname,
                                 fp_roomnumber, gv_departmentroomid, gv_departmentroomseq,
                                 fp_departmentnumber, fp_clientadminnumber, fp_gender,
                                 fp_deliverypointcode, gv_deliverypointid, fp_productcode,
                                 gv_productid, gv_productgroupid, fp_productdescription, gv_colorid,
                                 fp_sizecode, fp_productsortgroup, gv_productsortgroupid, gv_sizeid,
                                 gv_finishingmethodid, fp_infotext, gv_timezonehrsdiff, gv_statusid,
                                 gv_lastinscandate, gv_lastoutscandate, gv_lastrewashdate,
                                 gv_lastrepairdate, gv_loglevel, gv_departmentid, fp_department_desc,
                                 fp_clientfirstlastname, fp_productvolume, gv_databasecode);

  --clientname only lastname  HVL-20211105
  select k.name into fp_clientfirstlastname from client k where k.client_id = gv_clientid;

  --get_extra_information
  get_extra_information;
  --get_plpc_info
  gv_message := 'pack_sort_rs.get_plpc_info';
  pack_sort_rs.get_plpc_info(gv_plantid_paramater, gv_customerid, gv_productid, gv_sizeid,
                             gv_finishingmethodid, fp_status, gv_message, fp_finishingcode);
  --get client del note
  gv_message := 'pack_sort_rs.get_create_clientdelnote';
  pack_sort_rs.get_create_clientdelnote(gv_uniqueresidentialitemid, gv_businessunitid, fp_unitcode,
                                        gv_plantid_paramater, gv_customerid, gv_clientid,
                                        gv_productgroupid, gv_deliverypointid, fp_routenumber,
                                        gv_routeid, fp_routeday, fp_depot, fp_stopnumber,
                                        fp_clientdeliverynote, gv_clientdeliverynoteid,
                                        gv_clientdelnotlinescanid, gv_batchid, fp_status, gv_message,
                                        0, gv_loglevel, 'GETGARMENTDATARS', gv_systemuserid,
                                        gv_departmentid, fp_idcode, gv_productid, gv_sizeid,
                                        gv_finishingmethodid, sysdate, gv_databasecode,
                                        fp_in_batchid, fp_carouselnumber);
  --get fp_sortstring
  gv_message    := 'pack_sort_rs.get_sortstring';
  fp_sortstring := pack_sort_rs.get_sortstring(gv_plantid_paramater, gv_customerid,
                                               fp_customernumber, fp_stopnumber, fp_departmentnumber,
                                               fp_clientnumber, fp_clientsearchname, fp_roomnumber,
                                               fp_productcode, gv_productsortgroupseq,
                                               fp_deliverypointcode, fp_clientdeliverynote,
                                               gv_departmentroomseq, 'N');
  --get fp_stackchangeinfo
  gv_message         := 'pack_sort_rs.get_sortstring stack change';
  fp_stackchangeinfo := pack_sort_rs.get_sortstring(gv_plantid_paramater, gv_customerid,
                                                    fp_customernumber, fp_stopnumber,
                                                    fp_departmentnumber, fp_clientnumber,
                                                    fp_clientsearchname, fp_roomnumber,
                                                    fp_productcode, gv_productsortgroupseq,
                                                    fp_deliverypointcode, fp_clientdeliverynote,
                                                    gv_departmentroomseq, 'Y');
  --commit
  commit;
  fp_status       := 0;
  fp_errormessage := null;
  pack_sort_rs.write_logging('Ok, status 0; ID code ' || nvl(fp_idcode, 'NULL') || ' plant code ' ||
                             nvl(gv_plantcode, 'NULL'), gv_loglevel, 'GETGARMENTDATARS',
                             gv_plantid_paramater, 1, 0);
exception
  --error handling
  when no_data_found then
    begin
      rollback;
      fp_status       := 1; --no_data_found
      fp_errormessage := 'No data found, status 1; ' || gv_message || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(gv_plantcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'GETGARMENTDATARS',
                                 gv_plantid_paramater, 3, 0);
    end;
  when too_many_rows then
    begin
      rollback;
      fp_status       := 2; --too many rows
      fp_errormessage := 'Too many rows, status 2; ' || gv_message || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(gv_plantcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'GETGARMENTDATARS',
                                 gv_plantid_paramater, 3, 0);
    end;
  when gv_batchexception then
    begin
      rollback;
      fp_status       := 3; -- exception on batch
      fp_errormessage := 'Exception on batch, status 3; ' || gv_message || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(gv_plantcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'GETGARMENTDATARS',
                                 gv_plantid_paramater, 3, 0);
    end;
  when gv_clientinactive then
    begin
      rollback;
      fp_status       := 5; --Inactive client
      fp_errormessage := 'Client inactive, status 5; ' || gv_message || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(gv_plantcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'GETGARMENTDATARS',
                                 gv_plantid_paramater, 3, 0);
    end;
  when gv_idnotassgined then
    begin
      rollback;
      fp_status       := 6; --ID has no product assigned
      fp_errormessage := 'ID has no product assigned status 6: ' || gv_message || ' ID code ' ||
                         nvl(fp_idcode, 'NULL') || ' plant code ' || nvl(gv_plantcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'GETGARMENTDATARS',
                                 gv_plantid_paramater, 3, 0);
    end;

  when gv_fmnotallowed then
    begin
      rollback;
      fp_status       := 8; --Finishing Method not Allowed
      fp_errormessage := 'Finishing Method not Allowed, Status 8; ';
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'GETGARMENTDATARS',
                                 gv_plantid_paramater, 3, 0);
    end;
  when others then
    begin
      rollback;
      fp_status := 7;
      pack_sort_rs.write_logging('Error others: ' || gv_message || ' ID code ' ||
                                 nvl(fp_idcode, 'NULL') || ' plant code ' ||
                                 nvl(gv_plantcode, 'NULL') || ' see debug info!', gv_loglevel,
                                 'WGID_GETGARMENTDATARS', gv_plantid_paramater, 5, 0);
      fp_errormessage := 'Error others: ' || gv_message || ' ID code ' || nvl(fp_idcode, 'NULL') ||
                         ' plant code ' || nvl(gv_plantcode, 'NULL');
      pack_sort_rs.write_logging(fp_errormessage, gv_loglevel, 'WGID_GETGARMENTDATARS',
                                 gv_plantid_paramater, 5, 0);
    end;
end wgid_getgarmentdatars;
/
create or replace procedure wnc_correct_primaryids(fp_businessunitcode in varchar2,
                                                   fp_customernumber   in number,
                                                   fp_systemuserid     in number default 0) is
  --Procedure WNC_Correct_Primaryids version 0.1
  --Switches secondardyID length 24 to primaryID if that has a less then 24
  --22-04-2021 ABS-118023 WnC UHF and HF chipcode issue

  --Global variables
  gv_userexception exception;
  gv_counter        number := 0;
  gv_businessunitid businessunit.businessunit_id%type;
  gv_plantid        plant.plant_id%type;
  gv_customerid     customer.customer_id%type;
  gv_message        abslog.message%type;

  --Internal procedures
  procedure write_log(fp_priority in number) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'wnc_correct_primaryids', gv_plantid, fp_priority, gv_message);
    begin
      dbms_output.put_line(gv_message);
    exception
      when others then
        null; --ok no output to screen
    end;
  end write_log;

  procedure initialize is
  begin
    --initialize
    --check parameter fp_businessunitid
    if fp_businessunitcode is null and fp_customernumber is null then
      begin
        gv_message := 'Both parameters fp_businessunitcode and fp_customernumber cannot be left blank one must be filled!';
        raise gv_userexception;
      end;
    end if;
    --get businessunit id
    if fp_businessunitcode is not null then
      begin
        gv_message := 'Parameter fp_businessunitid ' || fp_businessunitcode;
        select bu.businessunit_id, bu.plant_id
        into   gv_businessunitid, gv_plantid
        from   businessunit bu
        where  bu.code = fp_businessunitcode;
      end;
    end if;
    --get customer id
    if fp_customernumber is not null then
      begin
        gv_message := 'Parameter fp_customernumber ' || to_char(fp_customernumber);
        select c.customer_id, c.defaultbusinessunit_id, bu.plant_id
        into   gv_customerid, gv_businessunitid, gv_plantid
        from   customer c
        join   businessunit bu
        on     bu.businessunit_id = c.defaultbusinessunit_id
        where  c.customernumber = fp_customernumber;
      end;
    end if;
  end initialize;

  procedure check_move_primaryid is
    procedure switch_ids(fp_uniqueitemid in number,
                         fp_primaryid    in varchar2,
                         fp_secondaryid  in varchar2) is
    begin
      --switch primary with secondary
      gv_message := 'switch primary id ' || fp_primaryid || ' with secondary id ' || fp_secondaryid;
      --switch primary to secondary
      update uniqueitem u
      set    u.primaryid = fp_secondaryid, u.systemuser_id = nvl(fp_systemuserid, 0),
             u.timestamp = sysdate
      where  u.uniqueitem_id = fp_uniqueitemid;
      --switch secondary to primary
      update secondaryuniqueitem su
      set    su.secondaryid = fp_primaryid, su.systemuser_id = nvl(fp_systemuserid, 0),
             su.timestamp = sysdate
      where  su.uniqueitem_id = fp_uniqueitemid;
      --count records updated
      gv_counter := gv_counter + 1;
    end switch_ids;
  begin
    --check_move_primaryid
    gv_message := 'check_move_primaryid';
    if fp_customernumber is null then
      begin
        --check for id's linked to gv_businessunitid
        for x in (select u.uniqueitem_id, u.primaryid, su.secondaryid
                  from   uniqueitem u
                  join   secondaryuniqueitem su
                  on     su.uniqueitem_id = u.uniqueitem_id
                  where  length(u.primaryid) < 24
                  and    length(su.secondaryid) = 24
                  and    u.businessunit_id = gv_businessunitid) loop
          begin
            switch_ids(x.uniqueitem_id, x.primaryid, x.secondaryid);
          end;
        end loop;
      end;
    else
      begin
        --check for wearer id's linked to gv_customerid
        for x in (select u.uniqueitem_id, u.primaryid, su.secondaryid
                  from   uniqueitem u
                  join   secondaryuniqueitem su
                  on     su.uniqueitem_id = u.uniqueitem_id
                  join   uniqueitemnonpool un
                  on     un.uniqueitem_id = u.uniqueitem_id
                  join   weareremployment we
                  on     we.weareremployment_id = un.weareremployment_id
                  join   wearer w
                  on     w.wearer_id = we.wearer_id
                  where  length(u.primaryid) < 24
                  and    length(su.secondaryid) = 24
                  and    w.customer_id = gv_customerid) loop
          begin
            switch_ids(x.uniqueitem_id, x.primaryid, x.secondaryid);
          end;
        end loop;
      end;
    end if;
  end check_move_primaryid;

  procedure finalize is
  begin
    --finalize
    commit;
    --return message
    if fp_businessunitcode is not null then
      gv_message := 'Ran ok ' || to_char(gv_counter) ||
                    ' primaryid''s corrected for businessunit code ' || fp_businessunitcode;
    end if;
    if fp_customernumber is not null then
      gv_message := 'Ran ok ' || to_char(gv_counter) || ' primaryid''s corrected for customer ' ||
                    to_char(fp_customernumber);
    end if;
    write_log(1);
  end finalize;
begin
  --initialize
  initialize;
  --check_move_primaryid
  check_move_primaryid;
  --finalize
  finalize;
exception
  --Exception handling
  when gv_userexception then
    begin
      rollback;
      write_log(3);
    end;
  when no_data_found then
    begin
      rollback;
      gv_message := 'Error, No Data Found ' || gv_message;
      write_log(3);
    end;
  when others then
    begin
      rollback;
      gv_message := 'Error ' || sqlerrm || ' ' || gv_message || ' businessunit ' ||
                    nvl(fp_businessunitcode, 'NULL') || ' customer ' ||
                    nvl(to_char(fp_customernumber), 'NULL');
      write_log(3);
    end;
end wnc_correct_primaryids;
/
create or replace procedure wol_recalc_after_po_up(fp_purchaseorderheaderid in purchaseorderheader.purchaseorderheader_id%type) is
  -----------------------
  --wo_recalc_after_po_up Version 0.3 Sept.2014
  --called from a custom made package, so NO rollback. commit for now!
  -----------------------
  --global variables
  gv_user_exception exception;
  gv_systemuserid           systemuser.systemuser_id%type := 0;
  gv_message                abslog.message%type;
  gv_purchaseordernumber    purchaseorderheader.purchaseordernumber%type;
  gv_stockroomid            stockroom.stockroom_id%type;
  gv_businessunitid         businessunit.businessunit_id%type;
  gv_distributionpointid    distributionpoint.distributionpoint_id%type;
  gv_deliverypointid        deliverypoint.deliverypoint_id%type;
  gv_departmentid           department.department_id%type;
  gv_plantid                plant.plant_id%type;
  gv_plpcid                 productlistpercustomer.productlistpercustomer_id%type;
  gv_numberofdaysforprewash number;
  gv_confirmdate            date;
  gv_daynumber              day.daynumber%type;
  gv_servicedays            stockroomsservicingbu.servicedays%type;
  gv_customerid             customer.customer_id%type;
  gv_nextdeldate            date;
  gv_dummyid                number;
  gv_counter                number;

  -----------------------
  --internal procedures
  procedure write_log(fp_message  in abslog.message%type,
                      fp_priority in abslog.priority%type default 1) is
  begin
    /*
    Write message in ABSLOG with these priorities
    1 = Message
    2 = Warning
    3 = Error
    4 = Stack trace
    5 = Debug info
    */
    abslogwrite.abslog_write(5, 'wol_recalc_after_po_up', gv_plantid, fp_priority, fp_message,
                             gv_systemuserid);
  end write_log;
  -----------------------
begin
  --lookup selected purchaseorderheader
  gv_message := 'lookup fp_purchaseorderheaderid ' ||
                nvl(to_char(fp_purchaseorderheaderid), 'NULL');
  select poh.purchaseordernumber, poh.stockroom_id
  into   gv_purchaseordernumber, gv_stockroomid
  from   purchaseorderheader poh
  where  poh.purchaseorderheader_id = fp_purchaseorderheaderid;
  --go through all workorders
  gv_message := 'go through all workorders for purchaseordernumber ' ||
                to_char(gv_purchaseordernumber);
  gv_counter := 0;
  for x in (select wol.workorder_id, pol.confirmeddate, p.typeofmerchandise, wol.workorderline_id,
                   wol.product_link_id, wol.sizedefinition_link_id, wol.finishingmethod_id
            from   purchaseorderline pol
            join   workorderline wol
            on     wol.purchaseorderline_id = pol.purchaseorderline_id
            join   product p
            on     p.product_id = wol.product_link_id
            where  pol.purchaseorderheader_id = fp_purchaseorderheaderid) loop
    begin
      begin
        --get workorder
        gv_message := 'get workorder ' || to_char(x.workorder_id);
        select w.customer_id, bu.plant_id, bu.businessunit_id, we.distributionpoint_id,
               dp.deliverypoint_id, dp.department_id
        into   gv_customerid, gv_plantid, gv_businessunitid, gv_distributionpointid,
               gv_deliverypointid, gv_departmentid
        from   workorder wo
        join   weareremployment we
        on     we.weareremployment_id = wo.weareremployment_link_id
        join   wearer w
        on     w.wearer_id = we.wearer_id
        join   businessunit bu
        on     bu.businessunit_id = wo.businessunit_id
        join   distributionpoint dp
        on     dp.distributionpoint_id = we.distributionpoint_id
        where  wo.workorder_id = x.workorder_id;
      exception
        when no_data_found then
          gv_message := 'no wearer linked to workorder id ' || to_char(x.workorder_id) ||
                        ' for purchaseorder id ' || nvl(to_char(fp_purchaseorderheaderid), 'NULL');
          raise gv_user_exception;
      end;
      --lookup system setting NUMBEROFDAYSFORPREWASH
      gv_message := 'lookup systemsetting NUMBEROFDAYSFORPREWASH for plant id ' ||
                    nvl(to_char(gv_plantid), 'NULL');
      select coalesce(to_number(st.value), to_number(st.factorydefault), 0)
      into   gv_numberofdaysforprewash
      from   systemsetting st
      where  st.plant_id = gv_plantid
      and    st.name = 'NUMBEROFDAYSFORPREWASH';
      --lookup stockroom days
      gv_message := 'lookup stockroom days for workorder id ' || to_char(x.workorder_id);
      select nvl(max(ss.servicedays), 0)
      into   gv_servicedays
      from   stockroomsservicingbu ss
      where  ss.stockroom_id = gv_stockroomid
      and    ss.businessunit_id = gv_businessunitid;
      --calc. gv_confirmdate
      gv_message     := 'calc. gv_confirmdate ' || to_char(x.workorder_id);
      gv_confirmdate := x.confirmeddate + gv_servicedays + gv_numberofdaysforprewash;
      gv_daynumber   := getabsdaynumber(gv_confirmdate);
      case gv_daynumber
        when 1 then
          select nvl(max(ss.logicaldays_day1), 0)
          into   gv_servicedays
          from   stockroomsservicingbu ss
          where  ss.stockroom_id = gv_stockroomid
          and    ss.businessunit_id = gv_businessunitid;
        when 2 then
          select nvl(max(ss.logicaldays_day2), 0)
          into   gv_servicedays
          from   stockroomsservicingbu ss
          where  ss.stockroom_id = gv_stockroomid
          and    ss.businessunit_id = gv_businessunitid;
        when 3 then
          select nvl(max(ss.logicaldays_day3), 0)
          into   gv_servicedays
          from   stockroomsservicingbu ss
          where  ss.stockroom_id = gv_stockroomid
          and    ss.businessunit_id = gv_businessunitid;
        when 4 then
          select nvl(max(ss.logicaldays_day4), 0)
          into   gv_servicedays
          from   stockroomsservicingbu ss
          where  ss.stockroom_id = gv_stockroomid
          and    ss.businessunit_id = gv_businessunitid;
        when 5 then
          select nvl(max(ss.logicaldays_day5), 0)
          into   gv_servicedays
          from   stockroomsservicingbu ss
          where  ss.stockroom_id = gv_stockroomid
          and    ss.businessunit_id = gv_businessunitid;
        when 6 then
          select nvl(max(ss.logicaldays_day1), 0) + 2 --also a monday + 2
          into   gv_servicedays
          from   stockroomsservicingbu ss
          where  ss.stockroom_id = gv_stockroomid
          and    ss.businessunit_id = gv_businessunitid;
        when 7 then
          select nvl(max(ss.logicaldays_day1), 0) + 1 --also a monday + 1
          into   gv_servicedays
          from   stockroomsservicingbu ss
          where  ss.stockroom_id = gv_stockroomid
          and    ss.businessunit_id = gv_businessunitid;
        else
          gv_servicedays := 0;
      end case;
      gv_confirmdate := x.confirmeddate + gv_servicedays;
      --get plpc id
      gv_message := 'pack_deliverybasics get plpc id for wolid ' || to_char(x.workorderline_id);
      select max(l.productlistpercustomer_id)
      into   gv_plpcid
      from   productlistpercustomer l
      where  gv_confirmdate between l.dateactive and l.dateinactive
      and    l.customer_id = gv_customerid
      and    l.product_id = x.product_link_id
      and    l.sizedefinition_id = x.sizedefinition_link_id
      and    l.finishingmethod_id = x.finishingmethod_id;
      if gv_plpcid is not null then
        begin
          ---now get next customer deliverydate based on gv_confirmdate
          gv_message := 'pack_deliverybasics.determinedeldaterouteclean for workorderline id ' ||
                        to_char(x.workorderline_id);
          pack_deliverybasics.determinedeldaterouteclean(gv_plantid /*fpi_plant_id*/, gv_customerid
                                                         /*fpi_customer_id*/, gv_deliverypointid
                                                         /*fpi_delpoint_id*/, gv_departmentid
                                                         /*fpi_department_id*/, x.typeofmerchandise
                                                         /*fpi_typeofmerch*/, gv_confirmdate
                                                         /*fpi_date*/, gv_plpcid /*fpi_plpc_id*/,
                                                         gv_distributionpointid
                                                         /*fpi_distribpoint_id*/, 'N'
                                                         /*fpi_log*/, gv_dummyid /*fpo_routestop_id*/,
                                                         gv_dummyid /*fpo_route_id*/, gv_dummyid
                                                         /*fpo_stop_id*/, gv_dummyid
                                                         /*fpo_routecontrol_id*/, gv_nextdeldate
                                                         /*fpo_drivingdate*/);
          --update workorderline
          gv_message := 'update workorderline id ' || to_char(x.workorderline_id);
          update workorderline wol
          set    wol.expecteddate = nvl(gv_nextdeldate, to_date('31122099', 'ddmmyyyy')),
                 wol.systemuser_id = gv_systemuserid, wol.timestamp = sysdate
          where  wol.workorderline_id = x.workorderline_id
          and    wol.expecteddate <> nvl(gv_nextdeldate, to_date('31122099', 'ddmmyyyy'));
          --update workorder
          gv_message := 'update workorder id ' || to_char(x.workorder_id);
          update workorder wo
          set    wo.expectedcompletedate =
                  (select max(nvl(wol.expecteddate, to_date('31122099', 'ddmmyyyy')))
                   from   workorderline wol
                   where  wol.workorder_id = wo.workorder_id), wo.systemuser_id = gv_systemuserid,
                 wo.timestamp = sysdate
          where  wo.workorder_id = x.workorder_id
          and    wo.confirmationdate <>
                 (select max(nvl(wol.expecteddate, to_date('31122099', 'ddmmyyyy')))
                   from   workorderline wol
                   where  wol.workorder_id = wo.workorder_id);
          --count updated WOLs
          gv_counter := gv_counter + 1;
        end;
      end if;
    end;
  end loop;
  if gv_counter > 0 then
    write_log('updated ' || to_char(gv_counter) || ' workorderlines for purchaseorderheader_id ' ||
              to_char(fp_purchaseorderheaderid));
  end if;
  -----------------------
exception
  when gv_user_exception then
    begin
      write_log(gv_message, 3);
    end;
  when others then
    begin
      write_log(gv_message, 3);
      write_log(sqlerrm, 5);
    end;
end wol_recalc_after_po_up;
/
create or replace procedure wo_outofservice_contact(fp_businessunitid in businessunit.businessunit_id%type,
                                                    fp_workorderid    in workorder.workorder_id%type,
                                                    fp_customerid     in customer.customer_id%type,
                                                    fp_systemuserid   in systemuser.systemuser_id%type) is
  -----------------------------------------------
  --- wo_outofservice_contact version 0.3     ---
  --------Internal variables---------------------
  pragma autonomous_transaction;

  gv_userexception exception;
  gv_message           abslog.message%type;
  gv_plantid           plant.plant_id%type;
  gv_callnumber        contact.callnumber%type;
  gv_rec_workorder     workorder%rowtype;
  gv_createdbyusername contact.createdbyusername%type;
  gv_contactcategoryid contact.contactcategory_id%type;
  gv_contactnotes      contact.contactnotes%type;
  gv_contactpersonname employee.name%type;
  gv_contactperson_id  employee.employee_id%type;

  --------Internal procedures/functions----------
  procedure write_log(fp_message in abslog.message%type, fp_priority in abslog.priority%type) is
  begin
    --write_log
    abslogwrite.abslog_write(5, 'wo_outofservice_contact', gv_plantid, fp_priority, fp_message,
                             fp_systemuserid);
  end write_log;

  procedure initialize is
    lv_bucode       businessunit.code%type;
    lv_languageid   languages.language_id%type;
    lv_languagecode languages.code%type;
  begin
    --initialize, get businessunit id
    gv_message := 'bussinessunit id ' || nvl(to_char(fp_businessunitid), 'NULL');
    select bu.code, bu.plant_id
    into   lv_bucode, gv_plantid
    from   businessunit bu
    where  bu.businessunit_id = fp_businessunitid;
    --get new call number
    gv_message := 'get new call number from SEQ_CONTACTMGR_' || lv_bucode;
    execute immediate 'select SEQ_CONTACTMGR_' || lv_bucode || '.nextval from dual'
      into gv_callnumber;
    --get workorder id
    gv_message := 'workorder id ' || nvl(to_char(fp_workorderid), 'NULL');
    select wo.* into gv_rec_workorder from workorder wo where wo.workorder_id = fp_workorderid;
    --get customer id
    gv_message := 'customer id ' || nvl(to_char(fp_customerid), 'NULL');
    select c.serviceemployee_id, c.language_id
    into   gv_contactperson_id, lv_languageid
    from   customer c
    where  c.customer_id = fp_customerid;
    if gv_contactperson_id is not null then
      begin
        --get the contact person name
        gv_message := 'contact person id ' || nvl(to_char(gv_contactperson_id), 'NULL');
        select substr(trim(e.name), 1, 30)
        into   gv_contactpersonname
        from   employee e
        where  e.employee_id = gv_contactperson_id;
      end;
    end if;
    if lv_languageid is not null then
      begin
        --get language code
        gv_message := 'language id ' || nvl(to_char(lv_languageid), 'NULL');
        select l.code into lv_languagecode from languages l where l.language_id = lv_languageid;
      end;
    end if;
    if lv_languagecode like '%DE%' then
      begin
        --German contact notes
        gv_contactnotes := 'Kundenauftrag ' || to_char(gv_rec_workorder.workordernumber) ||
                           ' fehlgeschlagen aufgrund unzureichendem Lagerbestands. Bitte verfolgen Sie dies weiter, danke.';
      end;
    else
      begin
        --Default English contact notes
        gv_contactnotes := 'Workorder ' || to_char(gv_rec_workorder.workordernumber) ||
                           ' failed due to insufficient stock, please follow up, thanks';
      end;
    end if;
    --get system user id
    gv_message := 'system user id ' || nvl(to_char(fp_systemuserid), 'NULL');
    select su.username
    into   gv_createdbyusername
    from   systemuser su
    where  su.systemuser_id = fp_systemuserid;
    --get contactcategory WOOOS
    begin
      gv_message := 'Get contactcategory WOOOS';
      select cc.contactcategory_id
      into   gv_contactcategoryid
      from   contactcategory cc
      where  cc.code = 'WOOOS';
    exception
      when no_data_found then
        begin
          select min(cc.contactcategory_id)
          into   gv_contactcategoryid
          from   contactcategory cc
          where  cc.defaultcontactcategory = 'Y';
          if gv_contactcategoryid is null then
            begin
              gv_message := 'No contactcategory WOOOS, and no default contactcategory!';
              raise gv_userexception;
            end;
          end if;
        end;
    end;
  end initialize;

  procedure create_contact is
    lv_nodate date := to_date('31-12-2099', 'DD-MM-YYYY');
  begin
    --create_contact
    gv_message := 'insert into contact';
    insert into contact
      (contact_id, customer_link_id, department_link_id, businessunit_id, contactcategory_id,
       createdbyuser_id, followupbyuser_id, newdate, callnumber, followupdate, inprogressdate,
       closedate, status, contactpersonname, contactperson_id, followupbyusername, createdbyusername,
       contactnotes, followupnotes, attachment, systemuser_id, timestamp, showonroutelist,
       inprogressbyuser_id, inprogressbyusername, closedbyuser_id, closedbyusername, priority,
       stop_id, contactcause_id, contactresolution_id)
    values
      (seq_contact.nextval, fp_customerid, null /*department_link_id*/, fp_businessunitid,
       gv_contactcategoryid, fp_systemuserid, null /*followupbyuser_id*/, trunc(sysdate) /*newdate*/,
       gv_callnumber, lv_nodate /*followupdate*/, lv_nodate /*inprogressdate*/, lv_nodate
       /*closedate*/, 2 /*status*/, gv_contactpersonname, gv_contactperson_id, null
       /*followupbyusername*/, gv_createdbyusername, gv_contactnotes /*contactnotes*/, null
       /*followupnotes*/, null /*attachment*/, fp_systemuserid, sysdate, 'N' /*showonroutelist*/,
       null, null, null /*closedbyuser_id*/, null /*closedbyusername*/, 1 /*priority*/, null
       /*stop_id*/, null, null);
  end create_contact;

  procedure finalize is
  begin
    --finalize
    gv_message := 'finalize';
    commit;
  end finalize;
begin
  --Main program section for wo_outofservice_contact
  initialize;
  create_contact;
  finalize;
exception
  --exception handling
  when gv_userexception then
    begin
      rollback;
      write_log(gv_message, 3);
    end;
  when no_data_found then
    begin
      rollback;
      write_log('Error No Data Found ' || gv_message, 3);
    end;
  when others then
    begin
      rollback;
      write_log('Error Others; ' || sqlerrm || ' ' || gv_message || ' bussinessunit id ' ||
                nvl(to_char(fp_businessunitid), 'NULL') || ' workorder id ' ||
                nvl(to_char(fp_workorderid), 'NULL') || ' customer id ' ||
                nvl(to_char(fp_customerid), 'NULL') || ' system user id ' ||
                nvl(to_char(fp_systemuserid), 'NULL'), 3);
    end;
end wo_outofservice_contact;
/
create or replace procedure wo_recalc_after_po_up(fp_purchaseorderheaderid in purchaseorderheader.purchaseorderheader_id%type) is
  -----------------------
  --wo_recalc_after_po_up Version 0.3 Sept.2014
  --called from a custom made package, so NO rollback. commit for now!
  -----------------------
  --global variables
  gv_user_exception exception;
  gv_systemuserid           systemuser.systemuser_id%type := 0;
  gv_message                abslog.message%type;
  gv_purchaseordernumber    purchaseorderheader.purchaseordernumber%type;
  gv_stockroomid            stockroom.stockroom_id%type;
  gv_businessunitid         businessunit.businessunit_id%type;
  gv_plantid                plant.plant_id%type;
  gv_numberofdaysforprewash number;
  gv_confirmdate            date;
  gv_daynumber              day.daynumber%type;
  gv_servicedays            stockroomsservicingbu.servicedays%type;
  gv_customerid             customer.customer_id%type;
  gv_nextdeldate            date;
  gv_counter                number;

  -----------------------
  --internal procedures
  procedure write_log(fp_message  in abslog.message%type,
                      fp_priority in abslog.priority%type default 1) is
  begin
    /*
    Write message in ABSLOG with these priorities
    1 = Message
    2 = Warning
    3 = Error
    4 = Stack trace
    5 = Debug info
    */
    abslogwrite.abslog_write(5, 'wo_recalc_after_po_up', gv_plantid, fp_priority, fp_message,
                             gv_systemuserid);
  end write_log;
  -----------------------
begin
  --lookup selected purchaseorderheader
  gv_message := 'lookup fp_purchaseorderheaderid ' ||
                nvl(to_char(fp_purchaseorderheaderid), 'NULL');
  select poh.purchaseordernumber, poh.stockroom_id
  into   gv_purchaseordernumber, gv_stockroomid
  from   purchaseorderheader poh
  where  poh.purchaseorderheader_id = fp_purchaseorderheaderid;
  --go through all workorders
  gv_message := 'go through all workorders for purchaseordernumber ' ||
                to_char(gv_purchaseordernumber);
  gv_counter := 0;
  for x in (select wol.workorder_id, max(pol.confirmeddate) confirmeddate,
                   max(p.typeofmerchandise) typeofmerchandise
            from   purchaseorderline pol
            join   workorderline wol
            on     wol.purchaseorderline_id = pol.purchaseorderline_id
            join   product p
            on     p.product_id = wol.product_link_id
            where  pol.purchaseorderheader_id = fp_purchaseorderheaderid
            group  by wol.workorder_id) loop
    begin
      begin
        --get workorder
        gv_message := 'get workorder ' || to_char(x.workorder_id);
        select w.customer_id, bu.plant_id, bu.businessunit_id
        into   gv_customerid, gv_plantid, gv_businessunitid
        from   workorder wo
        join   weareremployment we
        on     we.weareremployment_id = wo.weareremployment_link_id
        join   wearer w
        on     w.wearer_id = we.wearer_id
        join   businessunit bu
        on     bu.businessunit_id = wo.businessunit_id
        where  wo.workorder_id = x.workorder_id;
      exception
        when no_data_found then
          gv_message := 'no wearer linked to wokorder id ' || to_char(x.workorder_id) ||
                        ' for purchaseorder id ' || nvl(to_char(fp_purchaseorderheaderid), 'NULL');
          raise gv_user_exception;
      end;
      --lookup system setting NUMBEROFDAYSFORPREWASH
      gv_message := 'lookup systemsetting NUMBEROFDAYSFORPREWASH for plant id ' ||
                    nvl(to_char(gv_plantid), 'NULL');
      select coalesce(to_number(st.value), to_number(st.factorydefault), 0)
      into   gv_numberofdaysforprewash
      from   systemsetting st
      where  st.plant_id = gv_plantid
      and    st.name = 'NUMBEROFDAYSFORPREWASH';
      --lookup stockroom days
      gv_message := 'lookup stockroom days for workorder id ' || to_char(x.workorder_id);
      select nvl(max(ss.servicedays), 0)
      into   gv_servicedays
      from   stockroomsservicingbu ss
      where  ss.stockroom_id = gv_stockroomid
      and    ss.businessunit_id = gv_businessunitid;
      --calc. gv_confirmdate
      gv_message     := 'calc. gv_confirmdate ' || to_char(x.workorder_id);
      gv_confirmdate := x.confirmeddate + gv_servicedays + gv_numberofdaysforprewash;
      gv_daynumber   := getabsdaynumber(gv_confirmdate);
      case gv_daynumber
        when 1 then
          select nvl(max(ss.logicaldays_day1), 0)
          into   gv_servicedays
          from   stockroomsservicingbu ss
          where  ss.stockroom_id = gv_stockroomid
          and    ss.businessunit_id = gv_businessunitid;
        when 2 then
          select nvl(max(ss.logicaldays_day2), 0)
          into   gv_servicedays
          from   stockroomsservicingbu ss
          where  ss.stockroom_id = gv_stockroomid
          and    ss.businessunit_id = gv_businessunitid;
        when 3 then
          select nvl(max(ss.logicaldays_day3), 0)
          into   gv_servicedays
          from   stockroomsservicingbu ss
          where  ss.stockroom_id = gv_stockroomid
          and    ss.businessunit_id = gv_businessunitid;
        when 4 then
          select nvl(max(ss.logicaldays_day4), 0)
          into   gv_servicedays
          from   stockroomsservicingbu ss
          where  ss.stockroom_id = gv_stockroomid
          and    ss.businessunit_id = gv_businessunitid;
        when 5 then
          select nvl(max(ss.logicaldays_day5), 0)
          into   gv_servicedays
          from   stockroomsservicingbu ss
          where  ss.stockroom_id = gv_stockroomid
          and    ss.businessunit_id = gv_businessunitid;
        when 6 then
          select nvl(max(ss.logicaldays_day1), 0) + 2 --also a monday + 2
          into   gv_servicedays
          from   stockroomsservicingbu ss
          where  ss.stockroom_id = gv_stockroomid
          and    ss.businessunit_id = gv_businessunitid;
        when 7 then
          select nvl(max(ss.logicaldays_day1), 0) + 1 --also a monday + 1
          into   gv_servicedays
          from   stockroomsservicingbu ss
          where  ss.stockroom_id = gv_stockroomid
          and    ss.businessunit_id = gv_businessunitid;
        else
          gv_servicedays := 0;
      end case;
      gv_confirmdate := x.confirmeddate + gv_servicedays;
      ---now get next customer deliverydate based on gv_confirmdate
      gv_message     := 'pack_sort.getnextdeliverydate for workorder id ' ||
                        to_char(x.workorder_id);
      gv_nextdeldate := pack_sort.getnextdeliverydate(gv_confirmdate, gv_customerid,
                                                      x.typeofmerchandise);
      --update workorder
      gv_message := 'update workorder ' || to_char(x.workorder_id);
      update workorder wo
      set    wo.expectedcompletedate = coalesce(gv_nextdeldate, wo.expectedcompletedate)
      where  wo.workorder_id = x.workorder_id;
      --
      commit;
      gv_counter := gv_counter + 1;
    end;
  end loop;
  write_log('update ' || to_char(gv_counter) || ' workorders for purchaseorderheader_id ' ||
            to_char(fp_purchaseorderheaderid));
  -----------------------
exception
  when gv_user_exception then
    begin
      write_log(gv_message, 3);
    end;
  when others then
    begin
      write_log(gv_message, 3);
      write_log(sqlerrm, 5);
    end;
end wo_recalc_after_po_up;
/
create or replace procedure wsp_sendtrack_mats(fp_plantcode    in varchar2,
                                               fp_idcode       in varchar2,
                                               fp_transaction  in varchar2,
                                               fp_scandate     in varchar2,
                                               fp_scantime     in varchar2,
                                               fp_scanlocation in varchar2,
                                               fp_productid    in number,
                                               fp_sizeid       in number,
                                               fp_status       out number,
                                               fp_message      out varchar2) is
  /*procedure wsp_sendtrack_mats version 0.1*/
  pragma udf;
  --Global variables
  gv_userexception   exception;
  gv_systemuserid    number := 0;
  gv_message         abslog.message%type;
  gv_plantid         plant.plant_id%type;
  gv_workstationcode workstation.code%type;
  gv_businessunitid  businessunit.businessunit_id%type;
  gv_currencyid      currency.currency_id%type;
  gv_scandate        date;
  gv_productid       product.product_id%type;
  gv_supplierid      supplier.supplier_id%type;
  gv_sizeid          sizedefinition.sizedefinition_id%type;
  gv_stayid          stay.stay_id%type;
  gv_incirc          status.status_id%type;
  gv_assigned        status.status_id%type;

  --Internal procedures
  procedure write_log(fp_priority in number) is
  begin
    /* Logging: write message in ABSLOG with these priorities:
    1 = Message
    2 = Warning
    3 = Error */
    abslogwrite.abslog_write(5, 'wsp_sendtrack_mats', gv_plantid, fp_priority, fp_message,
                             gv_systemuserid);
    begin
      dbms_output.put_line(fp_message);
    exception
      when others then
        null; --ok no output to screen
    end;
  end write_log;

  procedure initialize is
    procedure get_systemuser is
    begin
      --get_systemuser
      gv_message := 'get_systemuser';
      select sy.systemuser_id into gv_systemuserid from systemuser sy where sy.username = 'WSPMAT';
    exception
      when no_data_found then
        gv_systemuserid := 0;
    end get_systemuser;

    procedure get_defaults is
    begin
      --get_defaults
      --get defaults
      gv_message := 'Stay Checkpoint/Inspection, stay nr 33';
      select st.stay_id
      into   gv_stayid
      from   stay st
      where  st.staynr = 33
      and    st.staytype = 1;
      --get status in circ
      gv_message := 'get status incirc  UI/20';
      select ss.status_id
      into   gv_incirc
      from   status ss
      where  ss.statustype = 'UI'
      and    ss.code = '20';
      --get status assinged
      gv_message := 'get status assigned  UI/30';
      select status_id
      into   gv_assigned
      from   status
      where  status.statustype = 'UI'
      and    status.code = '30';
    end get_defaults;
  begin
    --get_systemuser
    get_systemuser;
    --initialize, check parameters
    if fp_plantcode is null then
      begin
        gv_message := 'Parameter fp_plantcode cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        gv_message := 'Plant ' || fp_plantcode;
        select pt.plant_id, ct.defaultcurrency_id,
               (select min(bu.businessunit_id) from businessunit bu where bu.plant_id = pt.plant_id)
        into   gv_plantid, gv_currencyid, gv_businessunitid
        from   plant pt
        join   country ct
        on     ct.country_id = pt.country_id
        where  pt.code = fp_plantcode;
      end;
    end if;
    if fp_idcode is null then
      begin
        gv_message := 'Parameter fp_idcode cannot be left blank!';
        raise gv_userexception;
      end;
    end if;
    if fp_transaction is null then
      begin
        gv_message := 'Parameter fp_transaction cannot be left blank!';
        raise gv_userexception;
      end;
    elsif fp_transaction not in ('A', 'S') then
      begin
        gv_message := 'Parameter fp_transaction must be A or S and is ' || fp_transaction;
        raise gv_userexception;
      end;
    end if;
    if fp_scandate is null then
      begin
        gv_message := 'Parameter fp_scandate (YYYYMMDD) cannot be left blank!';
        raise gv_userexception;
      end;
    end if;
    if fp_scantime is null then
      begin
        gv_message := 'Parameter fp_scantime (HHMISS) (HH=24 hour notation) for example 140723 cannot be left blank!';
        raise gv_userexception;
      end;
    end if;
    --get scandate
    gv_message  := 'Determining scan date/time, format YYYYMMDD for date, HHMISS (HHMISS) (HH=24 hour notation) for time, for example 140723';
    gv_scandate := to_timestamp(fp_scandate || fp_scantime, 'YYYYMMDDHH24MISS');
    if fp_scanlocation is null then
      begin
        gv_message := 'Parameter fp_scanlocation cannot be left blank!';
        raise gv_userexception;
      end;
    else
      begin
        --get workstationcode
        gv_message := 'sortingimportdefinition for plant ' || fp_plantcode || ' location ' ||
                      fp_scanlocation;
        select wo.code
        into   gv_workstationcode
        from   sortingimportdefinition sio
        join   workstation wo
        on     wo.workstation_id = sio.workstation_id
        where  sio.location = fp_scanlocation
        and    sio.nextlocation is null
        and    sio.plant_id = gv_plantid;
      end;
    end if;
    if fp_productid is not null then
      begin
        --check if product id exists
        gv_message := 'fp_productid ' || fp_productid;
        select p.product_id, p.supplier_id
        into   gv_productid, gv_supplierid
        from   product p
        where  p.product_id = fp_productid;
      exception
        when no_data_found then
          begin
            gv_productid := null;
            if fp_transaction = 'A' then
              raise no_data_found;
            end if;
          end;
      end;
    elsif fp_transaction = 'A' then
      begin
        gv_message := 'Parameter fp_productid cannot be left blank for transaction A(ssign)!';
        raise gv_userexception;
      end;
    end if;
    if fp_sizeid is not null then
      begin
        --check if size id exists
        gv_message := 'fp_sizeid ' || fp_sizeid;
        select s.sizedefinition_id
        into   gv_sizeid
        from   sizedefinition s
        where  s.sizedefinition_id = fp_sizeid;
      exception
        when no_data_found then
          begin
            gv_sizeid := null;
            if fp_transaction = 'A' then
              raise no_data_found;
            end if;
          end;
      end;
    elsif fp_transaction = 'A' then
      begin
        gv_message := 'Parameter fp_sizeid cannot be left blank for transaction A(ssign)!';
        raise gv_userexception;
      end;
    end if;
    --get_defaults
    get_defaults;
  end initialize;

  procedure scan_mat is
    lv_rec_uniqueitem uniqueitem%rowtype;
    lv_secondaryid    secondaryuniqueitem.secondaryid%type;

    procedure get_uniqueitem is
    begin
      --get uniqueitem
      gv_message := 'fp_idcode ' || fp_idcode || ' (fp_plantcode ' || fp_plantcode || ')';
      pack_sort2.get_uniqueitem(fp_idcode => fp_idcode, fp_plantcode => fp_plantcode,
                                fp_plantid => gv_plantid, fp_rec_uniqueitem => lv_rec_uniqueitem,
                                fp_secondaryid => lv_secondaryid);
      if lv_rec_uniqueitem.status_id not in (gv_assigned, gv_incirc) then
        begin
          gv_message := 'Primary id ' || fp_idcode ||
                        ' is not in circulation nor assigned, cannot do checkpoint scan!';
          raise gv_userexception;
        end;
      end if;
    end get_uniqueitem;

    procedure create_scan(fp_transactiontype in number) is
      lv_routeid uniqueitemroute.plannedoutroute_id%type;

      procedure get_route is
      begin
        --get_route
        gv_message := 'get_route';
        select nvl(u.plannedoutroute_id, u.lastoutroute_id)
        into   lv_routeid
        from   uniqueitemroute u
        where  u.uniqueitem_id = lv_rec_uniqueitem.uniqueitem_id;
      exception
        when no_data_found then
          lv_routeid := null;
      end get_route;
    begin
      --get_route
      get_route;
      --create_scan
      gv_message := 'create_scan';
      insert into scan
        (scan_id, businessunit_id, scantimestamp, primaryid, customer_link_id,
         weareremployment_link_id, distributionpoint_link_id, product_link_id,
         sizedefinition_link_id, stay_id, status_id, scanstation, issuedate, route_id, reasoncode_id,
         customerowned, year, week, dayno, qualitygrade_id, systemuser_id, timestamp, prevstay_id,
         transactiontype_id, dayslate, uniqueitem_link_id, secondaryid)
      values
        (seq_scan.nextval, lv_rec_uniqueitem.businessunit_id, gv_scandate, fp_idcode,
         lv_rec_uniqueitem.relatedcustomer_id, null, lv_rec_uniqueitem.distributionpoint_id,
         lv_rec_uniqueitem.product_id, lv_rec_uniqueitem.sizedefinition_id, gv_stayid,
         lv_rec_uniqueitem.status_id, gv_workstationcode, null, lv_routeid, null,
         lv_rec_uniqueitem.customerowned, getyearofweek(gv_scandate), getisoweek(gv_scandate),
         getabsdaynumber(gv_scandate), null, gv_systemuserid, sysdate, lv_rec_uniqueitem.stay_id,
         fp_transactiontype, 0, lv_rec_uniqueitem.uniqueitem_id, lv_secondaryid);
    end create_scan;

    procedure update_uniqueitem is
    begin
      --update_uniqueitem
      gv_message := 'update_uniqueitem';
      update uniqueitem u
      set    u.lastscandate = gv_scandate, u.prevstay_id = lv_rec_uniqueitem.stay_id,
             u.stay_id = gv_stayid, u.staychangedate = sysdate, u.systemuser_id = gv_systemuserid,
             u.timestamp = sysdate
      where  u.uniqueitem_id = lv_rec_uniqueitem.uniqueitem_id;
    end update_uniqueitem;

    procedure create_uniqueitem is
      lv_finishingmethodid finishingmethod.finishingmethod_id%type;
      lv_reasoncodeid      reasoncode.reasoncode_id%type;
      lv_qualitygradeid    qualitygrade.qualitygrade_id%type;

      procedure get_defaults is
      begin
        --get_defaults
        gv_message := 'get_defaults';
        select min(rs.reasoncode_id)
        into   lv_reasoncodeid
        from   reasoncode rs
        where  rs.garmentreason = 'Y'
        and    rs.firstissue = 'Y';
        if lv_reasoncodeid is null then
          begin
            select min(rs.reasoncode_id)
            into   lv_reasoncodeid
            from   reasoncode rs
            where  rs.garmentreason = 'Y';
          end;
        end if;
        select min(q.qualitygrade_id)
        into   lv_qualitygradeid
        from   qualitygrade q
        where  q.defaultqualitygrade = 'Y';
        if lv_qualitygradeid is null then
          begin
            select min(q.qualitygrade_id) into lv_qualitygradeid from qualitygrade q;
          end;
        end if;
      end get_defaults;

      procedure check_productsize is
        lv_sequencenumber productsize.sequencenumber%type;
      begin
        --check_productsize
        gv_message := 'check productsize';
        select ps.sequencenumber
        into   lv_sequencenumber
        from   productsize ps
        where  ps.product_id = gv_productid
        and    ps.sizedefinition_id = gv_sizeid;
      exception
        when no_data_found then
          begin
            select max(ps.sequencenumber + 1)
            into   lv_sequencenumber
            from   productsize ps
            where  ps.product_id = gv_productid;
            insert into productsize
              (product_id, sizedefinition_id, sequencenumber, systemuser_id, timestamp)
            values
              (gv_productid, gv_sizeid, nvl(lv_sequencenumber, 1), gv_systemuserid, sysdate);
          end;
      end check_productsize;

      procedure get_finishingmethod is
      begin
        --get_finishingmethod
        gv_message := 'get finishingmethod';
        select min(pf.finishingmethod_id)
        into   lv_finishingmethodid
        from   productfinishingmethod pf
        where  pf.product_id = gv_productid;
      end get_finishingmethod;
    begin
      --get_defaults
      get_defaults;
      --check_productsize
      check_productsize;
      --get_finishingmethod
      get_finishingmethod;
      --create_uniqueitem
      gv_message := 'create uniqueitem';
      -- Inserting the unique items in ABSSolute database.
      insert into uniqueitem
        (uniqueitem_id, primaryid, idcodesequencenumber, statuschangedate, staychangedate,
         lastinscandate, lastoutscandate, lastscandate, iteminfoupdatedate, poolitem, washestotal,
         repairstotal, rewashtotal, customerowned, businessunit_id, status_id, prevstatus_id,
         prevstay_id, stay_id, product_id, sizedefinition_id, finishingmethod_id, relatedcustomer_id,
         distributionpoint_id, lastdistributionpoint_link_id, planneddeliverydate, deliveryfromstock,
         startrentfrom, unrelatedloan_id, systemuser_id, timestamp, residualvalue)
      values
        (seq_uniqueitem.nextval, fp_idcode, 1, sysdate, sysdate, null, null, gv_scandate, null, 1,
         0, 0, 0, 'N', gv_businessunitid, gv_assigned, null, null, gv_stayid, gv_productid,
         gv_sizeid, lv_finishingmethodid, null, null, null, null, 'N', 0, null, gv_systemuserid,
         sysdate, 0)
      returning uniqueitem_id into lv_rec_uniqueitem.uniqueitem_id;
      --fill lv_rec_uniqueitem with data
      select u.*
      into   lv_rec_uniqueitem
      from   uniqueitem u
      where  u.uniqueitem_id = lv_rec_uniqueitem.uniqueitem_id;
      --create link record
      insert into uniqueitem_link
        (uniqueitem_link_id, uniqueitem_id, raggeditem_id, systemuser_id, timestamp)
      values
        (lv_rec_uniqueitem.uniqueitem_id, lv_rec_uniqueitem.uniqueitem_id, null, gv_systemuserid,
         sysdate);
      --created fixedinfo uniqueitem
      insert into uniqueitemfixedinfo
        (uniqueitem_id, purchasedate, lastonstockdate, firstissuedate, lastissuedate,
         numberofissues, enddatefullrent, daysincircprevissue, daysinstockprevious, purchaseprice,
         remark, qualitygrade_id, supplier_id, currency_id, issuedbyworkorder_id, reasoncode_id,
         systemuser_id, timestamp, temporaryid)
      values
        (lv_rec_uniqueitem.uniqueitem_id, trunc(gv_scandate), null, trunc(sysdate), trunc(sysdate),
         1, to_date('31-12-2099', 'dd-mm-yyyy'), 0, 0, 0, null, lv_qualitygradeid, gv_supplierid,
         gv_currencyid, null, lv_reasoncodeid, gv_systemuserid, sysdate, 'N');
    exception
      when dup_val_on_index then
        begin
          gv_message := 'uniqueitem with idcode ' || fp_idcode || ' for plant ' || fp_plantcode ||
                        ' does already exists!';
          raise gv_userexception;
        end;
    end create_uniqueitem;
  begin
    --scan_mat
    gv_message := 'scan_mat';
    case fp_transaction
      when 'S' then
        begin
          --Create checkpoint scan for mats
          --get_uniqueitem mat
          get_uniqueitem;
          --create Checkpoint Scan
          create_scan(6);
          --update uniqueitem
          update_uniqueitem;
        end;
      when 'A' then
        begin
          --Assign new items
          create_uniqueitem;
          --Create assign product scan
          create_scan(34);
        end;
      else
        begin
          gv_message := 'unknown fp_transaction ' || fp_transaction ||
                        ' in procedure wsp_sendtrack_mats.scanmat';
          raise gv_userexception;
        end;
    end case;
  end scan_mat;

  procedure finalize is
  begin
    --finalize
    commit;
    gv_message := 'finalize';
    fp_status  := 0;
    fp_message := 'Ok';
  end finalize;
begin
  --initialize
  initialize;
  --scan_mat
  scan_mat;
  --finalize
  finalize;
exception
  --Exception handling
  when gv_userexception then
    begin
      rollback;
      fp_message := gv_message;
      write_log(3);
      fp_status := 3;
    end;
  when no_data_found then
    begin
      rollback;
      fp_message := 'Error, No Data Found ' || gv_message;
      write_log(3);
      fp_status := 2;
    end;
  when others then
    begin
      rollback;
      fp_message := 'Error ' || sqlerrm || ' ' || gv_message || ' , for idcode ' || fp_idcode;
      write_log(3);
      fp_status := 1;
    end;
end wsp_sendtrack_mats;
/
set define on 
/

