From b2a9801ed327338941f763642fb094b897e5c53f Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Mon, 26 Mar 2012 10:42:05 +0800 Subject: [PATCH] IDEMPIERE-209 Costing: clean up reversal code. IDEMPIERE-210 Costing: Revert [ 1693997 ] Calculation of cost should happen when transaction complete. --- .../src/org/compiere/acct/Doc_InOut.java | 226 ++++++++++-------- .../src/org/compiere/acct/Doc_Inventory.java | 44 ++-- .../src/org/compiere/acct/Doc_MatchInv.java | 121 ++++++---- .../src/org/compiere/acct/Doc_MatchPO.java | 106 ++++++++ .../src/org/compiere/acct/Doc_Movement.java | 41 +++- .../src/org/compiere/acct/Doc_Production.java | 8 +- .../src/org/compiere/model/MInventory.java | 73 +----- .../src/org/compiere/model/MMatchInv.java | 148 +++--------- .../src/org/compiere/model/MMatchPO.java | 151 ++---------- 9 files changed, 420 insertions(+), 498 deletions(-) diff --git a/org.adempiere.base/src/org/compiere/acct/Doc_InOut.java b/org.adempiere.base/src/org/compiere/acct/Doc_InOut.java index 697d7d432e..358e78ebf6 100644 --- a/org.adempiere.base/src/org/compiere/acct/Doc_InOut.java +++ b/org.adempiere.base/src/org/compiere/acct/Doc_InOut.java @@ -163,23 +163,34 @@ public class Doc_InOut extends Doc { for (int i = 0; i < p_lines.length; i++) { - DocLine line = p_lines[i]; - // MZ Goodwill - // if Shipment CostDetail exist then get Cost from Cost Detail - BigDecimal costs = line.getProductCosts(as, line.getAD_Org_ID(), true, "M_InOutLine_ID=?"); - // end MZ - if (costs == null || costs.signum() == 0) // zero costs OK + DocLine line = p_lines[i]; + BigDecimal costs = null; + if (!isReversal(line)) { - MProduct product = line.getProduct(); - if (product.isStocked()) + // MZ Goodwill + // if Shipment CostDetail exist then get Cost from Cost Detail + costs = line.getProductCosts(as, line.getAD_Org_ID(), true, "M_InOutLine_ID=?"); + + // end MZ + if (costs == null || costs.signum() == 0) // zero costs OK { - p_Error = "No Costs for " + line.getProduct().getName(); - log.log(Level.WARNING, p_Error); - return null; + MProduct product = line.getProduct(); + if (product.isStocked()) + { + p_Error = "No Costs for " + line.getProduct().getName(); + log.log(Level.WARNING, p_Error); + return null; + } + else // ignore service + continue; } - else // ignore service - continue; } + else + { + //temp to avoid NPE + costs = BigDecimal.ZERO; + } + // CoGS DR dr = fact.createLine(line, line.getAccount(ProductCost.ACCTTYPE_P_Cogs, as), @@ -195,8 +206,8 @@ public class Doc_InOut extends Doc dr.setLocationFromBPartner(getC_BPartner_Location_ID(), false); // to Loc dr.setAD_Org_ID(line.getOrder_Org_ID()); // Revenue X-Org dr.setQty(line.getQty().negate()); - if (m_DocStatus.equals(MInOut.DOCSTATUS_Reversed) - && m_Reversal_ID !=0 && line.getReversalLine_ID() != 0) + + if (isReversal(line)) { // Set AmtAcctDr from Original Shipment/Receipt if (!dr.updateReverseLine (MInOut.Table_ID, @@ -220,8 +231,8 @@ public class Doc_InOut extends Doc cr.setM_Locator_ID(line.getM_Locator_ID()); cr.setLocationFromLocator(line.getM_Locator_ID(), true); // from Loc cr.setLocationFromBPartner(getC_BPartner_Location_ID(), false); // to Loc - if (m_DocStatus.equals(MInOut.DOCSTATUS_Reversed) - && m_Reversal_ID !=0 && line.getReversalLine_ID() != 0) + + if (isReversal(line)) { // Set AmtAcctCr from Original Shipment/Receipt if (!cr.updateReverseLine (MInOut.Table_ID, @@ -235,11 +246,15 @@ public class Doc_InOut extends Doc // if (line.getM_Product_ID() != 0) { - MCostDetail.createShipment(as, line.getAD_Org_ID(), + if (!MCostDetail.createShipment(as, line.getAD_Org_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), line.get_ID(), 0, costs, line.getQty(), - line.getDescription(), true, getTrxName()); + line.getDescription(), true, getTrxName())) + { + p_Error = "Failed to create cost detail record"; + return null; + } } } // for all lines updateProductInfo(as.getC_AcctSchema_ID()); // only for SO! @@ -264,22 +279,30 @@ public class Doc_InOut extends Doc for (int i = 0; i < p_lines.length; i++) { DocLine line = p_lines[i]; - // MZ Goodwill - // if Shipment CostDetail exist then get Cost from Cost Detail - BigDecimal costs = line.getProductCosts(as, line.getAD_Org_ID(), true, "M_InOutLine_ID=?"); - // end MZ - - if (costs == null || costs.signum() == 0) // zero costs OK + BigDecimal costs = null; + if (!isReversal(line)) { - MProduct product = line.getProduct(); - if (product.isStocked()) + // MZ Goodwill + // if Shipment CostDetail exist then get Cost from Cost Detail + costs = line.getProductCosts(as, line.getAD_Org_ID(), true, "M_InOutLine_ID=?"); + // end MZ + + if (costs == null || costs.signum() == 0) // zero costs OK { - p_Error = "No Costs for " + line.getProduct().getName(); - log.log(Level.WARNING, p_Error); - return null; + MProduct product = line.getProduct(); + if (product.isStocked()) + { + p_Error = "No Costs for " + line.getProduct().getName(); + log.log(Level.WARNING, p_Error); + return null; + } + else // ignore service + continue; } - else // ignore service - continue; + } + else + { + costs = BigDecimal.ZERO; } // Inventory DR dr = fact.createLine(line, @@ -294,8 +317,7 @@ public class Doc_InOut extends Doc dr.setM_Locator_ID(line.getM_Locator_ID()); dr.setLocationFromLocator(line.getM_Locator_ID(), true); // from Loc dr.setLocationFromBPartner(getC_BPartner_Location_ID(), false); // to Loc - if (m_DocStatus.equals(MInOut.DOCSTATUS_Reversed) - && m_Reversal_ID !=0 && line.getReversalLine_ID() != 0) + if (isReversal(line)) { // Set AmtAcctDr from Original Shipment/Receipt if (!dr.updateReverseLine (MInOut.Table_ID, @@ -309,11 +331,15 @@ public class Doc_InOut extends Doc // if (line.getM_Product_ID() != 0) { - MCostDetail.createShipment(as, line.getAD_Org_ID(), + if (!MCostDetail.createShipment(as, line.getAD_Org_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), line.get_ID(), 0, costs, line.getQty(), - line.getDescription(), true, getTrxName()); + line.getDescription(), true, getTrxName())) + { + p_Error = "Failed to create cost detail record"; + return null; + } } // CoGS CR @@ -331,8 +357,7 @@ public class Doc_InOut extends Doc cr.setLocationFromBPartner(getC_BPartner_Location_ID(), false); // to Loc cr.setAD_Org_ID(line.getOrder_Org_ID()); // Revenue X-Org cr.setQty(line.getQty().negate()); - if (m_DocStatus.equals(MInOut.DOCSTATUS_Reversed) - && m_Reversal_ID !=0 && line.getReversalLine_ID() != 0) + if (isReversal(line)) { // Set AmtAcctCr from Original Shipment/Receipt if (!cr.updateReverseLine (MInOut.Table_ID, @@ -357,48 +382,55 @@ public class Doc_InOut extends Doc DocLine line = p_lines[i]; BigDecimal costs = null; MProduct product = line.getProduct(); - //get costing method for product - String costingMethod = product.getCostingMethod(as); - if (MAcctSchema.COSTINGMETHOD_AveragePO.equals(costingMethod) || - MAcctSchema.COSTINGMETHOD_LastPOPrice.equals(costingMethod) ) + if (!isReversal(line)) { - int C_OrderLine_ID = line.getC_OrderLine_ID(); - // Low - check if c_orderline_id is valid - if (C_OrderLine_ID > 0) + //get costing method for product + String costingMethod = product.getCostingMethod(as); + if (MAcctSchema.COSTINGMETHOD_AveragePO.equals(costingMethod) || + MAcctSchema.COSTINGMETHOD_LastPOPrice.equals(costingMethod) ) { - MOrderLine orderLine = new MOrderLine (getCtx(), C_OrderLine_ID, getTrxName()); - // Elaine 2008/06/26 - C_Currency_ID = orderLine.getC_Currency_ID(); - // - costs = orderLine.getPriceCost(); - if (costs == null || costs.signum() == 0) - { - costs = orderLine.getPriceActual(); - // Goodwill: Correct included Tax - int C_Tax_ID = orderLine.getC_Tax_ID(); - if (orderLine.isTaxIncluded() && C_Tax_ID != 0) - { - MTax tax = MTax.get(getCtx(), C_Tax_ID); - if (!tax.isZeroTax()) + int C_OrderLine_ID = line.getC_OrderLine_ID(); + // Low - check if c_orderline_id is valid + if (C_OrderLine_ID > 0) + { + MOrderLine orderLine = new MOrderLine (getCtx(), C_OrderLine_ID, getTrxName()); + // Elaine 2008/06/26 + C_Currency_ID = orderLine.getC_Currency_ID(); + // + costs = orderLine.getPriceCost(); + if (costs == null || costs.signum() == 0) + { + costs = orderLine.getPriceActual(); + // Goodwill: Correct included Tax + int C_Tax_ID = orderLine.getC_Tax_ID(); + if (orderLine.isTaxIncluded() && C_Tax_ID != 0) { - int stdPrecision = MCurrency.getStdPrecision(getCtx(), C_Currency_ID); - BigDecimal costTax = tax.calculateTax(costs, true, stdPrecision); - log.fine("Costs=" + costs + " - Tax=" + costTax); - costs = costs.subtract(costTax); - } - } // correct included Tax - } - costs = costs.multiply(line.getQty()); - } - else - { - costs = line.getProductCosts(as, line.getAD_Org_ID(), false); // current costs - } - // - } + MTax tax = MTax.get(getCtx(), C_Tax_ID); + if (!tax.isZeroTax()) + { + int stdPrecision = MCurrency.getStdPrecision(getCtx(), C_Currency_ID); + BigDecimal costTax = tax.calculateTax(costs, true, stdPrecision); + log.fine("Costs=" + costs + " - Tax=" + costTax); + costs = costs.subtract(costTax); + } + } // correct included Tax + } + costs = costs.multiply(line.getQty()); + } + else + { + costs = line.getProductCosts(as, line.getAD_Org_ID(), false); // current costs + } + // + } + else + { + costs = line.getProductCosts(as, line.getAD_Org_ID(), false); // current costs + } + } else { - costs = line.getProductCosts(as, line.getAD_Org_ID(), false); // current costs + costs = BigDecimal.ZERO; } if (costs == null || costs.signum() == 0) { @@ -434,7 +466,7 @@ public class Doc_InOut extends Doc dr.setM_Locator_ID(line.getM_Locator_ID()); dr.setLocationFromBPartner(getC_BPartner_Location_ID(), true); // from Loc dr.setLocationFromLocator(line.getM_Locator_ID(), false); // to Loc - if (m_DocStatus.equals(MInOut.DOCSTATUS_Reversed) && m_Reversal_ID !=0 && line.getReversalLine_ID() != 0) + if (isReversal(line)) { // Set AmtAcctDr from Original Shipment/Receipt if (!dr.updateReverseLine (MInOut.Table_ID, @@ -464,7 +496,7 @@ public class Doc_InOut extends Doc cr.setLocationFromBPartner(getC_BPartner_Location_ID(), true); // from Loc cr.setLocationFromLocator(line.getM_Locator_ID(), false); // to Loc cr.setQty(line.getQty().negate()); - if (m_DocStatus.equals(MInOut.DOCSTATUS_Reversed) && m_Reversal_ID !=0 && line.getReversalLine_ID() != 0) + if (isReversal(line)) { // Set AmtAcctCr from Original Shipment/Receipt if (!cr.updateReverseLine (MInOut.Table_ID, @@ -487,34 +519,19 @@ public class Doc_InOut extends Doc DocLine line = p_lines[i]; BigDecimal costs = null; MProduct product = line.getProduct(); - /* - * BF: [ 2048984 ] Purchase Return costing logic - //get costing method for product - String costingMethod = product.getCostingMethod(as); - if (MAcctSchema.COSTINGMETHOD_AveragePO.equals(costingMethod) || - MAcctSchema.COSTINGMETHOD_LastPOPrice.equals(costingMethod) ) + if (!isReversal(line)) { - int C_OrderLine_ID = line.getC_OrderLine_ID(); - MOrderLine orderLine = new MOrderLine (getCtx(), C_OrderLine_ID, getTrxName()); - costs = orderLine.getPriceCost(); + costs = line.getProductCosts(as, line.getAD_Org_ID(), false); // current costs if (costs == null || costs.signum() == 0) - costs = orderLine.getPriceActual(); - costs = costs.multiply(line.getQty()); - // Elaine 2008/06/26 - C_Currency_ID = orderLine.getC_Currency_ID(); - // + { + p_Error = "Resubmit - No Costs for " + product.getName(); + log.log(Level.WARNING, p_Error); + return null; + } } else { - costs = line.getProductCosts(as, line.getAD_Org_ID(), false); // current costs - } - */ - costs = line.getProductCosts(as, line.getAD_Org_ID(), false); // current costs - if (costs == null || costs.signum() == 0) - { - p_Error = "Resubmit - No Costs for " + product.getName(); - log.log(Level.WARNING, p_Error); - return null; + costs = BigDecimal.ZERO; } // NotInvoicedReceipt DR // Elaine 2008/06/26 @@ -535,7 +552,7 @@ public class Doc_InOut extends Doc dr.setLocationFromBPartner(getC_BPartner_Location_ID(), true); // from Loc dr.setLocationFromLocator(line.getM_Locator_ID(), false); // to Loc dr.setQty(line.getQty().negate()); - if (m_DocStatus.equals(MInOut.DOCSTATUS_Reversed) && m_Reversal_ID !=0 && line.getReversalLine_ID() != 0) + if (isReversal(line)) { // Set AmtAcctDr from Original Shipment/Receipt if (!dr.updateReverseLine (MInOut.Table_ID, @@ -565,7 +582,7 @@ public class Doc_InOut extends Doc cr.setM_Locator_ID(line.getM_Locator_ID()); cr.setLocationFromBPartner(getC_BPartner_Location_ID(), true); // from Loc cr.setLocationFromLocator(line.getM_Locator_ID(), false); // to Loc - if (m_DocStatus.equals(MInOut.DOCSTATUS_Reversed) && m_Reversal_ID !=0 && line.getReversalLine_ID() != 0) + if (isReversal(line)) { // Set AmtAcctCr from Original Shipment/Receipt if (!cr.updateReverseLine (MInOut.Table_ID, @@ -588,6 +605,11 @@ public class Doc_InOut extends Doc return facts; } // createFact + private boolean isReversal(DocLine line) { + return m_DocStatus.equals(MInOut.DOCSTATUS_Reversed) + && m_Reversal_ID !=0 && line.getReversalLine_ID() != 0; + } + /** * Update Sales Order Costing Product Info (old). diff --git a/org.adempiere.base/src/org/compiere/acct/Doc_Inventory.java b/org.adempiere.base/src/org/compiere/acct/Doc_Inventory.java index a90baf94f7..1fb0e6f9f0 100644 --- a/org.adempiere.base/src/org/compiere/acct/Doc_Inventory.java +++ b/org.adempiere.base/src/org/compiere/acct/Doc_Inventory.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import org.compiere.model.MAccount; import org.compiere.model.MAcctSchema; +import org.compiere.model.MCostDetail; import org.compiere.model.MInventory; import org.compiere.model.MInventoryLine; import org.compiere.model.ProductCost; @@ -147,14 +148,22 @@ public class Doc_Inventory extends Doc for (int i = 0; i < p_lines.length; i++) { DocLine line = p_lines[i]; - // MZ Goodwill - // if Physical Inventory CostDetail is exist then get Cost from Cost Detail - BigDecimal costs = line.getProductCosts(as, line.getAD_Org_ID(), true, "M_InventoryLine_ID=?"); - // end MZ - if (costs == null || costs.signum() == 0) + BigDecimal costs = null; + if (!isReversal(line)) { - p_Error = "No Costs for " + line.getProduct().getName(); - return null; + // MZ Goodwill + // if Physical Inventory CostDetail is exist then get Cost from Cost Detail + costs = line.getProductCosts(as, line.getAD_Org_ID(), true, "M_InventoryLine_ID=?"); + // end MZ + if (costs == null || costs.signum() == 0) + { + p_Error = "No Costs for " + line.getProduct().getName(); + return null; + } + } + else + { + costs = BigDecimal.ZERO; } // Inventory DR CR dr = fact.createLine(line, @@ -164,7 +173,7 @@ public class Doc_Inventory extends Doc if (dr == null) continue; dr.setM_Locator_ID(line.getM_Locator_ID()); - if (m_DocStatus.equals(MInventory.DOCSTATUS_Reversed) && m_Reversal_ID !=0 && line.getReversalLine_ID() != 0) + if (isReversal(line)) { // Set AmtAcctDr from Original Phys.Inventory if (!dr.updateReverseLine (MInventory.Table_ID, @@ -178,9 +187,7 @@ public class Doc_Inventory extends Doc // InventoryDiff DR CR // or Charge MAccount invDiff = null; - if (m_DocStatus.equals(MInventory.DOCSTATUS_Reversed) - && m_Reversal_ID != 0 - && line.getReversalLine_ID() != 0 + if (isReversal(line) && line.getC_Charge_ID() != 0) { invDiff = line.getChargeAccount(as, costs); } else { @@ -198,7 +205,7 @@ public class Doc_Inventory extends Doc if (line.getC_Charge_ID() != 0) // explicit overwrite for charge cr.setAD_Org_ID(line.getAD_Org_ID()); - if (m_DocStatus.equals(MInventory.DOCSTATUS_Reversed) && m_Reversal_ID !=0 && line.getReversalLine_ID() != 0) + if (isReversal(line)) { // Set AmtAcctCr from Original Phys.Inventory if (!cr.updateReverseLine (MInventory.Table_ID, @@ -211,12 +218,15 @@ public class Doc_Inventory extends Doc } // Cost Detail - /* Source move to MInventory.createCostDetail() - MCostDetail.createInventory(as, line.getAD_Org_ID(), + if (!MCostDetail.createInventory(as, line.getAD_Org_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), line.get_ID(), 0, costs, line.getQty(), - line.getDescription(), getTrxName());*/ + line.getDescription(), getTrxName())) + { + p_Error = "Failed to create cost detail record"; + return null; + } } // ArrayList facts = new ArrayList(); @@ -224,4 +234,8 @@ public class Doc_Inventory extends Doc return facts; } // createFact + private boolean isReversal(DocLine line) { + return m_DocStatus.equals(MInventory.DOCSTATUS_Reversed) && m_Reversal_ID !=0 && line.getReversalLine_ID() != 0; + } + } // Doc_Inventory diff --git a/org.adempiere.base/src/org/compiere/acct/Doc_MatchInv.java b/org.adempiere.base/src/org/compiere/acct/Doc_MatchInv.java index 03171feaed..59c24aff92 100644 --- a/org.adempiere.base/src/org/compiere/acct/Doc_MatchInv.java +++ b/org.adempiere.base/src/org/compiere/acct/Doc_MatchInv.java @@ -24,6 +24,7 @@ import org.compiere.model.MAccount; import org.compiere.model.MAcctSchema; import org.compiere.model.MAcctSchemaElement; import org.compiere.model.MConversionRate; +import org.compiere.model.MCostDetail; import org.compiere.model.MInOut; import org.compiere.model.MInOutLine; import org.compiere.model.MInvoice; @@ -305,55 +306,13 @@ public class Doc_MatchInv extends Doc } log.fine("IPV=" + ipv + "; Balance=" + fact.getSourceBalance()); -// Elaine 2008/6/20 -/* Source move to MInvoice.createMatchInvCostDetail() - // Cost Detail Record - data from Expense/IncClearing (CR) record - // MZ Goodwill - // Create Cost Detail Matched Invoice using Total Amount and Total Qty based on InvoiceLine - MMatchInv[] mInv = MMatchInv.getInvoiceLine(getCtx(), m_invoiceLine.getC_InvoiceLine_ID(), getTrxName()); - BigDecimal tQty = Env.ZERO; - BigDecimal tAmt = Env.ZERO; - for (int i = 0 ; i < mInv.length ; i++) + String error = createMatchInvCostDetail(as); + if (error != null && error.trim().length() > 0) { - if (mInv[i].isPosted() && mInv[i].getM_MatchInv_ID() != get_ID()) - { - tQty = tQty.add(mInv[i].getQty()); - multiplier = mInv[i].getQty() - .divide(m_invoiceLine.getQtyInvoiced(), 12, BigDecimal.ROUND_HALF_UP).abs(); - tAmt = tAmt.add(m_invoiceLine.getLineNetAmt().multiply(multiplier)); - } + p_Error = error; + return null; } - tAmt = tAmt.add(cr.getAcctBalance().negate()); //Invoice Price - - // Different currency - MInvoice invoice = m_invoiceLine.getParent(); - if (as.getC_Currency_ID() != invoice.getC_Currency_ID()) - { - tAmt = MConversionRate.convert(getCtx(), tAmt, - invoice.getC_Currency_ID(), as.getC_Currency_ID(), - invoice.getDateAcct(), invoice.getC_ConversionType_ID(), - invoice.getAD_Client_ID(), invoice.getAD_Org_ID()); - if (tAmt == null) - { - p_Error = "AP Invoice not convertible - " + as.getName(); - return null; - } - } - - // set Qty to negative value when MovementType is Vendor Returns - MInOut receipt = m_receiptLine.getParent(); - if (receipt.getMovementType().equals(MInOut.MOVEMENTTYPE_VendorReturns)) - tQty = tQty.add(getQty().negate()); // Qty is set to negative value - else - tQty = tQty.add(getQty()); - - // Set Total Amount and Total Quantity from Matched Invoice - MCostDetail.createInvoice(as, getAD_Org_ID(), - getM_Product_ID(), matchInv.getM_AttributeSetInstance_ID(), - m_invoiceLine.getC_InvoiceLine_ID(), 0, // No cost element - tAmt, tQty, getDescription(), getTrxName()); - // end MZ -*/ + // Update Costing updateProductInfo(as.getC_AcctSchema_ID(), MAcctSchema.COSTINGMETHOD_StandardCosting.equals(as.getCostingMethod())); @@ -390,6 +349,74 @@ public class Doc_MatchInv extends Doc return false; } + // Elaine 2008/6/20 + private String createMatchInvCostDetail(MAcctSchema as) + { + if (m_invoiceLine != null && m_invoiceLine.get_ID() > 0 + && m_receiptLine != null && m_receiptLine.get_ID() > 0) + { + BigDecimal LineNetAmt = m_invoiceLine.getLineNetAmt(); + BigDecimal multiplier = getQty() + .divide(m_invoiceLine.getQtyInvoiced(), 12, BigDecimal.ROUND_HALF_UP) + .abs(); + if (multiplier.compareTo(Env.ONE) != 0) + LineNetAmt = LineNetAmt.multiply(multiplier); + + // Source from Doc_MatchInv.createFacts(MAcctSchema) + // Cost Detail Record - data from Expense/IncClearing (CR) record + // MZ Goodwill + // Create Cost Detail Matched Invoice using Total Amount and Total Qty based on InvoiceLine + MMatchInv[] mInv = MMatchInv.getInvoiceLine(getCtx(), m_invoiceLine.getC_InvoiceLine_ID(), getTrxName()); + BigDecimal tQty = Env.ZERO; + BigDecimal tAmt = Env.ZERO; + for (int i = 0 ; i < mInv.length ; i++) + { + if (mInv[i].isPosted() && mInv[i].getM_MatchInv_ID() != get_ID()) + { + tQty = tQty.add(mInv[i].getQty()); + multiplier = mInv[i].getQty() + .divide(m_invoiceLine.getQtyInvoiced(), 12, BigDecimal.ROUND_HALF_UP).abs(); + tAmt = tAmt.add(m_invoiceLine.getLineNetAmt().multiply(multiplier)); + } + } + tAmt = tAmt.add(LineNetAmt); //Invoice Price + + // Different currency + MInvoice invoice = m_invoiceLine.getParent(); + if (as.getC_Currency_ID() != invoice.getC_Currency_ID()) + { + tAmt = MConversionRate.convert(getCtx(), tAmt, + invoice.getC_Currency_ID(), as.getC_Currency_ID(), + invoice.getDateAcct(), invoice.getC_ConversionType_ID(), + invoice.getAD_Client_ID(), invoice.getAD_Org_ID()); + if (tAmt == null) + { + return "AP Invoice not convertible - " + as.getName(); + } + } + + // set Qty to negative value when MovementType is Vendor Returns + MInOut receipt = m_receiptLine.getParent(); + if (receipt.getMovementType().equals(MInOut.MOVEMENTTYPE_VendorReturns)) + tQty = tQty.add(getQty().negate()); // Qty is set to negative value + else + tQty = tQty.add(getQty()); + + MMatchInv matchInv = (MMatchInv)getPO(); + // Set Total Amount and Total Quantity from Matched Invoice + if (!MCostDetail.createInvoice(as, getAD_Org_ID(), + getM_Product_ID(), matchInv.getM_AttributeSetInstance_ID(), + m_invoiceLine.getC_InvoiceLine_ID(), 0, // No cost element + tAmt, tQty, getDescription(), getTrxName())) + { + return "Failed to create cost detail record"; + } + // end MZ + } + + return ""; + } + /** * Update Product Info (old). * - Costing (CostStandardCumQty, CostStandardCumAmt, CostAverageCumQty, CostAverageCumAmt) diff --git a/org.adempiere.base/src/org/compiere/acct/Doc_MatchPO.java b/org.adempiere.base/src/org/compiere/acct/Doc_MatchPO.java index 0daf4f959c..c91f9635e2 100644 --- a/org.adempiere.base/src/org/compiere/acct/Doc_MatchPO.java +++ b/org.adempiere.base/src/org/compiere/acct/Doc_MatchPO.java @@ -26,12 +26,15 @@ import org.compiere.model.MAccount; import org.compiere.model.MAcctSchema; import org.compiere.model.MAcctSchemaElement; import org.compiere.model.MConversionRate; +import org.compiere.model.MCostDetail; +import org.compiere.model.MCurrency; import org.compiere.model.MInOut; import org.compiere.model.MInOutLine; import org.compiere.model.MMatchPO; import org.compiere.model.MOrder; import org.compiere.model.MOrderLine; import org.compiere.model.MProduct; +import org.compiere.model.MTax; import org.compiere.model.ProductCost; import org.compiere.model.X_M_InOut; import org.compiere.util.DB; @@ -64,6 +67,7 @@ public class Doc_MatchPO extends Doc // private int m_M_InOutLine_ID = 0; private MInOutLine m_ioLine = null; + @SuppressWarnings("unused") private int m_C_InvoiceLine_ID = 0; private ProductCost m_pc; @@ -167,6 +171,13 @@ public class Doc_MatchPO extends Doc poCost = poCost.setScale(as.getCostingPrecision(), BigDecimal.ROUND_HALF_UP); } + String costingError = createMatchPOCostDetail(as); + if (costingError != null && costingError.trim().length() > 0) + { + p_Error = costingError; + return null; + } + // Calculate PPV for standard costing MProduct product = MProduct.get(getCtx(), getM_Product_ID()); String costingMethod = product.getCostingMethod(as); @@ -305,5 +316,100 @@ public class Doc_MatchPO extends Doc int no = DB.executeUpdate(sql.toString(), getTrxName()); log.fine("M_Product_Costing - Updated=" + no); } // updateProductInfo + + // Elaine 2008/6/20 + private String createMatchPOCostDetail(MAcctSchema as) + { + if (m_ioLine != null && m_ioLine.getM_InOutLine_ID() > 0 && + m_oLine != null && m_oLine.getC_OrderLine_ID() > 0) + { + MMatchPO mMatchPO = (MMatchPO) getPO(); + + // Purchase Order Line + BigDecimal poCost = m_oLine.getPriceCost(); + if (poCost == null || poCost.signum() == 0) + { + poCost = m_oLine.getPriceActual(); + // Goodwill: Correct included Tax + int C_Tax_ID = m_oLine.getC_Tax_ID(); + if (m_oLine.isTaxIncluded() && C_Tax_ID != 0) + { + MTax tax = MTax.get(getCtx(), C_Tax_ID); + if (!tax.isZeroTax()) + { + int stdPrecision = MCurrency.getStdPrecision(getCtx(), m_oLine.getC_Currency_ID()); + BigDecimal costTax = tax.calculateTax(poCost, true, stdPrecision); + log.fine("Costs=" + poCost + " - Tax=" + costTax); + poCost = poCost.subtract(costTax); + } + } // correct included Tax + } + + // Source from Doc_MatchPO.createFacts(MAcctSchema) + MInOut inOut = m_ioLine.getParent(); + boolean isReturnTrx = inOut.getMovementType().equals(X_M_InOut.MOVEMENTTYPE_VendorReturns); + + // Create PO Cost Detail Record first + // MZ Goodwill + // Create Cost Detail Matched PO using Total Amount and Total Qty based on OrderLine + MMatchPO[] mPO = MMatchPO.getOrderLine(getCtx(), m_oLine.getC_OrderLine_ID(), getTrxName()); + BigDecimal tQty = Env.ZERO; + BigDecimal tAmt = Env.ZERO; + for (int i = 0 ; i < mPO.length ; i++) + { + if (mPO[i].getM_AttributeSetInstance_ID() == mMatchPO.getM_AttributeSetInstance_ID() + && mPO[i].getM_MatchPO_ID() != mMatchPO.getM_MatchPO_ID()) + { + BigDecimal qty = (isReturnTrx ? mPO[i].getQty().negate() : mPO[i].getQty()); + tQty = tQty.add(qty); + tAmt = tAmt.add(poCost.multiply(qty)); + } + } + + poCost = poCost.multiply(getQty()); // Delivered so far + tAmt = tAmt.add(isReturnTrx ? poCost.negate() : poCost); + tQty = tQty.add(isReturnTrx ? getQty().negate() : getQty()); + + // Different currency + if (m_oLine.getC_Currency_ID() != as.getC_Currency_ID()) + { + MOrder order = m_oLine.getParent(); + Timestamp dateAcct = order.getDateAcct(); + //get costing method for product + MProduct product = MProduct.get(getCtx(), getM_Product_ID()); + String costingMethod = product.getCostingMethod(as); + if (MAcctSchema.COSTINGMETHOD_AveragePO.equals(costingMethod) || + MAcctSchema.COSTINGMETHOD_LastPOPrice.equals(costingMethod) ) + dateAcct = inOut.getDateAcct(); //Movement Date + // + BigDecimal rate = MConversionRate.getRate( + order.getC_Currency_ID(), as.getC_Currency_ID(), + dateAcct, order.getC_ConversionType_ID(), + m_oLine.getAD_Client_ID(), m_oLine.getAD_Org_ID()); + if (rate == null) + { + return "Purchase Order not convertible - " + as.getName(); + } + poCost = poCost.multiply(rate); + if (poCost.scale() > as.getCostingPrecision()) + poCost = poCost.setScale(as.getCostingPrecision(), BigDecimal.ROUND_HALF_UP); + tAmt = tAmt.multiply(rate); + if (tAmt.scale() > as.getCostingPrecision()) + tAmt = tAmt.setScale(as.getCostingPrecision(), BigDecimal.ROUND_HALF_UP); + } + + // Set Total Amount and Total Quantity from Matched PO + if (!MCostDetail.createOrder(as, m_oLine.getAD_Org_ID(), + getM_Product_ID(), mMatchPO.getM_AttributeSetInstance_ID(), + m_oLine.getC_OrderLine_ID(), 0, // no cost element + tAmt, tQty, // Delivered + m_oLine.getDescription(), getTrxName())) + { + return "SaveError"; + } + // end MZ + } + return ""; + } } // Doc_MatchPO diff --git a/org.adempiere.base/src/org/compiere/acct/Doc_Movement.java b/org.adempiere.base/src/org/compiere/acct/Doc_Movement.java index cedfcd1637..36b31b4279 100644 --- a/org.adempiere.base/src/org/compiere/acct/Doc_Movement.java +++ b/org.adempiere.base/src/org/compiere/acct/Doc_Movement.java @@ -131,10 +131,19 @@ public class Doc_Movement extends Doc for (int i = 0; i < p_lines.length; i++) { DocLine line = p_lines[i]; - // MZ Goodwill - // if Inventory Move CostDetail exist then get Cost from Cost Detail - BigDecimal costs = line.getProductCosts(as, line.getAD_Org_ID(), true, "M_MovementLine_ID=? AND IsSOTrx='N'"); - // end MZ + BigDecimal costs = null; + + if (!isReversal(line)) + { + // MZ Goodwill + // if Inventory Move CostDetail exist then get Cost from Cost Detail + costs = line.getProductCosts(as, line.getAD_Org_ID(), true, "M_MovementLine_ID=? AND IsSOTrx='N'"); + // end MZ + } + else + { + costs = BigDecimal.ZERO; + } // ** Inventory DR CR dr = fact.createLine(line, @@ -144,7 +153,7 @@ public class Doc_Movement extends Doc continue; dr.setM_Locator_ID(line.getM_Locator_ID()); dr.setQty(line.getQty().negate()); // outgoing - if (m_DocStatus.equals(MMovement.DOCSTATUS_Reversed) && m_Reversal_ID !=0 && line.getReversalLine_ID() != 0) + if (isReversal(line)) { // Set AmtAcctDr from Original Movement if (!dr.updateReverseLine (MMovement.Table_ID, @@ -163,7 +172,7 @@ public class Doc_Movement extends Doc continue; cr.setM_Locator_ID(line.getM_LocatorTo_ID()); cr.setQty(line.getQty()); - if (m_DocStatus.equals(MMovement.DOCSTATUS_Reversed) && m_Reversal_ID !=0 && line.getReversalLine_ID() != 0) + if (isReversal(line)) { // Set AmtAcctCr from Original Movement if (!cr.updateReverseLine (MMovement.Table_ID, @@ -186,17 +195,25 @@ public class Doc_Movement extends Doc if (description == null) description = ""; // Cost Detail From - MCostDetail.createMovement(as, dr.getAD_Org_ID(), // locator org + if (!MCostDetail.createMovement(as, dr.getAD_Org_ID(), // locator org line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), line.get_ID(), 0, costs.negate(), line.getQty().negate(), true, - description + "(|->)", getTrxName()); + description + "(|->)", getTrxName())) + { + p_Error = "Failed to create cost detail record"; + return null; + } // Cost Detail To - MCostDetail.createMovement(as, cr.getAD_Org_ID(), // locator org + if (!MCostDetail.createMovement(as, cr.getAD_Org_ID(), // locator org line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), line.get_ID(), 0, costs, line.getQty(), false, - description + "(|<-)", getTrxName()); + description + "(|<-)", getTrxName())) + { + p_Error = "Failed to create cost detail record"; + return null; + } } } @@ -206,4 +223,8 @@ public class Doc_Movement extends Doc return facts; } // createFact + private boolean isReversal(DocLine line) { + return m_DocStatus.equals(MMovement.DOCSTATUS_Reversed) && m_Reversal_ID !=0 && line.getReversalLine_ID() != 0; + } + } // Doc_Movement diff --git a/org.adempiere.base/src/org/compiere/acct/Doc_Production.java b/org.adempiere.base/src/org/compiere/acct/Doc_Production.java index b9a31fda4b..de3e61dac1 100644 --- a/org.adempiere.base/src/org/compiere/acct/Doc_Production.java +++ b/org.adempiere.base/src/org/compiere/acct/Doc_Production.java @@ -228,11 +228,15 @@ public class Doc_Production extends Doc description = ""; if (line.isProductionBOM()) description += "(*)"; - MCostDetail.createProduction(as, line.getAD_Org_ID(), + if (!MCostDetail.createProduction(as, line.getAD_Org_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), line.get_ID(), 0, costs, line.getQty(), - description, getTrxName()); + description, getTrxName())) + { + p_Error = "Failed to create cost detail record"; + return null; + } } // ArrayList facts = new ArrayList(); diff --git a/org.adempiere.base/src/org/compiere/model/MInventory.java b/org.adempiere.base/src/org/compiere/model/MInventory.java index 4553306e98..196927cc3e 100644 --- a/org.adempiere.base/src/org/compiere/model/MInventory.java +++ b/org.adempiere.base/src/org/compiere/model/MInventory.java @@ -473,14 +473,6 @@ public class MInventory extends X_M_Inventory implements DocAction m_processMsg = "Transaction not inserted(2)"; return DocAction.STATUS_Invalid; } - if(QtyMA.signum() != 0) - { - String err = createCostDetail(line, ma.getM_AttributeSetInstance_ID() , QtyMA.negate()); - if (err != null && err.length() > 0) { - m_processMsg = err; - return DocAction.STATUS_Invalid; - } - } qtyDiff = QtyNew; @@ -530,16 +522,7 @@ public class MInventory extends X_M_Inventory implements DocAction { m_processMsg = "Transaction not inserted(2)"; return DocAction.STATUS_Invalid; - } - - if(qtyDiff.signum() != 0) - { - String err = createCostDetail(line, line.getM_AttributeSetInstance_ID(), qtyDiff); - if (err != null && err.length() > 0) { - m_processMsg = err; - return DocAction.STATUS_Invalid; - } - } + } } // Fallback } // stock movement @@ -941,60 +924,6 @@ public class MInventory extends X_M_Inventory implements DocAction return m_reversal; } // isReversal - /** - * Create Cost Detail - * @param line - * @param Qty - * @return an EMPTY String on success otherwise an ERROR message - */ - private String createCostDetail(MInventoryLine line, int M_AttributeSetInstance_ID, BigDecimal qty) - { - // Get Account Schemas to create MCostDetail - MAcctSchema[] acctschemas = MAcctSchema.getClientAcctSchema(getCtx(), getAD_Client_ID()); - for(int asn = 0; asn < acctschemas.length; asn++) - { - MAcctSchema as = acctschemas[asn]; - - if (as.isSkipOrg(getAD_Org_ID()) || as.isSkipOrg(line.getAD_Org_ID())) - { - continue; - } - - BigDecimal costs = Env.ZERO; - if (isReversal()) - { - String sql = "SELECT amt * -1 FROM M_CostDetail WHERE M_InventoryLine_ID=?"; // negate costs - MProduct product = new MProduct(getCtx(), line.getM_Product_ID(), line.get_TrxName()); - String CostingLevel = product.getCostingLevel(as); - if (MAcctSchema.COSTINGLEVEL_Organization.equals(CostingLevel)) - sql = sql + " AND AD_Org_ID=" + getAD_Org_ID(); - else if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(CostingLevel) && M_AttributeSetInstance_ID != 0) - sql = sql + " AND M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID; - costs = DB.getSQLValueBD(line.get_TrxName(), sql, line.getReversalLine_ID()); - } - else - { - ProductCost pc = new ProductCost (getCtx(), - line.getM_Product_ID(), M_AttributeSetInstance_ID, line.get_TrxName()); - pc.setQty(qty); - costs = pc.getProductCosts(as, line.getAD_Org_ID(), as.getCostingMethod(), 0,true); - } - if (costs == null) - { - return "No Costs for " + line.getProduct().getName(); - } - - // Set Total Amount and Total Quantity from Inventory - MCostDetail.createInventory(as, line.getAD_Org_ID(), - line.getM_Product_ID(), M_AttributeSetInstance_ID, - line.getM_InventoryLine_ID(), 0, // no cost element - costs, qty, - line.getDescription(), line.get_TrxName()); - } - - return ""; - } - /** * Document Status is Complete or Closed * @return true if CO, CL or RE diff --git a/org.adempiere.base/src/org/compiere/model/MMatchInv.java b/org.adempiere.base/src/org/compiere/model/MMatchInv.java index 25792ba48d..5953dec070 100644 --- a/org.adempiere.base/src/org/compiere/model/MMatchInv.java +++ b/org.adempiere.base/src/org/compiere/model/MMatchInv.java @@ -136,6 +136,7 @@ public class MMatchInv extends X_M_MatchInv /** Static Logger */ + @SuppressWarnings("unused") private static CLogger s_log = CLogger.getCLogger (MMatchInv.class); @@ -221,29 +222,6 @@ public class MMatchInv extends X_M_MatchInv return true; } // beforeSave - /** - * After Save. - * Set Order Qty Delivered/Invoiced - * @param newRecord new - * @param success success - * @return success - */ - protected boolean afterSave (boolean newRecord, boolean success) - { - if (newRecord && success) - { - // Elaine 2008/6/20 - String err = createMatchInvCostDetail(); - if(err != null && err.length() > 0) - { - s_log.warning(err); - return false; - } - } - // - return success; - } // afterSave - /** * Get the later Date Acct from invoice or shipment * @return date or null @@ -329,81 +307,6 @@ public class MMatchInv extends X_M_MatchInv return success; } // afterDelete - - // Elaine 2008/6/20 - private String createMatchInvCostDetail() - { - MInvoiceLine invoiceLine = new MInvoiceLine (getCtx(), getC_InvoiceLine_ID(), get_TrxName()); - - // Get Account Schemas to create MCostDetail - MAcctSchema[] acctschemas = MAcctSchema.getClientAcctSchema(getCtx(), getAD_Client_ID()); - for(int asn = 0; asn < acctschemas.length; asn++) - { - MAcctSchema as = acctschemas[asn]; - - if (as.isSkipOrg(getAD_Org_ID())) - { - continue; - } - - BigDecimal LineNetAmt = invoiceLine.getLineNetAmt(); - BigDecimal multiplier = getQty() - .divide(invoiceLine.getQtyInvoiced(), 12, BigDecimal.ROUND_HALF_UP) - .abs(); - if (multiplier.compareTo(Env.ONE) != 0) - LineNetAmt = LineNetAmt.multiply(multiplier); - - // Source from Doc_MatchInv.createFacts(MAcctSchema) - // Cost Detail Record - data from Expense/IncClearing (CR) record - // MZ Goodwill - // Create Cost Detail Matched Invoice using Total Amount and Total Qty based on InvoiceLine - MMatchInv[] mInv = MMatchInv.getInvoiceLine(getCtx(), invoiceLine.getC_InvoiceLine_ID(), get_TrxName()); - BigDecimal tQty = Env.ZERO; - BigDecimal tAmt = Env.ZERO; - for (int i = 0 ; i < mInv.length ; i++) - { - if (mInv[i].isPosted() && mInv[i].getM_MatchInv_ID() != get_ID()) - { - tQty = tQty.add(mInv[i].getQty()); - multiplier = mInv[i].getQty() - .divide(invoiceLine.getQtyInvoiced(), 12, BigDecimal.ROUND_HALF_UP).abs(); - tAmt = tAmt.add(invoiceLine.getLineNetAmt().multiply(multiplier)); - } - } - tAmt = tAmt.add(LineNetAmt); //Invoice Price - - // Different currency - MInvoice invoice = invoiceLine.getParent(); - if (as.getC_Currency_ID() != invoice.getC_Currency_ID()) - { - tAmt = MConversionRate.convert(getCtx(), tAmt, - invoice.getC_Currency_ID(), as.getC_Currency_ID(), - invoice.getDateAcct(), invoice.getC_ConversionType_ID(), - invoice.getAD_Client_ID(), invoice.getAD_Org_ID()); - if (tAmt == null) - { - return "AP Invoice not convertible - " + as.getName(); - } - } - - // set Qty to negative value when MovementType is Vendor Returns - MInOutLine receiptLine = new MInOutLine (getCtx(),getM_InOutLine_ID(), get_TrxName()); - MInOut receipt = receiptLine.getParent(); - if (receipt.getMovementType().equals(MInOut.MOVEMENTTYPE_VendorReturns)) - tQty = tQty.add(getQty().negate()); // Qty is set to negative value - else - tQty = tQty.add(getQty()); - - // Set Total Amount and Total Quantity from Matched Invoice - MCostDetail.createInvoice(as, getAD_Org_ID(), - getM_Product_ID(), getM_AttributeSetInstance_ID(), - invoiceLine.getC_InvoiceLine_ID(), 0, // No cost element - tAmt, tQty, getDescription(), get_TrxName()); - // end MZ - } - - return ""; - } // //AZ Goodwill private String deleteMatchInvCostDetail() @@ -424,29 +327,36 @@ public class MMatchInv extends X_M_MatchInv getC_InvoiceLine_ID(), getM_AttributeSetInstance_ID(), as.getC_AcctSchema_ID(), get_TrxName()); if (cd != null) { - MInOut receipt = (new MInOutLine(getCtx(),getM_InOutLine_ID(),get_TrxName())).getParent(); - BigDecimal qty = getQty(); - if (receipt.getMovementType().equals(MInOut.MOVEMENTTYPE_VendorReturns)) - qty = getQty().negate(); - // - BigDecimal price = null; - if (cd.getQty().compareTo(Env.ZERO) == 0) // avoid division by zero - price = Env.ZERO; - else - price = cd.getAmt().divide(cd.getQty(),12,BigDecimal.ROUND_HALF_UP); - cd.setDeltaAmt(price.multiply(qty.negate())); - cd.setDeltaQty(qty.negate()); - cd.setProcessed(false); - // - cd.setAmt(price.multiply(cd.getQty().subtract(qty))); - cd.setQty(cd.getQty().subtract(qty)); - if (!cd.isProcessed()) - { - cd.process(); - } - if (cd.getQty().compareTo(Env.ZERO) == 0) + if (cd.isProcessed()) { + MInOut receipt = (new MInOutLine(getCtx(),getM_InOutLine_ID(),get_TrxName())).getParent(); + BigDecimal qty = getQty(); + if (receipt.getMovementType().equals(MInOut.MOVEMENTTYPE_VendorReturns)) + qty = getQty().negate(); + // + BigDecimal price = null; + if (cd.getQty().compareTo(Env.ZERO) == 0) // avoid division by zero + price = Env.ZERO; + else + price = cd.getAmt().divide(cd.getQty(),12,BigDecimal.ROUND_HALF_UP); + cd.setDeltaAmt(price.multiply(qty.negate())); + cd.setDeltaQty(qty.negate()); cd.setProcessed(false); + // + cd.setAmt(price.multiply(cd.getQty().subtract(qty))); + cd.setQty(cd.getQty().subtract(qty)); + if (!cd.isProcessed()) + { + cd.process(); + } + if (cd.getQty().compareTo(Env.ZERO) == 0) + { + cd.setProcessed(false); + cd.delete(true); + } + } + else + { cd.delete(true); } } diff --git a/org.adempiere.base/src/org/compiere/model/MMatchPO.java b/org.adempiere.base/src/org/compiere/model/MMatchPO.java index 2f73b62204..a7365f3c69 100644 --- a/org.adempiere.base/src/org/compiere/model/MMatchPO.java +++ b/org.adempiere.base/src/org/compiere/model/MMatchPO.java @@ -619,17 +619,6 @@ public class MMatchPO extends X_M_MatchPO } } - if (newRecord || m_isInOutLineChange) - { - // Elaine 2008/6/20 - String err = createMatchPOCostDetail(); - if(err != null && err.length() > 0) - { - s_log.warning(err); - return false; - } - } - return true; } // beforeSave @@ -853,113 +842,6 @@ public class MMatchPO extends X_M_MatchPO s_log.info("Success #" + success + " - Error #" + errors); } // consolidate - // Elaine 2008/6/20 - private String createMatchPOCostDetail() - { - if (getM_InOutLine_ID() != 0) - { - MOrderLine oLine = getOrderLine(); - - // Get Account Schemas to create MCostDetail - MAcctSchema[] acctschemas = MAcctSchema.getClientAcctSchema(getCtx(), getAD_Client_ID()); - for(int asn = 0; asn < acctschemas.length; asn++) - { - MAcctSchema as = acctschemas[asn]; - - if (as.isSkipOrg(getAD_Org_ID())) - { - continue; - } - - // Purchase Order Line - BigDecimal poCost = oLine.getPriceCost(); - if (poCost == null || poCost.signum() == 0) - { - poCost = oLine.getPriceActual(); - // Goodwill: Correct included Tax - int C_Tax_ID = oLine.getC_Tax_ID(); - if (oLine.isTaxIncluded() && C_Tax_ID != 0) - { - MTax tax = MTax.get(getCtx(), C_Tax_ID); - if (!tax.isZeroTax()) - { - int stdPrecision = MCurrency.getStdPrecision(getCtx(), oLine.getC_Currency_ID()); - BigDecimal costTax = tax.calculateTax(poCost, true, stdPrecision); - log.fine("Costs=" + poCost + " - Tax=" + costTax); - poCost = poCost.subtract(costTax); - } - } // correct included Tax - } - - // Source from Doc_MatchPO.createFacts(MAcctSchema) - MInOutLine receiptLine = new MInOutLine (getCtx(), getM_InOutLine_ID(), get_TrxName()); - MInOut inOut = receiptLine.getParent(); - boolean isReturnTrx = inOut.getMovementType().equals(X_M_InOut.MOVEMENTTYPE_VendorReturns); - - // Create PO Cost Detail Record first - // MZ Goodwill - // Create Cost Detail Matched PO using Total Amount and Total Qty based on OrderLine - MMatchPO[] mPO = MMatchPO.getOrderLine(getCtx(), oLine.getC_OrderLine_ID(), get_TrxName()); - BigDecimal tQty = Env.ZERO; - BigDecimal tAmt = Env.ZERO; - for (int i = 0 ; i < mPO.length ; i++) - { - if (mPO[i].getM_AttributeSetInstance_ID() == getM_AttributeSetInstance_ID() - && mPO[i].getM_MatchPO_ID() != get_ID()) - { - BigDecimal qty = (isReturnTrx ? mPO[i].getQty().negate() : mPO[i].getQty()); - tQty = tQty.add(qty); - tAmt = tAmt.add(poCost.multiply(qty)); - } - } - - poCost = poCost.multiply(getQty()); // Delivered so far - tAmt = tAmt.add(isReturnTrx ? poCost.negate() : poCost); - tQty = tQty.add(isReturnTrx ? getQty().negate() : getQty()); - - // Different currency - if (oLine.getC_Currency_ID() != as.getC_Currency_ID()) - { - MOrder order = oLine.getParent(); - Timestamp dateAcct = order.getDateAcct(); - //get costing method for product - MProduct product = MProduct.get(getCtx(), getM_Product_ID()); - String costingMethod = product.getCostingMethod(as); - if (MAcctSchema.COSTINGMETHOD_AveragePO.equals(costingMethod) || - MAcctSchema.COSTINGMETHOD_LastPOPrice.equals(costingMethod) ) - dateAcct = inOut.getDateAcct(); //Movement Date - // - BigDecimal rate = MConversionRate.getRate( - order.getC_Currency_ID(), as.getC_Currency_ID(), - dateAcct, order.getC_ConversionType_ID(), - oLine.getAD_Client_ID(), oLine.getAD_Org_ID()); - if (rate == null) - { - return "Purchase Order not convertible - " + as.getName(); - } - poCost = poCost.multiply(rate); - if (poCost.scale() > as.getCostingPrecision()) - poCost = poCost.setScale(as.getCostingPrecision(), BigDecimal.ROUND_HALF_UP); - tAmt = tAmt.multiply(rate); - if (tAmt.scale() > as.getCostingPrecision()) - tAmt = tAmt.setScale(as.getCostingPrecision(), BigDecimal.ROUND_HALF_UP); - } - - // Set Total Amount and Total Quantity from Matched PO - if (!MCostDetail.createOrder(as, oLine.getAD_Org_ID(), - getM_Product_ID(), getM_AttributeSetInstance_ID(), - oLine.getC_OrderLine_ID(), 0, // no cost element - tAmt, tQty, // Delivered - oLine.getDescription(), get_TrxName())) - { - return "SaveError"; - } - // end MZ - } - } - return ""; - } - //AZ Goodwill private String deleteMatchPOCostDetail() { @@ -979,24 +861,31 @@ public class MMatchPO extends X_M_MatchPO getC_OrderLine_ID(), getM_AttributeSetInstance_ID(), as.getC_AcctSchema_ID(), get_TrxName()); if (cd != null) { - if (cd.getQty().compareTo(Env.ZERO) > 0) + if (cd.isProcessed()) { - BigDecimal price = cd.getAmt().divide(cd.getQty(),12,BigDecimal.ROUND_HALF_UP); - cd.setDeltaAmt(price.multiply(getQty().negate())); - cd.setDeltaQty(getQty().negate()); - cd.setProcessed(false); - // - cd.setAmt(price.multiply(cd.getQty().subtract(getQty()))); - cd.setQty(cd.getQty().subtract(getQty())); - if (!cd.isProcessed()) + if (cd.getQty().compareTo(Env.ZERO) > 0) { - cd.process(); + BigDecimal price = cd.getAmt().divide(cd.getQty(),12,BigDecimal.ROUND_HALF_UP); + cd.setDeltaAmt(price.multiply(getQty().negate())); + cd.setDeltaQty(getQty().negate()); + cd.setProcessed(false); + // + cd.setAmt(price.multiply(cd.getQty().subtract(getQty()))); + cd.setQty(cd.getQty().subtract(getQty())); + if (!cd.isProcessed()) + { + cd.process(); + } + } + //after process clean-up + if (cd.getQty().compareTo(Env.ZERO) == 0) + { + cd.setProcessed(false); + cd.delete(true); } } - //after process clean-up - if (cd.getQty().compareTo(Env.ZERO) == 0) + else { - cd.setProcessed(false); cd.delete(true); } }