Friday, March 21, 2014

Back Order

Order Management and Shipping Execution has two types of   Backorders.

Back-orders caused by Pick Releasing (PR)  order lines when there is no or not enough stock available.

And back-orders caused by shipping less, at Ship confirm, than what was released.



A. Backorders after Pick Releasing with Insufficient Stock

Pick Release will process all order (more correctly shipping) lines that you selected when
submitting PR.  It will create move order lines for each line, whether there is stock available or not.
You (or the system) will however, not be able to (auto) detail and (auto) Pick Confirm the    
lines where there is not enough stock available.  In R11i, you cannot switch off reservations
for PR.  Also, the system will not print pick slips for lines that are not detailed.
 
The delivery line, which was 'Ready to Release' before running PR will be split into a quantity
 that was available for picking and a unavailable quantity.  The first delivery line will become
status ‘Released’ (Pick Confirmed), the second 'Submitted for Release' (Move Order created,
but not confirmed).  In the latter case, the ‘Details Required' status is checked.  The order line will
 not split at this point, but receives a 'Picked partial' status.  After Ship Confirming the Released
delivery line, the original order line will be split into a 'Shipped' and a 'Submitted for Release' line
 (unless the shipped quantity falls within the under shipment tolerance).  The latter will be available
 for Pick Release as a 'Backorder' as soon as there is stock available.  On the sales order, there is
no order or workflow status called 'Backorder'.  You will not really see any difference
between a scheduled order line that was never released and a backordered line.  
Pick Release is able to distinguish between the two, because it allows you to release them
separately.

B. Backorders Caused by shipping less than what was Released

Before Ship Confirming a Released (Pick Confirmed) delivery line, you have theoption to update the 
shipped quantity.  If the shipped quantity is less than the picked quantity, you have can either 
designate the remaining quantity as
'Backordered' (meaning the quantity was lost somewhere along the picking/staging process) or 
leave it in staging in to assign it to a different delivery (i.e. truck was full and wait for next pick up).
At Ship Confirm, any staged quantities will be split off in a separate delivery line that is
immediately ready to be shipped in a subsequent delivery.  A backordered quantity will remain 
noted on the same delivery line.  Only when the original delivery line is interfaced through       
Inventory Interface/Order Management Interface, will the order line be split into a line for the 
shipped quantity and a new line for the backordered quantity (Awaiting shipping).  This enables 
you to pick the remaining quantity again in order to fulfill the complete order quantity.  This split 
will only happen if the backordered quantity is greater than the Under Shipment Tolerance.

Order Management Flows and Workflow Status

Friday, March 14, 2014

Bulk Collect EXCEPTION

Source




SQL%BULK_EXCEPTIONS(i).ERROR_CODE – Holds the exceptions error code.
The total number of exceptions can be returned using the collections COUNT method, which returns zero if no exceptions were raised.  The save_exceptions.sql script, a modified version of the handled_exception.sql script, demonstrates this functionality.
save_exceptions.sql
SET SERVEROUTPUT ON
DECLARE
  TYPE t_tab IS TABLE OF exception_test%ROWTYPE;
  l_tab          t_tab := t_tab();
  l_error_count  NUMBER; 
  ex_dml_errors EXCEPTION;
  PRAGMA EXCEPTION_INIT(ex_dml_errors, -24381);
