feat: Enhance inventory and invoice processing
- Added functionality to handle M_Movement_ID in MID_MInventory, allowing for the creation of inventory lines based on movement lines. - Implemented a method to sum movement lines in MID_MInventory. - Improved MID_MInventoryLineMA to ensure proper handling of movement quantities and attribute set instances. - Introduced createLineFrom method in MID_MInvoice to facilitate line creation from various sources (order, shipment, RMA). - Updated MID_MPayment to set prepayment status based on order presence. - Enhanced MID_Production with methods for reversing production documents and validating production lines. - Created MID_ProductionPlan class to manage production plans and their associated lines. - Developed MID_InvoiceCreateLineFrom process to automate invoice line creation from selections.
This commit is contained in:
parent
e47a1fd6f1
commit
2292c43d50
|
|
@ -43,6 +43,15 @@ public class MID_CalloutOrder extends CalloutEngine implements IColumnCallout {
|
|||
if(!isSOTrx) {
|
||||
log.info("Setting PaymentRule to OnCredit for non-SOTrx");
|
||||
mTab.setValue("PaymentRule", X_C_Order.PAYMENTRULE_OnCredit);
|
||||
}else {
|
||||
int org = (int) mTab.getValue(MOrder.COLUMNNAME_AD_Org_ID);
|
||||
if (org == 1000002) { // Balinusa
|
||||
log.info("Setting PaymentRule to Cash for SOTrx in Balinusa");
|
||||
mTab.setValue("PaymentRule", X_C_Order.PAYMENTRULE_Cash);
|
||||
} else { // MidSuit
|
||||
log.info("Setting PaymentRule to OnCredit for SOTrx in MidSuit");
|
||||
mTab.setValue("PaymentRule", X_C_Order.PAYMENTRULE_OnCredit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -96,7 +105,15 @@ public class MID_CalloutOrder extends CalloutEngine implements IColumnCallout {
|
|||
.setParameters(new Object[] { org, isSOTrx })
|
||||
.setOnlyActiveRecords(true)
|
||||
.firstId();
|
||||
|
||||
if(isSOTrx) {
|
||||
if (org == 1000002) { // Balinusa
|
||||
log.info("Setting PaymentRule to Cash for SOTrx in Balinusa");
|
||||
mTab.setValue("PaymentRule", X_C_Order.PAYMENTRULE_Cash);
|
||||
} else { // MidSuit
|
||||
log.info("Setting PaymentRule to OnCredit for SOTrx in MidSuit");
|
||||
mTab.setValue("PaymentRule", X_C_Order.PAYMENTRULE_OnCredit);
|
||||
}
|
||||
}
|
||||
if(priceList>0)
|
||||
mTab.setValue(MOrder.COLUMNNAME_M_PriceList_ID, priceList);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,14 +19,18 @@ public class MID_CalloutPPProductBOMLine extends CalloutEngine implements IColum
|
|||
// TODO Auto-generated method stub
|
||||
if(mField.getColumnName().equals("PriceEntered") || mField.getColumnName().equals("QtyBOM")) {
|
||||
// set linenetamt = QtyUsed * PriceEntered
|
||||
BigDecimal C_Charge_ID = BigDecimal.valueOf((int) mTab.getValue("C_Charge_ID"));
|
||||
if (C_Charge_ID != null && C_Charge_ID.intValue() <= 0) {
|
||||
mTab.setValue("LineNetAmt", null);
|
||||
return null; // do not calculate LineNetAmt if C_Charge_ID is set
|
||||
BigDecimal C_Charge_ID = null;
|
||||
Object chargeValue = mTab.getValue("C_Charge_ID");
|
||||
if (chargeValue != null) {
|
||||
C_Charge_ID = BigDecimal.valueOf((int) chargeValue);
|
||||
}
|
||||
if (C_Charge_ID == null || C_Charge_ID.intValue() <= 0) {
|
||||
mTab.setValue("LineNetAmt", null);
|
||||
return null; // do not calculate LineNetAmt if C_Charge_ID is not set
|
||||
}
|
||||
// if product is null
|
||||
int M_Product_ID = (int) mTab.getValue("M_Product_ID");
|
||||
if (M_Product_ID <= 0) {
|
||||
BigDecimal M_Product_ID = (BigDecimal) mTab.getValue("M_Product_ID");
|
||||
if (M_Product_ID == null || M_Product_ID.intValue() <= 0) {
|
||||
mTab.setValue("LineNetAmt", null);
|
||||
return null; // do not calculate LineNetAmt if M_Product_ID is not set
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,11 +135,11 @@ public class MID_DocProduction extends Doc
|
|||
sqlPL = "SELECT * FROM M_ProductionLine pro_line "
|
||||
+ "INNER JOIN M_ProductionPlan plan ON pro_line.M_ProductionPlan_id = plan.M_ProductionPlan_id "
|
||||
+ "INNER JOIN M_Production pro ON pro.M_Production_id = plan.M_Production_id "
|
||||
+ "WHERE pro.M_Production_ID=? "
|
||||
+ "WHERE (pro_line.m_product_id is not null or pro_line.c_charge_id is not null ) and pro.M_Production_ID=? "
|
||||
+ "ORDER BY plan.M_ProductionPlan_id, pro_line.Line";
|
||||
} else {
|
||||
sqlPL = "SELECT * FROM M_ProductionLine pl "
|
||||
+ "WHERE pl.M_Production_ID=? "
|
||||
+ "WHERE (pl.m_product_id is not null or pl.c_charge_id is not null ) and pl.M_Production_ID=? "
|
||||
+ "ORDER BY pl.Line";
|
||||
}
|
||||
|
||||
|
|
@ -207,6 +207,16 @@ public class MID_DocProduction extends Doc
|
|||
BigDecimal retValue = Env.ZERO;
|
||||
return retValue;
|
||||
} // getBalance
|
||||
|
||||
public boolean isEndProductWithAnyLinesChargeAndNoMaterial(X_M_Production prod) {
|
||||
String sql = "SELECT COUNT(*) FROM M_ProductionLine WHERE M_Production_ID=? AND C_Charge_ID IS NOT NULL AND M_Product_ID IS NULL";
|
||||
int count = DB.getSQLValue(getTrxName(), sql, prod.getM_Production_ID());
|
||||
String sql2 = "SELECT COUNT(*) FROM M_ProductionLine WHERE M_Production_ID=? AND C_Charge_ID IS NULL AND M_Product_ID IS NOT NULL AND IsEndProduct='N'";
|
||||
int count2 = DB.getSQLValue(getTrxName(), sql2, prod.getM_Production_ID());
|
||||
if (count > 0 && count2 == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Facts (the accounting logic) for
|
||||
|
|
@ -230,6 +240,7 @@ public class MID_DocProduction extends Doc
|
|||
X_M_Production prod = (X_M_Production)getPO();
|
||||
HashMap<String, BigDecimal> costMap = new HashMap<String, BigDecimal>();
|
||||
BigDecimal totalNetAmt = BigDecimal.ZERO;
|
||||
boolean isEndProductWithAnyLinesChargeAndNoMaterial = isEndProductWithAnyLinesChargeAndNoMaterial(prod);
|
||||
for (int i = 0; i < p_lines.length; i++)
|
||||
{
|
||||
DocLine line = p_lines[i];
|
||||
|
|
@ -240,7 +251,7 @@ public class MID_DocProduction extends Doc
|
|||
|
||||
if (!line.isItem()) {
|
||||
// Handle CHARGE (tanpa product)
|
||||
log.info("Handling Charge for ProductionLine: " + prodline.getLine() + " - " + prodline.getDescription());
|
||||
log.info("[1] Handling Charge for ProductionLine: " + prodline.getLine() + " - " + prodline.getDescription());
|
||||
|
||||
int C_Charge_ID = prodline.get_ValueAsInt("C_Charge_ID");
|
||||
BigDecimal LineNetAmt = (BigDecimal) prodline.get_Value("LineNetAmt");
|
||||
|
|
@ -276,11 +287,11 @@ public class MID_DocProduction extends Doc
|
|||
|
||||
MProductionLineMA mas[] = MProductionLineMA.get(getCtx(), prodline.get_ID(), getTrxName());
|
||||
MProduct product = (MProduct) prodline.getM_Product();
|
||||
log.info("Processing ProductionLine: " + prodline.getLine() + " - " + prodline.getDescription()
|
||||
log.info("[2] Processing ProductionLine: " + prodline.getLine() + " - " + prodline.getDescription()
|
||||
+ ", Product=" + product.getName() + " - " + product.getValue());
|
||||
String CostingLevel = product.getCostingLevel(as);
|
||||
String costingMethod = product.getCostingMethod(as);
|
||||
log.info("CostingLevel=" + CostingLevel + ", CostingMethod=" + costingMethod
|
||||
log.info("[3] CostingLevel=" + CostingLevel + ", CostingMethod=" + costingMethod
|
||||
+ ", Product=" + product.getName() + " - " + product.getValue());
|
||||
|
||||
if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(CostingLevel)) {
|
||||
|
|
@ -325,10 +336,10 @@ public class MID_DocProduction extends Doc
|
|||
int stdPrecision = as.getStdPrecision();
|
||||
BigDecimal bomCost = Env.ZERO;
|
||||
BigDecimal qtyProduced = null;
|
||||
log.info("Costs: " + costs + ", Is BOM:" + line.isProductionBOM() +", CostingLevel=" + CostingLevel
|
||||
log.info("[4] Costs: " + costs + ", Is BOM:" + line.isProductionBOM() +", CostingLevel=" + CostingLevel
|
||||
+ ", CostingMethod=" + costingMethod + ", Product=" + product.getName() + " - " + product.getValue());
|
||||
if (line.isProductionBOM()) {
|
||||
log.info("Processing Production BOM Line: " + line.getLine() + " - " + line.getDescription()
|
||||
log.info("[5] Processing Production BOM Line: " + line.getLine() + " - " + line.getDescription()
|
||||
+ ", Product=" + product.getName() + " - " + product.getValue());
|
||||
X_M_ProductionLine endProLine = (X_M_ProductionLine) line.getPO();
|
||||
int parentEndPro = prod.isUseProductionPlan() ? endProLine.getM_ProductionPlan_ID() : endProLine.getM_Production_ID();
|
||||
|
|
@ -341,8 +352,11 @@ public class MID_DocProduction extends Doc
|
|||
if (bomProLine.getM_Product_ID() == 0) {
|
||||
// add bomCost
|
||||
BigDecimal LineNetAmt = (BigDecimal) bomProLine.get_Value("LineNetAmt");
|
||||
if (LineNetAmt == null) {
|
||||
LineNetAmt = Env.ZERO;
|
||||
}
|
||||
totalChargeAmt = totalChargeAmt.add(LineNetAmt);
|
||||
log.info("Charge LineNetAmt: " + LineNetAmt + ", Total Charge Amount: " + totalChargeAmt);
|
||||
log.info("[6] Charge LineNetAmt: " + LineNetAmt + ", Total Charge Amount: " + totalChargeAmt);
|
||||
continue; // skip product logic for charge
|
||||
}
|
||||
int parentBomPro = prod.isUseProductionPlan() ? bomProLine.getM_ProductionPlan_ID() : bomProLine.getM_Production_ID();
|
||||
|
|
@ -350,9 +364,9 @@ public class MID_DocProduction extends Doc
|
|||
if (parentBomPro != parentEndPro)
|
||||
continue;
|
||||
if (!line0.isProductionBOM()) {
|
||||
log.info("bomProLine ID: " + bomProLine.get_ID() + "");
|
||||
log.info("[7] bomProLine ID: " + bomProLine.get_ID() + "");
|
||||
MProduct product0 = (MProduct) bomProLine.getM_Product();
|
||||
log.info("Processing BOM Line: " + bomProLine.getLine() + " - " + bomProLine.getDescription()
|
||||
log.info("[8] Processing BOM Line: " + bomProLine.getLine() + " - " + bomProLine.getDescription()
|
||||
+ ", Product=" + product0.getName() + " - " + product0.getValue());
|
||||
String CostingLevel0 = product0.getCostingLevel(as);
|
||||
if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(CostingLevel0)) {
|
||||
|
|
@ -367,13 +381,15 @@ public class MID_DocProduction extends Doc
|
|||
// get cost of children
|
||||
MCostDetail cd0 = MCostDetail.get(as.getCtx(), "M_ProductionLine_ID=?",
|
||||
line0.get_ID(), ma.getM_AttributeSetInstance_ID(), as.getC_AcctSchema_ID(), getTrxName());
|
||||
if (cd0 != null)
|
||||
if (cd0 != null) {
|
||||
maCost = cd0.getAmt();
|
||||
else {
|
||||
log.info("[8.1] CostDetail: " + cd0.get_ID() + " - " + maCost);
|
||||
} else {
|
||||
ProductCost pc = line0.getProductCost();
|
||||
pc.setQty(ma.getMovementQty());
|
||||
pc.setM_M_AttributeSetInstance_ID(ma.getM_AttributeSetInstance_ID());
|
||||
maCost = line0.getProductCosts(as, line0.getAD_Org_ID(), false);
|
||||
log.info("[8.2] ProductCost: " + line0.get_ID() + " - " + maCost);
|
||||
}
|
||||
costMap.put(line0.get_ID() + "_" + ma.getM_AttributeSetInstance_ID(), maCost);
|
||||
costs0 = costs0.add(maCost);
|
||||
|
|
@ -389,8 +405,10 @@ public class MID_DocProduction extends Doc
|
|||
BigDecimal costs0;
|
||||
if (cd0 != null) {
|
||||
costs0 = cd0.getAmt();
|
||||
log.info("[8.3] CostDetail: " + cd0.get_ID() + " - " + costs0);
|
||||
} else {
|
||||
costs0 = line0.getProductCosts(as, line0.getAD_Org_ID(), false);
|
||||
log.info("[8.4] ProductCost: " + line0.get_ID() + " - " + costs0);
|
||||
}
|
||||
costMap.put(line0.get_ID() + "_" + line0.getM_AttributeSetInstance_ID(), costs0);
|
||||
bomCost = bomCost.add(costs0);
|
||||
|
|
@ -403,34 +421,37 @@ public class MID_DocProduction extends Doc
|
|||
BigDecimal costs0;
|
||||
if (cd0 != null) {
|
||||
costs0 = cd0.getAmt();
|
||||
log.info("[8.5] CostDetail: " + cd0.get_ID() + " - " + costs0);
|
||||
} else {
|
||||
costs0 = line0.getProductCosts(as, line0.getAD_Org_ID(), false);
|
||||
log.info("[8.6] ProductCost: " + line0.get_ID() + " - " + costs0);
|
||||
}
|
||||
costMap.put(line0.get_ID() + "_" + line0.getM_AttributeSetInstance_ID(), costs0);
|
||||
bomCost = bomCost.add(costs0);
|
||||
}
|
||||
}
|
||||
}
|
||||
log.info("BOM Cost: " + bomCost + ", Total Charge Amount: " + totalChargeAmt);
|
||||
log.info("[9] BOM Cost: " + bomCost + ", Total Charge Amount: " + totalChargeAmt);
|
||||
qtyProduced = manipulateQtyProduced(mQtyProduced, endProLine, prod.isUseProductionPlan(), null);
|
||||
if (line.getQty().compareTo(qtyProduced) != 0) {
|
||||
BigDecimal factor = line.getQty().divide(qtyProduced, 12, RoundingMode.HALF_UP);
|
||||
bomCost = bomCost.multiply(factor);
|
||||
}
|
||||
// if bomCost is negative, it means charge cost, so we need to negate it
|
||||
if (bomCost.signum() < 0) {
|
||||
bomCost = bomCost.add(totalChargeAmt.negate());
|
||||
}else {
|
||||
bomCost = bomCost.add(totalChargeAmt);
|
||||
}
|
||||
|
||||
log.info("Final BOM Cost: " + bomCost + ", Total Charge Amount: " + totalChargeAmt);
|
||||
bomCost = bomCost.add(totalChargeAmt.negate());
|
||||
// if (bomCost.signum() < 0) {
|
||||
// bomCost = bomCost.add(totalChargeAmt.negate());
|
||||
// }else {
|
||||
// bomCost = bomCost.add(totalChargeAmt);
|
||||
// }
|
||||
|
||||
log.info("[10] Final BOM Cost: " + bomCost + ", Total Charge Amount: " + totalChargeAmt);
|
||||
|
||||
// add total charge amount to BOM cost
|
||||
|
||||
if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(CostingLevel)) {
|
||||
//post roll-up
|
||||
log.info("COSTINGLEVEL_BatchLot "+bomCost.setScale(stdPrecision, RoundingMode.HALF_UP));
|
||||
log.info("[11] COSTINGLEVEL_BatchLot "+bomCost.setScale(stdPrecision, RoundingMode.HALF_UP));
|
||||
fl = fact.createLine(line,
|
||||
line.getAccount(ProductCost.ACCTTYPE_P_Asset, as),
|
||||
as.getC_Currency_ID(), bomCost.setScale(stdPrecision, RoundingMode.HALF_UP));
|
||||
|
|
@ -442,9 +463,11 @@ public class MID_DocProduction extends Doc
|
|||
} else if (MAcctSchema.COSTINGMETHOD_StandardCosting.equals(costingMethod)) {
|
||||
BigDecimal variance = costs.subtract(bomCost).setScale(stdPrecision, RoundingMode.HALF_UP);
|
||||
// only post variance if it's not zero
|
||||
log.info("COSTINGMETHOD_StandardCosting "+variance);
|
||||
log.info("[12] COSTINGMETHOD_StandardCosting "+variance);
|
||||
if (variance.signum() != 0) {
|
||||
//post variance
|
||||
log.info("[13] Posting Variance for Standard Costing: " + variance.setScale(stdPrecision, RoundingMode.HALF_UP)
|
||||
+ ", Product=" + product.getName() + " - " + product.getValue());
|
||||
fl = fact.createLine(line,
|
||||
line.getAccount(ProductCost.ACCTTYPE_P_RateVariance, as),
|
||||
as.getC_Currency_ID(), variance.negate());
|
||||
|
|
@ -462,9 +485,21 @@ public class MID_DocProduction extends Doc
|
|||
// Inventory DR CR
|
||||
if (!(line.isProductionBOM() && MAcctSchema.COSTINGLEVEL_BatchLot.equals(CostingLevel))) {
|
||||
BigDecimal factLineAmt = costs;
|
||||
log.info("[14] Fact Line Amount before BOM check: " + factLineAmt.setScale(stdPrecision, RoundingMode.HALF_UP)
|
||||
+ ", Product=" + product.getName() + " - " + product.getValue());
|
||||
if (line.isProductionBOM() && !(MAcctSchema.COSTINGMETHOD_StandardCosting.equals(costingMethod))) {
|
||||
log.info("[15.1] isProductionBOM and not Standard Costing, negate bomCost: " + bomCost.setScale(stdPrecision, RoundingMode.HALF_UP)
|
||||
+ ", Product=" + product.getName() + " - " + product.getValue());
|
||||
factLineAmt = bomCost.negate();
|
||||
}
|
||||
log.info("[15.2] Creating Fact Line for Inventory: " + factLineAmt.setScale(stdPrecision, RoundingMode.HALF_UP)
|
||||
+ ", Product=" + product.getName() + " - " + product.getValue());
|
||||
// is end product
|
||||
if(prodline.isEndProduct() && isEndProductWithAnyLinesChargeAndNoMaterial) {
|
||||
// if end product with any lines charge and no material, then inventory account from charge
|
||||
log.info("[15.3] isEndProductWithAnyLinesChargeAndNoMaterial, get inventory account from charge");
|
||||
factLineAmt = factLineAmt.negate();
|
||||
}
|
||||
fl = fact.createLine(line,
|
||||
line.getAccount(ProductCost.ACCTTYPE_P_Asset, as),
|
||||
as.getC_Currency_ID(), factLineAmt.setScale(stdPrecision, RoundingMode.HALF_UP));
|
||||
|
|
@ -484,6 +519,8 @@ public class MID_DocProduction extends Doc
|
|||
description += "(*)";
|
||||
if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(CostingLevel)) {
|
||||
if (line.isProductionBOM()) {
|
||||
log.info("[16] Posting Cost Detail for BOM Line: " + line.getLine() + " - " + line.getDescription()
|
||||
+ ", Product=" + product.getName() + " - " + product.getValue());
|
||||
if (!MCostDetail.createProduction(as, line.getAD_Org_ID(),
|
||||
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
|
||||
line.get_ID(), 0,
|
||||
|
|
@ -500,6 +537,10 @@ public class MID_DocProduction extends Doc
|
|||
{
|
||||
MProductionLineMA ma = mas[j];
|
||||
BigDecimal maCost = costMap.get(line.get_ID() + "_" + ma.getM_AttributeSetInstance_ID());
|
||||
log.info("[17] Posting Cost Detail for MA Line: " + line.getLine() + " - " + line.getDescription()
|
||||
+ ", Product=" + product.getName() + " - " + product.getValue()
|
||||
+ ", ASI=" + ma.getM_AttributeSetInstance_ID() + ", Qty=" + ma.getMovementQty()
|
||||
+ ", Cost=" + maCost);
|
||||
if (!MCostDetail.createProduction(as, line.getAD_Org_ID(),
|
||||
line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(),
|
||||
line.get_ID(), 0,
|
||||
|
|
@ -513,6 +554,10 @@ public class MID_DocProduction extends Doc
|
|||
}
|
||||
else
|
||||
{
|
||||
log.info("[18] Posting Cost Detail for Line: " + line.getLine() + " - " + line.getDescription()
|
||||
+ ", Product=" + product.getName() + " - " + product.getValue()
|
||||
+ ", ASI=" + line.getM_AttributeSetInstance_ID() + ", Qty=" + line.getQty()
|
||||
+ ", Cost=" + costs);
|
||||
if (!MCostDetail.createProduction(as, line.getAD_Org_ID(),
|
||||
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
|
||||
line.get_ID(), 0,
|
||||
|
|
@ -525,7 +570,7 @@ public class MID_DocProduction extends Doc
|
|||
}
|
||||
} else {
|
||||
if (line.isProductionBOM() && !(MAcctSchema.COSTINGMETHOD_StandardCosting.equals(costingMethod))) {
|
||||
log.info("Posting Cost Detail for BOM Line: " + line.getLine() + " - " + line.getDescription()
|
||||
log.info("[19] Posting Cost Detail for BOM Line: " + line.getLine() + " - " + line.getDescription()
|
||||
+ ", Product=" + product.getName() + " - " + product.getValue());
|
||||
if (!MCostDetail.createProduction(as, line.getAD_Org_ID(),
|
||||
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
|
||||
|
|
@ -537,6 +582,10 @@ public class MID_DocProduction extends Doc
|
|||
return null;
|
||||
}
|
||||
} else {
|
||||
log.info("[20] Posting Cost Detail for Line: " + line.getLine() + " - " + line.getDescription()
|
||||
+ ", Product=" + product.getName() + " - " + product.getValue()
|
||||
+ ", ASI=" + line.getM_AttributeSetInstance_ID() + ", Qty=" + line.getQty()
|
||||
+ ", Cost=" + costs);
|
||||
if (!MCostDetail.createProduction(as, line.getAD_Org_ID(),
|
||||
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
|
||||
line.get_ID(), 0,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package balinusa.midsuit.model;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
|
@ -18,6 +19,7 @@ import org.compiere.model.MDocType;
|
|||
import org.compiere.model.MInventory;
|
||||
import org.compiere.model.MInventoryLine;
|
||||
import org.compiere.model.MInventoryLineMA;
|
||||
import org.compiere.model.MMovementLine;
|
||||
import org.compiere.model.MPeriod;
|
||||
import org.compiere.model.MProduct;
|
||||
import org.compiere.model.MStorageOnHand;
|
||||
|
|
@ -519,6 +521,63 @@ public class MID_MInventory extends MInventory {
|
|||
}
|
||||
|
||||
return super.afterSave(newRecord, success);
|
||||
}else if (get_ValueAsInt("M_Movement_ID") != 0 ) {
|
||||
int M_Movement_ID = get_ValueAsInt("M_Movement_ID");
|
||||
// Perform actions related to M_Movement_ID
|
||||
MID_MMovement movement = new MID_MMovement(getCtx(), M_Movement_ID, get_TrxName());
|
||||
MMovementLine[] lines = movement.getLines(true);
|
||||
int chargeID = DB.getSQLValueEx(null, " SELECT cc.C_Charge_ID FROM C_ChargeType_DocType cctd JOIN C_Charge cc ON cc.C_ChargeType_ID = cctd.C_ChargeType_ID WHERE cctd.C_DocType_ID = ? LIMIT 1 ", getC_DocType_ID());
|
||||
// filter and sum MovementQty by M_Product_ID and M_LocatorTo_ID
|
||||
StringBuffer sql = new StringBuffer("SELECT MIN(sl.M_MovementLine_ID) AS M_MovementLine_ID, ")
|
||||
.append(" sl.M_Product_ID, ")
|
||||
.append(" sl.M_LocatorTo_ID, ")
|
||||
.append(" SUM(sl.MovementQty) AS MovementQty ")
|
||||
.append("FROM M_MovementLine sl ")
|
||||
.append("WHERE sl.M_Movement_ID=? ") // filter header jika perlu
|
||||
.append("GROUP BY sl.M_Product_ID, sl.M_LocatorTo_ID");
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
pstmt = DB.prepareStatement(sql.toString(), get_TrxName());
|
||||
pstmt.setInt(1, M_Movement_ID); // set parameter header jika perlu
|
||||
rs = pstmt.executeQuery();
|
||||
// create array list to store filtered lines
|
||||
while (rs.next()) {
|
||||
MMovementLine line = new MMovementLine(getCtx(), rs.getInt("M_MovementLine_ID"), get_TrxName());
|
||||
MInventoryLine inventoryLine = new MInventoryLine(getCtx(), 0, get_TrxName());
|
||||
inventoryLine.setAD_Org_ID(getAD_Org_ID());
|
||||
inventoryLine.setM_Inventory_ID(getM_Inventory_ID());
|
||||
inventoryLine.setC_Charge_ID(chargeID);
|
||||
inventoryLine.setM_Product_ID(line.getM_Product_ID());
|
||||
inventoryLine.setM_Locator_ID(line.getM_LocatorTo_ID());
|
||||
inventoryLine.set_ValueOfColumn("QtyEntered", rs.getBigDecimal("MovementQty"));;
|
||||
inventoryLine.setQtyInternalUse(rs.getBigDecimal("MovementQty"));
|
||||
inventoryLine.saveEx();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
DB.close(rs, pstmt);
|
||||
rs = null;
|
||||
pstmt = null;
|
||||
}
|
||||
// MMovementLine[] filteredLines = sumMovementLines(lines);
|
||||
//
|
||||
// for (MMovementLine line : lines) {
|
||||
// // create inventory line for each movement line
|
||||
// MInventoryLine inventoryLine = new MInventoryLine(getCtx(), 0, get_TrxName());
|
||||
//
|
||||
// BigDecimal existingQtyInternalUse = inventoryLine.getQtyInternalUse() != null ? inventoryLine.getQtyInternalUse() : BigDecimal.ZERO;
|
||||
// BigDecimal newQtyInternalUse = existingQtyInternalUse.add(line.getMovementQty());
|
||||
// inventoryLine.setAD_Org_ID(getAD_Org_ID());
|
||||
// inventoryLine.setM_Inventory_ID(getM_Inventory_ID());
|
||||
// inventoryLine.setC_Charge_ID(chargeID);
|
||||
// inventoryLine.setM_Product_ID(line.getM_Product_ID());
|
||||
// inventoryLine.setM_Locator_ID(line.getM_LocatorTo_ID());
|
||||
// inventoryLine.set_ValueOfColumn("QtyEntered", newQtyInternalUse);;
|
||||
// inventoryLine.setQtyInternalUse(newQtyInternalUse);
|
||||
// inventoryLine.saveEx();
|
||||
// }
|
||||
}
|
||||
|
||||
return super.afterSave(newRecord, success);
|
||||
|
|
@ -527,5 +586,34 @@ public class MID_MInventory extends MInventory {
|
|||
|
||||
return super.afterSave(newRecord, success);
|
||||
}
|
||||
private MMovementLine[] sumMovementLines(MMovementLine[] lines) {
|
||||
// TODO Auto-generated method stub
|
||||
// create new array list
|
||||
MMovementLine[] summedLines = new MMovementLine[lines.length];
|
||||
// loop through lines
|
||||
for (MMovementLine line : lines) {
|
||||
boolean found = false;
|
||||
for (int i = 0; i < summedLines.length; i++) {
|
||||
if (summedLines[i] != null && summedLines[i].getM_Product_ID() == line.getM_Product_ID()
|
||||
&& summedLines[i].getM_LocatorTo_ID() == line.getM_LocatorTo_ID()) {
|
||||
// if product and locator already in array list, sum the movement qty
|
||||
summedLines[i].setMovementQty(summedLines[i].getMovementQty().add(line.getMovementQty()));
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// if product and locator not in array list, add to array list
|
||||
for (int i = 0; i < summedLines.length; i++) {
|
||||
if (summedLines[i] == null) {
|
||||
summedLines[i] = line;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// check if product and locator already in array list
|
||||
return summedLines;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import org.compiere.model.I_M_InventoryLineMA;
|
|||
import org.compiere.model.MInventoryLine;
|
||||
import org.compiere.model.MInventoryLineMA;
|
||||
import org.compiere.model.MStorageOnHand;
|
||||
import org.compiere.model.PO;
|
||||
import org.compiere.model.Query;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.DB;
|
||||
|
|
@ -46,17 +47,53 @@ public class MID_MInventoryLineMA extends MInventoryLineMA {
|
|||
return addOrCreate(line, M_AttributeSetInstance_ID, MovementQty,DateMaterialPolicy,true);
|
||||
}
|
||||
|
||||
public static MID_MInventoryLineMA addOrCreate(MInventoryLine line, int M_AttributeSetInstance_ID, BigDecimal MovementQty, Timestamp DateMaterialPolicy,boolean isAutoGenerated)
|
||||
// Language: Java
|
||||
public static MID_MInventoryLineMA addOrCreate(
|
||||
MInventoryLine line,
|
||||
int M_AttributeSetInstance_ID,
|
||||
BigDecimal MovementQty,
|
||||
Timestamp DateMaterialPolicy,
|
||||
boolean isAutoGenerated)
|
||||
{
|
||||
Query query = new Query(Env.getCtx(), I_M_InventoryLineMA.Table_Name, "M_InventoryLine_ID=? AND M_AttributeSetInstance_ID=? AND DateMaterialPolicy=trunc(cast(? as date))",
|
||||
line.get_TrxName());
|
||||
MID_MInventoryLineMA po = query.setParameters(line.getM_InventoryLine_ID(), M_AttributeSetInstance_ID, DateMaterialPolicy).first();
|
||||
if (po == null)
|
||||
po = new MID_MInventoryLineMA(line, M_AttributeSetInstance_ID, MovementQty, DateMaterialPolicy,isAutoGenerated);
|
||||
else
|
||||
po.setMovementQty(po.getMovementQty().add(MovementQty));
|
||||
return po;
|
||||
// Guard: pastikan qty ga null
|
||||
if (MovementQty == null)
|
||||
MovementQty = Env.ZERO;
|
||||
|
||||
// Cari existing row (kombinasi unik: Line + ASI + DateMaterialPolicy)
|
||||
Query query = new Query(
|
||||
Env.getCtx(),
|
||||
I_M_InventoryLineMA.Table_Name,
|
||||
"M_InventoryLine_ID=? AND M_AttributeSetInstance_ID=? AND DateMaterialPolicy=trunc(cast(? as date))",
|
||||
line.get_TrxName());
|
||||
|
||||
PO base = query
|
||||
.setParameters(line.getM_InventoryLine_ID(), M_AttributeSetInstance_ID, DateMaterialPolicy)
|
||||
.first();
|
||||
|
||||
MID_MInventoryLineMA po;
|
||||
|
||||
if (base != null) {
|
||||
// Muat ulang row yang sama tapi pakai subclass kita
|
||||
po = new MID_MInventoryLineMA(Env.getCtx(), base.get_ID(), line.get_TrxName());
|
||||
|
||||
BigDecimal current = po.getMovementQty();
|
||||
if (current == null) current = Env.ZERO;
|
||||
|
||||
po.setMovementQty(current.add(MovementQty));
|
||||
|
||||
} else {
|
||||
// Buat baru pakai constructor subclass
|
||||
po = new MID_MInventoryLineMA(line, M_AttributeSetInstance_ID, MovementQty, DateMaterialPolicy, isAutoGenerated);
|
||||
}
|
||||
|
||||
// Tergantung pola proyekmu: simpan di sini agar atomic,
|
||||
// atau kembalikan object lalu disave di layer pemanggil.
|
||||
po.saveEx();
|
||||
|
||||
return po;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static MID_MInventoryLineMA[] get (Properties ctx, int M_InventoryLine_ID, String trxName)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -38,10 +38,12 @@ import org.compiere.model.MPayment;
|
|||
import org.compiere.model.MPaymentProcessor;
|
||||
import org.compiere.model.MPaymentTransaction;
|
||||
import org.compiere.model.MPeriod;
|
||||
import org.compiere.model.MProduct;
|
||||
import org.compiere.model.MProductionLine;
|
||||
import org.compiere.model.MProject;
|
||||
import org.compiere.model.MRMALine;
|
||||
import org.compiere.model.MSysConfig;
|
||||
import org.compiere.model.MUOMConversion;
|
||||
import org.compiere.model.MUser;
|
||||
import org.compiere.model.MWarehouse;
|
||||
import org.compiere.model.MatchPOAutoMatch;
|
||||
|
|
@ -64,6 +66,7 @@ public class MID_MInvoice extends MInvoice implements DocAction{
|
|||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 5957690840999925125L;
|
||||
private static CLogger s_log = CLogger.getCLogger(MInvoice.class);
|
||||
|
||||
public MID_MInvoice(Properties ctx, int C_Order_ID, String trxName) {
|
||||
super(ctx, C_Order_ID, trxName);
|
||||
|
|
@ -171,7 +174,142 @@ public class MID_MInvoice extends MInvoice implements DocAction{
|
|||
}
|
||||
return bankAccount;
|
||||
}
|
||||
/**
|
||||
* Create Line from orderline/inoutline/rmaline
|
||||
* @param C_OrderLine_ID
|
||||
* @param M_InOutLine_ID
|
||||
* @param M_RMALine_ID
|
||||
* @param M_Product_ID
|
||||
* @param C_UOM_ID
|
||||
* @param Qty
|
||||
*/
|
||||
public void createLineFrom(int C_OrderLine_ID, int M_InOutLine_ID, int M_RMALine_ID,
|
||||
int M_Product_ID, int C_UOM_ID, BigDecimal Qty)
|
||||
{
|
||||
MInvoiceLine invoiceLine = new MInvoiceLine (this);
|
||||
invoiceLine.setM_Product_ID(M_Product_ID, C_UOM_ID); // Line UOM
|
||||
invoiceLine.setQty(Qty); // Invoiced/Entered
|
||||
BigDecimal QtyInvoiced = null;
|
||||
MProduct product = MProduct.get(Env.getCtx(), M_Product_ID);
|
||||
if (M_Product_ID > 0 && product.getC_UOM_ID() != C_UOM_ID) {
|
||||
QtyInvoiced = MUOMConversion.convertProductFrom(Env.getCtx(), M_Product_ID, C_UOM_ID, Qty);
|
||||
}
|
||||
if (QtyInvoiced == null)
|
||||
QtyInvoiced = Qty;
|
||||
invoiceLine.setQtyInvoiced(QtyInvoiced);
|
||||
|
||||
// Info
|
||||
MOrderLine orderLine = null;
|
||||
if (C_OrderLine_ID != 0)
|
||||
orderLine = new MOrderLine (Env.getCtx(), C_OrderLine_ID, get_TrxName());
|
||||
//
|
||||
MRMALine rmaLine = null;
|
||||
if (M_RMALine_ID > 0)
|
||||
rmaLine = new MRMALine (Env.getCtx(), M_RMALine_ID, get_TrxName());
|
||||
//
|
||||
MInOutLine inoutLine = null;
|
||||
if (M_InOutLine_ID != 0)
|
||||
{
|
||||
inoutLine = new MInOutLine (Env.getCtx(), M_InOutLine_ID, get_TrxName());
|
||||
if (orderLine == null && inoutLine.getC_OrderLine_ID() != 0)
|
||||
{
|
||||
C_OrderLine_ID = inoutLine.getC_OrderLine_ID();
|
||||
orderLine = new MOrderLine (Env.getCtx(), C_OrderLine_ID, get_TrxName());
|
||||
}
|
||||
}
|
||||
else if (C_OrderLine_ID > 0)
|
||||
{
|
||||
String whereClause = "EXISTS (SELECT 1 FROM M_InOut io WHERE io.M_InOut_ID=M_InOutLine.M_InOut_ID AND io.DocStatus IN ('CO','CL'))";
|
||||
MInOutLine[] lines = MInOutLine.getOfOrderLine(Env.getCtx(),
|
||||
C_OrderLine_ID, whereClause, get_TrxName());
|
||||
if (s_log.isLoggable(Level.FINE)) s_log.fine ("Receipt Lines with OrderLine = #" + lines.length);
|
||||
if (lines.length > 0)
|
||||
{
|
||||
for (int j = 0; j < lines.length; j++)
|
||||
{
|
||||
MInOutLine line = lines[j];
|
||||
// qty matched
|
||||
BigDecimal qtyMatched = Env.ZERO;
|
||||
for (MMatchInv match : MMatchInv.getInOutLine(Env.getCtx(), line.getM_InOutLine_ID(), get_TrxName())) {
|
||||
qtyMatched = qtyMatched.add(match.getQty());
|
||||
}
|
||||
if (line.getQtyEntered().subtract(qtyMatched).compareTo(Qty) == 0)
|
||||
{
|
||||
inoutLine = line;
|
||||
M_InOutLine_ID = inoutLine.getM_InOutLine_ID();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (M_RMALine_ID != 0)
|
||||
{
|
||||
String whereClause = "EXISTS (SELECT 1 FROM M_InOut io WHERE io.M_InOut_ID=M_InOutLine.M_InOut_ID AND io.DocStatus IN ('CO','CL'))";
|
||||
MInOutLine[] lines = MInOutLine.getOfRMALine(Env.getCtx(), M_RMALine_ID, whereClause, get_TrxName());
|
||||
if (s_log.isLoggable(Level.FINE)) s_log.fine ("Receipt Lines with RMALine = #" + lines.length);
|
||||
if (lines.length > 0)
|
||||
{
|
||||
for (int j = 0; j < lines.length; j++)
|
||||
{
|
||||
MInOutLine line = lines[j];
|
||||
BigDecimal alreadyInvoiced = rmaLine.getQtyInvoiced() != null ? rmaLine.getQtyInvoiced() : BigDecimal.ZERO;
|
||||
if (rmaLine.getQty().subtract(alreadyInvoiced).compareTo(Qty) >= 0)
|
||||
{
|
||||
inoutLine = line;
|
||||
M_InOutLine_ID = inoutLine.getM_InOutLine_ID();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rmaLine == null)
|
||||
{
|
||||
inoutLine = lines[0]; // first as default
|
||||
M_InOutLine_ID = inoutLine.getM_InOutLine_ID();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// get Ship info
|
||||
|
||||
// Shipment Info
|
||||
if (inoutLine != null)
|
||||
{
|
||||
invoiceLine.setShipLine(inoutLine); // overwrites
|
||||
if(invoiceLine.getC_UOM_ID()!=inoutLine.getC_UOM_ID()) {
|
||||
invoiceLine.setC_UOM_ID(inoutLine.getC_UOM_ID());
|
||||
BigDecimal PriceEntered = MUOMConversion.convertProductFrom (Env.getCtx(), M_Product_ID,
|
||||
inoutLine.getC_UOM_ID(), invoiceLine.getPriceEntered(), 12);
|
||||
if (PriceEntered == null)
|
||||
throw new AdempiereException("No Conversion For Price=" + invoiceLine.getPriceEntered());
|
||||
invoiceLine.setPriceEntered(PriceEntered);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (s_log.isLoggable(Level.FINE)) s_log.fine("No Receipt Line");
|
||||
// Order Info
|
||||
if (orderLine != null)
|
||||
{
|
||||
invoiceLine.setOrderLine(orderLine); // overwrites
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s_log.isLoggable(Level.FINE)) s_log.fine("No Order Line");
|
||||
invoiceLine.setPrice();
|
||||
invoiceLine.setTax();
|
||||
}
|
||||
|
||||
//RMA Info
|
||||
if (rmaLine != null)
|
||||
{
|
||||
invoiceLine.setRMALine(rmaLine); // overwrites
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s_log.isLoggable(Level.FINE)) s_log.fine("No RMA Line");
|
||||
}
|
||||
}
|
||||
invoiceLine.saveEx();
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete Document
|
||||
* @return new status (Complete, In Progress, Invalid, Waiting ..)
|
||||
|
|
|
|||
|
|
@ -549,6 +549,10 @@ public class MID_MPayment extends MPayment{
|
|||
}
|
||||
}
|
||||
}
|
||||
if(newRecord && getC_Order_ID() > 0 && !isPrepayment()) {
|
||||
setIsPrepayment(true);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
} // beforeSave
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import org.compiere.model.MProduct;
|
|||
import org.compiere.model.MProductCategory;
|
||||
import org.compiere.model.MProduction;
|
||||
import org.compiere.model.MProductionLine;
|
||||
import org.compiere.model.MProductionLineMA;
|
||||
import org.compiere.model.MProductionPlan;
|
||||
import org.compiere.model.MRequisitionLine;
|
||||
import org.compiere.model.MSequence;
|
||||
|
|
@ -32,6 +33,7 @@ import org.compiere.model.MTreeNode;
|
|||
import org.compiere.model.MTree_Base;
|
||||
import org.compiere.model.ModelValidationEngine;
|
||||
import org.compiere.model.ModelValidator;
|
||||
import org.compiere.model.PO;
|
||||
import org.compiere.model.Query;
|
||||
import org.compiere.model.X_AD_Tree;
|
||||
import org.compiere.model.X_M_CostElement;
|
||||
|
|
@ -50,6 +52,9 @@ import java.math.BigDecimal;
|
|||
import java.math.RoundingMode;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -82,6 +87,23 @@ public class MID_Production extends MProduction{
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lines
|
||||
* @return true if one of the production is an end product line (IsEndProduct=Y) and any materials minimum 1 and quantity.
|
||||
*/
|
||||
private boolean isHaveEndProductAndMaterials(MProductionLine[] lines) {
|
||||
boolean isHaveEndProduct = false;
|
||||
boolean isHaveMaterials = false;
|
||||
|
||||
for(MProductionLine line : lines) {
|
||||
if(line.isEndProduct())
|
||||
isHaveEndProduct = true;
|
||||
else if(line.getM_Product_ID() > 0 && line.getQtyUsed().compareTo(Env.ZERO) > 0)
|
||||
isHaveMaterials = true;
|
||||
}
|
||||
return isHaveEndProduct && isHaveMaterials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create production line
|
||||
* @param mustBeStocked true to verify BOM component has sufficient on hand
|
||||
|
|
@ -115,7 +137,238 @@ public class MID_Production extends MProduction{
|
|||
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reverseCorrectIt()
|
||||
{
|
||||
if (log.isLoggable(Level.INFO)) log.info(toString());
|
||||
// Before reverseCorrect
|
||||
m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_BEFORE_REVERSECORRECT);
|
||||
if (m_processMsg != null)
|
||||
return false;
|
||||
|
||||
MProduction reversal = reverse(false);
|
||||
if (reversal == null)
|
||||
return false;
|
||||
|
||||
// After reverseCorrect
|
||||
m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_REVERSECORRECT);
|
||||
if (m_processMsg != null)
|
||||
return false;
|
||||
|
||||
m_processMsg = reversal.getDocumentNo();
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Create new production from this production (including lines)
|
||||
* @param reversalDate movement date
|
||||
* @return new production record
|
||||
*/
|
||||
protected MID_Production copyFrom(Timestamp reversalDate) {
|
||||
MID_Production to = new MID_Production(getCtx(), 0, get_TrxName());
|
||||
PO.copyValues (this, to, getAD_Client_ID(), getAD_Org_ID());
|
||||
|
||||
to.set_ValueNoCheck ("DocumentNo", null);
|
||||
//
|
||||
to.setDocStatus (DOCSTATUS_Drafted); // Draft
|
||||
to.setDocAction(DOCACTION_Complete);
|
||||
to.setMovementDate(reversalDate);
|
||||
to.setIsComplete(false);
|
||||
to.setIsCreated("Y");
|
||||
to.setProcessing(false);
|
||||
to.setProcessed(false);
|
||||
to.setIsUseProductionPlan(isUseProductionPlan());
|
||||
if (isUseProductionPlan()) {
|
||||
to.saveEx();
|
||||
Query planQuery = new Query(Env.getCtx(), I_M_ProductionPlan.Table_Name, "M_ProductionPlan.M_Production_ID=?", get_TrxName());
|
||||
List<MProductionPlan> fplans = planQuery.setParameters(getM_Production_ID()).list();
|
||||
for(MProductionPlan fplan : fplans) {
|
||||
MProductionPlan tplan = new MProductionPlan(getCtx(), 0, get_TrxName());
|
||||
PO.copyValues (fplan, tplan, getAD_Client_ID(), getAD_Org_ID());
|
||||
tplan.setM_Production_ID(to.getM_Production_ID());
|
||||
tplan.setProductionQty(fplan.getProductionQty().negate());
|
||||
tplan.setProcessed(false);
|
||||
tplan.saveEx();
|
||||
|
||||
MProductionLine[] flines = fplan.getLines();
|
||||
for(MProductionLine fline : flines) {
|
||||
MProductionLine tline = new MProductionLine(tplan);
|
||||
PO.copyValues (fline, tline, getAD_Client_ID(), getAD_Org_ID());
|
||||
tline.setM_ProductionPlan_ID(tplan.getM_ProductionPlan_ID());
|
||||
tline.setMovementQty(fline.getMovementQty().negate());
|
||||
tline.setPlannedQty(fline.getPlannedQty().negate());
|
||||
tline.setQtyUsed(fline.getQtyUsed().negate());
|
||||
tline.saveEx();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
to.setProductionQty(getProductionQty().negate());
|
||||
to.saveEx();
|
||||
MProductionLine[] flines = getLinesWithCharge();
|
||||
log.info("Lines to reverse: " + flines.length);
|
||||
for(MProductionLine fline : flines) {
|
||||
MProductionLine tline = new MProductionLine(to);
|
||||
PO.copyValues (fline, tline, getAD_Client_ID(), getAD_Org_ID());
|
||||
tline.setM_Production_ID(to.getM_Production_ID());
|
||||
tline.setMovementQty(fline.getMovementQty().negate());
|
||||
tline.setPlannedQty(fline.getPlannedQty().negate());
|
||||
tline.setQtyUsed(fline.getQtyUsed().negate());
|
||||
if(fline.get_Value("C_Charge_ID") != null) {
|
||||
BigDecimal priceEntered = (BigDecimal) fline.get_Value("PriceEntered");
|
||||
BigDecimal quantity = fline.getQtyUsed().negate();
|
||||
tline.set_ValueOfColumn("C_Charge_ID", fline.get_Value("C_Charge_ID"));
|
||||
tline.setM_Product_ID(0);
|
||||
tline.set_ValueOfColumn("PriceEntered", fline.get_Value("PriceEntered"));
|
||||
tline.set_ValueOfColumn("LineNetAmt", priceEntered.multiply(quantity));
|
||||
};
|
||||
tline.saveEx();
|
||||
}
|
||||
}
|
||||
|
||||
return to;
|
||||
}
|
||||
/**
|
||||
* Reverse this production document
|
||||
* @param accrual true to use current date, false to use this production's movement date
|
||||
* @return reversal production record
|
||||
*/
|
||||
protected MProduction reverse(boolean accrual) {
|
||||
Timestamp reversalDate = accrual ? Env.getContextAsDate(getCtx(), Env.DATE) : getMovementDate();
|
||||
if (reversalDate == null) {
|
||||
reversalDate = new Timestamp(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
if (getC_OrderLine_ID() > 0)
|
||||
setC_OrderLine_ID(0);
|
||||
// if (isProcessed()) {
|
||||
// setProcessed(false);
|
||||
// saveEx(get_TrxName());
|
||||
// }
|
||||
MPeriod.testPeriodOpen(getCtx(), reversalDate, getC_DocType_ID(), getAD_Org_ID());
|
||||
MID_Production reversal = null;
|
||||
reversal = copyFrom(reversalDate);
|
||||
|
||||
StringBuilder msgadd = new StringBuilder("{->").append(getDocumentNo()).append(")");
|
||||
reversal.addDescription(msgadd.toString());
|
||||
reversal.setReversal_ID(getM_Production_ID());
|
||||
|
||||
reversal.saveEx(get_TrxName());
|
||||
|
||||
// Reverse Line Qty
|
||||
MProductionLine[] sLines = getLinesWithCharge();
|
||||
MProductionLine[] tLines = reversal.getLinesWithCharge();
|
||||
for (int i = 0; i < sLines.length; i++)
|
||||
{
|
||||
// We need to copy MA and required product
|
||||
if (sLines[i].getM_AttributeSetInstance_ID() == 0 && sLines[i].getM_Product_ID() != 0)
|
||||
{
|
||||
MProductionLineMA mas[] = MProductionLineMA.get(getCtx(), sLines[i].get_ID(), get_TrxName());
|
||||
for (int j = 0; j < mas.length; j++)
|
||||
{
|
||||
MProductionLineMA ma = new MProductionLineMA (tLines[i],
|
||||
mas[j].getM_AttributeSetInstance_ID(),
|
||||
mas[j].getMovementQty().negate(),mas[j].getDateMaterialPolicy());
|
||||
ma.saveEx(get_TrxName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!reversal.processIt(DocAction.ACTION_Complete))
|
||||
{
|
||||
m_processMsg = "Reversal ERROR: " + reversal.getProcessMsg();
|
||||
return null;
|
||||
}
|
||||
|
||||
reversal.closeIt();
|
||||
reversal.setProcessing (false);
|
||||
reversal.setDocStatus(DOCSTATUS_Reversed);
|
||||
reversal.setDocAction(DOCACTION_None);
|
||||
reversal.saveEx(get_TrxName());
|
||||
|
||||
msgadd = new StringBuilder("(").append(reversal.getDocumentNo()).append("<-)");
|
||||
addDescription(msgadd.toString());
|
||||
|
||||
setProcessed(true);
|
||||
setReversal_ID(reversal.getM_Production_ID());
|
||||
setDocStatus(DOCSTATUS_Reversed); // may come from void
|
||||
setDocAction(DOCACTION_None);
|
||||
|
||||
return reversal;
|
||||
}
|
||||
/**
|
||||
* Get production lines
|
||||
* @return array of MProductionLine
|
||||
*/
|
||||
public MProductionLine[] getLines() {
|
||||
ArrayList<MProductionLine> list = new ArrayList<MProductionLine>();
|
||||
|
||||
String sql = "SELECT pl.M_ProductionLine_ID "
|
||||
+ "FROM M_ProductionLine pl "
|
||||
+ "WHERE pl.m_product_id is not null and pl.M_Production_ID = ? "
|
||||
+ "ORDER BY pl.Line, pl.M_ProductionLine_ID ";
|
||||
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{
|
||||
pstmt = DB.prepareStatement(sql, get_TrxName());
|
||||
pstmt.setInt(1, get_ID());
|
||||
rs = pstmt.executeQuery();
|
||||
while (rs.next())
|
||||
list.add( new MProductionLine( getCtx(), rs.getInt(1), get_TrxName() ) );
|
||||
}
|
||||
catch (SQLException ex)
|
||||
{
|
||||
throw new AdempiereException("Unable to load production lines", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DB.close(rs, pstmt);
|
||||
rs = null;
|
||||
pstmt = null;
|
||||
}
|
||||
|
||||
MProductionLine[] retValue = new MProductionLine[list.size()];
|
||||
list.toArray(retValue);
|
||||
return retValue;
|
||||
}
|
||||
/**
|
||||
* Get production lines
|
||||
* @return array of MProductionLine
|
||||
*/
|
||||
public MProductionLine[] getLinesWithCharge() {
|
||||
ArrayList<MProductionLine> list = new ArrayList<MProductionLine>();
|
||||
|
||||
String sql = "SELECT pl.M_ProductionLine_ID "
|
||||
+ "FROM M_ProductionLine pl "
|
||||
+ "WHERE pl.M_Production_ID = ? "
|
||||
+ "ORDER BY pl.Line, pl.M_ProductionLine_ID ";
|
||||
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{
|
||||
pstmt = DB.prepareStatement(sql, get_TrxName());
|
||||
pstmt.setInt(1, get_ID());
|
||||
rs = pstmt.executeQuery();
|
||||
while (rs.next())
|
||||
list.add( new MProductionLine( getCtx(), rs.getInt(1), get_TrxName() ) );
|
||||
}
|
||||
catch (SQLException ex)
|
||||
{
|
||||
throw new AdempiereException("Unable to load production lines", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DB.close(rs, pstmt);
|
||||
rs = null;
|
||||
pstmt = null;
|
||||
}
|
||||
|
||||
MProductionLine[] retValue = new MProductionLine[list.size()];
|
||||
list.toArray(retValue);
|
||||
return retValue;
|
||||
}
|
||||
/**
|
||||
* Create production line
|
||||
* @param mustBeStocked true to verify BOM component has sufficient on hand
|
||||
|
|
@ -406,8 +659,14 @@ public class MID_Production extends MProduction{
|
|||
|
||||
if ( getIsCreated().equals("N") )
|
||||
{
|
||||
m_processMsg = "Not created";
|
||||
return DocAction.STATUS_Invalid;
|
||||
// get lines length
|
||||
MProductionLine[] lines = getLines();
|
||||
if(lines.length == 0) {
|
||||
m_processMsg = "No production lines";
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
// m_processMsg = "Not created";
|
||||
// return DocAction.STATUS_Invalid;
|
||||
}
|
||||
// !isUseProductionPlan()
|
||||
log.info("END PRODUCT: " + !isUseProductionPlan());
|
||||
|
|
@ -469,6 +728,10 @@ public class MID_Production extends MProduction{
|
|||
m_processMsg = "Production does not contain End Product";
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
// if(!isHaveEndProductAndMaterials(lines)) {
|
||||
// m_processMsg = "Production must contain Materials";
|
||||
// return DocAction.STATUS_Invalid;
|
||||
// }
|
||||
errors.append(processLines(lines));
|
||||
if (errors.length() > 0) {
|
||||
m_processMsg = errors.toString();
|
||||
|
|
@ -477,8 +740,8 @@ public class MID_Production extends MProduction{
|
|||
processed = processed + lines.length;
|
||||
} else {
|
||||
Query planQuery = new Query(Env.getCtx(), I_M_ProductionPlan.Table_Name, "M_ProductionPlan.M_Production_ID=?", get_TrxName());
|
||||
List<MProductionPlan> plans = planQuery.setParameters(getM_Production_ID()).list();
|
||||
for(MProductionPlan plan : plans) {
|
||||
List<MID_ProductionPlan> plans = planQuery.setParameters(getM_Production_ID()).list();
|
||||
for(MID_ProductionPlan plan : plans) {
|
||||
MProductionLine[] lines = plan.getLines();
|
||||
|
||||
//IDEMPIERE-3107 Check if End Product in Production Lines exist
|
||||
|
|
@ -486,6 +749,11 @@ public class MID_Production extends MProduction{
|
|||
m_processMsg = String.format("Production plan (line %1$d id %2$d) does not contain End Product", plan.getLine(), plan.get_ID());
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
|
||||
// if(!isHaveEndProductAndMaterials(lines)) {
|
||||
// m_processMsg = "Production must contain Materials";
|
||||
// return DocAction.STATUS_Invalid;
|
||||
// }
|
||||
|
||||
if (lines.length > 0) {
|
||||
errors.append(processLines(lines));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,122 @@
|
|||
package balinusa.midsuit.model;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.compiere.model.I_M_ProductionPlan;
|
||||
import org.compiere.model.MAccount;
|
||||
import org.compiere.model.MAcctSchema;
|
||||
import org.compiere.model.MAttributeSetInstance;
|
||||
import org.compiere.model.MClient;
|
||||
import org.compiere.model.MClientInfo;
|
||||
import org.compiere.model.MCost;
|
||||
import org.compiere.model.MCostElement;
|
||||
import org.compiere.model.MLocator;
|
||||
import org.compiere.model.MOrderLine;
|
||||
import org.compiere.model.MOrg;
|
||||
import org.compiere.model.MPeriod;
|
||||
import org.compiere.model.MProduct;
|
||||
import org.compiere.model.MProductCategory;
|
||||
import org.compiere.model.MProduction;
|
||||
import org.compiere.model.MProductionLine;
|
||||
import org.compiere.model.MProductionLineMA;
|
||||
import org.compiere.model.MProductionPlan;
|
||||
import org.compiere.model.MRequisitionLine;
|
||||
import org.compiere.model.MSequence;
|
||||
import org.compiere.model.MStorageOnHand;
|
||||
import org.compiere.model.MStorageReservation;
|
||||
import org.compiere.model.MSysConfig;
|
||||
import org.compiere.model.MTable;
|
||||
import org.compiere.model.MTree;
|
||||
import org.compiere.model.MTreeNode;
|
||||
import org.compiere.model.MTree_Base;
|
||||
import org.compiere.model.ModelValidationEngine;
|
||||
import org.compiere.model.ModelValidator;
|
||||
import org.compiere.model.Query;
|
||||
import org.compiere.model.X_AD_Tree;
|
||||
import org.compiere.model.X_M_CostElement;
|
||||
import org.compiere.model.X_M_Product;
|
||||
import org.compiere.process.DocAction;
|
||||
import org.compiere.util.AdempiereUserError;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.Util;
|
||||
import org.eevolution.model.MPPProductBOM;
|
||||
import org.eevolution.model.MPPProductBOMLine;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
public class MID_ProductionPlan extends MProductionPlan{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
private static final long serialVersionUID = 1563913040977233621L;
|
||||
private boolean isValueEmptyBeforeSave = false;
|
||||
private static CLogger s_log = CLogger.getCLogger (MCost.class);
|
||||
protected int lineno;
|
||||
protected int count;
|
||||
|
||||
public MID_ProductionPlan(Properties ctx, String M_ProductionPlan_UU, String trxName) {
|
||||
super(ctx, M_ProductionPlan_UU, trxName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ctx
|
||||
* @param M_ProductionPlan_ID
|
||||
* @param trxName
|
||||
*/
|
||||
public MID_ProductionPlan(Properties ctx, int M_ProductionPlan_ID, String trxName) {
|
||||
super(ctx, M_ProductionPlan_ID, trxName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array of MProductionLine
|
||||
*/
|
||||
public MProductionLine[] getLines() {
|
||||
ArrayList<MProductionLine> list = new ArrayList<MProductionLine>();
|
||||
|
||||
String sql = "SELECT pl.M_ProductionLine_ID "
|
||||
+ "FROM M_ProductionLine pl "
|
||||
+ "WHERE pl.m_product_id is not null and pl.M_ProductionPlan_ID = ? "
|
||||
+ "ORDER BY pl.Line, pl.M_ProductionLine_ID ";
|
||||
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{
|
||||
pstmt = DB.prepareStatement(sql, get_TrxName());
|
||||
pstmt.setInt(1, get_ID());
|
||||
rs = pstmt.executeQuery();
|
||||
while (rs.next())
|
||||
list.add( new MProductionLine( getCtx(), rs.getInt(1), get_TrxName() ) );
|
||||
}
|
||||
catch (SQLException ex)
|
||||
{
|
||||
throw new AdempiereException("Unable to load production lines", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DB.close(rs, pstmt);
|
||||
rs = null;
|
||||
pstmt = null;
|
||||
}
|
||||
|
||||
MProductionLine[] retValue = new MProductionLine[list.size()];
|
||||
list.toArray(retValue);
|
||||
return retValue;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,255 @@
|
|||
package balinusa.midsuit.process;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.sql.PreparedStatement;
|
||||
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.I_M_ProductionPlan;
|
||||
import org.compiere.model.MInOut;
|
||||
import org.compiere.model.MInvoice;
|
||||
import org.compiere.model.MOrder;
|
||||
import org.compiere.model.MProcessPara;
|
||||
import org.compiere.model.MProduct;
|
||||
import org.compiere.model.MProduction;
|
||||
import org.compiere.model.MProductionPlan;
|
||||
import org.compiere.model.MRMA;
|
||||
import org.compiere.model.MTable;
|
||||
import org.compiere.model.Query;
|
||||
import org.compiere.process.DocAction;
|
||||
import org.compiere.process.ProcessInfoParameter;
|
||||
import org.compiere.process.SvrProcess;
|
||||
import org.compiere.util.AdempiereUserError;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
import balinusa.midsuit.model.MID_MRequisitionTrx;
|
||||
import balinusa.midsuit.model.MID_Production;
|
||||
|
||||
public class MID_InvoiceCreateLineFrom extends SvrProcess{
|
||||
|
||||
private int p_C_Invoice_ID = 0;
|
||||
|
||||
private ArrayList<Integer> selectionIDList = new ArrayList<Integer>();
|
||||
private HashMap<String, Object> selectionValueMap = new HashMap<String, Object>();
|
||||
private int m_created = 0;
|
||||
|
||||
@Override
|
||||
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 if (name.equals("C_Invoice_ID"))
|
||||
p_C_Invoice_ID = para[i].getParameterAsInt();
|
||||
else
|
||||
MProcessPara.validateUnknownParameter(getProcessInfo().getAD_Process_ID(), para[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doIt() throws Exception {
|
||||
if (p_C_Invoice_ID == 0)
|
||||
throw new AdempiereUserError("@NotFound@ @C_Invoice_ID@");
|
||||
|
||||
if (getProcessInfo().getAD_InfoWindow_ID() > 0)
|
||||
return createLines();
|
||||
else
|
||||
throw new AdempiereException("@NotSupported@");
|
||||
}
|
||||
|
||||
private String createLines() {
|
||||
// Get Invoice
|
||||
MInvoice invoice = new MInvoice(getCtx(), p_C_Invoice_ID, get_TrxName());
|
||||
if (log.isLoggable(Level.CONFIG)) log.config(invoice.toString());
|
||||
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT t.T_Selection_ID, CAST(t.ViewID AS Integer) AS AD_Table_ID ");
|
||||
sql.append("FROM T_Selection t ");
|
||||
sql.append("WHERE t.AD_PInstance_ID=? ");
|
||||
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{
|
||||
pstmt = DB.prepareStatement(sql.toString(), get_TrxName());
|
||||
pstmt.setInt(1, getAD_PInstance_ID());
|
||||
rs = pstmt.executeQuery();
|
||||
while (rs.next())
|
||||
{
|
||||
int T_Selection_ID = rs.getInt("T_Selection_ID");
|
||||
if (!selectionIDList.contains(T_Selection_ID))
|
||||
selectionIDList.add(T_Selection_ID);
|
||||
|
||||
String ColumnName = "AD_Table_ID";
|
||||
MTable table = MTable.get(rs.getInt(ColumnName));
|
||||
String key = table.getKeyColumns()[0] + "_" + T_Selection_ID;
|
||||
selectionValueMap.put(key, T_Selection_ID);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new AdempiereException(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DB.close(rs, pstmt);
|
||||
rs = null;
|
||||
pstmt = null;
|
||||
}
|
||||
|
||||
sql = new StringBuilder();
|
||||
sql.append("SELECT T_Selection_ID, ColumnName, Value_String, Value_Number, Value_Date ");
|
||||
sql.append("FROM T_Selection_InfoWindow ");
|
||||
sql.append("WHERE AD_PInstance_ID=? ");
|
||||
sql.append("ORDER BY T_Selection_ID, ColumnName ");
|
||||
|
||||
pstmt = null;
|
||||
rs = null;
|
||||
try
|
||||
{
|
||||
pstmt = DB.prepareStatement(sql.toString(), get_TrxName());
|
||||
pstmt.setInt(1, getAD_PInstance_ID());
|
||||
rs = pstmt.executeQuery();
|
||||
while (rs.next())
|
||||
{
|
||||
int T_Selection_ID = rs.getInt("T_Selection_ID");
|
||||
String ColumnName = rs.getString("ColumnName");
|
||||
String Value_String = rs.getString("Value_String");
|
||||
|
||||
Object Value_Number = null;
|
||||
if (ColumnName.toUpperCase().endsWith("_ID"))
|
||||
Value_Number = rs.getInt("Value_Number");
|
||||
else
|
||||
Value_Number = rs.getBigDecimal("Value_Number");
|
||||
|
||||
Timestamp Value_Date = rs.getTimestamp("Value_Date");
|
||||
|
||||
String key = ColumnName + "_" + T_Selection_ID;
|
||||
Object value = null;
|
||||
if (Value_String != null)
|
||||
value = Value_String;
|
||||
else if (Value_Number != null)
|
||||
value = Value_Number;
|
||||
else if (Value_Date != null)
|
||||
value = Value_Date;
|
||||
selectionValueMap.put(key, value);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new AdempiereException(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DB.close(rs, pstmt);
|
||||
rs = null;
|
||||
pstmt = null;
|
||||
}
|
||||
|
||||
MOrder m_order = null;
|
||||
MInOut m_inout = null;
|
||||
MRMA m_rma = null;
|
||||
|
||||
for (int i = 0; i < selectionIDList.size(); i++)
|
||||
{
|
||||
int T_Selection_ID = selectionIDList.get(i);
|
||||
|
||||
String ColumnName = "C_Order_ID";
|
||||
String key = ColumnName + "_" + T_Selection_ID;
|
||||
Object value = selectionValueMap.get(key);
|
||||
int C_Order_ID = value != null ? ((Number) value).intValue() : 0;
|
||||
if (C_Order_ID > 0 && (m_order == null || m_order.getC_Order_ID() != C_Order_ID))
|
||||
{
|
||||
m_order = new MOrder(getCtx(), C_Order_ID, get_TrxName());
|
||||
invoice.setOrder(m_order); // overwrite header values
|
||||
invoice.saveEx();
|
||||
}
|
||||
|
||||
ColumnName = "M_InOut_ID";
|
||||
key = ColumnName + "_" + T_Selection_ID;
|
||||
value = selectionValueMap.get(key);
|
||||
int M_InOut_ID = value != null ? ((Number) value).intValue() : 0;
|
||||
if (M_InOut_ID > 0 && (m_inout == null || m_inout.getM_InOut_ID() != M_InOut_ID))
|
||||
{
|
||||
m_inout = new MInOut(getCtx(), M_InOut_ID, get_TrxName());
|
||||
invoice.setShipment(m_inout);
|
||||
invoice.saveEx();
|
||||
}
|
||||
|
||||
ColumnName = "M_RMA_ID";
|
||||
key = ColumnName + "_" + T_Selection_ID;
|
||||
value = selectionValueMap.get(key);
|
||||
int M_RMA_ID = value != null ? ((Number) value).intValue() : 0;
|
||||
if (M_RMA_ID > 0 && (m_rma == null || m_rma.getM_RMA_ID() != M_RMA_ID))
|
||||
{
|
||||
m_rma = new MRMA(getCtx(), M_RMA_ID, get_TrxName());
|
||||
invoice.setM_RMA_ID(m_rma.getM_RMA_ID());
|
||||
invoice.saveEx();
|
||||
}
|
||||
|
||||
ColumnName = "Qty";
|
||||
key = ColumnName + "_" + T_Selection_ID;
|
||||
value = selectionValueMap.get(key);
|
||||
BigDecimal QtyEntered = value != null ? (BigDecimal) value : null;
|
||||
|
||||
ColumnName = "C_UOM_ID";
|
||||
key = ColumnName + "_" + T_Selection_ID;
|
||||
value = selectionValueMap.get(key);
|
||||
int C_UOM_ID = value != null ? ((Number) value).intValue() : 0;
|
||||
|
||||
ColumnName = "M_Product_ID";
|
||||
key = ColumnName + "_" + T_Selection_ID;
|
||||
value = selectionValueMap.get(key);
|
||||
int M_Product_ID = value != null ? ((Number) value).intValue() : 0;
|
||||
|
||||
ColumnName = "C_OrderLine_ID";
|
||||
key = ColumnName + "_" + T_Selection_ID;
|
||||
value = selectionValueMap.get(key);
|
||||
int C_OrderLine_ID = value != null ? ((Number) value).intValue() : 0;
|
||||
|
||||
ColumnName = "M_InOutLine_ID";
|
||||
key = ColumnName + "_" + T_Selection_ID;
|
||||
value = selectionValueMap.get(key);
|
||||
int M_InOutLine_ID = value != null ? ((Number) value).intValue() : 0;
|
||||
|
||||
ColumnName = "M_RMALine_ID";
|
||||
key = ColumnName + "_" + T_Selection_ID;
|
||||
value = selectionValueMap.get(key);
|
||||
int M_RMALine_ID = value != null ? ((Number) value).intValue() : 0;
|
||||
|
||||
// Precision of Qty UOM
|
||||
int precision = 2;
|
||||
if (M_Product_ID != 0)
|
||||
{
|
||||
MProduct product = MProduct.get(getCtx(), M_Product_ID);
|
||||
precision = product.getUOMPrecision();
|
||||
}
|
||||
QtyEntered = QtyEntered.setScale(precision, RoundingMode.HALF_DOWN);
|
||||
//
|
||||
if (log.isLoggable(Level.FINE)) log.fine("Line QtyEntered=" + QtyEntered
|
||||
+ ", Product=" + M_Product_ID
|
||||
+ ", OrderLine=" + C_OrderLine_ID + ", InOutLine_ID=" + M_InOutLine_ID);
|
||||
|
||||
// Create new Invoice Line
|
||||
invoice.createLineFrom(C_OrderLine_ID, M_InOutLine_ID, M_RMALine_ID, M_Product_ID, C_UOM_ID, QtyEntered);
|
||||
m_created++;
|
||||
} // for all rows
|
||||
|
||||
// Update Header
|
||||
invoice.updateFrom(m_order);
|
||||
|
||||
StringBuilder msgreturn = new StringBuilder("@Created@ = ").append(m_created);
|
||||
return msgreturn.toString();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue