IDEMPIERE-3040 Invoice Price Variations for Average PO costing method (#2428)

* IDEMPIERE-3040 Invoice Price Variations for Average PO costing method

Co-authored-by: dpansheriya <deepakpansheriya@gmail.com>
This commit is contained in:
hengsin 2024-08-27 10:07:42 +08:00 committed by Carlos Ruiz
parent f61bda9a14
commit 9f14c96134
18 changed files with 5372 additions and 945 deletions

View File

@ -195,6 +195,24 @@ public class Doc_AllocationHdr extends Doc
invGainLossFactLines = new ArrayList<FactLine>(); invGainLossFactLines = new ArrayList<FactLine>();
payGainLossFactLines = new ArrayList<FactLine>(); payGainLossFactLines = new ArrayList<FactLine>();
// Do not create fact lines for reversal of invoice
if (p_lines.length == 2)
{
DocLine_Allocation line1 = (DocLine_Allocation)p_lines[0];
DocLine_Allocation line2 = (DocLine_Allocation)p_lines[1];
if (line1.getC_Payment_ID() == 0 && line1.getC_Order_ID() == 0 && line1.getC_CashLine_ID() == 0 && line1.getC_Invoice_ID() > 0
&& line2.getC_Payment_ID() == 0 && line2.getC_Order_ID() == 0 && line2.getC_CashLine_ID() == 0 && line2.getC_Invoice_ID() > 0)
{
MInvoice invoice1 = new MInvoice(Env.getCtx(), line1.getC_Invoice_ID(), getTrxName());
MInvoice invoice2 = new MInvoice(Env.getCtx(), line2.getC_Invoice_ID(), getTrxName());
if (invoice1.getGrandTotal().equals(invoice2.getGrandTotal().negate())
&& invoice2.getReversal_ID() == invoice1.getC_Invoice_ID())
{
return m_facts;
}
}
}
// create Fact Header // create Fact Header
Fact fact = new Fact(this, as, Fact.POST_Actual); Fact fact = new Fact(this, as, Fact.POST_Actual);
Fact factForRGL = new Fact(this, as, Fact.POST_Actual); // dummy fact (not posted) to calculate Realized Gain & Loss Fact factForRGL = new Fact(this, as, Fact.POST_Actual); // dummy fact (not posted) to calculate Realized Gain & Loss

View File

@ -25,6 +25,7 @@ import java.sql.Savepoint;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
@ -34,14 +35,18 @@ import org.compiere.model.MAccount;
import org.compiere.model.MAcctSchema; import org.compiere.model.MAcctSchema;
import org.compiere.model.MClientInfo; import org.compiere.model.MClientInfo;
import org.compiere.model.MConversionRate; import org.compiere.model.MConversionRate;
import org.compiere.model.MCost;
import org.compiere.model.MCostDetail; import org.compiere.model.MCostDetail;
import org.compiere.model.MCostElement;
import org.compiere.model.MCurrency; import org.compiere.model.MCurrency;
import org.compiere.model.MFactAcct;
import org.compiere.model.MInvoice; import org.compiere.model.MInvoice;
import org.compiere.model.MInvoiceLine; import org.compiere.model.MInvoiceLine;
import org.compiere.model.MLandedCostAllocation; import org.compiere.model.MLandedCostAllocation;
import org.compiere.model.MOrderLandedCostAllocation; import org.compiere.model.MOrderLandedCostAllocation;
import org.compiere.model.MTax; import org.compiere.model.MTax;
import org.compiere.model.ProductCost; import org.compiere.model.ProductCost;
import org.compiere.model.Query;
import org.compiere.model.X_M_Cost; import org.compiere.model.X_M_Cost;
import org.compiere.util.DB; import org.compiere.util.DB;
import org.compiere.util.Env; import org.compiere.util.Env;
@ -588,6 +593,12 @@ public class Doc_Invoice extends Doc
// ** API // ** API
else if (getDocumentType().equals(DOCTYPE_APInvoice)) else if (getDocumentType().equals(DOCTYPE_APInvoice))
{ {
MInvoice invoice = (MInvoice)getPO();
MInvoice originalInvoice = null;
if (invoice.getReversal_ID() > 0 && invoice.getReversal_ID() < invoice.getC_Invoice_ID())
{
originalInvoice = new MInvoice(Env.getCtx(), invoice.getReversal_ID(), invoice.get_TrxName());
}
BigDecimal grossAmt = getAmount(Doc.AMTTYPE_Gross); BigDecimal grossAmt = getAmount(Doc.AMTTYPE_Gross);
BigDecimal serviceAmt = Env.ZERO; BigDecimal serviceAmt = Env.ZERO;
@ -601,6 +612,10 @@ public class Doc_Invoice extends Doc
getC_Currency_ID(), m_taxes[i].getAmount(), null); getC_Currency_ID(), m_taxes[i].getAmount(), null);
if (tl != null) if (tl != null)
tl.setC_Tax_ID(m_taxes[i].getC_Tax_ID()); tl.setC_Tax_ID(m_taxes[i].getC_Tax_ID());
if (tl != null && invoice.getReversal_ID() > 0 && invoice.getReversal_ID() < invoice.getC_Invoice_ID())
{
tl.updateReverseLine(MInvoice.Table_ID, invoice.getReversal_ID(), 0, BigDecimal.ONE);
}
} }
// Expense DR // Expense DR
for (int i = 0; i < p_lines.length; i++) for (int i = 0; i < p_lines.length; i++)
@ -620,6 +635,17 @@ public class Doc_Invoice extends Doc
else else
desc += " 100%"; desc += " 100%";
fl.setDescription(desc); fl.setDescription(desc);
if (invoice.getReversal_ID() > 0 && invoice.getReversal_ID() < invoice.getC_Invoice_ID())
{
int lineId = 0;
if (originalInvoice != null)
{
MInvoiceLine[] lines = originalInvoice.getLines();
if (lines.length > i)
lineId = lines[i].getC_InvoiceLine_ID();
}
fl.updateReverseLine(MInvoice.Table_ID, invoice.getReversal_ID(), lineId, BigDecimal.ONE);
}
} }
if (!landedCost) if (!landedCost)
{ {
@ -636,12 +662,34 @@ public class Doc_Invoice extends Doc
amt = amt.add(discount); amt = amt.add(discount);
dAmt = discount; dAmt = discount;
MAccount tradeDiscountReceived = line.getAccount(ProductCost.ACCTTYPE_P_TDiscountRec, as); MAccount tradeDiscountReceived = line.getAccount(ProductCost.ACCTTYPE_P_TDiscountRec, as);
fact.createLine (line, tradeDiscountReceived, FactLine fl = fact.createLine (line, tradeDiscountReceived,
getC_Currency_ID(), null, dAmt); getC_Currency_ID(), null, dAmt);
if (fl != null && invoice.getReversal_ID() > 0 && invoice.getReversal_ID() < invoice.getC_Invoice_ID())
{
int lineId = 0;
if (originalInvoice != null)
{
MInvoiceLine[] lines = originalInvoice.getLines();
if (lines.length > i)
lineId = lines[i].getC_InvoiceLine_ID();
}
fl.updateReverseLine(MInvoice.Table_ID, invoice.getReversal_ID(), lineId, BigDecimal.ONE);
} }
} }
fact.createLine (line, expense, }
FactLine fl = fact.createLine (line, expense,
getC_Currency_ID(), amt, null); getC_Currency_ID(), amt, null);
if (fl != null && invoice.getReversal_ID() > 0 && invoice.getReversal_ID() < invoice.getC_Invoice_ID())
{
int lineId = 0;
if (originalInvoice != null)
{
MInvoiceLine[] lines = originalInvoice.getLines();
if (lines.length > i)
lineId = lines[i].getC_InvoiceLine_ID();
}
fl.updateReverseLine(MInvoice.Table_ID, invoice.getReversal_ID(), lineId, BigDecimal.ONE);
}
if (!line.isItem()) if (!line.isItem())
{ {
grossAmt = grossAmt.subtract(amt); grossAmt = grossAmt.subtract(amt);
@ -672,13 +720,23 @@ public class Doc_Invoice extends Doc
serviceAmt = getAmount(Doc.AMTTYPE_Gross); serviceAmt = getAmount(Doc.AMTTYPE_Gross);
grossAmt = Env.ZERO; grossAmt = Env.ZERO;
} }
if (grossAmt.signum() != 0) FactLine fl = null;
fact.createLine(null, MAccount.get(getCtx(), payables_ID), if (grossAmt.signum() > 0)
fl = fact.createLine(null, MAccount.get(getCtx(), payables_ID),
getC_Currency_ID(), null, grossAmt); getC_Currency_ID(), null, grossAmt);
if (serviceAmt.signum() != 0) else if (grossAmt.signum() < 0)
fact.createLine(null, MAccount.get(getCtx(), payablesServices_ID), fl = fact.createLine(null, MAccount.get(getCtx(), payables_ID),
getC_Currency_ID(), grossAmt.negate(), null);
if (serviceAmt.signum() > 0)
fl = fact.createLine(null, MAccount.get(getCtx(), payablesServices_ID),
getC_Currency_ID(), null, serviceAmt); getC_Currency_ID(), null, serviceAmt);
else if (serviceAmt.signum() < 0)
fl = fact.createLine(null, MAccount.get(getCtx(), payablesServices_ID),
getC_Currency_ID(), serviceAmt.negate(), null);
if (fl != null && invoice.getReversal_ID() > 0 && invoice.getReversal_ID() < invoice.getC_Invoice_ID())
{
fl.updateReverseLine(MInvoice.Table_ID, invoice.getReversal_ID(), 0, BigDecimal.ONE);
}
// Set Locations // Set Locations
FactLine[] fLines = fact.getLines(); FactLine[] fLines = fact.getLines();
for (int i = 0; i < fLines.length; i++) for (int i = 0; i < fLines.length; i++)
@ -934,7 +992,8 @@ public class Doc_Invoice extends Doc
for (int i = 0; i < lcas.length; i++) for (int i = 0; i < lcas.length; i++)
totalBase += lcas[i].getBase().doubleValue(); totalBase += lcas[i].getBase().doubleValue();
Map<String, BigDecimal> costDetailAmtMap = new HashMap<String, BigDecimal>(); Map<String, BigDecimal> costDetailAmtMap = new HashMap<>();
Map<String, BigDecimal> mcostQtyMap = new HashMap<>();
// Create New // Create New
MInvoiceLine il = new MInvoiceLine (getCtx(), C_InvoiceLine_ID, getTrxName()); MInvoiceLine il = new MInvoiceLine (getCtx(), C_InvoiceLine_ID, getTrxName());
@ -963,9 +1022,33 @@ public class Doc_Invoice extends Doc
{ {
BigDecimal allocationAmt = lca.getAmt(); BigDecimal allocationAmt = lca.getAmt();
boolean reversal = false;
if (allocationAmt.signum() < 0) //reversal
{
allocationAmt = allocationAmt.negate();
reversal = true;
}
BigDecimal estimatedAmt = BigDecimal.ZERO; BigDecimal estimatedAmt = BigDecimal.ZERO;
int oCurrencyId = 0; BigDecimal costAdjustmentAmt = BigDecimal.ZERO;
boolean usesSchemaCurrency = false; boolean usesSchemaCurrency = false;
MInvoiceLine reversalLine = null;
if (reversal)
{
MInvoice invoice = (MInvoice)getPO();
MInvoice reversalInvoice = new MInvoice(getCtx(), invoice.getReversal_ID(), getTrxName());
MInvoiceLine[] lines = invoice.getLines();
MInvoiceLine[] reversalLines = reversalInvoice.getLines();
for(int j = 0; j < lines.length; j++) {
if (lines[j].get_ID() == il.get_ID()) {
reversalLine = reversalLines[j];
break;
}
}
}
else
{
int oCurrencyId = 0;
Timestamp oDateAcct = getDateAcct(); Timestamp oDateAcct = getDateAcct();
if (lca.getM_InOutLine_ID() > 0) if (lca.getM_InOutLine_ID() > 0)
{ {
@ -995,7 +1078,7 @@ public class Doc_Invoice extends Doc
{ {
estimatedAmt = estimatedAmt.setScale(as.getCostingPrecision(), RoundingMode.HALF_UP); estimatedAmt = estimatedAmt.setScale(as.getCostingPrecision(), RoundingMode.HALF_UP);
} }
BigDecimal costAdjustmentAmt = allocationAmt; costAdjustmentAmt = allocationAmt;
if (estimatedAmt.signum() > 0) if (estimatedAmt.signum() > 0)
{ {
//get other allocation amt //get other allocation amt
@ -1008,11 +1091,6 @@ public class Doc_Invoice extends Doc
if (otherAmt != null) if (otherAmt != null)
{ {
estimatedAmt = estimatedAmt.subtract(otherAmt); estimatedAmt = estimatedAmt.subtract(otherAmt);
if (allocationAmt.signum() < 0)
{
//add back since the sum above would include the original trx
estimatedAmt = estimatedAmt.add(allocationAmt.negate());
}
} }
//added for IDEMPIERE-3014 //added for IDEMPIERE-3014
//convert to accounting schema currency //convert to accounting schema currency
@ -1033,24 +1111,69 @@ public class Doc_Invoice extends Doc
if (estimatedAmt.signum() > 0) if (estimatedAmt.signum() > 0)
{ {
if (allocationAmt.signum() > 0)
costAdjustmentAmt = allocationAmt.subtract(estimatedAmt); costAdjustmentAmt = allocationAmt.subtract(estimatedAmt);
else if (allocationAmt.signum() < 0)
costAdjustmentAmt = allocationAmt.add(estimatedAmt);
} }
} }
if (!dr) if (!dr)
costAdjustmentAmt = costAdjustmentAmt.negate(); costAdjustmentAmt = costAdjustmentAmt.negate();
}
boolean zeroQty = false; BigDecimal amtAsset = Env.ZERO;
if (costAdjustmentAmt.signum() != 0) BigDecimal amtVariance = Env.ZERO;
BigDecimal costDetailQty = lca.getQty();
if (costAdjustmentAmt.signum() != 0 && !reversal)
{ {
Trx trx = Trx.get(getTrxName(), false); Trx trx = Trx.get(getTrxName(), false);
Savepoint savepoint = null; Savepoint savepoint = null;
try { try {
savepoint = trx.setSavepoint(null); savepoint = trx.setSavepoint(null);
BigDecimal costDetailAmt = costAdjustmentAmt;
amtVariance = Env.ZERO;
amtAsset = costAdjustmentAmt;
if(X_M_Cost.COSTINGMETHOD_AveragePO.equals(costingMethod))
{
int AD_Org_ID = lca.getAD_Org_ID();
int M_AttributeSetInstance_ID = lca.getM_AttributeSetInstance_ID();
if (MAcctSchema.COSTINGLEVEL_Client.equals(as.getCostingLevel()))
{
AD_Org_ID = 0;
M_AttributeSetInstance_ID = 0;
}
else if (MAcctSchema.COSTINGLEVEL_Organization.equals(as.getCostingLevel()))
M_AttributeSetInstance_ID = 0;
else if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(as.getCostingLevel()))
AD_Org_ID = 0;
MCostElement ce = MCostElement.getMaterialCostElement(getCtx(), as.getCostingMethod(),
AD_Org_ID);
MCost c = MCost.get(getCtx(), getAD_Client_ID(), AD_Org_ID, lca.getM_Product_ID(),
as.getM_CostType_ID(), as.getC_AcctSchema_ID(), ce.getM_CostElement_ID(),
M_AttributeSetInstance_ID, getTrxName());
if (c != null)
{
BigDecimal mcostQty = c.getCurrentQty();
if (mcostQtyMap.containsKey(c.get_UUID())) {
mcostQty = mcostQty.subtract(mcostQtyMap.get(c.get_UUID()));
if (mcostQty.signum() < 0)
mcostQty = new BigDecimal("0.00");
}
if (mcostQty.compareTo(lca.getQty()) < 0) {
amtAsset = mcostQty.multiply(costAdjustmentAmt.divide(lca.getQty(), as.getCostingPrecision(), RoundingMode.HALF_UP));
amtVariance = costAdjustmentAmt.subtract(amtAsset);
costDetailQty = mcostQty;
}
if (mcostQtyMap.containsKey(c.get_UUID())) {
mcostQtyMap.put(c.get_UUID(), mcostQtyMap.get(c.get_UUID()).add(costDetailQty));
} else {
mcostQtyMap.put(c.get_UUID(), costDetailQty);
}
}
}
BigDecimal costDetailAmt = amtAsset;
//convert to accounting schema currency //convert to accounting schema currency
if (getC_Currency_ID() != as.getC_Currency_ID()) if (getC_Currency_ID() != as.getC_Currency_ID())
costDetailAmt = MConversionRate.convert(getCtx(), costDetailAmt, costDetailAmt = MConversionRate.convert(getCtx(), costDetailAmt,
@ -1066,18 +1189,20 @@ public class Doc_Invoice extends Doc
costDetailAmt = costDetailAmt.add(prevAmt); costDetailAmt = costDetailAmt.add(prevAmt);
} }
costDetailAmtMap.put(key, costDetailAmt); costDetailAmtMap.put(key, costDetailAmt);
if (!MCostDetail.createInvoice(as, lca.getAD_Org_ID(), if (costDetailAmt.signum() != 0 &&
!MCostDetail.createInvoice(as, lca.getAD_Org_ID(),
lca.getM_Product_ID(), lca.getM_AttributeSetInstance_ID(), lca.getM_Product_ID(), lca.getM_AttributeSetInstance_ID(),
C_InvoiceLine_ID, lca.getM_CostElement_ID(), C_InvoiceLine_ID, lca.getM_CostElement_ID(),
costDetailAmt, lca.getQty(), costDetailAmt, costDetailQty,
desc, getTrxName())) { desc, getTrxName())) {
throw new RuntimeException("Failed to create cost detail record."); throw new RuntimeException("Failed to create cost detail record.");
} }
} catch (SQLException e) { } catch (SQLException e) {
throw new RuntimeException(e.getLocalizedMessage(), e); throw new RuntimeException(e.getLocalizedMessage(), e);
} catch (AverageCostingZeroQtyException e) { } catch (AverageCostingZeroQtyException e) {
zeroQty = true;
try { try {
amtAsset = BigDecimal.ZERO;
amtVariance = costAdjustmentAmt;
trx.rollback(savepoint); trx.rollback(savepoint);
savepoint = null; savepoint = null;
} catch (SQLException e1) { } catch (SQLException e1) {
@ -1090,16 +1215,113 @@ public class Doc_Invoice extends Doc
} catch (SQLException e) {} } catch (SQLException e) {}
} }
} }
} } else if (reversal) {
costDetailQty = BigDecimal.ZERO;
int AD_Org_ID = lca.getAD_Org_ID();
int M_AttributeSetInstance_ID = lca.getM_AttributeSetInstance_ID();
boolean reversal = false; if (MAcctSchema.COSTINGLEVEL_Client.equals(as.getCostingLevel()))
if (allocationAmt.signum() < 0) //reversal
{ {
allocationAmt = allocationAmt.negate(); AD_Org_ID = 0;
reversal = true; M_AttributeSetInstance_ID = 0;
}
else if (MAcctSchema.COSTINGLEVEL_Organization.equals(as.getCostingLevel()))
M_AttributeSetInstance_ID = 0;
else if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(as.getCostingLevel()))
AD_Org_ID = 0;
String key = lca.getM_Product_ID()+"_"+M_AttributeSetInstance_ID;
if (!costDetailAmtMap.containsKey(key)) {
costDetailAmtMap.put(key, BigDecimal.ZERO);
amtAsset = BigDecimal.ZERO;
amtVariance = BigDecimal.ZERO;
MAccount varianceAccount = pc.getAccount(ProductCost.ACCTTYPE_P_AverageCostVariance, as);
MAccount assetAccount = pc.getAccount(ProductCost.ACCTTYPE_P_Asset, as);
Query query = MFactAcct.createRecordIdQuery(MInvoice.Table_ID, reversalLine.getC_Invoice_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
for(MFactAcct factAcct : factAccts) {
if (factAcct.getM_Product_ID() != lca.getM_Product_ID())
continue;
if (factAcct.getLine_ID() != reversalLine.get_ID())
continue;
if (factAcct.getAccount_ID() == assetAccount.getAccount_ID()) {
if (factAcct.getAmtAcctDr().signum() != 0)
amtAsset = amtAsset.add(factAcct.getAmtAcctDr());
else if (factAcct.getAmtAcctCr().signum() != 0)
amtAsset = amtAsset.subtract(factAcct.getAmtAcctCr());
} else if (factAcct.getAccount_ID() == varianceAccount.getAccount_ID()) {
if (factAcct.getAmtAcctDr().signum() != 0)
amtVariance = amtVariance.add(factAcct.getAmtAcctDr());
else if (factAcct.getAmtAcctCr().signum() != 0)
amtVariance = amtVariance.subtract(factAcct.getAmtAcctCr());
}
}
if (lca.getM_AttributeSetInstance_ID() > 0 && M_AttributeSetInstance_ID == 0) {
String sql =
"""
SELECT SUM(Qty)
FROM M_CostDetail
WHERE C_InvoiceLine_ID=? AND Coalesce(M_CostElement_ID,0)=?
AND M_Product_ID=? AND C_AcctSchema_ID=?
""";
costDetailQty = DB.getSQLValueBDEx(getTrxName(), sql, reversalLine.get_ID(), lca.getM_CostElement_ID(), lca.getM_Product_ID(), as.getC_AcctSchema_ID());
if (costDetailQty == null)
costDetailQty = BigDecimal.ZERO;
} else if (lca.getM_AttributeSetInstance_ID() > 0 && M_AttributeSetInstance_ID > 0) {
MCostDetail cd = MCostDetail.get (as.getCtx(), "C_InvoiceLine_ID=? AND Coalesce(M_CostElement_ID,0)="+lca.getM_CostElement_ID()+" AND M_Product_ID="+lca.getM_Product_ID(),
reversalLine.get_ID(), lca.getM_AttributeSetInstance_ID(), as.getC_AcctSchema_ID(), getTrxName());
costDetailQty = cd != null ? cd.getQty() : BigDecimal.ZERO;
if (cd != null) {
amtAsset = cd.getAmt();
}
if (i > 0) {
for(int j = 0; j < i; j++) {
if (lcas[j].getM_Product_ID() == lca.getM_Product_ID()) {
//variance have been posted by product
amtVariance = BigDecimal.ZERO;
}
}
}
} else {
MCostDetail cd = MCostDetail.get (as.getCtx(), "C_InvoiceLine_ID=? AND Coalesce(M_CostElement_ID,0)="+lca.getM_CostElement_ID()+" AND M_Product_ID="+lca.getM_Product_ID(),
reversalLine.get_ID(), lca.getM_AttributeSetInstance_ID(), as.getC_AcctSchema_ID(), getTrxName());
costDetailQty = cd != null ? cd.getQty() : BigDecimal.ZERO;
}
if (costDetailQty.signum() != 0)
{
MCostElement ce = MCostElement.getMaterialCostElement(getCtx(), as.getCostingMethod(),
AD_Org_ID);
MCost c = MCost.get(getCtx(), getAD_Client_ID(), AD_Org_ID, lca.getM_Product_ID(),
as.getM_CostType_ID(), as.getC_AcctSchema_ID(), ce.getM_CostElement_ID(),
M_AttributeSetInstance_ID, getTrxName());
if (c != null) {
if (c.getCurrentQty().signum() == 0) {
amtVariance = amtVariance.add(amtAsset);
amtAsset = BigDecimal.ZERO;
} else if (c.getCurrentQty().compareTo(costDetailQty) < 0) {
BigDecimal currentAmtAsset = amtAsset;
amtAsset = amtAsset.divide(costDetailQty, RoundingMode.HALF_UP).multiply(c.getCurrentQty());
amtVariance = amtVariance.add(currentAmtAsset.subtract(amtAsset));
costDetailQty = c.getCurrentQty();
}
}
}
if (amtAsset.signum() != 0) {
if (!MCostDetail.createInvoice(as, lca.getAD_Org_ID(),
lca.getM_Product_ID(), lca.getM_AttributeSetInstance_ID(),
C_InvoiceLine_ID, lca.getM_CostElement_ID(),
amtAsset.negate(), costDetailQty,
desc, getTrxName())) {
throw new RuntimeException("Failed to create cost detail record.");
}
}
if (getC_Currency_ID() != as.getC_Currency_ID()) {
usesSchemaCurrency = true;
setC_Currency_ID(as.getC_Currency_ID());
}
}
} }
if (allocationAmt.signum() > 0) if (allocationAmt.signum() > 0 && !reversal)
{ {
if (allocationAmt.scale() > as.getStdPrecision()) if (allocationAmt.scale() > as.getStdPrecision())
{ {
@ -1109,8 +1331,9 @@ public class Doc_Invoice extends Doc
{ {
estimatedAmt = estimatedAmt.setScale(as.getStdPrecision(), RoundingMode.HALF_UP); estimatedAmt = estimatedAmt.setScale(as.getStdPrecision(), RoundingMode.HALF_UP);
} }
int compare = allocationAmt.compareTo(estimatedAmt); if (allocationAmt.compareTo(estimatedAmt)!=0)
if (compare > 0) {
if (estimatedAmt.signum() != 0)
{ {
drAmt = dr ? (reversal ? null : estimatedAmt): (reversal ? estimatedAmt : null); drAmt = dr ? (reversal ? null : estimatedAmt): (reversal ? estimatedAmt : null);
crAmt = dr ? (reversal ? estimatedAmt : null): (reversal ? null : estimatedAmt); crAmt = dr ? (reversal ? estimatedAmt : null): (reversal ? null : estimatedAmt);
@ -1119,36 +1342,42 @@ public class Doc_Invoice extends Doc
fl.setDescription(desc); fl.setDescription(desc);
fl.setM_Product_ID(lca.getM_Product_ID()); fl.setM_Product_ID(lca.getM_Product_ID());
fl.setQty(line.getQty()); fl.setQty(line.getQty());
BigDecimal overAmt = allocationAmt.subtract(estimatedAmt);
drAmt = dr ? (reversal ? null : overAmt) : (reversal ? overAmt : null);
crAmt = dr ? (reversal ? overAmt : null) : (reversal ? null : overAmt);
account = zeroQty ? pc.getAccount(ProductCost.ACCTTYPE_P_AverageCostVariance, as) : pc.getAccount(ProductCost.ACCTTYPE_P_Asset, as);
fl = fact.createLine (line, account, getC_Currency_ID(), drAmt, crAmt);
fl.setDescription(desc);
fl.setM_Product_ID(lca.getM_Product_ID());
fl.setQty(line.getQty());
} }
else if (compare < 0)
{ if (amtVariance.signum() != 0) {
drAmt = dr ? (reversal ? null : estimatedAmt) : (reversal ? estimatedAmt : null); if (amtVariance.signum() > 0) {
crAmt = dr ? (reversal ? estimatedAmt : null) : (reversal ? null : estimatedAmt); drAmt = dr ? amtVariance : null;
account = pc.getAccount(ProductCost.ACCTTYPE_P_LandedCostClearing, as); crAmt = dr ? null : amtVariance;
} else {
BigDecimal underAmt = amtVariance.negate();
drAmt = dr ? null : underAmt;
crAmt = dr ? underAmt : null;
}
account = pc.getAccount(ProductCost.ACCTTYPE_P_AverageCostVariance, as);
FactLine fl = fact.createLine(line, account, getC_Currency_ID(), drAmt, crAmt); FactLine fl = fact.createLine(line, account, getC_Currency_ID(), drAmt, crAmt);
fl.setDescription(desc); fl.setDescription(desc);
fl.setM_Product_ID(lca.getM_Product_ID()); fl.setM_Product_ID(lca.getM_Product_ID());
fl.setQty(line.getQty()); fl.setQty(line.getQty());
}
BigDecimal underAmt = estimatedAmt.subtract(allocationAmt); if (amtAsset.signum() != 0) {
drAmt = dr ? (reversal ? underAmt : null) : (reversal ? null : underAmt); if (amtAsset.signum() > 0) {
crAmt = dr ? (reversal ? null : underAmt) : (reversal ? underAmt : null); drAmt = dr ? amtAsset : null;
account = zeroQty ? pc.getAccount(ProductCost.ACCTTYPE_P_AverageCostVariance, as) : pc.getAccount(ProductCost.ACCTTYPE_P_Asset, as); crAmt = dr ? null : amtAsset;
fl = fact.createLine (line, account, getC_Currency_ID(), drAmt, crAmt); } else {
BigDecimal underAmt = amtAsset.negate();
drAmt = dr ? null : underAmt;
crAmt = dr ? underAmt : null;
}
account = pc.getAccount(ProductCost.ACCTTYPE_P_Asset, as);
FactLine fl = fact.createLine(line, account, getC_Currency_ID(), drAmt, crAmt);
fl.setDescription(desc); fl.setDescription(desc);
fl.setM_Product_ID(lca.getM_Product_ID()); fl.setM_Product_ID(lca.getM_Product_ID());
fl.setQty(line.getQty()); fl.setQty(line.getQty());
} }
else }
else if (allocationAmt.signum() != 0)
{ {
drAmt = dr ? (reversal ? null : allocationAmt) : (reversal ? allocationAmt : null); drAmt = dr ? (reversal ? null : allocationAmt) : (reversal ? allocationAmt : null);
crAmt = dr ? (reversal ? allocationAmt : null) : (reversal ? null : allocationAmt); crAmt = dr ? (reversal ? allocationAmt : null) : (reversal ? null : allocationAmt);
@ -1158,6 +1387,45 @@ public class Doc_Invoice extends Doc
fl.setM_Product_ID(lca.getM_Product_ID()); fl.setM_Product_ID(lca.getM_Product_ID());
fl.setQty(line.getQty()); fl.setQty(line.getQty());
} }
} else if (reversal) {
account = pc.getAccount(ProductCost.ACCTTYPE_P_LandedCostClearing, as);
FactLine fl = fact.createLine (line, account, getC_Currency_ID(), BigDecimal.ZERO, BigDecimal.ZERO);
fl.updateReverseLine(MInvoice.Table_ID, reversalLine.getC_Invoice_ID(), reversalLine.get_ID(), BigDecimal.ONE);
if (fl.getAmtAcctCr().signum() == 0 && fl.getAmtAcctDr().signum() == 0)
fact.remove(fl);
if (amtVariance.signum() != 0) {
if (amtVariance.signum() > 0) {
drAmt = dr ? null : amtVariance;
crAmt = dr ? amtVariance : null;
} else {
BigDecimal underAmt = amtVariance.negate();
drAmt = dr ? underAmt : null;
crAmt = dr ? null : underAmt;
}
account = pc.getAccount(ProductCost.ACCTTYPE_P_AverageCostVariance, as);
fl = fact.createLine(line, account, getC_Currency_ID(), drAmt, crAmt);
fl.setDescription(desc);
fl.setM_Product_ID(lca.getM_Product_ID());
fl.setQty(line.getQty());
}
if (amtAsset.signum() != 0) {
if (amtAsset.signum() > 0) {
drAmt = dr ? null : amtAsset;
crAmt = dr ? amtAsset : null;
} else {
BigDecimal underAmt = amtAsset.negate();
drAmt = dr ? underAmt : null;
crAmt = dr ? null : underAmt;
}
account = pc.getAccount(ProductCost.ACCTTYPE_P_Asset, as);
fl = fact.createLine(line, account, getC_Currency_ID(), drAmt, crAmt);
fl.setDescription(desc);
fl.setM_Product_ID(lca.getM_Product_ID());
fl.setQty(line.getQty());
}
} }
if (usesSchemaCurrency) if (usesSchemaCurrency)
setC_Currency_ID(line.getC_Currency_ID()); setC_Currency_ID(line.getC_Currency_ID());

View File

@ -36,7 +36,9 @@ import org.compiere.model.MAccount;
import org.compiere.model.MAcctSchema; import org.compiere.model.MAcctSchema;
import org.compiere.model.MAcctSchemaElement; import org.compiere.model.MAcctSchemaElement;
import org.compiere.model.MConversionRate; import org.compiere.model.MConversionRate;
import org.compiere.model.MCost;
import org.compiere.model.MCostDetail; import org.compiere.model.MCostDetail;
import org.compiere.model.MCostElement;
import org.compiere.model.MCurrency; import org.compiere.model.MCurrency;
import org.compiere.model.MFactAcct; import org.compiere.model.MFactAcct;
import org.compiere.model.MInOut; import org.compiere.model.MInOut;
@ -389,7 +391,8 @@ public class Doc_MatchInv extends Doc
// Invoice Price Variance difference // Invoice Price Variance difference
BigDecimal ipv = cr.getAcctBalance().add(dr.getAcctBalance()).negate(); BigDecimal ipv = cr.getAcctBalance().add(dr.getAcctBalance()).negate();
processInvoicePriceVariance(as, fact, ipv); BigDecimal ipvSource = dr.getAmtSourceDr().subtract(cr.getAmtSourceCr()).negate();
processInvoicePriceVariance(as, fact, ipv, ipvSource);
if (log.isLoggable(Level.FINE)) log.fine("IPV=" + ipv + "; Balance=" + fact.getSourceBalance()); if (log.isLoggable(Level.FINE)) log.fine("IPV=" + ipv + "; Balance=" + fact.getSourceBalance());
String error = createMatchInvCostDetail(as); String error = createMatchInvCostDetail(as);
@ -421,15 +424,70 @@ public class Doc_MatchInv extends Doc
* @param ipv * @param ipv
*/ */
protected void processInvoicePriceVariance(MAcctSchema as, Fact fact, protected void processInvoicePriceVariance(MAcctSchema as, Fact fact,
BigDecimal ipv) { BigDecimal ipv, BigDecimal ipvSource) {
if (ipv.signum() == 0) return; if (ipv.signum() == 0) return;
FactLine pv = fact.createLine(null,
m_pc.getAccount(ProductCost.ACCTTYPE_P_IPV, as),
as.getC_Currency_ID(), ipv);
updateFactLine(pv);
MMatchInv matchInv = (MMatchInv)getPO(); MMatchInv matchInv = (MMatchInv)getPO();
String costingMethod = m_pc.getProduct().getCostingMethod(as);
BigDecimal amtVariance = Env.ZERO;
BigDecimal amtAsset = Env.ZERO;
BigDecimal qtyMatched = matchInv.getQty();
BigDecimal qtyCost = null;
Boolean isStockCoverage = false;
boolean isReversal = matchInv.getReversal_ID() > 0 && matchInv.getReversal_ID() < matchInv.get_ID();
if (X_M_Cost.COSTINGMETHOD_AveragePO.equals(costingMethod) && m_invoiceLine.getM_Product_ID() > 0 && !isReversal)
{
isStockCoverage = true;
int AD_Org_ID = m_receiptLine.getAD_Org_ID();
int M_AttributeSetInstance_ID = matchInv.getM_AttributeSetInstance_ID();
if (MAcctSchema.COSTINGLEVEL_Client.equals(as.getCostingLevel()))
{
AD_Org_ID = 0;
M_AttributeSetInstance_ID = 0;
}
else if (MAcctSchema.COSTINGLEVEL_Organization.equals(as.getCostingLevel()))
M_AttributeSetInstance_ID = 0;
else if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(as.getCostingLevel()))
AD_Org_ID = 0;
MCostElement ce = MCostElement.getMaterialCostElement(getCtx(), costingMethod, AD_Org_ID);
MCostDetail cd = MCostDetail.get (as.getCtx(), "M_MatchInv_ID=? AND Coalesce(M_CostElement_ID,0)=0",
matchInv.getM_MatchInv_ID(), M_AttributeSetInstance_ID, as.getC_AcctSchema_ID(), getTrxName());
if(cd!=null){
qtyCost = cd.getCurrentQty();
}else{
MCost c = MCost.get(getCtx(), getAD_Client_ID(), AD_Org_ID, m_invoiceLine.getM_Product_ID(),
as.getM_CostType_ID(), as.getC_AcctSchema_ID(), ce.getM_CostElement_ID(),
M_AttributeSetInstance_ID, getTrxName());
qtyCost = (c!=null? c.getCurrentQty():Env.ZERO);
}
if (qtyCost != null && qtyCost.compareTo(qtyMatched) < 0 )
{
//If current cost qty < invoice qty
amtAsset = qtyCost.multiply(ipv).divide(qtyMatched,as.getCostingPrecision(),RoundingMode.HALF_UP);
amtVariance = ipv.subtract(amtAsset);
}else{
//If current qty >= invoice qty
amtAsset = ipv;
}
}
else if (X_M_Cost.COSTINGMETHOD_AveragePO.equals(costingMethod) && m_invoiceLine.getM_Product_ID() > 0 && isReversal)
{
isStockCoverage = true;
int M_AttributeSetInstance_ID = matchInv.getM_AttributeSetInstance_ID();
MCostDetail cd = MCostDetail.get (as.getCtx(), "M_MatchInv_ID=? AND Coalesce(M_CostElement_ID,0)=0",
matchInv.getReversal_ID(), M_AttributeSetInstance_ID, as.getC_AcctSchema_ID(), getTrxName());
amtAsset = cd != null ? cd.getAmt().negate() : BigDecimal.ZERO;
amtVariance = ipv.subtract(amtAsset);
}
Trx trx = Trx.get(getTrxName(), false); Trx trx = Trx.get(getTrxName(), false);
Savepoint savepoint = null; Savepoint savepoint = null;
boolean zeroQty = false; boolean zeroQty = false;
@ -439,7 +497,7 @@ public class Doc_MatchInv extends Doc
if (!MCostDetail.createMatchInvoice(as, m_invoiceLine.getAD_Org_ID(), if (!MCostDetail.createMatchInvoice(as, m_invoiceLine.getAD_Org_ID(),
m_invoiceLine.getM_Product_ID(), m_invoiceLine.getM_AttributeSetInstance_ID(), m_invoiceLine.getM_Product_ID(), m_invoiceLine.getM_AttributeSetInstance_ID(),
matchInv.getM_MatchInv_ID(), 0, matchInv.getM_MatchInv_ID(), 0,
ipv, BigDecimal.ZERO, "Invoice Price Variance", getTrxName())) { isStockCoverage ? amtAsset: ipv, BigDecimal.ZERO, "Invoice Price Variance", getTrxName())) {
throw new RuntimeException("Failed to create cost detail record."); throw new RuntimeException("Failed to create cost detail record.");
} }
} catch (SQLException e) { } catch (SQLException e) {
@ -460,36 +518,57 @@ public class Doc_MatchInv extends Doc
} }
} }
String costingMethod = m_pc.getProduct().getCostingMethod(as);
MAccount account = m_pc.getAccount(ProductCost.ACCTTYPE_P_Asset, as); MAccount account = m_pc.getAccount(ProductCost.ACCTTYPE_P_Asset, as);
if (m_pc.isService()) if (m_pc.isService())
account = m_pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as); account = m_pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
if (X_M_Cost.COSTINGMETHOD_AveragePO.equals(costingMethod)) { if (X_M_Cost.COSTINGMETHOD_AveragePO.equals(costingMethod)) {
if (zeroQty) FactLine varianceLine = null;
account = m_pc.getAccount(ProductCost.ACCTTYPE_P_AverageCostVariance, as); if (amtVariance.compareTo(Env.ZERO) != 0)
FactLine line = fact.createLine(null, {
m_pc.getAccount(ProductCost.ACCTTYPE_P_IPV, as), varianceLine = fact.createLine(null,
as.getC_Currency_ID(), ipv.negate()); m_pc.getAccount(ProductCost.ACCTTYPE_P_AverageCostVariance, as), as.getC_Currency_ID(),
updateFactLine(line); amtVariance);
line.setQty(getQty().negate()); updateFactLine(varianceLine);
line = fact.createLine(null, account, as.getC_Currency_ID(), ipv); if (m_invoiceLine.getParent().getC_Currency_ID() != as.getC_Currency_ID())
{
updateFactLineAmtSource(varianceLine, ipvSource.multiply(amtVariance).divide(ipv));
}
}
if (amtAsset.compareTo(Env.ZERO) != 0)
{
FactLine line = fact.createLine(null, account, as.getC_Currency_ID(), amtAsset);
updateFactLine(line); updateFactLine(line);
if (m_invoiceLine.getParent().getC_Currency_ID() != as.getC_Currency_ID())
{
updateFactLineAmtSource(line, ipvSource.multiply(amtAsset).divide(ipv));
}
}
} else if (X_M_Cost.COSTINGMETHOD_AverageInvoice.equals(costingMethod) && !zeroQty) { } else if (X_M_Cost.COSTINGMETHOD_AverageInvoice.equals(costingMethod) && !zeroQty) {
FactLine line = fact.createLine(null, //TODO test for avg Invoice costing method as here dropped posting of posting to IPV account
FactLine line = fact.createLine(null, account, as.getC_Currency_ID(), ipv);
updateFactLine(line);
if (m_invoiceLine.getParent().getC_Currency_ID() != as.getC_Currency_ID())
{
updateFactLineAmtSource(line, ipvSource);
}
}else{
//For standard costing post to IPV account
FactLine pv = fact.createLine(null,
m_pc.getAccount(ProductCost.ACCTTYPE_P_IPV, as), m_pc.getAccount(ProductCost.ACCTTYPE_P_IPV, as),
as.getC_Currency_ID(), ipv.negate()); as.getC_Currency_ID(), ipv);
updateFactLine(line); updateFactLine(pv);
line.setQty(getQty().negate()); if (m_invoiceLine.getParent().getC_Currency_ID() != as.getC_Currency_ID())
{
line = fact.createLine(null, account, as.getC_Currency_ID(), ipv); updateFactLineAmtSource(pv, ipvSource);
updateFactLine(line); }
} }
} }
/** /** Verify if the posting involves two or more organizations
* Verify if the posting involves two or more organizations @return true if there are more than one org involved on the posting
* @return true if there are more than one org involved on the posting
*/ */
private boolean isInterOrg(MAcctSchema as) { private boolean isInterOrg(MAcctSchema as) {
MAcctSchemaElement elementorg = as.getAcctSchemaElement(MAcctSchemaElement.ELEMENTTYPE_Organization); MAcctSchemaElement elementorg = as.getAcctSchemaElement(MAcctSchemaElement.ELEMENTTYPE_Organization);
@ -907,7 +986,8 @@ public class Doc_MatchInv extends Doc
// Invoice Price Variance difference // Invoice Price Variance difference
BigDecimal ipv = cr.getAcctBalance().add(dr.getAcctBalance()).negate(); BigDecimal ipv = cr.getAcctBalance().add(dr.getAcctBalance()).negate();
processInvoicePriceVariance(as, fact, ipv); BigDecimal ipvSource = dr.getAmtSourceDr().subtract(cr.getAmtSourceCr()).negate();
processInvoicePriceVariance(as, fact, ipv, ipvSource);
if (log.isLoggable(Level.FINE)) log.fine("IPV=" + ipv + "; Balance=" + fact.getSourceBalance()); if (log.isLoggable(Level.FINE)) log.fine("IPV=" + ipv + "; Balance=" + fact.getSourceBalance());
String error = createMatchInvCostDetail(as); String error = createMatchInvCostDetail(as);
@ -1258,6 +1338,29 @@ public class Doc_MatchInv extends Doc
factLine.setQty(getQty()); factLine.setQty(getQty());
} }
/**
* Invoice currency & acct schema currency are not same then update AmtSource value
* to avoid source not balanced error/ignore suspense balancing.
*
* @param factLine
* @param ipvSource
*/
protected void updateFactLineAmtSource(FactLine factLine, BigDecimal ipvSource)
{
// When only Rate differ then set Dr & Cr Source amount as zero.
factLine.setAmtSourceCr(Env.ZERO);
factLine.setAmtSourceDr(Env.ZERO);
// Price is vary then set Source amount according to source variance
if (ipvSource.compareTo(Env.ZERO) != 0)
{
if (ipvSource.signum() < 0)
factLine.setAmtSourceCr(ipvSource);
else
factLine.setAmtSourceDr(ipvSource);
}
}
/** /**
* Create Gain/Loss for invoice * Create Gain/Loss for invoice
* @param as accounting schema * @param as accounting schema

View File

@ -276,6 +276,17 @@ public class MAccount extends X_C_ValidCombination implements ImmutablePOSupport
* @return account * @return account
*/ */
public static MAccount get (X_Fact_Acct fa) public static MAccount get (X_Fact_Acct fa)
{
return get(fa, (String)null);
}
/**
* Get from existing Accounting fact
* @param fa accounting fact
* @param trxName
* @return account
*/
public static MAccount get (X_Fact_Acct fa, String trxName)
{ {
MAccount acct = get (fa.getCtx(), MAccount acct = get (fa.getCtx(),
fa.getAD_Client_ID(), fa.getAD_Org_ID(), fa.getC_AcctSchema_ID(), fa.getAD_Client_ID(), fa.getAD_Org_ID(), fa.getC_AcctSchema_ID(),
@ -283,7 +294,7 @@ public class MAccount extends X_C_ValidCombination implements ImmutablePOSupport
fa.getM_Product_ID(), fa.getC_BPartner_ID(), fa.getAD_OrgTrx_ID(), fa.getM_Product_ID(), fa.getC_BPartner_ID(), fa.getAD_OrgTrx_ID(),
fa.getC_LocFrom_ID(), fa.getC_LocTo_ID(), fa.getC_SalesRegion_ID(), fa.getC_LocFrom_ID(), fa.getC_LocTo_ID(), fa.getC_SalesRegion_ID(),
fa.getC_Project_ID(), fa.getC_Campaign_ID(), fa.getC_Activity_ID(), fa.getC_Project_ID(), fa.getC_Campaign_ID(), fa.getC_Activity_ID(),
fa.getUser1_ID(), fa.getUser2_ID(), fa.getUserElement1_ID(), fa.getUserElement2_ID()); fa.getUser1_ID(), fa.getUser2_ID(), fa.getUserElement1_ID(), fa.getUserElement2_ID(), trxName);
return acct; return acct;
} // get } // get

View File

@ -126,6 +126,7 @@ public class MFactAcct extends X_Fact_Acct
sb.append(get_ID()).append("-Acct=").append(getAccount_ID()) sb.append(get_ID()).append("-Acct=").append(getAccount_ID())
.append(",Dr=").append(getAmtSourceDr()).append("|").append(getAmtAcctDr()) .append(",Dr=").append(getAmtSourceDr()).append("|").append(getAmtAcctDr())
.append(",Cr=").append(getAmtSourceCr()).append("|").append(getAmtAcctCr()) .append(",Cr=").append(getAmtSourceCr()).append("|").append(getAmtAcctCr())
.append(",C_Currency_ID=").append(getC_Currency_ID())
.append ("]"); .append ("]");
return sb.toString (); return sb.toString ();
} // toString } // toString

