I created this procedure
CREATE OR REPLACE PROCEDURE APPS.test_dlv3
IS
BEGIN
DECLARE
-- STANDARD PARAMETERS.
pApiVersion NUMBER := 1.0;
pInitMsgList VARCHAR2(30);
pCommit VARCHAR2(30);
-- PARAMETERS FOR WSH_DELIVERY_DETAILS_PUB.DETAIL_TO_DELIVERY
pDeliveryId NUMBER;
pDeliveryName VARCHAR2(30);
pTabOfDelDet WSH_DELIVERY_DETAILS_PUB.id_tab_type;
pAction VARCHAR2(30);
-- OUT PARAMETERS
xReturnStatus VARCHAR2(10);
xMsgCount NUMBER;
xMsgData VARCHAR2(2000);
xMsgDetails VARCHAR2(3000);
xMsgSummary VARCHAR2(3000);
-- HANDLE EXCEPTIONS
vFailApiException EXCEPTION;
BEGIN
-- INITIALIZE RETURN STATUS
xReturnStatus := WSH_UTIL_CORE.G_RET_STS_SUCCESS;
-- CALL THIS PROCEDURE TO INITIALIZE APPLICATIONS PARAMETERS.
FND_GLOBAL.APPS_INITIALIZE(
user_id => , --hide
resp_id => , --hide
resp_appl_id => ); --hide
-- VALUES FOR WSH_DELIVERY_DETAILS_PUB.DETAIL_TO_DELIVERY
pDeliveryId := 379358;
pDeliveryName := 'Delivery01';
pTabOfDelDet(1) := 354601 ;
pAction := 'ASSIGN';
-- CALL TO WSH_DELIVERY_DETAILS_PUB.DETAIL_TO_DELIVERY.
WSH_DELIVERY_DETAILS_PUB.detail_to_delivery(
p_api_version => pApiVersion,
p_init_msg_list => pInitMsgList,
p_commit => pCommit,
x_return_status => xReturnStatus,
x_msg_count => xMsgCount,
x_msg_data => xMsgData,
p_TabOfDelDets => pTabOfDelDet,
p_action => pAction,
p_delivery_id => pDeliveryId,
p_delivery_name => pDeliveryName );
IF (xReturnStatus <> WSH_UTIL_CORE.G_RET_STS_SUCCESS) THEN RAISE vFailApiException;
ELSE DBMS_OUTPUT.PUT_LINE('Detail '||pTabOfDelDet(1)|| ' assignment to the delivery '|| pDeliveryName ||' is successful');
END IF;
Exception
WHEN vFailApiException THEN WSH_UTIL_CORE.get_messages('Y', xMsgSummary, xMsgDetails, xMsgCount);
IF xMsgCount > 1 THEN xMsgData := xMsgSummary || xMsgDetails;
DBMS_OUTPUT.PUT_LINE('Message Data : '||xMsgData);
ELSE xMsgData := xMsgSummary;
DBMS_OUTPUT.PUT_LINE('Message Data : '||xMsgData);
END IF;
END;
END;
/
But the result is always like this :
Message Data : Error: Error in assigning one or more details to a delivery.
Warning: These entities can not be grouped together as their grouping attributes do not match.
Can anyone help me??
Each inventory organization that you ship from has Shipping Parameters defined in the Order Management/Shipping Execution setups.
One area of that form is "Delivery Grouping Attributes". Some attributes are mandatory -- ship from and ship to. Think about it -- if two order lines are being shipped from two different locations, they're not part of the same delivery (they can be part of the same trip, but that is a separate though related concept in Oracle Shipping Execution).
Anyway, if the organization you are shipping from has Shipping Parameters set up that specify a given attribute is part of the Delivery Grouping Attributes, then every delivery detail (~order line, sort of, but not always) you add to the delivery must match that attribute for the delivery.
For example, if "Ship Method" is a delivery grouping attribute and you try to add an order line shipped "Next Day Air" to a "LTL Truck" delivery, you'll get the error you are encountering.
Check the Shipping Parameters for the organizations from which you are shipping and then check the value of each Delivery Grouping Attribute to make sure they match between the delivery and the delivery detail you are attempting to assign to the delivery.
Related
I have been searching and searching trying to figure out how to do this, but I can't seem to find the answer...
I have a list of delivery names saved in a custom table. Now what I want to assign all those deliveries to a trip, and ship confirm the trip.
Right now I have the attached code working. It will successfully create a unique trip for each delivery, and ship confirm each trip. But I really need to be able to create only ONE trip for all deliveries. Please help!
function f_download_order_ship_confirm return boolean
is
cursor c_deliveries is
select *
from tup_mexico_dlvrs_to_reconcile
where nvl(attribute1,'0') != 'SHIP_CONFIRMED'
order by delivery_name;
p_ship_conf_status varchar2(5000);
x_msg_data varchar2(5000);
p_api_version_number number;
init_msg_list varchar2(30);
x_msg_count number;
x_msg_details varchar2(32000);
x_msg_summary varchar2(32000);
p_validation_level number;
p_commit varchar2(30);
x_return_status varchar2(15);
source_code varchar2(15);
changed_attributes wsh_delivery_details_pub.changedattributetabtype;
p_action_code varchar2(15);
p_delivery_id number;
p_delivery_name varchar2(30);
p_asg_trip_id number;
p_asg_trip_name varchar2(30);
p_asg_pickup_stop_id number;
p_asg_pickup_loc_id number;
p_asg_pickup_loc_code varchar2(30);
p_asg_pickup_arr_date date;
p_asg_pickup_dep_date date;
p_asg_dropoff_stop_id number;
p_asg_dropoff_loc_id number;
p_asg_dropoff_loc_code varchar2(30);
p_asg_dropoff_arr_date date;
p_asg_dropoff_dep_date date;
p_sc_action_flag varchar2(10);
p_sc_close_trip_flag varchar2(10);
p_defer_iface varchar2(10);
p_sc_create_bol_flag varchar2(10);
p_sc_stage_del_flag varchar2(10);
p_sc_trip_ship_method varchar2(30);
p_sc_actual_dep_date varchar2(30);
p_sc_report_set_id number;
p_sc_report_set_name varchar2(60);
p_wv_override_flag varchar2(10);
x_trip_id varchar2(30);
x_trip_name varchar2(30);
p_msg_data varchar2(32000);
fail_api exception;
n_cursor_count number := 0;
v_first_delivery varchar2(30);
v_last_delivery varchar2(30);
begin
x_return_status := wsh_util_core.g_ret_sts_success;
p_action_code := 'CONFIRM';
p_sc_action_flag := 'B';
p_sc_close_trip_flag := 'Y';
p_defer_iface := 'N';
for x in c_deliveries loop
wsh_deliveries_pub.delivery_action(p_api_version_number => 1.0
,p_init_msg_list => init_msg_list
,x_return_status => x_return_status
,x_msg_count => x_msg_count
,x_msg_data => p_msg_data
,p_action_code => p_action_code
,p_delivery_id => p_delivery_id
,p_delivery_name => x.delivery_name -- delivery name
,p_asg_trip_id => p_asg_trip_id
,p_asg_trip_name => p_asg_trip_name
,p_asg_pickup_stop_id => p_asg_pickup_stop_id
,p_asg_pickup_loc_id => p_asg_pickup_loc_id
,p_asg_pickup_loc_code => p_asg_pickup_loc_code
,p_asg_pickup_arr_date => p_asg_pickup_arr_date
,p_asg_pickup_dep_date => p_asg_pickup_dep_date
,p_asg_dropoff_stop_id => p_asg_dropoff_stop_id
,p_asg_dropoff_loc_id => p_asg_dropoff_loc_id
,p_asg_dropoff_loc_code => p_asg_dropoff_loc_code
,p_asg_dropoff_arr_date => p_asg_dropoff_arr_date
,p_asg_dropoff_dep_date => p_asg_dropoff_dep_date
,p_sc_action_flag => p_sc_action_flag
,p_sc_close_trip_flag => p_sc_close_trip_flag
,p_sc_create_bol_flag => p_sc_create_bol_flag
,p_sc_stage_del_flag => p_sc_stage_del_flag
,p_sc_trip_ship_method => p_sc_trip_ship_method
,p_sc_actual_dep_date => p_sc_actual_dep_date
,p_sc_report_set_id => p_sc_report_set_id
,p_sc_report_set_name => p_sc_report_set_name
,p_sc_defer_interface_flag => p_defer_iface
,p_wv_override_flag => p_wv_override_flag
,x_trip_id => x_trip_id
,x_trip_name => x_trip_name);
-- if api was not successful --
if (x_return_status <> wsh_util_core.g_ret_sts_success) then
wsh_util_core.get_messages('Y'
,x_msg_summary
,x_msg_details
,x_msg_count);
if x_msg_count > 1 then
x_msg_data := x_msg_summary || x_msg_details;
else
x_msg_data := x_msg_summary;
end if;
-- if api was successful --
else
-- mark as ship confirmed in custom table --
update tup_mexico_dlvrs_to_reconcile md
set md.attribute1 = 'SHIP_CONFIRMED'
,md.attribute5 = x_trip_id
where md.delivery_name = x.delivery_name;
end if;
end loop;
return true;
exception
when others then
return false;
end f_download_order_ship_confirm;
If you configure the Oracle EBS Shipping Execution module correctly, you can make it autocreate deliveries and assign them to open trips automatically.
Otherwise, you need to do that work yourself via the API.
The wsh_deliveries_pub public API, which you are already using, can do this if you specify the correct values for p_action_code
AUTOCREATE-TRIP ==> automatically create a trip for the delivery
ASSIGN-TRIP ==> assign a delivery to an existing trip
You'd probably want to call with "AUTOCREATE-TRIP" for the first delivery in the batch and then "ASSIGN-TRIP" for the subsequent ones.
Keep in mind the API will validate that the delivery can really be assigned to the trip you choose. There are rules. E.g., you cannot assign a delivery going to customer A to a trip that's only stopping at customer B.
Refer to Oracle's documentation for more about how to use the API with these action codes.
I have a page with 2 date fields and a button. A dynamic action with PLSQL code that references the value from the 2 date fields is created. For some reason, the page item values does not get passed in the dynamic action. When i use constant values, the DA works without any problem, but when i reference the item values, it doesn't work. No idea why. Can somebody please help??
I have included the DA (not working) code and the DA that works.
Not working DA
DECLARE
I_VCNAME VARCHAR2(200);
I_LPARAMS PK_JRXML2PDF_REPGEN.TPARAMLIST;
I_VCDIR VARCHAR2(200);
I_VCFILENAME VARCHAR2(200);
bl BLOB;
BEGIN
I_VCNAME:='Fundraiser_Stats';
I_VCDIR := 'FUNDAMENTAL_FTP';
I_LPARAMS(1).vcName:='date_from';
I_LPARAMS(1).vcValue:=:R1_FROM_DATE;
I_LPARAMS(2).vcName:='date_to';
I_LPARAMS(2).vcValue:=:R1_TO_DATE;
I_LPARAMS(3).vcName:='fundraiser';
FOR fundraiser_name IN (SELECT DISTINCT B.FUNDRAISER fundraiser FROM WAYSACT_SRC_VW A, PLEDGE_EXT B WHERE A.PLEDGE_ID = B.PLEDGE_ID
AND A.PLEDGE_DATE BETWEEN :R1_FROM_DATE AND :R1_TO_DATE)
LOOP
I_LPARAMS(3).vcValue:= fundraiser_name.fundraiser;
I_VCFILENAME := fundraiser_name.fundraiser||'-'||to_char(sysdate,'dd-Mon-yyyy')||'.pdf';
PK_JRXML2PDF_REPGEN.PR_RUN_TO_FILE(I_VCNAME => I_VCNAME, I_LPARAMS => I_LPARAMS, I_VCDIR => I_VCDIR,I_VCFILENAME => I_VCFILENAME);
END LOOP fundraiser_name;
--APEX_APPLICATION.STOP_APEX_ENGINE;
END;
Working DA:
DECLARE
I_VCNAME VARCHAR2(200);
I_LPARAMS PK_JRXML2PDF_REPGEN.TPARAMLIST;
I_VCDIR VARCHAR2(200);
I_VCFILENAME VARCHAR2(200);
bl BLOB;
BEGIN
I_VCNAME:='Fundraiser_Stats';
I_VCDIR := 'FUNDAMENTAL_FTP';
I_LPARAMS(1).vcName:='date_from';
I_LPARAMS(1).vcValue:='02-jun-2018';
I_LPARAMS(2).vcName:='date_to';
I_LPARAMS(2).vcValue:='02-jun-2018';
I_LPARAMS(3).vcName:='fundraiser';
FOR fundraiser_name IN (SELECT DISTINCT B.FUNDRAISER fundraiser FROM WAYSACT_SRC_VW A, PLEDGE_EXT B WHERE A.PLEDGE_ID = B.PLEDGE_ID
AND A.PLEDGE_DATE BETWEEN '02-jun-2018' AND '02-jun-2018')
LOOP
I_LPARAMS(3).vcValue:= fundraiser_name.fundraiser;
I_VCFILENAME := fundraiser_name.fundraiser||'-'||to_char(sysdate,'dd-Mon-yyyy')||'.pdf';
PK_JRXML2PDF_REPGEN.PR_RUN_TO_FILE(I_VCNAME => I_VCNAME, I_LPARAMS => I_LPARAMS, I_VCDIR => I_VCDIR,I_VCFILENAME => I_VCFILENAME);
END LOOP fundraiser_name;
--APEX_APPLICATION.STOP_APEX_ENGINE;
END;
This is the "Execute PL/SQL Code" dynamic action, is it not? Within DA's "Settings" section, there's the "Items to Submit" field - put names of all items you use in that code; I've noticed
R1_FROM_DATE, R1_TO_DATE
You'll know whether there are additional ones. If so, include them into the list.
I created a user defined function that calculates the quantity in stock for a product
CREATE OR REPLACE FUNCTION function_quantityInStock(
oldProductQuantity IN INTEGER,
orderedQuan IN INTEGER)
RETURN INTEGER
IS
v_newQuantity INTEGER;
v_oldQuantity INTEGER;
v_orderedQuan INTEGER;
BEGIN
v_newquantity := oldProductQuantity - orderedQuan;
RETURN v_newquantity;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Please check your data.');
END function_quantityInstock;
I then create a trigger that updates the table by calling the function
CREATE OR REPLACE TRIGGER TRIGGER_QUANTITY AFTER INSERT ON ordered_product
FOR EACH ROW
DECLARE
v_oldQuantity INTEGER;
BEGIN
SELECT PRODUCT_QUANTITYINSTOCK INTO v_oldQuantity
FROM product
WHERE product_id = :NEW.product_id;
UPDATE PRODUCT
SET product_quantityinstock =
function_quantityINSTOCK(v_oldQuantity, :NEW.ORDERED_PRODUCTQUANTITY)
WHERE product_id = :NEW.product_id;
END;
I want to display a message when the user enters invalid data but my exception block doesnt do that.
I use the following anonyomus block to test the function:
SET SERVEROUTPUT ON;
DECLARE
v_productID ordered_product.product_id%TYPE:= &ProductID;
v_orderID ordered_product.order_id%TYPE:=&OrderID;
v_orderedQuan ordered_product.ordered_productQuantity%TYPE := &OrderedProductQuantity;
v_totalCost ordered_product.ordered_productTotalCost%TYPE := '&TotalCost';
BEGIN
INSERT INTO ordered_product VALUES
(v_orderID, v_productID, v_orderedQuan, v_totalCost);
dbms_output.put_line('A new record has been inserted.');
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('Invalid data!');
WHEN VALUE_ERROR THEN
dbms_output.put_line('Error! Please check your values.'|| SQLERRM);
END;
You might be missing exec dbms_output.enable(10000) and therefore not be seeing the output.
You should throw the exception using
raise_application_error(-20000, 'Please check your data.');
Also it's bad practice to catch all exceptions using when others and then ignore them.
If I were you, I wouldn't rely on dbms_output.put_line to pass information around. Instead, rely on the standard exception handling, e.g. RAISE or RAISE_APPLICATION_ERROR. Also, given that you're trying to find the new quantity, I'd move the select on the product table into the function, something like:
CREATE OR REPLACE FUNCTION function_quantityinstock(p_product_id IN product.product_product_id p_orderedquan IN INTEGER)
RETURN INTEGER IS
v_newquantity INTEGER;
e_not_enough_stock EXCEPTION;
e_not_enough_stock_num INTEGER := -20001;
e_no_product_exists_num INTEGER := -20002;
PRAGMA EXCEPTION_INIT(e_not_enough_stock, -20001);
BEGIN
SELECT product_quantityinstock - orderedquan
INTO v_newquantity
FROM product
WHERE product_id = :new.product_id;
IF v_newquantity < 0
THEN
RAISE e_not_enough_stock;
END IF;
RETURN v_newquantity;
EXCEPTION
WHEN no_data_found THEN
raise_application_error(-e_no_product_exists_num,
'No product exists for product_id = ' || product_id);
-- no need to check for TOO_MANY_ROWS if product_id is the primary/unique key on the product table.
WHEN e_not_enough_stock THEN
raise_application_error(e_not_enough_stock_num,
'Not enough stock present to fulfil the order for product_id = ' ||
product_id);
WHEN OTHERS THEN
raise_application_error(SQLCODE,
'Unexpected error occurred whilst finding new quantity for product_id = ' ||
product_id || ': ' || SQLERRM);
END function_quantityinstock;
/
You'd need to change the function name though, to reflect the action that it's doing, since it's returning the new quantity in stock...
I used the following API to assign multiple items (one by one) from one organization to another.I had created test items through the inventory responsibility using master item window and then assign them to another organization using the following code:
BEGIN
DECLARE
l_api_version NUMBER := 1.0;
l_init_msg_list VARCHAR2(2) := FND_API.G_TRUE;
l_commit VARCHAR2(2) := FND_API.G_FALSE;
x_message_list error_handler.error_tbl_type;
itemid mtl_system_items_b.inventory_item_id %TYPE;
segment1 mtl_system_items_b.segment1 %TYPE;
primary_uom_code mtl_system_items_b.primary_uom_code %TYPE;
x_return_status VARCHAR2(2);
x_msg_count NUMBER := 0;
BEGIN
SELECT inventory_item_id INTO itemid FROM mtl_system_items_b WHERE inventory_item_id=2447106 and organization_id=116;
SELECT segment1
INTO segment1 FROM mtl_system_items_b WHERE inventory_item_id=2447106 and organization_id=116;
SELECT primary_uom_code INTO primary_uom_code FROM mtl_system_items_b WHERE inventory_item_id=2447106 and organization_id=116;
EGO_ITEM_PUB.ASSIGN_ITEM_TO_ORG(
P_API_VERSION => l_api_version
, P_INIT_MSG_LIST => l_INIT_MSG_LIST
, P_COMMIT => l_COMMIT
, P_INVENTORY_ITEM_ID => itemid --(item id from the above Query)
, P_ITEM_NUMBER => segment1 --(Item Code from the above Query)
, P_ORGANIZATION_ID => 117 --(Organization Id for assingment)
, P_ORGANIZATION_CODE => 'D12'--v_organization_code
, P_PRIMARY_UOM_CODE =>primary_uom_code --(UOM from the above Query)
, X_RETURN_STATUS => X_RETURN_STATUS
, X_MSG_COUNT => X_MSG_COUNT
);
DBMS_OUTPUT.PUT_LINE('Status: '||x_return_status);
IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
DBMS_OUTPUT.PUT_LINE('Error Messages :');
Error_Handler.GET_MESSAGE_LIST(x_message_list=> x_message_list);
FOR j IN 1..x_message_list.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(x_message_list(j).message_tex t);
END LOOP;
END IF;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Exception Occured :');
DBMS_OUTPUT.PUT_LINE(SQLCODE ||':'||SQLERRM);
END;
END;
After completion, I checked into the database and the items were assigned to the organization i wanted to. However, these items were not appearing in any of the windows when i searched through GUI (Item information window or item search window) under the new organization that i assigned them too.
I tried changing few values that appeared to be abnormal (E.g: last update time was '-1' probably because i used API and not GUI using my user id and password).
Why are not the items appearing in GUI?Is there a step other than executing the above code correctly that I am missing? Please help.
You are not committing the transaction. You declare:
l_commit VARCHAR2(2) := FND_API.G_FALSE;
Which you then pass into the API. If you then query the tables using the same transaction, you will see the modified data. But the application forms are using another session.
You need to add a commit at the end. As to whether to pass in G_TRUE, you need to read the API documentation.
I want to make list which will display values, like text item but in list.
My code:
DECLARE
rg_dept RecordGroup;
rg_dname VARCHAR2(4) := 'Name';
dlist_ID Item := Find_Item('PROJESCT.LIST_ID');
nDummy NUMBER;
BEGIN
rg_dept := Find_Group(rg_dname);
-- Delete any existing Group first
IF NOT Id_Null(rg_dept) THEN
Delete_Group(rg_dept);
END IF;
-- Now create a Record Group using a SQL query
-- Your Query must have a Label and a Value (two Columns)
-- and the data types must match your item type
rg_dept := Create_Group_From_Query(rg_dname,'SELECT department_name, to_char(department_id) FROM departments');
--Clear the existing List
Clear_List(dlist_ID);
-- Populate the Record Group
nDummy := Populate_Group(rg_dept);
-- Populate the List Item
Populate_List(dlist_ID ,rg_dept);
END;
If I make list item and add this code, form will display nothing; if I remove list, all is ok.
P.S. Trigger: when-list-item-change
I should recommend you to populate your lists from e.g. When-new-Form-Instance. As usual you will get a good idea what you need to do from Forms help (menu 'Help/Online Help'). This is a procedure I have made to simple populate list only by specifying the name of the list item and the select statement to populate the lsit item with.
PROCEDURE populate_list_item (
p_item_name VARCHAR2
, p_select VARCHAR2
) IS
l_rg_id RECORDGROUP;
l_list_id ITEM;
l_err_num PLS_INTEGER;
FUNCTION create_temp_group (
p_select VARCHAR2
) RETURN RECORDGROUP IS
l_rg_id RECORDGROUP;
l_group_name VARCHAR2(30) := 'TMP$RG';
BEGIN
l_rg_id := FIND_GROUP(l_group_name);
--Make sure that record group don't alreay exist
IF NOT ID_NULL(l_rg_id) THEN
DELETE_GROUP(l_rg_id);
END IF;
--Populate the temporary record group
l_rg_id := CREATE_GROUP_FROM_QUERY(l_group_name, p_select);
RETURN l_rg_id;
END create_temp_group;
BEGIN
l_rg_id := create_temp_group(p_select);
l_err_num := Populate_Group(l_rg_id);
--Allow for no data found in the selection query
IF l_err_num NOT IN (0, 1403) THEN
RAISE Form_Trigger_Failure;
END IF;
l_list_id := Find_Item(p_item_name);
IF ID_NULL(l_list_id) THEN
RAISE Form_Trigger_Failure;
END IF;
Populate_List(l_list_id, l_rg_id);
Delete_Group(l_rg_id);
END populate_list_item;
The When-New-Form-Instance is a form level trigger and should be under the form (instead of block or item):
The best thing to do is to build all your record groups at design time. It does not slow down the performance unless you have some huge, already slow form. Then populate your list items at run time. Always Copy/paste the code from Forms help.
--Oracle Forms Example: Create a record group from a query, and populate it.
DECLARE
rg_name VARCHAR2(40) := 'Salary_Range';
rg_id RecordGroup;
errcode NUMBER;
BEGIN
/*
** Make sure group doesn't already exist
*/
rg_id := Find_Group( rg_name );
/*
** If it does not exist, create it and add the two
** necessary columns to it.
*/
IF Id_Null(rg_id) THEN
rg_id := Create_Group_From_Query( rg_name,
'SELECT SAL-MOD(SAL,1000) BASE_SAL_RANGE,'
||'COUNT(EMPNO) EMPS_IN_RANGE '
||'FROM EMP '
||'GROUP BY SAL-MOD(SAL,1000) '
||'ORDER BY 1');
END IF;
/*
** Populate the record group
*/
errcode := Populate_Group( rg_id );
END;