Advertisement
TheLinkerZero

m_production_run

Mar 29th, 2020
1,151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PL/SQL 31.15 KB | None | 0 0
  1. -- Filter INSERT INTO M_PRODUCTIONLINE
  2.  
  3. CREATE OR REPLACE FUNCTION PUBLIC.m_production_run(pinstance_id character varying)
  4.  RETURNS void
  5.  LANGUAGE plpgsql
  6.  SET search_path TO '$user', 'public'
  7. AS $function$ DECLARE
  8. /*************************************************************************
  9.   * The contents of this file are subject to the Compiere Public
  10.   * License 1.1 ("License"); You may not use this file except in
  11.   * compliance with the License. You may obtain a copy of the License in
  12.   * the legal folder of your Openbravo installation.
  13.   * Software distributed under the License is distributed on an
  14.   * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  15.   * implied. See the License for the specific language governing rights
  16.   * and limitations under the License.
  17.   * The Original Code is  Compiere  ERP &  Business Solution
  18.   * The Initial Developer of the Original Code is Jorg Janke and ComPiere, Inc.
  19.   * Portions created by Jorg Janke are Copyright (C) 1999-2001 Jorg Janke,
  20.   * parts created by ComPiere are Copyright (C) ComPiere, Inc.;
  21.   * All Rights Reserved.
  22.   * Contributor(s): Openbravo SLU
  23.   * Contributions are Copyright (C) 2001-2017 Openbravo, S.L.U.
  24.   *
  25.   * Specifically, this derivative work is based upon the following Compiere
  26.   * file and version.
  27.   *************************************************************************
  28.   * $Id: M_Production_Run.sql,v 1.4 2003/09/05 04:58:06 jjanke Exp $
  29.   ***
  30.   * Title: Production of BOMs
  31.   * Description:
  32.   *  1) Creating ProductionLines when IsCreated = 'N'
  33.   *  2) Posting the Lines (optionally only when fully stocked)
  34.   ************************************************************************/
  35.   -- Logistice
  36.   v_ResultStr VARCHAR(2000):=''; --OBTG:VARCHAR2--
  37.   v_Message VARCHAR(2000):=''; --OBTG:VARCHAR2--
  38.   v_Record_ID VARCHAR(32); --OBTG:VARCHAR2--
  39.   v_Result NUMERIC:=1;
  40.   v_is_included NUMERIC:=0;
  41.   v_MovementDate TIMESTAMP;
  42.   v_available_period NUMERIC:=0;
  43.   v_is_ready AD_Org.IsReady%TYPE;
  44.   v_is_tr_allow AD_OrgType.IsTransactionsAllowed%TYPE;
  45.   v_isacctle AD_OrgType.IsAcctLegalEntity%TYPE;
  46.   -- Parameter
  47.   --TYPE RECORD IS REFCURSOR;
  48.     Cur_Parameter RECORD;
  49.     CUR_ProductionPlan RECORD;
  50.     CUR_PP RECORD;
  51.     CUR_PLineBOM RECORD;
  52.     CUR_BOM_PRODUCT RECORD;
  53.     CUR_PL_Post RECORD;
  54.   -- Parameter Variables
  55.   MustBeStocked CHAR(1) ;
  56.   v_IsCreated CHAR(1) ;
  57.   v_Processed VARCHAR(60) ; --OBTG:VARCHAR2--
  58.   v_Client_ID VARCHAR(32); --OBTG:VARCHAR2--
  59.   v_Org_ID VARCHAR(32); --OBTG:VARCHAR2--
  60.   --
  61.   v_Line NUMERIC;
  62.   v_Count NUMERIC;
  63.   p_User VARCHAR(32); --OBTG:VARCHAR2--
  64.   v_NegStockLocator VARCHAR(32); --OBTG:VARCHAR2--
  65.   v_NegStockWarehosue VARCHAR(32); --OBTG:VARCHAR2--
  66.   v_Product_Name m_product.name%TYPE;
  67.   -- Stocked BOMs
  68.   -- Proposed stock from given warehouse is priorized.
  69.   DECLARE CUR_STOCK CURSOR (v_ad_pinstance_id VARCHAR)  FOR
  70.       SELECT sd.m_product_id, sd.m_locator_id, sd.m_attributesetinstance_id,
  71.           sd.c_uom_id, sd.m_product_uom_id, u.stdprecision,
  72.           ms.quantity AS qty, ms.qtyorder AS qtyorder,
  73.           ms.priority, invs.overissue
  74.       FROM m_stock_proposed ms
  75.             LEFT JOIN m_storage_detail sd ON ms.m_storage_detail_id = sd.m_storage_detail_id
  76.             LEFT JOIN m_product_uom pu ON sd.m_product_uom_id = pu.m_product_uom_id
  77.             LEFT JOIN c_uom u ON pu.c_uom_id = u.c_uom_id
  78.             LEFT JOIN m_locator l ON sd.m_locator_id = l.m_locator_id
  79.             JOIN m_inventorystatus invs ON invs.m_inventorystatus_id = l.m_inventorystatus_id
  80.       WHERE ms.ad_pinstance_id = v_ad_pinstance_id
  81.       ORDER BY ms.priority;
  82.   v_storage RECORD; --OBTG:CUR_STOCK--
  83.   NEXT_PRODUCT BOOLEAN:=FALSE;
  84.   CUR_STOCK_ISOPEN BOOLEAN:=FALSE;
  85. BEGIN
  86.   --  Update AD_PInstance
  87.   RAISE NOTICE '%','Updating PInstance - Processing ' || PInstance_ID ;
  88.   v_ResultStr:='PInstanceNotFound';
  89.   PERFORM AD_UPDATE_PINSTANCE(PInstance_ID, NULL, 'Y', NULL, NULL) ;
  90. BEGIN --BODY
  91.   -- Get Parameters
  92.   v_ResultStr:='ReadingParameters';
  93.   FOR Cur_Parameter IN (
  94.       SELECT i.Record_ID, i.AD_User_ID, p.ParameterName,
  95.           p.P_String, p.P_Number, p.P_Date
  96.       FROM AD_ClientInfo ci JOIN AD_PInstance i ON ci.ad_client_id=i.ad_client_id
  97.             LEFT JOIN AD_PInstance_Para p ON i.AD_PInstance_ID=p.AD_PInstance_ID
  98.       WHERE i.AD_PInstance_ID=PInstance_ID
  99.       ORDER BY p.SeqNo
  100.   ) LOOP
  101.     v_Record_ID := Cur_Parameter.Record_ID;
  102.     p_User := Cur_Parameter.AD_User_ID;
  103.     IF (Cur_Parameter.ParameterName = 'MustBeStocked') THEN
  104.       MustBeStocked:=Cur_Parameter.P_String;
  105.       RAISE NOTICE '%','  MustBeStocked=' || MustBeStocked ;
  106.     ELSE
  107.       RAISE NOTICE '%','*** Unknown Parameter=' || Cur_Parameter.ParameterName ;
  108.     END IF;
  109.   END LOOP; -- Get Parameter
  110.   RAISE NOTICE '%','  Record_ID=' || v_Record_ID ;
  111.   -- Processing:1:2:3 Lock :4:5:6:7
  112.   -- TODO
  113.   /**
  114.   * Get Info + Lock
  115.   */
  116.   v_ResultStr:='ReadingRecord';
  117.   SELECT IsCreated, Processed, AD_Client_ID, AD_Org_ID, MovementDate
  118.     INTO v_IsCreated, v_Processed, v_Client_ID, v_Org_ID, v_MovementDate
  119.   FROM M_PRODUCTION
  120.   WHERE M_Production_ID=v_Record_ID  FOR UPDATE;
  121.   /**
  122.   * No Action
  123.   */
  124.   IF (v_Processed <> 'N') THEN
  125.     v_Message:='@AlreadyPosted@';
  126.     RAISE EXCEPTION '%', v_Message; --OBTG:-20000--
  127.   END IF;
  128.   /**************************************************************************
  129.   * Create Lines
  130.   */
  131.   /***************************************************************************/
  132.   -- Check the header belongs to a organization where transactions are posible and ready to use
  133.   SELECT AD_Org.IsReady, Ad_OrgType.IsTransactionsAllowed
  134.     INTO v_is_ready, v_is_tr_allow
  135.   FROM M_PRODUCTION, AD_Org, AD_OrgType
  136.   WHERE AD_Org.AD_Org_ID=M_PRODUCTION.AD_Org_ID
  137.     AND AD_Org.AD_OrgType_ID=AD_OrgType.AD_OrgType_ID
  138.     AND M_PRODUCTION.M_PRODUCTION_ID=v_Record_ID;
  139.   IF (v_is_ready='N') THEN
  140.     RAISE EXCEPTION '%', '@OrgHeaderNotReady@'; --OBTG:-20000--
  141.   END IF;
  142.   IF (v_is_tr_allow='N') THEN
  143.     RAISE EXCEPTION '%', '@OrgHeaderNotTransAllowed@'; --OBTG:-20000--
  144.   END IF;
  145.  
  146.   -- Check the lines belong to the same business unit or legal entity as the header    
  147.   SELECT AD_ORG_CHK_DOCUMENTS('M_PRODUCTION', 'M_PRODUCTIONPLAN', v_Record_ID, 'M_PRODUCTION_ID', 'M_PRODUCTION_ID') INTO v_is_included FROM dual;
  148.   IF (v_is_included = -1) THEN
  149.     RAISE EXCEPTION '%', '@LinesAndHeaderDifferentLEorBU@'; --OBTG:-20000--
  150.   END IF;
  151.   FOR CUR_PP IN (
  152.       SELECT M_PRODUCTIONPLAN_ID
  153.       FROM M_PRODUCTIONPLAN
  154.       WHERE M_PRODUCTION_ID = v_Record_ID
  155.   ) LOOP
  156.     SELECT AD_ORG_CHK_DOCUMENTS('M_PRODUCTIONPLAN', 'M_PRODUCTIONLINE', CUR_PP.M_PRODUCTIONPLAN_ID, 'M_PRODUCTIONPLAN_ID', 'M_PRODUCTIONPLAN_ID') INTO v_is_included FROM dual;
  157.     IF (v_is_included = -1) THEN
  158.       RAISE EXCEPTION '%', '@LinesAndHeaderDifferentLEorBU@'; --OBTG:-20000--
  159.     END IF;
  160.   END LOOP;
  161.  
  162.   -- Check the period control is opened (only if it is legal entity with accounting)
  163.   -- Gets the BU or LE of the document
  164.   SELECT AD_OrgType.IsAcctLegalEntity INTO v_isacctle
  165.   FROM AD_OrgType, AD_Org
  166.   WHERE AD_Org.AD_OrgType_ID = AD_OrgType.AD_OrgType_ID
  167.     AND AD_Org.AD_Org_ID = AD_GET_DOC_LE_BU('M_PRODUCTION', v_Record_ID, 'M_PRODUCTION_ID', 'LE');
  168.  
  169.   IF (v_isacctle='Y') THEN
  170.     SELECT C_CHK_OPEN_PERIOD(v_Org_ID, v_MovementDate, 'MMP', NULL)  INTO v_available_period FROM DUAL;
  171.  
  172.     IF (v_available_period<>1) THEN
  173.       RAISE EXCEPTION '%', '@PeriodNotAvailable@'; --OBTG:-20000--
  174.     END IF;
  175.   END IF;
  176.  
  177.   IF (v_IsCreated <> 'Y') THEN
  178.     -- For every Production Plan
  179.     FOR CUR_PP IN (
  180.         SELECT M_PRODUCTIONPLAN.*, M_PRODUCT.C_UOM_ID,
  181.             (CASE WHEN M_PRODUCT.ATTRSETVALUETYPE='D' THEN M_PRODUCT.M_AttributeSetInstance_ID ELSE NULL END) AS M_AttributeSetInstance_ID
  182.         FROM M_PRODUCTIONPLAN, M_PRODUCT
  183.         WHERE M_PRODUCTIONPLAN.M_Product_ID=M_PRODUCT.M_Product_ID
  184.           AND M_PRODUCTIONPLAN.M_Production_ID=v_Record_ID
  185.         ORDER BY M_PRODUCTIONPLAN.Line, M_PRODUCTIONPLAN.M_Product_ID
  186.     ) LOOP
  187.       IF (CUR_PP.M_Locator_ID IS NULL) THEN
  188.         RAISE EXCEPTION '%', '@ProductionPlanLocatorNeeded@'; --OBTG:-20000--
  189.       END IF;
  190.       -- Delete prior lines
  191.       DELETE
  192.       FROM M_PRODUCTIONLINE
  193.       WHERE M_ProductionPlan_ID=CUR_PP.M_ProductionPlan_ID;
  194.       -- Create BOM Line
  195.       v_ResultStr:='CreatingLine BOM';
  196.       v_Line:=10; -- OriginLine
  197.       INSERT INTO M_PRODUCTIONLINE (
  198.           M_ProductionLine_ID, M_ProductionPlan_ID, Line, AD_Client_ID,
  199.           AD_Org_ID, IsActive, Created, CreatedBy,
  200.           Updated, UpdatedBy, M_Product_ID, MovementQty,
  201.           M_Locator_ID, Description, C_UOM_ID,
  202.           M_AttributeSetInstance_ID
  203.       ) VALUES (
  204.           get_uuid(), CUR_PP.M_ProductionPlan_ID, v_Line, CUR_PP.AD_Client_ID,
  205.           CUR_PP.AD_Org_ID, 'Y', TO_DATE(NOW()), p_User,
  206.           TO_DATE(NOW()), p_User, CUR_PP.M_Product_ID, CUR_PP.ProductionQty,
  207.           CUR_PP.M_Locator_ID, CUR_PP.Description, CUR_PP.C_UOM_ID,
  208.           CUR_PP.M_AttributeSetInstance_ID
  209.       );
  210.     END LOOP;
  211.     --Creating BOM Lines
  212.     DECLARE
  213.       v_Product_old VARCHAR(32); --OBTG:VARCHAR2--
  214.       v_Warehouse_old VARCHAR(32); --OBTG:VARCHAR2--
  215.       v_UOM_old VARCHAR(32); --OBTG:VARCHAR2--
  216.       v_Qty NUMERIC;
  217.       v_QtyStorage NUMERIC:=0;
  218.       v_QtyAcumulated NUMERIC;
  219.       v_QtyOrder NUMERIC;
  220.       v_QtyOrderRate NUMERIC;
  221.       v_ProductionLineCount NUMERIC;
  222.       v_pinstance_id VARCHAR(32); --OBTG:VARCHAR2--
  223.       CUR_BOM RECORD;
  224.     BEGIN
  225.       FOR CUR_BOM IN (
  226.           SELECT pb.*,
  227.               p.C_UOM_ID, p.IsStocked, pp.M_LOCATOR_ID, pp.AD_Org_ID AS ORG_ID,
  228.               pp.ProductionQty, pp.M_ProductionPlan_ID, pp.AD_Client_ID AS Client_ID, p.name AS pname,
  229.               l.m_warehouse_id
  230.           FROM M_PRODUCT_BOM pb
  231.               JOIN M_PRODUCT p ON pb.M_ProductBOM_ID=p.M_Product_ID
  232.               JOIN M_PRODUCTIONPLAN pp ON pb.M_Product_ID=pp.M_PRODUCT_ID
  233.               JOIN M_LOCATOR l ON pp.m_locator_id = l.m_locator_id
  234.         WHERE pp.M_PRODUCTION_ID=v_Record_ID
  235.           AND pb.isactive='Y'
  236.         ORDER BY pb.M_PRODUCTBOM_ID, pb.Line
  237.       ) LOOP
  238.         v_ResultStr:='CreatingLine Products';
  239.         IF (CUR_BOM.IsStocked = 'Y') THEN
  240.           v_QtyAcumulated:=0;
  241.           IF ((NOT CUR_STOCK_ISOPEN)
  242.               OR (v_Product_old <> CUR_BOM.M_ProductBOM_ID OR v_Warehouse_old <> cur_bom.m_warehouse_id OR v_UOM_old <> CUR_BOM.C_UOM_ID)) THEN
  243.             NEXT_PRODUCT:=FALSE;
  244.             v_product_old := cur_bom.m_productbom_id;
  245.             v_warehouse_old := cur_bom.m_warehouse_id;
  246.             v_uom_old := cur_bom.c_uom_id;
  247.             IF (CUR_STOCK_ISOPEN) THEN
  248.               CLOSE CUR_STOCK;
  249.               CUR_STOCK_ISOPEN:=FALSE;
  250.             END IF;
  251.            
  252.             -- Call M_GET_STOCK
  253.             DECLARE
  254.               v_pinstance_result AD_PInstance.result%TYPE;
  255.               v_pinstance_msg AD_PInstance.errormsg%TYPE;
  256.             BEGIN
  257.               v_pinstance_id := get_uuid();
  258.              SELECT * INTO  v_pinstance_result, v_pinstance_msg FROM M_GET_STOCK_PARAM(v_pinstance_id, v_record_id, NULL, v_Product_old, NULL, NULL, v_Warehouse_old, cur_bom.org_id, NULL, p_user, v_client_id, NULL, v_UOM_old, NULL, NULL, NULL, 10, '137', NULL, 'N', 'Y', NULL, NULL);
  259.               -- Check result
  260.               IF (v_pinstance_result = 0) THEN
  261.                 -- Error on m_get_stock
  262.                 RAISE EXCEPTION '%', v_pinstance_msg; --OBTG:-20000--
  263.               END IF;
  264.             END; -- End Call M_GET_STOCK
  265.            
  266.             OPEN CUR_STOCK(v_pinstance_id);
  267.             CUR_STOCK_ISOPEN:=TRUE;
  268.             FETCH CUR_STOCK INTO v_storage;
  269.             IF ( NOT FOUND ) THEN --OBTG:CUR_STOCK--
  270.               NEXT_PRODUCT:=TRUE;
  271.             END IF;
  272.             v_qtystorage:=v_storage.qty;
  273.           END IF;
  274.           IF (NOT NEXT_PRODUCT) THEN
  275.             LOOP          
  276.               IF (v_storage.OVERISSUE = 'Y' AND v_NegStockLocator IS NULL) THEN
  277.                 v_NegStockLocator:= v_storage.m_locator_id;
  278.               END IF;
  279.  
  280.               v_Qty := LEAST(v_QtyStorage, CUR_BOM.ProductionQty * CUR_BOM.BOMQty - v_QtyAcumulated) ;
  281.               v_QtyStorage := v_QtyStorage - v_Qty;
  282.               v_QtyAcumulated := v_QtyAcumulated + v_Qty;
  283.               v_QtyOrder := ROUND(v_storage.QtyOrder*(v_Qty/v_storage.Qty), v_storage.stdprecision);
  284.               SELECT COALESCE(MAX(Line), 0) + 10 INTO v_Line
  285.               FROM M_PRODUCTIONLINE
  286.               WHERE M_ProductionPlan_ID=CUR_BOM.M_ProductionPlan_ID;
  287.               INSERT INTO M_PRODUCTIONLINE (
  288.                   M_ProductionLine_ID, M_ProductionPlan_ID, Line, AD_Client_ID,
  289.                   AD_Org_ID, IsActive, Created, CreatedBy,
  290.                   Updated, UpdatedBy, M_Product_ID, C_UOM_ID,
  291.                   MovementQty, M_Locator_ID,
  292.                   M_AttributeSetInstance_ID,
  293.                   M_Product_UOM_ID,
  294.                   QuantityOrder
  295.               ) VALUES (
  296.                   get_uuid(), CUR_BOM.M_ProductionPlan_ID, v_Line, CUR_BOM.Client_ID,
  297.                   CUR_BOM.Org_ID, 'Y', TO_DATE(NOW()), p_User,
  298.                   TO_DATE(NOW()), p_User, CUR_BOM.M_ProductBOM_ID, CUR_BOM.C_UOM_ID,
  299.                   -v_Qty, v_storage.M_Locator_ID,
  300.                   (CASE WHEN (SELECT ATTRSETVALUETYPE FROM M_PRODUCT WHERE M_PRODUCT_ID=CUR_BOM.M_ProductBOM_ID)='F' THEN NULL ELSE v_storage.M_AttributeSetInstance_ID END),
  301.                   v_storage.M_Product_UOM_ID,
  302.                   -v_QtyOrder
  303.               );
  304.               IF (v_QtyAcumulated >= CUR_BOM.ProductionQty*CUR_BOM.BOMQty) THEN
  305.                 EXIT;
  306.               END IF;
  307.               v_QtyStorage:=0;
  308.               v_ResultStr:='FetchingData';
  309.               FETCH CUR_STOCK INTO v_storage;
  310.               IF ( NOT FOUND ) THEN --OBTG:CUR_STOCK--
  311.                 CLOSE CUR_STOCK;
  312.                 CUR_STOCK_ISOPEN:=FALSE;
  313.                 EXIT;
  314.               END IF;
  315.               EXIT WHEN  NOT FOUND ; --OBTG:CUR_STOCK--
  316.               v_QtyStorage:=v_storage.Qty;
  317.             END LOOP;
  318.           END IF; --NEXT_PRODUCT
  319.         ELSE
  320.           SELECT COALESCE(MAX(Line), 0) + 10
  321.           INTO v_Line
  322.           FROM M_PRODUCTIONLINE
  323.           WHERE M_ProductionPlan_ID=CUR_BOM.M_ProductionPlan_ID;
  324.           INSERT INTO M_PRODUCTIONLINE (
  325.               M_ProductionLine_ID, M_ProductionPlan_ID, Line, AD_Client_ID,
  326.               AD_Org_ID, IsActive, Created, CreatedBy,
  327.               Updated, UpdatedBy, M_Product_ID, MovementQty,
  328.               M_Locator_ID, C_UOM_ID
  329.           ) VALUES (
  330.               get_uuid(), CUR_BOM.M_ProductionPlan_ID, v_Line, CUR_BOM.Client_ID,
  331.               CUR_BOM.Org_ID, 'Y', TO_DATE(NOW()), p_User,
  332.               TO_DATE(NOW()), p_User, CUR_BOM.M_ProductBOM_ID, -CUR_BOM.ProductionQty*CUR_BOM.BOMQty,
  333.               CUR_BOM.M_Locator_ID, CUR_BOM.C_UOM_ID
  334.           );
  335.         END IF;
  336.         v_Line:=v_Line;
  337.         IF (v_QtyAcumulated < CUR_BOM.BOMQTY*CUR_BOM.ProductionQty) THEN
  338.           IF (MustBeStocked='Y') THEN
  339.             v_Message := '@NotEnoughStocked@: ' || CUR_BOM.pname || ' ' || v_QtyAcumulated || ' / '|| CUR_BOM.BOMQTY*CUR_BOM.ProductionQty;
  340.             RAISE EXCEPTION '%', v_Message; --OBTG:-20000--
  341.           ELSE
  342.             IF (v_NegStockLocator IS NULL) THEN
  343.               -- Get Locator with negative Stock that belongs to the same Warehosue
  344.               SELECT m_warehouse_id
  345.               INTO v_NegStockWarehosue
  346.               FROM m_locator
  347.              WHERE m_locator_id = (SELECT m_locator_id
  348.                                    FROM M_PRODUCTIONPLAN
  349.                                    WHERE M_ProductionPlan_ID=CUR_BOM.M_ProductionPlan_ID);
  350.        
  351.               SELECT MIN(l.m_locator_id)
  352.               INTO v_NegStockLocator
  353.               FROM m_locator l
  354.               JOIN m_inventorystatus invs ON l.m_inventorystatus_id = invs.m_inventorystatus_id
  355.               WHERE l.m_warehouse_id = v_NegStockWarehosue
  356.               AND invs.overissue = 'Y'
  357.               AND l.isactive= 'Y'
  358.               AND priorityno = (SELECT MIN(priorityno)
  359.                                 FROM m_locator l
  360.                                 JOIN m_inventorystatus invs ON l.m_inventorystatus_id = invs.m_inventorystatus_id
  361.                                 WHERE l.m_warehouse_id = v_NegStockWarehosue
  362.                                 AND invs.overissue = 'Y'
  363.                                 AND l.isactive='Y');
  364.             END IF;        
  365.            
  366.             -- If there is a Storage Bin that allows negative stock and MustBeStocked is disabled and there is not enough stock,
  367.             -- pending quantity will be created for the same locator as production plan product, keeping a negative stock
  368.             IF (v_NegStockLocator IS NOT NULL) THEN  
  369.            
  370.               -- Check if exists a production line for this product with the same locator
  371.               SELECT COUNT(M_ProductionLine_ID)
  372.               INTO v_ProductionLineCount
  373.               FROM M_PRODUCTIONLINE
  374.               WHERE M_ProductionPlan_ID=CUR_BOM.M_ProductionPlan_ID
  375.               AND M_Product_ID=CUR_BOM.M_ProductBOM_ID
  376.               AND M_Locator_ID=v_NegStockLocator;
  377.  
  378.               -- If exists update it            
  379.               IF (v_ProductionLineCount <> 0) THEN
  380.                
  381.                 SELECT QuantityOrder / CASE WHEN (MovementQty <> 0) THEN MovementQty ELSE 1 END
  382.                 INTO v_QtyOrderRate
  383.                 FROM M_PRODUCTIONLINE
  384.                 WHERE M_ProductionPlan_ID=CUR_BOM.M_ProductionPlan_ID
  385.                 AND M_Product_ID=CUR_BOM.M_ProductBOM_ID
  386.                 AND M_Locator_ID=v_NegStockLocator;              
  387.                
  388.                 UPDATE M_PRODUCTIONLINE
  389.                 SET MovementQty = MovementQty - (CUR_BOM.BOMQTY*CUR_BOM.ProductionQty - v_QtyAcumulated),
  390.                 QuantityOrder = v_QtyOrderRate * (MovementQty - (CUR_BOM.BOMQTY*CUR_BOM.ProductionQty - v_QtyAcumulated))
  391.                 WHERE M_ProductionPlan_ID=CUR_BOM.M_ProductionPlan_ID
  392.                 AND M_Product_ID=CUR_BOM.M_ProductBOM_ID
  393.                 AND M_Locator_ID=v_NegStockLocator;
  394.  
  395.               -- If not exists, insert a new production line
  396.               ELSE
  397.                    
  398.                 SELECT COALESCE(MAX(Line), 0) + 10 INTO v_Line
  399.                 FROM M_PRODUCTIONLINE
  400.                 WHERE M_ProductionPlan_ID=CUR_BOM.M_ProductionPlan_ID;        
  401.                
  402.                 INSERT INTO M_PRODUCTIONLINE (
  403.                   M_ProductionLine_ID, M_ProductionPlan_ID, Line, AD_Client_ID,
  404.                   AD_Org_ID, IsActive, Created, CreatedBy,
  405.                   Updated, UpdatedBy, M_Product_ID, C_UOM_ID,
  406.                   MovementQty, M_Locator_ID
  407.               ) VALUES (
  408.                   get_uuid(), CUR_BOM.M_ProductionPlan_ID, v_Line, CUR_BOM.Client_ID,
  409.                   CUR_BOM.Org_ID, 'Y', TO_DATE(NOW()), p_User,
  410.                   TO_DATE(NOW()), p_User, CUR_BOM.M_ProductBOM_ID, CUR_BOM.C_UOM_ID,
  411.                   - (CUR_BOM.BOMQTY*CUR_BOM.ProductionQty - v_QtyAcumulated), v_NegStockLocator                  
  412.               );
  413.              
  414.               END IF;          
  415.             END IF;
  416.           END IF;  
  417.         END IF;
  418.         IF (CUR_BOM.ProductionQty <= 0) THEN
  419.           v_Message := '@NegativeBOMProductionQty@';
  420.           RAISE EXCEPTION '%', v_Message; --OBTG:-20000--
  421.         END IF;
  422.       END LOOP;
  423.       IF (CUR_STOCK_ISOPEN) THEN
  424.         CLOSE CUR_STOCK;
  425.         CUR_STOCK_ISOPEN := FALSE;
  426.       END IF;
  427.     END; --END OF DECLARE FOR BOM PRODUCTS INSERTION
  428.     -- While we have BOMs
  429.     LOOP
  430.       -- Are there non-stored BOMs to list details:8
  431.       v_ResultStr:='CreatingLine CheckBOM';
  432.       SELECT COUNT(*) INTO v_count
  433.       FROM M_PRODUCTIONLINE pl,
  434.         M_PRODUCT p,
  435.         M_PRODUCTIONPLAN pp
  436.       WHERE pl.M_Product_ID=p.M_Product_ID
  437.         AND pl.M_ProductionPlan_ID=pp.M_ProductionPlan_ID
  438.         AND pp.M_PRODUCTION_ID=v_Record_ID
  439.         AND pl.Line<>10 -- Origin Line
  440.         AND p.IsBOM='Y'
  441.         AND p.IsStocked='N';
  442.       -- Nothing to do
  443.       EXIT WHEN(v_count=0) ;
  444.       --
  445.       -- Resolve BOMs in ProductLine which are not stocked
  446.       FOR CUR_PLineBOM IN (
  447.           SELECT pl.M_ProductionLine_ID, pl.Line, pl.M_Product_ID, pl.MovementQty,
  448.               pp.M_LOCATOR_ID, pp.AD_Org_ID AS ORG_ID, pp.ProductionQty, pp.M_ProductionPlan_ID,
  449.               pp.AD_Client_ID AS Client_ID
  450.           FROM M_PRODUCTIONLINE pl, M_PRODUCT p, M_PRODUCTIONPLAN pp
  451.         WHERE pl.M_ProductionPlan_ID=pp.M_ProductionPlan_ID
  452.           AND pp.M_Production_ID=v_Record_ID
  453.           AND pl.M_Product_ID=p.M_Product_ID
  454.           AND pl.Line<>10 -- Origin Line
  455.           AND p.IsBOM='Y'
  456.           AND p.IsStocked='N'
  457.       ) LOOP
  458.         v_ResultStr:='CreatingLineBOM Resolution';
  459.         v_Line:=CUR_PLineBOM.Line;
  460.         -- Resolve BOM Line in product line
  461.         FOR CUR_BOM_PRODUCT IN (
  462.             SELECT pb.*, p.C_UOM_ID, p.IsStocked
  463.             FROM M_PRODUCT_BOM pb, M_PRODUCT p
  464.             WHERE pb.M_ProductBOM_ID=p.M_Product_ID
  465.               AND pb.M_Product_ID=CUR_PLineBOM.M_Product_ID
  466.               AND pb.isactive='Y'
  467.             ORDER BY pb.M_PRODUCTBOM_ID, pb.Line
  468.         ) LOOP
  469.           v_ResultStr:='CreatingLine Products2';
  470.           SELECT COALESCE(MAX(Line), 0) + 10 INTO v_Line
  471.           FROM M_PRODUCTIONLINE
  472.           WHERE M_ProductionPlan_ID=CUR_PLineBOM.M_ProductionPlan_ID;
  473.           INSERT INTO M_PRODUCTIONLINE (
  474.               M_ProductionLine_ID, M_ProductionPlan_ID, Line, AD_Client_ID,
  475.               AD_Org_ID, IsActive, Created, CreatedBy,
  476.               Updated, UpdatedBy, M_Product_ID, MovementQty,
  477.               M_Locator_ID, C_UOM_ID
  478.           ) VALUES (
  479.               get_uuid(), CUR_PLineBOM.M_ProductionPlan_ID, v_Line, CUR_PLineBOM.Client_ID,
  480.               CUR_PLineBOM.Org_ID, 'Y', TO_DATE(NOW()), p_User,
  481.               TO_DATE(NOW()), p_User, CUR_BOM_PRODUCT.M_ProductBOM_ID, CUR_PLineBOM.MovementQty*CUR_BOM_PRODUCT.BOMQty,
  482.               CUR_PLineBOM.M_Locator_ID, CUR_BOM_PRODUCT.C_UOM_ID
  483.           );
  484.         END LOOP;
  485.         -- Delete BOM line
  486.         DELETE
  487.         FROM M_PRODUCTIONLINE
  488.         WHERE M_ProductionLine_ID=CUR_PLineBOM.M_ProductionLine_ID;
  489.       END LOOP;
  490.     END LOOP; -- While we have BOMs
  491.     -- Modifying locator to have sufficient stock
  492.     -- Indicate that it is Created
  493.     UPDATE M_PRODUCTION  SET IsCreated='Y',Updated=TO_DATE(NOW()),UpdatedBy=p_User  WHERE M_Production_ID=v_Record_ID;
  494.   /**************************************************************************
  495.   * Post Lines
  496.   */
  497.   ELSE
  498.     v_ResultStr:='CheckingRestrictions';
  499.     SELECT COUNT(*) INTO v_Count
  500.     FROM M_PRODUCTIONPLAN PP, M_PRODUCTIONLINE PL, M_PRODUCT P
  501.     WHERE PL.M_PRODUCT_ID=P.M_PRODUCT_ID
  502.       AND P.M_ATTRIBUTESET_ID IS NOT NULL
  503.       AND (P.ATTRSETVALUETYPE IS NULL OR P.ATTRSETVALUETYPE <> 'F')
  504.       AND (SELECT ISONEATTRSETVALREQUIRED FROM M_ATTRIBUTESET WHERE M_ATTRIBUTESET_ID = P.M_ATTRIBUTESET_ID) = 'Y'
  505.       AND COALESCE(PL.M_ATTRIBUTESETINSTANCE_ID, '0') = '0'
  506.       AND PL.M_ProductionPlan_ID=pp.M_ProductionPlan_ID
  507.       AND pp.M_Production_ID=v_Record_ID;
  508.     IF (v_Count <> 0) THEN
  509.       SELECT MAX(P.name) INTO v_Product_Name
  510.       FROM M_PRODUCTIONPLAN PP, M_PRODUCTIONLINE PL, M_PRODUCT P
  511.       WHERE PL.M_PRODUCT_ID=P.M_PRODUCT_ID
  512.         AND P.M_ATTRIBUTESET_ID IS NOT NULL
  513.         AND (P.ATTRSETVALUETYPE IS NULL OR P.ATTRSETVALUETYPE <> 'F')
  514.         AND (SELECT ISONEATTRSETVALREQUIRED FROM M_ATTRIBUTESET WHERE M_ATTRIBUTESET_ID = P.M_ATTRIBUTESET_ID) = 'Y'
  515.         AND COALESCE(PL.M_ATTRIBUTESETINSTANCE_ID, '0') = '0'
  516.         AND PL.M_ProductionPlan_ID=pp.M_ProductionPlan_ID
  517.         AND pp.M_Production_ID=v_Record_ID;
  518.       v_Message:='@Product@'||' "' ||v_Product_Name ||'" ' || '@ProductWithoutAttributeSet@';
  519.       RAISE EXCEPTION '%', v_Message; --OBTG:-20000--
  520.     END IF;
  521.  
  522.     SELECT COUNT(M_ProductionPlan_ID)
  523.     INTO v_count
  524.     FROM M_ProductionPlan pp
  525.     WHERE pp.M_Production_ID = v_Record_ID
  526.     AND NOT EXISTS (SELECT 1 FROM M_ProductionLine WHERE M_ProductionPlan_ID = pp.M_ProductionPlan_ID AND MovementQty > 0);
  527.  
  528.     v_Message := NULL;      
  529.     IF(v_count <> 0) THEN
  530.       FOR CUR_ProductionPlan IN (
  531.     SELECT DISTINCT(pp.line)
  532.     FROM M_ProductionPlan pp
  533.     WHERE pp.M_Production_ID = v_Record_ID
  534.     AND NOT EXISTS (SELECT 1 FROM M_ProductionLine WHERE M_ProductionPlan_ID = pp.M_ProductionPlan_ID AND MovementQty > 0)
  535.     ORDER BY Line
  536.         )
  537.       LOOP
  538.         IF v_Message IS NULL THEN
  539.           v_Message := CUR_ProductionPlan.line;
  540.         ELSE
  541.       v_Message := v_Message || ', ' || CUR_ProductionPlan.line;
  542.     END IF;
  543.       END LOOP;
  544.       v_Message := '@ProducedProductWithNegativeQty@' || ' @ReferProductionPlanLines@' || ': ' || v_Message;
  545.       RAISE EXCEPTION '%', v_Message; --OBTG:-20000--
  546.     END IF;  
  547.  
  548.     SELECT COUNT(M_ProductionPlan_ID)
  549.     INTO v_count
  550.     FROM M_ProductionPlan pp
  551.     WHERE pp.M_Production_ID = v_Record_ID
  552.     AND (SELECT COUNT(M_ProductionLine_ID) FROM M_ProductionLine WHERE M_ProductionPlan_ID = pp.M_ProductionPlan_ID AND movementQty > 0) > 1;
  553.    
  554.     IF (v_count <> 0) THEN
  555.       FOR CUR_ProductionPlan IN (
  556.     SELECT DISTINCT(pp.line)
  557.     FROM M_ProductionPlan pp
  558.     WHERE pp.M_Production_ID = v_Record_ID
  559.     AND (SELECT COUNT(M_ProductionLine_ID) FROM M_ProductionLine WHERE M_ProductionPlan_ID = pp.M_ProductionPlan_ID AND movementQty > 0) > 1
  560.     ORDER BY Line
  561.       )
  562.       LOOP
  563.         IF v_Message IS NULL THEN
  564.           v_Message := CUR_ProductionPlan.line;
  565.         ELSE
  566.       v_Message := v_Message || ', ' || CUR_ProductionPlan.line;
  567.     END IF;
  568.       END LOOP;
  569.       v_Message:= '@ConsumedProductWithPostiveQty@' || ' @ReferProductionPlanLines@' || ': ' || v_Message;
  570.       RAISE EXCEPTION '%', v_Message; --OBTG:-20000--
  571.     END IF;
  572.  
  573.     DECLARE
  574.         v_Message_ProductionRun VARCHAR(2000);
  575.         v_Message_ProductLine VARCHAR(2000);
  576.         BEGIN
  577.           FOR CUR_ProductionPlan IN
  578.             (SELECT pp.Line, pp.M_PRODUCTIONPLAN_ID
  579.             FROM M_PRODUCTION p, M_PRODUCTIONPLAN pp
  580.             WHERE p.M_Production_ID=pp.M_Production_ID
  581.             AND pp.M_Production_ID=v_Record_ID
  582.             ORDER BY pp.Line)
  583.           LOOP
  584.             FOR CUR_PL_Post IN
  585.               (SELECT pl.Line
  586.               FROM M_PRODUCTIONLINE pl, M_PRODUCT pr
  587.               WHERE Cur_ProductionPlan.M_ProductionPlan_ID=pl.M_ProductionPlan_ID
  588.               AND pl.M_PRODUCT_ID=pr.M_PRODUCT_ID
  589.               AND pr.ISACTIVE='N'
  590.               ORDER BY pl.Line)
  591.             LOOP
  592.               v_Message_ProductLine := COALESCE(v_Message_ProductLine, '') || CUR_PL_Post.line || ', ';
  593.             END LOOP;
  594.             IF (v_Message_ProductLine IS NOT NULL) THEN
  595.               v_Message_ProductionRun := COALESCE(v_Message_ProductionRun, '') || '@ProductionRunLine@' || Cur_ProductionPlan.line || ' @ProductLine@' || v_Message_ProductLine;
  596.               v_Message_ProductLine := NULL;
  597.             END IF;
  598.           END LOOP;
  599.           IF (v_Message_ProductionRun IS NOT NULL) THEN
  600.             RAISE EXCEPTION '%', v_Message_ProductionRun||'@InActiveProducts@'; --OBTG:-20000--
  601.           END IF;
  602.         END;
  603.    
  604.     SELECT COUNT(*) INTO v_count
  605.     FROM dual
  606.     WHERE EXISTS (
  607.         SELECT 1
  608.         FROM m_productionplan pp
  609.             JOIN m_productionline pl ON pp.m_productionplan_id = pl.m_productionplan_id
  610.             JOIN m_product p ON pl.m_product_id = p.m_product_id
  611.         WHERE pp.m_production_id = v_record_id
  612.           AND p.isgeneric = 'Y');
  613.     IF (v_count > 0) THEN
  614.       SELECT MAX(p.name) INTO v_product_name
  615.       FROM m_productionplan pp
  616.           JOIN m_productionline pl ON pp.m_productionplan_id = pl.m_productionplan_id
  617.           JOIN m_product p ON pl.m_product_id = p.m_product_id
  618.       WHERE pp.m_production_id = v_record_id
  619.         AND p.isgeneric = 'Y';
  620.       RAISE EXCEPTION '%', '@CannotUseGenericProduct@ ' || v_product_Name; --OBTG:-20000--
  621.     END IF;
  622.  
  623.     -- All Production Lines
  624.     FOR CUR_PL_Post IN (
  625.         SELECT pl.M_ProductionLine_ID, pl.AD_Client_ID, pl.AD_Org_ID, p.MovementDate,
  626.             pl.M_Product_ID, pl.M_AttributeSetInstance_ID, pl.MovementQty, pl.M_Locator_ID,
  627.             pl.M_Product_UOM_ID, pl.QuantityOrder, pl.C_UOM_ID, pl.LINE
  628.         FROM M_PRODUCTION p, M_PRODUCTIONLINE pl, M_PRODUCTIONPLAN pp, M_PRODUCT pro
  629.         WHERE p.M_Production_ID=pp.M_Production_ID
  630.           AND pp.M_ProductionPlan_ID=pl.M_ProductionPlan_ID
  631.           AND pl.M_PRODUCT_ID = pro.M_PRODUCT_ID
  632.           AND pro.ISSTOCKED = 'Y'
  633.           AND pp.M_Production_ID=v_Record_ID
  634.         ORDER BY pp.Line, pl.Line
  635.     ) LOOP
  636.       -- M_ProductionLine_ID, AD_Client_ID, AD_Org_ID, MovementDate, M_Product_ID, MovementQty, M_Locator_ID
  637.       -- DBMS_OUTPUT.PUT_LINE('ProductionLine=' || pl.M_ProductionLine_ID);
  638.       -- DBMS_OUTPUT.PUT_LINE('  Qty=' || pl.MovementQty || ', OnHand=' || M_BOM_Qty_OnHand(pl.M_Product_ID, NULL, pl.M_Locator_ID));
  639.       -- Check Stock levels for reductions
  640.       IF (CUR_PL_Post.MovementQty<0 AND MustBeStocked<>'N' AND M_BOM_Qty_OnHand(CUR_PL_Post.M_Product_ID, NULL, CUR_PL_Post.M_Locator_ID) +CUR_PL_Post.MovementQty<0) THEN
  641.         SELECT '@NotEnoughStocked@: ' || Name INTO v_Message
  642.         FROM M_PRODUCT
  643.         WHERE M_Product_ID=CUR_PL_Post.M_Product_ID;
  644.         RAISE EXCEPTION '%', v_Message; --OBTG:-20000--
  645.       END IF;
  646.       -- Create Transaction Entry
  647.       v_ResultStr:='CreateTransaction';
  648.       INSERT INTO M_TRANSACTION (
  649.           M_Transaction_ID, M_ProductionLine_ID, AD_Client_ID, AD_Org_ID,
  650.           IsActive, Created, CreatedBy, Updated,
  651.           UpdatedBy, MovementType, M_Locator_ID, M_Product_ID,
  652.           M_AttributeSetInstance_ID,
  653.           MovementDate, MovementQty, M_Product_UOM_ID, QuantityOrder,
  654.           C_UOM_ID
  655.       ) VALUES (
  656.           get_uuid(), CUR_PL_Post.M_ProductionLine_ID, CUR_PL_Post.AD_Client_ID, CUR_PL_Post.AD_Org_ID,
  657.            'Y', TO_DATE(NOW()), p_User, TO_DATE(NOW()),
  658.           p_User, 'P+', CUR_PL_Post.M_Locator_ID, CUR_PL_Post.M_Product_ID,
  659.           COALESCE(CUR_PL_Post.M_AttributeSetInstance_ID, '0'), -- not distinguishing between assemby/disassembly
  660.           CUR_PL_Post.MovementDate, CUR_PL_Post.MovementQty, CUR_PL_Post.M_Product_UOM_ID, CUR_PL_Post.QuantityOrder,
  661.           CUR_PL_Post.C_UOM_ID
  662.       );
  663.       SELECT * INTO  v_Result, v_Message FROM M_Check_Stock(CUR_PL_Post.M_Product_ID, v_Client_ID, v_Org_ID, CUR_PL_Post.M_Locator_ID) ;
  664.       IF (v_Result = 0) THEN
  665.         v_Message:=v_Message || ' @Inline@ ' || CUR_PL_Post.line;
  666.         RAISE EXCEPTION '%', v_Message; --OBTG:-20000--
  667.       END IF;
  668.     END LOOP;
  669.     -- Indicate that we are done
  670.     UPDATE M_PRODUCTION
  671.     SET Processed='Y',
  672.         updated=TO_DATE(NOW()),
  673.         updatedby=p_User
  674.     WHERE M_Production_ID=v_Record_ID;
  675.   END IF;
  676.   ---- <<FINISH_PROCESS>>
  677.   --  Update AD_PInstance
  678.   RAISE NOTICE '%','Updating PInstance - Finished ' || v_Message ;
  679.   PERFORM AD_UPDATE_PINSTANCE(PInstance_ID, NULL, 'N', v_Result, v_Message) ;
  680.   RETURN;
  681. END; --BODY
  682. EXCEPTION
  683.   WHEN OTHERS THEN
  684.     RAISE NOTICE '%',v_ResultStr ;
  685.     v_ResultStr:= '@ERROR=' || SQLERRM;
  686.     RAISE NOTICE '%',v_ResultStr ;
  687.     -- ROLLBACK;
  688.     PERFORM AD_UPDATE_PINSTANCE(PInstance_ID, NULL, 'N', 0, v_ResultStr) ;
  689.     RETURN;
  690. END ; $function$
  691. ;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement