IDEMPIERE-2668 Exclude Locators for Demand Operations

This commit is contained in:
Carlos Ruiz 2015-06-12 23:14:33 -05:00
parent bacfd1bcb2
commit 5cd07c4c26
30 changed files with 3493 additions and 63 deletions

View File

@ -15,7 +15,7 @@ RETURN NUMBER
*/
AS
BEGIN
RETURN bomQtyOnHand(Product_ID, Warehouse_ID, Locator_ID)
RETURN bomQtyOnHandForReservation(Product_ID, Warehouse_ID, Locator_ID)
- bomQtyReserved(Product_ID, Warehouse_ID, Locator_ID);
END bomQtyAvailable;
/

View File

@ -60,7 +60,7 @@ BEGIN
WHEN OTHERS THEN
RETURN 0;
END;
-- Unimited capacity if no item
-- Unlimited capacity if no item
IF (IsBOM='N' AND (ProductType<>'I' OR IsStocked='N')) THEN
RETURN Quantity;
-- Stocked item
@ -68,16 +68,15 @@ BEGIN
-- 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);
FROM M_Storageonhand s
JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID)
WHERE s.M_Product_ID=Product_ID AND l.M_Warehouse_ID=myWarehouse_ID;
--
-- DBMS_OUTPUT.PUT_LINE('Qty=' || ProductQty);
RETURN ProductQty;
END IF;
-- Go though BOM
-- Go through BOM
-- DBMS_OUTPUT.PUT_LINE('BOM');
FOR bom IN CUR_BOM LOOP
-- Stocked Items "leaf node"
@ -85,10 +84,9 @@ BEGIN
-- 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);
FROM M_Storageonhand s
JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID)
WHERE s.M_Product_ID=bom.M_ProductBOM_ID AND l.M_Warehouse_ID=myWarehouse_ID;
-- Get Rounding Precision
SELECT NVL(MAX(u.StdPrecision), 0)
INTO StdPrecision

View File

@ -0,0 +1,127 @@
CREATE OR REPLACE FUNCTION BOMQTYONHANDFORRESERVATION
(
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 b.M_ProductBOM_ID != Product_ID
AND p.IsBOM='Y'
AND p.IsVerified='Y'
AND b.IsActive='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;
-- Unlimited 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_Storageonhand s
JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID)
LEFT JOIN M_LocatorType lt ON (l.M_LocatorType_ID=lt.M_LocatorType_ID)
WHERE s.M_Product_ID=Product_ID AND l.M_Warehouse_ID=myWarehouse_ID
AND COALESCE(lt.IsAvailableForReservation,'Y')='Y';
--
-- DBMS_OUTPUT.PUT_LINE('Qty=' || ProductQty);
RETURN ProductQty;
END IF;
-- Go through 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_Storageonhand s
JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID)
LEFT JOIN M_LocatorType lt ON (l.M_LocatorType_ID=lt.M_LocatorType_ID)
WHERE s.M_Product_ID=bom.M_ProductBOM_ID AND l.M_Warehouse_ID=myWarehouse_ID
AND COALESCE(lt.IsAvailableForReservation,'Y')='Y';
-- 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 := BomqtyonhandForReservation (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 BOMQTYONHANDFORRESERVATION;
/

View File

@ -3,11 +3,14 @@ CREATE OR REPLACE VIEW M_PRODUCT_STOCK_V
AS
SELECT
ms.IsActive, ms.Created, ms.CreatedBy, ms.Updated, ms.UpdatedBy,
mp.VALUE, mp.help, (ms.qtyonhand - ms.qtyreserved) AS qtyavailable, ms.qtyonhand,
mp.VALUE, mp.help,
(CASE WHEN COALESCE(lt.IsAvailableForReservation,'Y')='Y' THEN ms.qtyonhand ELSE 0 END - ms.qtyreserved) AS qtyavailable,
ms.qtyonhand,
ms.qtyreserved, mp.description, mw.NAME AS warehouse, mw.m_warehouse_id, mw.ad_client_id,
mw.ad_org_id, mp.documentnote, mp.m_product_id
FROM M_STORAGE ms
JOIN M_PRODUCT mp ON ms.m_product_id = mp.m_product_id
JOIN M_LOCATOR ml ON ms.m_locator_id = ml.m_locator_id
LEFT JOIN M_LOCATORTYPE lt ON ml.m_locatortype_id = lt.m_locatortype_id
JOIN M_WAREHOUSE mw ON ml.m_warehouse_id = mw.m_warehouse_id
ORDER BY mw.NAME;

View File

@ -10,7 +10,7 @@ SELECT s.ad_client_id,
s.substitute_id,
'S' AS rowtype,
mp.name,
sum(ms.qtyonhand - ms.qtyreserved) AS qtyavailable,
sum(CASE WHEN COALESCE(lt.IsAvailableForReservation,'Y')='Y' THEN ms.qtyonhand ELSE 0 END - ms.qtyreserved) AS qtyavailable,
sum(ms.qtyonhand) AS qtyonhand,
sum(ms.qtyreserved) AS qtyreserved,
currencyRound(MAX(mpr.pricestd),mpl.C_Currency_ID,'N') AS pricestd,
@ -21,6 +21,7 @@ SELECT s.ad_client_id,
JOIN m_storage ms ON ms.m_product_id = s.substitute_id
JOIN m_product mp ON ms.m_product_id = mp.m_product_id
JOIN m_locator ml ON ms.m_locator_id = ml.m_locator_id
LEFT JOIN M_LOCATORTYPE lt ON ml.m_locatortype_id = lt.m_locatortype_id
JOIN m_warehouse mw ON ml.m_warehouse_id = mw.m_warehouse_id
JOIN m_productprice mpr ON ms.m_product_id = mpr.m_product_id
JOIN m_pricelist_version mplv ON mplv.m_pricelist_version_id = mpr.m_pricelist_version_id
@ -52,7 +53,7 @@ SELECT s.ad_client_id,
r.relatedproduct_id AS substitute_id,
'R' AS rowtype,
mp.name,
sum(ms.qtyonhand - ms.qtyreserved) AS qtyavailable,
sum(CASE WHEN COALESCE(lt.IsAvailableForReservation,'Y')='Y' THEN ms.qtyonhand ELSE 0 END - ms.qtyreserved) AS qtyavailable,
sum(ms.qtyonhand) AS qtyonhand,
sum(ms.qtyreserved) AS qtyreserved,
currencyRound(MAX(mpr.pricestd),mpl.C_Currency_ID,'N') AS pricestd,
@ -63,6 +64,7 @@ SELECT s.ad_client_id,
JOIN m_storage ms ON ms.m_product_id = r.relatedproduct_id
JOIN m_product mp ON ms.m_product_id = mp.m_product_id
JOIN m_locator ml ON ms.m_locator_id = ml.m_locator_id
LEFT JOIN M_LOCATORTYPE lt ON ml.m_locatortype_id = lt.m_locatortype_id
JOIN m_warehouse mw ON ml.m_warehouse_id = mw.m_warehouse_id
JOIN m_productprice mpr ON ms.m_product_id = mpr.m_product_id
JOIN m_pricelist_version mplv ON mplv.m_pricelist_version_id = mpr.m_pricelist_version_id
@ -81,4 +83,4 @@ SELECT s.ad_client_id,
mpr.m_pricelist_version_id,
org.name,
mp.name,
mpl.C_Currency_ID;
mpl.C_Currency_ID;

View File

@ -23,7 +23,7 @@ AS
l.z,
s.qtyonhand,
s.qtyreserved,
s.qtyonhand - s.qtyreserved AS qtyavailable,
CASE WHEN COALESCE(lt.IsAvailableForReservation,'Y')='Y' THEN s.qtyonhand ELSE 0 END - s.qtyreserved AS qtyavailable,
s.qtyordered,
s.datelastinventory,
s.m_attributesetinstance_id,
@ -102,6 +102,8 @@ AS
FROM m_storage s
JOIN m_locator l
ON s.m_locator_id = l.m_locator_id
LEFT JOIN m_locatortype lt
ON l.m_locatortype_id = lt.m_locatortype_id
JOIN m_product p
ON s.m_product_id = p.m_product_id
LEFT JOIN m_attributesetinstance asi

View File

@ -1,7 +1,7 @@
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);
RETURN bomQtyOnHandForReservation(Product_ID, Warehouse_ID, Locator_ID) - bomQtyReserved(Product_ID, Warehouse_ID, Locator_ID);
END;
$BODY$
LANGUAGE 'plpgsql' STABLE

