EBS 中如何自定義ABC編制(ABC Compile)
(版權聲明,本人原創或者翻譯的文章如需轉載,如轉載用於個人學習,請註明出處;否則請與本人聯繫,違者必究)
ABC編制的定義過程如下
1. 通過Form來定義ABC Compile 頭。
2. 點擊Compile按鈕來提交‘Compile ABC analysis’Request來生成ABC Compile分錄並更新ABC編制頭。
3. 點擊菜單中的Print Compile來提交‘ABC descending value report’Request生成報表。
在第一步中只是定義了ABC 編制的頭,包括Criterion,和編制的範圍和計算值的範圍等信息,全部都是指定好的用來生成ABC編制分錄用的,沒有什麼可以特別自定義的。
對於第三步,它只是格式化ABC編制分錄中的數據,並利用分錄中的數據來生成報表,所以也沒什麼特別要自定義的部分。
對於第二步,往往用戶可能會有特殊的需求,比如說我只想對某一種類型的事務來統計ABC 編制,那麼就需要自定義了,但是生成ABC編制分錄的Concurrent Request是可執行文件,不好來替換啥的,但可以根據SQL TRACE文件看出其中的邏輯和使用的SQL語句,其基本原理是
1. 檢查ABC編制是不是有Assignment Group,如果有就報錯。
2. 根據不同的Criterion來執行不同的SQL來插入ABC編制分錄。
3. 對於數量爲0的物料也要插入到ABC編制分錄中。
4. 爲ABC分錄更新序列號,累積編制數量和累積編制價值。
5. 爲ABC編制頭更新物料數量,累積編制數量和累積編制價值等。
所以如果要自定義ABC編制的話,如果添加下面的第三步:
1. 通過Form來定義ABC Compile 頭。
2. 點擊Compile按鈕來提交‘Compile ABC analysis’Request來生成ABC Compile分錄並更新ABC編制頭。
3. 運行PL/SQL來刪除已有的ABC編制分錄,並根據自己的需要重新生成ABC編制分錄。
4. 點擊菜單中的Print Compile來提交‘ABC descending value report’Request生成報表。
那麼這個第三步中的PL/SQL應該要處理下面的所有事情,除了之前寫的那些事情還要刪除之前生成的分錄,基本步驟如下:
1. 檢查ABC編制是不是有Assignment Group,如果有就報錯。
2. 刪除已有的ABC編制分錄
3. 根據不同的Criterion來執行不同的SQL(已添加自己需要的條件或者調整)來插入ABC編制分錄。
4. 對於數量爲0的物料也要插入到ABC編制分錄中。
5. 爲ABC分錄更新序列號,累積編制數量和累積編制價值。
6. 爲ABC編制頭更新物料數量,累積編制數量和累積編制價值等。
下面的腳本是針對Historical usage value 的Criterion的腳本,可以指明對某一種或幾種事物類型來生成ABC編制分錄。
declare
l_abc_compile_id number :=&compile_id;
l_abc_group_count number :=0;
l_item_scope number :=0;
l_compile_type number :=0;
l_sec_inventory VARCHAR2(20);
l_org_id number;
l_start_date date;
l_end_date date;
l_compile_value number :=0;
l_compile_qty number:=0;
l_compile_rowid VARCHAR2(50);
l_cumulative_compile_value number :=0;
l_cumulative_compile_qty number :=0;
l_seq number :=0;
l_last_update_by number :=-1;
l_last_login number :=-1;
l_transaction_type_id number :=&transaction_type_id;
CURSOR updateSeq IS
SELECT ANAL.COMPILE_VALUE,
ANAL.COMPILE_QUANTITY,
ANAL.ROWID
FROM MTL_SYSTEM_ITEMS ITEM,
MTL_ABC_COMPILES ANAL
WHERE ANAL.ORGANIZATION_ID = l_org_id
AND ANAL.COMPILE_ID = l_abc_compile_id
AND ITEM.ORGANIZATION_ID = l_org_id
AND ANAL.INVENTORY_ITEM_ID = ITEM.INVENTORY_ITEM_ID
ORDER BY ANAL.COMPILE_VALUE DESC,
ITEM.SEGMENT1 ASC,
ITEM.SEGMENT2 ASC,
ITEM.SEGMENT3 ASC
FOR UPDATE OF ANAL.SEQUENCE_NUMBER,
ANAL.CUMULATIVE_VALUE,
ANAL.CUMULATIVE_QUANTITY;
begin
select count(1)
into l_abc_group_count
from MTL_ABC_ASSIGNMENT_GROUPS
where compile_id=l_abc_compile_id;
if l_abc_group_count = 0 then
delete MTL_ABC_COMPILES
where compile_id = l_abc_compile_id;
dbms_output.put_line('delete MTL_ABC_COMPILES successfully');
SELECT compile_type,item_scope_code, SECONDARY_INVENTORY,organization_id,start_date,cutoff_date,LAST_UPDATED_BY, -1
into l_compile_type, l_item_scope, l_sec_inventory, l_org_id, l_start_date, l_end_date, l_last_update_by,l_last_login
FROM MTL_ABC_COMPILE_HEADERS mach
WHERE compile_id = l_abc_compile_id;
dbms_output.put_line('compile_type:'||l_compile_type||',l_item_scope:'||l_item_scope||',l_sec_inventory:'||l_sec_inventory||',COMPILE_ID:'||l_abc_compile_id||',ORGANIZATION_ID:'||l_org_id);
if l_compile_type = 3 then
IF l_item_scope = 1 THEN
IF l_sec_inventory IS NULL THEN
INSERT INTO MTL_ABC_COMPILES (
COMPILE_ID,
INVENTORY_TYPE,
ORGANIZATION_ID,
INVENTORY_ITEM_ID,
SEQUENCE_NUMBER,
CREATION_DATE,
CREATED_BY,
LAST_UPDATE_DATE,
LAST_UPDATED_BY,
LAST_UPDATE_LOGIN,
COMPILE_QUANTITY,
COMPILE_VALUE)
SELECT
l_abc_compile_id,
'1',
l_org_id,
INVENTORY_ITEM_ID,
'0',
SYSDATE,
l_last_update_by,
SYSDATE,
l_last_update_by,
l_last_login,
SUM(ABS(PRIMARY_QUANTITY)),
SUM(ABS(NVL(PRIMARY_QUANTITY,0))*NVL(ACTUAL_COST,0) )
FROM MTL_MATERIAL_TRANSACTIONS
WHERE TRANSACTION_TYPE_ID <> 90
AND TRANSACTION_TYPE_ID = l_transaction_type_id
AND TRANSACTION_ACTION_ID <> 24
AND INVENTORY_ITEM_ID <> -1
AND ORGANIZATION_ID = l_org_id
AND transaction_date >= l_start_date
AND transaction_date <= l_end_date
GROUP BY INVENTORY_ITEM_ID;
--load zero item
INSERT INTO MTL_ABC_COMPILES
( INVENTORY_ITEM_ID,
ORGANIZATION_ID,
INVENTORY_TYPE,
COMPILE_ID,
LAST_UPDATE_DATE, LAST_UPDATED_BY, LAST_UPDATE_LOGIN,
CREATION_DATE, CREATED_BY,
COMPILE_QUANTITY,
COMPILE_VALUE )
SELECT
/*+ INDEX(ITEM MTL_SYSTEM_ITEMS_U1) */
INVENTORY_ITEM_ID,
l_org_id,
1,
l_abc_compile_id,
SYSDATE,
l_last_update_by,
l_last_login,
SYSDATE,
l_last_update_by,
0,
0
FROM MTL_SYSTEM_ITEMS ITEM
WHERE ITEM.ORGANIZATION_ID = l_org_id
AND ITEM.STOCK_ENABLED_FLAG = 'Y'
AND NOT EXISTS
( SELECT 'X'
FROM MTL_ABC_COMPILES
WHERE INVENTORY_ITEM_ID = ITEM.INVENTORY_ITEM_ID
AND ORGANIZATION_ID = l_org_id
AND COMPILE_ID = l_abc_compile_id );
ELSE
INSERT INTO MTL_ABC_COMPILES (
COMPILE_ID,
INVENTORY_TYPE,
ORGANIZATION_ID,
INVENTORY_ITEM_ID,
SEQUENCE_NUMBER,
CREATION_DATE,
CREATED_BY,
LAST_UPDATE_DATE,
LAST_UPDATED_BY,
LAST_UPDATE_LOGIN,
COMPILE_QUANTITY,
COMPILE_VALUE)
SELECT
l_abc_compile_id,
'1',
l_org_id,
INVENTORY_ITEM_ID,
'0',
SYSDATE,
l_last_update_by,
SYSDATE,
l_last_update_by,
l_last_login,
SUM(ABS(PRIMARY_QUANTITY)),
SUM(ABS(NVL(PRIMARY_QUANTITY,0))*NVL(ACTUAL_COST,0) )
FROM MTL_MATERIAL_TRANSACTIONS
WHERE TRANSACTION_TYPE_ID <> 90
AND TRANSACTION_TYPE_ID = l_transaction_type_id
AND TRANSACTION_ACTION_ID <> 24
AND INVENTORY_ITEM_ID <> -1
AND ORGANIZATION_ID = l_org_id
AND transaction_date >= l_start_date
AND transaction_date <= l_end_date
AND INVENTORY_ITEM_ID IN ( SELECT SUB.INVENTORY_ITEM_ID
FROM MTL_ITEM_SUB_INVENTORIES SUB
WHERE SUB.ORGANIZATION_ID = l_org_id
AND SUB.SECONDARY_INVENTORY =l_sec_inventory)
GROUP BY INVENTORY_ITEM_ID;
--load zero item
INSERT INTO MTL_ABC_COMPILES
( ORGANIZATION_ID,
INVENTORY_ITEM_ID,
INVENTORY_TYPE,
COMPILE_ID,
LAST_UPDATE_DATE, LAST_UPDATED_BY, LAST_UPDATE_LOGIN,
CREATION_DATE, CREATED_BY,
COMPILE_QUANTITY,
COMPILE_VALUE )
SELECT
/*+ INDEX(SUB MTL_ITEM_SUB_INVENTORIES_U2) INDEX(ITEM MTL_SYSTEM_ITEMS_U1) */
l_org_id,
ITEM.INVENTORY_ITEM_ID,
1,
l_abc_compile_id,
SYSDATE,
l_last_update_by,
l_last_login,
SYSDATE,
l_last_update_by,
0,
0
FROM MTL_SYSTEM_ITEMS ITEM,
MTL_ITEM_SUB_INVENTORIES SUB
WHERE ITEM.ORGANIZATION_ID = l_org_id
AND SUB.ORGANIZATION_ID = l_org_id
AND ITEM.INVENTORY_ITEM_ID = SUB.INVENTORY_ITEM_ID
AND SUB.SECONDARY_INVENTORY = l_sec_inventory
AND ITEM.STOCK_ENABLED_FLAG = 'Y'
AND NOT EXISTS
( SELECT 'X'
FROM MTL_ABC_COMPILES ABC
WHERE ABC.INVENTORY_ITEM_ID = ITEM.INVENTORY_ITEM_ID
AND ABC.ORGANIZATION_ID = l_org_id
AND ABC.COMPILE_ID = l_abc_compile_id )
GROUP BY ITEM.ORGANIZATION_ID, ITEM.INVENTORY_ITEM_ID;
END IF;
ELSE
INSERT INTO MTL_ABC_COMPILES (
COMPILE_ID,
INVENTORY_TYPE,
ORGANIZATION_ID,
INVENTORY_ITEM_ID,
SEQUENCE_NUMBER,
CREATION_DATE,
CREATED_BY,
LAST_UPDATE_DATE,
LAST_UPDATED_BY,
LAST_UPDATE_LOGIN,
COMPILE_QUANTITY,
COMPILE_VALUE)
SELECT
l_abc_compile_id,
'1',
l_org_id,
INVENTORY_ITEM_ID,
'0',
SYSDATE,
l_last_update_by,
SYSDATE,
l_last_update_by,
l_last_login,
SUM(ABS(PRIMARY_QUANTITY)),
SUM(ABS(NVL(PRIMARY_QUANTITY,0))*NVL(ACTUAL_COST,0) )
FROM MTL_MATERIAL_TRANSACTIONS
WHERE TRANSACTION_TYPE_ID <> 90
AND TRANSACTION_TYPE_ID = l_transaction_type_id
AND TRANSACTION_ACTION_ID <> 24
AND INVENTORY_ITEM_ID <> -1
AND ORGANIZATION_ID = l_org_id
AND transaction_date >= l_start_date
AND transaction_date <= l_end_date
AND SUBINVENTORY_CODE = l_sec_inventory
GROUP BY INVENTORY_ITEM_ID;
--load zero qty
INSERT INTO MTL_ABC_COMPILES
( ORGANIZATION_ID,
INVENTORY_ITEM_ID,
INVENTORY_TYPE,
COMPILE_ID,
LAST_UPDATE_DATE, LAST_UPDATED_BY, LAST_UPDATE_LOGIN,
CREATION_DATE, CREATED_BY,
COMPILE_QUANTITY,
COMPILE_VALUE )
SELECT
/*+ INDEX(SUB MTL_ITEM_SUB_INVENTORIES_U2) INDEX(ITEM MTL_SYSTEM_ITEMS_U1) */
l_org_id,
ITEM.INVENTORY_ITEM_ID,
1,
l_abc_compile_id,
SYSDATE,
l_last_update_by,
l_last_login,
SYSDATE,
l_last_update_by,
0,
0
FROM MTL_SYSTEM_ITEMS ITEM,
MTL_ITEM_SUB_INVENTORIES SUB
WHERE ITEM.ORGANIZATION_ID = l_org_id
AND SUB.ORGANIZATION_ID = l_org_id
AND ITEM.INVENTORY_ITEM_ID = SUB.INVENTORY_ITEM_ID
AND SUB.SECONDARY_INVENTORY = l_sec_inventory
AND ITEM.STOCK_ENABLED_FLAG = 'Y'
AND NOT EXISTS
( SELECT 'X'
FROM MTL_ABC_COMPILES ABC
WHERE ABC.INVENTORY_ITEM_ID = ITEM.INVENTORY_ITEM_ID
AND ABC.ORGANIZATION_ID = l_org_id
AND ABC.COMPILE_ID = l_abc_compile_id );
END IF;
--load seq number;
open updateSeq;
Loop
fetch updateSeq into l_compile_value, l_compile_qty , l_compile_rowid;
exit when updateSeq%notfound;
l_seq :=l_seq +1;
l_cumulative_compile_value :=l_cumulative_compile_value+l_compile_value;
l_cumulative_compile_qty :=l_cumulative_compile_qty + l_compile_qty;
UPDATE MTL_ABC_COMPILES
SET SEQUENCE_NUMBER = l_seq,
CUMULATIVE_VALUE = l_cumulative_compile_value,
CUMULATIVE_QUANTITY = l_cumulative_compile_qty
WHERE ROWID = l_compile_rowid;
end loop;
close updateSeq;
--update compile header
UPDATE MTL_ABC_COMPILE_HEADERS
SET COMPILE_ITEMS =
( SELECT COUNT(*)
FROM MTL_ABC_COMPILES
WHERE COMPILE_ID = l_abc_compile_id
AND ORGANIZATION_ID = l_org_id ),
CUMULATIVE_VALUE =
( SELECT SUM (COMPILE_VALUE)
FROM MTL_ABC_COMPILES
WHERE COMPILE_ID = l_abc_compile_id
AND ORGANIZATION_ID = l_org_id ),
CUMULATIVE_QUANTITY =
( SELECT SUM (COMPILE_QUANTITY)
FROM MTL_ABC_COMPILES
WHERE COMPILE_ID = l_abc_compile_id
AND ORGANIZATION_ID = l_org_id ),
LAST_UPDATE_DATE = SYSDATE,
LAST_UPDATED_BY = l_last_update_by,
COMPILE_DATE = SYSDATE
WHERE COMPILE_ID = l_abc_compile_id
AND ORGANIZATION_ID = l_org_id;
else
dbms_output.put_line('incorrect compile type');
end if;
else
dbms_output.put_line('there is abc group assignment');
end if;
end;
示例如下
1. ABC編制頭定義如下
2. 點擊Compile這個時候的ABC編制頭如下
3. 點擊Print Compile生成的‘ABC descending value report’報表如下
4. 運行腳本並指定事物類型爲,更新後的ABC編制頭如下
5. 重新生成的‘ABC descending valuereport’報表如下