工做經常使用


--報表:注意:AD_PI_ID對應數據字段 別忽略
-----執行計劃
explain plan for sql_statement;

select * from table(dbms_xplan.display);


----後臺自動任務(每五分鐘運行一次):
DECLARE 
  JOB_ID PLS_INTEGER; 
BEGIN 
  SYS.DBMS_JOB.SUBMIT(JOB => JOB_ID, 
                      WHAT => 'XQ_MIDSO_GEN;', 
                      INTERVAL => 'sysdate + 5/(24*60)'); 
  COMMIT; 
END;
------------------------------------------------------------------------------------------
--自動獲取單據編號示例:
                v_table_id        ad_table.id%TYPE; --採購退貨單m_ret_pur表的id
                v_m_ret_pur_docno m_ret_pur.docno%TYPE; ----採購退貨單m_ret_pur單據編號
                --獲取表m_ret_pur的id
                SELECT id
                INTO v_table_id
                FROM ad_table
                WHERE NAME = upper('m_ret_pur');
            
                --自動生成單據編號
                SELECT t.sequencename
                INTO v_m_ret_pur_docno
                FROM ad_column t
                WHERE t.ad_table_id = v_table_id
                AND t.dbname = 'DOCNO';
            
                v_m_ret_pur_docno := get_sequenceno(v_m_ret_pur_docno,
                                                    v.ad_client_id);
                	

------------------------------------------------------------------------------------------
--查看某表或視圖上的觸發器
select * from all_triggers WHERE table_name=upper('m_in');



查看代碼引用:
select * from user_source a where instr(lower(a.TEXT),'get_sequenceno') >= 1;

--擴展類經常使用於明細新增商品時,彈出界面,選擇顏色尺寸和輸入數量
nds.schema.AttributeDetailSupportTableImpl

獲取序號生成器語句:
select * from ad_sequence where name='序號生成器名稱';

--提交狀態:字段翻譯器
nds.web.alert.LimitValueAlerter

italic-purple-font-row
green-font-bold-row


---表的擴展屬性排序示例---------------------------------
{"orderby":[{"column":"BILL_TYPE","desc":false},{"column":"NC_VOUCH_TEMPLETSET_ID","desc":false},{"column":"DOCNO","desc":false}
,{"column":"DEPFLAG", "asc":true},{"column":"NC_ACCSUBJ_ID", "asc":true}]}
---------------------------------------------------------------



------------------------------------------------------------------------------------
查找存儲過程被哪些session鎖住而沒法編譯
select *  FROM dba_ddl_locks where name ='OPERATIONDATA_IMP';


--查看被鎖的表
select   p.spid,c.object_name,b.session_id,b.oracle_username,b.os_user_name   ,b.OBJECT_ID,a.sid,a.SERIAL#
from   v$process   p,v$session   a,   v$locked_object   b,all_objects   c   
where   p.addr=a.paddr   and   a.process=b.process   and   c.object_id=b.object_id-- and c.object_id=111579 
order by p.SPID;


--查看數據庫中的表鎖(特定表被哪些session鎖住)
SELECT A.OWNER,A.OBJECT_NAME,B.XIDUSN,B.XIDSLOT,B.XIDSQN,B.SESSION_ID,
B.ORACLE_USERNAME,B.OS_USER_NAME,B.PROCESS,B.LOCKED_MODE,C.MACHINE,C.STATUS,
C.SERVER,C.SID,C.SERIAL#,C.PROGRAM
FROM ALL_OBJECTS A,V$LOCKED_OBJECT B,SYS.GV_$SESSION C
WHERE ( A.OBJECT_ID = B.OBJECT_ID )
AND (B.PROCESS = C.PROCESS )
ORDER BY 1,2;



------------------------------------------------------------------------------------





---------------------------臨時表沒法修改解決------------------------------------
方法一:
select sid, serial#  
from v$session  
where sid in   
(  
    select sid  
    from v$lock  
    where id1 =   
    (  
        select object_id  
        from user_objects  
        where object_name = upper('rp_o2o_salesources10')  
    )  
);

alter system kill session '140,64317';


方法二:
select  'alter system kill session '||''''||a.SID||','||c.SERIAL#||''';',a.ID1,b.object_name
from v$lock a,dba_objects b,v$session c
where a.ID1=b.object_id and a.SID=c.SID and b.object_name='rp_o2o_salesources10';


alter system kill session 'SID,SERIAL#';
------------------------------------------------------
select count(*) from  B_PAY where STATUS = 1  AND id=$OBJECTID$ AND ISACTIVE='Y'

drop index idx_

---------------------------------解析前臺配置clob字段
v_sql        VARCHAR2(4000);
v_sql1       VARCHAR2(4000);
r_store_ids  r_tabid := r_tabid(); --門店id集合

v_sql := get_fitler_sql(v_marketid);
v_sql1 := 'select t.id from c_store t where t.id ' || v_sql;
r_store_ids := f_fast_table(v_sql1);



-----------------------------------------------------------
單對象界面按鈕:動做定義內調用動做定義
v_mppp_id b_canso.m_product_pub_po_id%TYPE; --added by xy 20180728
v_query      VARCHAR2(255); --added by xy 20180728
v_mppp_tabid ad_table.id%TYPE;--added by xy 20180728


--begin added by xy 20180728
--若是本單的宣傳品徵訂單不爲空,則:調用動做定義【撤單 M_PRODUCT_PUB_PO_CANCEL】
IF v_mppp_id IS NOT NULL THEN

    SELECT id
    INTO v_mppp_tabid
    FROM ad_table
    WHERE NAME = upper('m_product_pub_po');

    v_query := '<id>' || v_mppp_id || '</id><query/><table>' ||
               v_mppp_tabid || '</table>';
    m_product_pub_po_cancel(p_user_id, v_query, r_code, r_message);
END IF;
--end added by xy 20180728

------------------------------------------------------------------------    

---------------------------------------------trigger
CREATE OR REPLACE TRIGGER bi_m_product_pub
    BEFORE UPDATE ON m_product_pub
    FOR EACH ROW
DECLARE
    ----------------------------------------------
    --author:xy
    --date:20180727
    --description:
    --若是品種狀態不爲0或1,不容許修改商品編碼。
    --更新是否有尺寸要求、計量單位、備註、商品編碼爲最新的是否有尺寸要求、計量單位、備註、商品編碼

    ---------------------------------------------- 

BEGIN
    --若是品種狀態不爲0或1,不容許修改商品編碼
    IF (:new.typestatus <> 0 AND :new.typestatus <> 1) THEN
        raise_application_error(-20001, '品種狀態不爲0或1,不容許修改商品編碼!');
    END IF;

    --更新是否有尺寸要求、計量單位、備註、商品編碼爲最新的是否有尺寸要求、計量單位、備註、商品編碼
    UPDATE m_product_pub mpp
    SET mpp.is_size = :new.is_size, mpp.units = :new.units,
        mpp.description = :new.description, mpp.m_product_id = :new.m_product_id;
END;

---------------------------------------------
--AC模板
CREATE OR REPLACE PROCEDURE C_REBATE_ADJUST_AC(p_id IN NUMBER) AS
    -------------------------------------------------------------------------
    --History1.
    --Author:xuyang
    --Date:20180604
    --Description:
    --將庫存表中店倉在頭表所選的店倉內、款號上對應的供應商爲頭表所選的供應商、庫存數量>0的數據插入到本單明細中
    /*店倉:取符合條件的庫存表的店倉
    條碼、商品、ASI:取符合條件的庫存表裏面的條碼、商品、ASI
    庫存數量:取對應店倉、對應條碼的庫存數量
    採購價:取對應款號檔案的採購價
    返利:取對應款號檔案的固定返利
    當期成本:取【商品成本】表中該款號的單品成本
    調整成本:取採購價 - 返利
    */
    -------------------------------------------------------------------------
    
begin
  

end;

-----------------------------------------------------




--提交存儲過程模板
CREATE OR REPLACE PROCEDURE m_purchase_submit(p_submittedsheetid IN NUMBER,
                                              r_code             OUT NUMBER,
                                              r_message          OUT VARCHAR2) AS
    -------------------------------------------------------------------------
    --1. Author:XY
    --Date:20180728
    --Description:
    --
    --
    --
    -------------------------------------------------------------------------
    v_status number(1);    

BEGIN

    --併發控制,20120216 add by vetica
    EXECUTE IMMEDIATE ('select 1 from table_name t where t.id=' ||
                      p_submittedsheetid || ' for update');

    SELECT ad_client_id, status, modifierid, doctype, docno, p.b_po_id, p.isagt,
           description, p.is_bas
    INTO v_clientid, v_status, v_userid, v_doctype, v_docno, v_po_id, v_isagt,
         v_description, v_is_bas
    FROM m_purchase p
    WHERE id = p_submittedsheetid;

    IF v_status = 2 THEN
        raise_application_error(-20201, '單據已提交,不能重複提交!');
    
    END IF;

    

    --更新提交標記,提交人,提交時間
    UPDATE m_purchase t
    SET t.status = 2, t.statuserid = v_userid, t.statustime = SYSDATE
    WHERE t.id = p_submittedsheetid;

    UPDATE m_purchaseitem
    SET status = 2
    WHERE m_purchase_id = p_submittedsheetid;

    r_code := 0;
    r_message := v_docno || '提交成功!!';
END;


--地素:薪資管理-》基本薪資管理(author:me)
CREATE OR REPLACE PROCEDURE C_BASIC_SALARY_UNSUBMIT(p_submittedsheetid IN NUMBER,
                                                r_code             OUT NUMBER,
                                                r_message          OUT VARCHAR2) AS
    -------------------------------------------------------------------------
    --HISTORY:
    --1.AUTHOR:XUYANG
    --  DATE:20180601
    --  DESCRIPTION: 若是單據未提交,不容許取消提交。
    -- 更新單據狀態爲一、提交人爲空、提交時間爲空
    -------------------------------------------------------------------------

    v_status C_BASIC_SALARY.status%TYPE; --單據提交狀態
    v_docno  C_BASIC_SALARY.docno%TYPE; --單據編號

BEGIN
    --併發控制
    BEGIN
        EXECUTE IMMEDIATE 'select 1 from C_BASIC_SALARY t where t.id=' ||
                          p_submittedsheetid || ' for update nowait';
    EXCEPTION
        WHEN OTHERS THEN
            raise_application_error(-20201, '單據正在取消提交,不能重複取消!');
    END;

    --若是單據未提交,不容許取消提交
    SELECT cbs.status, cbs.docno
    INTO v_status, v_docno
    FROM C_BASIC_SALARY cbs
    WHERE cbs.id = p_submittedsheetid;

    IF v_status = 1 THEN
        raise_application_error(-20201, '單據未提交,不容許取消提交!');
    END IF;

    -- 更新單據狀態爲一、提交人爲空、提交時間爲空
    UPDATE C_BASIC_SALARY cbs
    SET cbs.status = 1, cbs.statuserid = NULL, cbs.statustime = NULL
    WHERE cbs.id = p_submittedsheetid;

    r_code := 0;
    r_message := v_docno || '取消提交成功!!';

END;



--奇客巴士:成本與月結->返利成本調整ac程序(author:me):
CREATE OR REPLACE PROCEDURE c_rebate_adjust_ac(p_id IN NUMBER) AS
    -------------------------------------------------------------------------
    --History1.
    --Author:xuyang
    --Date:20180604
    --Description:
    --將庫存表中店倉在頭表所選的店倉內、款號上對應的供應商爲頭表所選的供應商、庫存數量>0的數據插入到本單明細中
    /*店倉:取符合條件的庫存表的店倉
    條碼、商品、ASI:取符合條件的庫存表裏面的條碼、商品、ASI
    庫存數量:取對應店倉、對應條碼的庫存數量
    採購價:取對應款號檔案的採購價
    返利:取對應款號檔案的固定返利
    當期成本:取【商品成本】表中該款號的單品成本
    調整成本:取採購價 - 返利
    --注意:
    (1)若是頭表的供應商不爲空,店倉不爲空,則取庫存表中店倉在頭表所選的店倉內、款號上對應的供應商爲頭表所選的供應商、庫存數量>0的數據插入到本單明細;
    (2)若是頭表的供應商不爲空,店倉爲空,則取庫存表中、全部店倉下的、庫存數量>0的、款號對應的供應商爲頭表所選供應商的、全部條碼的數據插入到明細;
    (3)若是頭表的供應商爲空、店倉不爲空,則取所選店倉在庫存表中、全部庫存數量>0的全部條碼的數據插入到明細;
    (4)若是頭表的供應商爲空、店倉爲空,則取庫存表中、全部店倉下的、庫存數量>0的全部條碼的數據插入到明細
    */
    -------------------------------------------------------------------------
    v_ad_client_id c_rebate_adjust.ad_client_id%TYPE;
    v_ad_org_id    c_rebate_adjust.ad_org_id%TYPE;
    v_ownerid      c_rebate_adjust.ownerid%TYPE;
    --v_modifierid C_REBATE_ADJUST.MODIFIERID%type;
    --v_createdate C_REBATE_ADJUST.CREATIONDATE%type;
    --v_modifydate C_REBATE_ADJUST.MODIFIEDDATE%type;
    --v_cra_id c_rebate_adjust.id%TYPE;
    --v_c_store_id c_store.id%type;
    v_c_supplier_id c_rebate_adjust.c_supplier_id%TYPE;
    /*用於獲取所選店倉id集合*/
    v_rebate_adjust  c_rebate_adjust%ROWTYPE;
    v_sql            VARCHAR2(4000);
    v_sql1           VARCHAR2(4000);
    r_store          r_tabid := r_tabid(); --店倉集合
    v_c_store_filter c_rebate_adjust.c_store_filter%TYPE;

    /*用於獲取庫存中知足條件(1)的數據記錄*/
    CURSOR cur_fa_storage1 IS
        SELECT fas.m_product_id AS m_product_id, fas.c_store_id AS c_store_id,
               fas.m_attributesetinstance_id AS m_attributesetinstance_id,
               fas.qty AS qtystorage, fas.m_productalias_id AS m_productalias_id,
               mp.precost AS precost, mp.fixrebate AS fixrebate,
               fapc.percost AS precost_th,
               (mp.precost - nvl(mp.fixrebate, 0)) AS precost_adj
        FROM fa_storage fas
        JOIN m_product mp
        ON (fas.m_product_id = mp.id)
        LEFT JOIN fa_product_cost fapc
        ON (fapc.m_product_id = fas.m_product_id)
        WHERE fas.qty > 0
        AND mp.c_supplier_id = v_c_supplier_id
        AND EXISTS (SELECT 1
               FROM TABLE(r_store) t
               WHERE t.id = fas.c_store_id);
    TYPE list_table1 IS TABLE OF cur_fa_storage1%ROWTYPE INDEX BY BINARY_INTEGER;
    type_list_table1 list_table1;

    /*用於獲取庫存中知足條件(2)的數據記錄*/
    CURSOR cur_fa_storage2 IS
        SELECT fas.m_product_id AS m_product_id, fas.c_store_id AS c_store_id,
               fas.m_attributesetinstance_id AS m_attributesetinstance_id,
               fas.qty AS qtystorage, fas.m_productalias_id AS m_productalias_id,
               mp.precost AS precost, mp.fixrebate AS fixrebate,
               fapc.percost AS precost_th,
               (mp.precost - nvl(mp.fixrebate, 0)) AS precost_adj
        FROM fa_storage fas
        JOIN m_product mp
        ON (fas.m_product_id = mp.id)
        LEFT JOIN fa_product_cost fapc
        ON (fapc.m_product_id = fas.m_product_id)
        WHERE fas.qty > 0
        AND mp.c_supplier_id = v_c_supplier_id;
    TYPE list_table2 IS TABLE OF cur_fa_storage2%ROWTYPE INDEX BY BINARY_INTEGER;
    type_list_table2 list_table2;

    /*用於獲取庫存中知足條件(3)的數據記錄*/
    CURSOR cur_fa_storage3 IS
        SELECT fas.m_product_id AS m_product_id, fas.c_store_id AS c_store_id,
               fas.m_attributesetinstance_id AS m_attributesetinstance_id,
               fas.qty AS qtystorage, fas.m_productalias_id AS m_productalias_id,
               mp.precost AS precost, mp.fixrebate AS fixrebate,
               fapc.percost AS precost_th,
               (mp.precost - nvl(mp.fixrebate, 0)) AS precost_adj
        FROM fa_storage fas
        JOIN m_product mp
        ON (fas.m_product_id = mp.id)
        LEFT JOIN fa_product_cost fapc
        ON (fapc.m_product_id = fas.m_product_id)
        WHERE fas.qty > 0
        AND EXISTS (SELECT 1
               FROM TABLE(r_store) t
               WHERE t.id = fas.c_store_id);
    TYPE list_table3 IS TABLE OF cur_fa_storage3%ROWTYPE INDEX BY BINARY_INTEGER;
    type_list_table3 list_table3;

    /*用於獲取庫存中知足條件(4)的數據記錄*/
    CURSOR cur_fa_storage4 IS
        SELECT fas.m_product_id AS m_product_id, fas.c_store_id AS c_store_id,
               fas.m_attributesetinstance_id AS m_attributesetinstance_id,
               fas.qty AS qtystorage, fas.m_productalias_id AS m_productalias_id,
               mp.precost AS precost, mp.fixrebate AS fixrebate,
               fapc.percost AS precost_th,
               (mp.precost - nvl(mp.fixrebate, 0)) AS precost_adj
        FROM fa_storage fas
        JOIN m_product mp
        ON (fas.m_product_id = mp.id)
        LEFT JOIN fa_product_cost fapc
        ON (fapc.m_product_id = fas.m_product_id)
        WHERE fas.qty > 0;
    TYPE list_table4 IS TABLE OF cur_fa_storage4%ROWTYPE INDEX BY BINARY_INTEGER;
    type_list_table4 list_table4;

