/* 庫齡表重新開發 部分交易型態需歸類到最後區間,非所有都先進先出 */ DECLARE P_ORG_ID NUMBER := 137; P_DATE VARCHAR2(10) := '2023-03-31'; --P_ITEM VARCHAR2(100) := '4G1R-CHECK-VALVE'; P_COUNT NUMBER; --取得庫存、料號相關資訊 CURSOR ON_HAND_INFO IS SELECT MMT.ORGANIZATION_ID, MMT.INVENTORY_ITEM_ID, MSI.SEGMENT1, --MMT.SUBINVENTORY_CODE, SUM(MMT.PRIMARY_QUANTITY) ON_HAND_QTY FROM MTL_MATERIAL_TRANSACTIONS MMT, MTL_SYSTEM_ITEMS_B MSI, MTL_SECONDARY_INVENTORIES SUBINV WHERE 1 = 1 AND MMT.INVENTORY_ITEM_ID = MSI.INVENTORY_ITEM_ID AND MMT.ORGANIZATION_ID = MSI.ORGANIZATION_ID AND MMT.SUBINVENTORY_CODE = SUBINV.SECONDARY_INVENTORY_NAME AND MMT.ORGANIZATION_ID = SUBINV.ORGANIZATION_ID --AND MSI.SEGMENT1 = P_ITEM AND MMT.ORGANIZATION_ID = P_ORG_ID AND TRUNC(MMT.TRANSACTION_DATE) <= TO_DATE(P_DATE, 'YYYY-MM-DD') --庫存計算截止時間 AND SUBINV.ASSET_INVENTORY <> 2 --排除費用倉 AND MSI.INVENTORY_ITEM_ID NOT IN (201795, 201796, 201797, 14137273) --原程式排除料號 CHARGE、DEPOSIT、REPAIR、SERVICE FEE GROUP BY MMT.ORGANIZATION_ID, MMT.INVENTORY_ITEM_ID, MSI.SEGMENT1 --,MMT.SUBINVENTORY_CODE HAVING SUM(MMT.PRIMARY_QUANTITY) <> 0; --取得交易資料 CURSOR MMT(P_ORGANIZATION_ID NUMBER, P_INVENTORY_ITEM_ID NUMBER) IS SELECT MMT.TRANSACTION_ID, MMT.TRANSACTION_TYPE_ID, MMT.ORGANIZATION_ID, MMT.INVENTORY_ITEM_ID, MMT.PRIMARY_QUANTITY TRANSACTION_QTY, MMT.TRANSACTION_DATE ORIGINAL_TRANSACTION_DATE, --決定交易是否再最後區間 CASE WHEN MMT.TRANSACTION_TYPE_ID IN (18, 44, 1350) THEN --抓取原本MMT時間 CASE WHEN MMT.TRANSACTION_TYPE_ID = 1350 AND MMT.ATTRIBUTE10 IS NOT NULL THEN TO_DATE(MMT.ATTRIBUTE10, 'YYYY-MM-DD') ELSE TRUNC(MMT.TRANSACTION_DATE) END ELSE DATE '1900-01-01' END NEW_TRANSACTION_DATE FROM MTL_MATERIAL_TRANSACTIONS MMT WHERE 1 = 1 AND MMT.INVENTORY_ITEM_ID = P_INVENTORY_ITEM_ID AND MMT.ORGANIZATION_ID = P_ORGANIZATION_ID AND TRUNC(MMT.TRANSACTION_DATE) <= TO_DATE(P_DATE, 'YYYY-MM-DD') --交易截止時間 AND MMT.PRIMARY_QUANTITY > 0 --應該只看增加的交易 AND MMT.TRANSACTION_TYPE_ID NOT IN (10008, 52) --排除 10008 銷貨成本認列 52 Salse Order Pick AND MMT.TRANSACTION_TYPE_ID NOT IN (15, 42, 43, 1326, 1328, 1336, 5536) --測試發現排除 --AND MMT.TRANSACTION_TYPE_ID NOT IN (15, 42, 43, 1328, 1336, 5536) --20230425 測試 AND MMT.TRANSACTION_ACTION_ID NOT IN (2, 24, 30) --原本程式就排除 2 倉庫移轉 24 成本更新、30 工單報廢 ORDER BY MMT.TRANSACTION_DATE DESC; P_ON_HAND_QTY NUMBER; P_TRANSACTION_QTY NUMBER; P_LAST_QUANTITY NUMBER; P_MMT_ON_HAND NUMBER; BEGIN DELETE TEMP_TABLE; P_ON_HAND_QTY := 0; P_TRANSACTION_QTY := 0; FOR C1 IN ON_HAND_INFO LOOP P_ON_HAND_QTY := C1.ON_HAND_QTY; FOR C2 IN MMT(C1.ORGANIZATION_ID, C1.INVENTORY_ITEM_ID) LOOP --假設庫存量 <= 交易量,直接取交易時間,可能第一筆直接滿足或某一筆才滿足 IF 0 < P_ON_HAND_QTY AND P_ON_HAND_QTY <= C2.TRANSACTION_QTY THEN INSERT INTO TEMP_TABLE (TRANSACTION_ID, TRANSACTION_TYPE_ID, ORGANIZATION_ID, INVENTORY_ITEM_ID, ON_HAND_QTY, TRANSACTION_QTY, ORIGINAL_TRANSACTION_DATE, NEW_TRANSACTION_DATE, CHECK_FLAG) VALUES (C2.TRANSACTION_ID, C2.TRANSACTION_TYPE_ID, C2.ORGANIZATION_ID, C2.INVENTORY_ITEM_ID, C1.ON_HAND_QTY, C2.TRANSACTION_QTY, C2.ORIGINAL_TRANSACTION_DATE, C2.NEW_TRANSACTION_DATE, NULL); P_ON_HAND_QTY := P_ON_HAND_QTY - C2.TRANSACTION_QTY; --減少庫存 --可能P_ON_HAND_QTY會被減到變成負數 IF P_ON_HAND_QTY < 0 THEN UPDATE TEMP_TABLE SET CHECK_FLAG = 'ERROR' WHERE TRANSACTION_ID = C2.TRANSACTION_ID; END IF; END IF; --假設庫存量 > 交易量,要判斷 IF P_ON_HAND_QTY > C2.TRANSACTION_QTY THEN --先把當下交易寫入 INSERT INTO TEMP_TABLE (TRANSACTION_ID, TRANSACTION_TYPE_ID, ORGANIZATION_ID, INVENTORY_ITEM_ID, ON_HAND_QTY, TRANSACTION_QTY, ORIGINAL_TRANSACTION_DATE, NEW_TRANSACTION_DATE, CHECK_FLAG) VALUES (C2.TRANSACTION_ID, C2.TRANSACTION_TYPE_ID, C2.ORGANIZATION_ID, C2.INVENTORY_ITEM_ID, C1.ON_HAND_QTY, C2.TRANSACTION_QTY, C2.ORIGINAL_TRANSACTION_DATE, C2.NEW_TRANSACTION_DATE, NULL); P_ON_HAND_QTY := P_ON_HAND_QTY - C2.TRANSACTION_QTY; --減少庫存 END IF; END LOOP; END LOOP; --特殊處理_因為排除部分交易造成 --為了程式好閱讀另外處理,並讓以後好除錯 --有庫存但是沒有交易資料可抓取 --原程式都被歸到最後一類,202303檢查都是"05B型號調整(+)"造成,代表料號PC8-02 P_COUNT := 0; FOR C1 IN ON_HAND_INFO LOOP SELECT COUNT(*) INTO P_COUNT FROM MTL_MATERIAL_TRANSACTIONS MMT WHERE 1 = 1 AND MMT.INVENTORY_ITEM_ID = C1.INVENTORY_ITEM_ID AND MMT.ORGANIZATION_ID = C1.ORGANIZATION_ID AND TRUNC(MMT.TRANSACTION_DATE) <= TO_DATE(P_DATE, 'YYYY-MM-DD') --交易截止時間 AND MMT.PRIMARY_QUANTITY > 0 --應該只看增加的交易 AND MMT.TRANSACTION_TYPE_ID NOT IN (10008, 52) --排除 10008 銷貨成本認列 52 Salse Order Pick AND MMT.TRANSACTION_TYPE_ID NOT IN (15, 42, 43, 1326, 1328, 1336, 5536) --測試發現排除 --AND MMT.TRANSACTION_TYPE_ID NOT IN (15, 42, 43, 1328, 1336, 5536) --20230425 測試 AND MMT.TRANSACTION_ACTION_ID NOT IN (2, 24, 30) --原本程式就排除 2 倉庫移轉 24 成本更新、30 工單報廢 ORDER BY MMT.TRANSACTION_DATE DESC; IF C1.ON_HAND_QTY > 0 AND P_COUNT = 0 THEN INSERT INTO TEMP_TABLE (TRANSACTION_ID, TRANSACTION_TYPE_ID, ORGANIZATION_ID, INVENTORY_ITEM_ID, ON_HAND_QTY, TRANSACTION_QTY, ORIGINAL_TRANSACTION_DATE, NEW_TRANSACTION_DATE, CHECK_FLAG) VALUES (NULL, NULL, C1.ORGANIZATION_ID, C1.INVENTORY_ITEM_ID, C1.ON_HAND_QTY, C1.ON_HAND_QTY, NULL, TO_DATE('1900-01-01', 'YYYY-MM-DD'), NULL); END IF; END LOOP; /* 調整交易數量 狀況一(需處理)、沒有CHECK_FLAG 沒有ERROR,但因排除交易,造成庫存數 <> 交易庫存數 狀況二(需處理)、ROW_COUNT = 1(交易資料只有一筆) + 庫存數與交易數不一樣 狀況三(不需處理)、ROW_COUNT = 1(交易資料只有一筆) + 庫存數與交易數一樣 狀況四(需處理)、ROW_COUNT <>1(交易資料多筆) + 庫存數與交易數不一樣 */ DECLARE CURSOR CHECK_ERROR IS SELECT DISTINCT INVENTORY_ITEM_ID FROM TEMP_TABLE WHERE CHECK_FLAG = 'ERROR'; CURSOR CHECK_NO_ERROR IS SELECT ORGANIZATION_ID, INVENTORY_ITEM_ID, ON_HAND_QTY, SUM(TRANSACTION_QTY) MMT_ON_HAND_QTY FROM TEMP_TABLE GROUP BY ORGANIZATION_ID, INVENTORY_ITEM_ID, ON_HAND_QTY; P_MMT_ROW_COUNT NUMBER; P_TRANSACTION_QTY NUMBER; BEGIN FOR C1 IN CHECK_ERROR LOOP SELECT COUNT(*) INTO P_MMT_ROW_COUNT FROM TEMP_TABLE WHERE INVENTORY_ITEM_ID = C1.INVENTORY_ITEM_ID; --處理狀況二 IF P_MMT_ROW_COUNT = 1 THEN UPDATE TEMP_TABLE A SET A.TRANSACTION_QTY = A.ON_HAND_QTY, A.CHECK_FLAG = 'OK' WHERE CHECK_FLAG = 'ERROR' AND INVENTORY_ITEM_ID = C1.INVENTORY_ITEM_ID; --處理狀況四 ELSE SELECT A.ON_HAND_QTY - SUM(A.TRANSACTION_QTY) INTO P_TRANSACTION_QTY FROM TEMP_TABLE A WHERE CHECK_FLAG IS NULL AND INVENTORY_ITEM_ID = C1.INVENTORY_ITEM_ID GROUP BY A.ON_HAND_QTY; UPDATE TEMP_TABLE A SET A.TRANSACTION_QTY = P_TRANSACTION_QTY, A.CHECK_FLAG = 'OK' WHERE CHECK_FLAG = 'ERROR' AND INVENTORY_ITEM_ID = C1.INVENTORY_ITEM_ID; END IF; END LOOP; FOR C2 IN CHECK_NO_ERROR LOOP --處理狀況一 IF C2.ON_HAND_QTY <> C2.MMT_ON_HAND_QTY THEN INSERT INTO TEMP_TABLE (TRANSACTION_ID, TRANSACTION_TYPE_ID, ORGANIZATION_ID, INVENTORY_ITEM_ID, ON_HAND_QTY, TRANSACTION_QTY, ORIGINAL_TRANSACTION_DATE, NEW_TRANSACTION_DATE, CHECK_FLAG) VALUES (NULL, NULL, C2.ORGANIZATION_ID, C2.INVENTORY_ITEM_ID, C2.ON_HAND_QTY, C2.ON_HAND_QTY - C2.MMT_ON_HAND_QTY, NULL, TO_DATE('1900-01-01', 'YYYY-MM-DD'), NULL); END IF; END LOOP; END; COMMIT; END; /* 庫齡結果 SELECT MMT.ORGANIZATION_ID, MMT.TRANSACTION_ID, MMT.INVENTORY_ITEM_ID, MSI.SEGMENT1, MMT.TRANSACTION_QTY, CASE WHEN TO_DATE('20230331', 'YYYYMMDD') - TRUNC(MMT.NEW_TRANSACTION_DATE) <= 270 THEN 'A_0_270' WHEN TO_DATE('20230331', 'YYYYMMDD') - TRUNC(MMT.NEW_TRANSACTION_DATE) BETWEEN 271 AND 365 THEN 'B_271__365' WHEN TO_DATE('20230331', 'YYYYMMDD') - TRUNC(MMT.NEW_TRANSACTION_DATE) BETWEEN 366 AND 730 THEN 'C_366_730' WHEN TO_DATE('20230331', 'YYYYMMDD') - TRUNC(MMT.NEW_TRANSACTION_DATE) BETWEEN 731 AND 1095 THEN 'D_731_1095' WHEN TO_DATE('20230331', 'YYYYMMDD') - TRUNC(MMT.NEW_TRANSACTION_DATE) BETWEEN 1096 AND 1460 THEN 'E_1096_1460' WHEN TO_DATE('20230331', 'YYYYMMDD') - TRUNC(MMT.NEW_TRANSACTION_DATE) > 1460 THEN 'F_1460UP' END STOCK_AGE FROM TEMP_TABLE MMT, MTL_SYSTEM_ITEMS_B MSI WHERE 1 = 1 AND MMT.INVENTORY_ITEM_ID = MSI.INVENTORY_ITEM_ID AND MMT.ORGANIZATION_ID = MSI.ORGANIZATION_ID --AND MMT.INVENTORY_ITEM_ID = 13040420 CREATE TABLE TEMP_TABLE ( TRANSACTION_ID NUMBER, TRANSACTION_TYPE_ID NUMBER, ORGANIZATION_ID NUMBER, INVENTORY_ITEM_ID NUMBER, ON_HAND_QTY NUMBER, TRANSACTION_QTY NUMBER, ORIGINAL_TRANSACTION_DATE DATE, NEW_TRANSACTION_DATE DATE, CHECK_FLAG VARCHAR2(10) ) */
2023-05-12
[Oracle]Stock age report
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言