use of org.compiere.model.MStorage in project adempiere by adempiere.
the class MovementGenerate method generate.
/**
* Generate Shipments
* @param distributionOrders Orders
* @return info
*/
private String generate(List<MDDOrder> distributionOrders) {
distributionOrders.stream().filter(order -> order != null).forEach(order -> {
getCurrentMovement().filter(movement -> movement != null || !isConsolidatetooneDocument()).filter(movement -> movement.getC_BPartner_Location_ID() != order.getC_BPartner_Location_ID() || movement.getM_Shipper_ID() != order.getM_Shipper_ID()).ifPresent(movement -> completeMovement());
log.fine("check: " + order + " - DeliveryRule=" + order.getDeliveryRule());
Timestamp minGuaranteeDate = getMovementDate();
StringBuilder where = new StringBuilder(" 1=1 ");
if (getWarehouseId() > 0)
where.append(" AND ").append(getWarehouseId()).append(" IN (SELECT l.M_Warehouse_ID FROM M_Locator l WHERE l.M_Locator_ID=M_Locator_ID) ");
if (getDatePromised() != null)
where.append(" AND (TRUNC(DatePromised)<=").append(DB.TO_DATE(getDatePromised(), true)).append(" OR DatePromised IS NULL)");
if (!MDDOrder.DELIVERYRULE_Force.equals(order.getDeliveryRule()))
where.append(" AND (DD_OrderLine.M_Product_ID IS NULL").append(" OR EXISTS (SELECT * FROM M_Product p ").append("WHERE DD_OrderLine.M_Product_ID=p.M_Product_ID").append(" AND IsExcludeAutoDelivery='N'))");
if (!isOrderswithunconfirmedShipments())
where.append(" AND NOT EXISTS (SELECT * FROM M_MovementLine iol").append(" INNER JOIN M_Movement io ON (iol.M_Movement_ID=io.M_Movement_ID) ").append("WHERE iol.DD_OrderLine_ID=DD_OrderLine.DD_OrderLine_ID AND io.DocStatus IN ('IP','WC'))");
List<MDDOrderLine> orderLines = order.getLines(where.toString(), "M_Product_ID");
orderLines.stream().filter(orderLine -> orderLine.getM_Product_ID() > 0 || orderLine.getC_Charge_ID() > 0).filter(orderLine -> orderLine.getConfirmedQty().signum() != 0).forEach(orderLine -> {
MLocator locator = new MLocator(getCtx(), orderLine.getM_Locator_ID(), get_TrxName());
if (getWarehouseId() > 0 && locator.getM_Warehouse_ID() != getWarehouseId())
return;
log.fine("check: " + orderLine);
BigDecimal onHand = Env.ZERO;
BigDecimal toDeliver = orderLine.getConfirmedQty();
MProduct product = orderLine.getProduct();
BigDecimal unconfirmedShippedQty = Env.ZERO;
if (isOrderswithunconfirmedShipments() && product != null && toDeliver.signum() != 0) {
String whereLine = "EXISTS (SELECT * FROM M_Movement io WHERE io.M_Movement_ID=M_MovementLine.M_Movement_ID AND io.DocStatus IN ('IP','WC'))";
MMovementLine[] movementLines = MMovementLine.getOfOrderLine(getCtx(), orderLine.getDD_OrderLine_ID(), whereLine, null);
unconfirmedShippedQty = Arrays.asList(movementLines).stream().map(MMovementLine::getMovementQty).reduce(BigDecimal.ZERO, BigDecimal::add);
String logInfo = "Unconfirmed Qty=" + unconfirmedShippedQty + " - ToDeliver=" + orderLine.getConfirmedQty() + "->";
toDeliver = orderLine.getConfirmedQty().subtract(unconfirmedShippedQty);
logInfo += toDeliver;
if (toDeliver.signum() < 0) {
toDeliver = Env.ZERO;
logInfo += " (set to 0)";
}
onHand = onHand.subtract(unconfirmedShippedQty);
log.fine(logInfo);
}
if ((product == null || !product.isStocked()) && (orderLine.getQtyOrdered().signum() == 0 || toDeliver.signum() != 0)) {
if (!MDDOrder.DELIVERYRULE_CompleteOrder.equals(order.getDeliveryRule()))
createLine(order, orderLine, toDeliver, null, false);
return;
}
String policyMaterialIssue = getPolicyIssue(product);
MStorage[] storages = getStorages(locator.getM_Warehouse_ID(), orderLine.getM_Product_ID(), orderLine.getM_AttributeSetInstance_ID(), product.getM_AttributeSet_ID(), orderLine.getM_AttributeSetInstance_ID() == 0, minGuaranteeDate, MClient.MMPOLICY_FiFo.equals(policyMaterialIssue));
onHand = Arrays.asList(storages).stream().map(MStorage::getQtyOnHand).reduce(BigDecimal.ZERO, BigDecimal::add);
boolean fullLine = onHand.compareTo(toDeliver) >= 0 || toDeliver.signum() < 0;
boolean completeOrder = MDDOrder.DELIVERYRULE_CompleteOrder.equals(order.getDeliveryRule());
if (completeOrder && !fullLine) {
log.fine("Failed CompleteOrder - OnHand=" + onHand + " (Unconfirmed=" + unconfirmedShippedQty + "), ToDeliver=" + toDeliver + " - " + orderLine);
return;
} else if (fullLine && MDDOrder.DELIVERYRULE_CompleteLine.equals(order.getDeliveryRule())) {
log.fine("CompleteLine - OnHand=" + onHand + " (Unconfirmed=" + unconfirmedShippedQty + ", ToDeliver=" + toDeliver + " - " + orderLine);
createLine(order, orderLine, toDeliver, storages, false);
} else if (MDDOrder.DELIVERYRULE_Availability.equals(order.getDeliveryRule()) && (onHand.signum() > 0 || orderLine.getConfirmedQty().signum() < 0)) {
BigDecimal deliver = orderLine.getConfirmedQty();
log.fine("Available - OnHand=" + onHand + " (Unconfirmed=" + unconfirmedShippedQty + "), ToDeliver=" + toDeliver + ", Delivering=" + deliver + " - " + orderLine);
if (deliver.compareTo(onHand) > 0)
deliver = onHand;
createLine(order, orderLine, deliver, storages, false);
} else if (MDDOrder.DELIVERYRULE_Force.equals(order.getDeliveryRule())) {
BigDecimal deliver = toDeliver;
log.fine("Force - OnHand=" + onHand + " (Unconfirmed=" + unconfirmedShippedQty + "), ToDeliver=" + toDeliver + ", Delivering=" + deliver + " - " + orderLine);
createLine(order, orderLine, deliver, storages, true);
} else if (MDDOrder.DELIVERYRULE_Manual.equals(order.getDeliveryRule()))
log.fine("Manual - OnHand=" + onHand + " (Unconfirmed=" + unconfirmedShippedQty + ") - " + orderLine);
else
log.fine("Failed: " + order.getDeliveryRule() + " - OnHand=" + onHand + " (Unconfirmed=" + unconfirmedShippedQty + "), ToDeliver=" + toDeliver + " - " + orderLine);
});
boolean completeOrder = MDDOrder.DELIVERYRULE_CompleteOrder.equals(order.getDeliveryRule());
if (completeOrder && MDDOrder.DELIVERYRULE_CompleteOrder.equals(order.getDeliveryRule())) {
for (MDDOrderLine orderLine : orderLines) {
MLocator l = new MLocator(getCtx(), orderLine.getM_Locator_ID(), get_TrxName());
if (getWarehouseId() > 0 && l.getM_Warehouse_ID() != getWarehouseId())
continue;
MProduct product = orderLine.getProduct();
BigDecimal toDeliver = orderLine.getQtyOrdered().subtract(orderLine.getQtyDelivered());
MStorage[] storages = null;
if (product != null && product.isStocked()) {
MProductCategory pc = MProductCategory.get(order.getCtx(), product.getM_Product_Category_ID());
String MMPolicy = pc.getMMPolicy();
if (MMPolicy == null || MMPolicy.length() == 0)
MMPolicy = getClient().getMMPolicy();
storages = getStorages(l.getM_Warehouse_ID(), orderLine.getM_Product_ID(), orderLine.getM_AttributeSetInstance_ID(), product.getM_AttributeSet_ID(), orderLine.getM_AttributeSetInstance_ID() == 0, minGuaranteeDate, MClient.MMPOLICY_FiFo.equals(MMPolicy));
}
createLine(order, orderLine, toDeliver, storages, false);
}
}
lineNo += 1000;
completeMovement();
});
return "@Created@ = " + createdCount;
}
use of org.compiere.model.MStorage in project adempiere by adempiere.
the class StorageReasoner method getAvailableQtyLocator.
public MStorage getAvailableQtyLocator(MProduct p, MAttributeSetInstance asi, BigDecimal qtyRequired) {
int[] ids = getPOIDs(MLocator.Table_Name, null, null);
MStorage storage = null;
BigDecimal qtyAvailable = BigDecimal.ZERO;
BigDecimal qtyOnHand = BigDecimal.ZERO;
BigDecimal qtyReserved = BigDecimal.ZERO;
for (int i = 0; i < ids.length; i++) {
storage = MStorage.get(Env.getCtx(), ids[i], p.get_ID(), asi.get_ID(), null);
if (storage != null) {
qtyOnHand = (storage.getQtyOnHand() == null) ? BigDecimal.ZERO : storage.getQtyOnHand();
qtyReserved = (storage.getQtyReserved() == null) ? BigDecimal.ZERO : storage.getQtyReserved();
qtyAvailable = qtyOnHand.subtract(qtyReserved);
if (qtyRequired.compareTo(qtyAvailable) <= 0 && qtyOnHand.compareTo(BigDecimal.ZERO) > 0) {
break;
} else {
storage = null;
}
}
}
return storage;
}
use of org.compiere.model.MStorage in project adempiere by adempiere.
the class StorageReasoner method isQtyAvailable.
public boolean isQtyAvailable(MProduct p, MAttributeSetInstance asi) {
int[] ids = getPOIDs(MLocator.Table_Name, null, null);
MStorage storage = null;
BigDecimal sumQtyOnHand = BigDecimal.ZERO;
BigDecimal sumQtyReserved = BigDecimal.ZERO;
int count = 0;
for (int i = 0; i < ids.length; i++) {
storage = MStorage.get(Env.getCtx(), ids[i], p.get_ID(), asi.get_ID(), null);
if (storage == null) {
continue;
}
count++;
sumQtyOnHand = sumQtyOnHand.add(storage.getQtyOnHand());
sumQtyReserved = sumQtyReserved.add(storage.getQtyReserved());
}
double available = sumQtyOnHand.subtract(sumQtyReserved).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
if (count == 0 || (available <= 0.00d)) {
return false;
}
return true;
}
use of org.compiere.model.MStorage in project adempiere by adempiere.
the class MDDOrderLine method beforeSave.
// setQtyOrdered
/**************************************************************************
* Before Save
* @param newRecord
* @return true if it can be sabed
*/
protected boolean beforeSave(boolean newRecord) {
if (newRecord && getParent().isComplete()) {
log.saveError("ParentComplete", Msg.translate(getCtx(), "DD_OrderLine"));
return false;
}
/*if (getC_BPartner_ID() == 0 || getC_BPartner_Location_ID() == 0
|| getM_Warehouse_ID() == 0)
setOrder (getParent());*/
if (m_M_PriceList_ID == 0)
setHeaderInfo(getParent());
// R/O Check - Product/Warehouse Change
if (!newRecord && (is_ValueChanged("M_Product_ID") || is_ValueChanged("M_Locator_ID") || is_ValueChanged("M_LocatorTo_ID"))) {
if (!canChangeWarehouse())
return false;
}
// Charge
if (getC_Charge_ID() != 0 && getM_Product_ID() != 0)
setM_Product_ID(0);
// No Product
if (getM_Product_ID() == 0)
setM_AttributeSetInstance_ID(0);
// UOM
if (getC_UOM_ID() == 0 && (getM_Product_ID() != 0 || getC_Charge_ID() != 0)) {
int C_UOM_ID = MUOM.getDefault_UOM_ID(getCtx());
if (C_UOM_ID > 0)
setC_UOM_ID(C_UOM_ID);
}
// Qty Precision
if (newRecord || is_ValueChanged("QtyEntered"))
setQtyEntered(getQtyEntered());
if (newRecord || is_ValueChanged("QtyOrdered"))
setQtyOrdered(getQtyOrdered());
// Qty on instance ASI for SO
if (m_IsSOTrx && getM_AttributeSetInstance_ID() != 0 && (newRecord || is_ValueChanged("M_Product_ID") || is_ValueChanged("M_AttributeSetInstance_ID") || is_ValueChanged("M_Warehouse_ID"))) {
MProduct product = getProduct();
if (product.isStocked()) {
int M_AttributeSet_ID = product.getM_AttributeSet_ID();
boolean isInstance = M_AttributeSet_ID != 0;
if (isInstance) {
MAttributeSet mas = MAttributeSet.get(getCtx(), M_AttributeSet_ID);
isInstance = mas.isInstanceAttribute();
}
// Max
if (isInstance) {
MLocator locator_from = MLocator.get(getCtx(), getM_Locator_ID());
MStorage[] storages = MStorage.getWarehouse(getCtx(), locator_from.getM_Warehouse_ID(), getM_Product_ID(), getM_AttributeSetInstance_ID(), M_AttributeSet_ID, false, null, true, get_TrxName());
BigDecimal qty = Env.ZERO;
for (int i = 0; i < storages.length; i++) {
if (storages[i].getM_AttributeSetInstance_ID() == getM_AttributeSetInstance_ID())
qty = qty.add(storages[i].getQtyOnHand());
}
if (getQtyOrdered().compareTo(qty) > 0) {
log.warning("Qty - Stock=" + qty + ", Ordered=" + getQtyOrdered());
log.saveError("QtyInsufficient", "=" + qty);
return false;
}
}
}
// stocked
}
// FreightAmt Not used
if (Env.ZERO.compareTo(getFreightAmt()) != 0)
setFreightAmt(Env.ZERO);
// Get Line No
if (getLine() == 0) {
String sql = "SELECT COALESCE(MAX(Line),0)+10 FROM DD_OrderLine WHERE DD_Order_ID=?";
int ii = DB.getSQLValue(get_TrxName(), sql, getDD_Order_ID());
setLine(ii);
}
return true;
}
use of org.compiere.model.MStorage in project adempiere by adempiere.
the class MPPOrder method createIssue.
/**
* Create Issue
* @param orderBOMLine
* @param movementdate
* @param qtyToDeliver
* @param qtyScrapComponent
* @param qtyReject
* @param shortages
* @param forceIssue
*/
public static List<MPPCostCollector> createIssue(MPPOrder order, MPPOrderBOMLine orderBOMLine, Timestamp movementdate, BigDecimal qtyToDeliver, BigDecimal qtyScrapComponent, BigDecimal qtyReject, MStorage[] shortages, boolean forceIssue) {
List<MPPCostCollector> collectors = new ArrayList<MPPCostCollector>();
if (qtyToDeliver.signum() == 0)
return null;
BigDecimal toIssue = qtyToDeliver.add(qtyScrapComponent);
for (MStorage storage : shortages) {
if (storage.getQtyOnHand().signum() == 0)
continue;
BigDecimal qtyIssue = toIssue.min(storage.getQtyOnHand());
//create record for negative and positive transaction
if (qtyIssue.signum() != 0 || qtyScrapComponent.signum() != 0 || qtyReject.signum() != 0) {
String CostCollectorType = MPPCostCollector.COSTCOLLECTORTYPE_ComponentIssue;
if (orderBOMLine.isComponentType(MPPOrderBOMLine.COMPONENTTYPE_Co_Product))
CostCollectorType = MPPCostCollector.COSTCOLLECTORTYPE_MixVariance;
collectors.add(MPPCostCollector.createCollector(//MPPOrder
order, //M_Product_ID
orderBOMLine.getM_Product_ID(), //M_Locator_ID
storage.getM_Locator_ID(), //M_AttributeSetInstance_ID
storage.getM_AttributeSetInstance_ID(), //S_Resource_ID
order.getS_Resource_ID(), //PP_Order_BOMLine_ID
orderBOMLine.getPP_Order_BOMLine_ID(), //PP_Order_Node_ID
0, //C_DocType_ID,
MDocType.getDocType(MDocType.DOCBASETYPE_ManufacturingCostCollector), //Production "-"
CostCollectorType, //MovementDate
movementdate, //qty,scrap,reject
qtyIssue, //qty,scrap,reject
qtyScrapComponent, //qty,scrap,reject
qtyReject, //durationSetup,duration
Env.ZERO, //durationSetup,duration
Env.ZERO));
orderBOMLine.load(order.get_TrxName());
// Method Variance
if (orderBOMLine.getQtyBatch().signum() == 0 && orderBOMLine.getQtyBOM().signum() == 0)
order.createMethodChangeVariance(orderBOMLine);
}
toIssue = toIssue.subtract(qtyIssue);
if (toIssue.signum() == 0)
break;
}
if (forceIssue && toIssue.signum() != 0) {
collectors.add(MPPCostCollector.createCollector(//MPPOrder
order, //M_Product_ID
orderBOMLine.getM_Product_ID(), //M_Locator_ID
orderBOMLine.getM_Locator_ID(), //M_AttributeSetInstance_ID
orderBOMLine.getM_AttributeSetInstance_ID(), //S_Resource_ID
order.getS_Resource_ID(), //PP_Order_BOMLine_ID
orderBOMLine.getPP_Order_BOMLine_ID(), //PP_Order_Node_ID
0, //C_DocType_ID,
MDocType.getDocType(MDocType.DOCBASETYPE_ManufacturingCostCollector), //Production "-"
MPPCostCollector.COSTCOLLECTORTYPE_ComponentIssue, //MovementDate
movementdate, //qty,scrap,reject
toIssue, //qty,scrap,reject
Env.ZERO, //qty,scrap,reject
Env.ZERO, //durationSetup,duration
Env.ZERO, //durationSetup,duration
Env.ZERO));
return collectors;
}
//remove logic to allow qty return component
if (toIssue.signum() != 0) {
// should not happen because we validate Qty On Hand on start of this process
throw new AdempiereException("Should not happen toIssue=" + toIssue);
}
return collectors;
}
Aggregations