BEGIN
    --獲取相關數據
    SELECT cra.ad_client_id, cra.ad_org_id, cra.ownerid, cra.c_supplier_id,
           cra.c_store_filter
    INTO v_ad_client_id,v_ad_org_id,v_ownerid, v_c_supplier_id, v_c_store_filter
    FROM c_rebate_adjust cra
    WHERE cra.id = p_id;

    --獲取所選店倉集合
    IF v_c_store_filter IS NOT NULL THEN
        SELECT *
        INTO v_rebate_adjust
        FROM c_rebate_adjust cra
        WHERE cra.id = p_id;
        v_sql := get_fitler_sql(v_rebate_adjust.c_store_filter);
        v_sql1 := 'select  t.id  from c_store t where t.id ' || v_sql;
        r_store := f_fast_table(v_sql1);
    END IF;
    --將庫存表中店倉在頭表所選的店倉內、款號上對應的供應商爲頭表所選的供應商、庫存數量>0的數據插入到本單明細中

    IF v_c_supplier_id IS NOT NULL AND r_store.count > 0 THEN
        BEGIN
            OPEN cur_fa_storage1;
            FETCH cur_fa_storage1 BULK COLLECT
                INTO type_list_table1;
            FORALL idx IN 1 .. type_list_table1.count
                INSERT INTO c_rebate_adjustitem crai
                    (crai.id, crai.ad_client_id, crai.ad_org_id, crai.ownerid,
                     crai.modifierid, crai.creationdate, crai.modifieddate,
                     crai.c_rebate_adjust_id, crai.c_store_id,
                     crai.m_productalias_id, crai.m_product_id, crai.qtystorage,
                     crai.precost, crai.fixrebate, crai.precost_ths,
                     crai.precost_adj, crai.m_attributesetinstance_id)
                VALUES
                    (get_sequences('C_REBATE_ADJUSTITEM'), v_ad_client_id,
                     v_ad_org_id, v_ownerid, NULL, SYSDATE, NULL, p_id,
                     type_list_table1(idx).c_store_id,
                     type_list_table1(idx).m_productalias_id,
                     type_list_table1(idx).m_product_id,
                     type_list_table1(idx).qtystorage,
                     type_list_table1(idx).precost,
                     type_list_table1(idx).fixrebate,
                     type_list_table1(idx).precost_th,
                     type_list_table1(idx).precost_adj,
                     type_list_table1(idx).m_attributesetinstance_id);
            CLOSE cur_fa_storage1;
        END;
    ELSIF v_c_supplier_id IS NOT NULL AND r_store.count = 0 THEN
        --若是頭表的供應商不爲空,店倉爲空,則取庫存表中、全部店倉下的、庫存數量>0的、款號對應的供應商爲頭表所選供應商的、全部條碼的數據插入到明細
        BEGIN
            OPEN cur_fa_storage2;
            FETCH cur_fa_storage2 BULK COLLECT
                INTO type_list_table2;
            FORALL idx IN 1 .. type_list_table2.count
                INSERT INTO c_rebate_adjustitem crai
                    (crai.id, crai.ad_client_id, crai.ad_org_id, crai.ownerid,
                     crai.modifierid, crai.creationdate, crai.modifieddate,
                     crai.c_rebate_adjust_id, crai.c_store_id,
                     crai.m_productalias_id, crai.m_product_id, crai.qtystorage,
                     crai.precost, crai.fixrebate, crai.precost_ths,
                     crai.precost_adj, crai.m_attributesetinstance_id)
                VALUES
                    (get_sequences('C_REBATE_ADJUSTITEM'), v_ad_client_id,
                     v_ad_org_id, v_ownerid, NULL, SYSDATE, NULL, p_id,
                     type_list_table2(idx).c_store_id,
                     type_list_table2(idx).m_productalias_id,
                     type_list_table2(idx).m_product_id,
                     type_list_table2(idx).qtystorage,
                     type_list_table2(idx).precost,
                     type_list_table2(idx).fixrebate,
                     type_list_table2(idx).precost_th,
                     type_list_table2(idx).precost_adj,
                     type_list_table2(idx).m_attributesetinstance_id);
            CLOSE cur_fa_storage2;
        END;
    ELSIF nvl(v_c_supplier_id, 0) = 0 AND r_store.count > 0 THEN
        --若是頭表的供應商爲空、店倉不爲空,則取所選店倉在庫存表中、全部庫存數量>0的全部條碼的數據插入到明細;
        BEGIN
            OPEN cur_fa_storage3;
            FETCH cur_fa_storage3 BULK COLLECT
                INTO type_list_table3;
            FORALL idx IN 1 .. type_list_table3.count
                INSERT INTO c_rebate_adjustitem crai
                    (crai.id, crai.ad_client_id, crai.ad_org_id, crai.ownerid,
                     crai.modifierid, crai.creationdate, crai.modifieddate,
                     crai.c_rebate_adjust_id, crai.c_store_id,
                     crai.m_productalias_id, crai.m_product_id, crai.qtystorage,
                     crai.precost, crai.fixrebate, crai.precost_ths,
                     crai.precost_adj, crai.m_attributesetinstance_id)
                VALUES
                    (get_sequences('C_REBATE_ADJUSTITEM'), v_ad_client_id,
                     v_ad_org_id, v_ownerid, NULL, SYSDATE, NULL, p_id,
                     type_list_table3(idx).c_store_id,
                     type_list_table3(idx).m_productalias_id,
                     type_list_table3(idx).m_product_id,
                     type_list_table3(idx).qtystorage,
                     type_list_table3(idx).precost,
                     type_list_table3(idx).fixrebate,
                     type_list_table3(idx).precost_th,
                     type_list_table3(idx).precost_adj,
                     type_list_table3(idx).m_attributesetinstance_id);
            CLOSE cur_fa_storage3;
        END;
    ELSE
        --若是頭表的供應商爲空、店倉爲空,則取庫存表中、全部店倉下的、庫存數量>0的全部條碼的數據插入到明細
        BEGIN
            OPEN cur_fa_storage4;
            FETCH cur_fa_storage4 BULK COLLECT
                INTO type_list_table4;
            FORALL idx IN 1 .. type_list_table4.count
                INSERT INTO c_rebate_adjustitem
                    (id, ad_client_id, ad_org_id, ownerid, modifierid,
                     creationdate, modifieddate, c_rebate_adjust_id, c_store_id,
                     m_productalias_id, m_product_id, qtystorage, precost,
                     fixrebate, precost_ths, precost_adj,
                     m_attributesetinstance_id, isactive)
                VALUES
                    (get_sequences('C_REBATE_ADJUSTITEM'), v_ad_client_id,
                     v_ad_org_id, v_ownerid, NULL, SYSDATE, NULL, p_id,
                     type_list_table4(idx).c_store_id,
                     type_list_table4(idx).m_productalias_id,
                     type_list_table4(idx).m_product_id,
                     type_list_table4(idx).qtystorage,
                     type_list_table4(idx).precost,
                     type_list_table4(idx).fixrebate,
                     type_list_table4(idx).precost_th,
                     type_list_table4(idx).precost_adj,
                     type_list_table4(idx).m_attributesetinstance_id, 'Y');
        
            CLOSE cur_fa_storage4;
        END;
    END IF;

END;




----奇客巴士:成本與月結->返利成本調整提交程序(author:me)
CREATE OR REPLACE PROCEDURE c_rebate_adjust_submit(p_submittedsheetid IN NUMBER,
                                                   r_code             OUT NUMBER,
                                                   r_message          OUT VARCHAR2) AS
    -------------------------------------------------------------------------
    --History:
    --1. Author:xuyang
    --Date:2018-06-05
    --增長控制:若是單據已經提交,不容許再次提交
    --增長控制:若是明細中同一個商品存在調整成本不一致的記錄,不容許!(提示:商品:XXX,在明細中的調整成本不一致,不容許!)
    --增長控制:將本單數據生成一張已提交的成本調整單:
    /*
    單據編號:自動生成。
    單據日期:返利成本調整單的單據日期。
    經銷商:取經銷商級別爲‘總部’的經銷商檔案的ID。
    年月:返利成本調整單的單據日期對應的年月。
    備註:由返利成本調整單:XXX 提交生成!
    */
    --增長控制:將本單明細的數據按照商品彙總,生成成本調整單明細:
    /*
    商品:返利成本調整單明細的商品。
    單品成本:取明細中該商品的調整成本(取平均值,不能取合計值)
    */
    --更新單據狀態爲二、提交人爲單據的修改人、提交時間爲SYSDATE。
    --
    -------------------------------------------------------------------------
    v_status         c_rebate_adjust.status%TYPE; --單據提交狀態
    v_docno          c_rebate_adjust.docno%TYPE; --單據號
    v_submituserid   c_rebate_adjust.modifierid%TYPE; --提交人爲修改人
    v_item_cnt       NUMBER(10); --明細數量
    v_precost_adj    c_rebate_adjustitem.precost_adj%TYPE; --調整價
    v_billdate       c_rebate_adjust.billdate%TYPE; --單據日期
    v_m_product_name m_product.name%TYPE; --款號名

    v_ownerid           c_rebate_adjust.ownerid%TYPE;
    v_ad_org_id         c_rebate_adjust.ad_org_id%TYPE;
    v_ad_client_id      c_rebate_adjust.ad_client_id%TYPE;
    v_cost_adj_docno    fa_costinitial.docno%TYPE; --成本調整單據編號
    v_description       fa_costinitial.description%TYPE; --成本調整單備註
    v_c_customer_id     fa_costinitial.c_customer_id%TYPE; --成本調整單經銷商id
    v_fa_costinitial_id fa_costinitial.id%TYPE;

    v_table_id     ad_table.id%TYPE; --表fa_costinitial的id
    v_norepeat_cnt NUMBER(10); --返利成本調整單明細商品數(不重複)

BEGIN
    --併發控制
    EXECUTE IMMEDIATE ('select 1 from c_rebate_adjust t where t.id=' ||
                      p_submittedsheetid || ' for update');

    --若是單據已經提交,不容許再次提交
    SELECT cra.status, cra.docno, cra.modifierid, cra.billdate, ad_client_id,
           ad_org_id, ownerid
    INTO v_status, v_docno, v_submituserid, v_billdate, v_ad_client_id,
         v_ad_org_id, v_ownerid
    FROM c_rebate_adjust cra
    WHERE cra.id = p_submittedsheetid;

    IF v_status = 2 THEN
        raise_application_error(-20201, '單據已提交,不容許重複提交!');
    END IF;

    --獲取明細數量
    SELECT COUNT(1)
    INTO v_item_cnt
    FROM c_rebate_adjustitem crai
    WHERE crai.c_rebate_adjust_id = p_submittedsheetid;

    --若是明細中同一個商品存在調整成本不一致的記錄,不容許!(提示:商品:XXX,在明細中的調整成本不一致,不容許!)
    IF v_item_cnt >= 2 THEN
    
        FOR v_list IN (SELECT crai.id, crai.m_product_id,
                              nvl(crai.precost_adj, 0) AS precost_adj
                       FROM c_rebate_adjustitem crai
                       WHERE crai.c_rebate_adjust_id = p_submittedsheetid) LOOP
        
            SELECT nvl(crai1.precost_adj, 0) AS precost_adj
            INTO v_precost_adj
            FROM c_rebate_adjustitem crai1
            WHERE crai1.id <> v_list.id
            AND crai1.m_product_id = v_list.m_product_id
            AND rownum <= 1;
        
            IF v_list.precost_adj <> v_precost_adj THEN
            
                SELECT mp.name
                INTO v_m_product_name
                FROM m_product mp
                WHERE mp.id = v_list.m_product_id;
            
                raise_application_error(-20201,
                                        '商品:' || v_m_product_name ||
                                         ',在明細中的調整成本不一致,不容許!');
            END IF;
        END LOOP;
    END IF;

    --增長控制:將本單數據生成一張已提交的成本調整單
    /*
    單據編號:自動生成。
    單據日期:返利成本調整單的單據日期。
    經銷商:取經銷商級別爲‘總部’的經銷商檔案的ID。
    年月:返利成本調整單的單據日期對應的年月。
    備註:由返利成本調整單:XXX 提交生成!   
    */
    v_fa_costinitial_id := get_sequences('fa_costinitial');

    --獲取表fa_costinitial的id
    SELECT id
    INTO v_table_id
    FROM ad_table
    WHERE NAME = upper('fa_costinitial');

    --自動生成單據編號
    SELECT t.sequencename
    INTO v_cost_adj_docno
    FROM ad_column t
    WHERE t.ad_table_id = v_table_id
    AND t.dbname = 'DOCNO';

    v_cost_adj_docno := get_sequenceno(v_cost_adj_docno, v_ad_client_id);

    v_description := '由返利成本調整單:' || v_docno || '提交生成!';

    --獲取明細商品非重複數量
    SELECT COUNT(DISTINCT(m_product_id))
    INTO v_norepeat_cnt
    FROM c_rebate_adjustitem crai
    WHERE crai.c_rebate_adjust_id = p_submittedsheetid;

    --取經銷商級別爲‘總部’的經銷商檔案的ID
    SELECT cc.id
    INTO v_c_customer_id
    FROM c_customer cc
    JOIN c_cusrank ccr
    ON (cc.c_cusrank_id = ccr.id)
    WHERE ccr.name = '總部';

    INSERT INTO fa_costinitial fac
        (id, ad_client_id, ad_org_id, ownerid, modifierid, creationdate,
         modifieddate, isactive, docno, doctype, billdate, description, status,
         au_state, au_pi_id, tot_lines, c_period_id, submitdate, statuserid,
         statustime, c_customer_id, yearmonth)
    VALUES
        (v_fa_costinitial_id, v_ad_client_id, v_ad_org_id, v_ownerid,
         v_submituserid, SYSDATE, SYSDATE, 'Y', v_cost_adj_docno, NULL,
         v_billdate, v_description, 1, NULL, NULL, v_norepeat_cnt, NULL, NULL,
         NULL, NULL, v_c_customer_id, substr(v_billdate, 1, 6));

    --增長控制:將本單明細的數據按照商品彙總,生成成本調整單明細:
    /*
    商品:返利成本調整單明細的商品。
    單品成本:取明細中該商品的調整成本(取平均值,不能取合計值)
    */
    FOR v_list1 IN (SELECT m_product_id, AVG(precost_adj) AS precost_adj
                    FROM c_rebate_adjustitem
                    WHERE c_rebate_adjust_id = p_submittedsheetid
                    GROUP BY m_product_id) LOOP
        INSERT INTO fa_costinitialitem faci
            (id, ad_client_id, ad_org_id, ownerid, modifierid, creationdate,
             modifieddate, isactive, fa_costinitial_id, m_product_id, percost,
             status)
        VALUES
            (get_sequences('fa_costinitialitem'), v_ad_client_id, v_ad_org_id,
             v_ownerid, v_submituserid, SYSDATE, NULL, 'Y', v_fa_costinitial_id,
             v_list1.m_product_id, v_list1.precost_adj, 1);
    END LOOP;

    -- 更新單據狀態爲二、提交人爲單據的修改人、提交時間爲SYSDATE
    UPDATE c_rebate_adjust cra
    SET cra.status = 2, cra.statuserid = v_submituserid,
        cra.statustime = SYSDATE
    WHERE cra.id = p_submittedsheetid;

    r_code := 0;
    r_message := v_docno || '提交成功!!';

END;