View File

@ -1,4 +1,4 @@
CREATE OR REPLACE FUNCTION bomqtyonhand (in product_id numeric, in warehouse_id numeric, in locator_id numeric) RETURNS numeric AS
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;
@ -37,7 +37,7 @@ BEGIN
WHEN OTHERS THEN
RETURN 0;
END;
-- Unimited capacity if no item
-- Unlimited capacity if no item
IF (v_IsBOM='N' AND (v_ProductType<>'I' OR v_IsStocked='N')) THEN
RETURN v_Quantity;
-- Stocked item
@ -45,15 +45,14 @@ BEGIN
-- 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);
FROM M_Storageonhand s
JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID)
WHERE s.M_Product_ID=Product_ID AND l.M_Warehouse_ID=myWarehouse_ID;
--
RETURN v_ProductQty;
END IF;
-- Go though BOM
-- Go through 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
@ -69,10 +68,9 @@ BEGIN
-- 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);
FROM M_Storageonhand s
JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID)
WHERE s.M_Product_ID=bom.M_ProductBOM_ID AND l.M_Warehouse_ID=myWarehouse_ID;
-- Get Rounding Precision
SELECT COALESCE(MAX(u.StdPrecision), 0)
INTO v_StdPrecision

View File

@ -0,0 +1,113 @@
CREATE OR REPLACE FUNCTION BOMQtyOnHandForReservation (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;
-- 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;
-- Unlimited 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_Storageonhand s
JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID)
LEFT JOIN M_LocatorType lt ON (l.M_LocatorType_ID=lt.M_LocatorType_ID)
WHERE s.M_Product_ID=Product_ID AND l.M_Warehouse_ID=myWarehouse_ID
AND COALESCE(lt.IsAvailableForReservation,'Y')='Y';
--
RETURN v_ProductQty;
END IF;
-- Go through 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 b.M_ProductBOM_ID != Product_ID
AND p.IsBOM='Y'
AND p.IsVerified='Y'
AND b.IsActive='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_Storageonhand s
JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID)
LEFT JOIN M_LocatorType lt ON (l.M_LocatorType_ID=lt.M_LocatorType_ID)
WHERE s.M_Product_ID=bom.M_ProductBOM_ID AND l.M_Warehouse_ID=myWarehouse_ID
AND COALESCE(lt.IsAvailableForReservation,'Y')='Y';
-- 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 := BOMQtyOnHandForReservation (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' STABLE
;

View File

@ -3,11 +3,14 @@ CREATE OR REPLACE VIEW M_PRODUCT_STOCK_V
AS
SELECT
ms.IsActive, ms.Created, ms.CreatedBy, ms.Updated, ms.UpdatedBy,
mp.VALUE, mp.help, (ms.qtyonhand - ms.qtyreserved) AS qtyavailable, ms.qtyonhand,
mp.VALUE, mp.help,
(CASE WHEN COALESCE(lt.IsAvailableForReservation,'Y')='Y' THEN ms.qtyonhand ELSE 0 END - ms.qtyreserved) AS qtyavailable,
ms.qtyonhand,
ms.qtyreserved, mp.description, mw.NAME AS warehouse, mw.m_warehouse_id, mw.ad_client_id,
mw.ad_org_id, mp.documentnote, mp.m_product_id
FROM M_STORAGE ms
JOIN M_PRODUCT mp ON ms.m_product_id = mp.m_product_id
JOIN M_LOCATOR ml ON ms.m_locator_id = ml.m_locator_id
LEFT JOIN M_LOCATORTYPE lt ON ml.m_locatortype_id = lt.m_locatortype_id
JOIN M_WAREHOUSE mw ON ml.m_warehouse_id = mw.m_warehouse_id
ORDER BY mw.NAME;

View File

@ -10,7 +10,7 @@ SELECT s.ad_client_id,
s.substitute_id,
'S' AS rowtype,
mp.name,
sum(ms.qtyonhand - ms.qtyreserved) AS qtyavailable,
sum(CASE WHEN COALESCE(lt.IsAvailableForReservation,'Y')='Y' THEN ms.qtyonhand ELSE 0 END - ms.qtyreserved) AS qtyavailable,
sum(ms.qtyonhand) AS qtyonhand,
sum(ms.qtyreserved) AS qtyreserved,
currencyRound(MAX(mpr.pricestd),mpl.C_Currency_ID,'N') AS pricestd,
@ -21,6 +21,7 @@ SELECT s.ad_client_id,
JOIN m_storage ms ON ms.m_product_id = s.substitute_id
JOIN m_product mp ON ms.m_product_id = mp.m_product_id
JOIN m_locator ml ON ms.m_locator_id = ml.m_locator_id
LEFT JOIN M_LOCATORTYPE lt ON ml.m_locatortype_id = lt.m_locatortype_id
JOIN m_warehouse mw ON ml.m_warehouse_id = mw.m_warehouse_id
JOIN m_productprice mpr ON ms.m_product_id = mpr.m_product_id
JOIN m_pricelist_version mplv ON mplv.m_pricelist_version_id = mpr.m_pricelist_version_id
@ -52,7 +53,7 @@ SELECT s.ad_client_id,
r.relatedproduct_id AS substitute_id,
'R' AS rowtype,
mp.name,
sum(ms.qtyonhand - ms.qtyreserved) AS qtyavailable,
sum(CASE WHEN COALESCE(lt.IsAvailableForReservation,'Y')='Y' THEN ms.qtyonhand ELSE 0 END - ms.qtyreserved) AS qtyavailable,
sum(ms.qtyonhand) AS qtyonhand,
sum(ms.qtyreserved) AS qtyreserved,
currencyRound(MAX(mpr.pricestd),mpl.C_Currency_ID,'N') AS pricestd,
@ -63,6 +64,7 @@ SELECT s.ad_client_id,
JOIN m_storage ms ON ms.m_product_id = r.relatedproduct_id
JOIN m_product mp ON ms.m_product_id = mp.m_product_id
JOIN m_locator ml ON ms.m_locator_id = ml.m_locator_id
LEFT JOIN M_LOCATORTYPE lt ON ml.m_locatortype_id = lt.m_locatortype_id
JOIN m_warehouse mw ON ml.m_warehouse_id = mw.m_warehouse_id
JOIN m_productprice mpr ON ms.m_product_id = mpr.m_product_id
JOIN m_pricelist_version mplv ON mplv.m_pricelist_version_id = mpr.m_pricelist_version_id

View File

@ -22,7 +22,7 @@ SELECT s.ad_client_id,
l.z,
s.qtyonhand,
s.qtyreserved,
s.qtyonhand - s.qtyreserved AS qtyavailable,
CASE WHEN COALESCE(lt.IsAvailableForReservation,'Y')='Y' THEN s.qtyonhand ELSE 0 END - s.qtyreserved AS qtyavailable,
s.qtyordered,
s.datelastinventory,
s.m_attributesetinstance_id,
@ -99,6 +99,8 @@ SELECT s.ad_client_id,
FROM m_storage s
JOIN m_locator l
ON s.m_locator_id = l.m_locator_id
LEFT JOIN m_locatortype lt
ON l.m_locatortype_id = lt.m_locatortype_id
JOIN m_product p
ON s.m_product_id = p.m_product_id
LEFT JOIN m_attributesetinstance asi

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -22,12 +22,15 @@ import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException;
import org.compiere.model.MClient;
import org.compiere.model.MInOut;
import org.compiere.model.MInOutLine;
import org.compiere.model.MLocator;
import org.compiere.model.MLocatorType;
import org.compiere.model.MOrder;
import org.compiere.model.MOrderLine;
import org.compiere.model.MProduct;
@ -559,9 +562,23 @@ public class InOutGenerate extends SvrProcess
if (m_lastStorages == null)
{
m_lastStorages = MStorageOnHand.getWarehouse(getCtx(),
MStorageOnHand[] tmpStorages = MStorageOnHand.getWarehouse(getCtx(),
M_Warehouse_ID, M_Product_ID, M_AttributeSetInstance_ID,
minGuaranteeDate, FiFo,false, 0, get_TrxName());
/* IDEMPIERE-2668 - filter just locators enabled for shipping */
List<MStorageOnHand> m_storagesForShipping = new ArrayList<MStorageOnHand>();
for (MStorageOnHand soh : tmpStorages) {
MLocator loc = MLocator.get(getCtx(), soh.getM_Locator_ID());
MLocatorType lt = null;
if (loc.getM_LocatorType_ID() > 0)
lt = MLocatorType.get(getCtx(), loc.getM_LocatorType_ID());
if (lt == null || lt.isAvailableForShipping())
m_storagesForShipping.add(soh);
}
m_lastStorages = new MStorageOnHand[m_storagesForShipping.size()];
m_storagesForShipping.toArray(m_lastStorages);
m_map.put(m_lastPP, m_lastStorages);
}
return m_lastStorages;

View File

@ -28,6 +28,8 @@ import org.adempiere.base.Core;
import org.compiere.model.MBPartner;
import org.compiere.model.MClient;
import org.compiere.model.MDocType;
import org.compiere.model.MLocator;
import org.compiere.model.MLocatorType;
import org.compiere.model.MMovement;
import org.compiere.model.MMovementLine;
import org.compiere.model.MOrder;
@ -429,6 +431,9 @@ public class ReplenishReport extends SvrProcess
order.setM_Warehouse_ID(wh.getM_Warehouse_ID());
if (!order.save())
return;
addBufferLog(order.getC_Order_ID(), order.getDateOrdered(), null,
Msg.parseTranslation(getCtx(), "@C_Order_ID@ @Created@"),
MOrder.Table_ID, order.getC_Order_ID());
if (log.isLoggable(Level.FINE)) log.fine(order.toString());
noOrders++;
info.append(" - ");
@ -473,6 +478,9 @@ public class ReplenishReport extends SvrProcess
requisition.setM_Warehouse_ID(wh.getM_Warehouse_ID());
if (!requisition.save())
return;
addBufferLog(requisition.getM_Requisition_ID(), requisition.getDateDoc(), null,
Msg.parseTranslation(getCtx(), "@M_Requisition_ID@ @Created@"),
MRequisition.Table_ID, requisition.getM_Requisition_ID());
if (log.isLoggable(Level.FINE)) log.fine(requisition.toString());
noReqs++;
info.append(" - ");
@ -530,6 +538,9 @@ public class ReplenishReport extends SvrProcess
move.setAD_Org_ID(whSource.getAD_Org_ID());
if (!move.save())
return;
addBufferLog(move.getM_Movement_ID(), move.getMovementDate(), null,
Msg.parseTranslation(getCtx(), "@M_Movement_ID@ @Created@"),
MMovement.Table_ID, move.getM_Movement_ID());
if (log.isLoggable(Level.FINE)) log.fine(move.toString());
noMoves++;
info.append(" - ").append(move.getDocumentNo());
@ -549,6 +560,15 @@ public class ReplenishReport extends SvrProcess
MStorageOnHand storage = storages[j];
if (storage.getQtyOnHand().signum() <= 0)
continue;
/* IDEMPIERE-2668 - filter just locators enabled for replenishment */
MLocator loc = MLocator.get(getCtx(), storage.getM_Locator_ID());
MLocatorType lt = null;
if (loc.getM_LocatorType_ID() > 0)
lt = MLocatorType.get(getCtx(), loc.getM_LocatorType_ID());
if (lt != null && !lt.isAvailableForReplenishment())
continue;
BigDecimal moveQty = target;
if (storage.getQtyOnHand().compareTo(moveQty) < 0)
moveQty = storage.getQtyOnHand();
@ -653,6 +673,9 @@ public class ReplenishReport extends SvrProcess
if (!order.save())
return;
addBufferLog(order.getDD_Order_ID(), order.getDateOrdered(), null,
Msg.parseTranslation(getCtx(), "@DD_Order_ID@ @Created@"),
MDDOrder.Table_ID, order.getDD_Order_ID());
if (log.isLoggable(Level.FINE)) log.fine(order.toString());
noMoves++;
info.append(" - ").append(order.getDocumentNo());

View File

@ -29,6 +29,8 @@ import org.adempiere.base.Core;
import org.compiere.model.MBPartner;
import org.compiere.model.MClient;
import org.compiere.model.MDocType;
import org.compiere.model.MLocator;
import org.compiere.model.MLocatorType;
import org.compiere.model.MMovement;
import org.compiere.model.MMovementLine;
import org.compiere.model.MOrder;
@ -464,6 +466,9 @@ public class ReplenishReportProduction extends SvrProcess
order.setM_Warehouse_ID(wh.getM_Warehouse_ID());
if (!order.save())
return;
addBufferLog(order.getC_Order_ID(), order.getDateOrdered(), null,
Msg.parseTranslation(getCtx(), "@C_Order_ID@ @Created@"),
MOrder.Table_ID, order.getC_Order_ID());
if (log.isLoggable(Level.FINE)) log.fine(order.toString());
noOrders++;
info.append(" - ");
@ -508,6 +513,9 @@ public class ReplenishReportProduction extends SvrProcess
requisition.setM_Warehouse_ID(wh.getM_Warehouse_ID());
if (!requisition.save())
return;
addBufferLog(requisition.getM_Requisition_ID(), requisition.getDateDoc(), null,
Msg.parseTranslation(getCtx(), "@M_Requisition_ID@ @Created@"),
MRequisition.Table_ID, requisition.getM_Requisition_ID());
if (log.isLoggable(Level.FINE)) log.fine(requisition.toString());
noReqs++;
info.append(" - ");
@ -566,6 +574,9 @@ public class ReplenishReportProduction extends SvrProcess
move.setAD_Org_ID(whSource.getAD_Org_ID());
if (!move.save())
return;
addBufferLog(move.getM_Movement_ID(), move.getMovementDate(), null,
Msg.parseTranslation(getCtx(), "@M_Movement_ID@ @Created@"),
MMovement.Table_ID, move.getM_Movement_ID());
if (log.isLoggable(Level.FINE)) log.fine(move.toString());
noMoves++;
info.append(" - ").append(move.getDocumentNo());
@ -585,6 +596,15 @@ public class ReplenishReportProduction extends SvrProcess
MStorageOnHand storage = storages[j];
if (storage.getQtyOnHand().signum() <= 0)
continue;
/* IDEMPIERE-2668 - filter just locators enabled for replenishment */
MLocator loc = MLocator.get(getCtx(), storage.getM_Locator_ID());
MLocatorType lt = null;
if (loc.getM_LocatorType_ID() > 0)
lt = MLocatorType.get(getCtx(), loc.getM_LocatorType_ID());
if (lt != null && !lt.isAvailableForReplenishment())
continue;
BigDecimal moveQty = target;
if (storage.getQtyOnHand().compareTo(moveQty) < 0)
moveQty = storage.getQtyOnHand();
@ -689,6 +709,9 @@ public class ReplenishReportProduction extends SvrProcess
if (!order.save())
return;
addBufferLog(order.getDD_Order_ID(), order.getDateOrdered(), null,
Msg.parseTranslation(getCtx(), "@DD_Order_ID@ @Created@"),
MDDOrder.Table_ID, order.getDD_Order_ID());
if (log.isLoggable(Level.FINE)) log.fine(order.toString());
noMoves++;
info.append(" - ").append(order.getDocumentNo());
@ -819,6 +842,9 @@ public class ReplenishReportProduction extends SvrProcess
production.setIsCreated("Y");
production.saveEx(get_TrxName());
addBufferLog(production.getM_Production_ID(), production.getMovementDate(), null,
Msg.parseTranslation(getCtx(), "@M_Production_ID@ @Created@"),
MProduction.Table_ID, production.getM_Production_ID());
if (log.isLoggable(Level.FINE)) log.fine(production.toString());
noProds++;
info.append(" - ");

View File

@ -117,6 +117,17 @@ public interface I_M_Locator
*/
public int getM_Locator_ID();
/** Column name M_LocatorType_ID */
public static final String COLUMNNAME_M_LocatorType_ID = "M_LocatorType_ID";
/** Set Locator Type */
public void setM_LocatorType_ID (int M_LocatorType_ID);
/** Get Locator Type */
public int getM_LocatorType_ID();
public org.compiere.model.I_M_LocatorType getM_LocatorType() throws RuntimeException;
/** Column name M_Locator_UU */
public static final String COLUMNNAME_M_Locator_UU = "M_Locator_UU";

View File

@ -0,0 +1,193 @@
/******************************************************************************
* Product: iDempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2012 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 *
*****************************************************************************/
package org.compiere.model;
import java.math.BigDecimal;
import java.sql.Timestamp;
import org.compiere.util.KeyNamePair;
/** Generated Interface for M_LocatorType
* @author iDempiere (generated)
* @version Release 2.1
*/
public interface I_M_LocatorType
{
/** TableName=M_LocatorType */
public static final String Table_Name = "M_LocatorType";
/** AD_Table_ID=200175 */
public static final int Table_ID = 200175;
KeyNamePair Model = new KeyNamePair(Table_ID, Table_Name);
/** AccessLevel = 3 - Client - Org
*/
BigDecimal accessLevel = BigDecimal.valueOf(3);
/** Load Meta Data */
/** Column name AD_Client_ID */
public static final String COLUMNNAME_AD_Client_ID = "AD_Client_ID";
/** Get Client.
* Client/Tenant for this installation.
*/
public int getAD_Client_ID();
/** Column name AD_Org_ID */
public static final String COLUMNNAME_AD_Org_ID = "AD_Org_ID";
/** Set Organization.
* Organizational entity within client
*/
public void setAD_Org_ID (int AD_Org_ID);
/** Get Organization.
* Organizational entity within client
*/
public int getAD_Org_ID();
/** Column name Created */
public static final String COLUMNNAME_Created = "Created";
/** Get Created.
* Date this record was created
*/
public Timestamp getCreated();
/** Column name CreatedBy */
public static final String COLUMNNAME_CreatedBy = "CreatedBy";
/** Get Created By.
* User who created this records
*/
public int getCreatedBy();
/** Column name Description */
public static final String COLUMNNAME_Description = "Description";
/** Set Description.
* Optional short description of the record
*/
public void setDescription (String Description);
/** Get Description.
* Optional short description of the record
*/
public String getDescription();
/** Column name Help */
public static final String COLUMNNAME_Help = "Help";
/** Set Comment/Help.
* Comment or Hint
*/
public void setHelp (String Help);
/** Get Comment/Help.
* Comment or Hint
*/
public String getHelp();
/** Column name IsActive */
public static final String COLUMNNAME_IsActive = "IsActive";
/** Set Active.
* The record is active in the system
*/
public void setIsActive (boolean IsActive);
/** Get Active.
* The record is active in the system
*/
public boolean isActive();
/** Column name IsAvailableForReplenishment */
public static final String COLUMNNAME_IsAvailableForReplenishment = "IsAvailableForReplenishment";
/** Set Available for Replenishment */
public void setIsAvailableForReplenishment (boolean IsAvailableForReplenishment);
/** Get Available for Replenishment */
public boolean isAvailableForReplenishment();
/** Column name IsAvailableForReservation */
public static final String COLUMNNAME_IsAvailableForReservation = "IsAvailableForReservation";
/** Set Available for Reservation */
public void setIsAvailableForReservation (boolean IsAvailableForReservation);
/** Get Available for Reservation */
public boolean isAvailableForReservation();
/** Column name IsAvailableForShipping */
public static final String COLUMNNAME_IsAvailableForShipping = "IsAvailableForShipping";
/** Set Available for Shipping */
public void setIsAvailableForShipping (boolean IsAvailableForShipping);
/** Get Available for Shipping */
public boolean isAvailableForShipping();
/** Column name M_LocatorType_ID */
public static final String COLUMNNAME_M_LocatorType_ID = "M_LocatorType_ID";
/** Set Locator Type */
public void setM_LocatorType_ID (int M_LocatorType_ID);
/** Get Locator Type */
public int getM_LocatorType_ID();
/** Column name M_LocatorType_UU */
public static final String COLUMNNAME_M_LocatorType_UU = "M_LocatorType_UU";
/** Set M_LocatorType_UU */
public void setM_LocatorType_UU (String M_LocatorType_UU);
/** Get M_LocatorType_UU */
public String getM_LocatorType_UU();
/** Column name Name */
public static final String COLUMNNAME_Name = "Name";
/** Set Name.
* Alphanumeric identifier of the entity
*/
public void setName (String Name);
/** Get Name.
* Alphanumeric identifier of the entity
*/
public String getName();
/** Column name Updated */
public static final String COLUMNNAME_Updated = "Updated";
/** Get Updated.
* Date this record was updated
*/
public Timestamp getUpdated();
/** Column name UpdatedBy */
public static final String COLUMNNAME_UpdatedBy = "UpdatedBy";
/** Get Updated By.
* User who updated this records
*/
public int getUpdatedBy();
}

View File

@ -565,6 +565,18 @@ public class MInOutLine extends X_M_InOutLine
locator,
getLine());
}
// IDEMPIERE-2668
if (getParent().isSOTrx()) {
if (locator.getM_LocatorType_ID() > 0) {
MLocatorType lt = MLocatorType.get(getCtx(), locator.getM_LocatorType_ID());
if (! lt.isAvailableForShipping()) {
log.saveError("Error", Msg.translate(getCtx(), "LocatorNotAvailableForShipping"));
return false;
}
}
}
}
// if (getC_Charge_ID() == 0 && getM_Product_ID() == 0)

View File

@ -39,8 +39,7 @@ public class MLocator extends X_M_Locator
/**
*
*/
private static final long serialVersionUID = 6019655556196171287L;
private static final long serialVersionUID = 3649134803161895263L;
/**
* Get oldest Default Locator of warehouse with locator
@ -118,7 +117,12 @@ public class MLocator extends X_M_Locator
} // getDefault
/**
public static MLocator get (Properties ctx, int M_Warehouse_ID, String Value,
String X, String Y, String Z) {
return get (ctx, M_Warehouse_ID, Value, X, Y, Z, 0);
}
/**
* Get the Locator with the combination or create new one
* @param ctx Context
* @param M_Warehouse_ID warehouse
@ -129,7 +133,7 @@ public class MLocator extends X_M_Locator
* @return locator
*/
public static MLocator get (Properties ctx, int M_Warehouse_ID, String Value,
String X, String Y, String Z)
String X, String Y, String Z, int M_LocatorType_ID)
{
MLocator retValue = null;
String sql = "SELECT * FROM M_Locator WHERE IsActive = 'Y' AND M_Warehouse_ID=? AND X=? AND Y=? AND Z=?";
@ -160,6 +164,7 @@ public class MLocator extends X_M_Locator
MWarehouse wh = MWarehouse.get (ctx, M_Warehouse_ID);
retValue = new MLocator (wh, Value);
retValue.setXYZ(X, Y, Z);
retValue.setM_LocatorType_ID(M_LocatorType_ID);
retValue.saveEx();
}
return retValue;

View File

@ -0,0 +1,103 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* 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. *
* *
* Contributors: *
* - Carlos Ruiz - globalqss *
**********************************************************************/
package org.compiere.model;
import java.sql.ResultSet;
import java.util.Properties;
import org.compiere.util.CCache;
import org.compiere.util.CLogger;
/**
* Warehouse Locator Type Object
*
* @author Carlos Ruiz - Quality Systems & Solutions - globalqss
*/
public class MLocatorType extends X_M_LocatorType {
/**
*
*/
private static final long serialVersionUID = -7567584133468332781L;
/**
* Get Locator Type from Cache
* @param ctx context
* @param M_LocatorType_ID id
* @return MLocator
*/
public static MLocatorType get (Properties ctx, int M_LocatorType_ID) {
if (s_cache == null)
s_cache = new CCache<Integer,MLocatorType>(Table_Name, 20);
Integer key = new Integer (M_LocatorType_ID);
MLocatorType retValue = (MLocatorType) s_cache.get (key);
if (retValue != null)
return retValue;
retValue = new MLocatorType (ctx, M_LocatorType_ID, null);
if (retValue.get_ID () != 0)
s_cache.put (key, retValue);
return retValue;
} // get
/** Cache */
private volatile static CCache<Integer,MLocatorType> s_cache;
/** Logger */
@SuppressWarnings("unused")
private static CLogger s_log = CLogger.getCLogger (MLocatorType.class);
/**************************************************************************
* Standard Locator Constructor
* @param ctx Context
* @param M_LocatorType_ID id
* @param trxName transaction
*/
public MLocatorType (Properties ctx, int M_LocatorType_ID, String trxName) {
super (ctx, M_LocatorType_ID, trxName);
if (M_LocatorType_ID == 0) {
setIsAvailableForReplenishment (true);
setIsAvailableForReservation (true);
setIsAvailableForShipping (true);
}
} // MLocatorType
/**
* Load Constructor
* @param ctx context
* @param rs result set
* @param trxName transaction
*/
public MLocatorType (Properties ctx, ResultSet rs, String trxName) {
super(ctx, rs, trxName);
} // MLocatorType
/**
* Get String Representation
* @return Name
*/
public String toString() {
return getName();
} // toString
} // MLocatorType

View File

@ -18,15 +18,11 @@ package org.compiere.model;
import java.io.File;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Hashtable;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
import java.util.logging.Level;
import java.util.regex.Pattern;
@ -74,7 +70,7 @@ public class MOrder extends X_C_Order implements DocAction
/**
*
*/
private static final long serialVersionUID = -5424713436299981736L;
private static final long serialVersionUID = 6669447827539872218L;
/**
* Create new Order by copying
@ -2835,13 +2831,6 @@ public class MOrder extends X_C_Order implements DocAction
|| DOCSTATUS_Reversed.equals(ds);
} // isComplete
private static final String OrderLinesToAllocate = "select C_OrderLine.* from C_OrderLine " +
"JOIN C_Order ON C_OrderLine.C_Order_ID=C_Order.C_Order_ID " +
"JOIN M_Product ON C_OrderLine.M_Product_ID=M_Product.M_Product_ID " +
"where C_Order.IsSOTrx='Y' AND C_Order.DocStatus='CO' AND QtyAllocated<(QtyOrdered-QtyDelivered) " +
"AND M_Product.M_Product_ID=? " +
"order by PriorityRule, C_OrderLine.Created ";
/**
* Finds all order lines that contains not yet delivered physical items of a specific product.
*
@ -2850,7 +2839,14 @@ public class MOrder extends X_C_Order implements DocAction
* @return Order lines to allocate products to.
* @throws SQLException
*/
/* commenting out wrong unused function - column qtyallocated does not exist
public static List<MOrderLine> getOrderLinesToAllocate(Connection conn, int productId, String trxName) throws SQLException {
final String OrderLinesToAllocate = "select C_OrderLine.* from C_OrderLine " +
"JOIN C_Order ON C_OrderLine.C_Order_ID=C_Order.C_Order_ID " +
"JOIN M_Product ON C_OrderLine.M_Product_ID=M_Product.M_Product_ID " +
"where C_Order.IsSOTrx='Y' AND C_Order.DocStatus='CO' AND QtyAllocated<(QtyOrdered-QtyDelivered) " +
"AND M_Product.M_Product_ID=? " +
"order by PriorityRule, C_OrderLine.Created ";
List<MOrderLine> result = new Vector<MOrderLine>();
Properties ctx = Env.getCtx();
MOrderLine line;
@ -2872,6 +2868,7 @@ public class MOrder extends X_C_Order implements DocAction
}
return(result);
}
*/
/**
* Finds all products that can be allocated. A product can be allocated if there are more items
@ -2882,6 +2879,7 @@ public class MOrder extends X_C_Order implements DocAction
* @return
* @throws SQLException
*/
/* commenting out wrong unused function - column qtyallocated does not exist
public static List<StockInfo> getProductsToAllocate(Connection conn, int WarehouseID) throws SQLException {
List<StockInfo> result = new Vector<StockInfo>();
@ -2934,6 +2932,7 @@ public class MOrder extends X_C_Order implements DocAction
public StockInfo() {}
}
*/
/**
* Set process message

View File

@ -44,7 +44,7 @@ public class MStorageOnHand extends X_M_StorageOnHand
/**
*
*/
private static final long serialVersionUID = -4934837951332485064L;
private static final long serialVersionUID = 1137569740767949519L;
/**
*
@ -958,6 +958,39 @@ public class MStorageOnHand extends X_M_StorageOnHand
return qty;
}
/**
* Get Quantity On Hand of Warehouse Available for Reservation
* @param M_Product_ID
* @param M_Warehouse_ID
* @param M_AttributeSetInstance_ID
* @param trxName
* @return QtyOnHand
*/
public static BigDecimal getQtyOnHandForReservation(int M_Product_ID, int M_Warehouse_ID, int M_AttributeSetInstance_ID, String trxName) {
StringBuilder sql = new StringBuilder();
sql.append(" SELECT SUM(QtyOnHand) FROM M_StorageOnHand oh"
+ " JOIN M_Locator loc ON (oh.M_Locator_ID=loc.M_Locator_ID)"
+ " LEFT JOIN M_LocatorType lt ON (loc.M_LocatorType_ID=lt.M_LocatorType_ID)")
.append(" WHERE oh.M_Product_ID=?")
.append(" AND loc.M_Warehouse_ID=? AND COALESCE(lt.IsAvailableForReservation,'Y')='Y'");
ArrayList<Object> params = new ArrayList<Object>();
params.add(M_Product_ID);
params.add(M_Warehouse_ID);
// With ASI
if (M_AttributeSetInstance_ID != 0) {
sql.append(" AND oh.M_AttributeSetInstance_ID=?");
params.add(M_AttributeSetInstance_ID);
}
BigDecimal qty = DB.getSQLValueBD(trxName, sql.toString(), params);
if (qty == null)
qty = Env.ZERO;
return qty;
}
/**
* Get Quantity On Hand of Locator
* @param M_Product_ID

View File

@ -30,7 +30,7 @@ public class MStorageReservation extends X_M_StorageReservation {
/**
*
*/
private static final long serialVersionUID = -8646802850122507899L;
private static final long serialVersionUID = -2649259510341856418L;
/**
* Get Storage Info
@ -203,7 +203,7 @@ public class MStorageReservation extends X_M_StorageReservation {
public static BigDecimal getQtyAvailable (int M_Warehouse_ID,
int M_Product_ID, int M_AttributeSetInstance_ID, String trxName)
{
BigDecimal qtyOnHand = MStorageOnHand.getQtyOnHand(M_Product_ID, M_Warehouse_ID, M_AttributeSetInstance_ID, trxName);
BigDecimal qtyOnHand = MStorageOnHand.getQtyOnHandForReservation(M_Product_ID, M_Warehouse_ID, M_AttributeSetInstance_ID, trxName);
BigDecimal qtyReserved = MStorageReservation.getQty(M_Product_ID, M_Warehouse_ID, M_AttributeSetInstance_ID, true, trxName);
BigDecimal retValue = qtyOnHand.subtract(qtyReserved);
return retValue;

View File

@ -30,7 +30,7 @@ public class X_M_Locator extends PO implements I_M_Locator, I_Persistent
/**
*
*/
private static final long serialVersionUID = 20141030L;
private static final long serialVersionUID = 20150609L;
/** Standard Constructor */
public X_M_Locator (Properties ctx, int M_Locator_ID, String trxName)
@ -125,6 +125,31 @@ public class X_M_Locator extends PO implements I_M_Locator, I_Persistent
return ii.intValue();
}
public org.compiere.model.I_M_LocatorType getM_LocatorType() throws RuntimeException
{
return (org.compiere.model.I_M_LocatorType)MTable.get(getCtx(), org.compiere.model.I_M_LocatorType.Table_Name)
.getPO(getM_LocatorType_ID(), get_TrxName()); }
/** Set Locator Type.
@param M_LocatorType_ID Locator Type */
public void setM_LocatorType_ID (int M_LocatorType_ID)
{
if (M_LocatorType_ID < 1)
set_Value (COLUMNNAME_M_LocatorType_ID, null);
else
set_Value (COLUMNNAME_M_LocatorType_ID, Integer.valueOf(M_LocatorType_ID));
}
/** Get Locator Type.
@return Locator Type */
public int getM_LocatorType_ID ()
{
Integer ii = (Integer)get_Value(COLUMNNAME_M_LocatorType_ID);
if (ii == null)
return 0;
return ii.intValue();
}
/** Set M_Locator_UU.
@param M_Locator_UU M_Locator_UU */
public void setM_Locator_UU (String M_Locator_UU)

