Merged release-1.0c into development

This commit is contained in:
Heng Sin Low 2013-09-24 17:17:53 +08:00
commit d95c2af901
31 changed files with 1911 additions and 1915 deletions

View File

@ -1,4 +1,4 @@
CREATE OR REPLACE FUNCTION Bompricelimit CREATE OR REPLACE FUNCTION BOMPRICELIMIT
( (
Product_ID IN NUMBER, Product_ID IN NUMBER,
PriceList_Version_ID IN NUMBER PriceList_Version_ID IN NUMBER
@ -22,15 +22,12 @@ AS
v_ProductPrice NUMBER; v_ProductPrice NUMBER;
-- Get BOM Product info -- Get BOM Product info
CURSOR CUR_BOM IS CURSOR CUR_BOM IS
/*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM
FROM M_PRODUCT_BOM b, M_PRODUCT p FROM M_PRODUCT_BOM b, M_PRODUCT p
WHERE b.M_ProductBOM_ID=p.M_Product_ID 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 AND p.IsBOM='Y'
FROM PP_PRODUCT_BOM b AND p.IsVerified='Y';
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 BEGIN
-- Try to get price from PriceList directly -- Try to get price from PriceList directly
@ -51,3 +48,4 @@ BEGIN
RETURN v_Price; RETURN v_Price;
END Bompricelimit; END Bompricelimit;
/ /

View File

@ -1,4 +1,4 @@
CREATE OR REPLACE FUNCTION Bompricelist CREATE OR REPLACE FUNCTION BOMPRICELIST
( (
Product_ID IN NUMBER, Product_ID IN NUMBER,
PriceList_Version_ID IN NUMBER PriceList_Version_ID IN NUMBER
@ -22,15 +22,12 @@ AS
v_ProductPrice NUMBER; v_ProductPrice NUMBER;
-- Get BOM Product info -- Get BOM Product info
CURSOR CUR_BOM IS CURSOR CUR_BOM IS
/*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM
FROM M_PRODUCT_BOM b, M_PRODUCT p FROM M_PRODUCT_BOM b, M_PRODUCT p
WHERE b.M_ProductBOM_ID=p.M_Product_ID 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 AND p.IsBOM='Y'
FROM PP_PRODUCT_BOM b AND p.IsVerified='Y';
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 BEGIN
-- Try to get price from pricelist directly -- Try to get price from pricelist directly
@ -52,3 +49,4 @@ BEGIN
RETURN v_Price; RETURN v_Price;
END Bompricelist; END Bompricelist;
/ /

View File

@ -1,4 +1,4 @@
CREATE OR REPLACE FUNCTION Bompricestd CREATE OR REPLACE FUNCTION BOMPRICESTD
( (
Product_ID IN NUMBER, Product_ID IN NUMBER,
PriceList_Version_ID IN NUMBER PriceList_Version_ID IN NUMBER
@ -22,15 +22,12 @@ AS
v_ProductPrice NUMBER; v_ProductPrice NUMBER;
-- Get BOM Product info -- Get BOM Product info
CURSOR CUR_BOM IS CURSOR CUR_BOM IS
/*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM
FROM M_PRODUCT_BOM b, M_PRODUCT p FROM M_PRODUCT_BOM b, M_PRODUCT p
WHERE b.M_ProductBOM_ID=p.M_Product_ID 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 AND p.IsBOM='Y'
FROM PP_PRODUCT_BOM b AND p.IsVerified='Y';
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 BEGIN
-- Try to get price from pricelist directly -- Try to get price from pricelist directly
@ -52,3 +49,4 @@ BEGIN
RETURN v_Price; RETURN v_Price;
END Bompricestd; END Bompricestd;
/ /

View File

@ -1,4 +1,4 @@
CREATE OR REPLACE FUNCTION bomQtyAvailable CREATE OR REPLACE FUNCTION BOMQTYAVAILABLE
( (
Product_ID IN NUMBER, Product_ID IN NUMBER,
Warehouse_ID IN NUMBER, Warehouse_ID IN NUMBER,
@ -19,3 +19,4 @@ BEGIN
- bomQtyReserved(Product_ID, Warehouse_ID, Locator_ID); - bomQtyReserved(Product_ID, Warehouse_ID, Locator_ID);
END bomQtyAvailable; END bomQtyAvailable;
/ /

View File

@ -1,22 +0,0 @@
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;
/

View File

@ -1,4 +1,4 @@
CREATE OR REPLACE FUNCTION Bomqtyonhand CREATE OR REPLACE FUNCTION BOMQTYONHAND
( (
Product_ID IN NUMBER, Product_ID IN NUMBER,
Warehouse_ID IN NUMBER, Warehouse_ID IN NUMBER,
@ -23,15 +23,12 @@ AS
StdPrecision NUMBER; StdPrecision NUMBER;
-- Get BOM Product info -- Get BOM Product info
CURSOR CUR_BOM IS CURSOR CUR_BOM IS
/*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType
FROM M_PRODUCT_BOM b, M_PRODUCT p FROM M_PRODUCT_BOM b, M_PRODUCT p
WHERE b.M_ProductBOM_ID=p.M_Product_ID WHERE b.M_ProductBOM_ID=p.M_Product_ID
AND b.M_Product_ID=p_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 , p.IsStocked, p.ProductType AND p.IsBOM='Y'
FROM PP_PRODUCT_BOM b AND p.IsVerified='Y';
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 BEGIN
-- Check Parameters -- Check Parameters
@ -123,3 +120,4 @@ BEGIN
RETURN 0; RETURN 0;
END Bomqtyonhand; END Bomqtyonhand;
/ /

View File

@ -1,128 +0,0 @@
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;
/

View File

@ -1,4 +1,4 @@
CREATE OR REPLACE FUNCTION Bomqtyordered CREATE OR REPLACE FUNCTION BOMQTYORDERED
( (
p_Product_ID IN NUMBER, p_Product_ID IN NUMBER,
p_Warehouse_ID IN NUMBER, p_Warehouse_ID IN NUMBER,
@ -23,15 +23,12 @@ AS
v_StdPrecision NUMBER; v_StdPrecision NUMBER;
-- Get BOM Product info -- Get BOM Product info
CURSOR CUR_BOM IS CURSOR CUR_BOM IS
/*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType
FROM M_PRODUCT_BOM b, M_PRODUCT p FROM M_PRODUCT_BOM b, M_PRODUCT p
WHERE b.M_ProductBOM_ID=p.M_Product_ID 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 AND p.IsBOM='Y'
FROM PP_PRODUCT_BOM b AND p.IsVerified='Y';
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 BEGIN
-- Check Parameters -- Check Parameters
@ -129,3 +126,4 @@ BEGIN
RETURN 0; RETURN 0;
END Bomqtyordered; END Bomqtyordered;
/ /

View File

@ -1,134 +0,0 @@
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;
/

View File

@ -1,4 +1,4 @@
CREATE OR REPLACE FUNCTION Bomqtyreserved CREATE OR REPLACE FUNCTION BOMQTYRESERVED
( (
p_Product_ID IN NUMBER, p_Product_ID IN NUMBER,
p_Warehouse_ID IN NUMBER, p_Warehouse_ID IN NUMBER,
@ -23,15 +23,12 @@ AS
v_StdPrecision NUMBER; v_StdPrecision NUMBER;
-- Get BOM Product info -- Get BOM Product info
CURSOR CUR_BOM IS CURSOR CUR_BOM IS
/*SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType
FROM M_PRODUCT_BOM b, M_PRODUCT p FROM M_PRODUCT_BOM b, M_PRODUCT p
WHERE b.M_ProductBOM_ID=p.M_Product_ID 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 AND p.IsBOM='Y'
FROM PP_PRODUCT_BOM b AND p.IsVerified='Y';
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 BEGIN
-- Check Parameters -- Check Parameters
@ -128,3 +125,4 @@ BEGIN
RETURN 0; RETURN 0;
END Bomqtyreserved; END Bomqtyreserved;
/ /

View File

@ -1,133 +0,0 @@
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;
/

View File

@ -1,50 +1,37 @@
/* CREATE OR REPLACE FUNCTION bompricelimit (in product_id numeric, in pricelist_version_id numeric) RETURNS numeric AS
*This file is part of Adempiere ERP Bazaar
*http://www.adempiere.org
*
*Copyright (C) 2006-2008 Antonio Cañaveral, e-Evolution
*
*This program is free software; you can redistribute it and/or
*modify it under the terms of the GNU General Public License
*as published by the Free Software Foundation; either version 2
*of the License, or (at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program; if not, write to the Free Software
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.of
*/
CREATE OR REPLACE FUNCTION bompricelimit(p_product_id numeric, p_pricelist_version_id numeric)
RETURNS numeric AS
$BODY$ $BODY$
DECLARE DECLARE
v_Price numeric; v_Price NUMERIC;
v_ProductPrice numeric; v_ProductPrice NUMERIC;
bom record; bom RECORD;
BEGIN BEGIN
-- Try to get price from PriceList directly -- Try to get price from PriceList directly
SELECT COALESCE (SUM(PriceLimit), 0) SELECT COALESCE (SUM(PriceLimit), 0)
INTO v_Price INTO v_Price
FROM M_PRODUCTPRICE FROM M_ProductPrice
WHERE M_PriceList_Version_ID=p_PriceList_Version_ID AND M_Product_ID=p_Product_ID; WHERE M_PriceList_Version_ID=PriceList_Version_ID AND M_Product_ID=Product_ID;
-- No Price - Check if BOM
IF (v_Price = 0) THEN IF (v_Price = 0) THEN
FOR bom in SELECT bl.M_Product_ID AS M_ProductBOM_ID, FOR bom IN
CASE WHEN bl.IsQtyPercentage = 'N' THEN bl.QtyBOM ELSE bl.QtyBatch / 100 END AS BomQty , p.IsBOM SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM
FROM PP_PRODUCT_BOM b FROM M_Product_BOM b, M_Product p
INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) WHERE b.M_ProductBOM_ID=p.M_Product_ID
INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) AND b.M_Product_ID=Product_ID
WHERE b.M_Product_ID = p_Product_ID AND p.IsBOM='Y'
AND p.IsVerified='Y'
LOOP LOOP
v_ProductPrice := Bompricelimit (bom.M_ProductBOM_ID, p_PriceList_Version_ID); v_ProductPrice := bomPriceLimit (bom.M_ProductBOM_ID, PriceList_Version_ID);
v_Price := v_Price + (bom.BOMQty * v_ProductPrice); v_Price := v_Price + (bom.BOMQty * v_ProductPrice);
END LOOP; END LOOP;
END IF; END IF;
-- --
RETURN v_Price; RETURN v_Price;
END; END;
$BODY$ $BODY$
LANGUAGE 'plpgsql' ; LANGUAGE 'plpgsql'
;

View File

@ -1,60 +1,37 @@
/* CREATE OR REPLACE FUNCTION bompricelist (in product_id numeric, in pricelist_version_id numeric) RETURNS numeric AS
*This file is part of Adempiere ERP Bazaar
*http://www.adempiere.org
*Copyright (C) 2006-2008 victor.perez@e-evolution.com, e-Evolution
*This program is free software; you can redistribute it and/or
*modify it under the terms of the GNU General Public License
*as published by the Free Software Foundation; either version 2
*of the License, or (at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program; if not, write to the Free Software
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.of
* Title: Return List Price of Product/BOM
* Description:
*/
CREATE OR REPLACE FUNCTION Bompricelist
(
Product_ID numeric,
PriceList_Version_ID numeric
)
RETURNS numeric
AS
$BODY$ $BODY$
DECLARE DECLARE
v_Price numeric; v_Price NUMERIC;
v_ProductPrice numeric; v_ProductPrice NUMERIC;
bom record; bom RECORD;
BEGIN BEGIN
-- Try to get price from pricelist directly -- Try to get price from pricelist directly
SELECT COALESCE (SUM(PriceList), 0) SELECT COALESCE (SUM(PriceList), 0)
INTO v_Price INTO v_Price
FROM M_PRODUCTPRICE FROM M_ProductPrice
WHERE M_PriceList_Version_ID=PriceList_Version_ID AND M_Product_ID=Product_ID; 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 -- No Price - Check if BOM
IF (v_Price = 0) THEN IF (v_Price = 0) THEN
FOR bom IN FOR bom IN
--Get BOM Product info SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM
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 M_Product_BOM b, M_Product p
FROM PP_PRODUCT_BOM b WHERE b.M_ProductBOM_ID=p.M_Product_ID
INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) AND b.M_Product_ID=Product_ID
INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) AND p.IsBOM='Y'
WHERE b.M_Product_ID = Product_ID AND p.IsVerified='Y'
LOOP 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); v_Price := v_Price + (bom.BOMQty * v_ProductPrice);
-- DBMS_OUTPUT.PUT_LINE('Qry=' || bom.BOMQty || ' @ ' || v_ProductPrice || ', Price=' || v_Price); END LOOP;
END LOOP; -- BOM
END IF; END IF;
-- --
RETURN v_Price; RETURN v_Price;
END; END;
$BODY$ $BODY$
LANGUAGE 'plpgsql' ; LANGUAGE 'plpgsql'
;

View File

@ -1,59 +1,37 @@
/* CREATE OR REPLACE FUNCTION bompricestd (in product_id numeric, in pricelist_version_id numeric) RETURNS numeric AS
*This file is part of Adempiere ERP Bazaar
*http://www.adempiere.org
*Copyright (C) 2006-2008 victor.perez@e-evolution.com, e-Evolution
*This program is free software; you can redistribute it and/or
*modify it under the terms of the GNU General Public License
*as published by the Free Software Foundation; either version 2
*of the License, or (at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program; if not, write to the Free Software
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.of
* Title: Return Standard Price of Product/BOM
* Description:
*/
CREATE OR REPLACE FUNCTION Bompricestd
(
Product_ID numeric,
PriceList_Version_ID numeric
)
RETURNS numeric
AS
$BODY$ $BODY$
DECLARE DECLARE
v_Price numeric; v_Price NUMERIC;
v_ProductPrice numeric; v_ProductPrice NUMERIC;
bom record; bom RECORD;
BEGIN BEGIN
-- Try to get price from pricelist directly -- Try to get price from PriceList directly
SELECT COALESCE(SUM(PriceStd), 0) SELECT COALESCE(SUM(PriceStd), 0)
INTO v_Price INTO v_Price
FROM M_PRODUCTPRICE FROM M_ProductPrice
WHERE M_PriceList_Version_ID=PriceList_Version_ID AND M_Product_ID=Product_ID; 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 -- No Price - Check if BOM
IF (v_Price = 0) THEN IF (v_Price = 0) THEN
FOR bom IN -- Get BOM Product info FOR bom IN
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 SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM
FROM PP_PRODUCT_BOM b FROM M_Product_BOM b, M_Product p
INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) WHERE b.M_ProductBOM_ID=p.M_Product_ID
INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) AND b.M_Product_ID=Product_ID
WHERE b.M_Product_ID = Product_ID AND p.IsBOM='Y'
AND p.IsVerified='Y'
LOOP 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); v_Price := v_Price + (bom.BOMQty * v_ProductPrice);
-- DBMS_OUTPUT.PUT_LINE('Price=' || v_Price); END LOOP;
END LOOP; -- BOM
END IF; END IF;
-- --
RETURN v_Price; RETURN v_Price;
END; END;
$BODY$ $BODY$
LANGUAGE 'plpgsql' ; LANGUAGE 'plpgsql'
;

View File

@ -1,26 +1,9 @@
/* CREATE OR REPLACE FUNCTION bomqtyavailable (in product_id numeric, in warehouse_id numeric, in locator_id numeric) RETURNS numeric AS
*This file is part of Adempiere ERP Bazaar
*http://www.adempiere.org
*Copyright (C) 2006-2008 victor.perez@e-evolution.com, e-Evolution
*This program is free software; you can redistribute it and/or
*modify it under the terms of the GNU General Public License
*as published by the Free Software Foundation; either version 2
*of the License, or (at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program; if not, write to the Free Software
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.of
*/
CREATE OR REPLACE FUNCTION bomQtyAvailable(Product_ID numeric, Warehouse_ID numeric ,Locator_ID numeric)
RETURNS numeric AS
$BODY$ $BODY$
BEGIN BEGIN
RETURN bomQtyOnHand(Product_ID, Warehouse_ID, Locator_ID) - bomQtyReserved(Product_ID, Warehouse_ID, Locator_ID); RETURN bomQtyOnHand(Product_ID, Warehouse_ID, Locator_ID) - bomQtyReserved(Product_ID, Warehouse_ID, Locator_ID);
END; END;
$BODY$ $BODY$
LANGUAGE 'plpgsql' ; LANGUAGE 'plpgsql'
;

View File