View File

@ -24,10 +24,15 @@
**********************************************************************/ **********************************************************************/
package org.idempiere.test; package org.idempiere.test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.fail;
import java.math.RoundingMode;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Properties; import java.util.Properties;
@ -35,6 +40,7 @@ import org.adempiere.util.ServerContext;
import org.compiere.Adempiere; import org.compiere.Adempiere;
import org.compiere.model.MAcctSchema; import org.compiere.model.MAcctSchema;
import org.compiere.model.MClientInfo; import org.compiere.model.MClientInfo;
import org.compiere.model.MFactAcct;
import org.compiere.model.MRole; import org.compiere.model.MRole;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.compiere.util.Language; import org.compiere.util.Language;
@ -239,4 +245,104 @@ public abstract class AbstractTestCase {
Adempiere.startup(false); Adempiere.startup(false);
} }
} }
/**
* Match expectedList against a list of MFactAcct records
* @param factAccts
* @param expectedList
*/
protected void assertFactAcctEntries(List<MFactAcct> factAccts, List<FactAcct> expectedList) {
List<FactAcct> found = new ArrayList<FactAcct>();
List<MFactAcct> matches = new ArrayList<MFactAcct>();
expectedList.forEach(fa -> {
//LineId and account id match
List<MFactAcct> accountMatches = new ArrayList<MFactAcct>();
//find exact match
for(MFactAcct mfa : factAccts) {
if (fa.account().getAccount().get_ID() == mfa.getAccount_ID()) {
if (fa.lineId() > 0 && fa.lineId() != mfa.getLine_ID())
continue;
accountMatches.add(mfa);
if (fa.qty() != null && (mfa.getQty() == null || !mfa.getQty().setScale(fa.rounding(), RoundingMode.HALF_UP).equals(fa.qty().setScale(fa.rounding(), RoundingMode.HALF_UP))))
continue;
if (fa.debit()) {
if (fa.accountedAmount() != null && !fa.accountedAmount().setScale(fa.rounding(), RoundingMode.HALF_UP).equals(mfa.getAmtAcctDr().setScale(fa.rounding(), RoundingMode.HALF_UP)))
continue;
if (fa.sourceAmount() != null && !fa.sourceAmount().setScale(fa.rounding(), RoundingMode.HALF_UP).equals(mfa.getAmtSourceDr().setScale(fa.rounding(), RoundingMode.HALF_UP)))
continue;
found.add(fa);
matches.add(mfa);
break;
} else {
if (fa.accountedAmount() != null && !fa.accountedAmount().setScale(fa.rounding(), RoundingMode.HALF_UP).equals(mfa.getAmtAcctCr().setScale(fa.rounding(), RoundingMode.HALF_UP)))
continue;
if (fa.sourceAmount() != null && !fa.sourceAmount().setScale(fa.rounding(), RoundingMode.HALF_UP).equals(mfa.getAmtSourceCr().setScale(fa.rounding(), RoundingMode.HALF_UP)))
continue;
found.add(fa);
matches.add(mfa);
break;
}
}
}
//assert qty mismatch
if (!found.contains(fa) && !accountMatches.isEmpty()) {
for(MFactAcct mfa : accountMatches) {
if (fa.debit()) {
if (fa.accountedAmount() != null && !fa.accountedAmount().setScale(fa.rounding(), RoundingMode.HALF_UP).equals(mfa.getAmtAcctDr().setScale(fa.rounding(), RoundingMode.HALF_UP)))
continue;
if (fa.sourceAmount() != null && !fa.sourceAmount().setScale(fa.rounding(), RoundingMode.HALF_UP).equals(mfa.getAmtSourceDr().setScale(fa.rounding(), RoundingMode.HALF_UP)))
continue;
} else {
if (fa.accountedAmount() != null && !fa.accountedAmount().setScale(fa.rounding(), RoundingMode.HALF_UP).equals(mfa.getAmtAcctCr().setScale(fa.rounding(), RoundingMode.HALF_UP)))
continue;
if (fa.sourceAmount() != null && !fa.sourceAmount().setScale(fa.rounding(), RoundingMode.HALF_UP).equals(mfa.getAmtSourceCr().setScale(fa.rounding(), RoundingMode.HALF_UP)))
continue;
}
assertEquals(fa.qty().setScale(fa.rounding(), RoundingMode.HALF_UP), mfa.getQty().setScale(fa.rounding(), RoundingMode.HALF_UP), "Unexpected Qty for " + fa);
found.add(fa);
}
}
});
//assert amount mismatch
expectedList.forEach(fa -> {
if (!found.contains(fa)) {
for(MFactAcct mfa : factAccts) {
if (matches.contains(mfa))
continue;
if (fa.account().getAccount().get_ID() != mfa.getAccount_ID())
continue;
if (fa.lineId() > 0 && fa.lineId() != mfa.getLine_ID())
continue;
if (fa.debit()) {
if (fa.accountedAmount() != null && fa.accountedAmount().signum() == mfa.getAmtAcctDr().signum())
assertEquals(fa.accountedAmount().setScale(fa.rounding(), RoundingMode.HALF_UP), mfa.getAmtAcctDr().setScale(fa.rounding(), RoundingMode.HALF_UP), "Unexpected Accounted Dr amount for " + fa);
else if (fa.accountedAmount() != null)
continue;
if (fa.sourceAmount() != null && fa.sourceAmount().signum() == mfa.getAmtSourceDr().signum())
assertEquals(fa.accountedAmount().setScale(fa.rounding(), RoundingMode.HALF_UP), mfa.getAmtSourceDr().setScale(fa.rounding(), RoundingMode.HALF_UP), "Unexpected Source Dr amount for " + fa);
else if (fa.sourceAmount() != null)
continue;
} else {
if (fa.accountedAmount() != null && fa.accountedAmount().signum() == mfa.getAmtAcctCr().signum())
assertEquals(fa.accountedAmount().setScale(fa.rounding(), RoundingMode.HALF_UP), mfa.getAmtAcctCr().setScale(fa.rounding(), RoundingMode.HALF_UP), "Unexpected Accounted Cr amount for " + fa);
else if (fa.accountedAmount() != null)
continue;
if (fa.sourceAmount() != null && fa.sourceAmount().signum() == mfa.getAmtSourceCr().signum())
assertEquals(fa.accountedAmount().setScale(fa.rounding(), RoundingMode.HALF_UP), mfa.getAmtSourceCr().setScale(fa.rounding(), RoundingMode.HALF_UP), "Unexpected Source Cr amount for " + fa);
else if (fa.sourceAmount() != null)
continue;
}
if (fa.qty() != null && mfa.getQty() != null)
assertEquals(fa.qty().setScale(fa.rounding(), RoundingMode.HALF_UP), mfa.getQty().setScale(fa.rounding(), RoundingMode.HALF_UP), "Unexpected Qty for " + fa);
found.add(fa);
}
}
});
//assert not found
for(FactAcct factAcct : expectedList) {
assertTrue(found.contains(factAcct), "No fact acct record found for " + factAcct);
}
}
} }