View File

@ -0,0 +1,235 @@
/******************************************************************************
* Product: iDempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2012 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 *
*****************************************************************************/
/** Generated Model - DO NOT CHANGE */
package org.compiere.model;
import java.sql.ResultSet;
import java.util.Properties;
import org.compiere.util.KeyNamePair;
/** Generated Model for M_LocatorType
* @author iDempiere (generated)
* @version Release 2.1 - $Id$ */
public class X_M_LocatorType extends PO implements I_M_LocatorType, I_Persistent
{
/**
*
*/
private static final long serialVersionUID = 20150609L;
/** Standard Constructor */
public X_M_LocatorType (Properties ctx, int M_LocatorType_ID, String trxName)
{
super (ctx, M_LocatorType_ID, trxName);
/** if (M_LocatorType_ID == 0)
{
setIsAvailableForReplenishment (true);
// Y
setIsAvailableForReservation (true);
// Y
setIsAvailableForShipping (true);
// Y
setM_LocatorType_ID (0);
setName (null);
} */
}
/** Load Constructor */
public X_M_LocatorType (Properties ctx, ResultSet rs, String trxName)
{
super (ctx, rs, trxName);
}
/** AccessLevel
* @return 3 - Client - Org
*/
protected int get_AccessLevel()
{
return accessLevel.intValue();
}
/** Load Meta Data */
protected POInfo initPO (Properties ctx)
{
POInfo poi = POInfo.getPOInfo (ctx, Table_ID, get_TrxName());
return poi;
}
public String toString()
{
StringBuffer sb = new StringBuffer ("X_M_LocatorType[")
.append(get_ID()).append("]");
return sb.toString();
}
/** Set Description.
@param Description
Optional short description of the record
*/
public void setDescription (String Description)
{
set_Value (COLUMNNAME_Description, Description);
}
/** Get Description.
@return Optional short description of the record
*/
public String getDescription ()
{
return (String)get_Value(COLUMNNAME_Description);
}
/** Set Comment/Help.
@param Help
Comment or Hint
*/
public void setHelp (String Help)
{
set_Value (COLUMNNAME_Help, Help);
}
/** Get Comment/Help.
@return Comment or Hint
*/
public String getHelp ()
{
return (String)get_Value(COLUMNNAME_Help);
}
/** Set Available for Replenishment.
@param IsAvailableForReplenishment Available for Replenishment */
public void setIsAvailableForReplenishment (boolean IsAvailableForReplenishment)
{
set_Value (COLUMNNAME_IsAvailableForReplenishment, Boolean.valueOf(IsAvailableForReplenishment));
}
/** Get Available for Replenishment.
@return Available for Replenishment */
public boolean isAvailableForReplenishment ()
{
Object oo = get_Value(COLUMNNAME_IsAvailableForReplenishment);
if (oo != null)
{
if (oo instanceof Boolean)
return ((Boolean)oo).booleanValue();
return "Y".equals(oo);
}
return false;
}
/** Set Available for Reservation.
@param IsAvailableForReservation Available for Reservation */
public void setIsAvailableForReservation (boolean IsAvailableForReservation)
{
set_Value (COLUMNNAME_IsAvailableForReservation, Boolean.valueOf(IsAvailableForReservation));
}
/** Get Available for Reservation.
@return Available for Reservation */
public boolean isAvailableForReservation ()
{
Object oo = get_Value(COLUMNNAME_IsAvailableForReservation);
if (oo != null)
{
if (oo instanceof Boolean)
return ((Boolean)oo).booleanValue();
return "Y".equals(oo);
}
return false;
}
/** Set Available for Shipping.
@param IsAvailableForShipping Available for Shipping */
public void setIsAvailableForShipping (boolean IsAvailableForShipping)
{
set_Value (COLUMNNAME_IsAvailableForShipping, Boolean.valueOf(IsAvailableForShipping));
}
/** Get Available for Shipping.
@return Available for Shipping */
public boolean isAvailableForShipping ()
{
Object oo = get_Value(COLUMNNAME_IsAvailableForShipping);
if (oo != null)
{
if (oo instanceof Boolean)
return ((Boolean)oo).booleanValue();
return "Y".equals(oo);
}
return false;
}
/** Set Locator Type.
@param M_LocatorType_ID Locator Type */
public void setM_LocatorType_ID (int M_LocatorType_ID)
{
if (M_LocatorType_ID < 1)
set_ValueNoCheck (COLUMNNAME_M_LocatorType_ID, null);
else
set_ValueNoCheck (COLUMNNAME_M_LocatorType_ID, Integer.valueOf(M_LocatorType_ID));
}
/** Get Locator Type.
@return Locator Type */
public int getM_LocatorType_ID ()
{
Integer ii = (Integer)get_Value(COLUMNNAME_M_LocatorType_ID);
if (ii == null)
return 0;
return ii.intValue();
}
/** Set M_LocatorType_UU.
@param M_LocatorType_UU M_LocatorType_UU */
public void setM_LocatorType_UU (String M_LocatorType_UU)
{
set_Value (COLUMNNAME_M_LocatorType_UU, M_LocatorType_UU);
}
/** Get M_LocatorType_UU.
@return M_LocatorType_UU */
public String getM_LocatorType_UU ()
{
return (String)get_Value(COLUMNNAME_M_LocatorType_UU);
}
/** Set Name.
@param Name
Alphanumeric identifier of the entity
*/
public void setName (String Name)
{
set_Value (COLUMNNAME_Name, Name);
}
/** Get Name.
@return Alphanumeric identifier of the entity
*/
public String getName ()
{
return (String)get_Value(COLUMNNAME_Name);
}
/** Get Record ID/ColumnName
@return ID/ColumnName pair
*/
public KeyNamePair getKeyNamePair()
{
return new KeyNamePair(get_ID(), getName());
}
}