@ -1,27 +0,0 @@
/*
*This file is part of Adempiere ERP Bazaar
*http://www.adempiere.org
*Copyright (C) 2006-2008 carlos.ruiz@globalqss.com, GlobalQSS
*This program is free software; you can redistribute it and/or
*modify it under the terms of the GNU General Public License
*as published by the Free Software Foundation; either version 2
*of the License, or (at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program; if not, write to the Free Software
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.of
*/
CREATE OR REPLACE FUNCTION bomQtyAvailableASI(Product_ID numeric, AttributeSetInstance_ID numeric, Warehouse_ID numeric ,Locator_ID numeric)
RETURNS numeric AS
$BODY$
BEGIN
RETURN bomQtyOnHandASI(Product_ID, AttributeSetInstance_ID, Warehouse_ID, Locator_ID) -
bomQtyReservedASI(Product_ID, AttributeSetInstance_ID, Warehouse_ID, Locator_ID);
END;
$BODY$
LANGUAGE 'plpgsql' ;

View File

@ -1,29 +1,4 @@
/* CREATE OR REPLACE FUNCTION bomqtyonhand (in product_id numeric, in warehouse_id numeric, in locator_id numeric) RETURNS numeric AS
*This file is part of Adempiere ERP Bazaar
*http://www.adempiere.org
*Copyright (C) 2006-2008 victor.perez@e-evolution.com, e-Evolution
*This program is free software; you can redistribute it and/or
*modify it under the terms of the GNU General Public License
*as published by the Free Software Foundation; either version 2
*of the License, or (at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program; if not, write to the Free Software
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.of
*/
CREATE OR REPLACE FUNCTION Bomqtyonhand
(
Product_ID numeric,
Warehouse_ID numeric,
Locator_ID numeric -- Only used, if warehouse is null
)
RETURNS numeric
AS
$BODY$ $BODY$
DECLARE DECLARE
myWarehouse_ID numeric; myWarehouse_ID numeric;
@ -50,7 +25,7 @@ BEGIN
IF (myWarehouse_ID IS NULL) THEN IF (myWarehouse_ID IS NULL) THEN
RETURN 0; RETURN 0;
END IF; END IF;
-- DBMS_OUTPUT.PUT_LINE('Warehouse=' || myWarehouse_ID); -- DBMS_OUTPUT.PUT_LINE(''Warehouse='' || myWarehouse_ID);
-- Check, if product exists and if it is stocked -- Check, if product exists and if it is stocked
BEGIN BEGIN
@ -76,18 +51,19 @@ BEGIN
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); AND l.M_Warehouse_ID=myWarehouse_ID);
-- --
-- DBMS_OUTPUT.PUT_LINE('Qty=' || v_ProductQty); -- DBMS_OUTPUT.PUT_LINE(''Qty='' || v_ProductQty);
RETURN v_ProductQty; RETURN v_ProductQty;
END IF; END IF;
-- Go though BOM -- Go though BOM
-- DBMS_OUTPUT.PUT_LINE('BOM'); -- DBMS_OUTPUT.PUT_LINE(''BOM'');
FOR bom IN -- Get BOM Product info FOR bom IN -- Get BOM Product info
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 SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType
FROM PP_PRODUCT_BOM b FROM M_PRODUCT_BOM b, M_PRODUCT p
INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) WHERE b.M_ProductBOM_ID=p.M_Product_ID
INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) AND b.M_Product_ID=product_ID
WHERE b.M_Product_ID = Product_ID AND p.IsBOM='Y'
AND p.IsVerified='Y'
LOOP LOOP
-- Stocked Items "leaf node" -- Stocked Items "leaf node"
IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN
@ -131,4 +107,6 @@ BEGIN
RETURN 0; RETURN 0;
END; END;
$BODY$ $BODY$
LANGUAGE 'plpgsql' ; LANGUAGE 'plpgsql'
;

View File