View File

@ -0,0 +1,113 @@
/***********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
**********************************************************************/
package org.idempiere.test;
import java.math.BigDecimal;
import java.math.RoundingMode;
import org.compiere.model.MAccount;
/**
* @param account
* @param accountedAmount
* @param sourceAmount
* @param rounding
* @param debit
* @param lineId
* @param qty
*/
public record FactAcct(MAccount account, BigDecimal accountedAmount, BigDecimal sourceAmount, int rounding, boolean debit, int lineId, BigDecimal qty) {
/**
* @param account
* @param accountedAmount
* @param sourceAmount
* @param rounding
* @param debit
* @param lineId
*/
public FactAcct(MAccount account, BigDecimal accountedAmount, BigDecimal sourceAmount, int rounding, boolean debit, int lineId) {
this(account, accountedAmount, sourceAmount, rounding, debit, lineId, (BigDecimal)null);
}
/**
* @param account
* @param accountedAmount
* @param sourceAmount
* @param rounding
* @param debit
* @param qty
*/
public FactAcct(MAccount account, BigDecimal accountedAmount, BigDecimal sourceAmount, int rounding, boolean debit, BigDecimal qty) {
this(account, accountedAmount, sourceAmount, rounding, debit, 0, qty);
}
/**
* @param account
* @param accountedAmount
* @param rounding
* @param debit
* @param qty
*/
public FactAcct(MAccount account, BigDecimal accountedAmount, int rounding, boolean debit, BigDecimal qty) {
this(account, accountedAmount, null, rounding, debit, 0, qty);
}
/**
* @param account
* @param accountedAmount
* @param rounding
* @param debit
*/
public FactAcct(MAccount account, BigDecimal accountedAmount, int rounding, boolean debit) {
this(account, accountedAmount, null, rounding, debit, 0);
}
/**
* @param account
* @param accountedAmount
* @param sourceAmount
* @param rounding
* @param debit
*/
public FactAcct(MAccount account, BigDecimal accountedAmount, BigDecimal sourceAmount, int rounding, boolean debit) {
this(account, accountedAmount, sourceAmount, rounding, debit, 0);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("Account=").append(account.getAccount_ID()).append(" | ")
.append(account.getAccount());
builder.append(", ").append(debit ? "Dr" : "Cr").append("[");
if (accountedAmount != null)
builder.append("Accounted=").append(accountedAmount.setScale(rounding, RoundingMode.HALF_UP).toPlainString());
if (sourceAmount != null) {
if (accountedAmount != null) builder.append(", ");
builder.append("Source=").append(sourceAmount.setScale(rounding, RoundingMode.HALF_UP).toPlainString());
}
builder.append("]");
if (lineId > 0)
builder.append(", LineId=").append(lineId);
if (qty != null)
builder.append(", Qty=").append(qty.setScale(rounding, RoundingMode.HALF_UP).toPlainString());
return builder.toString();
}
}

View File