--新駿:訂單總彙報表示例(author:others):
CREATE OR REPLACE PROCEDURE rp_posum_gen(p_pi_id NUMBER) IS
    --Author:Arwen
    -- 1. Date:20180521
    -- Author :Arwen
    -- Modification :
    /*新增報表模板【訂單總彙報表】,類型:統計報表,類別:財務報表,事實表:RP_POSUM,
    預計算程序:RP_POSUM_GEN,具體邏輯:
    查詢條件:單據日期(日期範圍、必填) 、商品(關聯款號檔案,非必填)、
    供應商(外鍵關聯供應商檔案,多選,非必填)、採購訂單(外鍵關聯採購訂單,多選,非必填)、
    店倉(外鍵關聯店倉檔案,多選,非必填)、工廠交期(日期範圍、必填)、客人交期(日期範圍、必填)
    查詢邏輯: 取單據日期在查詢條件日期範圍內、商品在查詢條件的商品內、
    供應商在查詢條件的供應商內、採購訂單在查詢條件的採購訂單內、
    採購店倉在查詢條件的店倉內、已提交、可用的【採購訂單】的數據。*/

    -- 2. Date:20180607
    -- Author :xuyang
    -- Modification :修改彙總字段: 運費和毛利
    /* 運費:
      原邏輯:取符合條件的銷售單對應的銷售覈價單表頭的【運費】字段(若是沒有核價單,運費就取0)
      現邏輯:取符合條件的銷售單對應的銷售覈價單明細的【運費】字段(若是沒有核價單,運費就取0
      
      毛利:
      原邏輯:賣價-買價。
      現邏輯:賣價-買價-運費
    */

    v_sql_0        VARCHAR(4000); --原始SQL
    v_modifierid   ad_pinstance.modifierid%TYPE; --修改人
    v_ad_client_id ad_pinstance.ad_client_id%TYPE; --所屬公司
    v_ad_org_id    ad_pinstance.ad_org_id%TYPE; --所屬組織

    v_date      LONG; --日期
    v_datebegin NUMBER(8); --單據日期開始
    v_dateend   NUMBER(8); --單據日期結束

    v_date2      LONG; --日期
    v_datebegin2 NUMBER(8); --工廠日期開始
    v_dateend2   NUMBER(8); --工廠日期結束

    v_date3      LONG; --日期
    v_datebegin3 NUMBER(8); --客人日期開始
    v_dateend3   NUMBER(8); --客人日期結束

    r_c_supplier_id r_tabid; --供應商檢索
    r_b_po_id       r_tabid; --採購訂單檢索
    r_m_product     r_tabid; --款號檢索
    r_c_store       r_tabid; --店檢索
    v_sql_1         LONG; --檢索條件1
    v_sql_2         LONG; --檢索條件2
    v_sql_3         LONG; --檢索條件3
    v_sql_4         LONG;
BEGIN
    EXECUTE IMMEDIATE ('truncate TABLE  RP_POSUM');
    --raise_application_error(-20201, p_pi_id);
    /*獲取檢索條件*/
    v_sql_0 := 'select t.info from ad_pinstance_para t
            where t.name=:name and t.ad_pinstance_id=:pid';
    SELECT t.modifierid, t.ad_client_id, t.ad_org_id
    INTO v_modifierid, v_ad_client_id, v_ad_org_id
    FROM ad_pinstance t
    WHERE t.id = p_pi_id;

    --供應商集合
    EXECUTE IMMEDIATE v_sql_0
        INTO v_sql_1
        USING 'SUP', p_pi_id;
    r_c_supplier_id := f_fast_table(v_sql_1);
    --採購訂單
    EXECUTE IMMEDIATE v_sql_0
        INTO v_sql_2
        USING 'DOCNO', p_pi_id;
    r_b_po_id := f_fast_table(v_sql_2);

    --款號
    EXECUTE IMMEDIATE v_sql_0
        INTO v_sql_3
        USING 'PRODUCT', p_pi_id;
    r_m_product := f_fast_table(v_sql_3);

    --店倉
    EXECUTE IMMEDIATE v_sql_0
        INTO v_sql_4
        USING 'C_STORE', p_pi_id;
    r_c_store := f_fast_table(v_sql_4);

    --單據日期
    SELECT t.info
    INTO v_date
    FROM ad_pinstance_para t
    WHERE t.name = 'BILLDATE'
    AND t.ad_pinstance_id = p_pi_id;

    IF v_date IS NULL THEN
        --如開始日期和結束日期都沒有選擇,則查詢全部日期範圍內數據
        v_datebegin := 0;
        v_dateend := 20991231;
    ELSE
        IF instr(v_date, '>=') > 0 THEN
            --如只選擇了開始日期,則結束日期默認爲20991231
            v_dateend := 20991231;
            SELECT substr(v_date, 13, 8) --注意這裏是否是從9開始,取決於日期參數定義,例如日期參數名定義爲DATE,則此處爲9,如定義爲BILLDATE,此處爲13,以此類推
            INTO v_datebegin
            FROM dual;
        ELSIF instr(v_date, '<=') > 0 THEN
            --如只選擇告終束日期,則開始日期默認爲0
            v_datebegin := 0;
            SELECT substr(v_date, 13, 8) --注意這裏是否是從9開始,取決於日期參數定義,例如日期參數名定義爲DATE,則此處爲9,如定義爲BILLDATE,此處爲13,以此類推
            INTO v_dateend
            FROM dual;
        ELSE
            --如開始日期和結束日期都進行了選擇,則均從參數值獲取
            SELECT substr(v_date, 21, 8), substr(v_date, 34, 8) --注意這裏是否是分別從17,30開始,也是取決於日期參數定義,,例如日期參數名定義爲DATE,則此處爲1七、30,如定義爲BILLDATE,此處爲2一、34,以此類推
            INTO v_datebegin, v_dateend
            FROM dual;
        END IF;
    END IF;

    --工廠交期
    SELECT t.info
    INTO v_date2
    FROM ad_pinstance_para t
    WHERE t.name = 'GCJQDATE'
    AND t.ad_pinstance_id = p_pi_id;

    IF v_date2 IS NULL THEN
        --如開始日期和結束日期都沒有選擇,則查詢全部日期範圍內數據
        v_datebegin2 := 0;
        v_dateend2 := 20991231;
    ELSE
        IF instr(v_date2, '>=') > 0 THEN
            --如只選擇了開始日期,則結束日期默認爲20991231
            v_dateend2 := 20991231;
            SELECT substr(v_date2, 13, 8) --注意這裏是否是從9開始,取決於日期參數定義,例如日期參數名定義爲DATE,則此處爲9,如定義爲BILLDATE,此處爲13,以此類推
            INTO v_datebegin2
            FROM dual;
        ELSIF instr(v_date2, '<=') > 0 THEN
            --如只選擇告終束日期,則開始日期默認爲0
            v_datebegin2 := 0;
            SELECT substr(v_date2, 13, 8) --注意這裏是否是從9開始,取決於日期參數定義,例如日期參數名定義爲DATE,則此處爲9,如定義爲BILLDATE,此處爲13,以此類推
            INTO v_dateend2
            FROM dual;
        ELSE
            --如開始日期和結束日期都進行了選擇,則均從參數值獲取
            SELECT substr(v_date2, 21, 8), substr(v_date2, 34, 8) --注意這裏是否是分別從17,30開始,也是取決於日期參數定義,,例如日期參數名定義爲DATE,則此處爲1七、30,如定義爲BILLDATE,此處爲2一、34,以此類推
            INTO v_datebegin2, v_dateend2
            FROM dual;
        END IF;
    END IF;

    --客人交期
    SELECT t.info
    INTO v_date3
    FROM ad_pinstance_para t
    WHERE t.name = 'KRJQDATE'
    AND t.ad_pinstance_id = p_pi_id;

    IF v_date3 IS NULL THEN
        --如開始日期和結束日期都沒有選擇,則查詢全部日期範圍內數據
        v_datebegin3 := 0;
        v_dateend3 := 20991231;
    ELSE
        IF instr(v_date3, '>=') > 0 THEN
            --如只選擇了開始日期,則結束日期默認爲20991231
            v_dateend3 := 20991231;
            SELECT substr(v_date3, 13, 8) --注意這裏是否是從9開始,取決於日期參數定義,例如日期參數名定義爲DATE,則此處爲9,如定義爲BILLDATE,此處爲13,以此類推
            INTO v_datebegin3
            FROM dual;
        ELSIF instr(v_date3, '<=') > 0 THEN
            --如只選擇告終束日期,則開始日期默認爲0
            v_datebegin3 := 0;
            SELECT substr(v_date3, 13, 8) --注意這裏是否是從9開始,取決於日期參數定義,例如日期參數名定義爲DATE,則此處爲9,如定義爲BILLDATE,此處爲13,以此類推
            INTO v_dateend3
            FROM dual;
        ELSE
            --如開始日期和結束日期都進行了選擇,則均從參數值獲取
            SELECT substr(v_date3, 21, 8), substr(v_date3, 34, 8) --注意這裏是否是分別從17,30開始,也是取決於日期參數定義,,例如日期參數名定義爲DATE,則此處爲1七、30,如定義爲BILLDATE,此處爲2一、34,以此類推
            INTO v_datebegin3, v_dateend3
            FROM dual;
        END IF;
    END IF;

    /* 原邏輯:取符合條件的銷售單對應的銷售覈價單表頭的【運費】字段(若是沒有核價單,運費就取0)
    現邏輯:取符合條件的銷售單對應的銷售覈價單明細的【運費】字段(若是沒有核價單,運費就取0*/
    --插入銷售值
    INSERT INTO rp_posum
        (id, ad_client_id, ad_org_id, m_product_id, sa_contractno,
         c_customer_id, pdtno, pz, contractno, contractpno, confirmdate,
         factorydate, priceactual, amt_tran, sa_qty, sa_qtyout, sa_amtout,
         m_attributesetinstance_id, ownerid, creationdate, modifierid,
         modifieddate, isactive, ad_pi_id, m_productalias_id, pu_contractno)
        SELECT get_sequences('rp_posum'), 37, 27, b.m_product_id,
               /* a.contractno_orig*/ a.old_docno, a.c_customer_id, a.pdtno,
               a.pz, a.contractno, a.contractpno, a.confirmdate, a.factorydate,
               b.priceactual, AVG(nvl(b.amt_tran, 0)), SUM(b.qty), SUM(b.qtyout),
               SUM(b.tot_amtout_actual), b.m_attributesetinstance_id,
               v_modifierid, SYSDATE, v_modifierid, SYSDATE, 'Y', p_pi_id,
               b.m_productalias_id, b.contractno_orig
        FROM m_sale a, m_saleitem b, TABLE(r_c_store) rc, TABLE(r_m_product) rp
        WHERE a.id = b.m_sale_id
        AND b.contractno_orig IS NOT NULL
        AND a.status = 2
        AND a.isactive = 'Y'
        AND a.c_store_id = rc.id
        AND b.m_product_id = rp.id
        AND a.billdate BETWEEN v_datebegin AND v_dateend
        AND a.factorydate BETWEEN v_datebegin2 AND v_dateend2
        AND a.confirmdate BETWEEN v_datebegin3 AND v_dateend3
        GROUP BY b.m_product_id, /*a.contractno_orig*/ a.old_docno,
                 a.c_customer_id, a.pdtno, a.pz, a.contractno, a.contractpno,
                 a.confirmdate, a.factorydate, b.priceactual,
                 b.m_attributesetinstance_id, b.m_productalias_id,
                 b.contractno_orig;
    --插入採購值
    MERGE INTO rp_posum m
    USING (SELECT a.id, a.docno, a.billdate, a.old_docno AS contractno,
                  a.c_supplier_id, b.m_product_id, b.m_productalias_id,
                  b.m_attributesetinstance_id AS asi,
                  AVG(b.priceactual) AS po_priceactual, SUM(b.qty) AS po_qty,
                  SUM(b.qtyconsign) AS po_qtyin
           FROM b_po a, b_poitem b, TABLE(r_b_po_id) bp, TABLE(r_c_store) rc,
                TABLE(r_m_product) rp, TABLE(r_c_supplier_id) rs
           WHERE a.id = b.b_po_id
           AND a.id = bp.id
           AND a.c_supplier_id = rs.id
           AND a.billdate BETWEEN v_datebegin AND v_dateend
           AND a.c_store_id = rc.id
           AND b.m_product_id = rp.id
           GROUP BY a.id, a.docno, a.billdate, a.old_docno, a.c_supplier_id,
                    b.m_product_id, b.m_productalias_id,
                    b.m_attributesetinstance_id) n
    ON (m.pu_contractno = n.contractno AND m.m_productalias_id = n.m_productalias_id)
    WHEN MATCHED THEN
        UPDATE
        SET m.c_supplier_id = n.c_supplier_id, m.billdate = n.billdate,
            m.po_priceactual = n.po_priceactual, m.po_qty = n.po_qty,
            m.po_qtyin = n.po_qtyin, m.po_amtin = n.po_qtyin * n.po_priceactual,
            m.b_po_id = n.id
        WHERE m.ad_pi_id = p_pi_id
    WHEN NOT MATCHED THEN
        INSERT
            (id, ad_client_id, ad_org_id, m_product_id, c_supplier_id, billdate,
             pu_contractno, po_priceactual, po_qty, po_qtyin, po_amtin,
             m_attributesetinstance_id, ownerid, creationdate, modifierid,
             modifieddate, isactive, ad_pi_id, m_productalias_id, b_po_id)
        VALUES
            (get_sequences('rp_posum'), 37, 27, n.m_product_id, n.c_supplier_id,
             n.billdate, n.contractno, n.po_priceactual, n.po_qty, n.po_qtyin,
             n.po_qtyin * n.po_priceactual, n.asi, v_modifierid, SYSDATE,
             v_modifierid, SYSDATE, 'Y', p_pi_id, n.m_productalias_id, n.id);

    --入庫日期更新
    FOR v IN (SELECT a.b_po_id, MIN(a.datein) AS datein
              FROM m_purchase a
              WHERE EXISTS (SELECT 1
                     FROM rp_posum b
                     WHERE a.b_po_id = b.b_po_id
                     AND b.b_po_id IS NOT NULL
                     AND b.ad_pi_id = p_pi_id)
              AND a.datein IS NOT NULL
              GROUP BY a.b_po_id) LOOP
        UPDATE rp_posum t
        SET t.datein = v.datein
        WHERE t.b_po_id = v.b_po_id
        AND t.ad_pi_id = p_pi_id;
    END LOOP;
    --毛利計算
    /*
    毛利:
      原邏輯:賣價-買價。
      現邏輯:賣價-買價-運費
    */
    UPDATE rp_posum t
    SET t.profit = t.priceactual - t.po_priceactual - t.amt_tran,
        t.diff_qty = t.po_qty - t.sa_qty, t.inventory = t.po_qtyin - t.sa_qtyout
    WHERE t.ad_pi_id = p_pi_id;

    --raise_application_error(-20201, v_datebegin3);

END;





--新駿:採購覈價單-》平攤運費(動做定義)存儲過程(author:me)
CREATE OR REPLACE PROCEDURE m_puramttran_avg(p_user_id IN NUMBER,
                                             p_query   IN VARCHAR2,
                                             r_code    OUT NUMBER,
                                             r_message OUT VARCHAR2) AS
    ---------------------------------------------------------
    --author: xuyang
    --date: 20180607
    /*增長控制:若是單據已提交,不容許。
    若是頭表的運費不爲空,則:
    更新明細的運費=頭表的運費*明細的審覈金額/頭表的總審覈金額(最後多出來的放在最後一行)
    */

    ---------------------------------------------------------
    --聲明用於從p_query解析參數得到單據ID的相關記錄和變量
    TYPE t_queryobj IS RECORD(
        "table" VARCHAR2(255),
        query   VARCHAR2(32676),
        id      VARCHAR2(10));
    v_queryobj t_queryobj;
    TYPE t_selection IS TABLE OF NUMBER(10) INDEX BY BINARY_INTEGER;
    v_selection t_selection;
    st_xml      VARCHAR2(32676);
    v_xml       xmltype;
    p_id        NUMBER(10); --單據ID

    --其餘變量定義
    v_status   m_pur_price.status%TYPE; --單據狀態
    v_amt_tran m_pur_price.amt_tran%TYPE; --單據運費
    v_docno    m_pur_price.docno%TYPE; --單據編號

    v_tot_amtin_pcheck m_pur_price.tot_amtin_pcheck%TYPE; --總審覈金額
    v_avg_amt_tran     m_pur_price.amt_tran%TYPE; ----平攤運費
    v_mod_amt_tran     m_pur_price.amt_tran%TYPE; --剩餘運費

    v_m_purchase_id m_purchase.id%TYPE; --所屬採購單ID

    /*聲明用於獲取本單據明細中數量及存儲各明細記錄ID*/
    TYPE type_list IS TABLE OF m_purchase.id%TYPE INDEX BY BINARY_INTEGER;
    v_list type_list;

    v_cnt NUMBER(10); --明細中行數
    --用於獲取明細數量的遊標
    CURSOR cur_list IS
        SELECT id
        FROM m_pur_priceitem
        WHERE m_purchase_id = v_m_purchase_id;