BEGIN
  -- Fill the collection.
  FOR i IN 1 .. 100 LOOP
    l_tab.extend;
    l_tab(l_tab.last).id := i;
  END LOOP;
  -- Cause a failure.
  l_tab(50).id := NULL;
  l_tab(51).id := NULL; 
  EXECUTE IMMEDIATE 'TRUNCATE TABLE exception_test';
  -- Perform a bulk operation.
  BEGIN
    FORALL i IN l_tab.first .. l_tab.last SAVE EXCEPTIONS
      INSERT INTO exception_test
      VALUES l_tab(i);
  EXCEPTION
    WHEN ex_dml_errors THEN
      l_error_count := SQL%BULK_EXCEPTIONS.count;
      DBMS_OUTPUT.put_line('Number of failures: ' || l_error_count);
      FOR i IN 1 .. l_error_count LOOP
        DBMS_OUTPUT.put_line('Error: ' || i ||
          ' Array Index: ' || SQL%BULK_EXCEPTIONS(i).error_index ||
          ' Message: ' || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
      END LOOP;
  END;
END;
/
SET ECHO ON
SELECT COUNT(*)
FROM   exception_test;
SET ECHO OFF
The FORALL statement includes the SAVE EXCEPTIONS clause, and the exception handler displays the number of exceptions and their associated error messages.  The output from the save_exceptions.sql script is listed below.
SQL> @save_exceptions.sql
Number of failures: 2
Error: 1 Array Index: 50 Message: ORA-01400: cannot insert NULL into ()
Error: 2 Array Index: 51 Message: ORA-01400: cannot insert NULL into ()
PL/SQL procedure successfully completed.
SQL> SELECT COUNT(*)
  2  FROM   exception_test;
  COUNT(*)
----------
        98
1 row selected.
SQL> SET ECHO OFF
As expected the test table contains 98 of the 100 records, and the associated error message has been displayed by looping through the SQL%BULK_EXCEPTION collection.
If the SAVE EXCEPTIONS clause is omitted from the FORALL statement, execution of the bulk operation stops at the first exception and the SQL%BULK_EXCEPTIONS collection contains a single record.  The no_save_exceptions.sql script demonstrates this behavior.
no_save_exceptions.sql
SET SERVEROUTPUT ON
DECLARE
  TYPE t_tab IS TABLE OF exception_test%ROWTYPE;
  l_tab          t_tab := t_tab();
  l_error_count  NUMBER; 
  ex_dml_errors EXCEPTION;
  PRAGMA EXCEPTION_INIT(ex_dml_errors, -01400);
BEGIN
  -- Fill the collection.
  FOR i IN 1 .. 100 LOOP
    l_tab.extend;
    l_tab(l_tab.last).id := i;
  END LOOP;
  -- Cause a failure.
  l_tab(50).id := NULL;
  l_tab(51).id := NULL; 
  EXECUTE IMMEDIATE 'TRUNCATE TABLE exception_test';
  -- Perform a bulk operation.
  BEGIN
    FORALL i IN l_tab.first .. l_tab.last
      INSERT INTO exception_test
      VALUES l_tab(i);
  EXCEPTION
    WHEN ex_dml_errors THEN
      l_error_count := SQL%BULK_EXCEPTIONS.count;
      DBMS_OUTPUT.put_line('Number of failures: ' || l_error_count);
      FOR i IN 1 .. l_error_count LOOP
        DBMS_OUTPUT.put_line('Error: ' || i ||
          ' Array Index: ' || SQL%BULK_EXCEPTIONS(i).error_index ||
          ' Message: ' || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
     END LOOP;
  END;
END;
/
SET ECHO ON
SELECT COUNT(*)
FROM   exception_test;
SET ECHO OFF
Notice that in addition to the SAVE EXCEPTIONS clause being removed, the no_save_exceptions.sql script now traps a different error number.  The output from this script is listed below.
SQL> @no_save_exceptions.sql
Number of failures: 1
Error: 1 Array Index: 50 Message: ORA-01400: cannot insert NULL into
("TIM_HALL"."EXCEPTION_TEST"."ID")
PL/SQL procedure successfully completed.
SQL> SELECT COUNT(*)
  2  FROM   exception_test;
  COUNT(*)
----------
        49
1 row selected.
SQL> SET ECHO OFF
As expected there is only a single error in the SQL%BULK_EXCEPTIONS collection, and there are only 49 records in the test table as the operation has rolled back to the preceding implicit savepoint.