@ -31,6 +31,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.Arrays;
import java.util.List; import java.util.List;
import org.compiere.acct.Doc; import org.compiere.acct.Doc;
@ -70,6 +71,7 @@ import org.compiere.wf.MWorkflow;
import org.idempiere.test.AbstractTestCase; import org.idempiere.test.AbstractTestCase;
import org.idempiere.test.ConversionRateHelper; import org.idempiere.test.ConversionRateHelper;
import org.idempiere.test.DictionaryIDs; import org.idempiere.test.DictionaryIDs;
import org.idempiere.test.FactAcct;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.ResourceLock; import org.junit.jupiter.api.parallel.ResourceLock;
@ -146,23 +148,14 @@ public class InOutTest extends AbstractTestCase {
doc.setC_BPartner_ID(receipt.getC_BPartner_ID()); doc.setC_BPartner_ID(receipt.getC_BPartner_ID());
MAccount acctNIR = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as); MAccount acctNIR = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MInOut.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + receipt.get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID();
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
for (int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (acctNIR.getAccount_ID() == fa.getAccount_ID()) {
if (receiptLine.get_ID() == fa.getLine_ID()) {
BigDecimal acctSource = orderLine.getPriceActual().multiply(receiptLine.getMovementQty()) BigDecimal acctSource = orderLine.getPriceActual().multiply(receiptLine.getMovementQty())
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP); .setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
BigDecimal acctAmount = acctSource.multiply(rate) BigDecimal acctAmount = acctSource.multiply(rate)
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP); .setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
assertTrue(fa.getAmtSourceCr().compareTo(acctSource) == 0, fa.getAmtSourceCr().toPlainString() + " != " + acctSource.toPlainString()); Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, receipt.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
assertTrue(fa.getAmtAcctCr().compareTo(acctAmount) == 0, fa.getAmtAcctCr().toPlainString() + " != " + acctAmount.toPlainString()); List<MFactAcct> factAccts = query.list();
} List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, acctAmount, acctSource, as.getC_Currency().getStdPrecision(), false, receiptLine.get_ID()));
} assertFactAcctEntries(factAccts, expected);
}
} }
order = createPurchaseOrder(bpartner, currentDate, priceList.getM_PriceList_ID(), Spot_ConversionType_ID); order = createPurchaseOrder(bpartner, currentDate, priceList.getM_PriceList_ID(), Spot_ConversionType_ID);
@ -185,23 +178,14 @@ public class InOutTest extends AbstractTestCase {
doc.setC_BPartner_ID(receipt.getC_BPartner_ID()); doc.setC_BPartner_ID(receipt.getC_BPartner_ID());
MAccount acctNIR = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as); MAccount acctNIR = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MInOut.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + receipt.get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID();
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
for (int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (acctNIR.getAccount_ID() == fa.getAccount_ID()) {
if (receiptLine.get_ID() == fa.getLine_ID()) {
BigDecimal acctSource = orderLine.getPriceActual().multiply(receiptLine.getMovementQty()) BigDecimal acctSource = orderLine.getPriceActual().multiply(receiptLine.getMovementQty())
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP); .setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
BigDecimal acctAmount = acctSource.multiply(rate) BigDecimal acctAmount = acctSource.multiply(rate)
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP); .setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
assertTrue(fa.getAmtSourceCr().compareTo(acctSource) == 0, fa.getAmtSourceCr().toPlainString() + " != " + acctSource.toPlainString()); Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, receipt.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
assertTrue(fa.getAmtAcctCr().compareTo(acctAmount) == 0, fa.getAmtAcctCr().toPlainString() + " != " + acctAmount.toPlainString()); List<MFactAcct> factAccts = query.list();
} List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, acctAmount, acctSource, as.getC_Currency().getStdPrecision(), false, receiptLine.get_ID()));
} assertFactAcctEntries(factAccts, expected);
}
} }
} finally { } finally {
rollback(); rollback();
@ -276,20 +260,14 @@ public class InOutTest extends AbstractTestCase {
doc.setC_BPartner_ID(receipt.getC_BPartner_ID()); doc.setC_BPartner_ID(receipt.getC_BPartner_ID());
MAccount acctNIR = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as); MAccount acctNIR = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as);
Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, receipt.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> fas = query.list();
for (MFactAcct fa : fas) {
if (acctNIR.getAccount_ID() == fa.getAccount_ID()) {
if (receiptLine.get_ID() == fa.getLine_ID()) {
BigDecimal acctSource = orderLine.getPriceActual().multiply(receiptLine.getMovementQty()) BigDecimal acctSource = orderLine.getPriceActual().multiply(receiptLine.getMovementQty())
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP); .setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
BigDecimal acctAmount = acctSource.multiply(rate) BigDecimal acctAmount = acctSource.multiply(rate)
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP); .setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
assertTrue(fa.getAmtSourceCr().compareTo(acctSource) == 0, fa.getAmtSourceCr().toPlainString() + " != " + acctSource.toPlainString()); Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, receipt.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
assertTrue(fa.getAmtAcctCr().compareTo(acctAmount) == 0, fa.getAmtAcctCr().toPlainString() + " != " + acctAmount.toPlainString()); List<MFactAcct> fas = query.list();
} List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, acctAmount, acctSource, 2, false, receiptLine.get_ID()));
} assertFactAcctEntries(fas, expected);
}
} }
MRMA rma = new MRMA(Env.getCtx(), 0, getTrxName()); MRMA rma = new MRMA(Env.getCtx(), 0, getTrxName());
@ -343,19 +321,14 @@ public class InOutTest extends AbstractTestCase {
doc.setC_BPartner_ID(delivery.getC_BPartner_ID()); doc.setC_BPartner_ID(delivery.getC_BPartner_ID());
MAccount acctNIR = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as); MAccount acctNIR = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as);
Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, delivery.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> fas = query.list();
for (MFactAcct fa : fas) {
if (acctNIR.getAccount_ID() == fa.getAccount_ID()) {
if (deliveryLine.get_ID() == fa.getLine_ID()) {
BigDecimal acctSource = orderLine.getPriceActual().multiply(deliveryLine.getMovementQty()) BigDecimal acctSource = orderLine.getPriceActual().multiply(deliveryLine.getMovementQty())
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP); .setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
BigDecimal acctAmount = acctSource.multiply(rate) BigDecimal acctAmount = acctSource.multiply(rate)
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP); .setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
assertTrue(fa.getAmtAcctDr().compareTo(acctAmount) == 0, fa.getAmtAcctDr().toPlainString() + " != " + acctAmount.toPlainString()); Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, delivery.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
} List<MFactAcct> fas = query.list();
} List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, acctAmount, null, 2, true, deliveryLine.get_ID()));
} assertFactAcctEntries(fas, expected);
} }
} finally { } finally {
rollback(); rollback();

View File

@ -34,6 +34,7 @@ import java.sql.Timestamp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import org.compiere.acct.Doc; import org.compiere.acct.Doc;
import org.compiere.acct.DocManager; import org.compiere.acct.DocManager;
@ -59,6 +60,7 @@ import org.compiere.model.MProductPrice;
import org.compiere.model.MWarehouse; import org.compiere.model.MWarehouse;
import org.compiere.model.PO; import org.compiere.model.PO;
import org.compiere.model.ProductCost; import org.compiere.model.ProductCost;
import org.compiere.model.Query;
import org.compiere.process.DocAction; import org.compiere.process.DocAction;
import org.compiere.process.DocumentEngine; import org.compiere.process.DocumentEngine;
import org.compiere.process.ProcessInfo; import org.compiere.process.ProcessInfo;
@ -1840,12 +1842,9 @@ public class MatchInv2ndAcctSchemaTest extends AbstractTestCase {
BigDecimal totalNIRAmtAcct = Env.ZERO; BigDecimal totalNIRAmtAcct = Env.ZERO;
BigDecimal totalInvClrAmtAcct = Env.ZERO; BigDecimal totalInvClrAmtAcct = Env.ZERO;
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID Query query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); for (MFactAcct fa : factAccts) {
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
for (int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (acctNIR.getAccount_ID() == fa.getAccount_ID()) if (acctNIR.getAccount_ID() == fa.getAccount_ID())
totalNIRAmtAcct = totalNIRAmtAcct.add(fa.getAmtAcctDr()).subtract(fa.getAmtAcctCr()); totalNIRAmtAcct = totalNIRAmtAcct.add(fa.getAmtAcctDr()).subtract(fa.getAmtAcctCr());
else if (acctInvClr.getAccount_ID() == fa.getAccount_ID()) else if (acctInvClr.getAccount_ID() == fa.getAccount_ID())

View File

@ -31,6 +31,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.Arrays;
import java.util.List;
import org.compiere.acct.Doc; import org.compiere.acct.Doc;
import org.compiere.acct.DocManager; import org.compiere.acct.DocManager;
@ -63,9 +65,11 @@ import org.compiere.process.DocAction;
import org.compiere.process.DocumentEngine; import org.compiere.process.DocumentEngine;
import org.compiere.process.ProcessInfo; import org.compiere.process.ProcessInfo;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.compiere.util.TimeUtil;
import org.compiere.wf.MWorkflow; import org.compiere.wf.MWorkflow;
import org.idempiere.test.AbstractTestCase; import org.idempiere.test.AbstractTestCase;
import org.idempiere.test.DictionaryIDs; import org.idempiere.test.DictionaryIDs;
import org.idempiere.test.FactAcct;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
/** /**
@ -223,17 +227,10 @@ public class MatchInvTest extends AbstractTestCase {
ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName()); ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as); MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID Query query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, credMatchAmt, 2, false), new FactAcct(acctInvClr, credMatchAmt, 2, true));
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); assertFactAcctEntries(factAccts, expected);
for (int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (fa.getAccount_ID() == acctNIR.getAccount_ID())
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), credMatchAmt.setScale(2, RoundingMode.HALF_UP), "MatchInv incorrect amount posted "+fa.getAmtAcctCr().toPlainString());
else if (fa.getAccount_ID() == acctInvClr.getAccount_ID())
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), credMatchAmt.setScale(2, RoundingMode.HALF_UP), "MatchInv incorrect amount posted "+fa.getAmtAcctDr().toPlainString());
}
} }
rollback(); rollback();
@ -334,17 +331,10 @@ public class MatchInvTest extends AbstractTestCase {
ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName()); ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as); MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID Query query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, invMatchAmt, 2, true), new FactAcct(acctInvClr, invMatchAmt, 2, false));
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); assertFactAcctEntries(factAccts, expected);
for (int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (fa.getAccount_ID() == acctNIR.getAccount_ID())
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), invMatchAmt.setScale(2, RoundingMode.HALF_UP), "MatchInv incorrect amount posted "+fa.getAmtAcctCr().toPlainString());
else if (fa.getAccount_ID() == acctInvClr.getAccount_ID())
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), invMatchAmt.setScale(2, RoundingMode.HALF_UP), "MatchInv incorrect amount posted "+fa.getAmtAcctCr().toPlainString());
}
} }
rollback(); rollback();
@ -452,21 +442,11 @@ public class MatchInvTest extends AbstractTestCase {
ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName()); ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as); MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID Query query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); List<FactAcct> expected = Arrays.asList(new FactAcct(acctInvClr, invMatchAmt, 2, false, mi.getQty().negate()),
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); new FactAcct(acctNIR, invMatchAmt, 2, true, mi.getQty()));
for (int id : ids) { assertFactAcctEntries(factAccts, expected);
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (fa.getAccount_ID() == acctNIR.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), invMatchAmt.setScale(2, RoundingMode.HALF_UP), "MatchInv incorrect amount posted "+fa.getAmtAcctDr().toPlainString());
assertEquals(mi.getQty(), fa.getQty(), "Accounting fact quantity incorrect");
}
else if (fa.getAccount_ID() == acctInvClr.getAccount_ID()) {
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), invMatchAmt.setScale(2, RoundingMode.HALF_UP), "MatchInv incorrect amount posted "+fa.getAmtAcctCr().toPlainString());
assertEquals(mi.getQty().negate().setScale(2, RoundingMode.HALF_UP), fa.getQty().setScale(2, RoundingMode.HALF_UP), "Accounting fact quantity incorrect");
}
}
} }
MInvoice creditMemo = new MInvoice(Env.getCtx(), 0, getTrxName()); MInvoice creditMemo = new MInvoice(Env.getCtx(), 0, getTrxName());
@ -513,26 +493,11 @@ public class MatchInvTest extends AbstractTestCase {
ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName()); ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as); MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
BigDecimal amtAcctDrInvClr = BigDecimal.ZERO; Query query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
BigDecimal amtAcctCrInvClr = BigDecimal.ZERO; List<MFactAcct> factAccts = query.list();
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID List<FactAcct> expected = Arrays.asList(new FactAcct(acctInvClr, credMatchAmt, 2, false, mi.getQty()),
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID() new FactAcct(acctInvClr, credMatchAmt, 2, true, mi.getQty().negate()));
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); assertFactAcctEntries(factAccts, expected);
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
for (int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (fa.getAccount_ID() == acctInvClr.getAccount_ID() && fa.getQty().compareTo(BigDecimal.ZERO) < 0) {
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), credMatchAmt.setScale(2, RoundingMode.HALF_UP), "MatchInv incorrect amount posted "+fa.getAmtAcctCr().toPlainString());
amtAcctCrInvClr = amtAcctCrInvClr.add(fa.getAmtAcctCr());
assertEquals(mi.getQty(), fa.getQty(), "Accounting fact quantity incorrect");
}
else if (fa.getAccount_ID() == acctInvClr.getAccount_ID() && fa.getQty().compareTo(BigDecimal.ZERO) > 0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), credMatchAmt.setScale(2, RoundingMode.HALF_UP), "MatchInv incorrect amount posted "+fa.getAmtAcctDr().toPlainString());
amtAcctDrInvClr = amtAcctDrInvClr.add(fa.getAmtAcctDr());
assertEquals(mi.getQty().negate(), fa.getQty(), "Accounting fact quantity incorrect");
}
}
assertTrue(amtAcctDrInvClr.compareTo(amtAcctCrInvClr) == 0);
} }
rollback(); rollback();
@ -679,25 +644,14 @@ public class MatchInvTest extends AbstractTestCase {
ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName()); ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as); MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID Query query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, acctAmount, acctSource, 2, true),
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); new FactAcct(acctInvClr, acctAmount, acctSource, 2, false));
for (int id : ids) { assertFactAcctEntries(factAccts, expected);
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); assertTrue(acctAmount.compareTo(Env.ZERO) >= 0);
if (fa.getAccount_ID() == acctNIR.getAccount_ID()) { for (MFactAcct fa : factAccts) {
assertTrue(fa.getAmtAcctDr().compareTo(Env.ZERO) >= 0);
assertEquals(acctAmount, fa.getAmtAcctDr(), fa.getAmtAcctDr().toPlainString() + " != " + acctAmount.toPlainString());
// verify source amt and currency
assertTrue(fa.getC_Currency_ID() == japaneseYen.getC_Currency_ID()); assertTrue(fa.getC_Currency_ID() == japaneseYen.getC_Currency_ID());
assertEquals(acctSource, fa.getAmtSourceDr(), fa.getAmtSourceDr().toPlainString() + " != " + acctSource.toPlainString());
} else if (fa.getAccount_ID() == acctInvClr.getAccount_ID()) {
assertTrue(fa.getAmtAcctCr().compareTo(Env.ZERO) >= 0);
assertEquals(acctAmount, fa.getAmtAcctCr(), fa.getAmtAcctCr().toPlainString() + " != " + acctAmount.toPlainString());
// verify source amt and currency
assertTrue(fa.getC_Currency_ID() == japaneseYen.getC_Currency_ID());
assertEquals(acctSource, fa.getAmtSourceCr(), fa.getAmtSourceCr().toPlainString() + " != " + acctSource.toPlainString());
}
} }
} }
} finally { } finally {
@ -1042,27 +996,206 @@ public class MatchInvTest extends AbstractTestCase {
ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName()); ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as); MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID Query query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, invMatchAmt, 2, !mi.isReversal(), mi.getQty()),
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); new FactAcct(acctInvClr, invMatchAmt, 2, mi.isReversal(), mi.getQty().negate()));
for (int id : ids) { assertFactAcctEntries(factAccts, expected);
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (fa.getAccount_ID() == acctNIR.getAccount_ID()) {
if (mi.isReversal())
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), invMatchAmt.setScale(2, RoundingMode.HALF_UP), "MatchInv incorrect amount posted ");
else
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), invMatchAmt.setScale(2, RoundingMode.HALF_UP), "MatchInv incorrect amount posted ");
assertEquals(mi.getQty(), fa.getQty(), "Accounting fact quantity incorrect");
}
else if (fa.getAccount_ID() == acctInvClr.getAccount_ID()) {
if (mi.isReversal())
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), invMatchAmt.setScale(2, RoundingMode.HALF_UP), "MatchInv incorrect amount posted ");
else
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), invMatchAmt.setScale(2, RoundingMode.HALF_UP), "MatchInv incorrect amount posted ");
assertEquals(mi.getQty().negate(), fa.getQty(), "Accounting fact quantity incorrect");
} }
} }
@Test
public void testReversalPostingWithZeroOnHand() {
MBPartner bpartner = MBPartner.get(Env.getCtx(), DictionaryIDs.C_BPartner.TREE_FARM.id); // Tree Farm Inc.
MProduct product = null;
MClient client = MClient.get(Env.getCtx());
MAcctSchema as = client.getAcctSchema();
Timestamp today = TimeUtil.getDay(null);
try {
product = new MProduct(Env.getCtx(), 0, null);
product.setM_Product_Category_ID(DictionaryIDs.M_Product_Category.STANDARD.id);
product.setName("testReversalPostingWithZeroOnHand");
product.setProductType(MProduct.PRODUCTTYPE_Item);
product.setIsStocked(true);
product.setIsSold(true);
product.setIsPurchased(true);
product.setC_UOM_ID(DictionaryIDs.C_UOM.EACH.id);
product.setC_TaxCategory_ID(DictionaryIDs.C_TaxCategory.STANDARD.id);
product.saveEx();
MPriceListVersion plv = MPriceList.get(DictionaryIDs.M_PriceList.PURCHASE.id).getPriceListVersion(null);
MProductPrice pp = new MProductPrice(Env.getCtx(), 0, getTrxName());
pp.setM_PriceList_Version_ID(plv.getM_PriceList_Version_ID());
pp.setM_Product_ID(product.get_ID());
BigDecimal orderPrice = new BigDecimal("2.00");
pp.setPriceStd(orderPrice);
pp.setPriceList(orderPrice);
pp.saveEx();
int purchaseId = DictionaryIDs.M_PriceList.PURCHASE.id; // Purchase Price List
MOrder order = new MOrder(Env.getCtx(), 0, getTrxName());
order.setBPartner(bpartner);
order.setIsSOTrx(false);
order.setC_DocTypeTarget_ID();
order.setM_PriceList_ID(purchaseId);
order.setDocStatus(DocAction.STATUS_Drafted);
order.setDocAction(DocAction.ACTION_Complete);
order.saveEx();
MOrderLine orderLine = new MOrderLine(order);
orderLine.setLine(10);
orderLine.setProduct(product);
orderLine.setQty(BigDecimal.TEN);
orderLine.saveEx();
ProcessInfo info = MWorkflow.runDocumentActionWorkflow(order, DocAction.ACTION_Complete);
order.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Completed, order.getDocStatus());
MInOut receipt = new MInOut(order, DictionaryIDs.C_DocType.MM_RECEIPT.id, order.getDateOrdered()); // MM Receipt
receipt.saveEx();
MInOutLine receiptLine = new MInOutLine(receipt);
receiptLine.setC_OrderLine_ID(orderLine.get_ID());
receiptLine.setLine(10);
receiptLine.setProduct(product);
receiptLine.setQty(orderLine.getQtyOrdered());
MWarehouse wh = MWarehouse.get(Env.getCtx(), receipt.getM_Warehouse_ID());
int M_Locator_ID = wh.getDefaultLocator().getM_Locator_ID();
receiptLine.setM_Locator_ID(M_Locator_ID);
receiptLine.saveEx();
info = MWorkflow.runDocumentActionWorkflow(receipt, DocAction.ACTION_Complete);
receipt.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Completed, receipt.getDocStatus());
if (!receipt.isPosted()) {
String error = DocumentEngine.postImmediate(Env.getCtx(), receipt.getAD_Client_ID(), MInOut.Table_ID, receipt.get_ID(), false, getTrxName());
assertTrue(error == null);
}
receipt.load(getTrxName());
assertTrue(receipt.isPosted());
//customer shipment
MOrder salesOrder = new MOrder(Env.getCtx(), 0, getTrxName());
salesOrder.setBPartner(MBPartner.get(Env.getCtx(), DictionaryIDs.C_BPartner.JOE_BLOCK.id));
salesOrder.setC_DocTypeTarget_ID(MOrder.DocSubTypeSO_Standard);
salesOrder.setDeliveryRule(MOrder.DELIVERYRULE_CompleteOrder);
salesOrder.setDocStatus(DocAction.STATUS_Drafted);
salesOrder.setDocAction(DocAction.ACTION_Complete);
salesOrder.setDatePromised(today);
salesOrder.saveEx();
MOrderLine salesLine1 = new MOrderLine(salesOrder);
salesLine1.setLine(10);
salesLine1.setProduct(product);
salesLine1.setQty(orderLine.getQtyOrdered());
salesLine1.setDatePromised(today);
salesLine1.saveEx();
info = MWorkflow.runDocumentActionWorkflow(salesOrder, DocAction.ACTION_Complete);
salesOrder.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Completed, salesOrder.getDocStatus(), "Unexpected Document Status");
MInOut shipment = new MInOut(salesOrder, DictionaryIDs.C_DocType.MM_SHIPMENT.id, salesOrder.getDateOrdered());
shipment.setDocStatus(DocAction.STATUS_Drafted);
shipment.setDocAction(DocAction.ACTION_Complete);
shipment.saveEx();
MInOutLine shipmentLine = new MInOutLine(shipment);
shipmentLine.setOrderLine(salesLine1, 0, orderLine.getQtyOrdered());
shipmentLine.setQty(orderLine.getQtyOrdered());
shipmentLine.saveEx();
info = MWorkflow.runDocumentActionWorkflow(shipment, DocAction.ACTION_Complete);
assertFalse(info.isError(), info.getSummary());
shipment.load(getTrxName());
assertEquals(DocAction.STATUS_Completed, shipment.getDocStatus(), "Unexpected Document Status");
MInvoice invoice = new MInvoice(receipt, receipt.getMovementDate());
invoice.setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_APInvoice);
invoice.setDocStatus(DocAction.STATUS_Drafted);
invoice.setDocAction(DocAction.ACTION_Complete);
invoice.saveEx();
//MR invoice
MInvoiceLine invoiceLine = new MInvoiceLine(invoice);
invoiceLine.setM_InOutLine_ID(receiptLine.get_ID());
invoiceLine.setLine(10);
invoiceLine.setProduct(product);
invoiceLine.setQty(orderLine.getQtyOrdered());
invoiceLine.setPrice(orderPrice.add(BigDecimal.ONE));
invoiceLine.saveEx();
info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Complete);
invoice.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Completed, invoice.getDocStatus());
if (!invoice.isPosted()) {
String error = DocumentEngine.postImmediate(Env.getCtx(), invoice.getAD_Client_ID(), MInvoice.Table_ID, invoice.get_ID(), false, getTrxName());
assertTrue(error == null, error);
}
BigDecimal invMatchAmt = invoiceLine.getMatchedQty().multiply(invoiceLine.getPriceActual()).setScale(as.getStdPrecision(), RoundingMode.HALF_UP);
BigDecimal poMatchAmt = invoiceLine.getMatchedQty().multiply(orderLine.getPriceActual()).setScale(as.getStdPrecision(), RoundingMode.HALF_UP);
invoice.load(getTrxName());
assertTrue(invoice.isPosted());
//reverse MR invoice
info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Reverse_Correct);
invoice.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Reversed, invoice.getDocStatus());
MInvoice reversalInvoice = new MInvoice(Env.getCtx(), invoice.getReversal_ID(), getTrxName());
if (!reversalInvoice.isPosted()) {
String error = DocumentEngine.postImmediate(Env.getCtx(), reversalInvoice.getAD_Client_ID(), MInvoice.Table_ID, invoice.get_ID(), false, getTrxName());
assertTrue(error == null, error);
}
MMatchInv[] miList = MMatchInv.getInvoiceLine(Env.getCtx(), invoiceLine.get_ID(), getTrxName());
assertEquals(2, miList.length);
for (MMatchInv mi : miList) {
if (!mi.isPosted()) {
String error = DocumentEngine.postImmediate(Env.getCtx(), mi.getAD_Client_ID(), MMatchInv.Table_ID, mi.get_ID(), false, getTrxName());
assertTrue(error == null, error);
}
mi.load(getTrxName());
assertTrue(mi.isPosted());
MMatchInv mir = new MMatchInv(Env.getCtx(), mi.getReversal_ID(), getTrxName());
if (!mir.isPosted()) {
String error = DocumentEngine.postImmediate(Env.getCtx(), mir.getAD_Client_ID(), MMatchInv.Table_ID, mir.get_ID(), false, getTrxName());
assertTrue(error == null, error);
}
mir.load(getTrxName());
assertTrue(mir.isPosted());
Doc doc = DocManager.getDocument(as, MMatchInv.Table_ID, mi.get_ID(), getTrxName());
doc.setC_BPartner_ID(mi.getC_InvoiceLine().getC_Invoice().getC_BPartner_ID());
MAccount acctNIR = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as);
ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
MAccount acctIPV = pc.getAccount(ProductCost.ACCTTYPE_P_AverageCostVariance, as);
Query query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, poMatchAmt, 2, !mi.isReversal(), mi.getQty()),
new FactAcct(acctInvClr, invMatchAmt, 2, mi.isReversal(), mi.getQty().negate()),
new FactAcct(acctIPV, invMatchAmt.subtract(poMatchAmt), 2, !mi.isReversal()));
assertFactAcctEntries(factAccts, expected);
}
} finally {
rollback();
if (product != null) {
product.set_TrxName(null);
product.deleteEx(true);
}
} }
} }
} }

View File

@ -27,12 +27,17 @@ package org.idempiere.test.base;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional;
import org.compiere.acct.Doc; import org.compiere.acct.Doc;
import org.compiere.acct.DocManager; import org.compiere.acct.DocManager;
@ -42,6 +47,8 @@ import org.compiere.model.MBPartner;
import org.compiere.model.MClient; import org.compiere.model.MClient;
import org.compiere.model.MConversionRate; import org.compiere.model.MConversionRate;
import org.compiere.model.MCost; import org.compiere.model.MCost;
import org.compiere.model.MCostElement;
import org.compiere.model.MCurrency;
import org.compiere.model.MDocType; import org.compiere.model.MDocType;
import org.compiere.model.MFactAcct; import org.compiere.model.MFactAcct;
import org.compiere.model.MInOut; import org.compiere.model.MInOut;
@ -53,19 +60,26 @@ import org.compiere.model.MInvoiceLine;
import org.compiere.model.MMatchInv; import org.compiere.model.MMatchInv;
import org.compiere.model.MOrder; import org.compiere.model.MOrder;
import org.compiere.model.MOrderLine; import org.compiere.model.MOrderLine;
import org.compiere.model.MPriceList;
import org.compiere.model.MPriceListVersion;
import org.compiere.model.MProduct; import org.compiere.model.MProduct;
import org.compiere.model.MProductCategory; import org.compiere.model.MProductCategory;
import org.compiere.model.MProductCategoryAcct; import org.compiere.model.MProductCategoryAcct;
import org.compiere.model.MProductPrice;
import org.compiere.model.MWarehouse; import org.compiere.model.MWarehouse;
import org.compiere.model.ProductCost; import org.compiere.model.ProductCost;
import org.compiere.model.Query; import org.compiere.model.Query;
import org.compiere.process.DocAction; import org.compiere.process.DocAction;
import org.compiere.process.DocumentEngine; import org.compiere.process.DocumentEngine;
import org.compiere.process.ProcessInfo; import org.compiere.process.ProcessInfo;
import org.compiere.util.CacheMgt;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.compiere.util.TimeUtil;
import org.compiere.wf.MWorkflow; import org.compiere.wf.MWorkflow;
import org.idempiere.test.AbstractTestCase; import org.idempiere.test.AbstractTestCase;
import org.idempiere.test.ConversionRateHelper;
import org.idempiere.test.DictionaryIDs; import org.idempiere.test.DictionaryIDs;
import org.idempiere.test.FactAcct;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Isolated; import org.junit.jupiter.api.parallel.Isolated;
@ -240,21 +254,13 @@ public class MatchInvTestIsolated extends AbstractTestCase {
MAccount acctIPV = pc.getAccount(ProductCost.ACCTTYPE_P_IPV, as); MAccount acctIPV = pc.getAccount(ProductCost.ACCTTYPE_P_IPV, as);
int C_AcctSchema_ID = as.getC_AcctSchema_ID(); int C_AcctSchema_ID = as.getC_AcctSchema_ID();
String whereClause2 = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID Query query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), C_AcctSchema_ID, getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + C_AcctSchema_ID;
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause2, getTrxName());
BigDecimal invMatchAmt = invoiceLine.getMatchedQty().multiply(invoiceLine.getPriceActual()).setScale(as.getStdPrecision(), RoundingMode.HALF_UP); BigDecimal invMatchAmt = invoiceLine.getMatchedQty().multiply(invoiceLine.getPriceActual()).setScale(as.getStdPrecision(), RoundingMode.HALF_UP);
mulchCost = mulchCost.setScale(as.getStdPrecision(), RoundingMode.HALF_UP); mulchCost = mulchCost.setScale(as.getStdPrecision(), RoundingMode.HALF_UP);
for (int id : ids) { List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, mulchCost, 2, true), new FactAcct(acctInvClr, invMatchAmt, 2, false),
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); new FactAcct(acctIPV, invMatchAmt.subtract(mulchCost), 2, true));
if (fa.getAccount_ID() == acctNIR.getAccount_ID()) assertFactAcctEntries(factAccts, expected);
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), mulchCost.setScale(2, RoundingMode.HALF_UP), "");
else if (fa.getAccount_ID() == acctInvClr.getAccount_ID())
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), invMatchAmt.setScale(2, RoundingMode.HALF_UP), "");
else if (fa.getAccount_ID() == acctIPV.getAccount_ID())
assertEquals(fa.getAmtAcctDr().subtract(fa.getAmtAcctCr()).setScale(2, RoundingMode.HALF_UP), invMatchAmt.subtract(mulchCost).setScale(2, RoundingMode.HALF_UP), "");
}
} }
} finally { } finally {
getTrx().rollback(); getTrx().rollback();
@ -263,4 +269,617 @@ public class MatchInvTestIsolated extends AbstractTestCase {
category.deleteEx(true); category.deleteEx(true);
} }
} }
/**
* Test Average PO Cost and Invoice Price Variance posting
*/
@Test
public void testAverageCostingIPV() {
MProduct product = null;
MClient client = MClient.get(Env.getCtx());
MAcctSchema as = client.getAcctSchema();
assertEquals(as.getCostingMethod(), MCostElement.COSTINGMETHOD_AveragePO, "Default costing method not Average PO");
try {
product = new MProduct(Env.getCtx(), 0, null);
product.setM_Product_Category_ID(DictionaryIDs.M_Product_Category.STANDARD.id);
product.setName("testAverageCostingIPV");
product.setProductType(MProduct.PRODUCTTYPE_Item);
product.setIsStocked(true);
product.setIsSold(true);
product.setIsPurchased(true);
product.setC_UOM_ID(DictionaryIDs.C_UOM.EACH.id);
product.setC_TaxCategory_ID(DictionaryIDs.C_TaxCategory.STANDARD.id);
product.saveEx();
MPriceListVersion plv = MPriceList.get(DictionaryIDs.M_PriceList.PURCHASE.id).getPriceListVersion(null);
MProductPrice pp = new MProductPrice(Env.getCtx(), 0, getTrxName());
pp.setM_PriceList_Version_ID(plv.getM_PriceList_Version_ID());
pp.setM_Product_ID(product.get_ID());
BigDecimal orderPrice = new BigDecimal("2.00");
pp.setPriceStd(orderPrice);
pp.setPriceList(orderPrice);
pp.saveEx();
int purchaseId = DictionaryIDs.M_PriceList.PURCHASE.id; // Purchase Price List
MBPartner bpartner = MBPartner.get(Env.getCtx(), DictionaryIDs.C_BPartner.SEED_FARM.id);
MOrder order = new MOrder(Env.getCtx(), 0, getTrxName());
order.setBPartner(bpartner);
order.setIsSOTrx(false);
order.setC_DocTypeTarget_ID();
order.setM_PriceList_ID(purchaseId);
order.setDocStatus(DocAction.STATUS_Drafted);
order.setDocAction(DocAction.ACTION_Complete);
order.saveEx();
MOrderLine orderLine = new MOrderLine(order);
orderLine.setLine(10);
orderLine.setProduct(product);
orderLine.setQty(BigDecimal.TEN);
orderLine.saveEx();
ProcessInfo info = MWorkflow.runDocumentActionWorkflow(order, DocAction.ACTION_Complete);
order.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Completed, order.getDocStatus());
MInOut receipt = new MInOut(order, 122, order.getDateOrdered()); // MM Receipt
receipt.saveEx();
MInOutLine receiptLine = new MInOutLine(receipt);
receiptLine.setC_OrderLine_ID(orderLine.get_ID());
receiptLine.setLine(10);
receiptLine.setProduct(product);
receiptLine.setQty(BigDecimal.TEN);
MWarehouse wh = MWarehouse.get(Env.getCtx(), receipt.getM_Warehouse_ID());
int M_Locator_ID = wh.getDefaultLocator().getM_Locator_ID();
receiptLine.setM_Locator_ID(M_Locator_ID);
receiptLine.saveEx();
info = MWorkflow.runDocumentActionWorkflow(receipt, DocAction.ACTION_Complete);
receipt.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Completed, receipt.getDocStatus());
if (!receipt.isPosted()) {
String error = DocumentEngine.postImmediate(Env.getCtx(), receipt.getAD_Client_ID(), MInOut.Table_ID, receipt.get_ID(), false, getTrxName());
assertTrue(error == null);
}
receipt.load(getTrxName());
assertTrue(receipt.isPosted());
product.set_TrxName(getTrxName());
MCost cost = product.getCostingRecord(as, getAD_Org_ID(), 0, as.getCostingMethod());
assertNotNull(cost, "No MCost record found");
assertEquals(orderPrice, cost.getCurrentCostPrice().setScale(2, RoundingMode.HALF_UP), "Unexpected current cost price");
MInvoice invoice = new MInvoice(receipt, receipt.getMovementDate());
invoice.setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_APInvoice);
invoice.setDocStatus(DocAction.STATUS_Drafted);
invoice.setDocAction(DocAction.ACTION_Complete);
invoice.saveEx();
MInvoiceLine invoiceLine = new MInvoiceLine(invoice);
invoiceLine.setM_InOutLine_ID(receiptLine.get_ID());
invoiceLine.setLine(10);
invoiceLine.setProduct(product);
invoiceLine.setQty(BigDecimal.TEN);
BigDecimal invoicePrice = new BigDecimal("2.50");
invoiceLine.setPrice(invoicePrice);
invoiceLine.saveEx();
info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Complete);
invoice.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Completed, invoice.getDocStatus());
if (!invoice.isPosted()) {
String error = DocumentEngine.postImmediate(Env.getCtx(), invoice.getAD_Client_ID(), MInvoice.Table_ID, invoice.get_ID(), false, getTrxName());
assertTrue(error == null);
}
invoice.load(getTrxName());
assertTrue(invoice.isPosted());
MMatchInv[] miList = MMatchInv.getInvoiceLine(Env.getCtx(), invoiceLine.get_ID(), getTrxName());
for (MMatchInv mi : miList) {
if (!mi.isPosted()) {
String error = DocumentEngine.postImmediate(Env.getCtx(), mi.getAD_Client_ID(), MMatchInv.Table_ID, mi.get_ID(), false, getTrxName());
assertTrue(error == null);
}
mi.load(getTrxName());
assertTrue(mi.isPosted());
cost = product.getCostingRecord(as, getAD_Org_ID(), 0, as.getCostingMethod());
assertNotNull(cost, "No MCost record found");
assertEquals(invoicePrice, cost.getCurrentCostPrice().setScale(2, RoundingMode.HALF_UP), "Unexpected current cost price");
ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
MAccount acctAsset = pc.getAccount(ProductCost.ACCTTYPE_P_Asset, as);
Doc doc = DocManager.getDocument(as, MInvoice.Table_ID, invoice.get_ID(), getTrxName());
MAccount nirAccount = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as);
int C_AcctSchema_ID = as.getC_AcctSchema_ID();
Query query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), C_AcctSchema_ID, getTrxName());
List<MFactAcct> factAccts = query.list();
BigDecimal ipvAmt = invoicePrice.subtract(orderPrice).multiply(BigDecimal.TEN);
List<FactAcct> expected = Arrays.asList(new FactAcct(acctAsset, ipvAmt, 2, true),
new FactAcct(nirAccount, orderPrice.multiply(BigDecimal.TEN), 2, true),
new FactAcct(acctInvClr, invoicePrice.multiply(BigDecimal.TEN), 2, false));
assertFactAcctEntries(factAccts, expected);
}
} finally {
rollback();
if (product != null) {
product.set_TrxName(null);
product.deleteEx(true);
}
}
}
/**
* Test Average PO Cost and Invoice Price Variance posting (after customer shipment)
*/
@Test
public void testAverageCostingIPVAfterShipment() {
MProduct product = null;
MClient client = MClient.get(Env.getCtx());
MAcctSchema[] ass = MAcctSchema.getClientAcctSchema(Env.getCtx(), Env.getAD_Client_ID(Env.getCtx()));
List<MAcctSchema> allowNegatives = new ArrayList<MAcctSchema>();
Arrays.stream(ass).forEach(e -> {
MAcctSchema copy = MAcctSchema.getCopy(Env.getCtx(), e.getC_AcctSchema_ID(), null);
if (copy.isAllowNegativePosting())
{
copy.setIsAllowNegativePosting(false);
copy.saveEx();
allowNegatives.add(copy);
}
});
if (allowNegatives.size() > 0)
CacheMgt.get().reset(MAcctSchema.Table_Name);
ass = MAcctSchema.getClientAcctSchema(Env.getCtx(), Env.getAD_Client_ID(Env.getCtx()));
MAcctSchema as = client.getAcctSchema();
assertEquals(as.getCostingMethod(), MCostElement.COSTINGMETHOD_AveragePO, "Default costing method not Average PO");
MCurrency usd = MCurrency.get(DictionaryIDs.C_Currency.USD.id);
MCurrency euro = MCurrency.get(DictionaryIDs.C_Currency.EUR.id);
int C_ConversionType_ID = DictionaryIDs.C_ConversionType.SPOT.id;
Timestamp today = TimeUtil.getDay(null);
Timestamp tomorrow = TimeUtil.addDays(today, 1);
MConversionRate cr1 = ConversionRateHelper.createConversionRate(usd.getC_Currency_ID(), euro.getC_Currency_ID(), C_ConversionType_ID, today, new BigDecimal("0.91"), true);
MConversionRate cr2 = ConversionRateHelper.createConversionRate(usd.getC_Currency_ID(), euro.getC_Currency_ID(), C_ConversionType_ID, tomorrow, new BigDecimal("0.85"), true);
try {
product = new MProduct(Env.getCtx(), 0, null);
product.setM_Product_Category_ID(DictionaryIDs.M_Product_Category.STANDARD.id);
product.setName("testAverageCostingIPVAfterShipment");
product.setProductType(MProduct.PRODUCTTYPE_Item);
product.setIsStocked(true);
product.setIsSold(true);
product.setIsPurchased(true);
product.setC_UOM_ID(DictionaryIDs.C_UOM.EACH.id);
product.setC_TaxCategory_ID(DictionaryIDs.C_TaxCategory.STANDARD.id);
product.saveEx();
MPriceListVersion plv = MPriceList.get(DictionaryIDs.M_PriceList.PURCHASE.id).getPriceListVersion(null);
MProductPrice pp = new MProductPrice(Env.getCtx(), 0, getTrxName());
pp.setM_PriceList_Version_ID(plv.getM_PriceList_Version_ID());
pp.setM_Product_ID(product.get_ID());
BigDecimal orderPrice = new BigDecimal("2.00");
pp.setPriceStd(orderPrice);
pp.setPriceList(orderPrice);
pp.saveEx();
//PO and MR
int purchaseId = DictionaryIDs.M_PriceList.PURCHASE.id; // Purchase Price List
MBPartner bpartner = MBPartner.get(Env.getCtx(), DictionaryIDs.C_BPartner.SEED_FARM.id);
MOrder order = new MOrder(Env.getCtx(), 0, getTrxName());
order.setBPartner(bpartner);
order.setIsSOTrx(false);
order.setC_DocTypeTarget_ID();
order.setM_PriceList_ID(purchaseId);
order.setDocStatus(DocAction.STATUS_Drafted);
order.setDocAction(DocAction.ACTION_Complete);
order.saveEx();
MOrderLine orderLine = new MOrderLine(order);
orderLine.setLine(10);
orderLine.setProduct(product);
orderLine.setQty(BigDecimal.TEN);
orderLine.saveEx();
ProcessInfo info = MWorkflow.runDocumentActionWorkflow(order, DocAction.ACTION_Complete);
order.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Completed, order.getDocStatus());
MInOut receipt = new MInOut(order, 122, order.getDateOrdered()); // MM Receipt
receipt.saveEx();
MInOutLine receiptLine = new MInOutLine(receipt);
receiptLine.setC_OrderLine_ID(orderLine.get_ID());
receiptLine.setLine(10);
receiptLine.setProduct(product);
receiptLine.setQty(BigDecimal.TEN);
MWarehouse wh = MWarehouse.get(Env.getCtx(), receipt.getM_Warehouse_ID());
int M_Locator_ID = wh.getDefaultLocator().getM_Locator_ID();
receiptLine.setM_Locator_ID(M_Locator_ID);
receiptLine.saveEx();
info = MWorkflow.runDocumentActionWorkflow(receipt, DocAction.ACTION_Complete);
receipt.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Completed, receipt.getDocStatus());
if (!receipt.isPosted()) {
String error = DocumentEngine.postImmediate(Env.getCtx(), receipt.getAD_Client_ID(), MInOut.Table_ID, receipt.get_ID(), false, getTrxName());
assertTrue(error == null);
}
receipt.load(getTrxName());
assertTrue(receipt.isPosted());
product.set_TrxName(getTrxName());
MCost cost = product.getCostingRecord(as, getAD_Org_ID(), 0, as.getCostingMethod());
assertNotNull(cost, "No MCost record found");
assertEquals(orderPrice, cost.getCurrentCostPrice().setScale(2, RoundingMode.HALF_UP), "Unexpected current cost price");
//customer shipment
MOrder salesOrder = new MOrder(Env.getCtx(), 0, getTrxName());
salesOrder.setBPartner(MBPartner.get(Env.getCtx(), DictionaryIDs.C_BPartner.JOE_BLOCK.id));
salesOrder.setC_DocTypeTarget_ID(MOrder.DocSubTypeSO_Standard);
salesOrder.setDeliveryRule(MOrder.DELIVERYRULE_CompleteOrder);
salesOrder.setDocStatus(DocAction.STATUS_Drafted);
salesOrder.setDocAction(DocAction.ACTION_Complete);
salesOrder.setDatePromised(today);
salesOrder.saveEx();
BigDecimal salesQty = new BigDecimal("5");
MOrderLine salesLine1 = new MOrderLine(salesOrder);
salesLine1.setLine(10);
salesLine1.setProduct(product);
salesLine1.setQty(salesQty);
salesLine1.setDatePromised(today);
salesLine1.saveEx();
info = MWorkflow.runDocumentActionWorkflow(salesOrder, DocAction.ACTION_Complete);
salesOrder.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Completed, salesOrder.getDocStatus(), "Unexpected Document Status");
MInOut shipment = new MInOut(salesOrder, DictionaryIDs.C_DocType.MM_SHIPMENT.id, salesOrder.getDateOrdered());
shipment.setDocStatus(DocAction.STATUS_Drafted);
shipment.setDocAction(DocAction.ACTION_Complete);
shipment.saveEx();
MInOutLine shipmentLine = new MInOutLine(shipment);
shipmentLine.setOrderLine(salesLine1, 0, salesQty);
shipmentLine.setQty(salesQty);
shipmentLine.saveEx();
info = MWorkflow.runDocumentActionWorkflow(shipment, DocAction.ACTION_Complete);
assertFalse(info.isError(), info.getSummary());
shipment.load(getTrxName());
assertEquals(DocAction.STATUS_Completed, shipment.getDocStatus(), "Unexpected Document Status");
//MR invoice
MInvoice invoice = new MInvoice(receipt, receipt.getMovementDate());
invoice.setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_APInvoice);
invoice.setDocStatus(DocAction.STATUS_Drafted);
invoice.setDocAction(DocAction.ACTION_Complete);
invoice.saveEx();
MInvoiceLine invoiceLine = new MInvoiceLine(invoice);
invoiceLine.setM_InOutLine_ID(receiptLine.get_ID());
invoiceLine.setLine(10);
invoiceLine.setProduct(product);
invoiceLine.setQty(BigDecimal.TEN);
BigDecimal invoicePrice = new BigDecimal("2.50");
invoiceLine.setPrice(invoicePrice);
invoiceLine.saveEx();
info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Complete);
invoice.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Completed, invoice.getDocStatus());
if (!invoice.isPosted()) {
String error = DocumentEngine.postImmediate(Env.getCtx(), invoice.getAD_Client_ID(), MInvoice.Table_ID, invoice.get_ID(), false, getTrxName());
assertTrue(error == null);
}
invoice.load(getTrxName());
assertTrue(invoice.isPosted());
MMatchInv[] miList = MMatchInv.getInvoiceLine(Env.getCtx(), invoiceLine.get_ID(), getTrxName());
for (MMatchInv mi : miList) {
if (!mi.isPosted()) {
String error = DocumentEngine.postImmediate(Env.getCtx(), mi.getAD_Client_ID(), MMatchInv.Table_ID, mi.get_ID(), false, getTrxName());
assertTrue(error == null);
}
mi.load(getTrxName());
assertTrue(mi.isPosted());
cost = product.getCostingRecord(as, getAD_Org_ID(), 0, as.getCostingMethod());
assertNotNull(cost, "No MCost record found");
assertEquals(invoicePrice, cost.getCurrentCostPrice().setScale(2, RoundingMode.HALF_UP), "Unexpected current cost price");
ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
MAccount acctAsset = pc.getAccount(ProductCost.ACCTTYPE_P_Asset, as);
MAccount varianceAccount = pc.getAccount(ProductCost.ACCTTYPE_P_AverageCostVariance, as);
Doc doc = DocManager.getDocument(as, MInvoice.Table_ID, invoice.get_ID(), getTrxName());
MAccount nirAccount = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as);
int C_AcctSchema_ID = as.getC_AcctSchema_ID();
Query query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), C_AcctSchema_ID, getTrxName());
List<MFactAcct> factAccts = query.list();
BigDecimal stockBalance = BigDecimal.TEN.subtract(salesQty);
BigDecimal assetAmt = invoicePrice.subtract(orderPrice).multiply(stockBalance);
List<FactAcct> expected = Arrays.asList(new FactAcct(acctAsset, assetAmt, 2, true),
new FactAcct(varianceAccount, invoicePrice.subtract(orderPrice).multiply(BigDecimal.TEN.subtract(stockBalance)), 2, true),
new FactAcct(nirAccount, orderPrice.multiply(BigDecimal.TEN), 2, true),
new FactAcct(acctInvClr, invoicePrice.multiply(BigDecimal.TEN), 2, false));
assertFactAcctEntries(factAccts, expected);
}
//test reversal posting
Env.setContext(Env.getCtx(), Env.DATE, tomorrow);
info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Reverse_Accrual);
invoice.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Reversed, invoice.getDocStatus());
assertTrue(invoice.getReversal_ID() > 0, "No reversal invoice id");
MInvoice reversalInvoice = new MInvoice(Env.getCtx(), invoice.getReversal_ID(), getTrxName());
assertEquals(invoice.getReversal_ID(), reversalInvoice.get_ID(), "Failed to load reversal invoice");
if (!reversalInvoice.isPosted()) {
String error = DocumentEngine.postImmediate(Env.getCtx(), reversalInvoice.getAD_Client_ID(), MInvoice.Table_ID, reversalInvoice.get_ID(), false, getTrxName());
assertTrue(error == null, error);
}
reversalInvoice.load(getTrxName());
assertTrue(reversalInvoice.isPosted());
for (MMatchInv mi : miList) {
mi.load(getTrxName());
Query query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), as.get_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.getReversal_ID(), as.get_ID(), getTrxName());
List<MFactAcct> rFactAccts = query.list();
ArrayList<FactAcct> expected = new ArrayList<FactAcct>();
for(MFactAcct factAcct : factAccts) {
MAccount acct = MAccount.get(factAcct, getTrxName());
if (factAcct.getAmtAcctDr().signum() != 0) {
expected.add(new FactAcct(acct, factAcct.getAmtAcctDr(), 2, false));
} else if (factAcct.getAmtAcctCr().signum() != 0) {
expected.add(new FactAcct(acct, factAcct.getAmtAcctCr(), 2, true));
}
}
assertFactAcctEntries(rFactAccts, expected);
Optional<MAcctSchema> optional = Arrays.stream(ass).filter(e -> e.getC_AcctSchema_ID() != as.get_ID()).findFirst();
if (optional.isPresent()) {
MAcctSchema as2 = optional.get();
query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), as2.get_ID(), getTrxName());
factAccts = query.list();
query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.getReversal_ID(), as2.get_ID(), getTrxName());
rFactAccts = query.list();
expected = new ArrayList<FactAcct>();
for(MFactAcct factAcct : factAccts) {
MAccount acct = MAccount.get(factAcct, getTrxName());
if (factAcct.getAmtAcctDr().signum() != 0) {
expected.add(new FactAcct(acct, factAcct.getAmtAcctDr(), 2, false));
} else if (factAcct.getAmtAcctCr().signum() != 0) {
expected.add(new FactAcct(acct, factAcct.getAmtAcctCr(), 2, true));
}
}
assertFactAcctEntries(rFactAccts, expected);
}
}
//assert reversal invoice posting
Query query = MFactAcct.createRecordIdQuery(MInvoice.Table_ID, invoice.get_ID(), as.get_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
query = MFactAcct.createRecordIdQuery(MInvoice.Table_ID, invoice.getReversal_ID(), as.get_ID(), getTrxName());
List<MFactAcct> rFactAccts = query.list();
ArrayList<FactAcct> expected = new ArrayList<FactAcct>();
for(MFactAcct factAcct : factAccts) {
MAccount acct = MAccount.get(factAcct, getTrxName());
if (factAcct.getAmtAcctDr().signum() != 0) {
expected.add(new FactAcct(acct, factAcct.getAmtAcctDr(), 2, false));
} else if (factAcct.getAmtAcctCr().signum() != 0) {
expected.add(new FactAcct(acct, factAcct.getAmtAcctCr(), 2, true));
}
}
assertFactAcctEntries(rFactAccts, expected);
Optional<MAcctSchema> optional = Arrays.stream(ass).filter(e -> e.getC_AcctSchema_ID() != as.get_ID()).findFirst();
if (optional.isPresent()) {
MAcctSchema as2 = optional.get();
query = MFactAcct.createRecordIdQuery(MInvoice.Table_ID, invoice.get_ID(), as2.get_ID(), getTrxName());
factAccts = query.list();
query = MFactAcct.createRecordIdQuery(MInvoice.Table_ID, invoice.getReversal_ID(), as2.get_ID(), getTrxName());
rFactAccts = query.list();
expected = new ArrayList<FactAcct>();
for(MFactAcct factAcct : factAccts) {
MAccount acct = MAccount.get(factAcct, getTrxName());
if (factAcct.getAmtAcctDr().signum() != 0) {
expected.add(new FactAcct(acct, factAcct.getAmtAcctDr(), 2, false));
} else if (factAcct.getAmtAcctCr().signum() != 0) {
expected.add(new FactAcct(acct, factAcct.getAmtAcctCr(), 2, true));
}
}
assertFactAcctEntries(rFactAccts, expected);
}
} finally {
rollback();
if (product != null) {
product.set_TrxName(null);
product.deleteEx(true);
}
ConversionRateHelper.deleteConversionRate(cr1);
ConversionRateHelper.deleteConversionRate(cr2);
if (allowNegatives.size() > 0) {
allowNegatives.forEach(e -> {
e.setIsAllowNegativePosting(true);
e.saveEx();
});
}
}
}
/**
* Test Average PO Cost and Invoice Price Variance posting for partial MR
*/
@Test
public void testAverageCostingIPVPartialMR() {
MProduct product = null;
MClient client = MClient.get(Env.getCtx());
MAcctSchema as = client.getAcctSchema();
assertEquals(as.getCostingMethod(), MCostElement.COSTINGMETHOD_AveragePO, "Default costing method not Average PO");
try {
product = new MProduct(Env.getCtx(), 0, null);
product.setM_Product_Category_ID(DictionaryIDs.M_Product_Category.STANDARD.id);
product.setName("testAverageCostingIPVPartialMR");
product.setProductType(MProduct.PRODUCTTYPE_Item);
product.setIsStocked(true);
product.setIsSold(true);
product.setIsPurchased(true);
product.setC_UOM_ID(DictionaryIDs.C_UOM.EACH.id);
product.setC_TaxCategory_ID(DictionaryIDs.C_TaxCategory.STANDARD.id);
product.saveEx();
MPriceListVersion plv = MPriceList.get(DictionaryIDs.M_PriceList.PURCHASE.id).getPriceListVersion(null);
MProductPrice pp = new MProductPrice(Env.getCtx(), 0, getTrxName());
pp.setM_PriceList_Version_ID(plv.getM_PriceList_Version_ID());
pp.setM_Product_ID(product.get_ID());
BigDecimal orderPrice = new BigDecimal("2.00");
pp.setPriceStd(orderPrice);
pp.setPriceList(orderPrice);
pp.saveEx();
int purchaseId = DictionaryIDs.M_PriceList.PURCHASE.id; // Purchase Price List
MBPartner bpartner = MBPartner.get(Env.getCtx(), DictionaryIDs.C_BPartner.SEED_FARM.id);
MOrder order = new MOrder(Env.getCtx(), 0, getTrxName());
order.setBPartner(bpartner);
order.setIsSOTrx(false);
order.setC_DocTypeTarget_ID();
order.setM_PriceList_ID(purchaseId);
order.setDocStatus(DocAction.STATUS_Drafted);
order.setDocAction(DocAction.ACTION_Complete);
order.saveEx();
MOrderLine orderLine = new MOrderLine(order);
orderLine.setLine(10);
orderLine.setProduct(product);
orderLine.setQty(BigDecimal.TEN);
orderLine.saveEx();
ProcessInfo info = MWorkflow.runDocumentActionWorkflow(order, DocAction.ACTION_Complete);
order.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Completed, order.getDocStatus());
//partial MR
MInOut receipt = new MInOut(order, 122, order.getDateOrdered()); // MM Receipt
receipt.saveEx();
BigDecimal mrQty = new BigDecimal("5");
MInOutLine receiptLine = new MInOutLine(receipt);
receiptLine.setC_OrderLine_ID(orderLine.get_ID());
receiptLine.setLine(10);
receiptLine.setProduct(product);
receiptLine.setQty(mrQty);
MWarehouse wh = MWarehouse.get(Env.getCtx(), receipt.getM_Warehouse_ID());
int M_Locator_ID = wh.getDefaultLocator().getM_Locator_ID();
receiptLine.setM_Locator_ID(M_Locator_ID);
receiptLine.saveEx();
info = MWorkflow.runDocumentActionWorkflow(receipt, DocAction.ACTION_Complete);
receipt.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Completed, receipt.getDocStatus());
if (!receipt.isPosted()) {
String error = DocumentEngine.postImmediate(Env.getCtx(), receipt.getAD_Client_ID(), MInOut.Table_ID, receipt.get_ID(), false, getTrxName());
assertTrue(error == null);
}
receipt.load(getTrxName());
assertTrue(receipt.isPosted());
product.set_TrxName(getTrxName());
MCost cost = product.getCostingRecord(as, getAD_Org_ID(), 0, as.getCostingMethod());
assertNotNull(cost, "No MCost record found");
assertEquals(orderPrice, cost.getCurrentCostPrice().setScale(2, RoundingMode.HALF_UP), "Unexpected current cost price");
//ap invoce, full
MInvoice invoice = new MInvoice(receipt, receipt.getMovementDate());
invoice.setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_APInvoice);
invoice.setDocStatus(DocAction.STATUS_Drafted);
invoice.setDocAction(DocAction.ACTION_Complete);
invoice.saveEx();
MInvoiceLine invoiceLine = new MInvoiceLine(invoice);
invoiceLine.setM_InOutLine_ID(receiptLine.get_ID());
invoiceLine.setLine(10);
invoiceLine.setProduct(product);
invoiceLine.setQty(BigDecimal.TEN);
BigDecimal invoicePrice = new BigDecimal("4.00");
invoiceLine.setPrice(invoicePrice);
invoiceLine.saveEx();
info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Complete);
invoice.load(getTrxName());
assertFalse(info.isError(), info.getSummary());
assertEquals(DocAction.STATUS_Completed, invoice.getDocStatus());
if (!invoice.isPosted()) {
String error = DocumentEngine.postImmediate(Env.getCtx(), invoice.getAD_Client_ID(), MInvoice.Table_ID, invoice.get_ID(), false, getTrxName());
assertTrue(error == null);
}
invoice.load(getTrxName());
assertTrue(invoice.isPosted());
MMatchInv[] miList = MMatchInv.getInvoiceLine(Env.getCtx(), invoiceLine.get_ID(), getTrxName());
for (MMatchInv mi : miList) {
if (!mi.isPosted()) {
String error = DocumentEngine.postImmediate(Env.getCtx(), mi.getAD_Client_ID(), MMatchInv.Table_ID, mi.get_ID(), false, getTrxName());
assertTrue(error == null);
}
mi.load(getTrxName());
assertTrue(mi.isPosted());
cost = product.getCostingRecord(as, getAD_Org_ID(), 0, as.getCostingMethod());
assertNotNull(cost, "No MCost record found");
assertEquals(invoicePrice, cost.getCurrentCostPrice().setScale(2, RoundingMode.HALF_UP), "Unexpected current cost price");
ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
MAccount acctAsset = pc.getAccount(ProductCost.ACCTTYPE_P_Asset, as);
Doc doc = DocManager.getDocument(as, MInvoice.Table_ID, invoice.get_ID(), getTrxName());
MAccount nirAccount = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as);
int C_AcctSchema_ID = as.getC_AcctSchema_ID();
Query query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), C_AcctSchema_ID, getTrxName());
List<MFactAcct> factAccts = query.list();
BigDecimal assetAmt = invoicePrice.subtract(orderPrice).multiply(mrQty);
List<FactAcct> expected = Arrays.asList(new FactAcct(acctAsset, assetAmt, 2, true),
new FactAcct(nirAccount, orderPrice.multiply(mrQty), 2, true),
new FactAcct(acctInvClr, invoicePrice.multiply(mrQty), 2, false));
assertFactAcctEntries(factAccts, expected);
}
} finally {
rollback();
if (product != null) {
product.set_TrxName(null);
product.deleteEx(true);
}
}
}
} }