BEGIN
    -- 從p_query解析參數
    st_xml := '<data>' || p_query || '</data>';
    v_xml := xmltype(st_xml);

    SELECT extractvalue(VALUE(t), '/data/table'),
           extractvalue(VALUE(t), '/data/query'),
           extractvalue(VALUE(t), '/data/id')
    INTO v_queryobj
    FROM TABLE(xmlsequence(extract(v_xml, '/data'))) t;

    SELECT extractvalue(VALUE(t), '/selection')
    BULK COLLECT
    INTO v_selection
    FROM TABLE(xmlsequence(extract(v_xml, '/data/selection'))) t;
    p_id := v_queryobj.id;

    --end 解析參數

    --獲取提交狀態,運費,單據編號
    SELECT mpp.status,nvl(mpp.amt_tran, 0), mpp.docno, mpp.tot_amtin_pcheck
    INTO v_status, v_amt_tran, v_docno, v_tot_amtin_pcheck
    FROM m_pur_price mpp
    WHERE mpp.id = p_id;

    --獲取所屬採購單ID
    SELECT id
    INTO v_m_purchase_id
    FROM m_purchase
    WHERE docno = v_docno;

    --若是單據已提交,不容許
    IF v_status = 2 THEN
        raise_application_error(-20201, '單據已提交,不容許!');
    END IF;

    /*若是頭表的運費不爲空,則:更新明細的運費=頭表的運費*明細的審覈金額/頭表的總審覈金額(最後多出來的放在最後一行)*/
    IF v_amt_tran <> 0 THEN
    
        --獲取需求運費和多餘運費
    
        OPEN cur_list;
        FETCH cur_list BULK COLLECT
            INTO v_list;
        v_cnt := v_list.count;
    
        IF v_list.count >= 2 THEN
        
            v_mod_amt_tran := v_amt_tran; --起始剩餘運費
        
            --設置多行行明細運費
            FOR idx IN 1 .. v_list.count - 1 LOOP
            
                SELECT ((v_amt_tran * mppi.tot_amtin_pchecktax) /
                        v_tot_amtin_pcheck)
                INTO v_avg_amt_tran
                FROM m_pur_priceitem mppi
                WHERE mppi.id = v_list(idx);
            
                UPDATE m_purchaseitem mpi
                SET mpi.amt_tran = v_avg_amt_tran
                WHERE mpi.id = v_list(idx);
            
                --剩餘運費
                v_mod_amt_tran := v_mod_amt_tran - v_avg_amt_tran;
            END LOOP;
        
            IF v_mod_amt_tran > 0 THEN
                --設置最後一行明細運費
                UPDATE m_purchaseitem mpi
                SET mpi.amt_tran = v_mod_amt_tran
                WHERE mpi.id = v_list(v_cnt);
            
            END IF;
        ELSIF v_list.count = 1 THEN
            --設置單行明細運費
            UPDATE m_purchaseitem mpi
            SET mpi.amt_tran = v_amt_tran
            WHERE mpi.m_purchase_id = v_m_purchase_id;
        END IF;
    
        CLOSE cur_list;
    
    END IF;

    r_code := 1;
    r_message := '平攤運費成功!!';
END;


--新駿:銷售覈價單-》平攤運費(動做定義)存儲過程(author:me)
CREATE OR REPLACE PROCEDURE m_saleamttran_avg(p_user_id IN NUMBER,
                                              p_query   IN VARCHAR2,
                                              r_code    OUT NUMBER,
                                              r_message OUT VARCHAR2) AS
    ---------------------------------------------------------
    --author: xuyang
    --date: 20180607
    /*增長控制:若是單據已提交,不容許。
    若是頭表的運費不爲空,則:
    更新明細的運費=頭表的運費*明細的審覈金額/頭表的總審覈金額(最後多出來的放在最後一行)
    */

    ---------------------------------------------------------
    --聲明用於從p_query解析參數得到單據ID的相關記錄和變量
    TYPE t_queryobj IS RECORD(
        "table" VARCHAR2(255),
        query   VARCHAR2(32676),
        id      VARCHAR2(10));
    v_queryobj t_queryobj;
    TYPE t_selection IS TABLE OF NUMBER(10) INDEX BY BINARY_INTEGER;
    v_selection t_selection;
    st_xml      VARCHAR2(32676);
    v_xml       xmltype;
    p_id        NUMBER(10); --單據ID

    --其餘變量定義
    v_status   m_sale_pck.status%TYPE; --單據狀態
    v_amt_tran m_sale_pck.amt_tran%TYPE; --單據運費
    v_docno    m_sale_pck.docno%TYPE; --單據編號

    v_tot_amtout_actual m_sale_pck.tot_amtout_actual%TYPE; --總審覈金額
    v_avg_amt_tran      m_sale_pck.amt_tran%TYPE; ----平攤運費
    v_mod_amt_tran      m_sale_pck.amt_tran%TYPE; --剩餘運費

    v_m_sale_id m_sale.id%TYPE; --所屬銷售單ID

    /*聲明用於獲取本單據明細中數量及存儲各明細記錄ID*/
    TYPE type_list IS TABLE OF m_sale.id%TYPE INDEX BY BINARY_INTEGER;
    v_list type_list;

    v_cnt NUMBER(10); --銷售明細中行數
    --用於獲取銷售明細數量的遊標
    CURSOR cur_list IS
        SELECT id
        FROM m_sale_pckitem
        WHERE m_sale_id = v_m_sale_id;

BEGIN
    -- 從p_query解析參數
    st_xml := '<data>' || p_query || '</data>';
    v_xml := xmltype(st_xml);

    SELECT extractvalue(VALUE(t), '/data/table'),
           extractvalue(VALUE(t), '/data/query'),
           extractvalue(VALUE(t), '/data/id')
    INTO v_queryobj
    FROM TABLE(xmlsequence(extract(v_xml, '/data'))) t;

    SELECT extractvalue(VALUE(t), '/selection')
    BULK COLLECT
    INTO v_selection
    FROM TABLE(xmlsequence(extract(v_xml, '/data/selection'))) t;
    p_id := v_queryobj.id;

    --end 解析參數

    --獲取提交狀態,運費,單據編號
    SELECT msp.status,nvl(msp.amt_tran, 0), msp.docno, msp.tot_amtout_actual
    INTO v_status, v_amt_tran, v_docno, v_tot_amtout_actual
    FROM m_sale_pck msp
    WHERE msp.id = p_id;

    --若是單據已提交,不容許
    IF v_status = 2 THEN
        raise_application_error(-20201, '單據已提交,不容許!');
    END IF;

    --獲取所屬銷售單ID
    SELECT id
    INTO v_m_sale_id
    FROM m_sale
    WHERE docno = v_docno;

    /*若是頭表的運費不爲空,則:更新明細的運費=頭表的運費*明細的審覈金額/頭表的總審覈金額(最後多出來的放在最後一行)*/
    IF v_amt_tran <> 0 THEN
    
        --獲取需求運費和多餘運費
    
        OPEN cur_list;
        FETCH cur_list BULK COLLECT
            INTO v_list;
        v_cnt := v_list.count;
    
        IF v_list.count >= 2 THEN
        
            v_mod_amt_tran := v_amt_tran; --起始剩餘運費
        
            --設置多行行明細運費
            FOR idx IN 1 .. v_list.count - 1 LOOP
            
                SELECT ((v_amt_tran * mspi.tot_amtout_actual) /
                        v_tot_amtout_actual)
                INTO v_avg_amt_tran
                FROM m_sale_pckitem mspi
                WHERE mspi.id = v_list(idx);
            
                UPDATE m_saleitem msi
                SET msi.amt_tran = v_avg_amt_tran
                WHERE msi.id = v_list(idx);
            
                --剩餘運費
                v_mod_amt_tran := v_mod_amt_tran - v_avg_amt_tran;
            END LOOP;
        
            IF v_mod_amt_tran > 0 THEN
                --設置最後一行明細運費
                UPDATE m_saleitem msi
                SET msi.amt_tran = v_mod_amt_tran
                WHERE msi.id = v_list(v_cnt);
            
            END IF;
        ELSIF v_list.count = 1 THEN
            --設置單行明細運費
            UPDATE m_saleitem msi
            SET msi.amt_tran = v_amt_tran
            WHERE msi.m_sale_id = v_m_sale_id;
        END IF;
    
        CLOSE cur_list;
    
    END IF;

    r_code := 1;
    r_message := '平攤運費成功!!';
END;



--凰艮:商品銷售排行榜報表procedure:
CREATE OR REPLACE PROCEDURE rp_retail_order_generate(p_pi_id NUMBER) IS
    /*Version    date      name    reason
    0.0        20091222  eiffie  created*/
    --1.Author:zxx
    --Date:20161117
    --Modification:取值查詢條件的庫存店倉,已作單未出庫的數量之和(別人發貨但尚未出庫的數量統計。例如發貨店倉是A,作10件銷售單已提交未出庫,收貨店倉B的在單數量爲10。單據包含銷售單,銷售退貨單,調撥單)
    ---------------------------------------------------
    --2: author:xuyang
    --date:20180608
    --modification:
    /*
    在途庫存:取值該店倉、該條碼在[庫存查詢 V_FA_STORAGE]中的在途數量。
    預計庫存:在途庫存+庫存數量。
    */
    ---------------------------------------------------

    v_userid    NUMBER(10);
    v_date      VARCHAR2(80);
    v_datebegin NUMBER(8);
    v_dateend   NUMBER(8);
    v_sql1      VARCHAR2(4000);
    v_sql2      VARCHAR2(4000);
    v_cnt       NUMBER(10);
    r_store     r_tabid := r_tabid(); --記錄店倉id集合
    r_product   r_tabid := r_tabid(); --記錄款號單id集合
    r_qtystore  r_tabid := r_tabid(); --記錄庫存店倉id集合

BEGIN
    EXECUTE IMMEDIATE ('truncate TABLE rp_retail_order');

    --    raise_application_error(-20201, p_pi_id);
    --定義公共sql
    v_sql1 := 'SELECT t.info
                      FROM ad_pinstance_para t
                      WHERE t.name = :name AND t.ad_pinstance_id = :p_pi_id';

    SELECT t.modifierid
    INTO v_userid
    FROM ad_pinstance t
    WHERE t.id = p_pi_id;
    --依次獲取界面查詢條件參數

    EXECUTE IMMEDIATE v_sql1
        INTO v_date
        USING '日期', p_pi_id;

    IF v_date IS NULL THEN
        --如開始日期和結束日期都沒有選擇,則查詢全部日期範圍內數據
        v_datebegin := 0;
        v_dateend := 20991231;
    ELSE
        IF instr(v_date, '>=') > 0 THEN
            --如只選擇了開始日期,則結束日期默認爲20991231
            v_dateend := 20991231;
            SELECT substr(v_date, 7, 8) --注意這裏是否是從9開始,取決於日期參數定義,例如日期參數名定義爲DATE,則此處爲9,如定義爲BILLDATE,此處爲13,以此類推
            INTO v_datebegin
            FROM dual;
        ELSIF instr(v_date, '<=') > 0 THEN
            --如只選擇告終束日期,則開始日期默認爲0
            v_datebegin := 0;
            SELECT substr(v_date, 7, 8) --注意這裏是否是從9開始,取決於日期參數定義,例如日期參數名定義爲DATE,則此處爲9,如定義爲BILLDATE,此處爲13,以此類推
            INTO v_dateend
            FROM dual;
        ELSE
            --如開始日期和結束日期都進行了選擇,則均從參數值獲取
            SELECT substr(v_date, 15, 8), substr(v_date, 28, 8) --注意這裏是否是分別從17,30開始,也是取決於日期參數定義,,例如日期參數名定義爲DATE,則此處爲1七、30,如定義爲BILLDATE,此處爲2一、34,以此類推
            INTO v_datebegin, v_dateend
            FROM dual;
        END IF;
    END IF;

    EXECUTE IMMEDIATE v_sql1
        INTO v_sql2
        USING '店倉', p_pi_id;
    r_store := f_fast_table(v_sql2);

    EXECUTE IMMEDIATE v_sql1
        INTO v_sql2
        USING '商品', p_pi_id;

    r_product := f_fast_table(v_sql2);

    EXECUTE IMMEDIATE v_sql1
        INTO v_sql2
        USING '庫存店倉', p_pi_id;
    r_qtystore := f_fast_table(v_sql2);

    INSERT INTO rp_retail_order
        (id, ad_client_id, ad_org_id, m_product_id, qty, tot_amt_actual,
         ownerid, modifierid, creationdate, modifieddate, isactive, ad_pi_id)
        SELECT get_sequences('RP_RETAIL_ORDER'), a.ad_client_id, a.ad_org_id,
               b.m_product_id, SUM(b.qty) qty, SUM(b.tot_amt_actual) amt_actual,
               v_userid, v_userid, SYSDATE, SYSDATE, 'Y', p_pi_id
        FROM m_retail a, m_retailitem b, TABLE(r_store) rs, TABLE(r_product) rp
        WHERE a.id = b.m_retail_id
        AND a.c_store_id = rs.id
        AND b.m_product_id = rp.id
        AND a.status = 2
        AND a.billdate BETWEEN v_datebegin AND v_dateend
        GROUP BY a.ad_client_id, a.ad_org_id, b.m_product_id;

    --begin modification by xuyang 20180608
    /*更新如下兩字段:
    在途庫存prein_qty:取值該店倉、該條碼在[庫存查詢 V_FA_STORAGE]中的在途數量。
    預計庫存pre_qty:在途庫存+庫存數量。*/
    MERGE INTO rp_retail_order g
    USING (SELECT c.ad_client_id, c.ad_org_id, c.m_product_id,
                  SUM(c.qty) qty_storage, SUM(c.qtyprein) qtyprein
           FROM fa_storage c, TABLE(r_product) rp, TABLE(r_qtystore) rq
           WHERE c.c_store_id = rq.id
           AND c.m_product_id = rp.id
           GROUP BY c.ad_client_id, c.ad_org_id, c.m_product_id) w
    ON (g.m_product_id = w.m_product_id AND g.ad_client_id = w.ad_client_id AND g.ad_org_id = w.ad_org_id AND g.ad_pi_id = p_pi_id)
    WHEN MATCHED THEN
        UPDATE
        SET g.qty_storage = nvl(g.qty_storage, 0) + w.qty_storage,
            g.prein_qty = w.qtyprein,
            --added by xuyang
            g.pre_qty = nvl(g.qty_storage, 0) + w.qty_storage + w.qtyprein --added by xuyang
    
    WHEN NOT MATCHED THEN
        INSERT
            (id, ad_client_id, ad_org_id, ownerid, modifierid, creationdate,
             modifieddate, isactive, ad_pi_id, m_product_id, qty_storage,
             prein_qty, pre_qty)
        VALUES
            (get_sequences('RP_RETAIL_ORDER'), w.ad_client_id, w.ad_org_id,
             v_userid, v_userid, SYSDATE, SYSDATE, 'Y', p_pi_id, w.m_product_id,
             w.qty_storage, w.qtyprein, (w.qtyprein + w.qty_storage)); --added by xuyang
    --end modification by xuyang 20180608

    --add by zxx 20161117 在單數量2
    MERGE INTO rp_retail_order a
    USING (SELECT nvl(SUM(g.qtypreout), 0) AS qtypreout, /* g.c_store_id,*/
                  g.m_product_id
           FROM (SELECT nvl(SUM(mi.qty), 0) AS qtypreout,
                         /* m.c_dest_id AS c_store_id, */ mi.m_product_id
                  FROM m_sale m, TABLE(r_qtystore) rs, TABLE(r_product) rp,
                       m_saleitem mi
                  WHERE m.c_dest_id = rs.id
                  AND mi.m_sale_id = m.id
                  AND mi.m_product_id = rp.id
                  AND m.status = 2
                  AND m.out_status = 1
                  GROUP BY /*m.c_dest_id,*/ mi.m_product_id
                  UNION ALL
                  SELECT nvl(SUM(mri.qty), 0) AS qtypreout,
                         /* mr.c_store_id AS c_store_id,*/ mri.m_product_id
                  FROM m_ret_sale mr, TABLE(r_qtystore) rs, TABLE(r_product) rp,
                       m_ret_saleitem mri
                  WHERE mr.c_store_id = rs.id
                  AND mri.m_ret_sale_id = mr.id
                  AND mri.m_product_id = rp.id
                  AND mr.status = 2
                  AND mr.out_status = 1
                  GROUP BY /* mr.c_store_id,*/ mri.m_product_id
                  UNION ALL
                  SELECT nvl(SUM(mti.qty), 0) AS qtypreout,
                         /*  mt.c_dest_id AS c_store_id,*/ mti.m_product_id
                  FROM m_transfer mt, TABLE(r_qtystore) rs, TABLE(r_product) rp,
                       m_transferitem mti
                  WHERE mt.c_dest_id = rs.id
                  AND mti.m_product_id = rp.id
                  AND mti.m_transfer_id = mt.id
                  AND mt.status = 2
                  AND mt.out_status = 1
                  GROUP BY /*mt.c_dest_id,*/ mti.m_product_id) g
           GROUP BY /* g.c_store_id,*/ g.m_product_id) tt
    ON ( /*a.c_store_id = tt.c_store_id AND */
    a.m_product_id = tt.m_product_id)
    WHEN MATCHED THEN
        UPDATE
        SET a.qtypreout2 = tt.qtypreout;
    --end by zxx 20161117

    UPDATE rp_retail_order g
    SET pricelist = (SELECT pricelist
                      FROM m_product a
                      WHERE a.id = g.m_product_id)
    WHERE g.ad_pi_id = p_pi_id;

    UPDATE rp_retail_order g
    SET rateamt = (SELECT decode(SUM(a.tot_amt_actual), 0, 0,
                                   g.tot_amt_actual / SUM(a.tot_amt_actual))
                    FROM rp_retail_order a
                    WHERE a.ad_pi_id = p_pi_id);

    SELECT length(COUNT(1))
    INTO v_cnt
    FROM rp_retail_order t
    WHERE t.ad_pi_id = p_pi_id;

    UPDATE rp_retail_order g
    SET n = (SELECT substr('00000000000' || n, -v_cnt, v_cnt)
              FROM (SELECT id,
                            rank() over(PARTITION BY ad_client_id, ad_org_id ORDER BY nvl(qty, 0) DESC) n
                     FROM rp_retail_order a
                     WHERE a.ad_pi_id = p_pi_id) w
              WHERE w.id = g.id)
    WHERE EXISTS (SELECT 1
           FROM rp_retail_order a
           WHERE g.id = a.id)
    AND g.ad_pi_id = p_pi_id;

END; /* edit by shizhishu 2016/11/18 16:39:15 */



