diff --git a/db/ddlutils/oracle/functions/BOM_PriceLimit.sql b/db/ddlutils/oracle/functions/BOM_PriceLimit.sql index c7f124c69c..4294c57bbc 100644 --- a/db/ddlutils/oracle/functions/BOM_PriceLimit.sql +++ b/db/ddlutils/oracle/functions/BOM_PriceLimit.sql @@ -1,5 +1,5 @@ -CREATE OR REPLACE FUNCTION bomPriceLimit -( +CREATE OR REPLACE FUNCTION Bompricelimit +( Product_ID IN NUMBER, PriceList_Version_ID IN NUMBER ) @@ -22,27 +22,32 @@ AS v_ProductPrice NUMBER; -- Get BOM Product info CURSOR CUR_BOM IS - SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM - FROM M_Product_BOM b, M_Product p + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM + FROM M_PRODUCT_BOM b, M_PRODUCT p WHERE b.M_ProductBOM_ID=p.M_Product_ID - AND b.M_Product_ID=Product_ID; + AND b.M_Product_ID=Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = Product_ID; -- BEGIN -- Try to get price from PriceList directly SELECT COALESCE (SUM(PriceLimit), 0) INTO v_Price - FROM M_ProductPrice + FROM M_PRODUCTPRICE WHERE M_PriceList_Version_ID=PriceList_Version_ID AND M_Product_ID=Product_ID; -- DBMS_OUTPUT.PUT_LINE('Price=' || v_Price); -- No Price - Check if BOM IF (v_Price = 0) THEN FOR bom IN CUR_BOM LOOP - v_ProductPrice := bomPriceLimit (bom.M_ProductBOM_ID, PriceList_Version_ID); + v_ProductPrice := Bompricelimit (bom.M_ProductBOM_ID, PriceList_Version_ID); v_Price := v_Price + (bom.BOMQty * v_ProductPrice); - END LOOP; + END LOOP; END IF; -- RETURN v_Price; -END bomPriceLimit; -/ \ No newline at end of file +END Bompricelimit; +/ diff --git a/db/ddlutils/oracle/functions/BOM_PriceList.sql b/db/ddlutils/oracle/functions/BOM_PriceList.sql index 17f42e6a09..0de404cc7e 100644 --- a/db/ddlutils/oracle/functions/BOM_PriceList.sql +++ b/db/ddlutils/oracle/functions/BOM_PriceList.sql @@ -1,5 +1,5 @@ -CREATE OR REPLACE FUNCTION bomPriceList -( +CREATE OR REPLACE FUNCTION Bompricelist +( Product_ID IN NUMBER, PriceList_Version_ID IN NUMBER ) @@ -22,28 +22,33 @@ AS v_ProductPrice NUMBER; -- Get BOM Product info CURSOR CUR_BOM IS - SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM - FROM M_Product_BOM b, M_Product p + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM + FROM M_PRODUCT_BOM b, M_PRODUCT p WHERE b.M_ProductBOM_ID=p.M_Product_ID - AND b.M_Product_ID=Product_ID; + AND b.M_Product_ID=Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = Product_ID; -- BEGIN -- Try to get price from pricelist directly SELECT COALESCE (SUM(PriceList), 0) INTO v_Price - FROM M_ProductPrice + FROM M_PRODUCTPRICE WHERE M_PriceList_Version_ID=PriceList_Version_ID AND M_Product_ID=Product_ID; -- DBMS_OUTPUT.PUT_LINE('Price=' || Price); -- No Price - Check if BOM IF (v_Price = 0) THEN FOR bom IN CUR_BOM LOOP - v_ProductPrice := bomPriceList (bom.M_ProductBOM_ID, PriceList_Version_ID); + v_ProductPrice := Bompricelist (bom.M_ProductBOM_ID, PriceList_Version_ID); v_Price := v_Price + (bom.BOMQty * v_ProductPrice); -- DBMS_OUTPUT.PUT_LINE('Qry=' || bom.BOMQty || ' @ ' || v_ProductPrice || ', Price=' || v_Price); END LOOP; -- BOM END IF; -- RETURN v_Price; -END bomPriceList; -/ \ No newline at end of file +END Bompricelist; +/ diff --git a/db/ddlutils/oracle/functions/BOM_PriceStd.sql b/db/ddlutils/oracle/functions/BOM_PriceStd.sql index fde4309c6d..adf8662b68 100644 --- a/db/ddlutils/oracle/functions/BOM_PriceStd.sql +++ b/db/ddlutils/oracle/functions/BOM_PriceStd.sql @@ -1,5 +1,5 @@ -CREATE OR REPLACE FUNCTION bomPriceStd -( +CREATE OR REPLACE FUNCTION Bompricestd +( Product_ID IN NUMBER, PriceList_Version_ID IN NUMBER ) @@ -22,28 +22,33 @@ AS v_ProductPrice NUMBER; -- Get BOM Product info CURSOR CUR_BOM IS - SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM - FROM M_Product_BOM b, M_Product p + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM + FROM M_PRODUCT_BOM b, M_PRODUCT p WHERE b.M_ProductBOM_ID=p.M_Product_ID - AND b.M_Product_ID=Product_ID; + AND b.M_Product_ID=Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = Product_ID; -- BEGIN -- Try to get price from pricelist directly SELECT COALESCE(SUM(PriceStd), 0) INTO v_Price - FROM M_ProductPrice + FROM M_PRODUCTPRICE WHERE M_PriceList_Version_ID=PriceList_Version_ID AND M_Product_ID=Product_ID; -- DBMS_OUTPUT.PUT_LINE('Price=' || v_Price); -- No Price - Check if BOM IF (v_Price = 0) THEN FOR bom IN CUR_BOM LOOP - v_ProductPrice := bomPriceStd (bom.M_ProductBOM_ID, PriceList_Version_ID); + v_ProductPrice := Bompricestd (bom.M_ProductBOM_ID, PriceList_Version_ID); v_Price := v_Price + (bom.BOMQty * v_ProductPrice); -- DBMS_OUTPUT.PUT_LINE('Price=' || v_Price); END LOOP; -- BOM END IF; -- RETURN v_Price; -END bomPriceStd; -/ \ No newline at end of file +END Bompricestd; +/ diff --git a/db/ddlutils/oracle/functions/BOM_Qty_AvailableASI.sql b/db/ddlutils/oracle/functions/BOM_Qty_AvailableASI.sql new file mode 100644 index 0000000000..f7de6896a3 --- /dev/null +++ b/db/ddlutils/oracle/functions/BOM_Qty_AvailableASI.sql @@ -0,0 +1,22 @@ +CREATE OR REPLACE FUNCTION BomqtyavailableASI +( + Product_ID IN NUMBER, + AttributeSetInstance_ID IN NUMBER, + Warehouse_ID IN NUMBER, + Locator_ID IN NUMBER -- Only used, if warehouse is null +) +RETURN NUMBER +/****************************************************************************** + * ** Compiere Product ** Copyright (c) 1999-2001 Accorto, Inc. USA + * Open Source Software Provided "AS IS" without warranty or liability + * When you use any parts (changed or unchanged), add "Powered by Compiere" to + * your product name; See license details http://www.compiere.org/license.html + ****************************************************************************** + * Return quantity available for BOM ASI + */ +AS +BEGIN + RETURN BomqtyonhandASI(Product_ID, AttributeSetInstance_ID, Warehouse_ID, Locator_ID) + - BomqtyreservedASI(Product_ID, AttributeSetInstance_ID, Warehouse_ID, Locator_ID); +END BomqtyavailableASI; +/ diff --git a/db/ddlutils/oracle/functions/BOM_Qty_OnHand.sql b/db/ddlutils/oracle/functions/BOM_Qty_OnHand.sql index a741dfc695..9c3fe43b69 100644 --- a/db/ddlutils/oracle/functions/BOM_Qty_OnHand.sql +++ b/db/ddlutils/oracle/functions/BOM_Qty_OnHand.sql @@ -1,5 +1,5 @@ -CREATE OR REPLACE FUNCTION bomQtyOnHand -( +CREATE OR REPLACE FUNCTION Bomqtyonhand +( Product_ID IN NUMBER, Warehouse_ID IN NUMBER, Locator_ID IN NUMBER -- Only used, if warehouse is null @@ -23,10 +23,15 @@ AS StdPrecision NUMBER; -- Get BOM Product info CURSOR CUR_BOM IS - SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType - FROM M_Product_BOM b, M_Product p + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType + FROM M_PRODUCT_BOM b, M_PRODUCT p WHERE b.M_ProductBOM_ID=p.M_Product_ID - AND b.M_Product_ID=Product_ID; + AND b.M_Product_ID=p_Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM , p.IsStocked, p.ProductType + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = Product_ID; -- BEGIN -- Check Parameters @@ -36,7 +41,7 @@ BEGIN RETURN 0; ELSE SELECT SUM(M_Warehouse_ID) INTO myWarehouse_ID - FROM M_Locator + FROM M_LOCATOR WHERE M_Locator_ID=Locator_ID; END IF; END IF; @@ -49,7 +54,7 @@ BEGIN BEGIN SELECT IsBOM, ProductType, IsStocked INTO IsBOM, ProductType, IsStocked - FROM M_Product + FROM M_PRODUCT WHERE M_Product_ID=Product_ID; -- EXCEPTION -- not found @@ -64,9 +69,9 @@ BEGIN -- Get ProductQty SELECT NVL(SUM(QtyOnHand), 0) INTO ProductQty - FROM M_Storage s + FROM M_STORAGE s WHERE M_Product_ID=Product_ID - AND EXISTS (SELECT * FROM M_Locator l WHERE s.M_Locator_ID=l.M_Locator_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID AND l.M_Warehouse_ID=myWarehouse_ID); -- -- DBMS_OUTPUT.PUT_LINE('Qty=' || ProductQty); @@ -81,14 +86,14 @@ BEGIN -- Get ProductQty SELECT NVL(SUM(QtyOnHand), 0) INTO ProductQty - FROM M_Storage s + FROM M_STORAGE s WHERE M_Product_ID=bom.M_ProductBOM_ID - AND EXISTS (SELECT * FROM M_Locator l WHERE s.M_Locator_ID=l.M_Locator_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID AND l.M_Warehouse_ID=myWarehouse_ID); -- Get Rounding Precision SELECT NVL(MAX(u.StdPrecision), 0) INTO StdPrecision - FROM C_UOM u, M_Product p + FROM C_UOM u, M_PRODUCT p WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=bom.M_ProductBOM_ID; -- How much can we make with this product ProductQty := ROUND (ProductQty/bom.BOMQty, StdPrecision); @@ -98,7 +103,7 @@ BEGIN END IF; -- Another BOM ELSIF (bom.IsBOM = 'Y') THEN - ProductQty := bomQtyOnHand (bom.M_ProductBOM_ID, myWarehouse_ID, Locator_ID); + ProductQty := Bomqtyonhand (bom.M_ProductBOM_ID, myWarehouse_ID, Locator_ID); -- How much can we make overall IF (ProductQty < Quantity) THEN Quantity := ProductQty; @@ -110,11 +115,11 @@ BEGIN -- Get Rounding Precision for Product SELECT NVL(MAX(u.StdPrecision), 0) INTO StdPrecision - FROM C_UOM u, M_Product p + FROM C_UOM u, M_PRODUCT p WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=Product_ID; -- RETURN ROUND (Quantity, StdPrecision); END IF; RETURN 0; -END bomQtyOnHand; -/ \ No newline at end of file +END Bomqtyonhand; +/ diff --git a/db/ddlutils/oracle/functions/BOM_Qty_OnHandASI.sql b/db/ddlutils/oracle/functions/BOM_Qty_OnHandASI.sql new file mode 100644 index 0000000000..948631da7b --- /dev/null +++ b/db/ddlutils/oracle/functions/BOM_Qty_OnHandASI.sql @@ -0,0 +1,128 @@ +CREATE OR REPLACE FUNCTION BomqtyonhandASI +( + Product_ID IN NUMBER, + AttributeSetInstance_ID IN NUMBER, + Warehouse_ID IN NUMBER, + Locator_ID IN NUMBER -- Only used, if warehouse is null +) +RETURN NUMBER +/****************************************************************************** + * ** Compiere Product ** Copyright (c) 1999-2001 Accorto, Inc. USA + * Open Source Software Provided "AS IS" without warranty or liability + * When you use any parts (changed or unchanged), add "Powered by Compiere" to + * your product name; See license details http://www.compiere.org/license.html + ****************************************************************************** + * Return quantity on hand for BOM + */ +AS + myWarehouse_ID NUMBER; + Quantity NUMBER := 99999; -- unlimited + IsBOM CHAR(1); + IsStocked CHAR(1); + ProductType CHAR(1); + ProductQty NUMBER; + StdPrecision NUMBER; + -- Get BOM Product info + CURSOR CUR_BOM IS + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType + FROM M_PRODUCT_BOM b, M_PRODUCT p + WHERE b.M_ProductBOM_ID=p.M_Product_ID + AND b.M_Product_ID=p_Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM , p.IsStocked, p.ProductType + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = Product_ID; + -- +BEGIN + -- Check Parameters + myWarehouse_ID := Warehouse_ID; + IF (myWarehouse_ID IS NULL) THEN + IF (Locator_ID IS NULL) THEN + RETURN 0; + ELSE + SELECT SUM(M_Warehouse_ID) INTO myWarehouse_ID + FROM M_LOCATOR + WHERE M_Locator_ID=Locator_ID; + END IF; + END IF; + IF (myWarehouse_ID IS NULL) THEN + RETURN 0; + END IF; +-- DBMS_OUTPUT.PUT_LINE('Warehouse=' || myWarehouse_ID); + + -- Check, if product exists and if it is stocked + BEGIN + SELECT IsBOM, ProductType, IsStocked + INTO IsBOM, ProductType, IsStocked + FROM M_PRODUCT + WHERE M_Product_ID=Product_ID; + -- + EXCEPTION -- not found + WHEN OTHERS THEN + RETURN 0; + END; + -- Unimited capacity if no item + IF (IsBOM='N' AND (ProductType<>'I' OR IsStocked='N')) THEN + RETURN Quantity; + -- Stocked item + ELSIF (IsStocked='Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyOnHand), 0) + INTO ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=Product_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=myWarehouse_ID) + AND (s.M_AttributeSetInstance_ID = AttributeSetInstance_ID OR NVL(AttributeSetInstance_ID,0) = 0); + -- + -- DBMS_OUTPUT.PUT_LINE('Qty=' || ProductQty); + RETURN ProductQty; + END IF; + + -- Go though BOM +-- DBMS_OUTPUT.PUT_LINE('BOM'); + FOR bom IN CUR_BOM LOOP + -- Stocked Items "leaf node" + IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyOnHand), 0) + INTO ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=bom.M_ProductBOM_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=myWarehouse_ID) + AND (s.M_AttributeSetInstance_ID = AttributeSetInstance_ID OR NVL(AttributeSetInstance_ID,0) = 0); + -- Get Rounding Precision + SELECT NVL(MAX(u.StdPrecision), 0) + INTO StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=bom.M_ProductBOM_ID; + -- How much can we make with this product + ProductQty := ROUND (ProductQty/bom.BOMQty, StdPrecision); + -- How much can we make overall + IF (ProductQty < Quantity) THEN + Quantity := ProductQty; + END IF; + -- Another BOM + ELSIF (bom.IsBOM = 'Y') THEN + ProductQty := BomqtyonhandASI (bom.M_ProductBOM_ID, AttributeSetInstance_ID, myWarehouse_ID, Locator_ID); + -- How much can we make overall + IF (ProductQty < Quantity) THEN + Quantity := ProductQty; + END IF; + END IF; + END LOOP; -- BOM + + IF (Quantity > 0) THEN + -- Get Rounding Precision for Product + SELECT NVL(MAX(u.StdPrecision), 0) + INTO StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=Product_ID; + -- + RETURN ROUND (Quantity, StdPrecision); + END IF; + RETURN 0; +END BomqtyonhandASI; +/ diff --git a/db/ddlutils/oracle/functions/BOM_Qty_Ordered.sql b/db/ddlutils/oracle/functions/BOM_Qty_Ordered.sql index 292cd936a5..540aea2535 100644 --- a/db/ddlutils/oracle/functions/BOM_Qty_Ordered.sql +++ b/db/ddlutils/oracle/functions/BOM_Qty_Ordered.sql @@ -1,4 +1,4 @@ -CREATE OR REPLACE FUNCTION bomQtyOrdered +CREATE OR REPLACE FUNCTION Bomqtyordered ( p_Product_ID IN NUMBER, p_Warehouse_ID IN NUMBER, @@ -23,10 +23,15 @@ AS v_StdPrecision NUMBER; -- Get BOM Product info CURSOR CUR_BOM IS - SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType - FROM M_Product_BOM b, M_Product p + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType + FROM M_PRODUCT_BOM b, M_PRODUCT p WHERE b.M_ProductBOM_ID=p.M_Product_ID - AND b.M_Product_ID=p_Product_ID; + AND b.M_Product_ID=p_Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM , p.IsStocked, p.ProductType + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = p_Product_ID; -- BEGIN -- Check Parameters @@ -36,7 +41,7 @@ BEGIN RETURN 0; ELSE SELECT MAX(M_Warehouse_ID) INTO v_Warehouse_ID - FROM M_Locator + FROM M_LOCATOR WHERE M_Locator_ID=p_Locator_ID; END IF; END IF; @@ -49,7 +54,7 @@ BEGIN BEGIN SELECT IsBOM, ProductType, IsStocked INTO v_IsBOM, v_ProductType, v_IsStocked - FROM M_Product + FROM M_PRODUCT WHERE M_Product_ID=p_Product_ID; -- EXCEPTION -- not found @@ -65,9 +70,9 @@ BEGIN -- Get ProductQty SELECT NVL(SUM(QtyOrdered), 0) INTO v_ProductQty - FROM M_Storage s + FROM M_STORAGE s WHERE M_Product_ID=p_Product_ID - AND EXISTS (SELECT * FROM M_Locator l WHERE s.M_Locator_ID=l.M_Locator_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID AND l.M_Warehouse_ID=v_Warehouse_ID); -- RETURN v_ProductQty; @@ -81,14 +86,14 @@ BEGIN -- Get ProductQty SELECT NVL(SUM(QtyOrdered), 0) INTO v_ProductQty - FROM M_Storage s + FROM M_STORAGE s WHERE M_Product_ID=bom.M_ProductBOM_ID - AND EXISTS (SELECT * FROM M_Locator l WHERE s.M_Locator_ID=l.M_Locator_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID AND l.M_Warehouse_ID=v_Warehouse_ID); -- Get Rounding Precision SELECT NVL(MAX(u.StdPrecision), 0) INTO v_StdPrecision - FROM C_UOM u, M_Product p + FROM C_UOM u, M_PRODUCT p WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=bom.M_ProductBOM_ID; -- How much can we make with this product v_ProductQty := ROUND (v_ProductQty/bom.BOMQty, v_StdPrecision); @@ -98,7 +103,7 @@ BEGIN END IF; -- Another BOM ELSIF (bom.IsBOM = 'Y') THEN - v_ProductQty := bomQtyOrdered (bom.M_ProductBOM_ID, v_Warehouse_ID, p_Locator_ID); + v_ProductQty := Bomqtyordered (bom.M_ProductBOM_ID, v_Warehouse_ID, p_Locator_ID); -- How much can we make overall IF (v_ProductQty < v_Quantity) THEN v_Quantity := v_ProductQty; @@ -115,12 +120,12 @@ BEGIN -- Get Rounding Precision for Product SELECT NVL(MAX(u.StdPrecision), 0) INTO v_StdPrecision - FROM C_UOM u, M_Product p + FROM C_UOM u, M_PRODUCT p WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=p_Product_ID; -- RETURN ROUND (v_Quantity, v_StdPrecision); END IF; -- RETURN 0; -END bomQtyOrdered; -/ \ No newline at end of file +END Bomqtyordered; +/ diff --git a/db/ddlutils/oracle/functions/BOM_Qty_OrderedASI.sql b/db/ddlutils/oracle/functions/BOM_Qty_OrderedASI.sql new file mode 100644 index 0000000000..a727661762 --- /dev/null +++ b/db/ddlutils/oracle/functions/BOM_Qty_OrderedASI.sql @@ -0,0 +1,134 @@ +CREATE OR REPLACE FUNCTION BomqtyorderedASI +( + p_Product_ID IN NUMBER, + AttributeSetInstance_ID IN NUMBER, + p_Warehouse_ID IN NUMBER, + p_Locator_ID IN NUMBER -- Only used, if warehouse is null +) +RETURN NUMBER +/****************************************************************************** + * ** Compiere Product ** Copyright (c) 1999-2001 Accorto, Inc. USA + * Open Source Software Provided "AS IS" without warranty or liability + * When you use any parts (changed or unchanged), add "Powered by Compiere" to + * your product name; See license details http://www.compiere.org/license.html + ****************************************************************************** + * Return quantity ordered for BOM + */ +AS + v_Warehouse_ID NUMBER; + v_Quantity NUMBER := 99999; -- unlimited + v_IsBOM CHAR(1); + v_IsStocked CHAR(1); + v_ProductType CHAR(1); + v_ProductQty NUMBER; + v_StdPrecision NUMBER; + -- Get BOM Product info + CURSOR CUR_BOM IS + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType + FROM M_PRODUCT_BOM b, M_PRODUCT p + WHERE b.M_ProductBOM_ID=p.M_Product_ID + AND b.M_Product_ID=p_Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM , p.IsStocked, p.ProductType + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = p_Product_ID; + -- +BEGIN + -- Check Parameters + v_Warehouse_ID := p_Warehouse_ID; + IF (v_Warehouse_ID IS NULL) THEN + IF (p_Locator_ID IS NULL) THEN + RETURN 0; + ELSE + SELECT MAX(M_Warehouse_ID) INTO v_Warehouse_ID + FROM M_LOCATOR + WHERE M_Locator_ID=p_Locator_ID; + END IF; + END IF; + IF (v_Warehouse_ID IS NULL) THEN + RETURN 0; + END IF; +-- DBMS_OUTPUT.PUT_LINE('Warehouse=' || v_Warehouse_ID); + + -- Check, if product exists and if it is stocked + BEGIN + SELECT IsBOM, ProductType, IsStocked + INTO v_IsBOM, v_ProductType, v_IsStocked + FROM M_PRODUCT + WHERE M_Product_ID=p_Product_ID; + -- + EXCEPTION -- not found + WHEN OTHERS THEN + RETURN 0; + END; + + -- No reservation for non-stocked + IF (v_IsBOM='N' AND (v_ProductType<>'I' OR v_IsStocked='N')) THEN + RETURN 0; + -- Stocked item + ELSIF (v_IsStocked='Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyOrdered), 0) + INTO v_ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=p_Product_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=v_Warehouse_ID) + AND (s.M_AttributeSetInstance_ID = AttributeSetInstance_ID OR NVL(AttributeSetInstance_ID,0) = 0); + -- + RETURN v_ProductQty; + END IF; + + -- Go though BOM +-- DBMS_OUTPUT.PUT_LINE('BOM'); + FOR bom IN CUR_BOM LOOP + -- Stocked Items "leaf node" + IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyOrdered), 0) + INTO v_ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=bom.M_ProductBOM_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=v_Warehouse_ID) + AND (s.M_AttributeSetInstance_ID = AttributeSetInstance_ID OR NVL(AttributeSetInstance_ID,0) = 0); + -- Get Rounding Precision + SELECT NVL(MAX(u.StdPrecision), 0) + INTO v_StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=bom.M_ProductBOM_ID; + -- How much can we make with this product + v_ProductQty := ROUND (v_ProductQty/bom.BOMQty, v_StdPrecision); + -- How much can we make overall + IF (v_ProductQty < v_Quantity) THEN + v_Quantity := v_ProductQty; + END IF; + -- Another BOM + ELSIF (bom.IsBOM = 'Y') THEN + v_ProductQty := BomqtyorderedASI (bom.M_ProductBOM_ID, AttributeSetInstance_ID, v_Warehouse_ID, p_Locator_ID); + -- How much can we make overall + IF (v_ProductQty < v_Quantity) THEN + v_Quantity := v_ProductQty; + END IF; + END IF; + END LOOP; -- BOM + + -- Unlimited (e.g. only services) + IF (v_Quantity = 99999) THEN + RETURN 0; + END IF; + + IF (v_Quantity > 0) THEN + -- Get Rounding Precision for Product + SELECT NVL(MAX(u.StdPrecision), 0) + INTO v_StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=p_Product_ID; + -- + RETURN ROUND (v_Quantity, v_StdPrecision); + END IF; + -- + RETURN 0; +END BomqtyorderedASI; +/ diff --git a/db/ddlutils/oracle/functions/BOM_Qty_Reserved.sql b/db/ddlutils/oracle/functions/BOM_Qty_Reserved.sql index 73e9f0b1f8..8b50796a28 100644 --- a/db/ddlutils/oracle/functions/BOM_Qty_Reserved.sql +++ b/db/ddlutils/oracle/functions/BOM_Qty_Reserved.sql @@ -1,4 +1,4 @@ -CREATE OR REPLACE FUNCTION bomQtyReserved +CREATE OR REPLACE FUNCTION Bomqtyreserved ( p_Product_ID IN NUMBER, p_Warehouse_ID IN NUMBER, @@ -23,10 +23,15 @@ AS v_StdPrecision NUMBER; -- Get BOM Product info CURSOR CUR_BOM IS - SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType - FROM M_Product_BOM b, M_Product p + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType + FROM M_PRODUCT_BOM b, M_PRODUCT p WHERE b.M_ProductBOM_ID=p.M_Product_ID - AND b.M_Product_ID=p_Product_ID; + AND b.M_Product_ID=p_Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM , p.IsStocked, p.ProductType + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = p_Product_ID; -- BEGIN -- Check Parameters @@ -36,7 +41,7 @@ BEGIN RETURN 0; ELSE SELECT MAX(M_Warehouse_ID) INTO v_Warehouse_ID - FROM M_Locator + FROM M_LOCATOR WHERE M_Locator_ID=p_Locator_ID; END IF; END IF; @@ -49,7 +54,7 @@ BEGIN BEGIN SELECT IsBOM, ProductType, IsStocked INTO v_IsBOM, v_ProductType, v_IsStocked - FROM M_Product + FROM M_PRODUCT WHERE M_Product_ID=p_Product_ID; -- EXCEPTION -- not found @@ -65,9 +70,9 @@ BEGIN -- Get ProductQty SELECT NVL(SUM(QtyReserved), 0) INTO v_ProductQty - FROM M_Storage s + FROM M_STORAGE s WHERE M_Product_ID=p_Product_ID - AND EXISTS (SELECT * FROM M_Locator l WHERE s.M_Locator_ID=l.M_Locator_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID AND l.M_Warehouse_ID=v_Warehouse_ID); -- RETURN v_ProductQty; @@ -81,14 +86,14 @@ BEGIN -- Get ProductQty SELECT NVL(SUM(QtyReserved), 0) INTO v_ProductQty - FROM M_Storage s + FROM M_STORAGE s WHERE M_Product_ID=bom.M_ProductBOM_ID - AND EXISTS (SELECT * FROM M_Locator l WHERE s.M_Locator_ID=l.M_Locator_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID AND l.M_Warehouse_ID=v_Warehouse_ID); -- Get Rounding Precision SELECT NVL(MAX(u.StdPrecision), 0) INTO v_StdPrecision - FROM C_UOM u, M_Product p + FROM C_UOM u, M_PRODUCT p WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=bom.M_ProductBOM_ID; -- How much can we make with this product v_ProductQty := ROUND (v_ProductQty/bom.BOMQty, v_StdPrecision); @@ -98,7 +103,7 @@ BEGIN END IF; -- Another BOM ELSIF (bom.IsBOM = 'Y') THEN - v_ProductQty := bomQtyReserved (bom.M_ProductBOM_ID, v_Warehouse_ID, p_Locator_ID); + v_ProductQty := Bomqtyreserved (bom.M_ProductBOM_ID, v_Warehouse_ID, p_Locator_ID); -- How much can we make overall IF (v_ProductQty < v_Quantity) THEN v_Quantity := v_ProductQty; @@ -115,11 +120,11 @@ BEGIN -- Get Rounding Precision for Product SELECT NVL(MAX(u.StdPrecision), 0) INTO v_StdPrecision - FROM C_UOM u, M_Product p + FROM C_UOM u, M_PRODUCT p WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=p_Product_ID; -- RETURN ROUND (v_Quantity, v_StdPrecision); END IF; RETURN 0; -END bomQtyReserved; -/ \ No newline at end of file +END Bomqtyreserved; +/ diff --git a/db/ddlutils/oracle/functions/BOM_Qty_ReservedASI.sql b/db/ddlutils/oracle/functions/BOM_Qty_ReservedASI.sql new file mode 100644 index 0000000000..425f0a3b10 --- /dev/null +++ b/db/ddlutils/oracle/functions/BOM_Qty_ReservedASI.sql @@ -0,0 +1,133 @@ +CREATE OR REPLACE FUNCTION BomqtyreservedASI +( + p_Product_ID IN NUMBER, + AttributeSetInstance_ID IN NUMBER, + p_Warehouse_ID IN NUMBER, + p_Locator_ID IN NUMBER -- Only used, if warehouse is null +) +RETURN NUMBER +/****************************************************************************** + * ** Compiere Product ** Copyright (c) 1999-2001 Accorto, Inc. USA + * Open Source Software Provided "AS IS" without warranty or liability + * When you use any parts (changed or unchanged), add "Powered by Compiere" to + * your product name; See license details http://www.compiere.org/license.html + ****************************************************************************** + * Return quantity reserved for BOM + */ +AS + v_Warehouse_ID NUMBER; + v_Quantity NUMBER := 99999; -- unlimited + v_IsBOM CHAR(1); + v_IsStocked CHAR(1); + v_ProductType CHAR(1); + v_ProductQty NUMBER; + v_StdPrecision NUMBER; + -- Get BOM Product info + CURSOR CUR_BOM IS + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType + FROM M_PRODUCT_BOM b, M_PRODUCT p + WHERE b.M_ProductBOM_ID=p.M_Product_ID + AND b.M_Product_ID=p_Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM , p.IsStocked, p.ProductType + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = p_Product_ID; + -- +BEGIN + -- Check Parameters + v_Warehouse_ID := p_Warehouse_ID; + IF (v_Warehouse_ID IS NULL) THEN + IF (p_Locator_ID IS NULL) THEN + RETURN 0; + ELSE + SELECT MAX(M_Warehouse_ID) INTO v_Warehouse_ID + FROM M_LOCATOR + WHERE M_Locator_ID=p_Locator_ID; + END IF; + END IF; + IF (v_Warehouse_ID IS NULL) THEN + RETURN 0; + END IF; +-- DBMS_OUTPUT.PUT_LINE('Warehouse=' || v_Warehouse_ID); + + -- Check, if product exists and if it is stocked + BEGIN + SELECT IsBOM, ProductType, IsStocked + INTO v_IsBOM, v_ProductType, v_IsStocked + FROM M_PRODUCT + WHERE M_Product_ID=p_Product_ID; + -- + EXCEPTION -- not found + WHEN OTHERS THEN + RETURN 0; + END; + + -- No reservation for non-stocked + IF (v_IsBOM='N' AND (v_ProductType<>'I' OR v_IsStocked='N')) THEN + RETURN 0; + -- Stocked item + ELSIF (v_IsStocked='Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyReserved), 0) + INTO v_ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=p_Product_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=v_Warehouse_ID) + AND (s.M_AttributeSetInstance_ID = AttributeSetInstance_ID OR NVL(AttributeSetInstance_ID,0) = 0); + -- + RETURN v_ProductQty; + END IF; + + -- Go though BOM +-- DBMS_OUTPUT.PUT_LINE('BOM'); + FOR bom IN CUR_BOM LOOP + -- Stocked Items "leaf node" + IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyReserved), 0) + INTO v_ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=bom.M_ProductBOM_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=v_Warehouse_ID) + AND (s.M_AttributeSetInstance_ID = AttributeSetInstance_ID OR NVL(AttributeSetInstance_ID,0) = 0); + -- Get Rounding Precision + SELECT NVL(MAX(u.StdPrecision), 0) + INTO v_StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=bom.M_ProductBOM_ID; + -- How much can we make with this product + v_ProductQty := ROUND (v_ProductQty/bom.BOMQty, v_StdPrecision); + -- How much can we make overall + IF (v_ProductQty < v_Quantity) THEN + v_Quantity := v_ProductQty; + END IF; + -- Another BOM + ELSIF (bom.IsBOM = 'Y') THEN + v_ProductQty := BomqtyreservedASI (bom.M_ProductBOM_ID, AttributeSetInstance_ID, v_Warehouse_ID, p_Locator_ID); + -- How much can we make overall + IF (v_ProductQty < v_Quantity) THEN + v_Quantity := v_ProductQty; + END IF; + END IF; + END LOOP; -- BOM + + -- Unlimited (e.g. only services) + IF (v_Quantity = 99999) THEN + RETURN 0; + END IF; + + IF (v_Quantity > 0) THEN + -- Get Rounding Precision for Product + SELECT NVL(MAX(u.StdPrecision), 0) + INTO v_StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=p_Product_ID; + -- + RETURN ROUND (v_Quantity, v_StdPrecision); + END IF; + RETURN 0; +END BomqtyreservedASI; +/ \ No newline at end of file diff --git a/db/ddlutils/oracle/functions/C_Invoice_OpenToDate.sql b/db/ddlutils/oracle/functions/C_Invoice_OpenToDate.sql new file mode 100644 index 0000000000..04fdd3fecc --- /dev/null +++ b/db/ddlutils/oracle/functions/C_Invoice_OpenToDate.sql @@ -0,0 +1,118 @@ +CREATE OR REPLACE FUNCTION InvoiceopenToDate +( + p_C_Invoice_ID IN NUMBER, + p_C_InvoicePaySchedule_ID IN NUMBER, + p_DateAcct IN DATE +) +RETURN NUMBER +/************************************************************************* + * The contents of this file are subject to the Compiere License. You may + * obtain a copy of the License at http://www.compiere.org/license.html + * Software is on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for details. Code: Compiere ERP+CRM + * Copyright (C) 1999-2001 Jorg Janke, ComPiere, Inc. All Rights Reserved. + ************************************************************************* + * $Id: C_Invoice_Open.sql,v 1.1 2006/04/21 17:51:58 jjanke Exp $ + *** + * Title: Calculate Open Item Amount in Invoice Currency + * Description: + * Add up total amount open for C_Invoice_ID if no split payment. + * Grand Total minus Sum of Allocations in Invoice Currency + * + * For Split Payments: + * Allocate Payments starting from first schedule. + +SELECT C_Invoice_Open (109) FROM DUAL; +SELECT C_Invoice_Open (109, null) FROM DUAL; +SELECT C_Invoice_Open (109, 11) FROM DUAL; +SELECT C_Invoice_Open (109, 102) FROM DUAL; +SELECT C_Invoice_Open (109, 103) FROM DUAL; +SELECT * FROM RV_OpenItem WHERE C_Invoice_ID=109; +SELECT C_InvoicePaySchedule_ID, DueAmt FROM C_InvoicePaySchedule WHERE C_Invoice_ID=109 ORDER BY DueDate; + + * Cannot be used for IsPaid as mutating + ************************************************************************/ +AS + v_Currency_ID NUMBER(10); + v_TotalOpenAmt NUMBER := 0; + v_PaidAmt NUMBER := 0; + v_Remaining NUMBER := 0; + v_MultiplierAP NUMBER := 0; + v_MultiplierCM NUMBER := 0; + v_Temp NUMBER := 0; + -- + CURSOR Cur_Alloc IS + SELECT a.AD_Client_ID, a.AD_Org_ID, + al.Amount, al.DiscountAmt, al.WriteOffAmt, + a.C_Currency_ID, a.DateTrx + FROM C_ALLOCATIONLINE al + INNER JOIN C_ALLOCATIONHDR a ON (al.C_AllocationHdr_ID=a.C_AllocationHdr_ID) + WHERE al.C_Invoice_ID = p_C_Invoice_ID + AND a.DateAcct <= p_DateAcct + AND a.IsActive='Y'; + -- + CURSOR Cur_PaySchedule IS + SELECT C_InvoicePaySchedule_ID, DueAmt + FROM C_INVOICEPAYSCHEDULE + WHERE C_Invoice_ID = p_C_Invoice_ID + AND IsValid='Y' + ORDER BY DueDate; + +BEGIN + -- Get Currency + BEGIN + SELECT MAX(C_Currency_ID), SUM(GrandTotal), MAX(MultiplierAP), MAX(Multiplier) + INTO v_Currency_ID, v_TotalOpenAmt, v_MultiplierAP, v_MultiplierCM + FROM C_Invoice_v -- corrected for CM / Split Payment + WHERE C_Invoice_ID = p_C_Invoice_ID + AND DateAcct <= p_DateAcct; + EXCEPTION -- Invoice in draft form + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('InvoiceOpen - ' || SQLERRM); + RETURN NULL; + END; +-- DBMS_OUTPUT.PUT_LINE('== C_Invoice_ID=' || p_C_Invoice_ID || ', Total=' || v_TotalOpenAmt || ', AP=' || v_MultiplierAP || ', CM=' || v_MultiplierCM); + + -- Calculate Allocated Amount + FOR a IN Cur_Alloc LOOP + v_Temp := a.Amount + a.DisCountAmt + a.WriteOffAmt; + v_PaidAmt := v_PaidAmt + -- Allocation + + Currencyconvert(v_Temp * v_MultiplierAP, + a.C_Currency_ID, v_Currency_ID, a.DateTrx, NULL, a.AD_Client_ID, a.AD_Org_ID); + DBMS_OUTPUT.PUT_LINE(' PaidAmt=' || v_PaidAmt || ', Allocation=' || v_Temp || ' * ' || v_MultiplierAP); + END LOOP; + + -- Do we have a Payment Schedule ? + IF (p_C_InvoicePaySchedule_ID > 0) THEN -- if not valid = lists invoice amount + v_Remaining := v_PaidAmt; + FOR s IN Cur_PaySchedule LOOP + IF (s.C_InvoicePaySchedule_ID = p_C_InvoicePaySchedule_ID) THEN + v_TotalOpenAmt := (s.DueAmt*v_MultiplierCM) - v_Remaining; + IF (s.DueAmt - v_Remaining < 0) THEN + v_TotalOpenAmt := 0; + END IF; + -- DBMS_OUTPUT.PUT_LINE('Sched Total=' || v_TotalOpenAmt || ', Due=' || s.DueAmt || ',Remaining=' || v_Remaining || ',CM=' || v_MultiplierCM); + ELSE -- calculate amount, which can be allocated to next schedule + v_Remaining := v_Remaining - s.DueAmt; + IF (v_Remaining < 0) THEN + v_Remaining := 0; + END IF; + -- DBMS_OUTPUT.PUT_LINE('Remaining=' || v_Remaining); + END IF; + END LOOP; + ELSE + v_TotalOpenAmt := v_TotalOpenAmt - v_PaidAmt; + END IF; +-- DBMS_OUTPUT.PUT_LINE('== Total=' || v_TotalOpenAmt); + + -- Ignore Rounding + IF (v_TotalOpenAmt BETWEEN -0.00999 AND 0.00999) THEN + v_TotalOpenAmt := 0; + END IF; + + -- Round to penny + v_TotalOpenAmt := ROUND(COALESCE(v_TotalOpenAmt,0), 2); + RETURN v_TotalOpenAmt; +END InvoiceopenToDate; +/ diff --git a/db/ddlutils/oracle/functions/C_Invoice_PaidToDate.sql b/db/ddlutils/oracle/functions/C_Invoice_PaidToDate.sql new file mode 100644 index 0000000000..fd3a80d088 --- /dev/null +++ b/db/ddlutils/oracle/functions/C_Invoice_PaidToDate.sql @@ -0,0 +1,62 @@ +CREATE OR REPLACE FUNCTION InvoicepaidToDate +( + p_C_Invoice_ID IN NUMBER, + p_C_Currency_ID IN NUMBER, + p_MultiplierAP IN NUMBER, -- DEFAULT 1 + p_DateAcct IN DATE +) +RETURN NUMBER +/************************************************************************* + * The contents of this file are subject to the Compiere License. You may + * obtain a copy of the License at http://www.compiere.org/license.html + * Software is on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for details. Code: Compiere ERP+CRM + * Copyright (C) 1999-2001 Jorg Janke, ComPiere, Inc. All Rights Reserved. + ************************************************************************* + * $Id: C_Invoice_Paid.sql,v 1.1 2006/04/21 17:51:58 jjanke Exp $ + *** + * Title: Calculate Paid/Allocated amount in Currency + * Description: + * Add up total amount paid for for C_Invoice_ID. + * Split Payments are ignored. + * all allocation amounts converted to invoice C_Currency_ID + * round it to the nearest cent + * and adjust for CreditMemos by using C_Invoice_v + * and for Payments with the multiplierAP (-1, 1) + * + SELECT C_Invoice_ID, IsPaid, IsSOTrx, GrandTotal, + C_Invoice_Paid (C_Invoice_ID, C_Currency_ID, MultiplierAP) + FROM C_Invoice_v; + -- + UPDATE C_Invoice_v1 + SET IsPaid = CASE WHEN C_Invoice_Paid(C_Invoice_ID,C_Currency_ID,MultiplierAP)=GrandTotal THEN 'Y' ELSE 'N' END + WHERE C_Invoice_ID>1000000 + * + ************************************************************************/ +AS + v_MultiplierAP NUMBER := 1; + v_PaymentAmt NUMBER := 0; + CURSOR Cur_Alloc IS + SELECT a.AD_Client_ID, a.AD_Org_ID, + al.Amount, al.DiscountAmt, al.WriteOffAmt, + a.C_Currency_ID, a.DateTrx + FROM C_ALLOCATIONLINE al + INNER JOIN C_ALLOCATIONHDR a ON (al.C_AllocationHdr_ID=a.C_AllocationHdr_ID) + WHERE al.C_Invoice_ID = p_C_Invoice_ID + AND a.IsActive='Y' + AND a.DateAcct <= p_DateAcct; +BEGIN + -- Default + IF (p_MultiplierAP IS NOT NULL) THEN + v_MultiplierAP := p_MultiplierAP; + END IF; + -- Calculate Allocated Amount + FOR a IN Cur_Alloc LOOP + v_PaymentAmt := v_PaymentAmt + + Currencyconvert(a.Amount + a.DisCountAmt + a.WriteOffAmt, + a.C_Currency_ID, p_C_Currency_ID, a.DateTrx, NULL, a.AD_Client_ID, a.AD_Org_ID); + END LOOP; + -- + RETURN ROUND(NVL(v_PaymentAmt,0), 2) * v_MultiplierAP; +END InvoicepaidToDate; +/ diff --git a/migration/340s-trunk/169_fix_wrong_reference.sql b/migration/340s-trunk/169_fix_wrong_reference.sql new file mode 100644 index 0000000000..8f2cdd48ef --- /dev/null +++ b/migration/340s-trunk/169_fix_wrong_reference.sql @@ -0,0 +1,2 @@ +UPDATE AD_COLUMN SET ad_reference_id = 29 WHERE ad_column_id = 54301 +; \ No newline at end of file diff --git a/migration/340s-trunk/170_version351a.sql b/migration/340s-trunk/170_version351a.sql new file mode 100644 index 0000000000..ad57e981ea --- /dev/null +++ b/migration/340s-trunk/170_version351a.sql @@ -0,0 +1,6 @@ +UPDATE AD_SYSTEM + SET releaseno = '351a', + VERSION = '2008-05-29' + WHERE ad_system_id = 0 AND ad_client_id = 0; + +COMMIT ; diff --git a/migration/340s-trunk/173_InvoiceOpenToDate.sql b/migration/340s-trunk/173_InvoiceOpenToDate.sql new file mode 100644 index 0000000000..04fdd3fecc --- /dev/null +++ b/migration/340s-trunk/173_InvoiceOpenToDate.sql @@ -0,0 +1,118 @@ +CREATE OR REPLACE FUNCTION InvoiceopenToDate +( + p_C_Invoice_ID IN NUMBER, + p_C_InvoicePaySchedule_ID IN NUMBER, + p_DateAcct IN DATE +) +RETURN NUMBER +/************************************************************************* + * The contents of this file are subject to the Compiere License. You may + * obtain a copy of the License at http://www.compiere.org/license.html + * Software is on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for details. Code: Compiere ERP+CRM + * Copyright (C) 1999-2001 Jorg Janke, ComPiere, Inc. All Rights Reserved. + ************************************************************************* + * $Id: C_Invoice_Open.sql,v 1.1 2006/04/21 17:51:58 jjanke Exp $ + *** + * Title: Calculate Open Item Amount in Invoice Currency + * Description: + * Add up total amount open for C_Invoice_ID if no split payment. + * Grand Total minus Sum of Allocations in Invoice Currency + * + * For Split Payments: + * Allocate Payments starting from first schedule. + +SELECT C_Invoice_Open (109) FROM DUAL; +SELECT C_Invoice_Open (109, null) FROM DUAL; +SELECT C_Invoice_Open (109, 11) FROM DUAL; +SELECT C_Invoice_Open (109, 102) FROM DUAL; +SELECT C_Invoice_Open (109, 103) FROM DUAL; +SELECT * FROM RV_OpenItem WHERE C_Invoice_ID=109; +SELECT C_InvoicePaySchedule_ID, DueAmt FROM C_InvoicePaySchedule WHERE C_Invoice_ID=109 ORDER BY DueDate; + + * Cannot be used for IsPaid as mutating + ************************************************************************/ +AS + v_Currency_ID NUMBER(10); + v_TotalOpenAmt NUMBER := 0; + v_PaidAmt NUMBER := 0; + v_Remaining NUMBER := 0; + v_MultiplierAP NUMBER := 0; + v_MultiplierCM NUMBER := 0; + v_Temp NUMBER := 0; + -- + CURSOR Cur_Alloc IS + SELECT a.AD_Client_ID, a.AD_Org_ID, + al.Amount, al.DiscountAmt, al.WriteOffAmt, + a.C_Currency_ID, a.DateTrx + FROM C_ALLOCATIONLINE al + INNER JOIN C_ALLOCATIONHDR a ON (al.C_AllocationHdr_ID=a.C_AllocationHdr_ID) + WHERE al.C_Invoice_ID = p_C_Invoice_ID + AND a.DateAcct <= p_DateAcct + AND a.IsActive='Y'; + -- + CURSOR Cur_PaySchedule IS + SELECT C_InvoicePaySchedule_ID, DueAmt + FROM C_INVOICEPAYSCHEDULE + WHERE C_Invoice_ID = p_C_Invoice_ID + AND IsValid='Y' + ORDER BY DueDate; + +BEGIN + -- Get Currency + BEGIN + SELECT MAX(C_Currency_ID), SUM(GrandTotal), MAX(MultiplierAP), MAX(Multiplier) + INTO v_Currency_ID, v_TotalOpenAmt, v_MultiplierAP, v_MultiplierCM + FROM C_Invoice_v -- corrected for CM / Split Payment + WHERE C_Invoice_ID = p_C_Invoice_ID + AND DateAcct <= p_DateAcct; + EXCEPTION -- Invoice in draft form + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('InvoiceOpen - ' || SQLERRM); + RETURN NULL; + END; +-- DBMS_OUTPUT.PUT_LINE('== C_Invoice_ID=' || p_C_Invoice_ID || ', Total=' || v_TotalOpenAmt || ', AP=' || v_MultiplierAP || ', CM=' || v_MultiplierCM); + + -- Calculate Allocated Amount + FOR a IN Cur_Alloc LOOP + v_Temp := a.Amount + a.DisCountAmt + a.WriteOffAmt; + v_PaidAmt := v_PaidAmt + -- Allocation + + Currencyconvert(v_Temp * v_MultiplierAP, + a.C_Currency_ID, v_Currency_ID, a.DateTrx, NULL, a.AD_Client_ID, a.AD_Org_ID); + DBMS_OUTPUT.PUT_LINE(' PaidAmt=' || v_PaidAmt || ', Allocation=' || v_Temp || ' * ' || v_MultiplierAP); + END LOOP; + + -- Do we have a Payment Schedule ? + IF (p_C_InvoicePaySchedule_ID > 0) THEN -- if not valid = lists invoice amount + v_Remaining := v_PaidAmt; + FOR s IN Cur_PaySchedule LOOP + IF (s.C_InvoicePaySchedule_ID = p_C_InvoicePaySchedule_ID) THEN + v_TotalOpenAmt := (s.DueAmt*v_MultiplierCM) - v_Remaining; + IF (s.DueAmt - v_Remaining < 0) THEN + v_TotalOpenAmt := 0; + END IF; + -- DBMS_OUTPUT.PUT_LINE('Sched Total=' || v_TotalOpenAmt || ', Due=' || s.DueAmt || ',Remaining=' || v_Remaining || ',CM=' || v_MultiplierCM); + ELSE -- calculate amount, which can be allocated to next schedule + v_Remaining := v_Remaining - s.DueAmt; + IF (v_Remaining < 0) THEN + v_Remaining := 0; + END IF; + -- DBMS_OUTPUT.PUT_LINE('Remaining=' || v_Remaining); + END IF; + END LOOP; + ELSE + v_TotalOpenAmt := v_TotalOpenAmt - v_PaidAmt; + END IF; +-- DBMS_OUTPUT.PUT_LINE('== Total=' || v_TotalOpenAmt); + + -- Ignore Rounding + IF (v_TotalOpenAmt BETWEEN -0.00999 AND 0.00999) THEN + v_TotalOpenAmt := 0; + END IF; + + -- Round to penny + v_TotalOpenAmt := ROUND(COALESCE(v_TotalOpenAmt,0), 2); + RETURN v_TotalOpenAmt; +END InvoiceopenToDate; +/ diff --git a/migration/340s-trunk/174_InvoicepaidToDate.sql b/migration/340s-trunk/174_InvoicepaidToDate.sql new file mode 100644 index 0000000000..fd3a80d088 --- /dev/null +++ b/migration/340s-trunk/174_InvoicepaidToDate.sql @@ -0,0 +1,62 @@ +CREATE OR REPLACE FUNCTION InvoicepaidToDate +( + p_C_Invoice_ID IN NUMBER, + p_C_Currency_ID IN NUMBER, + p_MultiplierAP IN NUMBER, -- DEFAULT 1 + p_DateAcct IN DATE +) +RETURN NUMBER +/************************************************************************* + * The contents of this file are subject to the Compiere License. You may + * obtain a copy of the License at http://www.compiere.org/license.html + * Software is on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for details. Code: Compiere ERP+CRM + * Copyright (C) 1999-2001 Jorg Janke, ComPiere, Inc. All Rights Reserved. + ************************************************************************* + * $Id: C_Invoice_Paid.sql,v 1.1 2006/04/21 17:51:58 jjanke Exp $ + *** + * Title: Calculate Paid/Allocated amount in Currency + * Description: + * Add up total amount paid for for C_Invoice_ID. + * Split Payments are ignored. + * all allocation amounts converted to invoice C_Currency_ID + * round it to the nearest cent + * and adjust for CreditMemos by using C_Invoice_v + * and for Payments with the multiplierAP (-1, 1) + * + SELECT C_Invoice_ID, IsPaid, IsSOTrx, GrandTotal, + C_Invoice_Paid (C_Invoice_ID, C_Currency_ID, MultiplierAP) + FROM C_Invoice_v; + -- + UPDATE C_Invoice_v1 + SET IsPaid = CASE WHEN C_Invoice_Paid(C_Invoice_ID,C_Currency_ID,MultiplierAP)=GrandTotal THEN 'Y' ELSE 'N' END + WHERE C_Invoice_ID>1000000 + * + ************************************************************************/ +AS + v_MultiplierAP NUMBER := 1; + v_PaymentAmt NUMBER := 0; + CURSOR Cur_Alloc IS + SELECT a.AD_Client_ID, a.AD_Org_ID, + al.Amount, al.DiscountAmt, al.WriteOffAmt, + a.C_Currency_ID, a.DateTrx + FROM C_ALLOCATIONLINE al + INNER JOIN C_ALLOCATIONHDR a ON (al.C_AllocationHdr_ID=a.C_AllocationHdr_ID) + WHERE al.C_Invoice_ID = p_C_Invoice_ID + AND a.IsActive='Y' + AND a.DateAcct <= p_DateAcct; +BEGIN + -- Default + IF (p_MultiplierAP IS NOT NULL) THEN + v_MultiplierAP := p_MultiplierAP; + END IF; + -- Calculate Allocated Amount + FOR a IN Cur_Alloc LOOP + v_PaymentAmt := v_PaymentAmt + + Currencyconvert(a.Amount + a.DisCountAmt + a.WriteOffAmt, + a.C_Currency_ID, p_C_Currency_ID, a.DateTrx, NULL, a.AD_Client_ID, a.AD_Org_ID); + END LOOP; + -- + RETURN ROUND(NVL(v_PaymentAmt,0), 2) * v_MultiplierAP; +END InvoicepaidToDate; +/ diff --git a/migration/340s-trunk/175_BomqtyavailableASI.sql b/migration/340s-trunk/175_BomqtyavailableASI.sql new file mode 100644 index 0000000000..f7de6896a3 --- /dev/null +++ b/migration/340s-trunk/175_BomqtyavailableASI.sql @@ -0,0 +1,22 @@ +CREATE OR REPLACE FUNCTION BomqtyavailableASI +( + Product_ID IN NUMBER, + AttributeSetInstance_ID IN NUMBER, + Warehouse_ID IN NUMBER, + Locator_ID IN NUMBER -- Only used, if warehouse is null +) +RETURN NUMBER +/****************************************************************************** + * ** Compiere Product ** Copyright (c) 1999-2001 Accorto, Inc. USA + * Open Source Software Provided "AS IS" without warranty or liability + * When you use any parts (changed or unchanged), add "Powered by Compiere" to + * your product name; See license details http://www.compiere.org/license.html + ****************************************************************************** + * Return quantity available for BOM ASI + */ +AS +BEGIN + RETURN BomqtyonhandASI(Product_ID, AttributeSetInstance_ID, Warehouse_ID, Locator_ID) + - BomqtyreservedASI(Product_ID, AttributeSetInstance_ID, Warehouse_ID, Locator_ID); +END BomqtyavailableASI; +/ diff --git a/migration/340s-trunk/176_BomqtyonhandASI.sql b/migration/340s-trunk/176_BomqtyonhandASI.sql new file mode 100644 index 0000000000..948631da7b --- /dev/null +++ b/migration/340s-trunk/176_BomqtyonhandASI.sql @@ -0,0 +1,128 @@ +CREATE OR REPLACE FUNCTION BomqtyonhandASI +( + Product_ID IN NUMBER, + AttributeSetInstance_ID IN NUMBER, + Warehouse_ID IN NUMBER, + Locator_ID IN NUMBER -- Only used, if warehouse is null +) +RETURN NUMBER +/****************************************************************************** + * ** Compiere Product ** Copyright (c) 1999-2001 Accorto, Inc. USA + * Open Source Software Provided "AS IS" without warranty or liability + * When you use any parts (changed or unchanged), add "Powered by Compiere" to + * your product name; See license details http://www.compiere.org/license.html + ****************************************************************************** + * Return quantity on hand for BOM + */ +AS + myWarehouse_ID NUMBER; + Quantity NUMBER := 99999; -- unlimited + IsBOM CHAR(1); + IsStocked CHAR(1); + ProductType CHAR(1); + ProductQty NUMBER; + StdPrecision NUMBER; + -- Get BOM Product info + CURSOR CUR_BOM IS + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType + FROM M_PRODUCT_BOM b, M_PRODUCT p + WHERE b.M_ProductBOM_ID=p.M_Product_ID + AND b.M_Product_ID=p_Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM , p.IsStocked, p.ProductType + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = Product_ID; + -- +BEGIN + -- Check Parameters + myWarehouse_ID := Warehouse_ID; + IF (myWarehouse_ID IS NULL) THEN + IF (Locator_ID IS NULL) THEN + RETURN 0; + ELSE + SELECT SUM(M_Warehouse_ID) INTO myWarehouse_ID + FROM M_LOCATOR + WHERE M_Locator_ID=Locator_ID; + END IF; + END IF; + IF (myWarehouse_ID IS NULL) THEN + RETURN 0; + END IF; +-- DBMS_OUTPUT.PUT_LINE('Warehouse=' || myWarehouse_ID); + + -- Check, if product exists and if it is stocked + BEGIN + SELECT IsBOM, ProductType, IsStocked + INTO IsBOM, ProductType, IsStocked + FROM M_PRODUCT + WHERE M_Product_ID=Product_ID; + -- + EXCEPTION -- not found + WHEN OTHERS THEN + RETURN 0; + END; + -- Unimited capacity if no item + IF (IsBOM='N' AND (ProductType<>'I' OR IsStocked='N')) THEN + RETURN Quantity; + -- Stocked item + ELSIF (IsStocked='Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyOnHand), 0) + INTO ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=Product_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=myWarehouse_ID) + AND (s.M_AttributeSetInstance_ID = AttributeSetInstance_ID OR NVL(AttributeSetInstance_ID,0) = 0); + -- + -- DBMS_OUTPUT.PUT_LINE('Qty=' || ProductQty); + RETURN ProductQty; + END IF; + + -- Go though BOM +-- DBMS_OUTPUT.PUT_LINE('BOM'); + FOR bom IN CUR_BOM LOOP + -- Stocked Items "leaf node" + IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyOnHand), 0) + INTO ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=bom.M_ProductBOM_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=myWarehouse_ID) + AND (s.M_AttributeSetInstance_ID = AttributeSetInstance_ID OR NVL(AttributeSetInstance_ID,0) = 0); + -- Get Rounding Precision + SELECT NVL(MAX(u.StdPrecision), 0) + INTO StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=bom.M_ProductBOM_ID; + -- How much can we make with this product + ProductQty := ROUND (ProductQty/bom.BOMQty, StdPrecision); + -- How much can we make overall + IF (ProductQty < Quantity) THEN + Quantity := ProductQty; + END IF; + -- Another BOM + ELSIF (bom.IsBOM = 'Y') THEN + ProductQty := BomqtyonhandASI (bom.M_ProductBOM_ID, AttributeSetInstance_ID, myWarehouse_ID, Locator_ID); + -- How much can we make overall + IF (ProductQty < Quantity) THEN + Quantity := ProductQty; + END IF; + END IF; + END LOOP; -- BOM + + IF (Quantity > 0) THEN + -- Get Rounding Precision for Product + SELECT NVL(MAX(u.StdPrecision), 0) + INTO StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=Product_ID; + -- + RETURN ROUND (Quantity, StdPrecision); + END IF; + RETURN 0; +END BomqtyonhandASI; +/ diff --git a/migration/340s-trunk/177_BomqtyorderedASI.sql b/migration/340s-trunk/177_BomqtyorderedASI.sql new file mode 100644 index 0000000000..a727661762 --- /dev/null +++ b/migration/340s-trunk/177_BomqtyorderedASI.sql @@ -0,0 +1,134 @@ +CREATE OR REPLACE FUNCTION BomqtyorderedASI +( + p_Product_ID IN NUMBER, + AttributeSetInstance_ID IN NUMBER, + p_Warehouse_ID IN NUMBER, + p_Locator_ID IN NUMBER -- Only used, if warehouse is null +) +RETURN NUMBER +/****************************************************************************** + * ** Compiere Product ** Copyright (c) 1999-2001 Accorto, Inc. USA + * Open Source Software Provided "AS IS" without warranty or liability + * When you use any parts (changed or unchanged), add "Powered by Compiere" to + * your product name; See license details http://www.compiere.org/license.html + ****************************************************************************** + * Return quantity ordered for BOM + */ +AS + v_Warehouse_ID NUMBER; + v_Quantity NUMBER := 99999; -- unlimited + v_IsBOM CHAR(1); + v_IsStocked CHAR(1); + v_ProductType CHAR(1); + v_ProductQty NUMBER; + v_StdPrecision NUMBER; + -- Get BOM Product info + CURSOR CUR_BOM IS + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType + FROM M_PRODUCT_BOM b, M_PRODUCT p + WHERE b.M_ProductBOM_ID=p.M_Product_ID + AND b.M_Product_ID=p_Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM , p.IsStocked, p.ProductType + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = p_Product_ID; + -- +BEGIN + -- Check Parameters + v_Warehouse_ID := p_Warehouse_ID; + IF (v_Warehouse_ID IS NULL) THEN + IF (p_Locator_ID IS NULL) THEN + RETURN 0; + ELSE + SELECT MAX(M_Warehouse_ID) INTO v_Warehouse_ID + FROM M_LOCATOR + WHERE M_Locator_ID=p_Locator_ID; + END IF; + END IF; + IF (v_Warehouse_ID IS NULL) THEN + RETURN 0; + END IF; +-- DBMS_OUTPUT.PUT_LINE('Warehouse=' || v_Warehouse_ID); + + -- Check, if product exists and if it is stocked + BEGIN + SELECT IsBOM, ProductType, IsStocked + INTO v_IsBOM, v_ProductType, v_IsStocked + FROM M_PRODUCT + WHERE M_Product_ID=p_Product_ID; + -- + EXCEPTION -- not found + WHEN OTHERS THEN + RETURN 0; + END; + + -- No reservation for non-stocked + IF (v_IsBOM='N' AND (v_ProductType<>'I' OR v_IsStocked='N')) THEN + RETURN 0; + -- Stocked item + ELSIF (v_IsStocked='Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyOrdered), 0) + INTO v_ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=p_Product_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=v_Warehouse_ID) + AND (s.M_AttributeSetInstance_ID = AttributeSetInstance_ID OR NVL(AttributeSetInstance_ID,0) = 0); + -- + RETURN v_ProductQty; + END IF; + + -- Go though BOM +-- DBMS_OUTPUT.PUT_LINE('BOM'); + FOR bom IN CUR_BOM LOOP + -- Stocked Items "leaf node" + IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyOrdered), 0) + INTO v_ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=bom.M_ProductBOM_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=v_Warehouse_ID) + AND (s.M_AttributeSetInstance_ID = AttributeSetInstance_ID OR NVL(AttributeSetInstance_ID,0) = 0); + -- Get Rounding Precision + SELECT NVL(MAX(u.StdPrecision), 0) + INTO v_StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=bom.M_ProductBOM_ID; + -- How much can we make with this product + v_ProductQty := ROUND (v_ProductQty/bom.BOMQty, v_StdPrecision); + -- How much can we make overall + IF (v_ProductQty < v_Quantity) THEN + v_Quantity := v_ProductQty; + END IF; + -- Another BOM + ELSIF (bom.IsBOM = 'Y') THEN + v_ProductQty := BomqtyorderedASI (bom.M_ProductBOM_ID, AttributeSetInstance_ID, v_Warehouse_ID, p_Locator_ID); + -- How much can we make overall + IF (v_ProductQty < v_Quantity) THEN + v_Quantity := v_ProductQty; + END IF; + END IF; + END LOOP; -- BOM + + -- Unlimited (e.g. only services) + IF (v_Quantity = 99999) THEN + RETURN 0; + END IF; + + IF (v_Quantity > 0) THEN + -- Get Rounding Precision for Product + SELECT NVL(MAX(u.StdPrecision), 0) + INTO v_StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=p_Product_ID; + -- + RETURN ROUND (v_Quantity, v_StdPrecision); + END IF; + -- + RETURN 0; +END BomqtyorderedASI; +/ diff --git a/migration/340s-trunk/178_BomqtyreservedASI.sql b/migration/340s-trunk/178_BomqtyreservedASI.sql new file mode 100644 index 0000000000..425f0a3b10 --- /dev/null +++ b/migration/340s-trunk/178_BomqtyreservedASI.sql @@ -0,0 +1,133 @@ +CREATE OR REPLACE FUNCTION BomqtyreservedASI +( + p_Product_ID IN NUMBER, + AttributeSetInstance_ID IN NUMBER, + p_Warehouse_ID IN NUMBER, + p_Locator_ID IN NUMBER -- Only used, if warehouse is null +) +RETURN NUMBER +/****************************************************************************** + * ** Compiere Product ** Copyright (c) 1999-2001 Accorto, Inc. USA + * Open Source Software Provided "AS IS" without warranty or liability + * When you use any parts (changed or unchanged), add "Powered by Compiere" to + * your product name; See license details http://www.compiere.org/license.html + ****************************************************************************** + * Return quantity reserved for BOM + */ +AS + v_Warehouse_ID NUMBER; + v_Quantity NUMBER := 99999; -- unlimited + v_IsBOM CHAR(1); + v_IsStocked CHAR(1); + v_ProductType CHAR(1); + v_ProductQty NUMBER; + v_StdPrecision NUMBER; + -- Get BOM Product info + CURSOR CUR_BOM IS + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType + FROM M_PRODUCT_BOM b, M_PRODUCT p + WHERE b.M_ProductBOM_ID=p.M_Product_ID + AND b.M_Product_ID=p_Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM , p.IsStocked, p.ProductType + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = p_Product_ID; + -- +BEGIN + -- Check Parameters + v_Warehouse_ID := p_Warehouse_ID; + IF (v_Warehouse_ID IS NULL) THEN + IF (p_Locator_ID IS NULL) THEN + RETURN 0; + ELSE + SELECT MAX(M_Warehouse_ID) INTO v_Warehouse_ID + FROM M_LOCATOR + WHERE M_Locator_ID=p_Locator_ID; + END IF; + END IF; + IF (v_Warehouse_ID IS NULL) THEN + RETURN 0; + END IF; +-- DBMS_OUTPUT.PUT_LINE('Warehouse=' || v_Warehouse_ID); + + -- Check, if product exists and if it is stocked + BEGIN + SELECT IsBOM, ProductType, IsStocked + INTO v_IsBOM, v_ProductType, v_IsStocked + FROM M_PRODUCT + WHERE M_Product_ID=p_Product_ID; + -- + EXCEPTION -- not found + WHEN OTHERS THEN + RETURN 0; + END; + + -- No reservation for non-stocked + IF (v_IsBOM='N' AND (v_ProductType<>'I' OR v_IsStocked='N')) THEN + RETURN 0; + -- Stocked item + ELSIF (v_IsStocked='Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyReserved), 0) + INTO v_ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=p_Product_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=v_Warehouse_ID) + AND (s.M_AttributeSetInstance_ID = AttributeSetInstance_ID OR NVL(AttributeSetInstance_ID,0) = 0); + -- + RETURN v_ProductQty; + END IF; + + -- Go though BOM +-- DBMS_OUTPUT.PUT_LINE('BOM'); + FOR bom IN CUR_BOM LOOP + -- Stocked Items "leaf node" + IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyReserved), 0) + INTO v_ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=bom.M_ProductBOM_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=v_Warehouse_ID) + AND (s.M_AttributeSetInstance_ID = AttributeSetInstance_ID OR NVL(AttributeSetInstance_ID,0) = 0); + -- Get Rounding Precision + SELECT NVL(MAX(u.StdPrecision), 0) + INTO v_StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=bom.M_ProductBOM_ID; + -- How much can we make with this product + v_ProductQty := ROUND (v_ProductQty/bom.BOMQty, v_StdPrecision); + -- How much can we make overall + IF (v_ProductQty < v_Quantity) THEN + v_Quantity := v_ProductQty; + END IF; + -- Another BOM + ELSIF (bom.IsBOM = 'Y') THEN + v_ProductQty := BomqtyreservedASI (bom.M_ProductBOM_ID, AttributeSetInstance_ID, v_Warehouse_ID, p_Locator_ID); + -- How much can we make overall + IF (v_ProductQty < v_Quantity) THEN + v_Quantity := v_ProductQty; + END IF; + END IF; + END LOOP; -- BOM + + -- Unlimited (e.g. only services) + IF (v_Quantity = 99999) THEN + RETURN 0; + END IF; + + IF (v_Quantity > 0) THEN + -- Get Rounding Precision for Product + SELECT NVL(MAX(u.StdPrecision), 0) + INTO v_StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=p_Product_ID; + -- + RETURN ROUND (v_Quantity, v_StdPrecision); + END IF; + RETURN 0; +END BomqtyreservedASI; +/ \ No newline at end of file diff --git a/migration/340s-trunk/179_Bomqtyordered.sql b/migration/340s-trunk/179_Bomqtyordered.sql new file mode 100644 index 0000000000..540aea2535 --- /dev/null +++ b/migration/340s-trunk/179_Bomqtyordered.sql @@ -0,0 +1,131 @@ +CREATE OR REPLACE FUNCTION Bomqtyordered +( + p_Product_ID IN NUMBER, + p_Warehouse_ID IN NUMBER, + p_Locator_ID IN NUMBER -- Only used, if warehouse is null +) +RETURN NUMBER +/****************************************************************************** + * ** Compiere Product ** Copyright (c) 1999-2001 Accorto, Inc. USA + * Open Source Software Provided "AS IS" without warranty or liability + * When you use any parts (changed or unchanged), add "Powered by Compiere" to + * your product name; See license details http://www.compiere.org/license.html + ****************************************************************************** + * Return quantity ordered for BOM + */ +AS + v_Warehouse_ID NUMBER; + v_Quantity NUMBER := 99999; -- unlimited + v_IsBOM CHAR(1); + v_IsStocked CHAR(1); + v_ProductType CHAR(1); + v_ProductQty NUMBER; + v_StdPrecision NUMBER; + -- Get BOM Product info + CURSOR CUR_BOM IS + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType + FROM M_PRODUCT_BOM b, M_PRODUCT p + WHERE b.M_ProductBOM_ID=p.M_Product_ID + AND b.M_Product_ID=p_Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM , p.IsStocked, p.ProductType + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = p_Product_ID; + -- +BEGIN + -- Check Parameters + v_Warehouse_ID := p_Warehouse_ID; + IF (v_Warehouse_ID IS NULL) THEN + IF (p_Locator_ID IS NULL) THEN + RETURN 0; + ELSE + SELECT MAX(M_Warehouse_ID) INTO v_Warehouse_ID + FROM M_LOCATOR + WHERE M_Locator_ID=p_Locator_ID; + END IF; + END IF; + IF (v_Warehouse_ID IS NULL) THEN + RETURN 0; + END IF; +-- DBMS_OUTPUT.PUT_LINE('Warehouse=' || v_Warehouse_ID); + + -- Check, if product exists and if it is stocked + BEGIN + SELECT IsBOM, ProductType, IsStocked + INTO v_IsBOM, v_ProductType, v_IsStocked + FROM M_PRODUCT + WHERE M_Product_ID=p_Product_ID; + -- + EXCEPTION -- not found + WHEN OTHERS THEN + RETURN 0; + END; + + -- No reservation for non-stocked + IF (v_IsBOM='N' AND (v_ProductType<>'I' OR v_IsStocked='N')) THEN + RETURN 0; + -- Stocked item + ELSIF (v_IsStocked='Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyOrdered), 0) + INTO v_ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=p_Product_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=v_Warehouse_ID); + -- + RETURN v_ProductQty; + END IF; + + -- Go though BOM +-- DBMS_OUTPUT.PUT_LINE('BOM'); + FOR bom IN CUR_BOM LOOP + -- Stocked Items "leaf node" + IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyOrdered), 0) + INTO v_ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=bom.M_ProductBOM_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=v_Warehouse_ID); + -- Get Rounding Precision + SELECT NVL(MAX(u.StdPrecision), 0) + INTO v_StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=bom.M_ProductBOM_ID; + -- How much can we make with this product + v_ProductQty := ROUND (v_ProductQty/bom.BOMQty, v_StdPrecision); + -- How much can we make overall + IF (v_ProductQty < v_Quantity) THEN + v_Quantity := v_ProductQty; + END IF; + -- Another BOM + ELSIF (bom.IsBOM = 'Y') THEN + v_ProductQty := Bomqtyordered (bom.M_ProductBOM_ID, v_Warehouse_ID, p_Locator_ID); + -- How much can we make overall + IF (v_ProductQty < v_Quantity) THEN + v_Quantity := v_ProductQty; + END IF; + END IF; + END LOOP; -- BOM + + -- Unlimited (e.g. only services) + IF (v_Quantity = 99999) THEN + RETURN 0; + END IF; + + IF (v_Quantity > 0) THEN + -- Get Rounding Precision for Product + SELECT NVL(MAX(u.StdPrecision), 0) + INTO v_StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=p_Product_ID; + -- + RETURN ROUND (v_Quantity, v_StdPrecision); + END IF; + -- + RETURN 0; +END Bomqtyordered; +/ diff --git a/migration/340s-trunk/180_Bompricestd.sql b/migration/340s-trunk/180_Bompricestd.sql new file mode 100644 index 0000000000..adf8662b68 --- /dev/null +++ b/migration/340s-trunk/180_Bompricestd.sql @@ -0,0 +1,54 @@ +CREATE OR REPLACE FUNCTION Bompricestd +( + Product_ID IN NUMBER, + PriceList_Version_ID IN NUMBER +) +RETURN NUMBER +/************************************************************************* + * The contents of this file are subject to the Compiere License. You may + * obtain a copy of the License at http://www.compiere.org/license.html + * Software is on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for details. Code: Compiere ERP+CRM + * Copyright (C) 1999-2002 Jorg Janke, ComPiere, Inc. All Rights Reserved. + ************************************************************************* + * $Id: BOM_PriceStd.sql,v 1.1 2006/04/21 17:51:58 jjanke Exp $ + *** + * Title: Return Standard Price of Product/BOM + * Description: + * if not found: 0 + ************************************************************************/ +AS + v_Price NUMBER; + v_ProductPrice NUMBER; + -- Get BOM Product info + CURSOR CUR_BOM IS + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM + FROM M_PRODUCT_BOM b, M_PRODUCT p + WHERE b.M_ProductBOM_ID=p.M_Product_ID + AND b.M_Product_ID=Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = Product_ID; + -- +BEGIN + -- Try to get price from pricelist directly + SELECT COALESCE(SUM(PriceStd), 0) + INTO v_Price + FROM M_PRODUCTPRICE + WHERE M_PriceList_Version_ID=PriceList_Version_ID AND M_Product_ID=Product_ID; +-- DBMS_OUTPUT.PUT_LINE('Price=' || v_Price); + + -- No Price - Check if BOM + IF (v_Price = 0) THEN + FOR bom IN CUR_BOM LOOP + v_ProductPrice := Bompricestd (bom.M_ProductBOM_ID, PriceList_Version_ID); + v_Price := v_Price + (bom.BOMQty * v_ProductPrice); + -- DBMS_OUTPUT.PUT_LINE('Price=' || v_Price); + END LOOP; -- BOM + END IF; + -- + RETURN v_Price; +END Bompricestd; +/ diff --git a/migration/340s-trunk/181_Bomqtyreserved.sql b/migration/340s-trunk/181_Bomqtyreserved.sql new file mode 100644 index 0000000000..8b50796a28 --- /dev/null +++ b/migration/340s-trunk/181_Bomqtyreserved.sql @@ -0,0 +1,130 @@ +CREATE OR REPLACE FUNCTION Bomqtyreserved +( + p_Product_ID IN NUMBER, + p_Warehouse_ID IN NUMBER, + p_Locator_ID IN NUMBER -- Only used, if warehouse is null +) +RETURN NUMBER +/****************************************************************************** + * ** Compiere Product ** Copyright (c) 1999-2001 Accorto, Inc. USA + * Open Source Software Provided "AS IS" without warranty or liability + * When you use any parts (changed or unchanged), add "Powered by Compiere" to + * your product name; See license details http://www.compiere.org/license.html + ****************************************************************************** + * Return quantity reserved for BOM + */ +AS + v_Warehouse_ID NUMBER; + v_Quantity NUMBER := 99999; -- unlimited + v_IsBOM CHAR(1); + v_IsStocked CHAR(1); + v_ProductType CHAR(1); + v_ProductQty NUMBER; + v_StdPrecision NUMBER; + -- Get BOM Product info + CURSOR CUR_BOM IS + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType + FROM M_PRODUCT_BOM b, M_PRODUCT p + WHERE b.M_ProductBOM_ID=p.M_Product_ID + AND b.M_Product_ID=p_Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM , p.IsStocked, p.ProductType + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = p_Product_ID; + -- +BEGIN + -- Check Parameters + v_Warehouse_ID := p_Warehouse_ID; + IF (v_Warehouse_ID IS NULL) THEN + IF (p_Locator_ID IS NULL) THEN + RETURN 0; + ELSE + SELECT MAX(M_Warehouse_ID) INTO v_Warehouse_ID + FROM M_LOCATOR + WHERE M_Locator_ID=p_Locator_ID; + END IF; + END IF; + IF (v_Warehouse_ID IS NULL) THEN + RETURN 0; + END IF; +-- DBMS_OUTPUT.PUT_LINE('Warehouse=' || v_Warehouse_ID); + + -- Check, if product exists and if it is stocked + BEGIN + SELECT IsBOM, ProductType, IsStocked + INTO v_IsBOM, v_ProductType, v_IsStocked + FROM M_PRODUCT + WHERE M_Product_ID=p_Product_ID; + -- + EXCEPTION -- not found + WHEN OTHERS THEN + RETURN 0; + END; + + -- No reservation for non-stocked + IF (v_IsBOM='N' AND (v_ProductType<>'I' OR v_IsStocked='N')) THEN + RETURN 0; + -- Stocked item + ELSIF (v_IsStocked='Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyReserved), 0) + INTO v_ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=p_Product_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=v_Warehouse_ID); + -- + RETURN v_ProductQty; + END IF; + + -- Go though BOM +-- DBMS_OUTPUT.PUT_LINE('BOM'); + FOR bom IN CUR_BOM LOOP + -- Stocked Items "leaf node" + IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyReserved), 0) + INTO v_ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=bom.M_ProductBOM_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=v_Warehouse_ID); + -- Get Rounding Precision + SELECT NVL(MAX(u.StdPrecision), 0) + INTO v_StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=bom.M_ProductBOM_ID; + -- How much can we make with this product + v_ProductQty := ROUND (v_ProductQty/bom.BOMQty, v_StdPrecision); + -- How much can we make overall + IF (v_ProductQty < v_Quantity) THEN + v_Quantity := v_ProductQty; + END IF; + -- Another BOM + ELSIF (bom.IsBOM = 'Y') THEN + v_ProductQty := Bomqtyreserved (bom.M_ProductBOM_ID, v_Warehouse_ID, p_Locator_ID); + -- How much can we make overall + IF (v_ProductQty < v_Quantity) THEN + v_Quantity := v_ProductQty; + END IF; + END IF; + END LOOP; -- BOM + + -- Unlimited (e.g. only services) + IF (v_Quantity = 99999) THEN + RETURN 0; + END IF; + + IF (v_Quantity > 0) THEN + -- Get Rounding Precision for Product + SELECT NVL(MAX(u.StdPrecision), 0) + INTO v_StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=p_Product_ID; + -- + RETURN ROUND (v_Quantity, v_StdPrecision); + END IF; + RETURN 0; +END Bomqtyreserved; +/ diff --git a/migration/340s-trunk/182_Bomqtyonhand.sql b/migration/340s-trunk/182_Bomqtyonhand.sql new file mode 100644 index 0000000000..9c3fe43b69 --- /dev/null +++ b/migration/340s-trunk/182_Bomqtyonhand.sql @@ -0,0 +1,125 @@ +CREATE OR REPLACE FUNCTION Bomqtyonhand +( + Product_ID IN NUMBER, + Warehouse_ID IN NUMBER, + Locator_ID IN NUMBER -- Only used, if warehouse is null +) +RETURN NUMBER +/****************************************************************************** + * ** Compiere Product ** Copyright (c) 1999-2001 Accorto, Inc. USA + * Open Source Software Provided "AS IS" without warranty or liability + * When you use any parts (changed or unchanged), add "Powered by Compiere" to + * your product name; See license details http://www.compiere.org/license.html + ****************************************************************************** + * Return quantity on hand for BOM + */ +AS + myWarehouse_ID NUMBER; + Quantity NUMBER := 99999; -- unlimited + IsBOM CHAR(1); + IsStocked CHAR(1); + ProductType CHAR(1); + ProductQty NUMBER; + StdPrecision NUMBER; + -- Get BOM Product info + CURSOR CUR_BOM IS + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType + FROM M_PRODUCT_BOM b, M_PRODUCT p + WHERE b.M_ProductBOM_ID=p.M_Product_ID + AND b.M_Product_ID=p_Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM , p.IsStocked, p.ProductType + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = Product_ID; + -- +BEGIN + -- Check Parameters + myWarehouse_ID := Warehouse_ID; + IF (myWarehouse_ID IS NULL) THEN + IF (Locator_ID IS NULL) THEN + RETURN 0; + ELSE + SELECT SUM(M_Warehouse_ID) INTO myWarehouse_ID + FROM M_LOCATOR + WHERE M_Locator_ID=Locator_ID; + END IF; + END IF; + IF (myWarehouse_ID IS NULL) THEN + RETURN 0; + END IF; +-- DBMS_OUTPUT.PUT_LINE('Warehouse=' || myWarehouse_ID); + + -- Check, if product exists and if it is stocked + BEGIN + SELECT IsBOM, ProductType, IsStocked + INTO IsBOM, ProductType, IsStocked + FROM M_PRODUCT + WHERE M_Product_ID=Product_ID; + -- + EXCEPTION -- not found + WHEN OTHERS THEN + RETURN 0; + END; + -- Unimited capacity if no item + IF (IsBOM='N' AND (ProductType<>'I' OR IsStocked='N')) THEN + RETURN Quantity; + -- Stocked item + ELSIF (IsStocked='Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyOnHand), 0) + INTO ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=Product_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=myWarehouse_ID); + -- + -- DBMS_OUTPUT.PUT_LINE('Qty=' || ProductQty); + RETURN ProductQty; + END IF; + + -- Go though BOM +-- DBMS_OUTPUT.PUT_LINE('BOM'); + FOR bom IN CUR_BOM LOOP + -- Stocked Items "leaf node" + IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN + -- Get ProductQty + SELECT NVL(SUM(QtyOnHand), 0) + INTO ProductQty + FROM M_STORAGE s + WHERE M_Product_ID=bom.M_ProductBOM_ID + AND EXISTS (SELECT * FROM M_LOCATOR l WHERE s.M_Locator_ID=l.M_Locator_ID + AND l.M_Warehouse_ID=myWarehouse_ID); + -- Get Rounding Precision + SELECT NVL(MAX(u.StdPrecision), 0) + INTO StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=bom.M_ProductBOM_ID; + -- How much can we make with this product + ProductQty := ROUND (ProductQty/bom.BOMQty, StdPrecision); + -- How much can we make overall + IF (ProductQty < Quantity) THEN + Quantity := ProductQty; + END IF; + -- Another BOM + ELSIF (bom.IsBOM = 'Y') THEN + ProductQty := Bomqtyonhand (bom.M_ProductBOM_ID, myWarehouse_ID, Locator_ID); + -- How much can we make overall + IF (ProductQty < Quantity) THEN + Quantity := ProductQty; + END IF; + END IF; + END LOOP; -- BOM + + IF (Quantity > 0) THEN + -- Get Rounding Precision for Product + SELECT NVL(MAX(u.StdPrecision), 0) + INTO StdPrecision + FROM C_UOM u, M_PRODUCT p + WHERE u.C_UOM_ID=p.C_UOM_ID AND p.M_Product_ID=Product_ID; + -- + RETURN ROUND (Quantity, StdPrecision); + END IF; + RETURN 0; +END Bomqtyonhand; +/ diff --git a/migration/340s-trunk/183_Bompricelimit.sql b/migration/340s-trunk/183_Bompricelimit.sql new file mode 100644 index 0000000000..4294c57bbc --- /dev/null +++ b/migration/340s-trunk/183_Bompricelimit.sql @@ -0,0 +1,53 @@ +CREATE OR REPLACE FUNCTION Bompricelimit +( + Product_ID IN NUMBER, + PriceList_Version_ID IN NUMBER +) +RETURN NUMBER +/************************************************************************* + * The contents of this file are subject to the Compiere License. You may + * obtain a copy of the License at http://www.compiere.org/license.html + * Software is on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for details. Code: Compiere ERP+CRM + * Copyright (C) 1999-2002 Jorg Janke, ComPiere, Inc. All Rights Reserved. + ************************************************************************* + * $Id: BOM_PriceLimit.sql,v 1.1 2006/04/21 17:51:58 jjanke Exp $ + *** + * Title: Return Limit Price of Product/BOM + * Description: + * if not found: 0 + ************************************************************************/ +AS + v_Price NUMBER; + v_ProductPrice NUMBER; + -- Get BOM Product info + CURSOR CUR_BOM IS + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM + FROM M_PRODUCT_BOM b, M_PRODUCT p + WHERE b.M_ProductBOM_ID=p.M_Product_ID + AND b.M_Product_ID=Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = Product_ID; + -- +BEGIN + -- Try to get price from PriceList directly + SELECT COALESCE (SUM(PriceLimit), 0) + INTO v_Price + FROM M_PRODUCTPRICE + WHERE M_PriceList_Version_ID=PriceList_Version_ID AND M_Product_ID=Product_ID; +-- DBMS_OUTPUT.PUT_LINE('Price=' || v_Price); + + -- No Price - Check if BOM + IF (v_Price = 0) THEN + FOR bom IN CUR_BOM LOOP + v_ProductPrice := Bompricelimit (bom.M_ProductBOM_ID, PriceList_Version_ID); + v_Price := v_Price + (bom.BOMQty * v_ProductPrice); + END LOOP; + END IF; + -- + RETURN v_Price; +END Bompricelimit; +/ diff --git a/migration/340s-trunk/184_Bompricelist.sql b/migration/340s-trunk/184_Bompricelist.sql new file mode 100644 index 0000000000..0de404cc7e --- /dev/null +++ b/migration/340s-trunk/184_Bompricelist.sql @@ -0,0 +1,54 @@ +CREATE OR REPLACE FUNCTION Bompricelist +( + Product_ID IN NUMBER, + PriceList_Version_ID IN NUMBER +) +RETURN NUMBER +/************************************************************************* + * The contents of this file are subject to the Compiere License. You may + * obtain a copy of the License at http://www.compiere.org/license.html + * Software is on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for details. Code: Compiere ERP+CRM + * Copyright (C) 1999-2002 Jorg Janke, ComPiere, Inc. All Rights Reserved. + ************************************************************************* + * $Id: BOM_PriceList.sql,v 1.1 2006/04/21 17:51:58 jjanke Exp $ + *** + * Title: Return List Price of Product/BOM + * Description: + * if not found: 0 + ************************************************************************/ +AS + v_Price NUMBER; + v_ProductPrice NUMBER; + -- Get BOM Product info + CURSOR CUR_BOM IS + /*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM + FROM M_PRODUCT_BOM b, M_PRODUCT p + WHERE b.M_ProductBOM_ID=p.M_Product_ID + AND b.M_Product_ID=Product_ID;*/ + SELECT bl.M_Product_ID AS M_ProductBOM_ID, CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM + FROM PP_PRODUCT_BOM b + INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) + INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + WHERE b.M_Product_ID = Product_ID; + -- +BEGIN + -- Try to get price from pricelist directly + SELECT COALESCE (SUM(PriceList), 0) + INTO v_Price + FROM M_PRODUCTPRICE + WHERE M_PriceList_Version_ID=PriceList_Version_ID AND M_Product_ID=Product_ID; +-- DBMS_OUTPUT.PUT_LINE('Price=' || Price); + + -- No Price - Check if BOM + IF (v_Price = 0) THEN + FOR bom IN CUR_BOM LOOP + v_ProductPrice := Bompricelist (bom.M_ProductBOM_ID, PriceList_Version_ID); + v_Price := v_Price + (bom.BOMQty * v_ProductPrice); + -- DBMS_OUTPUT.PUT_LINE('Qry=' || bom.BOMQty || ' @ ' || v_ProductPrice || ', Price=' || v_Price); + END LOOP; -- BOM + END IF; + -- + RETURN v_Price; +END Bompricelist; +/ diff --git a/migration/340s-trunk/postgresql/169_fix_wrong_reference.sql b/migration/340s-trunk/postgresql/169_fix_wrong_reference.sql new file mode 100644 index 0000000000..8f2cdd48ef --- /dev/null +++ b/migration/340s-trunk/postgresql/169_fix_wrong_reference.sql @@ -0,0 +1,2 @@ +UPDATE AD_COLUMN SET ad_reference_id = 29 WHERE ad_column_id = 54301 +; \ No newline at end of file diff --git a/migration/340s-trunk/postgresql/170_version351a.sql b/migration/340s-trunk/postgresql/170_version351a.sql new file mode 100644 index 0000000000..ad57e981ea --- /dev/null +++ b/migration/340s-trunk/postgresql/170_version351a.sql @@ -0,0 +1,6 @@ +UPDATE AD_SYSTEM + SET releaseno = '351a', + VERSION = '2008-05-29' + WHERE ad_system_id = 0 AND ad_client_id = 0; + +COMMIT ; diff --git a/migration/340s-trunk/postgresql/173_InvoiceOpenToDate.sql b/migration/340s-trunk/postgresql/173_InvoiceOpenToDate.sql new file mode 100644 index 0000000000..0212aa195b --- /dev/null +++ b/migration/340s-trunk/postgresql/173_InvoiceOpenToDate.sql @@ -0,0 +1 @@ +-- placeholder for postgresl - script is just for oracle \ No newline at end of file diff --git a/migration/340s-trunk/postgresql/174_InvoicepaidToDate.sql b/migration/340s-trunk/postgresql/174_InvoicepaidToDate.sql new file mode 100644 index 0000000000..0212aa195b --- /dev/null +++ b/migration/340s-trunk/postgresql/174_InvoicepaidToDate.sql @@ -0,0 +1 @@ +-- placeholder for postgresl - script is just for oracle \ No newline at end of file diff --git a/migration/340s-trunk/postgresql/175_BomqtyavailableASI.sql b/migration/340s-trunk/postgresql/175_BomqtyavailableASI.sql new file mode 100644 index 0000000000..0212aa195b --- /dev/null +++ b/migration/340s-trunk/postgresql/175_BomqtyavailableASI.sql @@ -0,0 +1 @@ +-- placeholder for postgresl - script is just for oracle \ No newline at end of file diff --git a/migration/340s-trunk/postgresql/176_BomqtyonhandASI.sql b/migration/340s-trunk/postgresql/176_BomqtyonhandASI.sql new file mode 100644 index 0000000000..0212aa195b --- /dev/null +++ b/migration/340s-trunk/postgresql/176_BomqtyonhandASI.sql @@ -0,0 +1 @@ +-- placeholder for postgresl - script is just for oracle \ No newline at end of file diff --git a/migration/340s-trunk/postgresql/177_BomqtyorderedASI.sql b/migration/340s-trunk/postgresql/177_BomqtyorderedASI.sql new file mode 100644 index 0000000000..0212aa195b --- /dev/null +++ b/migration/340s-trunk/postgresql/177_BomqtyorderedASI.sql @@ -0,0 +1 @@ +-- placeholder for postgresl - script is just for oracle \ No newline at end of file diff --git a/migration/340s-trunk/postgresql/178_BomqtyreservedASI.sql b/migration/340s-trunk/postgresql/178_BomqtyreservedASI.sql new file mode 100644 index 0000000000..0212aa195b --- /dev/null +++ b/migration/340s-trunk/postgresql/178_BomqtyreservedASI.sql @@ -0,0 +1 @@ +-- placeholder for postgresl - script is just for oracle \ No newline at end of file diff --git a/migration/340s-trunk/postgresql/179_Bomqtyordered.sql b/migration/340s-trunk/postgresql/179_Bomqtyordered.sql new file mode 100644 index 0000000000..0212aa195b --- /dev/null +++ b/migration/340s-trunk/postgresql/179_Bomqtyordered.sql @@ -0,0 +1 @@ +-- placeholder for postgresl - script is just for oracle \ No newline at end of file diff --git a/migration/340s-trunk/postgresql/180_Bompricestd.sql b/migration/340s-trunk/postgresql/180_Bompricestd.sql new file mode 100644 index 0000000000..0212aa195b --- /dev/null +++ b/migration/340s-trunk/postgresql/180_Bompricestd.sql @@ -0,0 +1 @@ +-- placeholder for postgresl - script is just for oracle \ No newline at end of file diff --git a/migration/340s-trunk/postgresql/181_Bomqtyreserved.sql b/migration/340s-trunk/postgresql/181_Bomqtyreserved.sql new file mode 100644 index 0000000000..0212aa195b --- /dev/null +++ b/migration/340s-trunk/postgresql/181_Bomqtyreserved.sql @@ -0,0 +1 @@ +-- placeholder for postgresl - script is just for oracle \ No newline at end of file diff --git a/migration/340s-trunk/postgresql/182_Bomqtyonhand.sql b/migration/340s-trunk/postgresql/182_Bomqtyonhand.sql new file mode 100644 index 0000000000..0212aa195b --- /dev/null +++ b/migration/340s-trunk/postgresql/182_Bomqtyonhand.sql @@ -0,0 +1 @@ +-- placeholder for postgresl - script is just for oracle \ No newline at end of file diff --git a/migration/340s-trunk/postgresql/183_Bompricelimit.sql b/migration/340s-trunk/postgresql/183_Bompricelimit.sql new file mode 100644 index 0000000000..0212aa195b --- /dev/null +++ b/migration/340s-trunk/postgresql/183_Bompricelimit.sql @@ -0,0 +1 @@ +-- placeholder for postgresl - script is just for oracle \ No newline at end of file diff --git a/migration/340s-trunk/postgresql/184_Bompricelist.sql b/migration/340s-trunk/postgresql/184_Bompricelist.sql new file mode 100644 index 0000000000..0212aa195b --- /dev/null +++ b/migration/340s-trunk/postgresql/184_Bompricelist.sql @@ -0,0 +1 @@ +-- placeholder for postgresl - script is just for oracle \ No newline at end of file