• 工作常用



    --报表:注意: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: 如果单据未提交,不允许取消提交。
        -- 更新单据状态为1、提交人为空、提交时间为空
        -------------------------------------------------------------------------
    
        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;
    
        -- 更新单据状态为1、提交人为空、提交时间为空
        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 提交生成!
        */
        --增加控制:将本单明细的数据按照商品汇总,生成成本调整单明细:
        /*
        商品:返利成本调整单明细的商品。
        单品成本:取明细中该商品的调整成本(取平均值,不能取合计值)
        */
        --更新单据状态为2、提交人为单据的修改人、提交时间为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;
    
        -- 更新单据状态为2、提交人为单据的修改人、提交时间为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,则此处为17、30,如定义为BILLDATE,此处为21、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,则此处为17、30,如定义为BILLDATE,此处为21、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,则此处为17、30,如定义为BILLDATE,此处为21、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,则此处为17、30,如定义为BILLDATE,此处为21、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,则此处为17、30,如定义为BILLDATE,此处为21、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,则此处为17、30,如定义为BILLDATE,此处为21、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: 一、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;
    

      

    ------

    (美邦)存储过程: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的下一个值
    -->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    

      

  • 相关阅读:
    jQuery实现返回顶部
    css position全解析
    css选择器优先级全解析
    java算法(二)
    java实现输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。
    用1、2、2、3、4、5这六个数字,用java写一个main函数,打印出所有不同的排列,如:512234、412345等,要求:"4"不能在第三位,"3"与"5"不能相连。
    java输出任意两个日期之间有多少天
    假如现在有一堆长度大于3小于9的电话号码,用座机呼叫,如果出现这样的号码【123和12345】那么12345将永远不会被拨出,因为拨到123的时候电话已经呼出了,试写一个函数输出所有不能被呼出的电话号码(java实现)
    解如下方程(java实现)
    统计第一个空字符前面的字符长度(java实现)
  • 原文地址:https://www.cnblogs.com/Jeffrey-xu/p/9388669.html
Copyright © 2020-2023  润新知