DECLARE
PROCEDURE create_move_order
IS
l_hdr_rec inv_move_order_pub.trohdr_rec_type := inv_move_order_pub.g_miss_trohdr_rec;
l_line_tbl inv_move_order_pub.trolin_tbl_type := inv_move_order_pub.g_miss_trolin_tbl;
x_return_status VARCHAR2 (1);
x_msg_count NUMBER;
x_msg_data VARCHAR2 (4000);
x_hdr_rec inv_move_order_pub.trohdr_rec_type := inv_move_order_pub.g_miss_trohdr_rec;
x_hdr_val_rec inv_move_order_pub.trohdr_val_rec_type;
x_line_tbl inv_move_order_pub.trolin_tbl_type;
x_line_val_tbl inv_move_order_pub.trolin_val_tbl_type;
v_msg_index_out NUMBER;
l_rsr_type inv_reservation_global.mtl_reservation_tbl_type;
BEGIN
l_line_tbl.DELETE;
x_line_tbl.DELETE;
mo_global.set_policy_context (‘S’, 204);
inv_globals.set_org_id (207);
fnd_global.apps_initialize (1005902, 50583, 401);
l_hdr_rec.date_required := SYSDATE;
l_hdr_rec.header_status := inv_globals.g_to_status_preapproved;
l_hdr_rec.organization_id := 207;
l_hdr_rec.status_date := SYSDATE;
l_hdr_rec.transaction_type_id := inv_globals.g_type_transfer_order_issue;
l_hdr_rec.move_order_type := inv_globals.g_move_order_requisition;
l_hdr_rec.db_flag := fnd_api.g_true;
l_hdr_rec.operation := inv_globals.g_opr_create;
l_hdr_rec.description := ‘Test Move Order’;
l_hdr_rec.to_account_id := 12831;
l_hdr_rec.from_subinventory_code := ‘FGI’;
l_line_tbl (1).date_required := SYSDATE;
l_line_tbl (1).inventory_item_id := 167742;
l_line_tbl (1).line_id := fnd_api.g_miss_num;
l_line_tbl (1).line_number := 1;
l_line_tbl (1).line_status := inv_globals.g_to_status_preapproved;
l_line_tbl (1).transaction_type_id := inv_globals.g_type_transfer_order_issue;
l_line_tbl (1).organization_id := 207;
l_line_tbl (1).quantity := 1;
l_line_tbl (1).status_date := SYSDATE;
l_line_tbl (1).uom_code := ‘Ea’;
l_line_tbl (1).db_flag := fnd_api.g_true;
l_line_tbl (1).operation := inv_globals.g_opr_create;
l_line_tbl (1).from_subinventory_code := ‘FGI’;
l_line_tbl (1).to_account_id := 12831;
l_line_tbl (1).lot_number := ‘A01’; –If the item is lot controlled
l_line_tbl (1).serial_number_start := ‘A01-0031’; –If the item is serial number controlled
l_line_tbl (1).serial_number_end := ‘A01-0031’; –If the item is serial number controlled
inv_move_order_pub.process_move_order (p_api_version_number => 1.0
, p_init_msg_list => fnd_api.g_false
, p_return_values => fnd_api.g_false
, p_commit => fnd_api.g_false
, x_return_status => x_return_status
, x_msg_count => x_msg_count
, x_msg_data => x_msg_data
, p_trohdr_rec => l_hdr_rec
, p_trolin_tbl => l_line_tbl
, x_trohdr_rec => x_hdr_rec
, x_trohdr_val_rec => x_hdr_val_rec
, x_trolin_tbl => x_line_tbl
, x_trolin_val_tbl => x_line_val_tbl
);
DBMS_OUTPUT.put_line (‘Return Status is :’ || x_return_status);
DBMS_OUTPUT.put_line (‘Message Count is :’ || x_msg_count);
DBMS_OUTPUT.put_line (‘Move Order Number is :’ || x_hdr_rec.request_number);
DBMS_OUTPUT.put_line (‘Number of Lines Created are :’ || x_line_tbl.COUNT);
IF x_return_status = ‘S’
THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
IF x_msg_count > 0
THEN
FOR v_index IN 1 .. x_msg_count
LOOP
fnd_msg_pub.get (p_msg_index => v_index, p_encoded => ‘F’, p_data => x_msg_data, p_msg_index_out => v_msg_index_out);
x_msg_data := SUBSTR (x_msg_data, 1, 200);
DBMS_OUTPUT.put_line (x_msg_data);
DBMS_OUTPUT.put_line (‘============================================================’);
END LOOP;
END IF;
END;
BEGIN
create_move_order;
END;
Oracle R12 Allocate Order using APIs
x_return_status VARCHAR2 (1);
x_msg_data VARCHAR2 (4000);
x_msg_count NUMBER;
l_line_tbl inv_move_order_pub.trolin_tbl_type;
PROCEDURE allocate_move_order (
p_line_tbl IN inv_move_order_pub.trolin_tbl_type
, x_return_status OUT VARCHAR2
, x_msg_data OUT VARCHAR2
, x_msg_count OUT NUMBER
)
IS
x_line_tbl inv_move_order_pub.trolin_tbl_type;
l_trolin_tbl inv_move_order_pub.trolin_tbl_type;
l_mold_tbl inv_mo_line_detail_util.g_mmtt_tbl_type;
l_qty_detailed NUMBER;
l_qty_delivered NUMBER;
l_return_status VARCHAR2 (1);
v_msg_index_out NUMBER;
l_rsr_type inv_reservation_global.mtl_reservation_tbl_type;
i INTEGER;
l_trolin_rec inv_move_order_pub.trolin_rec_type;
BEGIN
x_line_tbl := p_line_tbl;
IF x_line_tbl.COUNT > 0
THEN
FOR j IN x_line_tbl.FIRST .. x_line_tbl.LAST
LOOP
DBMS_OUTPUT.put_line (x_line_tbl (j).line_id);
BEGIN
inv_ppengine_pvt.create_suggestions (p_api_version => 1.0
, p_init_msg_list => fnd_api.g_false
, p_commit => fnd_api.g_false
, p_validation_level => fnd_api.g_valid_level_none
, x_return_status => x_return_status
, x_msg_count => x_msg_count
, x_msg_data => x_msg_data
, p_transaction_temp_id => x_line_tbl (j).line_id
, p_reservations => l_rsr_type
, p_suggest_serial => fnd_api.g_true
, p_plan_tasks => FALSE
, p_quick_pick_flag => ‘N’
, p_organization_id => 207
);
DBMS_OUTPUT.put_line (‘Return Status is :’ || x_return_status);
DBMS_OUTPUT.put_line (‘Message Count is :’ || x_msg_count);
IF x_return_status = ‘S’
THEN
BEGIN
l_trolin_tbl := x_line_tbl;
IF (l_trolin_tbl.COUNT <> 0)
THEN
i := l_trolin_tbl.FIRST;
WHILE i IS NOT NULL
LOOP
IF ( l_trolin_tbl (i).return_status <> fnd_api.g_ret_sts_unexp_error
AND l_trolin_tbl (i).return_status <> fnd_api.g_ret_sts_error
)
THEN
l_trolin_rec := inv_trolin_util.query_row (l_trolin_tbl (i).line_id);
l_trolin_tbl (i) := l_trolin_rec;
l_qty_detailed := l_trolin_tbl (i).quantity_detailed;
l_qty_delivered := NVL (l_trolin_tbl (i).quantity_delivered, 0);
IF NVL (l_qty_detailed, 0) = 0
THEN
l_mold_tbl := inv_mo_line_detail_util.query_rows (p_line_id => l_trolin_tbl (i).line_id);
FOR j IN 1 .. l_mold_tbl.COUNT
LOOP
l_mold_tbl (j).transaction_status := 3;
l_mold_tbl (j).transaction_mode := 1;
l_mold_tbl (j).source_line_id := l_trolin_tbl (i).line_id;
inv_mo_line_detail_util.update_row (l_return_status, l_mold_tbl (j));
END LOOP;
SELECT transaction_header_id, transaction_quantity
INTO l_trolin_tbl (i).transaction_header_id, l_trolin_tbl (i).quantity_detailed
FROM mtl_material_transactions_temp
WHERE move_order_line_id = l_trolin_tbl (i).line_id;
l_trolin_tbl (i).last_update_date := SYSDATE;
l_trolin_tbl (i).last_update_login := fnd_global.login_id;
IF l_trolin_tbl (i).last_update_login = -1
THEN
l_trolin_tbl (i).last_update_login := fnd_global.conc_login_id;
END IF;
l_trolin_tbl (i).last_updated_by := fnd_global.user_id;
l_trolin_tbl (i).program_id := fnd_global.conc_program_id;
l_trolin_tbl (i).program_update_date := SYSDATE;
l_trolin_tbl (i).request_id := fnd_global.conc_request_id;
l_trolin_tbl (i).program_application_id := fnd_global.prog_appl_id;
inv_trolin_util.update_row (l_trolin_tbl (i));
END IF;
END IF;
i := l_trolin_tbl.NEXT (i);
END LOOP;
END IF;
END;
ELSE
ROLLBACK;
END IF;
IF x_msg_count > 0
THEN
FOR v_index IN 1 .. x_msg_count
LOOP
fnd_msg_pub.get (p_msg_index => v_index
, p_encoded => ‘F’
, p_data => x_msg_data
, p_msg_index_out => v_msg_index_out
);
x_msg_data := SUBSTR (x_msg_data, 1, 200);
DBMS_OUTPUT.put_line (x_msg_data);
DBMS_OUTPUT.put_line (‘============================================================’);
END LOOP;
END IF;
END;
END LOOP;
END IF;
END;
BEGIN
l_line_tbl (1).line_id := 3929705;
allocate_move_order (l_line_tbl, x_return_status, x_msg_data, x_msg_count);
COMMIT;
END;
Share this:
Oracle R12 Create Order using APIs
PROCEDURE create_move_order
IS
l_hdr_rec inv_move_order_pub.trohdr_rec_type := inv_move_order_pub.g_miss_trohdr_rec;
l_line_tbl inv_move_order_pub.trolin_tbl_type := inv_move_order_pub.g_miss_trolin_tbl;
x_return_status VARCHAR2 (1);
x_msg_count NUMBER;
x_msg_data VARCHAR2 (4000);
x_hdr_rec inv_move_order_pub.trohdr_rec_type := inv_move_order_pub.g_miss_trohdr_rec;
x_hdr_val_rec inv_move_order_pub.trohdr_val_rec_type;
x_line_tbl inv_move_order_pub.trolin_tbl_type;
x_line_val_tbl inv_move_order_pub.trolin_val_tbl_type;
v_msg_index_out NUMBER;
l_rsr_type inv_reservation_global.mtl_reservation_tbl_type;
BEGIN
l_line_tbl.DELETE;
x_line_tbl.DELETE;
mo_global.set_policy_context (‘S’, 204);
inv_globals.set_org_id (207);
fnd_global.apps_initialize (1005902, 50583, 401);
l_hdr_rec.date_required := SYSDATE;
l_hdr_rec.header_status := inv_globals.g_to_status_preapproved;
l_hdr_rec.organization_id := 207;
l_hdr_rec.status_date := SYSDATE;
l_hdr_rec.transaction_type_id := inv_globals.g_type_transfer_order_issue;
l_hdr_rec.move_order_type := inv_globals.g_move_order_requisition;
l_hdr_rec.db_flag := fnd_api.g_true;
l_hdr_rec.operation := inv_globals.g_opr_create;
l_hdr_rec.description := ‘Test Move Order’;
l_hdr_rec.to_account_id := 12831;
l_hdr_rec.from_subinventory_code := ‘FGI’;
l_line_tbl (1).date_required := SYSDATE;
l_line_tbl (1).inventory_item_id := 167742;
l_line_tbl (1).line_id := fnd_api.g_miss_num;
l_line_tbl (1).line_number := 1;
l_line_tbl (1).line_status := inv_globals.g_to_status_preapproved;
l_line_tbl (1).transaction_type_id := inv_globals.g_type_transfer_order_issue;
l_line_tbl (1).organization_id := 207;
l_line_tbl (1).quantity := 1;
l_line_tbl (1).status_date := SYSDATE;
l_line_tbl (1).uom_code := ‘Ea’;
l_line_tbl (1).db_flag := fnd_api.g_true;
l_line_tbl (1).operation := inv_globals.g_opr_create;
l_line_tbl (1).from_subinventory_code := ‘FGI’;
l_line_tbl (1).to_account_id := 12831;
l_line_tbl (1).lot_number := ‘A01’; –If the item is lot controlled
l_line_tbl (1).serial_number_start := ‘A01-0031’; –If the item is serial number controlled
l_line_tbl (1).serial_number_end := ‘A01-0031’; –If the item is serial number controlled
inv_move_order_pub.process_move_order (p_api_version_number => 1.0
, p_init_msg_list => fnd_api.g_false
, p_return_values => fnd_api.g_false
, p_commit => fnd_api.g_false
, x_return_status => x_return_status
, x_msg_count => x_msg_count
, x_msg_data => x_msg_data
, p_trohdr_rec => l_hdr_rec
, p_trolin_tbl => l_line_tbl
, x_trohdr_rec => x_hdr_rec
, x_trohdr_val_rec => x_hdr_val_rec
, x_trolin_tbl => x_line_tbl
, x_trolin_val_tbl => x_line_val_tbl
);
DBMS_OUTPUT.put_line (‘Return Status is :’ || x_return_status);
DBMS_OUTPUT.put_line (‘Message Count is :’ || x_msg_count);
DBMS_OUTPUT.put_line (‘Move Order Number is :’ || x_hdr_rec.request_number);
DBMS_OUTPUT.put_line (‘Number of Lines Created are :’ || x_line_tbl.COUNT);
IF x_return_status = ‘S’
THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
IF x_msg_count > 0
THEN
FOR v_index IN 1 .. x_msg_count
LOOP
fnd_msg_pub.get (p_msg_index => v_index, p_encoded => ‘F’, p_data => x_msg_data, p_msg_index_out => v_msg_index_out);
x_msg_data := SUBSTR (x_msg_data, 1, 200);
DBMS_OUTPUT.put_line (x_msg_data);
DBMS_OUTPUT.put_line (‘============================================================’);
END LOOP;
END IF;
END;
BEGIN
create_move_order;
END;
Share this:
R12: Create, Allocate and Transact a Move Order using APIs
Move Orders can be created from different sources. These move orders are identified by Move order type at the header level.
Different types of move orders are:
Move Order Requisitions: These are created from the move order form. Based on the setup at the organization and item level, move orders require approval before they can be allocated and transacted. These requisitions can be created to charge an account or move the material from one subinventory to another.
Replenishment Move Orders: These are auto-created with pre approved status. Depending on the planning type you can replenish the quantity in a subinventory for an item. Three types of replenishment plans (in relation to move orders) are available:
Based on these sources, when appropriate programs are run, move orders are automatically created.
Pick Wave Move Order Requisitions: These move orders are specifically for the sales order picking process. When Pick Releasing program is run move orders are created as preapproved and allocated. Pick Confirm process transacts these pick wave move orders.
Move orders contain headers and lines. All types of approved move orders have to be allocated (basically reserved) before they can be transacted. Depending on the item transaction controls (Subinventory, Locator, Revision, Lot or Serial number) move order creation and allocation gets complex.
The process is simple. Create and approve Move orders, allocate move order lines and transact them.
In this article let us review creating, allocating, and transacting a move order requisition of first type (requisitions) using APIs. These move orders will be created in pre approved status and hence do not use workflow. Move Order Issue transaction type is used in this example. An account is chosen while creating this move order. When successfully transacted, this account gets debited, crediting inventory account of the subinventory. From the user interface, to create Move orders, Move Orders window is used.
The lines are allocated when allocation step is performed. In this example the logic for allocation and transaction is borrowed from pick confirmation code. To allocate and transact same form is used: Transact Move Orders.
If the item is lot and serial number controlled (as in this example), you have to pass the lot number and serial number information into the move order lines table parameter. And also make sure to pass another parameter (p_suggess_serial) as true. This will automatically take care of allocating the lot and serial numbers into the appropriate table as mentioned in the process flow. Also when we allocate the move order from the user interface, the records in the form are created in the mtl_material_transactions_temp table with transaction_status as 2, which allows the user to change the values from user interface. But in order to perform transaction from SQL, you have to change this value to 3 so that the transaction manager can pick these records up. You find that logic in the allocating code.
The tables affected in each process step are mentioned in the process flow. Code for each step as well as complete code to create, allocate and transact can be see here:
Oracle R12 Create Order using APIs
Oracle R12 Allocate Order using APIs
Oracle R12 Transact Order using APIs
Oracle R12 Move Order using APIs
Share this:
What are Business Events in Oracle Apps?
Business events in workflow are no different from the above scenario. As the human actions that flow from one department to another, workflow also passes the message from source to destination so that information can be processed in the supply chain. Also business events can be raised and read accross applications and systems.
From technical point of view, just like a department which ”performs” the action that should be communicated, there is a source that “raises” the event. This event when raised is “queued” into an “agent”. Then there is an “agent listener” this picks up the queue from this agent processes it or “dequeues” it. While dequeueing, the “agent listener” processes the rule function that is attached as a ”subscription” using the information that contained in the queue message (“parameters”).
Take an example. Say a new employee joined your company. The day she reports to work, you generate an employee record for her. Say,once she is assinged an employee number, you have to communicate to payroll and systems departments (among others). This information either can be an email to both the departments or inter-office memo for each department. This memo will be picked by mail department and delivered. Once this mail is received, payroll and systems divisions use this information like employee number to complete their own work.
So if you extend this example to business events in wokflow, HR Department raises this event (creation of employee). This event will have a message to be delivered (parameters). This message will be picked up by mail department and delivered (Agent). Once delviered, respective departments receive this information (listened to the queue). This message will be delivered to an appropriate person in the department (subscriber) who will process this information (executing code or kicking a workflow off).
Nailing this down to simple diagram in technical terms, this is how it looks.
There are can be two kinds of subscriptions: Deferred or Immediate. Deferred subscriptions are those that are queued and to be processed by listener. The above example is of that kind. HR deferred the work to be processed by Payroll. On the other hand there are chances that the HR and Payroll handled by the same person. In that case there is nothing to be deferred. This is synchronous process and both the functions are performed in the same department (no need of mail delivery) or by the same person.
And subscribers can process the information in two different ways: either kick off a workflow or execute pl/sql package or java class. If the rule function controls this. Also based on the rule function (workflow vs pl/sql of Java function) appropriate queue is used. If it is pl/sql WF_DEFERRED is used and if it is Java then WF_JAVA_DEFERRED is used.
Share this:
What is under one item type in workflow?
set serveroutput on;
DECLARE
l number;
m number;
l_item_type varchar2(30) :=’OEOL’;
l_std_type varchar2(30) :=’WFSTD’;
CURSOR c1 (p_item_type IN VARCHAR2)
IS
SELECT display_name,NAME
FROM wf_item_types_tl
WHERE NAME = p_item_type;
CURSOR c2 (p_item_type IN VARCHAR2)
IS
SELECT *
FROM wf_runnable_processes_v
WHERE item_type = p_item_type;
CURSOR c3 (p_item_type IN VARCHAR2, p_process_name IN VARCHAR2,p_std_type in varchar2)
IS
SELECT a.process_name, e.description, b.NAME activity_name,
d.description act_desc, c.TYPE process_type, b.TYPE activity_type,
b.FUNCTION, substr(icon_geometry,1,(instr(a.icon_geometry,’,’)-1))
FROM wf_process_activities a,
wf_activities b,
wf_activities c,
wf_activities_tl d,
wf_activities_tl e
WHERE process_item_type=p_item_type
–and activity_item_type in (p_item_type,p_std_type)
AND process_name = p_process_name
AND a.activity_name = b.NAME
AND process_item_type = b.item_type
AND b.end_date IS NULL
AND c.end_date IS NULL
AND a.process_name = c.NAME
AND c.item_type = a.process_item_type
AND a.process_version = c.VERSION
AND b.item_type = d.item_type
AND b.NAME = d.NAME
AND c.item_type = e.item_type
AND c.NAME = e.NAME
AND b.VERSION = d.VERSION
AND c.VERSION = e.VERSION
ORDER BY to_number(substr(a.icon_geometry,1,(instr(a.icon_geometry,’,’)-1)));
CURSOR c4 (p_item_type IN VARCHAR2, p_process_name IN VARCHAR2,p_std_type in varchar2)
IS
SELECT a.process_name, e.description, b.NAME activity_name,
d.description act_desc, c.TYPE process_type, b.TYPE activity_type,
b.FUNCTION, substr(icon_geometry,1,(instr(a.icon_geometry,’,’)-1))
FROM wf_process_activities a,
wf_activities b,
wf_activities c,
wf_activities_tl d,
wf_activities_tl e
WHERE process_item_type=p_item_type
–and activity_item_type in (p_item_type,p_std_type)
AND process_name = p_process_name
AND a.activity_name = b.NAME
AND process_item_type = b.item_type
AND b.end_date IS NULL
AND c.end_date IS NULL
AND a.process_name = c.NAME
AND c.item_type = a.process_item_type
AND a.process_version = c.VERSION
AND b.item_type = d.item_type
AND b.NAME = d.NAME
AND c.item_type = e.item_type
AND c.NAME = e.NAME
AND b.VERSION = d.VERSION
AND c.VERSION = e.VERSION
ORDER BY to_number(substr(a.icon_geometry,1,(instr(a.icon_geometry,’,’)-1)));
assertion_failure EXCEPTION;
PROCEDURE pl (
str IN VARCHAR2,
len IN INTEGER := 80,
expand_in IN BOOLEAN := TRUE
)
IS
v_len PLS_INTEGER := LEAST (len, 255);
v_str VARCHAR2 (2000);
BEGIN
IF LENGTH (str) > v_len
THEN
v_str := SUBSTR (str, 1, v_len);
DBMS_OUTPUT.put_line (v_str);
pl (SUBSTR (str, len + 1), v_len, expand_in);
ELSE
v_str := str;
DBMS_OUTPUT.put_line (v_str);
END IF;
EXCEPTION
WHEN OTHERS
THEN
IF expand_in
THEN
DBMS_OUTPUT.ENABLE (1000000);
DBMS_OUTPUT.put_line (v_str);
ELSE
RAISE;
END IF;
END pl;
BEGIN
l:=1;
m:=1;
FOR i IN c1 (l_item_type)
LOOP
pl(‘===========================================================’);
pl(‘ITEM TYPE : ‘||i.display_name);
pl(‘===========================================================’);
FOR j IN c2 (i.name)
LOOP
pl(‘———————————————————‘);
pl(‘MAIN RUNNABLE PROCESS : ‘ ||j.display_name);
pl(‘———————————————————‘);
l:=1;
FOR k IN c3 (l_item_type, j.process_name,l_std_type)
LOOP
pl(‘—‘||l||’.’||k.act_desc||’-‘||k.function);
IF k.process_type = ‘PROCESS’
THEN
m:=1;
FOR j IN c4 (l_item_type, k.activity_name,l_std_type)
LOOP
PL(‘—-‘||l||’.’||m||’:’||j.act_desc);
m:=m+1;
END LOOP;
END IF;
l:=l+1;
END LOOP;
END LOOP;
END LOOP;
END;
Share this: