--报表:注意: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的下一个值 -->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>