View File

@ -666,6 +666,7 @@ public class InfoProductWindow extends InfoWindow {
sql += " w.Name, l.Value "
+ "FROM M_Storage s"
+ " INNER JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID)"
+ " LEFT JOIN M_LocatorType lt ON (l.M_LocatorType_ID=lt.M_LocatorType_ID)"
+ " INNER JOIN M_Warehouse w ON (l.M_Warehouse_ID=w.M_Warehouse_ID) "
+ "WHERE M_Product_ID=?";
if (m_M_Warehouse_ID != 0)
@ -673,6 +674,7 @@ public class InfoProductWindow extends InfoWindow {
if (m_M_AttributeSetInstance_ID > 0)
sql += " AND s.M_AttributeSetInstance_ID=?";
sql += " AND (s.QtyOnHand<>0 OR s.QtyReserved<>0 OR s.QtyOrdered<>0)";
sql += " AND COALESCE(lt.IsAvailableForReservation,'Y')='Y'";
if (!showDetail)
sql += " GROUP BY productAttribute(s.M_AttributeSetInstance_ID), w.Name, l.Value";
sql += " ORDER BY l.Value";

View File

@ -182,10 +182,11 @@ public class InvoiceHistory extends Window implements EventListener<Event>
confirmPanel.addActionListener(this);
Borderlayout borderlayout = new Borderlayout();
borderlayout.setWidth("700px");
borderlayout.setHeight("400px");
this.setWidth("700px");
this.setHeight("400px");
borderlayout.setStyle("border: none; position: relative");
this.appendChild(borderlayout);
this.setClosable(true);
North north = new North();
north.setStyle("border: none");
@ -615,6 +616,7 @@ public class InvoiceHistory extends Window implements EventListener<Event>
sql += " w.Name, l.Value "
+ "FROM M_Storage s"
+ " INNER JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID)"
+ " LEFT JOIN M_LocatorType lt ON (l.M_LocatorType_ID=lt.M_LocatorType_ID)"
+ " INNER JOIN M_Warehouse w ON (l.M_Warehouse_ID=w.M_Warehouse_ID) "
+ "WHERE M_Product_ID=?";
if (m_M_Warehouse_ID != 0)
@ -622,6 +624,7 @@ public class InvoiceHistory extends Window implements EventListener<Event>
if (m_M_AttributeSetInstance_ID > 0)
sql += " AND s.M_AttributeSetInstance_ID=?";
sql += " AND (s.QtyOnHand<>0 OR s.QtyReserved<>0 OR s.QtyOrdered<>0)";
sql += " AND COALESCE(lt.IsAvailableForReservation,'Y')='Y'";
if (!showDetailATP)
sql += " GROUP BY productAttribute(s.M_AttributeSetInstance_ID), w.Name, l.Value";
sql += " ORDER BY l.Value";

View File

@ -42,6 +42,7 @@ import org.adempiere.webui.component.Textbox;
import org.adempiere.webui.component.Window;
import org.compiere.model.MLocator;
import org.compiere.model.MLocatorLookup;
import org.compiere.model.MLocatorType;
import org.compiere.model.MRole;
import org.compiere.util.AdempiereUserError;
import org.compiere.util.CLogger;
@ -69,16 +70,18 @@ public class WLocatorDialog extends Window implements EventListener<Event>
/**
*
*/
private static final long serialVersionUID = -1013647722305985723L;
private static final long serialVersionUID = -2441739966645819543L;
private Grid mainPanel = GridFactory.newGridLayout();
private Listbox lstLocator = new Listbox();
private Listbox lstWarehouse = new Listbox();
private Listbox lstLocatorType = new Listbox();
private Checkbox chkCreateNew = new Checkbox();
private Textbox txtWarehouse = new Textbox();
private Textbox txtLocatorType = new Textbox();
private Textbox txtAisleX = new Textbox();
private Textbox txtBinY = new Textbox();
private Textbox txtLevelZ = new Textbox();
@ -87,6 +90,8 @@ public class WLocatorDialog extends Window implements EventListener<Event>
private Label lblLocator = new Label();
private Label lblWarehouse = new Label();
private Label lblWarehouse2 = new Label();
private Label lblLocatorType = new Label();
private Label lblLocatorType2 = new Label();
private Label lblAisleX = new Label();
private Label lblBinY = new Label();
private Label lblLevelZ = new Label();
@ -152,6 +157,8 @@ public class WLocatorDialog extends Window implements EventListener<Event>
lblLocator.setValue(Msg.translate(Env.getCtx(), "M_Locator_ID"));
lblWarehouse.setValue(Msg.translate(Env.getCtx(), "M_Warehouse_ID"));
lblWarehouse2.setValue(Msg.translate(Env.getCtx(), "M_Warehouse_ID"));
lblLocatorType.setValue(Msg.getElement(Env.getCtx(), "M_LocatorType_ID"));
lblLocatorType2.setValue(Msg.getElement(Env.getCtx(), "M_LocatorType_ID"));
lblAisleX.setValue(Msg.getElement(Env.getCtx(), "X"));
lblBinY.setValue(Msg.getElement(Env.getCtx(), "Y"));
lblLevelZ.setValue(Msg.getElement(Env.getCtx(), "Z"));
@ -166,7 +173,11 @@ public class WLocatorDialog extends Window implements EventListener<Event>
lstWarehouse.setMold("select");
lstWarehouse.setRows(0);
LayoutUtils.addSclass("z-label", lstWarehouse);
lstLocatorType.setMold("select");
lstLocatorType.setRows(0);
LayoutUtils.addSclass("z-label", lstLocatorType);
confirmPanel = new ConfirmPanel(true);
confirmPanel.addActionListener(this);
@ -205,7 +216,19 @@ public class WLocatorDialog extends Window implements EventListener<Event>
row.appendChild(lblWarehouse2);
row.appendChild(txtWarehouse);
txtWarehouse.setHflex("1");
row = new Row();
rows.appendChild(row);
row.appendChild(lblLocatorType);
row.appendChild(lstLocatorType);
lstLocatorType.setHflex("1");
row = new Row();
rows.appendChild(row);
row.appendChild(lblLocatorType2);
row.appendChild(txtLocatorType);
txtLocatorType.setHflex("1");
row = new Row();
rows.appendChild(row);
row.appendChild(lblAisleX);
@ -253,7 +276,7 @@ public class WLocatorDialog extends Window implements EventListener<Event>
this.setClosable(true);
this.setBorder("normal");
this.setWidth("260px");
this.setHeight("300px"); // required fixed height for ZK to auto adjust the position based on available space
this.setHeight("350px"); // required fixed height for ZK to auto adjust the position based on available space
this.setShadow(true);
this.setAttribute(Window.MODE_KEY, Window.MODE_HIGHLIGHTED);
this.setSizable(true); // Elaine 2009/02/02 - window set to resizable
@ -298,6 +321,38 @@ public class WLocatorDialog extends Window implements EventListener<Event>
if (log.isLoggable(Level.FINE)) log.fine("Warehouses=" + lstWarehouse.getItemCount());
// Load Locator Type
sql = "SELECT M_LocatorType_ID, Name FROM M_LocatorType WHERE IsActive='Y'";
SQL = MRole.getDefault().addAccessSQL(
sql, "M_LocatorType", MRole.SQL_NOTQUALIFIED, MRole.SQL_RO)
+ " ORDER BY 2";
pstmt = null;
rs = null;
KeyNamePair keyEmpty = new KeyNamePair(0, "");
lstLocatorType.appendItem(keyEmpty.getName(), keyEmpty);
try
{
pstmt = DB.prepareStatement(SQL, null);
rs = pstmt.executeQuery();
while (rs.next())
{
KeyNamePair key = new KeyNamePair(rs.getInt(1), rs.getString(2));
lstLocatorType.appendItem(key.getName(), key);
}
}
catch (SQLException e)
{
log.log(Level.SEVERE, SQL, e);
}
finally
{
DB.close(rs, pstmt);
rs = null;
pstmt = null;
}
if (log.isLoggable(Level.FINE)) log.fine("LocatorTypes=" + lstLocatorType.getItemCount());
// Load existing Locators
m_mLocator.fillComboBox(m_mandatory, true, true, false, false); // IDEMPIERE 90
@ -338,7 +393,6 @@ public class WLocatorDialog extends Window implements EventListener<Event>
enableNew();
lstWarehouse.addEventListener(Events.ON_SELECT, this);
txtAisleX.addEventListener(Events.ON_CHANGE, this);
txtBinY.addEventListener(Events.ON_CHANGE, this);
txtLevelZ.addEventListener(Events.ON_CHANGE, this);
@ -363,6 +417,14 @@ public class WLocatorDialog extends Window implements EventListener<Event>
m_M_Locator_ID = l.getM_Locator_ID();
txtWarehouse.setText(l.getWarehouseName());
if (l.getM_LocatorType_ID() > 0) {
MLocatorType lt = MLocatorType.get(Env.getCtx(), l.getM_LocatorType_ID());
txtLocatorType.setText(lt.getName());
} else {
txtLocatorType.setText("");
}
txtAisleX.setText(l.getX());
txtBinY.setText(l.getY());
txtLevelZ.setText(l.getZ());
@ -385,6 +447,19 @@ public class WLocatorDialog extends Window implements EventListener<Event>
continue;
}
}
// Set Locator Type
size = lstLocatorType.getItemCount();
for (int i = 0; i < size; i++)
{
ListItem listItem = lstLocatorType.getItemAtIndex(i);
KeyNamePair pp = (KeyNamePair)listItem.getValue();
if (pp.getKey() == l.getM_LocatorType_ID())
{
lstLocatorType.setSelectedIndex(i);
continue;
}
}
} // displayLocator
/**
@ -400,8 +475,14 @@ public class WLocatorDialog extends Window implements EventListener<Event>
//lWarehouseInfo.setVisible(!sel);
txtWarehouse.setVisible(!sel);
txtWarehouse.getParent().setVisible(!sel);
txtWarehouse.setReadonly(true);
lstLocatorType.setVisible(sel);
lstLocatorType.getParent().setVisible(sel);
txtLocatorType.setVisible(!sel);
txtLocatorType.getParent().setVisible(!sel);
txtLocatorType.setReadonly(true);
txtAisleX.setReadonly(!sel);
txtBinY.setReadonly(!sel);
txtLevelZ.setReadonly(!sel);
@ -525,8 +606,14 @@ public class WLocatorDialog extends Window implements EventListener<Event>
return;
}
listitem = lstLocatorType.getSelectedItem();
pp = (KeyNamePair)listitem.getValue();
int lt = 0;
if (pp != null)
lt = pp.getKey();
MLocator loc = MLocator.get(Env.getCtx(), m_M_Warehouse_ID, txtKey.getText(),
txtAisleX.getText(), txtBinY.getText(), txtLevelZ.getText());
txtAisleX.getText(), txtBinY.getText(), txtLevelZ.getText(), lt);
m_M_Locator_ID = loc.getM_Locator_ID();
@ -596,7 +683,8 @@ public class WLocatorDialog extends Window implements EventListener<Event>
else if (event.getTarget() == chkCreateNew)
enableNew();
// Entered/Changed data for Value
else if (chkCreateNew.isChecked() && event.getTarget() == lstWarehouse)
else if (chkCreateNew.isChecked()
&& (event.getTarget() == lstWarehouse || event.getTarget() == txtAisleX || event.getTarget() == txtBinY || event.getTarget() == txtLevelZ))
createValue();
}
}