--MY FIRST REPORT TABLE MODEL
CREATE OR REPLACE PROCEDURE rp_o2o_salesources_gen(p_pi_id NUMBER) IS
    ---------------------------------------------------
    --Author:xuyang
    -- Date:20180615
    -- Author :xuyang
    -- Description :
    /* 
    查詢條件:單據日期(日期範圍、必填) 、訂單來源(下拉框選項:EBSOURCE,非必填)
    查詢邏輯:
      取查詢單據日期在查詢條件的開始日期和結束日期內、
      訂單來源爲查詢條件的訂單來源、 已提交、未結案、可用的 【雲倉訂單】的數據。
      (--PS: 控制查詢條件的結束日期-開始日期=6,若是不等於6,則報錯‘該報表爲週報表,請以7天爲一個週期’)
    查詢結果:
     行定義:
        序號:顯示1,2,3,4……。
        渠道:取值符合條件的雲倉訂單主表的【接口訂單類型】。
        訂單來源:取值符合條件的雲倉訂單主表的【訂單來源】。
     彙總字段:
        銷量:取值符合查詢條件的、該渠道、該訂單來源對應的雲倉訂單主表【訂單數量】的彙總。
        銷售額(萬元):取值符合查詢條件的、該渠道、該訂單來源對應的雲倉訂單主表【訂單成交金額】/10000,四捨五入取整。
        銷量佔比(%):取值(本條記錄的銷量/全部訂單來源銷量之和 )*100,百分比格式,百分比以後顯示兩位小數。
        銷售額佔比(%):取值(本條記錄的銷售額(萬元) / 全部訂單來源銷售額之和)*100,百分比格式,百分比以後顯示兩位小數。
        銷量周環比(%):取值[(本條記錄的銷量-上週銷量)/上週銷量]*100,本週爲查詢日期選擇的起始日期和結束日期,上週爲本週的上一個7天做爲一週;百分比格式,百分比以後顯示兩位小數。
        銷售額周環比(%):取值[(本條記錄的銷售額(萬元)-上週銷售額(萬元))/上週銷售額(萬元)]*100,本週爲查詢日期選擇的起始日期和結束日期,上週爲本週的上一個7天做爲一週;百分比格式,百分比以後顯示兩位小數。
        件單價(元) :銷售額(萬元)*10000/ 銷量,四捨五入取整。
        成交折扣:取值本記錄的銷售額(萬元)*10000/ 符合查詢條件的、該渠道、該訂單來源對應的雲倉訂單主表【訂單標準金額】,小數點後面兩位。
     --PS:銷量佔比(%)、銷售額佔比(%)、銷量周環比(%)、銷售額周環比(%)、件單價、成交折扣合計時,取平均數。
     */
    ---------------------------------------------------

    v_userid    NUMBER(10);
    v_date      VARCHAR2(80);
    v_datebegin VARCHAR2(8);
    v_dateend   VARCHAR2(8);
    v_sql1      VARCHAR2(4000);
    --v_sql2      VARCHAR2(4000);

    v_source     rp_o2o_salesources.source%TYPE; --訂單來源
    v_tmp_source rp_o2o_salesources.source%TYPE;
    v_loc1       NUMBER(10); --訂單來源字符解析位置1
    v_loc2       NUMBER(10); --訂單來源字符解析位置2

    v_days NUMBER(10);

    v_all_tot_num rp_o2o_salesources.num%TYPE; --全部訂單來源銷量之和
    v_all_tot_amt rp_o2o_salesources.tot_amt_actual%TYPE; --全部訂單來源銷售額之和
    --v_sales_last     rp_o2o_salesources.num%TYPE; --上週銷量
    --v_sales_amt_last rp_o2o_salesources.tot_amt_actual%TYPE; --上週銷售額