View File

@ -21,6 +21,7 @@ import static org.junit.jupiter.api.Assertions.fail;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.Arrays;
import java.util.List; import java.util.List;
import org.compiere.acct.Doc; import org.compiere.acct.Doc;
@ -67,6 +68,7 @@ import org.eevolution.model.MPPProductBOM;
import org.eevolution.model.MPPProductBOMLine; import org.eevolution.model.MPPProductBOMLine;
import org.idempiere.test.AbstractTestCase; import org.idempiere.test.AbstractTestCase;
import org.idempiere.test.DictionaryIDs; import org.idempiere.test.DictionaryIDs;
import org.idempiere.test.FactAcct;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Isolated; import org.junit.jupiter.api.parallel.Isolated;
@ -133,38 +135,11 @@ public class NonStockedExpTypeAvgPOCostingTest extends AbstractTestCase
ProductCost pc = new ProductCost(Env.getCtx(), rLine.getM_Product_ID(), 0, getTrxName()); ProductCost pc = new ProductCost(Env.getCtx(), rLine.getM_Product_ID(), 0, getTrxName());
MAccount productExpense = pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as); MAccount productExpense = pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
StringBuilder whereClause = new StringBuilder(); Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, rLine.getM_InOut_ID(), as.getC_AcctSchema_ID(), getTrxName());
whereClause List<MFactAcct> factAccts = query.list();
.append(MFactAcct.COLUMNNAME_AD_Table_ID) List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, BD_20, 2, false, new BigDecimal("-10.00")),
.append("=") new FactAcct(productExpense, BD_20, 2, true, BigDecimal.TEN));
.append(MInOut.Table_ID) assertFactAcctEntries(factAccts, expected);
.append(" AND ")
.append(MFactAcct.COLUMNNAME_Record_ID)
.append("=")
.append(rLine.getM_InOut_ID())
.append(" AND ")
.append(MFactAcct.COLUMNNAME_C_AcctSchema_ID)
.append("=")
.append(as.getC_AcctSchema_ID());
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause.toString(), getTrxName());
for (int id : ids)
{
// Test Accounting for MR
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (fa.getAccount_ID() == acctNIR.getAccount_ID())
{
assertEquals(BD_20, fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), "");
assertEquals(new BigDecimal("-10.00"), fa.getQty().setScale(2, RoundingMode.HALF_UP), "");
}
else if (fa.getAccount_ID() == productExpense.getAccount_ID())
{
assertEquals(BD_20, fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), "");
assertEquals(BigDecimal.TEN.setScale(2, RoundingMode.HALF_UP), fa.getQty().setScale(2, RoundingMode.HALF_UP), "");
}
}
} }
finally finally
{ {
@ -379,27 +354,11 @@ public class NonStockedExpTypeAvgPOCostingTest extends AbstractTestCase
// get AccPayable of the Invoice // get AccPayable of the Invoice
MAccount acctPT = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getV_Liability_Acct(), getTrxName()); MAccount acctPT = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getV_Liability_Acct(), getTrxName());
String whereClause = "AD_Table_ID = " + MInvoice.Table_ID; Query query = MFactAcct.createRecordIdQuery(MInvoice.Table_ID, iLine.getC_Invoice_ID(), as.getC_AcctSchema_ID(), getTrxName());
whereClause += " AND Record_ID = " + iLine.getC_Invoice_ID(); List<MFactAcct> factAccts = query.list();
whereClause += " AND C_AcctSchema_ID = " + as.getC_AcctSchema_ID(); List<FactAcct> expected = Arrays.asList(new FactAcct(acctPT, BD_20, 2, false, BigDecimal.ZERO),
new FactAcct(productExpense, BD_20, 2, true, BigDecimal.TEN));
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause.toString(), getTrxName()); assertFactAcctEntries(factAccts, expected);
for (int id : ids)
{
// Test Accounting for Invoice
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (fa.getAccount_ID() == acctPT.getAccount_ID())
{
assertEquals(BD_20, fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), "");
assertEquals(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP), fa.getQty().setScale(2, RoundingMode.HALF_UP), "");
}
else if (fa.getAccount_ID() == productExpense.getAccount_ID())
{
assertEquals(BD_20, fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), "");
assertEquals(BigDecimal.TEN.setScale(2, RoundingMode.HALF_UP), fa.getQty().setScale(2, RoundingMode.HALF_UP), "");
}
}
// Testing Accounting For MatchInv // Testing Accounting For MatchInv
MMatchInv[] matchInvoices = MMatchInv.getInOut(Env.getCtx(), rLine.getM_InOut_ID(), getTrxName()); MMatchInv[] matchInvoices = MMatchInv.getInOut(Env.getCtx(), rLine.getM_InOut_ID(), getTrxName());
@ -416,29 +375,11 @@ public class NonStockedExpTypeAvgPOCostingTest extends AbstractTestCase
// get Product Expense for the MatchInv // get Product Expense for the MatchInv
pc = new ProductCost(Env.getCtx(), matchInvoices[0].getM_Product_ID(), 0, getTrxName()); pc = new ProductCost(Env.getCtx(), matchInvoices[0].getM_Product_ID(), 0, getTrxName());
productExpense = pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as); productExpense = pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
whereClause = null; query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, matchInvoices[0].get_ID(), as.getC_AcctSchema_ID(), getTrxName());
whereClause = "AD_Table_ID = " + MMatchInv.Table_ID; factAccts = query.list();
whereClause += " AND Record_ID = " + matchInvoices[0].get_ID(); expected = Arrays.asList(new FactAcct(acctNIR, BD_20, 2, true, BigDecimal.TEN),
whereClause += " AND C_AcctSchema_ID = " + as.getC_AcctSchema_ID(); new FactAcct(productExpense, BD_20, 2, false, BigDecimal.TEN.negate()));
assertFactAcctEntries(factAccts, expected);
int[] idsMatchInv = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause.toString(), getTrxName());
for (int id : idsMatchInv)
{
// Test Accounting for MatchINV
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (fa.getAccount_ID() == acctNIR.getAccount_ID())
{
assertEquals(BD_20, fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), "");
assertEquals(BigDecimal.TEN.setScale(2, RoundingMode.HALF_UP), fa.getQty().setScale(2, RoundingMode.HALF_UP), "");
}
else if (fa.getAccount_ID() == productExpense.getAccount_ID())
{
assertEquals(BD_20, fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), "");
assertEquals(new BigDecimal("-10.00"), fa.getQty().setScale(2, RoundingMode.HALF_UP), "");
}
}
} }
finally finally
{ {

View File

@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.fail;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.Arrays;
import java.util.List; import java.util.List;
import org.compiere.acct.Doc; import org.compiere.acct.Doc;
@ -68,6 +69,7 @@ import org.eevolution.model.MPPProductBOM;
import org.eevolution.model.MPPProductBOMLine; import org.eevolution.model.MPPProductBOMLine;
import org.idempiere.test.AbstractTestCase; import org.idempiere.test.AbstractTestCase;
import org.idempiere.test.DictionaryIDs; import org.idempiere.test.DictionaryIDs;
import org.idempiere.test.FactAcct;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Isolated; import org.junit.jupiter.api.parallel.Isolated;
@ -129,38 +131,11 @@ public class NonStockedExpTypeStdCostingTest extends AbstractTestCase
ProductCost pc = new ProductCost(Env.getCtx(), rLine.getM_Product_ID(), 0, getTrxName()); ProductCost pc = new ProductCost(Env.getCtx(), rLine.getM_Product_ID(), 0, getTrxName());
MAccount productExpense = pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as); MAccount productExpense = pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
StringBuilder whereClause = new StringBuilder(); Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, rLine.getM_InOut_ID(), as.getC_AcctSchema_ID(), getTrxName());
whereClause List<MFactAcct> factAccts = query.list();
.append(MFactAcct.COLUMNNAME_AD_Table_ID) List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, BD_20, 2, false, BigDecimal.TEN.negate()),
.append("=") new FactAcct(productExpense, BD_20, 2, true, BigDecimal.TEN));
.append(MInOut.Table_ID) assertFactAcctEntries(factAccts, expected);
.append(" AND ")
.append(MFactAcct.COLUMNNAME_Record_ID)
.append("=")
.append(rLine.getM_InOut_ID())
.append(" AND ")
.append(MFactAcct.COLUMNNAME_C_AcctSchema_ID)
.append("=")
.append(as.getC_AcctSchema_ID());
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause.toString(), getTrxName());
for (int id : ids)
{
// Test Accounting for MR
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (fa.getAccount_ID() == acctNIR.getAccount_ID())
{
assertEquals(BD_20, fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), "");
assertEquals(new BigDecimal("-10.00"), fa.getQty().setScale(2, RoundingMode.HALF_UP), "");
}
else if (fa.getAccount_ID() == productExpense.getAccount_ID())
{
assertEquals(BD_20, fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), "");
assertEquals(BigDecimal.TEN.setScale(2, RoundingMode.HALF_UP), fa.getQty().setScale(2, RoundingMode.HALF_UP), "");
}
}
} }
finally finally
{ {
@ -377,38 +352,11 @@ public class NonStockedExpTypeStdCostingTest extends AbstractTestCase
// get AccPayable of the Invoice // get AccPayable of the Invoice
MAccount acctPT = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getV_Liability_Acct(), getTrxName()); MAccount acctPT = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getV_Liability_Acct(), getTrxName());
StringBuilder whereClause = new StringBuilder(); Query query = MFactAcct.createRecordIdQuery(MInvoice.Table_ID, iLine.getC_Invoice_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
whereClause List<FactAcct> expected = Arrays.asList(new FactAcct(acctPT, BD_20, 2, false, BigDecimal.ZERO),
.append(MFactAcct.COLUMNNAME_AD_Table_ID) new FactAcct(productExpense, BD_20, 2, true, BigDecimal.TEN));
.append("=") assertFactAcctEntries(factAccts, expected);
.append(MInvoice.Table_ID)
.append(" AND ")
.append(MFactAcct.COLUMNNAME_Record_ID)
.append("=")
.append(iLine.getC_Invoice_ID())
.append(" AND ")
.append(MFactAcct.COLUMNNAME_C_AcctSchema_ID)
.append("=")
.append(as.getC_AcctSchema_ID());
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause.toString(), getTrxName());
for (int id : ids)
{
// Test Accounting for Invoice
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (fa.getAccount_ID() == acctPT.getAccount_ID())
{
assertEquals(BD_20, fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), "");
assertEquals(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP), fa.getQty().setScale(2, RoundingMode.HALF_UP), "");
}
else if (fa.getAccount_ID() == productExpense.getAccount_ID())
{
assertEquals(BD_20, fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), "");
assertEquals(BigDecimal.TEN.setScale(2, RoundingMode.HALF_UP), fa.getQty().setScale(2, RoundingMode.HALF_UP), "");
}
}
//Accounting MatchInv //Accounting MatchInv
MMatchInv[] matchInvoices = MMatchInv.getInOut(Env.getCtx(), rLine.getM_InOut_ID(), getTrxName()); MMatchInv[] matchInvoices = MMatchInv.getInOut(Env.getCtx(), rLine.getM_InOut_ID(), getTrxName());
@ -426,39 +374,11 @@ public class NonStockedExpTypeStdCostingTest extends AbstractTestCase
pc = new ProductCost(Env.getCtx(), matchInvoices[0].getM_Product_ID(), 0, getTrxName()); pc = new ProductCost(Env.getCtx(), matchInvoices[0].getM_Product_ID(), 0, getTrxName());
productExpense = pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as); productExpense = pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
whereClause = null; query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, matchInvoices[0].get_ID(), as.getC_AcctSchema_ID(), getTrxName());
whereClause = new StringBuilder(); factAccts = query.list();
whereClause expected = Arrays.asList(new FactAcct(acctNIR, BD_20, 2, true, BigDecimal.TEN),
.append(MFactAcct.COLUMNNAME_AD_Table_ID) new FactAcct(productExpense, BD_20, 2, false, BigDecimal.TEN.negate()));
.append("=") assertFactAcctEntries(factAccts, expected);
.append(MMatchInv.Table_ID)
.append(" AND ")
.append(MFactAcct.COLUMNNAME_Record_ID)
.append("=")
.append(matchInvoices[0].get_ID())
.append(" AND ")
.append(MFactAcct.COLUMNNAME_C_AcctSchema_ID)
.append("=")
.append(as.getC_AcctSchema_ID());
int[] idsMatchInv = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause.toString(), getTrxName());
for (int id : idsMatchInv)
{
// Test Accounting for MatchINV
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (fa.getAccount_ID() == acctNIR.getAccount_ID())
{
assertEquals(BD_20, fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), "");
assertEquals(BigDecimal.TEN.setScale(2, RoundingMode.HALF_UP), fa.getQty().setScale(2, RoundingMode.HALF_UP), "");
}
else if (fa.getAccount_ID() == productExpense.getAccount_ID())
{
assertEquals(BD_20, fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), "");
assertEquals(new BigDecimal("-10.00"), fa.getQty().setScale(2, RoundingMode.HALF_UP), "");
}
}
} }
finally finally
{ {

View File

@ -34,6 +34,7 @@ import java.sql.Timestamp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import org.compiere.acct.Doc; import org.compiere.acct.Doc;
import org.compiere.acct.DocManager; import org.compiere.acct.DocManager;
@ -1453,11 +1454,11 @@ public class Allocation2ndAcctSchemaTest extends AbstractTestCase {
BigDecimal allocAmount = new BigDecimal(1000); BigDecimal allocAmount = new BigDecimal(1000);
ArrayList<PostingLine> tradeLineList = new ArrayList<PostingLine>(); ArrayList<PostingLine> tradeLineList = new ArrayList<PostingLine>();
ArrayList<PostingLine> gainLossLineList = new ArrayList<PostingLine>(); ArrayList<PostingLine> gainLossLineList = new ArrayList<PostingLine>();
BigDecimal accountedDrAmt = getAccountedAmount(usd, allocAmount, cr2.getMultiplyRate()); BigDecimal accountedDrAmt = getAccountedAmount(usd, allocAmount, cr1.getMultiplyRate());
BigDecimal accountedCrAmt = getAccountedAmount(usd, allocAmount, cr1.getMultiplyRate()); BigDecimal accountedCrAmt = getAccountedAmount(usd, allocAmount, cr1.getMultiplyRate());
tradeLineList.add(new PostingLine(usd, accountedDrAmt, Env.ZERO)); tradeLineList.add(new PostingLine(usd, accountedDrAmt, Env.ZERO));
tradeLineList.add(new PostingLine(usd, Env.ZERO, accountedCrAmt)); tradeLineList.add(new PostingLine(usd, Env.ZERO, accountedCrAmt));
BigDecimal gainLossAmt = new BigDecimal(1000).setScale(usd.getStdPrecision(), RoundingMode.HALF_UP); BigDecimal gainLossAmt = BigDecimal.ZERO;
gainLossLineList.add(new PostingLine(usd, Env.ZERO, gainLossAmt)); gainLossLineList.add(new PostingLine(usd, Env.ZERO, gainLossAmt));
testAllocationPosting(ass, allocList, null, tradeLineList, gainLossLineList, null); testAllocationPosting(ass, allocList, null, tradeLineList, gainLossLineList, null);
@ -2181,12 +2182,9 @@ public class Allocation2ndAcctSchemaTest extends AbstractTestCase {
BigDecimal totalTradeAmtAcct = Env.ZERO; BigDecimal totalTradeAmtAcct = Env.ZERO;
BigDecimal totalGainLossAmtAcct = Env.ZERO; BigDecimal totalGainLossAmtAcct = Env.ZERO;
BigDecimal totalCurrBalAmtAcct = Env.ZERO; BigDecimal totalCurrBalAmtAcct = Env.ZERO;
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, alloc.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + alloc.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); for (MFactAcct fa : factAccts) {
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
for (int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (C_Charge_ID != 0 && acctCharge != null && acctCharge.getAccount_ID() == fa.getAccount_ID()) if (C_Charge_ID != 0 && acctCharge != null && acctCharge.getAccount_ID() == fa.getAccount_ID())
totalPaymentAmtAcct = totalPaymentAmtAcct.add(fa.getAmtAcctDr()).subtract(fa.getAmtAcctCr()); totalPaymentAmtAcct = totalPaymentAmtAcct.add(fa.getAmtAcctDr()).subtract(fa.getAmtAcctCr());
else if (C_Charge_ID == 0 && acctUnallocatedCash != null && acctUnallocatedCash.getAccount_ID() == fa.getAccount_ID()) else if (C_Charge_ID == 0 && acctUnallocatedCash != null && acctUnallocatedCash.getAccount_ID() == fa.getAccount_ID())

View File

@ -31,7 +31,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.logging.LogRecord; import java.util.logging.LogRecord;
@ -64,6 +66,7 @@ import org.compiere.wf.MWorkflow;
import org.idempiere.test.AbstractTestCase; import org.idempiere.test.AbstractTestCase;
import org.idempiere.test.ConversionRateHelper; import org.idempiere.test.ConversionRateHelper;
import org.idempiere.test.DictionaryIDs; import org.idempiere.test.DictionaryIDs;
import org.idempiere.test.FactAcct;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Isolated; import org.junit.jupiter.api.parallel.Isolated;
import org.junit.jupiter.api.parallel.ResourceLock; import org.junit.jupiter.api.parallel.ResourceLock;
@ -459,12 +462,9 @@ public class AllocationTest extends AbstractTestCase {
BigDecimal ucAmtAcctCr = new BigDecimal(31000); BigDecimal ucAmtAcctCr = new BigDecimal(31000);
BigDecimal lossAmtAcct = new BigDecimal(1000); BigDecimal lossAmtAcct = new BigDecimal(1000);
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocation.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocation.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); for (MFactAcct fa : factAccts) {
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
for (int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (acctUC.getAccount_ID() == fa.getAccount_ID()) { if (acctUC.getAccount_ID() == fa.getAccount_ID()) {
if (fa.getAmtAcctDr().signum() > 0) if (fa.getAmtAcctDr().signum() > 0)
assertTrue(fa.getAmtAcctDr().compareTo(ucAmtAcctDr) == 0, fa.getAmtAcctDr().toPlainString() + "!=" + ucAmtAcctDr.toPlainString()); assertTrue(fa.getAmtAcctDr().compareTo(ucAmtAcctDr) == 0, fa.getAmtAcctDr().toPlainString() + "!=" + ucAmtAcctDr.toPlainString());
@ -605,12 +605,9 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctLiability = doc.getAccount(Doc.ACCTTYPE_V_Liability, as); MAccount acctLiability = doc.getAccount(Doc.ACCTTYPE_V_Liability, as);
BigDecimal tradeAmtAcct = new BigDecimal(2.13).setScale(usd.getStdPrecision(), RoundingMode.HALF_UP);; BigDecimal tradeAmtAcct = new BigDecimal(2.13).setScale(usd.getStdPrecision(), RoundingMode.HALF_UP);;
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocation.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocation.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); for (MFactAcct fa : factAccts) {
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
for (int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (acctLiability.getAccount_ID() == fa.getAccount_ID()) { if (acctLiability.getAccount_ID() == fa.getAccount_ID()) {
if (fa.getAmtAcctDr().signum() > 0) if (fa.getAmtAcctDr().signum() > 0)
assertTrue(fa.getAmtAcctDr().compareTo(tradeAmtAcct) == 0, fa.getAmtAcctDr().toPlainString() + "!=" + tradeAmtAcct.toPlainString()); assertTrue(fa.getAmtAcctDr().compareTo(tradeAmtAcct) == 0, fa.getAmtAcctDr().toPlainString() + "!=" + tradeAmtAcct.toPlainString());
@ -706,12 +703,9 @@ public class AllocationTest extends AbstractTestCase {
BigDecimal ucAmtAcctCr = new BigDecimal(31000); BigDecimal ucAmtAcctCr = new BigDecimal(31000);
BigDecimal lossAmtAcct = new BigDecimal(1000); BigDecimal lossAmtAcct = new BigDecimal(1000);
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocation.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocation.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); for (MFactAcct fa : factAccts) {
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
for (int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (acctUC.getAccount_ID() == fa.getAccount_ID()) { if (acctUC.getAccount_ID() == fa.getAccount_ID()) {
if (fa.getAmtAcctDr().signum() > 0) if (fa.getAmtAcctDr().signum() > 0)
assertTrue(fa.getAmtAcctDr().compareTo(ucAmtAcctDr) == 0, fa.getAmtAcctDr().toPlainString() + "!=" + ucAmtAcctDr.toPlainString()); assertTrue(fa.getAmtAcctDr().compareTo(ucAmtAcctDr) == 0, fa.getAmtAcctDr().toPlainString() + "!=" + ucAmtAcctDr.toPlainString());
@ -897,43 +891,14 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctART = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getC_Receivable_Acct(), getTrxName()); MAccount acctART = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getC_Receivable_Acct(), getTrxName());
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Due_Acct(), getTrxName()); MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Due_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, alloc.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + alloc.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID() List<FactAcct> expected = Arrays.asList(new FactAcct(acctUC, new BigDecimal("102.00"), 2, true),
+ " ORDER BY Created"; new FactAcct(acctDEP, new BigDecimal("2.00"), 2, true), new FactAcct(acctDEP, new BigDecimal("0.11"), 2, false),
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); new FactAcct(acctWO, new BigDecimal("2.00"), 2, true), new FactAcct(acctWO, new BigDecimal("0.11"), 2, false),
new FactAcct(acctART, new BigDecimal("106.00"), 2, false),
for (int id : ids) { new FactAcct(acctTD, new BigDecimal("0.11"), 2, true));
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); assertFactAcctEntries(factAccts, expected);
if(fa.getAccount_ID() == acctUC.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("102.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else if(fa.getAccount_ID() == acctDEP.getAccount_ID()) {
if(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)>0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
}
} else if(fa.getAccount_ID() == acctWO.getAccount_ID()) {
if(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)>0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
}
} else if(fa.getAccount_ID() == acctART.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("106.00"));
} else if(fa.getAccount_ID() == acctTD.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
}
} }
} finally { } finally {
@ -1028,42 +993,14 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctART = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getC_Receivable_Acct(), getTrxName()); MAccount acctART = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getC_Receivable_Acct(), getTrxName());
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Due_Acct(), getTrxName()); MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Due_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, alloc.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + alloc.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID() List<FactAcct> expected = Arrays.asList(new FactAcct(acctPS, new BigDecimal("-102.00"), 2, true),
+ " ORDER BY Created"; new FactAcct(acctDEP, new BigDecimal("2.00").negate(), 2, true), new FactAcct(acctDEP, new BigDecimal("0.11"), 2, true),
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); new FactAcct(acctWO, new BigDecimal("2.00").negate(), 2, true), new FactAcct(acctWO, new BigDecimal("0.11"), 2, true),
new FactAcct(acctART, new BigDecimal("106.00").negate(), 2, false),
for (int id : ids) { new FactAcct(acctTD, new BigDecimal("0.11"), 2, false));
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); assertFactAcctEntries(factAccts, expected);
if(fa.getAccount_ID() == acctPS.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("102.00").negate());
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else if(fa.getAccount_ID() == acctDEP.getAccount_ID()) {
if(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)<0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00").negate());
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
} else if(fa.getAccount_ID() == acctWO.getAccount_ID()) {
if(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)<0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00").negate());
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
} else if(fa.getAccount_ID() == acctART.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("106.00").negate());
} else if(fa.getAccount_ID() == acctTD.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
}
}
} }
} finally { } finally {
@ -1158,42 +1095,14 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctPS = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getB_PaymentSelect_Acct(), getTrxName()); MAccount acctPS = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getB_PaymentSelect_Acct(), getTrxName());
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Credit_Acct(), getTrxName()); MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Credit_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, alloc.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + alloc.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID() List<FactAcct> expected = Arrays.asList(new FactAcct(acctPT, new BigDecimal("106.00"), 2, true),
+ " ORDER BY Created"; new FactAcct(acctDRE, new BigDecimal("2.00"), 2, false), new FactAcct(acctDRE, new BigDecimal("0.11"), 2, true),
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); new FactAcct(acctWO, new BigDecimal("2.00"), 2, false), new FactAcct(acctWO, new BigDecimal("0.11"), 2, true),
new FactAcct(acctPS, new BigDecimal("102.00"), 2, false),
for (int id : ids) { new FactAcct(acctTD, new BigDecimal("0.11"), 2, false));
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); assertFactAcctEntries(factAccts, expected);
if(fa.getAccount_ID() == acctPT.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("106.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else if(fa.getAccount_ID() == acctDRE.getAccount_ID()) {
if(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)>0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
} else if(fa.getAccount_ID() == acctWO.getAccount_ID()) {
if(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)>0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
} else if(fa.getAccount_ID() == acctPS.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("102.00"));
} else if(fa.getAccount_ID() == acctTD.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
}
}
} }
} finally { } finally {
@ -1288,44 +1197,15 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctUC = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getB_UnallocatedCash_Acct(), getTrxName()); MAccount acctUC = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getB_UnallocatedCash_Acct(), getTrxName());
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Credit_Acct(), getTrxName()); MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Credit_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, alloc.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + alloc.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID() List<FactAcct> expected = Arrays.asList(new FactAcct(acctPT, new BigDecimal("106.00").negate(), 2, true),
+ " ORDER BY Created"; new FactAcct(acctDRE, new BigDecimal("2.00").negate(), 2, false), new FactAcct(acctDRE, new BigDecimal("0.11"), 2, false),
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); new FactAcct(acctWO, new BigDecimal("2.00").negate(), 2, false), new FactAcct(acctWO, new BigDecimal("0.11"), 2, false),
new FactAcct(acctUC, new BigDecimal("102.00").negate(), 2, false),
for (int id : ids) { new FactAcct(acctTD, new BigDecimal("0.11"), 2, true));
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); assertFactAcctEntries(factAccts, expected);
if(fa.getAccount_ID() == acctPT.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("106.00").negate());
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else if(fa.getAccount_ID() == acctDRE.getAccount_ID()) {
if(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)<0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00").negate());
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
} }
} else if(fa.getAccount_ID() == acctWO.getAccount_ID()) {
if(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)<0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00").negate());
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
}
} else if(fa.getAccount_ID() == acctUC.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("102.00").negate());
} else if(fa.getAccount_ID() == acctTD.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
}
}
} finally { } finally {
rollback(); rollback();
@ -1419,43 +1299,14 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctART = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getC_Receivable_Acct(), getTrxName()); MAccount acctART = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getC_Receivable_Acct(), getTrxName());
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Due_Acct(), getTrxName()); MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Due_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocationa[0].get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocationa[0].get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID() List<FactAcct> expected = Arrays.asList(new FactAcct(acctUC, new BigDecimal("102.00"), 2, true),
+ " ORDER BY Created"; new FactAcct(acctDEP, new BigDecimal("2.00"), 2, true), new FactAcct(acctDEP, new BigDecimal("0.11"), 2, false),
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); new FactAcct(acctWO, new BigDecimal("2.00"), 2, true), new FactAcct(acctWO, new BigDecimal("0.11"), 2, false),
new FactAcct(acctART, new BigDecimal("106.00"), 2, false),
for (int id : ids) { new FactAcct(acctTD, new BigDecimal("0.11"), 2, true));
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); assertFactAcctEntries(factAccts, expected);
if(fa.getAccount_ID() == acctUC.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("102.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else if(fa.getAccount_ID() == acctDEP.getAccount_ID()) {
if(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)>0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
}
} else if(fa.getAccount_ID() == acctWO.getAccount_ID()) {
if(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)>0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
}
} else if(fa.getAccount_ID() == acctART.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("106.00"));
} else if(fa.getAccount_ID() == acctTD.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
}
} }
} finally { } finally {
@ -1545,48 +1396,20 @@ public class AllocationTest extends AbstractTestCase {
// 78100_Bad Debts Write-off | 0.11 | 0.00 // 78100_Bad Debts Write-off | 0.11 | 0.00
// 21610 Tax due | 0.00 | 0.11 // 21610 Tax due | 0.00 | 0.11
// -------------------------------------------------------------------- // --------------------------------------------------------------------
MAccount acctPS = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getB_PaymentSelect_Acct(), getTrxName()); MAccount acctPS = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getB_UnallocatedCash_Acct(), getTrxName());
MAccount acctDEP = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getPayDiscount_Exp_Acct(), getTrxName()); MAccount acctDEP = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getPayDiscount_Exp_Acct(), getTrxName());
MAccount acctWO = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getWriteOff_Acct(), getTrxName()); MAccount acctWO = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getWriteOff_Acct(), getTrxName());
MAccount acctART = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getC_Receivable_Acct(), getTrxName()); MAccount acctART = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getC_Receivable_Acct(), getTrxName());
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Due_Acct(), getTrxName()); MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Due_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocationa[0].get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocationa[0].get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID() List<FactAcct> expected = Arrays.asList(new FactAcct(acctPS, new BigDecimal("102.00").negate(), 2, true),
+ " ORDER BY Created"; new FactAcct(acctDEP, new BigDecimal("2.00").negate(), 2, true), new FactAcct(acctDEP, new BigDecimal("0.11"), 2, true),
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); new FactAcct(acctWO, new BigDecimal("2.00").negate(), 2, true), new FactAcct(acctWO, new BigDecimal("0.11"), 2, true),
new FactAcct(acctART, new BigDecimal("106.00").negate(), 2, false),
for (int id : ids) { new FactAcct(acctTD, new BigDecimal("0.11"), 2, false));
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); assertFactAcctEntries(factAccts, expected);
if(fa.getAccount_ID() == acctPS.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("102.00").negate());
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else if(fa.getAccount_ID() == acctDEP.getAccount_ID()) {
if(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)<0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00").negate());
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
} else if(fa.getAccount_ID() == acctWO.getAccount_ID()) {
if(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)<0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00").negate());
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
} else if(fa.getAccount_ID() == acctART.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("106.00").negate());
} else if(fa.getAccount_ID() == acctTD.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
}
}
} }
} finally { } finally {
@ -1682,42 +1505,14 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctPS = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getB_PaymentSelect_Acct(), getTrxName()); MAccount acctPS = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getB_PaymentSelect_Acct(), getTrxName());
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Credit_Acct(), getTrxName()); MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Credit_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocationa[0].get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocationa[0].get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID() List<FactAcct> expected = Arrays.asList(new FactAcct(acctPT, new BigDecimal("106.00"), 2, true),
+ " ORDER BY Created"; new FactAcct(acctDRE, new BigDecimal("2.00"), 2, false), new FactAcct(acctDRE, new BigDecimal("0.11"), 2, true),
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); new FactAcct(acctWO, new BigDecimal("2.00"), 2, false), new FactAcct(acctWO, new BigDecimal("0.11"), 2, true),
new FactAcct(acctPS, new BigDecimal("102.00"), 2, false),
for (int id : ids) { new FactAcct(acctTD, new BigDecimal("0.11"), 2, false));
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); assertFactAcctEntries(factAccts, expected);
if(fa.getAccount_ID() == acctPT.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("106.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else if(fa.getAccount_ID() == acctDRE.getAccount_ID()) {
if(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)>0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
} else if(fa.getAccount_ID() == acctWO.getAccount_ID()) {
if(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)>0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
} else if(fa.getAccount_ID() == acctPS.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("102.00"));
} else if(fa.getAccount_ID() == acctTD.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
}
}
} }
} finally { } finally {
@ -1810,45 +1605,17 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctPT = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getV_Liability_Acct(), getTrxName()); MAccount acctPT = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getV_Liability_Acct(), getTrxName());
MAccount acctDRE = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getPayDiscount_Rev_Acct(), getTrxName()); MAccount acctDRE = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getPayDiscount_Rev_Acct(), getTrxName());
MAccount acctWO = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getWriteOff_Acct(), getTrxName()); MAccount acctWO = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getWriteOff_Acct(), getTrxName());
MAccount acctUC = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getB_UnallocatedCash_Acct(), getTrxName()); MAccount acctUC = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getB_PaymentSelect_Acct(), getTrxName());
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Credit_Acct(), getTrxName()); MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Credit_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocationa[0].get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocationa[0].get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID() List<FactAcct> expected = Arrays.asList(new FactAcct(acctPT, new BigDecimal("106.00").negate(), 2, true),
+ " ORDER BY Created"; new FactAcct(acctDRE, new BigDecimal("2.00").negate(), 2, false), new FactAcct(acctDRE, new BigDecimal("0.11"), 2, false),
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); new FactAcct(acctWO, new BigDecimal("2.00").negate(), 2, false), new FactAcct(acctWO, new BigDecimal("0.11"), 2, false),
new FactAcct(acctUC, new BigDecimal("102.00").negate(), 2, false),
for (int id : ids) { new FactAcct(acctTD, new BigDecimal("0.11"), 2, true));
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); assertFactAcctEntries(factAccts, expected);
if(fa.getAccount_ID() == acctPT.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("106.00").negate());
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else if(fa.getAccount_ID() == acctDRE.getAccount_ID()) {
if(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)<0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00").negate());
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
}
} else if(fa.getAccount_ID() == acctWO.getAccount_ID()) {
if(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)<0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00").negate());
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
}
} else if(fa.getAccount_ID() == acctUC.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("104.00").negate());
} else if(fa.getAccount_ID() == acctTD.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
}
} }
} finally { } finally {
@ -1932,60 +1699,29 @@ public class AllocationTest extends AbstractTestCase {
// Account | Acct Debit | Acct Credit // Account | Acct Debit | Acct Credit
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// 59201_Payment discount revenue | 2.00 | 0.00 // 59201_Payment discount expense | 2.00 | 0.00
// 78100_Bad Debts Write-off | 2.00 | 0.00 // 78100_Bad Debts Write-off | 2.00 | 0.00
// 12110 Accounts Receivable - Trade | 0.00 | 106.00 // 12110 Accounts Receivable - Trade | 0.00 | 106.00
// 21610 Tax due | 0.11 | 0.00 // 21610 Tax due | 0.11 | 0.00
// 59201_Payment discount revenue | 0.00 | 0.11 // 59201_Payment discount expense | 0.00 | 0.11
// 21610 Tax due | 0.11 | 0.00 // 21610 Tax due | 0.11 | 0.00
// 78100_Bad Debts Write-off | 0.00 | 0.11 // 78100_Bad Debts Write-off | 0.00 | 0.11
// 12110_Accounts Receivable - Trade | 0.00 | -102.00 // 12110_Accounts Receivable - Trade | 0.00 | -102.00
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// ToDo: set Account doc.setC_BPartner_ID(bpartner.getC_BPartner_ID());
MAccount acctDRE = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getPayDiscount_Rev_Acct(), getTrxName()); MAccount acctDRE = doc.getAccount(Doc.ACCTTYPE_DiscountExp, as);
MAccount acctWO = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getWriteOff_Acct(), getTrxName()); MAccount acctWO = doc.getAccount(Doc.ACCTTYPE_WriteOff, as);
MAccount acctART = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getC_Receivable_Acct(), getTrxName()); MAccount acctART = doc.getAccount(Doc.ACCTTYPE_C_Receivable, as);
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Due_Acct(), getTrxName()); MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Due_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, alloc.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + alloc.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID() List<FactAcct> expected = Arrays.asList(new FactAcct(acctDRE, new BigDecimal("2.00"), 2, true),
+ " ORDER BY Created"; new FactAcct(acctDRE, new BigDecimal("0.11"), 2, false),
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); new FactAcct(acctWO, new BigDecimal("2.00"), 2, true), new FactAcct(acctWO, new BigDecimal("0.11"), 2, false),
new FactAcct(acctART, new BigDecimal("106.00"), 2, false), new FactAcct(acctART, new BigDecimal("-102.00"), 2, false),
for (int id : ids) { new FactAcct(acctTD, new BigDecimal("0.11"), 2, true));
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); assertFactAcctEntries(factAccts, expected);
if(fa.getAccount_ID() == acctDRE.getAccount_ID()) {
if(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)>0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
}
} else if(fa.getAccount_ID() == acctWO.getAccount_ID()) {
if(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)>0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
}
} else if(fa.getAccount_ID() == acctART.getAccount_ID()) {
if(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)>0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("106.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("-102.00"));
}
} else if(fa.getAccount_ID() == acctTD.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
}
} }
} finally { } finally {
@ -2085,43 +1821,14 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctWO = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getWriteOff_Acct(), getTrxName()); MAccount acctWO = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getWriteOff_Acct(), getTrxName());
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Credit_Acct(), getTrxName()); MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Credit_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, alloc.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + alloc.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID() List<FactAcct> expected = Arrays.asList(new FactAcct(acctPT, new BigDecimal("106.00"), 2, true),
+ " ORDER BY Created"; new FactAcct(acctPT, new BigDecimal("-102.00"), 2, true),
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); new FactAcct(acctDRE, new BigDecimal("2.00"), 2, false), new FactAcct(acctDRE, new BigDecimal("0.11"), 2, true),
new FactAcct(acctWO, new BigDecimal("2.00"), 2, false), new FactAcct(acctWO, new BigDecimal("0.11"), 2, true),
for (int id : ids) { new FactAcct(acctTD, new BigDecimal("0.11"), 2, false));
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); assertFactAcctEntries(factAccts, expected);
if(fa.getAccount_ID() == acctPT.getAccount_ID()) {
if(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)>0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("106.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("-102.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
} else if(fa.getAccount_ID() == acctDRE.getAccount_ID()) {
if(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)>0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
} else if(fa.getAccount_ID() == acctWO.getAccount_ID()) {
if(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP).compareTo(Env.ZERO)>0) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("2.00"));
} else {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
}
} else if(fa.getAccount_ID() == acctTD.getAccount_ID()) {
assertEquals(fa.getAmtAcctDr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.00"));
assertEquals(fa.getAmtAcctCr().setScale(2, RoundingMode.HALF_UP), new BigDecimal("0.11"));
}
}
} }
} finally { } finally {
@ -2242,18 +1949,10 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctUC = doc.getAccount(Doc.ACCTTYPE_UnallocatedCash, as); MAccount acctUC = doc.getAccount(Doc.ACCTTYPE_UnallocatedCash, as);
BigDecimal ucAmtAcctDr = new BigDecimal(370.88).setScale(2, RoundingMode.HALF_UP); BigDecimal ucAmtAcctDr = new BigDecimal(370.88).setScale(2, RoundingMode.HALF_UP);
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocation.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocation.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID() List<FactAcct> expected = Arrays.asList(new FactAcct(acctUC, ucAmtAcctDr, 2, true));
+ " ORDER BY Created"; assertFactAcctEntries(factAccts, expected);
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
for (int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (acctUC.getAccount_ID() == fa.getAccount_ID()) {
if (fa.getAmtAcctDr().signum() > 0)
assertTrue(fa.getAmtAcctDr().compareTo(ucAmtAcctDr) == 0, fa.getAmtAcctDr().toPlainString() + "!=" + ucAmtAcctDr.toPlainString());
}
}
} }
MInvoice invoice2 = new MInvoice(Env.getCtx(), 0, getTrxName()); MInvoice invoice2 = new MInvoice(Env.getCtx(), 0, getTrxName());
@ -2313,13 +2012,9 @@ public class AllocationTest extends AbstractTestCase {
BigDecimal ucAmtAcctDr = new BigDecimal(175.67).setScale(2, RoundingMode.HALF_UP); BigDecimal ucAmtAcctDr = new BigDecimal(175.67).setScale(2, RoundingMode.HALF_UP);
BigDecimal ucAmtAcctCr = new BigDecimal(0.01).setScale(2, RoundingMode.HALF_UP); BigDecimal ucAmtAcctCr = new BigDecimal(0.01).setScale(2, RoundingMode.HALF_UP);
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocation.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocation.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID() for (MFactAcct fa : factAccts) {
+ " ORDER BY Created";
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
for (int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (acctUC.getAccount_ID() == fa.getAccount_ID()) { if (acctUC.getAccount_ID() == fa.getAccount_ID()) {
if (fa.getAmtAcctDr().signum() > 0) if (fa.getAmtAcctDr().signum() > 0)
assertTrue(fa.getAmtAcctDr().compareTo(ucAmtAcctDr) == 0, fa.getAmtAcctDr().toPlainString() + "!=" + ucAmtAcctDr.toPlainString()); assertTrue(fa.getAmtAcctDr().compareTo(ucAmtAcctDr) == 0, fa.getAmtAcctDr().toPlainString() + "!=" + ucAmtAcctDr.toPlainString());

View File

@ -31,6 +31,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.util.List;
import java.util.Properties; import java.util.Properties;
import org.adempiere.base.Core; import org.adempiere.base.Core;
@ -58,6 +59,7 @@ import org.compiere.model.MTax;
import org.compiere.model.MTaxCategory; import org.compiere.model.MTaxCategory;
import org.compiere.model.MWarehouse; import org.compiere.model.MWarehouse;
import org.compiere.model.ProductCost; import org.compiere.model.ProductCost;
import org.compiere.model.Query;
import org.compiere.model.Tax; import org.compiere.model.Tax;
import org.compiere.model.X_C_Order; import org.compiere.model.X_C_Order;
import org.compiere.process.DocAction; import org.compiere.process.DocAction;
@ -325,13 +327,10 @@ public class MTaxTest extends AbstractTestCase {
assertEquals(expectedCost, averageCost, "Un-expected average cost"); assertEquals(expectedCost, averageCost, "Un-expected average cost");
MAccount acctAsset = productCost.getAccount(ProductCost.ACCTTYPE_P_Asset, schema); MAccount acctAsset = productCost.getAccount(ProductCost.ACCTTYPE_P_Asset, schema);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MInOut.Table_ID Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, receipt.get_ID(), schema.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + receipt.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + schema.getC_AcctSchema_ID();
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
BigDecimal totalDebit = new BigDecimal("0.00"); BigDecimal totalDebit = new BigDecimal("0.00");
for(int id : ids) { for(MFactAcct fa : factAccts) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (fa.getAccount_ID() == acctAsset.getAccount_ID()) { if (fa.getAccount_ID() == acctAsset.getAccount_ID()) {
totalDebit = totalDebit.add(fa.getAmtAcctDr()); totalDebit = totalDebit.add(fa.getAmtAcctDr());
} }
@ -470,13 +469,10 @@ public class MTaxTest extends AbstractTestCase {
assertEquals(expectedCost, averageCost, "Un-expected average cost"); assertEquals(expectedCost, averageCost, "Un-expected average cost");
MAccount acctAsset = productCost.getAccount(ProductCost.ACCTTYPE_P_Asset, schema); MAccount acctAsset = productCost.getAccount(ProductCost.ACCTTYPE_P_Asset, schema);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MInOut.Table_ID Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, receipt.get_ID(), schema.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + receipt.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + schema.getC_AcctSchema_ID();
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
BigDecimal totalDebit = new BigDecimal("0.00"); BigDecimal totalDebit = new BigDecimal("0.00");
for(int id : ids) { for(MFactAcct fa : factAccts) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
if (fa.getAccount_ID() == acctAsset.getAccount_ID()) { if (fa.getAccount_ID() == acctAsset.getAccount_ID()) {
totalDebit = totalDebit.add(fa.getAmtAcctDr()); totalDebit = totalDebit.add(fa.getAmtAcctDr());
} }

View File

@ -33,6 +33,7 @@ import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.List; import java.util.List;
import java.util.Optional;
import org.compiere.model.MAccount; import org.compiere.model.MAccount;
import org.compiere.model.MAcctSchema; import org.compiere.model.MAcctSchema;
@ -312,17 +313,12 @@ public class ProductionTestIsolated extends AbstractTestCase {
ProductCost pc = new ProductCost (Env.getCtx(), mulchX.getM_Product_ID(), 0, getTrxName()); ProductCost pc = new ProductCost (Env.getCtx(), mulchX.getM_Product_ID(), 0, getTrxName());
MAccount acctVariance = pc.getAccount(ProductCost.ACCTTYPE_P_RateVariance, as); MAccount acctVariance = pc.getAccount(ProductCost.ACCTTYPE_P_RateVariance, as);
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MProduction.Table_ID Query query = MFactAcct.createRecordIdQuery(MProduction.Table_ID, production.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + production.get_ID() List<MFactAcct> factAccts = query.list();
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID()
+ " AND " + MFactAcct.COLUMNNAME_Account_ID + "=" + acctVariance.getAccount_ID();
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
BigDecimal variance = BigDecimal.ZERO; BigDecimal variance = BigDecimal.ZERO;
for (int id : ids) { Optional<MFactAcct> optional = factAccts.stream().filter(e -> e.getAccount_ID() == acctVariance.getAccount_ID()).findFirst();
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); if (optional.isPresent())
variance = fa.getAmtAcctDr().subtract(fa.getAmtAcctCr()); variance = optional.get().getAmtAcctDr().subtract(optional.get().getAmtAcctCr());
break;
}
BigDecimal varianceExpected = componentCost.subtract(endProductCost).setScale(as.getStdPrecision(), RoundingMode.HALF_UP); BigDecimal varianceExpected = componentCost.subtract(endProductCost).setScale(as.getStdPrecision(), RoundingMode.HALF_UP);
assertEquals(varianceExpected.setScale(2, RoundingMode.HALF_UP), variance.setScale(2, RoundingMode.HALF_UP), "Variance not posted correctly."); assertEquals(varianceExpected.setScale(2, RoundingMode.HALF_UP), variance.setScale(2, RoundingMode.HALF_UP), "Variance not posted correctly.");
} finally { } finally {