@ -1,138 +0,0 @@
/*
*This file is part of Adempiere ERP Bazaar
*http://www.adempiere.org
*Copyright (C) 2006-2008 victor.perez@e-evolution.com, e-Evolution
*This program is free software; you can redistribute it and/or
*modify it under the terms of the GNU General Public License
*as published by the Free Software Foundation; either version 2
*of the License, or (at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program; if not, write to the Free Software
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.of
* Return quantity on hand for BOM ASI
*/
CREATE OR REPLACE FUNCTION BomqtyonhandASI
(
Product_ID numeric,
AttributeSetInstance_ID numeric,
Warehouse_ID numeric,
Locator_ID numeric -- Only used, if warehouse is null
)
RETURNS numeric
AS
$BODY$
DECLARE
myWarehouse_ID numeric;
v_Quantity numeric := 99999; -- unlimited
v_IsBOM CHAR(1);
v_IsStocked CHAR(1);
v_ProductType CHAR(1);
v_ProductQty numeric;
v_StdPrecision numeric;
bom record;
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 v_IsBOM, v_ProductType, v_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 (v_IsBOM='N' AND (v_ProductType<>'I' OR v_IsStocked='N')) THEN
RETURN v_Quantity;
-- Stocked item
ELSIF (v_IsStocked='Y') THEN
-- Get v_ProductQty
SELECT COALESCE(SUM(QtyOnHand), 0)
INTO v_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 COALESCE(AttributeSetInstance_ID,0) = 0);
--
-- DBMS_OUTPUT.PUT_LINE('Qty=' || v_ProductQty);
RETURN v_ProductQty;
END IF;
-- Go though BOM
-- DBMS_OUTPUT.PUT_LINE('BOM');
FOR bom IN
-- Get BOM Product info
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
LOOP
-- Stocked Items "leaf node"
IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN
-- Get v_ProductQty
SELECT COALESCE(SUM(QtyOnHand), 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=myWarehouse_ID)
AND (s.M_AttributeSetInstance_ID = AttributeSetInstance_ID OR COALESCE(AttributeSetInstance_ID,0) = 0);
-- Get Rounding Precision
SELECT COALESCE(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 := BomqtyonhandASI (bom.M_ProductBOM_ID, AttributeSetInstance_ID, myWarehouse_ID, 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
IF (v_Quantity > 0) THEN
-- Get Rounding Precision for Product
SELECT COALESCE(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=Product_ID;
--
RETURN ROUND (v_Quantity, v_StdPrecision );
END IF;
RETURN 0;
END;
$BODY$
LANGUAGE 'plpgsql' ;

View File

@ -1,30 +1,4 @@
/* CREATE OR REPLACE FUNCTION bomqtyordered (in p_product_id numeric, in p_warehouse_id numeric, in p_locator_id numeric) RETURNS numeric AS
*This file is part of Adempiere ERP Bazaar
*http://www.adempiere.org
*Copyright (C) 2006-2008 victor.perez@e-evolution.com, e-Evolution
*This program is free software; you can redistribute it and/or
*modify it under the terms of the GNU General Public License
*as published by the Free Software Foundation; either version 2
*of the License, or (at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program; if not, write to the Free Software
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.of
* Return quantity ordered for BOM
*/
CREATE OR REPLACE FUNCTION Bomqtyordered
(
p_Product_ID numeric,
p_Warehouse_ID numeric,
p_Locator_ID numeric -- Only used, if warehouse is null
)
RETURNS numeric
AS
$BODY$ $BODY$
DECLARE DECLARE
v_Warehouse_ID numeric; v_Warehouse_ID numeric;
@ -50,7 +24,7 @@ BEGIN
IF (v_Warehouse_ID IS NULL) THEN IF (v_Warehouse_ID IS NULL) THEN
RETURN 0; RETURN 0;
END IF; END IF;
-- DBMS_OUTPUT.PUT_LINE('Warehouse=' || v_Warehouse_ID); -- DBMS_OUTPUT.PUT_LINE(''Warehouse='' || v_Warehouse_ID);
-- Check, if product exists and if it is stocked -- Check, if product exists and if it is stocked
BEGIN BEGIN
@ -81,14 +55,15 @@ BEGIN
END IF; END IF;
-- Go though BOM -- Go though BOM
-- DBMS_OUTPUT.PUT_LINE('BOM'); -- DBMS_OUTPUT.PUT_LINE(''BOM'');
FOR bom IN FOR bom IN
-- Get BOM Product info -- Get BOM Product info
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 SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType
FROM PP_PRODUCT_BOM b FROM M_PRODUCT_BOM b, M_PRODUCT p
INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) WHERE b.M_ProductBOM_ID=p.M_Product_ID
INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) AND b.M_Product_ID=p_Product_ID
WHERE b.M_Product_ID = p_Product_ID AND p.IsBOM='Y'
AND p.IsVerified='Y'
LOOP LOOP
-- Stocked Items "leaf node" -- Stocked Items "leaf node"
IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN
@ -139,4 +114,6 @@ BEGIN
RETURN 0; RETURN 0;
END; END;
$BODY$ $BODY$
LANGUAGE 'plpgsql' ; LANGUAGE 'plpgsql'
;

View File

@ -1,144 +0,0 @@
/*
*This file is part of Adempiere ERP Bazaar
*http://www.adempiere.org
*Copyright (C) 2006-2008 victor.perez@e-evolution.com, e-Evolution
*This program is free software; you can redistribute it and/or
*modify it under the terms of the GNU General Public License
*as published by the Free Software Foundation; either version 2
*of the License, or (at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program; if not, write to the Free Software
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.of
* Return quantity ordered for BOM ASI
*/
CREATE OR REPLACE FUNCTION BomqtyorderedASI
(
p_Product_ID numeric,
AttributeSetInstance_ID numeric,
p_Warehouse_ID numeric,
p_Locator_ID numeric -- Only used, if warehouse is null
)
RETURNS numeric
AS
$BODY$
DECLARE
v_Warehouse_ID numeric;
v_Quantity numeric := 99999; -- unlimited
v_IsBOM CHAR(1);
v_IsStocked CHAR(1);
v_ProductType CHAR(1);
v_ProductQty numeric;
v_StdPrecision int;
bom record;
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 COALESCE(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 COALESCE(AttributeSetInstance_ID,0) = 0);
--
RETURN v_ProductQty;
END IF;
-- Go though BOM
-- DBMS_OUTPUT.PUT_LINE('BOM');
FOR bom IN
-- Get BOM Product info
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
LOOP
-- Stocked Items "leaf node"
IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN
-- Get ProductQty
SELECT COALESCE(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 COALESCE(AttributeSetInstance_ID,0) = 0);
-- Get Rounding Precision
SELECT COALESCE(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 COALESCE(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;
$BODY$
LANGUAGE 'plpgsql' ;

View File

@ -1,30 +1,4 @@
/* CREATE OR REPLACE FUNCTION bomqtyreserved (in p_product_id numeric, in p_warehouse_id numeric, in p_locator_id numeric) RETURNS numeric AS
*This file is part of Adempiere ERP Bazaar
*http://www.adempiere.org
*Copyright (C) 2006-2008 victor.perez@e-evolution.com, e-Evolution
*This program is free software; you can redistribute it and/or
*modify it under the terms of the GNU General Public License
*as published by the Free Software Foundation; either version 2
*of the License, or (at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program; if not, write to the Free Software
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.of
* Return quantity reserved for BOM
*/
CREATE OR REPLACE FUNCTION Bomqtyreserved
(
p_Product_ID numeric,
p_Warehouse_ID numeric,
p_Locator_ID numeric -- Only used, if warehouse is null
)
RETURNS numeric
AS
$BODY$ $BODY$
DECLARE DECLARE
v_Warehouse_ID numeric; v_Warehouse_ID numeric;
@ -50,7 +24,7 @@ BEGIN
IF (v_Warehouse_ID IS NULL) THEN IF (v_Warehouse_ID IS NULL) THEN
RETURN 0; RETURN 0;
END IF; END IF;
-- DBMS_OUTPUT.PUT_LINE('Warehouse=' || v_Warehouse_ID); -- DBMS_OUTPUT.PUT_LINE(''Warehouse='' || v_Warehouse_ID);
-- Check, if product exists and if it is stocked -- Check, if product exists and if it is stocked
BEGIN BEGIN
@ -81,14 +55,15 @@ BEGIN
END IF; END IF;
-- Go though BOM -- Go though BOM
-- DBMS_OUTPUT.PUT_LINE('BOM'); -- DBMS_OUTPUT.PUT_LINE(''BOM'');
FOR bom IN FOR bom IN
-- Get BOM Product info -- Get BOM Product info
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 SELECT b.M_ProductBOM_ID, b.BOMQty, p.IsBOM, p.IsStocked, p.ProductType
FROM PP_PRODUCT_BOM b FROM M_PRODUCT_BOM b, M_PRODUCT p
INNER JOIN M_PRODUCT p ON (p.M_Product_ID=b.M_Product_ID) WHERE b.M_ProductBOM_ID=p.M_Product_ID
INNER JOIN PP_PRODUCT_BOMLINE bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) AND b.M_Product_ID=p_Product_ID
WHERE b.M_Product_ID = p_Product_ID AND p.IsBOM='Y'
AND p.IsVerified='Y'
LOOP LOOP
-- Stocked Items "leaf node" -- Stocked Items "leaf node"
IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN
@ -137,4 +112,6 @@ BEGIN
RETURN 0; RETURN 0;
END; END;
$BODY$ $BODY$
LANGUAGE 'plpgsql' ; LANGUAGE 'plpgsql'
;

View File

@ -1,144 +0,0 @@
/*
*This file is part of Adempiere ERP Bazaar
*http://www.adempiere.org
*Copyright (C) 2006-2008 victor.perez@e-evolution.com, e-Evolution
*This program is free software; you can redistribute it and/or
*modify it under the terms of the GNU General Public License
*as published by the Free Software Foundation; either version 2
*of the License, or (at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program; if not, write to the Free Software
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.of
* Return quantity reserved for BOM ASI
*/
CREATE OR REPLACE FUNCTION BomqtyreservedASI
(
p_Product_ID numeric,
AttributeSetInstance_ID numeric,
p_Warehouse_ID numeric,
p_Locator_ID numeric -- Only used, if warehouse is null
)
RETURNS numeric
AS
$BODY$
DECLARE
v_Warehouse_ID numeric;
v_Quantity numeric := 99999; -- unlimited
v_IsBOM CHAR(1);
v_IsStocked CHAR(1);
v_ProductType CHAR(1);
v_ProductQty numeric;
v_StdPrecision int;
bom record;
--
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 COALESCE(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 COALESCE(AttributeSetInstance_ID,0) = 0);
--
RETURN v_ProductQty;
END IF;
-- Go though BOM
-- DBMS_OUTPUT.PUT_LINE('BOM');
FOR bom IN
--Get BOM Product info
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
LOOP
-- Stocked Items "leaf node"
IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN
-- Get ProductQty
SELECT COALESCE(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 COALESCE(AttributeSetInstance_ID,0) = 0);
-- Get Rounding Precision
SELECT COALESCE(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 COALESCE(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;
$BODY$
LANGUAGE 'plpgsql' ;

View File

@ -1,8 +1,3 @@
-- Aug 23, 2013 6:08:39 PM MYT
-- IDEMPIERE-1297 2Pack: Remove code for the lookup of record and reference using business key
UPDATE AD_SysConfig SET Value='IDEMPIERE-1298 2Pack: Support copying of data from one client to another',Updated=TO_DATE('2013-08-23 18:08:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_SysConfig_ID=50003
;
-- Aug 23, 2013 6:09:08 PM MYT -- Aug 23, 2013 6:09:08 PM MYT
-- IDEMPIERE-1298 2Pack: Support copying of data from one client to another -- IDEMPIERE-1298 2Pack: Support copying of data from one client to another
INSERT INTO AD_Table (ImportTable,CopyColumnsFromTable,IsSecurityEnabled,AccessLevel,LoadSeq,AD_Table_ID,IsHighVolume,IsView,IsChangeLog,EntityType,ReplicationType,AD_Table_UU,IsCentrallyMaintained,IsDeleteable,TableName,Description,Name,IsActive,AD_Org_ID,CreatedBy,Updated,UpdatedBy,Created,AD_Client_ID) VALUES ('N','N','N','2',0,200105,'Y','N','N','D','L','af0292e5-c824-47c2-b0cd-99ec92b9fc02','Y','Y','AD_Package_UUID_Map','UUID Mapping between client','UUID Mapping','Y',0,100,TO_DATE('2013-08-23 18:09:02','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2013-08-23 18:09:02','YYYY-MM-DD HH24:MI:SS'),0) INSERT INTO AD_Table (ImportTable,CopyColumnsFromTable,IsSecurityEnabled,AccessLevel,LoadSeq,AD_Table_ID,IsHighVolume,IsView,IsChangeLog,EntityType,ReplicationType,AD_Table_UU,IsCentrallyMaintained,IsDeleteable,TableName,Description,Name,IsActive,AD_Org_ID,CreatedBy,Updated,UpdatedBy,Created,AD_Client_ID) VALUES ('N','N','N','2',0,200105,'Y','N','N','D','L','af0292e5-c824-47c2-b0cd-99ec92b9fc02','Y','Y','AD_Package_UUID_Map','UUID Mapping between client','UUID Mapping','Y',0,100,TO_DATE('2013-08-23 18:09:02','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2013-08-23 18:09:02','YYYY-MM-DD HH24:MI:SS'),0)

View File

@ -0,0 +1,625 @@
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
AND p.IsBOM='Y'
AND p.IsVerified='Y';
--
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;
/
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
AND p.IsBOM='Y'
AND p.IsVerified='Y';
--
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;
/
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
AND p.IsBOM='Y'
AND p.IsVerified='Y';
--
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;
/
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=Product_ID
AND p.IsBOM='Y'
AND p.IsVerified='Y';
--
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;
/
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
AND p.IsBOM='Y'
AND p.IsVerified='Y';
--
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;
/
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
AND p.IsBOM='Y'
AND p.IsVerified='Y';
--
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;
/
CREATE OR REPLACE FUNCTION BOMQTYAVAILABLE
(
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 available for BOM
*/
AS
BEGIN
RETURN bomQtyOnHand(Product_ID, Warehouse_ID, Locator_ID)
- bomQtyReserved(Product_ID, Warehouse_ID, Locator_ID);
END bomQtyAvailable;
/
DROP FUNCTION BOMQTYAVAILABLEASI
;
DROP FUNCTION BOMQTYONHANDASI
;
DROP FUNCTION BOMQTYORDEREDASI
;
DROP FUNCTION BOMQTYRESERVEDASI
;
-- Sep 19, 2013 8:34:08 PM COT
-- IDEMPIERE-1370 Circular Reference in Product Info when a bom product is referenced to itself and its price-lists prices are set to zero
UPDATE AD_Process SET IsActive='N',Updated=TO_DATE('2013-09-19 20:34:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_ID=346
;
-- Sep 19, 2013 8:34:08 PM COT
UPDATE AD_Menu SET Name='Verify BOMs', Description='Verify BOM Structures', IsActive='N',Updated=TO_DATE('2013-09-19 20:34:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Menu_ID=585
;
-- Sep 19, 2013 8:36:42 PM COT
UPDATE AD_Process_Para SET IsMandatory='Y', DefaultValue='Y',Updated=TO_DATE('2013-09-19 20:36:42','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=53463
;
-- Sep 19, 2013 8:55:22 PM COT
UPDATE AD_Field SET IsReadOnly='Y',Updated=TO_DATE('2013-09-19 20:55:22','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=3746
;
-- Sep 19, 2013 8:55:55 PM COT
UPDATE AD_Field SET IsReadOnly='Y',Updated=TO_DATE('2013-09-19 20:55:55','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=59805
;
-- Sep 19, 2013 8:59:20 PM COT
UPDATE AD_Process_Para SET DefaultValue='@M_Product_ID@',Updated=TO_DATE('2013-09-19 20:59:20','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=53461
;
-- Sep 19, 2013 8:59:36 PM COT
UPDATE AD_Process_Para SET ReadOnlyLogic='@M_Product_ID@>0',Updated=TO_DATE('2013-09-19 20:59:36','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=53461
;
-- Sep 19, 2013 8:59:50 PM COT
UPDATE AD_Process_Para SET DisplayLogic='@M_Product_ID@=0',Updated=TO_DATE('2013-09-19 20:59:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=53462
;
-- Sep 19, 2013 9:12:59 PM COT
UPDATE AD_Process_Para SET DisplayLogic='@M_Product_ID@=0',Updated=TO_DATE('2013-09-19 21:12:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=53463
;
-- Sep 19, 2013 9:21:47 PM COT
UPDATE M_Product SET IsVerified='Y',Updated=TO_DATE('2013-09-19 21:21:47','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE M_Product_ID=133
;
-- Sep 19, 2013 9:21:47 PM COT
UPDATE M_Product SET IsVerified='Y',Updated=TO_DATE('2013-09-19 21:21:47','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE M_Product_ID=145
;
-- Sep 19, 2013 9:22:10 PM COT
UPDATE M_Product SET IsVerified='Y',Updated=TO_DATE('2013-09-19 21:22:10','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE M_Product_ID=50001
;
-- Sep 19, 2013 9:44:39 PM COT
UPDATE M_Product SET IsVerified='Y',Updated=TO_DATE('2013-09-19 21:44:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE M_Product_ID=50000
;
SELECT register_migration_script('201309192024_IDEMPIERE-1370.sql') FROM dual
;

View File

@ -1,8 +1,3 @@
-- Aug 23, 2013 6:08:39 PM MYT
-- IDEMPIERE-1297 2Pack: Remove code for the lookup of record and reference using business key
UPDATE AD_SysConfig SET Value='IDEMPIERE-1298 2Pack: Support copying of data from one client to another',Updated=TO_TIMESTAMP('2013-08-23 18:08:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_SysConfig_ID=50003
;
-- Aug 23, 2013 6:09:08 PM MYT -- Aug 23, 2013 6:09:08 PM MYT
-- IDEMPIERE-1298 2Pack: Support copying of data from one client to another -- IDEMPIERE-1298 2Pack: Support copying of data from one client to another
INSERT INTO AD_Table (ImportTable,CopyColumnsFromTable,IsSecurityEnabled,AccessLevel,LoadSeq,AD_Table_ID,IsHighVolume,IsView,IsChangeLog,EntityType,ReplicationType,AD_Table_UU,IsCentrallyMaintained,IsDeleteable,TableName,Description,Name,IsActive,AD_Org_ID,CreatedBy,Updated,UpdatedBy,Created,AD_Client_ID) VALUES ('N','N','N','2',0,200105,'Y','N','N','D','L','af0292e5-c824-47c2-b0cd-99ec92b9fc02','Y','Y','AD_Package_UUID_Map','UUID Mapping between client','UUID Mapping','Y',0,100,TO_TIMESTAMP('2013-08-23 18:09:02','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2013-08-23 18:09:02','YYYY-MM-DD HH24:MI:SS'),0) INSERT INTO AD_Table (ImportTable,CopyColumnsFromTable,IsSecurityEnabled,AccessLevel,LoadSeq,AD_Table_ID,IsHighVolume,IsView,IsChangeLog,EntityType,ReplicationType,AD_Table_UU,IsCentrallyMaintained,IsDeleteable,TableName,Description,Name,IsActive,AD_Org_ID,CreatedBy,Updated,UpdatedBy,Created,AD_Client_ID) VALUES ('N','N','N','2',0,200105,'Y','N','N','D','L','af0292e5-c824-47c2-b0cd-99ec92b9fc02','Y','Y','AD_Package_UUID_Map','UUID Mapping between client','UUID Mapping','Y',0,100,TO_TIMESTAMP('2013-08-23 18:09:02','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2013-08-23 18:09:02','YYYY-MM-DD HH24:MI:SS'),0)

View File

@ -0,0 +1,539 @@
CREATE OR REPLACE FUNCTION bompricelimit (in product_id numeric, in pricelist_version_id numeric) RETURNS numeric AS
$BODY$
DECLARE
v_Price NUMERIC;
v_ProductPrice NUMERIC;
bom RECORD;
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;
-- No Price - Check if BOM
IF (v_Price = 0) THEN
FOR bom IN
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 p.IsBOM='Y'
AND p.IsVerified='Y'
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;
$BODY$
LANGUAGE 'plpgsql'
;
CREATE OR REPLACE FUNCTION bompricelist (in product_id numeric, in pricelist_version_id numeric) RETURNS numeric AS
$BODY$
DECLARE
v_Price NUMERIC;
v_ProductPrice NUMERIC;
bom RECORD;
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;
-- No Price - Check if BOM
IF (v_Price = 0) THEN
FOR bom IN
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 p.IsBOM='Y'
AND p.IsVerified='Y'
LOOP
v_ProductPrice := bomPriceList (bom.M_ProductBOM_ID, PriceList_Version_ID);
v_Price := v_Price + (bom.BOMQty * v_ProductPrice);
END LOOP;
END IF;
--
RETURN v_Price;
END;
$BODY$
LANGUAGE 'plpgsql'
;
CREATE OR REPLACE FUNCTION bompricestd (in product_id numeric, in pricelist_version_id numeric) RETURNS numeric AS
$BODY$
DECLARE
v_Price NUMERIC;
v_ProductPrice NUMERIC;
bom RECORD;
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;
-- No Price - Check if BOM
IF (v_Price = 0) THEN
FOR bom IN
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 p.IsBOM='Y'
AND p.IsVerified='Y'
LOOP
v_ProductPrice := bomPriceStd (bom.M_ProductBOM_ID, PriceList_Version_ID);
v_Price := v_Price + (bom.BOMQty * v_ProductPrice);
END LOOP;
END IF;
--
RETURN v_Price;
END;
$BODY$
LANGUAGE 'plpgsql'
;
CREATE OR REPLACE FUNCTION bomqtyonhand (in product_id numeric, in warehouse_id numeric, in locator_id numeric) RETURNS numeric AS
$BODY$
DECLARE
myWarehouse_ID numeric;
v_Quantity numeric := 99999; -- unlimited
v_IsBOM CHAR(1);
v_IsStocked CHAR(1);
v_ProductType CHAR(1);
v_ProductQty numeric;
v_StdPrecision int;
bom record;
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 v_IsBOM, v_ProductType, v_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 (v_IsBOM='N' AND (v_ProductType<>'I' OR v_IsStocked='N')) THEN
RETURN v_Quantity;
-- Stocked item
ELSIF (v_IsStocked='Y') THEN
-- Get ProductQty
SELECT COALESCE(SUM(QtyOnHand), 0)
INTO v_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='' || v_ProductQty);
RETURN v_ProductQty;
END IF;
-- Go though BOM
-- DBMS_OUTPUT.PUT_LINE(''BOM'');
FOR bom IN -- Get BOM Product info
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 p.IsBOM='Y'
AND p.IsVerified='Y'
LOOP
-- Stocked Items "leaf node"
IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN
-- Get v_ProductQty
SELECT COALESCE(SUM(QtyOnHand), 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=myWarehouse_ID);
-- Get Rounding Precision
SELECT COALESCE(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 := Bomqtyonhand (bom.M_ProductBOM_ID, myWarehouse_ID, 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
IF (v_Quantity > 0) THEN
-- Get Rounding Precision for Product
SELECT COALESCE(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=Product_ID;
--
RETURN ROUND (v_Quantity, v_StdPrecision);
END IF;
RETURN 0;
END;
$BODY$
LANGUAGE 'plpgsql'
;
CREATE OR REPLACE FUNCTION bomqtyordered (in p_product_id numeric, in p_warehouse_id numeric, in p_locator_id numeric) RETURNS numeric AS
$BODY$
DECLARE
v_Warehouse_ID numeric;
v_Quantity numeric := 99999; -- unlimited
v_IsBOM CHAR(1);
v_IsStocked CHAR(1);
v_ProductType CHAR(1);
v_ProductQty numeric;
v_StdPrecision int;
bom record;
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 COALESCE(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
-- Get BOM Product info
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 p.IsBOM='Y'
AND p.IsVerified='Y'
LOOP
-- Stocked Items "leaf node"
IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN
-- Get ProductQty
SELECT COALESCE(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 COALESCE(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 COALESCE(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;
$BODY$
LANGUAGE 'plpgsql'
;
CREATE OR REPLACE FUNCTION bomqtyreserved (in p_product_id numeric, in p_warehouse_id numeric, in p_locator_id numeric) RETURNS numeric AS
$BODY$
DECLARE
v_Warehouse_ID numeric;
v_Quantity numeric := 99999; -- unlimited
v_IsBOM CHAR(1);
v_IsStocked CHAR(1);
v_ProductType CHAR(1);
v_ProductQty numeric;
v_StdPrecision int;
bom record;
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 COALESCE(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
-- Get BOM Product info
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 p.IsBOM='Y'
AND p.IsVerified='Y'
LOOP
-- Stocked Items "leaf node"
IF (bom.ProductType = 'I' AND bom.IsStocked = 'Y') THEN
-- Get ProductQty
SELECT COALESCE(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 COALESCE(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 COALESCE(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;
$BODY$
LANGUAGE 'plpgsql'
;
CREATE OR REPLACE FUNCTION bomqtyavailable (in product_id numeric, in warehouse_id numeric, in locator_id numeric) RETURNS numeric AS
$BODY$
BEGIN
RETURN bomQtyOnHand(Product_ID, Warehouse_ID, Locator_ID) - bomQtyReserved(Product_ID, Warehouse_ID, Locator_ID);
END;
$BODY$
LANGUAGE 'plpgsql'
;
DROP FUNCTION bomqtyavailable (in product_id numeric, in attributesetinstance_id numeric, in warehouse_id numeric, in locator_id numeric)
;
DROP FUNCTION bomqtyavailableasi (in product_id numeric, in attributesetinstance_id numeric, in warehouse_id numeric, in locator_id numeric)
;
DROP FUNCTION bomqtyonhandasi (in product_id numeric, in attributesetinstance_id numeric, in warehouse_id numeric, in locator_id numeric)
;
DROP FUNCTION bomqtyorderedasi (in p_product_id numeric, in attributesetinstance_id numeric, in p_warehouse_id numeric, in p_locator_id numeric)
;
DROP FUNCTION bomqtyreservedasi (in p_product_id numeric, in attributesetinstance_id numeric, in p_warehouse_id numeric, in p_locator_id numeric)
;
-- Sep 19, 2013 8:34:08 PM COT
-- IDEMPIERE-1370 Circular Reference in Product Info when a bom product is referenced to itself and its price-lists prices are set to zero
UPDATE AD_Process SET IsActive='N',Updated=TO_TIMESTAMP('2013-09-19 20:34:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_ID=346
;
-- Sep 19, 2013 8:34:08 PM COT
UPDATE AD_Menu SET Name='Verify BOMs', Description='Verify BOM Structures', IsActive='N',Updated=TO_TIMESTAMP('2013-09-19 20:34:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Menu_ID=585
;
-- Sep 19, 2013 8:36:42 PM COT
UPDATE AD_Process_Para SET IsMandatory='Y', DefaultValue='Y',Updated=TO_TIMESTAMP('2013-09-19 20:36:42','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=53463
;
-- Sep 19, 2013 8:55:22 PM COT
UPDATE AD_Field SET IsReadOnly='Y',Updated=TO_TIMESTAMP('2013-09-19 20:55:22','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=3746
;
-- Sep 19, 2013 8:55:55 PM COT
UPDATE AD_Field SET IsReadOnly='Y',Updated=TO_TIMESTAMP('2013-09-19 20:55:55','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=59805
;
-- Sep 19, 2013 8:59:20 PM COT
UPDATE AD_Process_Para SET DefaultValue='@M_Product_ID@',Updated=TO_TIMESTAMP('2013-09-19 20:59:20','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=53461
;
-- Sep 19, 2013 8:59:36 PM COT
UPDATE AD_Process_Para SET ReadOnlyLogic='@M_Product_ID@>0',Updated=TO_TIMESTAMP('2013-09-19 20:59:36','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=53461
;
-- Sep 19, 2013 8:59:50 PM COT
UPDATE AD_Process_Para SET DisplayLogic='@M_Product_ID@=0',Updated=TO_TIMESTAMP('2013-09-19 20:59:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=53462
;
-- Sep 19, 2013 9:12:59 PM COT
UPDATE AD_Process_Para SET DisplayLogic='@M_Product_ID@=0',Updated=TO_TIMESTAMP('2013-09-19 21:12:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=53463
;
-- Sep 19, 2013 9:21:47 PM COT
UPDATE M_Product SET IsVerified='Y',Updated=TO_TIMESTAMP('2013-09-19 21:21:47','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE M_Product_ID=133
;
-- Sep 19, 2013 9:21:47 PM COT
UPDATE M_Product SET IsVerified='Y',Updated=TO_TIMESTAMP('2013-09-19 21:21:47','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE M_Product_ID=145
;
-- Sep 19, 2013 9:22:10 PM COT
UPDATE M_Product SET IsVerified='Y',Updated=TO_TIMESTAMP('2013-09-19 21:22:10','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE M_Product_ID=50001
;
-- Sep 19, 2013 9:44:39 PM COT
UPDATE M_Product SET IsVerified='Y',Updated=TO_TIMESTAMP('2013-09-19 21:44:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE M_Product_ID=50000
;
SELECT register_migration_script('201309192024_IDEMPIERE-1370.sql') FROM dual
;

View File

@ -39,6 +39,8 @@ public class BOMVerify extends SvrProcess
/** Re-Validate */ /** Re-Validate */
private boolean p_IsReValidate = false; private boolean p_IsReValidate = false;
private boolean p_fromButton = false;
/** List of Products */ /** List of Products */
private ArrayList<MProduct> foundproducts = new ArrayList<MProduct>(); private ArrayList<MProduct> foundproducts = new ArrayList<MProduct>();
private ArrayList<MProduct> validproducts = new ArrayList<MProduct>(); private ArrayList<MProduct> validproducts = new ArrayList<MProduct>();
@ -68,6 +70,7 @@ public class BOMVerify extends SvrProcess
} }
if ( p_M_Product_ID == 0 ) if ( p_M_Product_ID == 0 )
p_M_Product_ID = getRecord_ID(); p_M_Product_ID = getRecord_ID();
p_fromButton = (getRecord_ID() > 0);
} // prepare } // prepare
/** /**
@ -155,9 +158,12 @@ public class BOMVerify extends SvrProcess
MProductBOM[] productsBOMs = MProductBOM.getBOMLines(product); MProductBOM[] productsBOMs = MProductBOM.getBOMLines(product);
boolean containsinvalid = false; boolean containsinvalid = false;
boolean invalid = false; boolean invalid = false;
for (int i = 0; i < productsBOMs.length; i++) int lines = 0;
for (MProductBOM productsBOM : productsBOMs)
{ {
MProductBOM productsBOM = productsBOMs[i]; if (! productsBOM.isActive())
continue;
lines++;
MProduct pp = new MProduct(getCtx(), productsBOM.getM_ProductBOM_ID(), get_TrxName()); MProduct pp = new MProduct(getCtx(), productsBOM.getM_ProductBOM_ID(), get_TrxName());
if (!pp.isBOM()) { if (!pp.isBOM()) {
if (log.isLoggable(Level.FINER)) log.finer(pp.getName()); if (log.isLoggable(Level.FINER)) log.finer(pp.getName());
@ -173,6 +179,9 @@ public class BOMVerify extends SvrProcess
else if (foundproducts.contains(pp)) else if (foundproducts.contains(pp))
{ {
invalid = true; invalid = true;
if (p_fromButton)
addLog(0, null, null, product.getValue() + " recursively contains " + pp.getValue());
else
addLog(0, null, null, product.getValue() + " recursively contains " + pp.getValue(), MProduct.Table_ID, product.getM_Product_ID()); addLog(0, null, null, product.getValue() + " recursively contains " + pp.getValue(), MProduct.Table_ID, product.getM_Product_ID());
} }
else else
@ -184,9 +193,14 @@ public class BOMVerify extends SvrProcess
} }
} }
}
if (lines == 0) {
invalid = true;
if (p_fromButton)
addLog(0, null, null, product.getValue() + " does not have lines");
else
addLog(0, null, null, product.getValue() + " does not have lines", MProduct.Table_ID, product.getM_Product_ID());
} }
checkedproducts.add(product); checkedproducts.add(product);

View File

@ -1,193 +0,0 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
* Portions created by Carlos Ruiz are Copyright (C) 2005 QSS Ltda.
* Contributor(s): Carlos Ruiz (globalqss)
*****************************************************************************/
package org.compiere.process;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Level;
import org.compiere.model.X_M_Product;
import org.compiere.util.AdempiereUserError;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.ValueNamePair;
/**
* Title: Check BOM Structure (free of cycles)
* Description:
* Tree cannot contain BOMs which are already referenced
*
* @author Carlos Ruiz (globalqss)
* @version $Id: M_Product_BOM_Check.java,v 1.0 2005/09/17 13:32:00 globalqss Exp $
* @author Carlos Ruiz (globalqss)
* Make T_Selection tables permanent
*/
public class M_Product_BOM_Check extends SvrProcess
{
/** The Record */
private int p_Record_ID = 0;
private int m_AD_PInstance_ID = 0;
/**
* Prepare - e.g., get Parameters.
*/
protected void prepare()
{
ProcessInfoParameter[] para = getParameter();
for (int i = 0; i < para.length; i++)
{
String name = para[i].getParameterName();
if (para[i].getParameter() == null)
;
else
log.log(Level.SEVERE, "Unknown Parameter: " + name);
}
p_Record_ID = getRecord_ID();
m_AD_PInstance_ID = getAD_PInstance_ID();
} // prepare
/**
* Process
* @return message
* @throws Exception
*/
protected String doIt() throws Exception
{
StringBuilder sql1 = null;
int no = 0;
log.info("Check BOM Structure");
// Record ID is M_Product_ID of product to be tested
X_M_Product xp = new X_M_Product(Env.getCtx(), p_Record_ID, get_TrxName());
if (! xp.isBOM()) {
log.info("NOT BOM Product");
// No BOM - should not happen, but no problem
xp.setIsVerified(true);
xp.saveEx(get_TrxName());
return "OK";
}
// Table to put all BOMs - duplicate will cause exception
sql1 = new StringBuilder("DELETE FROM T_Selection2 WHERE Query_ID = 0 AND AD_PInstance_ID=").append(m_AD_PInstance_ID);
no = DB.executeUpdate(sql1.toString(), get_TrxName());
sql1 = new StringBuilder("INSERT INTO T_Selection2 (AD_PInstance_ID, Query_ID, T_Selection_ID) VALUES (")
.append(m_AD_PInstance_ID)
.append(", 0, ")
.append(p_Record_ID).append(")");
no = DB.executeUpdate(sql1.toString(), get_TrxName());
// Table of root modes
sql1 = new StringBuilder("DELETE FROM T_Selection WHERE AD_PInstance_ID=").append(m_AD_PInstance_ID);
no = DB.executeUpdate(sql1.toString(), get_TrxName());
sql1 = new StringBuilder("INSERT INTO T_Selection (AD_PInstance_ID, T_Selection_ID) VALUES (")
.append(m_AD_PInstance_ID)
.append(", ")
.append(p_Record_ID).append(")");
no = DB.executeUpdate(sql1.toString(), get_TrxName());
while (true) {
// Get count remaining on t_selection
int countno = 0;
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
StringBuilder dbpst = new StringBuilder("SELECT COUNT(*) FROM T_Selection WHERE AD_PInstance_ID=").append(m_AD_PInstance_ID);
pstmt = DB.prepareStatement(dbpst.toString(), get_TrxName());
rs = pstmt.executeQuery();
if (rs.next())
countno = rs.getInt(1);
}
catch (SQLException e)
{
throw new Exception ("count t_selection", e);
}
finally
{
DB.close(rs, pstmt);
rs = null;
pstmt = null;
}
if (log.isLoggable(Level.FINE)) log.fine("Count T_Selection =" + countno);
if (countno == 0)
break;
try
{
// if any command fails (no==-1) break and inform failure
// Insert BOM Nodes into "All" table
sql1 = new StringBuilder("INSERT INTO T_Selection2 (AD_PInstance_ID, Query_ID, T_Selection_ID) ")
.append("SELECT ").append(m_AD_PInstance_ID).append(", 0, p.M_Product_ID FROM M_Product p WHERE IsBOM='Y' AND EXISTS ")
//+ "(SELECT * FROM M_Product_BOM b WHERE p.M_Product_ID=b.M_ProductBOM_ID AND b.M_Product_ID IN "
.append("(SELECT * FROM PP_Product_BOM b WHERE p.M_Product_ID=b.M_Product_ID AND b.M_Product_ID IN ")
.append("(SELECT T_Selection_ID FROM T_Selection WHERE AD_PInstance_ID=").append(m_AD_PInstance_ID).append("))");
no = DB.executeUpdate(sql1.toString(), get_TrxName());
if (no == -1) raiseError("InsertingRoot:ERROR", sql1.toString());
// Insert BOM Nodes into temporary table
sql1 = new StringBuilder("DELETE FROM T_Selection2 WHERE Query_ID = 1 AND AD_PInstance_ID=").append(m_AD_PInstance_ID);
no = DB.executeUpdate(sql1.toString(), get_TrxName());
if (no == -1) raiseError("InsertingRoot:ERROR", sql1.toString());
sql1 = new StringBuilder("INSERT INTO T_Selection2 (AD_PInstance_ID, Query_ID, T_Selection_ID) ")
.append("SELECT ").append(m_AD_PInstance_ID).append(", 1, p.M_Product_ID FROM M_Product p WHERE IsBOM='Y' AND EXISTS ")
//+ "(SELECT * FROM M_Product_BOM b WHERE p.M_Product_ID=b.M_ProductBOM_ID AND b.M_Product_ID IN "
.append("(SELECT * FROM PP_Product_BOM b WHERE p.M_Product_ID=b.M_Product_ID AND b.M_Product_ID IN ")
.append("(SELECT T_Selection_ID FROM T_Selection WHERE AD_PInstance_ID=").append(m_AD_PInstance_ID).append("))");
no = DB.executeUpdate(sql1.toString(), get_TrxName());
if (no == -1) raiseError("InsertingRoot:ERROR", sql1.toString());
// Copy into root table
sql1 = new StringBuilder("DELETE FROM T_Selection WHERE AD_PInstance_ID=").append(m_AD_PInstance_ID);
no = DB.executeUpdate(sql1.toString(), get_TrxName());
if (no == -1) raiseError("InsertingRoot:ERROR", sql1.toString());
sql1 = new StringBuilder("INSERT INTO T_Selection (AD_PInstance_ID, T_Selection_ID) ")
.append("SELECT ").append(m_AD_PInstance_ID).append(", T_Selection_ID ")
.append("FROM T_Selection2 WHERE Query_ID = 1 AND AD_PInstance_ID=").append(m_AD_PInstance_ID);
no = DB.executeUpdate(sql1.toString(), get_TrxName());
if (no == -1) raiseError("InsertingRoot:ERROR", sql1.toString());
}
catch (Exception e)
{
throw new Exception ("root insert", e);
}
}
// Finish process
xp.setIsVerified(true);
xp.saveEx(get_TrxName());
return "OK";
} // doIt
private void raiseError(String string, String sql) throws Exception {
DB.rollback(false, get_TrxName());
StringBuilder msg = new StringBuilder(string);
ValueNamePair pp = CLogger.retrieveError();
if (pp != null)
msg = new StringBuilder(pp.getName()).append(" - ");
msg.append(sql);
throw new AdempiereUserError (msg.toString());
}
} // M_Product_BOM_Check

View File

@ -21,6 +21,7 @@ import java.util.List;
import java.util.Properties; import java.util.Properties;
import org.compiere.util.CLogger; import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env; import org.compiere.util.Env;
/** /**
@ -37,8 +38,7 @@ public class MProductBOM extends X_M_Product_BOM
/** /**
* *
*/ */
private static final long serialVersionUID = 6029128559467083124L; private static final long serialVersionUID = 2615029184168566124L;
/** /**
* Get BOM Lines for Product * Get BOM Lines for Product
@ -96,7 +96,7 @@ public class MProductBOM extends X_M_Product_BOM
} // MProductBOM } // MProductBOM
/** /**
* Load Construvtor * Load Constructor
* @param ctx context * @param ctx context
* @param rs result set * @param rs result set
* @param trxName transaction * @param trxName transaction
@ -159,22 +159,51 @@ public class MProductBOM extends X_M_Product_BOM
{ {
if (!success) if (!success)
return success; return success;
// Product Line was changed
if (newRecord || is_ValueChanged("M_ProductBOM_ID"))
{
// Invalidate BOM
MProduct product = new MProduct (getCtx(), getM_Product_ID(), get_TrxName()); MProduct product = new MProduct (getCtx(), getM_Product_ID(), get_TrxName());
if (get_TrxName() != null) if (get_TrxName() != null)
product.load(get_TrxName()); product.load(get_TrxName());
if (product.isVerified()) if (product.isVerified())
{ {
if ( newRecord
|| is_ValueChanged("M_ProductBOM_ID") // Product Line was changed
|| (is_ValueChanged("IsActive") && isActive())) // line was activated
{
// Invalidate BOM
product.setIsVerified(false); product.setIsVerified(false);
product.saveEx(get_TrxName()); product.saveEx(get_TrxName());
} }
// Invalidate Products where BOM is used if (product.isVerified() && is_ValueChanged("IsActive") && !isActive()) { // line was inactivated
if (! hasActiveComponents(getM_Product_ID())) {
product.setIsVerified(false);
product.saveEx(get_TrxName());
}
}
} }
return success; return success;
} // afterSave } // afterSave
@Override
protected boolean afterDelete(boolean success) {
if (!success)
return success;
MProduct product = new MProduct (getCtx(), getM_Product_ID(), get_TrxName());
if (get_TrxName() != null)
product.load(get_TrxName());
if (product.isVerified())
{
if (! hasActiveComponents(getM_Product_ID())) {
product.setIsVerified(false);
product.saveEx(get_TrxName());
}
}
return success;
}
private boolean hasActiveComponents(int productID) {
int cnt = DB.getSQLValue(get_TrxName(),
"SELECT COUNT(*) FROM M_Product_BOM WHERE IsActive='Y' AND M_Product_ID=? AND M_Product_BOM_ID!=?",
productID, getM_Product_BOM_ID());
return cnt > 0;
}
} // MProductBOM } // MProductBOM

View File

@ -65,6 +65,7 @@ import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.MaximizeEvent; import org.zkoss.zk.ui.event.MaximizeEvent;
import org.zkoss.zul.Anchorchildren; import org.zkoss.zul.Anchorchildren;
import org.zkoss.zul.Anchorlayout; import org.zkoss.zul.Anchorlayout;
import org.zkoss.zul.Caption;
import org.zkoss.zul.Html; import org.zkoss.zul.Html;
import org.zkoss.zul.Iframe; import org.zkoss.zul.Iframe;
import org.zkoss.zul.Include; import org.zkoss.zul.Include;
@ -174,12 +175,13 @@ public class DashboardController implements EventListener<Event> {
} }
Panel panel = new Panel(); Panel panel = new Panel();
Caption caption = new Caption(dc.get_Translation(MDashboardContent.COLUMNNAME_Name));
panel.appendChild(caption);
panel.setAttribute("PA_DashboardContent_ID", dp.getPA_DashboardContent_ID()); panel.setAttribute("PA_DashboardContent_ID", dp.getPA_DashboardContent_ID());
panel.setAttribute("PA_DashboardPreference_ID", dp.getPA_DashboardPreference_ID()); panel.setAttribute("PA_DashboardPreference_ID", dp.getPA_DashboardPreference_ID());
panelList.add(panel); panelList.add(panel);
panel.addEventListener(Events.ON_MAXIMIZE, this); panel.addEventListener(Events.ON_MAXIMIZE, this);
panel.setSclass("dashboard-widget"); panel.setSclass("dashboard-widget");
panel.setTitle(dc.get_Translation(MDashboardContent.COLUMNNAME_Name));
panel.setMaximizable(true); panel.setMaximizable(true);
String description = dc.get_Translation(MDashboardContent.COLUMNNAME_Description); String description = dc.get_Translation(MDashboardContent.COLUMNNAME_Description);
@ -191,7 +193,7 @@ public class DashboardController implements EventListener<Event> {
panel.addEventListener(Events.ON_OPEN, this); panel.addEventListener(Events.ON_OPEN, this);
panel.setDroppable("true"); panel.setDroppable("true");
panel.setDraggable("true"); panel.getCaption().setDraggable("true");
panel.addEventListener(Events.ON_DROP, this); panel.addEventListener(Events.ON_DROP, this);
panel.setBorder("normal"); panel.setBorder("normal");
@ -471,11 +473,16 @@ public class DashboardController implements EventListener<Event> {
DropEvent de = (DropEvent) event; DropEvent de = (DropEvent) event;
Component dragged = de.getDragged(); Component dragged = de.getDragged();
if(dragged instanceof Panel) if(dragged instanceof Caption)
{ {
Panel panel = (Panel) dragged; Caption caption = (Caption) dragged;
Panel panel = null;
if (caption.getParent() instanceof Panel)
panel = (Panel) caption.getParent();
if(comp instanceof Panel) if (panel == null)
;
else if(comp instanceof Panel)
{ {
Panel target = (Panel) comp; Panel target = (Panel) comp;

View File

@ -592,10 +592,19 @@ div.wc-modal, div.wc-modal-none, div.wc-highlighted, div.wc-highlighted-none {
.z-panel-hl .z-panel-header { .z-panel-hl .z-panel-header {
padding: 0 0 2px 0; padding: 0 0 2px 0;
color: #262626; color: #262626;
background: #F4F4F4;
font-weight: 300; font-weight: 300;
font-size: 13px; font-size: 13px;
} }
.z-caption .z-caption-l, .z-caption .z-caption-r {
padding: 0 0 2px 0;
color: #262626;
font-weight: 300;
font-size: 13px;
cursor: move;
}
.desktop-home-tabpanel .z-panel-tl, .desktop-home-tabpanel .z-panel-tr, .desktop-home-tabpanel .z-panel-tl, .desktop-home-tabpanel .z-panel-tr,
.desktop-home-tabpanel .z-panel-hr, .desktop-home-tabpanel .z-panel-hl, .desktop-home-tabpanel .z-panel-hr, .desktop-home-tabpanel .z-panel-hl,
.desktop-home-tabpanel .z-panel-hm { .desktop-home-tabpanel .z-panel-hm {