BEGIN
    EXECUTE IMMEDIATE ('truncate TABLE RP_O2O_SALESOURCES');

    --    raise_application_error(-20201, p_pi_id);
    --定義公共sql
    v_sql1 := 'SELECT t.info
                      FROM ad_pinstance_para t
                      WHERE t.name = :name AND t.ad_pinstance_id = :p_pi_id';

    SELECT t.modifierid
    INTO v_userid
    FROM ad_pinstance t
    WHERE t.id = p_pi_id;
    --依次獲取界面查詢條件參數

    EXECUTE IMMEDIATE v_sql1
        INTO v_date
        USING 'BILLDATE', p_pi_id;
    --raise_application_error(-20201, 'debug:' || v_date);
    -- debug: (BILLDATE>=20180605)
    IF v_date IS NULL THEN
        --如開始日期和結束日期都沒有選擇,
        raise_application_error(-20201, '請選擇日期範圍!');
    ELSE
        IF instr(v_date, '>=') > 0 THEN
        
            --如只選擇了開始日期,則結束日期默認爲開始往後六天
            SELECT substr(v_date, 13, 8) --注意這裏是否是從9開始,取決於日期參數定義,例如日期參數名定義爲DATE,則此處爲9,如定義爲BILLDATE,此處爲13,以此類推
            INTO v_datebegin
            FROM dual;
            --raise_application_error(-20201, 'debug: ' || v_datebegin);
            --結束日期默認爲開始往後六天
            v_dateend := to_char(to_date(v_datebegin, 'yyyymmdd') + 6,
                                 'yyyymmdd');
        
        ELSIF instr(v_date, '<=') > 0 THEN
            --如只選擇告終束日期,則開始日期默認爲前六天BILLDATE<=20180615
            SELECT substr(v_date, 13, 8) --注意這裏是否是從9開始,取決於日期參數定義,例如日期參數名定義爲DATE,則此處爲9,如定義爲BILLDATE,此處爲13,以此類推
            INTO v_dateend
            FROM dual;
        
            --開始日期默認爲前六天
            v_datebegin := to_char(to_date(v_dateend, 'yyyymmdd') - 6,
                                   'yyyymmdd');
        
        ELSE
            --如開始日期和結束日期都進行了選擇,則均從參數值獲取debug: ( BILLDATE BETWEEN 20180605 AND 20180615)
            --raise_application_error(-20201, 'debug:' || v_date);
            SELECT substr(v_date, 21, 8), substr(v_date, 34, 8) --注意這裏是否是分別從20,33開始,也是取決於日期參數定義,,例如日期參數名定義爲DATE,則此處爲1七、30,如定義爲BILLDATE,此處爲2一、34,以此類推
            INTO v_datebegin, v_dateend
            FROM dual;
        
            /*raise_application_error(-20201,
            'debug:' || v_datebegin || '--' ||
             v_dateend);*/
            SELECT to_date(v_dateend, 'yyyymmdd') -
                    to_date(v_datebegin, 'yyyymmdd')
            INTO v_days
            FROM dual;
            --raise_application_error(-20201, 'debug:' || v_days);
            IF v_days <> 6 THEN
                raise_application_error(-20201, '該報表爲週報表,請以7天爲一個週期!');
            END IF;
        
        END IF;
    END IF;

    --獲取訂單來源
    EXECUTE IMMEDIATE v_sql1
        INTO v_tmp_source
        USING 'SOURCE', p_pi_id;
    --raise_application_error(-20201, 'debug:' || v_days);
    --debug: (SOURCE LIKE '%0%')
    --debug: (SOURCE = 'taobao')
    --debug: (SOURCE = 'HAND')
    --debug: (SOURCE = 'WEB')
    --未選擇訂單來源,則給予提示
    IF v_tmp_source IS NULL THEN
        raise_application_error(-20201, '請選擇訂單來源!');
    END IF;

    --訂單來源爲查詢條件的訂單來源、 已提交、未結案、可用的 【雲倉訂單】的數據。
    /*
        銷量:取值符合查詢條件的、該渠道、該訂單來源對應的雲倉訂單主表【訂單數量】的彙總。
        銷售額(萬元):取值符合查詢條件的、該渠道、該訂單來源對應的雲倉訂單主表【訂單成交金額】/10000,四捨五入取整。
        銷量佔比(%):取值(本條記錄的銷量/全部訂單來源銷量之和 )*100,百分比格式,百分比以後顯示兩位小數。
        銷售額佔比(%):取值(本條記錄的銷售額(萬元) / 全部訂單來源銷售額之和)*100,百分比格式,百分比以後顯示兩位小數。
        件單價(元) :銷售額(萬元)*10000/ 銷量,四捨五入取整。
        成交折扣:取值本記錄的銷售額(萬元)*10000/ 符合查詢條件的、該渠道、該訂單來源對應的雲倉訂單主表【訂單標準金額】,小數點後面兩位。
     --PS:銷量佔比(%)、銷售額佔比(%)、銷量周環比(%)、銷售額周環比(%)、件單價、成交折扣合計時,取平均數。
    */

    --獲取全部訂單銷量和銷售額之和
    SELECT nvl(SUM(os.tot_amt_actual), 0), nvl(SUM(os.num), 0)
    INTO v_all_tot_amt, v_all_tot_num
    FROM o2o_so os;

    IF instr(v_tmp_source, '=') > 0 THEN
        --獲取字符‘位置
        v_loc1 := instr(v_tmp_source, '''');
        v_loc2 := instr(v_tmp_source, '''', v_loc1 + 1);
        --raise_application_error(-20201, 'debug:' || v_loc1 || '---' || v_loc2);
        --獲取到訂單來源
        v_source := substr(v_tmp_source, v_loc1 + 1, v_loc2 - v_loc1 - 1);
    
        --臨時表插入數據
        INSERT INTO rp_o2o_salesources
            (id, ad_client_id, ad_org_id, interface_type, SOURCE, num,
             tot_amt_actual, price, deal_discount, ownerid, modifierid,
             creationdate, modifieddate, isactive, ad_pi_id, no, sales_rate,
             sales_amt_rate)
            SELECT get_sequences('rp_o2o_salesources'), a.ad_client_id,
                   a.ad_org_id, a.interface_type, a.source, SUM(a.num),
                   round(SUM(a.tot_amt_actual) / 10000),
                   round(((round(SUM(a.tot_amt_actual) / 10000)) * 10000) /
                          SUM(a.num)),
                   trunc((((round(SUM(a.tot_amt_actual) / 10000)) * 10000) /
                          SUM(a.tot_amt_list)), 2), v_userid, v_userid, SYSDATE,
                   SYSDATE, 'Y', p_pi_id,
                   dense_rank() over(PARTITION BY NULL ORDER BY SUM(a.tot_amt_actual)),
                   trunc((SUM(a.num) / v_all_tot_num) * 100, 2),
                   trunc((SUM(tot_amt_actual) / v_all_tot_amt) * 100, 2)
            FROM o2o_so a
            WHERE a.status = 2
            AND a.isactive = 'Y'
            AND a.close_status = 1
            AND a.source = v_source
            AND to_date(a.billdate, 'yyyymmdd') BETWEEN
                  to_date(v_datebegin, 'yyyymmdd') AND
                  to_date(v_dateend, 'yyyymmdd')
            GROUP BY a.ad_client_id, a.ad_org_id, a.interface_type, a.source
            ORDER BY SUM(a.num);
    
    ELSIF instr(v_tmp_source, 'LIKE') > 0 THEN
        INSERT INTO rp_o2o_salesources
            (id, ad_client_id, ad_org_id, interface_type, SOURCE, num,
             tot_amt_actual, price, deal_discount, ownerid, modifierid,
             creationdate, modifieddate, isactive, ad_pi_id, no, sales_rate,
             sales_amt_rate)
            SELECT get_sequences('rp_o2o_salesources'), a.ad_client_id,
                   a.ad_org_id, a.interface_type, a.source, SUM(a.num),
                   round(SUM(a.tot_amt_actual) / 10000),
                   round(((round(SUM(a.tot_amt_actual) / 10000)) * 10000) /
                          SUM(a.num)),
                   trunc((((round(SUM(a.tot_amt_actual) / 10000)) * 10000) /
                          SUM(a.tot_amt_list)), 2), v_userid, v_userid, SYSDATE,
                   SYSDATE, 'Y', p_pi_id,
                   dense_rank() over(PARTITION BY NULL ORDER BY SUM(a.tot_amt_actual)),
                   trunc((SUM(a.num) / v_all_tot_num) * 100, 2),
                   trunc((SUM(tot_amt_actual) / v_all_tot_amt) * 100, 2)
            FROM o2o_so a
            WHERE a.status = 2
            AND a.isactive = 'Y'
            AND a.close_status = 1
            AND to_date(a.billdate, 'yyyymmdd') BETWEEN
                  to_date(v_datebegin, 'yyyymmdd') AND
                  to_date(v_dateend, 'yyyymmdd')
            GROUP BY a.ad_client_id, a.ad_org_id, a.interface_type, a.source
            ORDER BY SUM(a.num);
    
    END IF;

    /*
    
    銷量周環比(%):取值[(本條記錄的銷量-上週銷量)/上週銷量]*100,本週爲查詢日期選擇的起始日期和結束日期,上週爲本週的上一個7天做爲一週;百分比格式,百分比以後顯示兩位小數。
    銷售額周環比(%):取值[(本條記錄的銷售額(萬元)-上週銷售額(萬元))/上週銷售額(萬元)]*100,本週爲查詢日期選擇的起始日期和結束日期,上週爲本週的上一個7天做爲一週;百分比格式,百分比以後顯示兩位小數。
    
    */
    MERGE INTO rp_o2o_salesources rps
    USING (SELECT os.interface_type interface_type, os.source SOURCE,
                  SUM(os.num) tot_num_last, SUM(os.tot_amt_actual) tot_amt_last
           FROM o2o_so os
           WHERE to_date(os.billdate, 'yyyymmdd') BETWEEN
                 to_date(v_datebegin, 'yyyymmdd') - 6 AND
                 to_date(v_dateend, 'yyyymmdd') - 6
           GROUP BY os.interface_type, os.source) rs
    ON (rps.interface_type = rs.interface_type AND rps.source = rs.source)
    WHEN MATCHED THEN
        UPDATE
        SET rps.sales_week_rate = trunc(((rps.num - rs.tot_num_last) /
                                         rs.tot_num_last) * 100, 2),
            rps.sales_amtweek_rate = trunc(((rps.tot_amt_actual -
                                            rs.tot_amt_last) / rs.tot_amt_last) * 100,
                                            2);
END;



---V1.0-20180608-06全渠道各渠道TOP10銷售分析報表存儲過程
CREATE OR REPLACE PROCEDURE rp_o2o_salesources10_gen(p_pi_id NUMBER) IS
    ---------------------------------------------------
    --Author:xuyang
    -- Date:20180616
    -- Author :xuyang
    -- Description :
    /*
    查詢條件:單據日期(日期範圍、必填) 、訂單來源(下拉框選項:EBSOURCE,非必填)
    查詢邏輯:
      查詢邏輯:取查詢單據日期在查詢條件的開始日期和結束日期內、訂單來源爲查詢條件的訂單來源、 已提交、未結案、可用的 【雲倉訂單】的數據
      (--PS: 控制查詢條件的結束日期-開始日期=6,若是不等於6,則報錯‘該報表爲週報表,請以7天爲一個週期’)
    查詢結果:
     行定義:
        序號:顯示1,2,3,4……按照本訂單來源的銷量降序,取前十名。--即:每一個訂單來源只統計【銷量】排行前十的款號
        訂單來源:取值符合條件的雲倉訂單主表的【訂單來源】。
        款號:取值符合條件的雲倉訂單明細的【款號】。
     彙總字段:
        銷量:取值符合查詢條件的、該訂單來源、該款號對應的雲倉訂單明細的【訂單數量】的彙總。
        銷售額(元):取值符合查詢條件的、該訂單來源、該款號對應的雲倉訂單明細的【訂單成交金額】的彙總,四捨五入取整。
        銷量佔比(%):取值(本條記錄的銷量/全部訂單來源銷量之和 )*100,百分比格式,百分比以後顯示兩位小數。
        銷售額佔比(%):取值(本條記錄的銷售額(元) / 全部訂單來源銷售額之和)*100,百分比格式,百分比以後顯示兩位小數。
     */
    ---------------------------------------------------

    v_userid    NUMBER(10);
    v_date      VARCHAR2(80);
    v_datebegin VARCHAR2(8);
    v_dateend   VARCHAR2(8);
    v_sql1      VARCHAR2(4000);

    v_source     rp_o2o_salesources10.source%TYPE; --訂單來源
    v_tmp_source rp_o2o_salesources10.source%TYPE;
    v_loc1       NUMBER(10); --訂單來源字符解析位置1
    v_loc2       NUMBER(10); --訂單來源字符解析位置2

    v_all_tot_num rp_o2o_salesources10.num%TYPE; --全部訂單來源銷量之和
    v_all_tot_amt rp_o2o_salesources10.tot_amt_actual%TYPE; --全部訂單來源銷售額之和

BEGIN
    EXECUTE IMMEDIATE ('truncate TABLE RP_O2O_SALESOURCES');

    --    raise_application_error(-20201, p_pi_id);
    --定義公共sql
    v_sql1 := 'SELECT t.info
                      FROM ad_pinstance_para t
                      WHERE t.name = :name AND t.ad_pinstance_id = :p_pi_id';

    SELECT t.modifierid
    INTO v_userid
    FROM ad_pinstance t
    WHERE t.id = p_pi_id;
    --依次獲取界面查詢條件參數

    EXECUTE IMMEDIATE v_sql1
        INTO v_date
        USING 'BILLDATE', p_pi_id;
    --raise_application_error(-20201, 'debug:' || v_date);
    -- debug: (BILLDATE>=20180605)
    IF v_date IS NULL THEN
        --如開始日期和結束日期都沒有選擇,
        raise_application_error(-20201, '請選擇日期範圍!');
    ELSE
        IF instr(v_date, '>=') > 0 THEN
        
            --如只選擇了開始日期,則結束日期默認爲開始往後六天
            SELECT substr(v_date, 13, 8) --注意這裏是否是從9開始,取決於日期參數定義,例如日期參數名定義爲DATE,則此處爲9,如定義爲BILLDATE,此處爲13,以此類推
            INTO v_datebegin
            FROM dual;
            --raise_application_error(-20201, 'debug: ' || v_datebegin);
            --結束日期默認爲開始往後六天
            v_dateend := to_char(to_date(v_datebegin, 'yyyymmdd') + 6,
                                 'yyyymmdd');
        
        ELSIF instr(v_date, '<=') > 0 THEN
            --如只選擇告終束日期,則開始日期默認爲前六天BILLDATE<=20180615
            SELECT substr(v_date, 13, 8) --注意這裏是否是從9開始,取決於日期參數定義,例如日期參數名定義爲DATE,則此處爲9,如定義爲BILLDATE,此處爲13,以此類推
            INTO v_dateend
            FROM dual;
        
            --開始日期默認爲前六天
            v_datebegin := to_char(to_date(v_dateend, 'yyyymmdd') - 6,
                                   'yyyymmdd');
        
        ELSE
            --如開始日期和結束日期都進行了選擇,則均從參數值獲取debug: ( BILLDATE BETWEEN 20180605 AND 20180615)
            --raise_application_error(-20201, 'debug:' || v_date);
            SELECT substr(v_date, 21, 8), substr(v_date, 34, 8) --注意這裏是否是分別從20,33開始,也是取決於日期參數定義,,例如日期參數名定義爲DATE,則此處爲1七、30,如定義爲BILLDATE,此處爲2一、34,以此類推
            INTO v_datebegin, v_dateend
            FROM dual;
        
        END IF;
    END IF;

    --獲取訂單來源
    EXECUTE IMMEDIATE v_sql1
        INTO v_tmp_source
        USING 'SOURCE', p_pi_id;
    --raise_application_error(-20201, 'debug:' || v_days);

    --未選擇訂單來源,則給予提示
    IF v_tmp_source IS NULL THEN
        raise_application_error(-20201, '請選擇訂單來源!');
    END IF;

    --訂單來源爲查詢條件的訂單來源、 已提交、未結案、可用的 【雲倉訂單】的數據。
    /*
        銷量:取值符合查詢條件的、該訂單來源、該款號對應的雲倉訂單明細的【訂單數量】的彙總。
        銷售額(元):取值符合查詢條件的、該訂單來源、該款號對應的雲倉訂單明細的【訂單成交金額】的彙總,四捨五入取整。
        銷量佔比(%):取值(本條記錄的銷量/全部訂單來源銷量之和 )*100,百分比格式,百分比以後顯示兩位小數。
        銷售額佔比(%):取值(本條記錄的銷售額(元) / 全部訂單來源銷售額之和)*100,百分比格式,百分比以後顯示兩位小數。
    */

    --獲取全部訂單銷量和銷售額之和
    SELECT nvl(SUM(os.tot_amt_actual), 0), nvl(SUM(os.num), 0)
    INTO v_all_tot_amt, v_all_tot_num
    FROM o2o_so os;

    IF instr(v_tmp_source, '=') > 0 THEN
        --獲取字符‘位置
        v_loc1 := instr(v_tmp_source, '''');
        v_loc2 := instr(v_tmp_source, '''', v_loc1 + 1);
    
        --獲取到訂單來源
        v_source := substr(v_tmp_source, v_loc1 + 1, v_loc2 - v_loc1 - 1);
    
        --臨時表插入數據,插入指定訂單來源的數據
        INSERT INTO rp_o2o_salesources10
            (id, ad_client_id, ad_org_id, SOURCE, num, tot_amt_actual, ownerid,
             modifierid, creationdate, modifieddate, isactive, ad_pi_id,
             sales_rate, sales_amt_rate, m_product_id, no)
            SELECT ab.id, ab.ad_clien_id, ab.ad_org_id, ab.source, ab.tot_qty,
                   ab.tot_amt, v_userid, v_userid, SYSDATE, SYSDATE, 'Y',
                   p_pi_id, ab.sales_rate, ab.sales_amt_rate, ab.m_product_id,
                   dense_rank() over(PARTITION BY NULL ORDER BY ab.tot_qty DESC)
            FROM (SELECT get_sequences('rp_o2o_salesources') id,
                          a.ad_client_id ad_clien_id, a.ad_org_id ad_org_id,
                          a.source SOURCE, SUM(osi.qty) tot_qty,
                          round(SUM(osi.tot_amt_actual)) tot_amt,
                          dense_rank() over(PARTITION BY a.source ORDER BY SUM(osi.qty) DESC) ct,
                          trunc((SUM(osi.qty) / v_all_tot_num) * 100, 2) sales_rate,
                          trunc((SUM(osi.tot_amt_actual) / v_all_tot_amt) * 100, 2) sales_amt_rate,
                          osi.m_product_id m_product_id
                   FROM o2o_so a
                   JOIN o2o_soitem osi
                   ON (osi.eb_orderso_id = a.id)
                   WHERE a.status = 2
                   AND a.isactive = 'Y'
                   AND a.close_status = 1
                   AND a.source = v_source
                   AND to_date(a.billdate, 'yyyymmdd') BETWEEN
                         to_date(v_datebegin, 'yyyymmdd') AND
                         to_date(v_dateend, 'yyyymmdd')
                   GROUP BY a.ad_client_id, a.ad_org_id, a.source,
                            osi.m_product_id
                   ORDER BY SUM(osi.qty) DESC) ab
            WHERE ab.ct <= 10;
    
    ELSIF instr(v_tmp_source, 'LIKE') > 0 THEN
        --插入全部符合條件的訂單來源數據
        INSERT INTO rp_o2o_salesources10
            (id, ad_client_id, ad_org_id, SOURCE, num, tot_amt_actual, ownerid,
             modifierid, creationdate, modifieddate, isactive, ad_pi_id,
             sales_rate, sales_amt_rate, m_product_id, no)
            SELECT ab.id, ab.ad_clien_id, ab.ad_org_id, ab.source, ab.tot_qty,
                   ab.tot_amt, v_userid, v_userid, SYSDATE, SYSDATE, 'Y',
                   p_pi_id, ab.sales_rate, ab.sales_amt_rate, ab.m_product_id,
                   dense_rank() over(ORDER BY ab.tot_qty DESC)
            FROM (SELECT get_sequences('rp_o2o_salesources') id,
                          a.ad_client_id ad_clien_id, a.ad_org_id ad_org_id,
                          a.source SOURCE, SUM(osi.qty) tot_qty,
                          round(SUM(osi.tot_amt_actual)) tot_amt,
                          dense_rank() over(PARTITION BY a.source ORDER BY SUM(osi.qty) DESC) ct,
                          trunc((SUM(osi.qty) / v_all_tot_num) * 100, 2) sales_rate,
                          trunc((SUM(osi.tot_amt_actual) / v_all_tot_amt) * 100, 2) sales_amt_rate,
                          osi.m_product_id m_product_id
                   FROM o2o_so a
                   JOIN o2o_soitem osi
                   ON (osi.eb_orderso_id = a.id)
                   WHERE a.status = 2
                   AND a.isactive = 'Y'
                   AND a.close_status = 1
                   AND to_date(a.billdate, 'yyyymmdd') BETWEEN
                         to_date(v_datebegin, 'yyyymmdd') AND
                         to_date(v_dateend, 'yyyymmdd')
                   GROUP BY a.ad_client_id, a.ad_org_id, a.source,
                            osi.m_product_id
                   ORDER BY SUM(osi.qty) DESC) ab
            WHERE ab.ct <= 10;
    
    END IF;

END;






--------------------------------------------
--解析Json數據
CREATE OR REPLACE PROCEDURE test_proc(p1 VARCHAR2) AS    v_json_varchar2 VARCHAR2(4000);
    injson          json;
    paramlist       json_list;
    onejson         json;

    --第一層  
    v_marketcode VARCHAR2(8);
    v_marketname VARCHAR2(64);
    v_address    VARCHAR2(64);
    v_tel        VARCHAR2(11);
    --第二層  
    v_name      VARCHAR2(64);
    v_fruitcode VARCHAR2(8);

BEGIN
    --定義json數據,固然json數據也可從參數中傳來
    v_json_varchar2 := '{  
    "marketcode": "123456",  
    "marketname": "好吃的水果店",  
    "address": "一個好地方",  
    "tel": "12345678901",  
    "fruitlist": {  
        "name": "apple",  
        "fruitcode": "223344",  
        "applelist": [  
            {  
                "applename": "redapple ",  
                "applecode": "111000",  
                "price": "10"  
            },  
            {  
                "applename": "greenapple ",  
                "applecode": "111111",  
                "price": "12"  
            },  
            {  
                "applename": "yellowapple ",  
                "applecode": "111222",  
                "price": "8"  
            }  
        ]  
    }  
}';
    injson := json(v_json_varchar2);
    --獲取第一層json值  
    v_marketcode := json_ext.get_string(injson, 'marketcode');
    v_marketname := json_ext.get_string(injson, 'marketname');
    v_address := json_ext.get_string(injson, 'address');
    v_tel := json_ext.get_string(injson, 'tel');
    --第二層  
    v_name := json_ext.get_string(injson, 'fruitlist.name');
    v_fruitcode := json_ext.get_string(injson, 'fruitlist.fruitcode');

    --接下來獲取第三層,使用json_list來存放json列表  
    paramlist := json_list();
    onejson := json();
    paramlist := json_ext.get_json_list(injson, 'fruitlist.applelist');

    --使用循環返回每一個json部分的值  
    FOR i IN 1 .. paramlist.count LOOP
        --讀取每一個品種具體信息
        onejson := json(paramlist.get_elem(i));
        dbms_output.put_line(json_ext.get_string(onejson, 'applename'));
        dbms_output.put_line(json_ext.get_string(onejson, 'applecode'));
        dbms_output.put_line(json_ext.get_string(onejson, 'price'));
    
    END LOOP;

END;





-----------------------------------------------------------------------------------
注:將clob類型字段讀取出來到變量,需dbms_lob.substr(xms.param)轉化爲varchar2類型
CREATE OR REPLACE PROCEDURE xq_midso_gen AS
    ----------------------------------------------------------
    --author:xuyang
    --date:20180627
    --description:
    /*
    FOR (查詢實際表[訂單接口  XQ_MIDSO]中的[是否生成訂單]爲Y的記錄) LOOP
      根據接口信息的json信息生成未提交的發貨訂單。
      生成發貨訂單頭表:
      單據日期取SYSDATE。
      訂單類型取新貨訂單。
      發貨店倉取總部店倉。
      收貨店倉取接口中的customer_name對應的經銷商下的任一店倉(根據名稱匹配)。
      鮮橋訂單編碼取接口中的ordercode。
      備註:由鮮橋接口自動生成!
      調用存儲過程:B_SO_AC。
      生成發貨訂單明細:
          條碼、款號、ASI取接口中的product_name對應條碼的值。
          數量取接口中的amount。
      調用存儲過程:B_SOITEM_ACM。
      調用存儲過程:B_SO_AM。
    END LOOP;
    */

    /*
    
    */
    ----------------------------------------------------------

    v_injson json; --用於將接口信息轉換爲json格式
    --v_ordercode  b_so.xq_ordercode%TYPE; --發貨訂單鮮橋訂單編碼

    --v_customer_name c_customer.name%TYPE; --訂單頭信息中的經銷商名稱

    v_delivery_time VARCHAR2(20); --配送時間(發貨日期)
    --v_delivery_address b_so.dest_address%TYPE; --收貨地址

    v_clob_varchar2 VARCHAR2(4000);

BEGIN
    --查詢實際表[訂單接口  XQ_MIDSO]中的[是否生成訂單]爲Y的記錄
    FOR v_list IN (SELECT xms.id, xms.ad_client_id, xms.ad_org_id,
                          xms.creationdate, xms.ownerid, xms.errormeg
                   FROM xq_midso xms
                   WHERE xms.is_so = 'Y') LOOP
        
        SELECT dbms_lob.substr(xms.param)
        INTO v_clob_varchar2
        FROM xq_midso xms
        WHERE xms.id = v_list.id;
        v_injson := json(v_clob_varchar2);
    
        --獲取headerlist:orderHeader
        --v_id := json_ext.get_string(v_injson, 'CallInfo.orderHeader.id');
        --v_ordercode := json_ext.get_string(v_injson,
        --'CallInfo.orderHeader.ordercode');
        --v_customer_name := json_ext.get_string(v_injson,'CallInfo.orderHeader.customer_name');
        v_delivery_time := substr(json_ext.get_string(v_injson,
                                                      'CallInfo.orderHeader.delivery_time'),
                                  1, 10);
    
        dbms_output.put_line('v_delivery_time:' ||
                             to_number(REPLACE(v_delivery_time, '-', '')));
    
    END LOOP;

END;





------------------------------------------------------------
*************解析json格式數據實例*******************
--新駿:訂單接口,生成發貨訂單(自動任務:每5分鐘運行一次)mantis:0029682

CREATE OR REPLACE PROCEDURE xq_midso_gen(p_id IN NUMBER) AS
    ----------------------------------------------------------
    --author:xuyang
    --date:20180627
    --description:
    /*
    FOR (查詢實際表[訂單接口  XQ_MIDSO]中的[是否生成訂單]爲Y的記錄) LOOP
      根據接口信息的json信息生成未提交的發貨訂單。
      生成發貨訂單頭表:
      單據日期取SYSDATE。
      訂單類型取新貨訂單。
      發貨店倉取總部店倉。
      收貨店倉取接口中的customer_name對應的經銷商下的任一店倉(根據名稱匹配)。
      鮮橋訂單編碼取接口中的ordercode。
      備註:由鮮橋接口自動生成!
      調用存儲過程:B_SO_AC。
      生成發貨訂單明細:
          條碼、款號、ASI取接口中的product_name對應條碼的值。
          數量取接口中的amount。
      調用存儲過程:B_SOITEM_ACM。
      調用存儲過程:B_SO_AM。
    END LOOP;
    */

    /*
    
    */
    ----------------------------------------------------------

    v_injson json; --用於將接口信息轉換爲json格式

    v_b_so_id    b_so.id%TYPE; --要使用的發貨訂單ID
    v_b_so_docno b_so.docno%TYPE; --發貨訂單據編號
    v_table_id   ad_table.id%TYPE; --發貨訂單m_agtpur表的id
    v_ordercode  b_so.xq_ordercode%TYPE; --發貨訂單鮮橋訂單編碼

    v_c_store_id c_store.id%TYPE; --總部店倉ID

    v_customer_name c_customer.name%TYPE; --訂單頭信息中的經銷商名稱
    v_cc_store_id   c_store.id%TYPE; --經銷商下任一id

    v_delivery_time    VARCHAR2(20); --配送時間(發貨日期)
    v_delivery_time1   NUMBER(8); --配送時間(發貨日期)
    v_delivery_address b_so.dest_address%TYPE; --收貨地址
    v_amount           b_soitem.qty%TYPE; --數量

    v_bodylist            json_list; --訂單明細信息列表
    v_onejson             json; --用於解析每個明細數據
    v_m_product_id        m_product.id%TYPE; --款號
    v_m_productalias_name m_product_alias.no%TYPE; --條碼名
    v_m_productalias_id   m_product_alias.id%TYPE; --條碼id

    v_asi         b_soitem.m_attributesetinstance_id%TYPE; --asi
    v_b_soitem_id b_soitem.id%TYPE; --發貨訂單明細id

    v_code    NUMBER(3);
    v_message VARCHAR2(500);

    v_clob_varchar2 VARCHAR2(4000);

BEGIN
    --查詢實際表[訂單接口  XQ_MIDSO]中的[是否生成訂單]爲Y的記錄
    FOR v_list IN (SELECT xms.id, xms.ad_client_id, xms.ad_org_id,
                          xms.creationdate, xms.ownerid, xms.errormeg
                   FROM xq_midso xms
                   WHERE xms.is_so = 'Y') LOOP
        BEGIN
        
            --獲取接口信息
            SELECT dbms_lob.substr(xms.param)
            INTO v_clob_varchar2
            FROM xq_midso xms
            WHERE xms.id = v_list.id;
        
            v_injson := json(v_clob_varchar2);
        
            --獲取headerlist:orderHeader
            --v_id := json_ext.get_string(v_injson, 'CallInfo.orderHeader.id');
            v_ordercode := json_ext.get_string(v_injson,
                                               'CallInfo.orderHeader.ordercode');
            v_customer_name := json_ext.get_string(v_injson,
                                                   'CallInfo.orderHeader.customer_name');
            v_delivery_time := substr(json_ext.get_string(v_injson,
                                                          'CallInfo.orderHeader.delivery_time'),
                                      1, 10);
            v_delivery_time1 := to_number(REPLACE(v_delivery_time, '-', ''));
            v_delivery_address := json_ext.get_string(v_injson,
                                                      'CallInfo.orderHeader.delivery_address');
        
            --獲取表b_so的id
            SELECT id
            INTO v_table_id
            FROM ad_table
            WHERE NAME = upper('b_so');
        
            --自動生成單據編號
            SELECT t.sequencename
            INTO v_b_so_docno
            FROM ad_column t
            WHERE t.ad_table_id = v_table_id
            AND t.dbname = 'DOCNO';
        
            v_b_so_docno := get_sequenceno(v_b_so_docno, v_list.ad_client_id);
        
            --獲取要使用的發貨訂單id
            v_b_so_id := get_sequences('B_SO');
        
            --獲取總部店倉ID
            SELECT cs.id
            INTO v_c_store_id
            FROM c_store cs
            WHERE cs.name = '總部倉庫'
            AND cs.ad_client_id = v_list.ad_client_id;
        
            BEGIN
                --獲取對應經銷商下任一店倉ID:v_cc_store_id
                SELECT nvl(cs.id, 0)
                INTO v_cc_store_id
                FROM c_store cs
                JOIN c_customer ccu
                ON (cs.c_customer_id = ccu.id AND ccu.name = v_customer_name)
                WHERE rownum <= 1;
            EXCEPTION
                WHEN no_data_found THEN
                    v_cc_store_id := NULL;
            END;
            /*
            生成發貨訂單頭表:
            單據日期取SYSDATE。
            訂單類型取新貨訂單。
            發貨店倉取總部店倉。
            收貨店倉取接口中的customer_name對應的經銷商下的任一店倉(根據名稱匹配)。
            鮮橋訂單編碼取接口中的ordercode。
            備註:由鮮橋接口自動生成!
             調用存儲過程:B_SO_AC。
            */
            --dbms_output.put_line('xuyang123:v_b_so_docno:' || v_b_so_docno);
            BEGIN
                INSERT INTO b_so
                    (id, billdate, docno, doctype, c_store_id, c_dest_id,
                     xq_ordercode, predateout, dest_address, description,
                     ad_client_id, ad_org_id, ownerid, creationdate, status,
                     isactive)
                VALUES
                    (v_b_so_id, to_number(to_char(SYSDATE, 'yyyymmdd')),
                     v_b_so_docno, 'FWD', v_c_store_id, v_cc_store_id,
                     v_ordercode, v_delivery_time1, v_delivery_address,
                     '由鮮橋接口自動生成!', v_list.ad_client_id, v_list.ad_org_id,
                     v_list.ownerid, SYSDATE, 1, 'Y');
            EXCEPTION
                WHEN OTHERS THEN
                    dbms_output.put_line('(debug)訂單接口記錄id:' || v_list.id ||
                                         ',生成發貨訂單發生異常:' || SQLERRM);
                    CONTINUE;
            END;
        
            --調用存儲過程:B_SO_AC。
            BEGIN
                b_so_ac(v_b_so_id);
            EXCEPTION
                WHEN OTHERS THEN
                    dbms_output.put_line('發貨訂單記錄id:' || v_b_so_id ||
                                         ',調用發貨訂單ac程序b_so_ac發生異常:' || SQLERRM);
            END;
            /*獲取明細數據,插入到發貨訂單明細表*/
            /*
              生成發貨訂單明細:
              條碼、款號、ASI取接口中的product_name對應條碼的值。
              數量取接口中的amount。
              調用存儲過程:B_SOITEM_ACM。
              調用存儲過程:B_SO_AM。
            */
            v_bodylist := json_list();
            v_onejson := json();
        
            --獲取body:orderBody
            v_bodylist := json_ext.get_json_list(v_injson, 'CallInfo.orderBody');
        
            --循環獲取明細數據,並插入數據庫中
            FOR idx IN 1 .. v_bodylist.count LOOP
                --讀取每一個明細信息
                v_onejson := json(v_bodylist.get_elem(idx));
                v_m_productalias_name := json_ext.get_string(v_onejson,
                                                             'product_name');
                v_amount := to_number(json_ext.get_string(v_onejson, 'amount'));
            
                --獲取品名對應的款號,條碼,asi
                BEGIN
                    SELECT mpa.id, mpa.m_product_id,
                           mpa.m_attributesetinstance_id
                    INTO v_m_productalias_id, v_m_product_id, v_asi
                    FROM m_product_alias mpa
                    WHERE mpa.no = v_m_productalias_name;
                EXCEPTION
                    WHEN no_data_found THEN
                        dbms_output.put_line('條碼:' || v_m_productalias_name ||
                                             ',在條碼檔案中不存在!');
                        CONTINUE;
                END;
                --獲取即將使用的發貨訂單明細記錄id
                v_b_soitem_id := get_sequences('bo_soitem');
            
                --插入發貨訂單明細表
                INSERT INTO b_soitem
                    (id, b_so_id, m_productalias_id, m_product_id,
                     m_attributesetinstance_id, qty)
                VALUES
                    (v_b_soitem_id, v_b_so_id, v_m_productalias_id,
                     v_m_product_id, v_asi, v_amount);
            
                --調用存儲過程:B_SOITEM_ACM
                BEGIN
                    b_soitem_acm(v_b_soitem_id);
                EXCEPTION
                    WHEN OTHERS THEN
                        dbms_output.put_line('發貨訂單明細記錄id:' || v_b_soitem_id ||
                                             ',調用發貨訂單明細acm程序b_soitem_acm發生異常:' ||
                                             SQLERRM);
                END;
            
                --調用存儲過程:B_SO_AM
                BEGIN
                    b_so_am(v_b_so_id, v_code, v_message);
                EXCEPTION
                    WHEN OTHERS THEN
                        dbms_output.put_line('發貨訂單記錄id:' || v_b_so_id ||
                                             ',調用發貨訂單am程序B_SO_AM發生異常:' ||
                                             SQLERRM);
                END;
            
            END LOOP;
        
            --生成發貨訂單後,更新訂單接口xq_midso當前記錄is_so爲‘N’
            UPDATE xq_midso xms
            SET xms.is_so = 'N'
            WHERE xms.id = v_list.id;
        
            COMMIT;
        
        EXCEPTION
            WHEN OTHERS THEN
                dbms_output.put_line('訂單接口記錄id:' || v_list.id ||
                                     ',生成發貨訂單發生異常:' || SQLERRM);
        END;
    END LOOP;

END;




----用於自動生成單據編號
CREATE OR REPLACE FUNCTION get_sequenceno(p_seqname  IN VARCHAR2,
                                          p_clientid IN NUMBER) RETURN VARCHAR2 AS
    PRAGMA AUTONOMOUS_TRANSACTION;
    v_prefix      VARCHAR2(30);
    v_postfix     VARCHAR2(30);
    v_format      VARCHAR2(120);
    v_currentnext NUMBER(10);
    v_id          NUMBER(10);
    v_lastdate    DATE;
    v_no          VARCHAR2(255);
    v_cycletype   CHAR(1);
    v_incrementno NUMBER(10);
    v_sql         VARCHAR2(400);
    pctx          plog.log_ctx := plog.init('Get_SequenceNo', plog.linfo);

    /**
    *  根據ad_table定義的ad_sequence的名字
    *  vFormat 中含有生成的序列的規則, 最終的編號規則是
    *  prefix + vFormat + postfix
    *  vFormat 中 yy/mm/dd 表示年,9999表示按日循環遞增,0000表示無循環遞增
    *  @param p_seqName 是 ad_sequence 表的name 字段的值
    */
BEGIN
    SELECT id, nvl(prefix, ''), nvl(suffix, ''), vformat, currentnext,
           to_date(to_char(lastdate), 'YYYYMMDD'), cycletype,
           nvl(incrementno, 1)
    INTO v_id, v_prefix, v_postfix, v_format, v_currentnext, v_lastdate,
         v_cycletype, v_incrementno
    FROM ad_sequence
    WHERE NAME = upper(TRIM(p_seqname))
    AND ad_client_id = p_clientid
    FOR UPDATE;

    IF v_cycletype = 'D' THEN
        -- cycle by day
        IF to_char(v_lastdate, 'yyyymmdd') <> to_char(SYSDATE, 'yyyymmdd') THEN
            v_currentnext := 0;
        END IF;
    ELSIF v_cycletype = 'M' THEN
        -- cycle by month
        IF to_char(v_lastdate, 'yyyymm') <> to_char(SYSDATE, 'yyyymm') THEN
            v_currentnext := 0;
        END IF;
    ELSIF v_cycletype = 'Y' THEN
        -- cycle by year
        IF to_char(v_lastdate, 'yyyy') <> to_char(SYSDATE, 'yyyy') THEN
            v_currentnext := 0;
        END IF;
    END IF;

    v_currentnext := v_currentnext + v_incrementno;

    UPDATE ad_sequence
    SET lastdate = to_number(to_char(SYSDATE, 'YYYYMMDD')),
        currentnext = v_currentnext
    WHERE id = v_id;

    v_sql := 'select ' ||
             REPLACE(v_format, '$nextval', ltrim(to_char(v_currentnext))) ||
             ' from dual ';
    EXECUTE IMMEDIATE v_sql
        INTO v_no;

    COMMIT;
    plog.info(pctx,
              'p_seqName=' || p_seqname || ', CURRENTNEXT=' || v_currentnext ||
               ', v_lastdate=' || v_lastdate);
    COMMIT;
    RETURN v_prefix || v_no || v_postfix;
EXCEPTION
    WHEN OTHERS THEN
        ROLLBACK;
        plog.error(pctx,
                   'Error for Get_SequenceNo(' || p_seqname || ',' ||
                    p_clientid || '):code=' || SQLCODE || ', err=' || SQLERRM);
        COMMIT;
        raise_application_error(-20201, '沒法生成名稱爲 ' || p_seqname || ' 的單據號!');

END;

---------------------------------------------------------------
報表
----0030525: 1、20180727-V1.0-凰艮項目20180717-雲倉訂單信息彙總表 4h
CREATE OR REPLACE PROCEDURE rp_o2oinfo_generate(p_pi_id NUMBER) IS
    ---------------------------------------------------
    --Author:xy
    -- Date:20180721
    -- Description :
    -- 查詢單據日期在查詢條件的單據日期範圍內、 下單店倉與查詢條件的店倉一致、而且已提交的、未結案、可用的雲倉訂單
    ---------------------------------------------------

    v_userid      NUMBER(10);
    v_date        VARCHAR2(80);
    v_datebegin   NUMBER(8); --開始日期
    v_dateend     NUMBER(8); --結束日期
    v_c_store_ids r_tabid := r_tabid(); --下單店倉id集合

    v_sql1 VARCHAR2(4000);

BEGIN
    -- raise_application_error(-20201, p_pi_id);
    EXECUTE IMMEDIATE ('truncate TABLE RP_O2OINFO');

    --定義公共sql
    v_sql1 := 'SELECT t.info
                      FROM ad_pinstance_para t
                      WHERE t.name = :name AND t.ad_pinstance_id = :p_pi_id';

    SELECT t.modifierid
    INTO v_userid
    FROM ad_pinstance t
    WHERE t.id = p_pi_id;
    --依次獲取界面查詢條件參數

    EXECUTE IMMEDIATE v_sql1
        INTO v_date
        USING 'BILLDATE', p_pi_id;

    IF v_date IS NULL THEN
        --如開始日期和結束日期都沒有選擇,
        raise_application_error(-20201, '請選擇單據日期範圍!');
    ELSE
        IF instr(v_date, '>=') > 0 THEN
        
            --如只選擇了開始日期,則結束日期默認爲當前時間
            --注意這裏是否是從9開始,取決於日期參數定義,例如日期參數名定義爲DATE,則此處爲9,如定義爲BILLDATE,此處爲13,以此類推
        
            v_datebegin := substr(v_date, 13, 8);
            --結束日期默認爲當前日期
            v_dateend := to_char(SYSDATE, 'yyyymmdd');
        
        ELSIF instr(v_date, '<=') > 0 THEN
            --如只選擇告終束日期,則開始日期默認18400101
            --注意這裏是否是從9開始,取決於日期參數定義,例如日期參數名定義爲DATE,則此處爲9,如定義爲BILLDATE,此處爲13,以此類推
            v_dateend := substr(v_date, 13, 8);
        
            v_datebegin := 18400101;
        ELSE
            v_datebegin := substr(v_date, 21, 8);
            v_dateend := substr(v_date, 34, 8);
        END IF;
    END IF;

    --獲取下單店倉id集合
    EXECUTE IMMEDIATE v_sql1
        INTO v_sql1
        USING 'C_STORE_ID', p_pi_id;

    v_c_store_ids := f_fast_table(v_sql1);

    IF v_c_store_ids.COUNT = 0 THEN
        v_sql1 := 'SELECT CS.ID FROM C_STORE CS WHERE CS.ISACTIVE = ''Y''';
        v_c_store_ids := f_fast_table(v_sql1);
    END IF;

    --下單次數:單據日期等於行定義單據日期,下單店倉等於行定義店鋪,已提交的可用的雲倉訂單的個數
    INSERT INTO rp_o2oinfo
        (id, ad_client_id, ad_org_id, billdate, yearmonth, c_store_id, ownerid,
         isactive, ordernum, ad_pi_id)
        SELECT get_sequences('RP_O2OINFO'), os.ad_client_id, os.ad_org_id,
               os.billdate, substr(os.billdate, 1, 6), os.c_store_id, os.ownerid,
               'Y', COUNT(1), p_pi_id
        FROM o2o_so os, TABLE(v_c_store_ids) vs
        WHERE os.isactive = 'Y'
        AND os.status = 2
        AND os.close_status = 1
        AND os.billdate BETWEEN v_datebegin AND v_dateend
        AND os.c_store_id = vs.id
        GROUP BY os.ad_client_id, os.ad_org_id, os.billdate, os.c_store_id,
                 os.ownerid;

    --發貨次數:發貨日期等於行定義的單據日期,發貨店倉等於行定義店鋪,發貨狀態爲已提交的雲倉訂單的個數
    --快遞費用:發貨時間的日期等於行定義單據日期,發貨店倉等於行定義店鋪,發貨狀態爲已提交的雲倉訂單中快遞費用/元的和
    MERGE INTO rp_o2oinfo rp
    USING (SELECT os.dateoutin, os.c_orig_id, COUNT(os.id) AS cnt,
                  SUM(os.deliverycosts) AS tot_exp_fee
           FROM o2o_so os, TABLE(v_c_store_ids) vs
           WHERE os.isactive = 'Y'
           AND os.out_status = 2
           AND os.status = 2
           AND os.close_status = 1
           AND os.dateoutin BETWEEN v_datebegin AND v_dateend
           AND os.c_orig_id = vs.id
           GROUP BY os.dateoutin, os.c_orig_id) tp
    ON (rp.c_store_id = tp.c_orig_id AND rp.billdate = tp.dateoutin)
    WHEN MATCHED THEN
        UPDATE
        SET rp.deliverynum = tp.cnt, rp.express_fee = tp.tot_exp_fee;

    --客訴:單據日期等於行定義單據日期,發貨店倉等於行定義店鋪,已提交的客訴申請單的的個數。
    MERGE INTO rp_o2oinfo rp
    USING (SELECT cc.billdate, cc.c_orig_id, COUNT(cc.id) AS cnt
           FROM c_complain cc, TABLE(v_c_store_ids) vs
           WHERE cc.status = 2
           AND cc.billdate BETWEEN v_datebegin AND v_dateend
           AND cc.c_orig_id = vs.id
           GROUP BY cc.billdate, cc.c_orig_id) tp
    ON (rp.c_store_id = tp.c_orig_id AND rp.billdate = tp.billdate)
    WHEN MATCHED THEN
        UPDATE
        SET rp.complain_num = tp.cnt;

    --拒單次數:變動時間的日期等於行定義單據日期,店倉等於行定義店鋪,
    --從新指派緣由或者退回緣由不爲空的表【派單日誌O2O_SOSPLIT_LOG】的記錄的條數。
    MERGE INTO rp_o2oinfo rp
    USING (SELECT to_number(to_char(osl.changetime, 'YYYYMMDD')) AS changedate,
                  osl.c_store_id, COUNT(osl.id) AS cnt
           FROM o2o_sosplit_log osl, TABLE(v_c_store_ids) vs
           WHERE to_number(to_char(osl.changetime, 'YYYYMMDD')) BETWEEN
                 v_datebegin AND v_dateend
           AND (osl.o2o_assignorig_reason_id IS NOT NULL OR
                  osl.o2o_back_reason_id IS NOT NULL)
           AND osl.c_store_id = vs.id
           GROUP BY to_number(to_char(osl.changetime, 'YYYYMMDD')),
                    osl.c_store_id) tp
    ON (rp.billdate = tp.changedate AND rp.c_store_id = tp.c_store_id)
    WHEN MATCHED THEN
        UPDATE
        SET rp.reject_ordernum = tp.cnt;

    --次品拒單:變動時間的日期等於行定義單據日期,店倉等於行定義店鋪,
    --退回緣由O2O_BACK_REASON_ID等於表【退回緣由O2O_BACK_REASON】中描述=「貨品殘次」;表【派單日誌O2O_SOSPLIT_LOG】的記錄的條數。
    MERGE INTO rp_o2oinfo rp
    USING (SELECT to_number(to_char(osl.changetime, 'YYYYMMDD')) AS changedate,
                  osl.c_store_id, COUNT(osl.id) AS cnt
           FROM o2o_sosplit_log osl, o2o_back_reason obr, TABLE(v_c_store_ids) vs
           WHERE to_number(to_char(osl.changetime, 'YYYYMMDD')) BETWEEN
                 v_datebegin AND v_dateend
           AND obr.id = osl.o2o_back_reason_id
           AND obr.NAME = '貨品殘次'
           AND osl.c_store_id = vs.id
           GROUP BY to_number(to_char(osl.changetime, 'YYYYMMDD')),
                    osl.c_store_id) tp
    ON (rp.billdate = tp.changedate AND rp.c_store_id = tp.c_store_id)
    WHEN MATCHED THEN
        UPDATE
        SET rp.reject_defectnum = tp.cnt;

    --無實貨拒單:變動時間的日期等於行定義單據日期,店倉等於行定義店鋪,
    --退回緣由O2O_BACK_REASON_ID等於表【退回緣由O2O_BACK_REASON】中描述=「庫存不足」;表【派單日誌O2O_SOSPLIT_LOG】的記錄的條數。
    MERGE INTO rp_o2oinfo rp
    USING (SELECT to_number(to_char(osl.changetime, 'YYYYMMDD')) AS changedate,
                  osl.c_store_id, COUNT(osl.id) AS cnt
           FROM o2o_sosplit_log osl, o2o_back_reason obr, TABLE(v_c_store_ids) vs
           WHERE to_number(to_char(osl.changetime, 'YYYYMMDD')) BETWEEN
                 v_datebegin AND v_dateend
           AND obr.id = osl.o2o_back_reason_id
           AND obr.NAME = '庫存不足'
           AND osl.c_store_id = vs.id
           GROUP BY to_number(to_char(osl.changetime, 'YYYYMMDD')),
                    osl.c_store_id) tp
    ON (rp.billdate = tp.changedate AND rp.c_store_id = tp.c_store_id)
    WHEN MATCHED THEN
        UPDATE
        SET rp.rejet_nogoods_num = tp.cnt;

    --超時轉單次數:變動時間的日期等於行定義單據日期,店倉等於行定義店鋪,
    --退回緣由O2O_BACK_REASON_ID等於表【退回緣由O2O_BACK_REASON】中描述=「系統退回」;表【派單日誌O2O_SOSPLIT_LOG】的記錄的條數。
    MERGE INTO rp_o2oinfo rp
    USING (SELECT to_number(to_char(osl.changetime, 'YYYYMMDD')) AS changedate,
                  osl.c_store_id, COUNT(osl.id) AS cnt
           FROM o2o_sosplit_log osl, o2o_back_reason obr, TABLE(v_c_store_ids) vs
           WHERE to_number(to_char(osl.changetime, 'YYYYMMDD')) BETWEEN
                 v_datebegin AND v_dateend
           AND obr.id = osl.o2o_back_reason_id
           AND obr.NAME = '系統退回'
           AND osl.c_store_id = vs.id
           GROUP BY to_number(to_char(osl.changetime, 'YYYYMMDD')),
                    osl.c_store_id) tp
    ON (rp.billdate = tp.changedate AND rp.c_store_id = tp.c_store_id)
    WHEN MATCHED THEN
        UPDATE
        SET rp.overtime_ordernum = tp.cnt;

    --所得獎勵:激勵時間的日期等於行定義單據日期,店鋪等於行定義店鋪,表【店鋪激勵明細表】中激勵金額的和。
    MERGE INTO rp_o2oinfo rp
    USING (SELECT to_number(to_char(cso.supdate, 'YYYYMMDD')) AS supdate,
                  cso.c_store_id, SUM(cso.supamt) AS tot_supamt
           FROM c_storesup_o2o cso, TABLE(v_c_store_ids) vs
           WHERE to_number(to_char(cso.supdate, 'YYYYMMDD')) BETWEEN v_datebegin AND
                 v_dateend
           AND cso.c_store_id = vs.id
           GROUP BY to_number(to_char(cso.supdate, 'YYYYMMDD')), cso.c_store_id) tp
    ON (rp.billdate = tp.supdate AND rp.c_store_id = tp.c_store_id)
    WHEN MATCHED THEN
        UPDATE
        SET rp.reward = tp.tot_supamt;

    --信用分:變更日期等於行定義單據日期,店倉等於行定義店倉,表【店倉信用流水帳】中信用額度的和。
    MERGE INTO rp_o2oinfo rp
    USING (SELECT fsf.c_store_id, fsf.changedate,
                  SUM(fsf.credit_quota) AS tot_cred_quota
           FROM fa_storecredit_ftp fsf, TABLE(v_c_store_ids) vs
           WHERE fsf.changedate BETWEEN v_datebegin AND v_dateend
           AND fsf.c_store_id = vs.id
           GROUP BY fsf.changedate, fsf.c_store_id) tp
    ON (rp.billdate = tp.changedate AND rp.c_store_id = tp.c_store_id)
    WHEN MATCHED THEN
        UPDATE
        SET rp.credit_score = tp.tot_cred_quota;

END;

----------------------------------------------------------------------------
--美邦:期貨銷售合同中的’預配‘動做定義

CREATE OR REPLACE PROCEDURE b_perallot_gen(p_user_id IN NUMBER,
                                           p_query   IN VARCHAR2,
                                           r_code    OUT NUMBER,
                                           r_message OUT VARCHAR2) AS
    ---------------------------------------------------------
    --author: xy
    --date: 20180725
    --併發控制。
    --增長控制:若是單據未提交,不容許。
    --增長控制:若是系統中存在期貨合同編號爲本單的期貨定貨單或期貨配差單,不容許。
    --增長控制:若是期貨銷售合同在中間表中已經存在,不容許再次傳入(用合同編號判斷)。
    --將本單期貨銷售合同頭表信息傳入中間表[UNI_FIRSO]、期貨銷售合同明細信息傳入中間表[UNI_FIRSOITEM]
    --傳入中間表後,更新單據的[預配是否傳入中間表]爲Y
    ---------------------------------------------------------
    --聲明用於從p_query解析參數得到單據ID的相關記錄和變量
    TYPE t_queryobj IS RECORD(
        "table" VARCHAR2(255),
        query   VARCHAR2(32676),
        id      VARCHAR2(10));
    v_queryobj t_queryobj;
    TYPE t_selection IS TABLE OF NUMBER(10) INDEX BY BINARY_INTEGER;
    v_selection t_selection;
    st_xml      VARCHAR2(32676);
    v_xml       xmltype;
    p_id        NUMBER(10); --單據ID

    --其餘變量定義
    v_status b_fir_so.status%TYPE; --單據狀態
    v_docno  b_fir_so.docno%TYPE; --單據編號

    v_cnt  NUMBER(10);
    v_cnt1 NUMBER(10);

BEGIN
    --從p_query解析參數
    st_xml := '<data>' || p_query || '</data>';
    v_xml := xmltype(st_xml);

    SELECT extractvalue(VALUE(t), '/data/table'),
           extractvalue(VALUE(t), '/data/query'),
           extractvalue(VALUE(t), '/data/id')
    INTO v_queryobj
    FROM TABLE(xmlsequence(extract(v_xml, '/data'))) t;

    SELECT extractvalue(VALUE(t), '/selection')
    BULK COLLECT
    INTO v_selection
    FROM TABLE(xmlsequence(extract(v_xml, '/data/selection'))) t;
    p_id := v_queryobj.id;

    --end 解析參數

    --併發控制
    BEGIN
        EXECUTE IMMEDIATE 'select 1 from b_fir_so t where t.id=' || p_id ||
                          ' for update nowait';
    EXCEPTION
        WHEN OTHERS THEN
            raise_application_error(-20201, SQLERRM);
    END;

    --獲取提交狀態,單據編號
    SELECT bfs.status, bfs.docno
    INTO v_status, v_docno
    FROM b_fir_so bfs
    WHERE bfs.id = p_id;

    --若是單據未提交,不容許
    IF v_status = 1 THEN
        raise_application_error(-20201, '單據未提交,不容許!');
    END IF;

    --若是系統中存在期貨合同編號爲本單的期貨定貨單或期貨配差單,不容許
    SELECT nvl(COUNT(1), 0)
    INTO v_cnt
    FROM b_fwdso bfw
    WHERE bfw.b_fir_so_id = p_id;

    SELECT nvl(COUNT(1), 0)
    INTO v_cnt1
    FROM b_fwdtocan bfw
    WHERE bfw.b_fir_so_id = p_id;

    IF v_cnt <> 0 OR v_cnt1 <> 0 THEN
        raise_application_error(-20201, '系統中存在期貨合同編號爲本單的期貨定貨單或期貨配差單,不容許!');
    END IF;

    --若是期貨銷售合同在中間表中已經存在,不容許再次傳入(用合同編號判斷)
    SELECT nvl(COUNT(id), 0)
    INTO v_cnt
    FROM uni_firso uf
    WHERE uf.code = v_docno;

    IF v_cnt <> 0 THEN
        raise_application_error(-20201,
                                '期貨銷售合同:' || v_docno || '在中間表中已經存在,不容許再次傳入!');
    END IF;

    --將本單期貨銷售合同頭表信息傳入中間表[UNI_FIRSO]、期貨銷售合同明細信息傳入中間表[UNI_FIRSOITEM]
    INSERT INTO uni_firso
        (id, ad_client_id, ad_org_id, code, vender_code, vendee_code, doc_date,
         shop_code, rcv_wareh_code, is_assign_wareh, assign_wareh_code,
         order_qty, audit_date, require_date, brand_code, remark, ediflag,
         ownerid, modifierid, creationdate, modifieddate, isactive)
        SELECT bfs.id, bfs.ad_client_id, bfs.ad_org_id, bfs.docno, gc.code,
               gc1.code, bfs.billdate, cs.code,
               decode(bfs.protype, 1, cs1.code, 2, cs2.code),
               decode(bfs.is_origstore, 'Y', 'T', 'N', 'F'), cs3.code,
               bfs.tot_qty, bfs.statustime, bfs.perdate, md.attribcode,
               bfs.description, 80, p_user_id, p_user_id, SYSDATE, SYSDATE, 'Y'
        FROM b_fir_so bfs
        LEFT JOIN g_company gc
        ON (gc.id = bfs.g_company_id)
        LEFT JOIN g_company gc1
        ON (gc1.id = bfs.g_destpany_id)
        LEFT JOIN c_store cs
        ON (cs.id = bfs.c_dest_id)
        LEFT JOIN c_store cs1
        ON (cs1.id = cs.c_spstore_id)
        LEFT JOIN c_store cs2
        ON (cs2.id = cs.c_flstore_id)
        LEFT JOIN c_store cs3
        ON (cs3.id = bfs.c_store_id)
        LEFT JOIN m_dim md
        ON (md.id = bfs.m_dim1_id)
        WHERE bfs.id = p_id;

    INSERT INTO uni_firsoitem
        (id, ad_client_id, ad_org_id, fuc_code, prod_code, order_qty, ediflag,
         ownerid, modifierid, creationdate, modifieddate, isactive)
        SELECT bfi.id, bfi.ad_client_id, bfi.ad_org_id, v_docno, mpa.no, bfi.qty,
               80, p_user_id, p_user_id, SYSDATE, SYSDATE, 'Y'
        FROM b_fir_soitem bfi
        JOIN m_product_alias mpa
        ON (mpa.id = bfi.m_productalias_id)
        WHERE bfi.b_fir_so_id = p_id;

    --傳入中間表後,更新單據的[預配是否傳入中間表] 
    UPDATE b_fir_so bfs
    SET bfs.is_pretouni = 'Y'
    WHERE bfs.id = p_id;

    r_code := 1;
    r_message := '預配成功!!';
END;
---------------------------------------------------------------------------------
 

  

 --從界面端clob字段獲取對應sql語句
CREATE OR REPLACE FUNCTION get_fitler_sql(p_str IN CLOB) RETURN CLOB IS

  v_xml    xmltype;
  myresult CLOB;

BEGIN

  --edit by robin 解決超過4000個字符問題
  if p_str is null then
  return null;
  end if;

  begin
    v_xml:=xmltype(p_str);
    SELECT extractvalue(VALUE(t), '/filter/sql')
      INTO myresult
      FROM TABLE(xmlsequence(extract(v_xml, '/filter'))) t;

  exception
    when others then
      myresult := clobTransXml(clobSubStr(p_str, '<sql>', '</sql>'));
  end;
  RETURN myresult;

END get_fitler_sql;

----------------------------------------------------------------------------
--獲取對應記錄id集合
create or replace function f_fast_table(v_sql in varchar2) return r_tabid as
    v_test r_tabid := r_tabid();
    type t_type1 is table of number(10) index by binary_integer;
    p_id t_type1;
begin

    execute immediate v_sql bulk collect into p_id;
    
    if p_id.count != 0 then
    for i in 1 .. p_id.last loop
        v_test.extend();
        v_test(v_test.count) := r_id(p_id(i));
    end loop;
    else
        v_test.extend();
        v_test(1) := r_id(0);
    end if;
    return v_test;
end ;
-------------------------------------------------------------------------
--獲取指定單據編號
CREATE OR REPLACE FUNCTION get_sequenceno(p_seqname  IN VARCHAR2,
                                          p_clientid IN NUMBER) RETURN VARCHAR2 AS
    PRAGMA AUTONOMOUS_TRANSACTION;
    v_prefix      VARCHAR2(30);
    v_postfix     VARCHAR2(30);
    v_format      VARCHAR2(120);
    v_currentnext NUMBER(10);
    v_id          NUMBER(10);
    v_lastdate    DATE;
    v_no          VARCHAR2(255);
    v_cycletype   CHAR(1);
    v_incrementno NUMBER(10);
    v_sql         VARCHAR2(400);
    pctx          plog.log_ctx := plog.init('Get_SequenceNo', plog.linfo);

    /**
    *  根據ad_table定義的ad_sequence的名字
    *  vFormat 中含有生成的序列的規則, 最終的編號規則是
    *  prefix + vFormat + postfix
    *  vFormat 中 yy/mm/dd 表示年,9999表示按日循環遞增,0000表示無循環遞增
    *  @param p_seqName 是 ad_sequence 表的name 字段的值
    */
BEGIN
    SELECT id, nvl(prefix, ''), nvl(suffix, ''), vformat, currentnext,
           to_date(to_char(lastdate), 'YYYYMMDD'), cycletype,
           nvl(incrementno, 1)
    INTO v_id, v_prefix, v_postfix, v_format, v_currentnext, v_lastdate,
         v_cycletype, v_incrementno
    FROM ad_sequence
    WHERE NAME = upper(TRIM(p_seqname))
    AND ad_client_id = p_clientid
    FOR UPDATE;

    IF v_cycletype = 'D' THEN
        -- cycle by day
        IF to_char(v_lastdate, 'yyyymmdd') <> to_char(SYSDATE, 'yyyymmdd') THEN
            v_currentnext := 0;
        END IF;
    ELSIF v_cycletype = 'M' THEN
        -- cycle by month
        IF to_char(v_lastdate, 'yyyymm') <> to_char(SYSDATE, 'yyyymm') THEN
            v_currentnext := 0;
        END IF;
    ELSIF v_cycletype = 'Y' THEN
        -- cycle by year
        IF to_char(v_lastdate, 'yyyy') <> to_char(SYSDATE, 'yyyy') THEN
            v_currentnext := 0;
        END IF;
    END IF;

    v_currentnext := v_currentnext + v_incrementno;

    UPDATE ad_sequence
    SET lastdate = to_number(to_char(SYSDATE, 'YYYYMMDD')),
        currentnext = v_currentnext
    WHERE id = v_id;

    v_sql := 'select ' ||
             REPLACE(v_format, '$nextval', ltrim(to_char(v_currentnext))) ||
             ' from dual ';
    EXECUTE IMMEDIATE v_sql
        INTO v_no;

    COMMIT;
    plog.info(pctx,
              'p_seqName=' || p_seqname || ', CURRENTNEXT=' || v_currentnext ||
               ', v_lastdate=' || v_lastdate);
    COMMIT;
    RETURN v_prefix || v_no || v_postfix;
EXCEPTION
    WHEN OTHERS THEN
        ROLLBACK;
        plog.error(pctx,
                   'Error for Get_SequenceNo(' || p_seqname || ',' ||
                    p_clientid || '):code=' || SQLCODE || ', err=' || SQLERRM);
        COMMIT;
        raise_application_error(-20201, '沒法生成名稱爲 ' || p_seqname || ' 的單據號!');

END;

  

------html

(美邦)存儲過程:MATMULTI_INVENTORY
--彈出一個對話框,而且在關閉時刷新後面的那張網頁
SELECT to_char(id)
INTO t_id
FROM ad_table
WHERE NAME = 'M_MATMULTI_INVENTORY';

r_code := 5;
r_message := 'showDialog("/html/nds/object/object.jsp?table=' || t_id ||
             '&fixedcolumns=&id=' || v_m_matmulti_inventory_id ||
             '",940, 530,true)'; 

  

 

 

-->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
輸入的數據已存在ID: 
SELECT MAX(ID) FROM AD_COLUMN;
根據max(ID)設置序列SEQ_AD_COLUMN的下一個值
-->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
相關文章
相關標籤/搜索