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>();
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
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

View File

@ -25,6 +25,7 @@ import java.sql.Savepoint;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
@ -34,14 +35,18 @@ import org.compiere.model.MAccount;
import org.compiere.model.MAcctSchema;
import org.compiere.model.MClientInfo;
import org.compiere.model.MConversionRate;
import org.compiere.model.MCost;
import org.compiere.model.MCostDetail;
import org.compiere.model.MCostElement;
import org.compiere.model.MCurrency;
import org.compiere.model.MFactAcct;
import org.compiere.model.MInvoice;
import org.compiere.model.MInvoiceLine;
import org.compiere.model.MLandedCostAllocation;
import org.compiere.model.MOrderLandedCostAllocation;
import org.compiere.model.MTax;
import org.compiere.model.ProductCost;
import org.compiere.model.Query;
import org.compiere.model.X_M_Cost;
import org.compiere.util.DB;
import org.compiere.util.Env;
@ -422,7 +427,7 @@ public class Doc_Invoice extends Doc
// ** ARI, ARF
if (getDocumentType().equals(DOCTYPE_ARInvoice)
|| getDocumentType().equals(DOCTYPE_ARProForma))
{
{
BigDecimal grossAmt = getAmount(Doc.AMTTYPE_Gross);
BigDecimal serviceAmt = Env.ZERO;
@ -440,7 +445,7 @@ public class Doc_Invoice extends Doc
FactLine tl = fact.createLine(null, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxDue, as),
getC_Currency_ID(), null, amt);
if (tl != null)
tl.setC_Tax_ID(m_taxes[i].getC_Tax_ID());
tl.setC_Tax_ID(m_taxes[i].getC_Tax_ID());
}
}
// Revenue CR
@ -588,6 +593,12 @@ public class Doc_Invoice extends Doc
// ** API
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 serviceAmt = Env.ZERO;
@ -601,6 +612,10 @@ public class Doc_Invoice extends Doc
getC_Currency_ID(), m_taxes[i].getAmount(), null);
if (tl != null)
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
for (int i = 0; i < p_lines.length; i++)
@ -620,6 +635,17 @@ public class Doc_Invoice extends Doc
else
desc += " 100%";
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)
{
@ -636,12 +662,34 @@ public class Doc_Invoice extends Doc
amt = amt.add(discount);
dAmt = discount;
MAccount tradeDiscountReceived = line.getAccount(ProductCost.ACCTTYPE_P_TDiscountRec, as);
fact.createLine (line, tradeDiscountReceived,
FactLine fl = fact.createLine (line, tradeDiscountReceived,
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);
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())
{
grossAmt = grossAmt.subtract(amt);
@ -672,13 +720,23 @@ public class Doc_Invoice extends Doc
serviceAmt = getAmount(Doc.AMTTYPE_Gross);
grossAmt = Env.ZERO;
}
if (grossAmt.signum() != 0)
fact.createLine(null, MAccount.get(getCtx(), payables_ID),
FactLine fl = null;
if (grossAmt.signum() > 0)
fl = fact.createLine(null, MAccount.get(getCtx(), payables_ID),
getC_Currency_ID(), null, grossAmt);
if (serviceAmt.signum() != 0)
fact.createLine(null, MAccount.get(getCtx(), payablesServices_ID),
else if (grossAmt.signum() < 0)
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);
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
FactLine[] fLines = fact.getLines();
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++)
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
MInvoiceLine il = new MInvoiceLine (getCtx(), C_InvoiceLine_ID, getTrxName());
@ -962,95 +1021,159 @@ public class Doc_Invoice extends Doc
if (X_M_Cost.COSTINGMETHOD_AverageInvoice.equals(costingMethod) || X_M_Cost.COSTINGMETHOD_AveragePO.equals(costingMethod))
{
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;
int oCurrencyId = 0;
BigDecimal costAdjustmentAmt = BigDecimal.ZERO;
boolean usesSchemaCurrency = false;
Timestamp oDateAcct = getDateAcct();
if (lca.getM_InOutLine_ID() > 0)
MInvoiceLine reversalLine = null;
if (reversal)
{
I_M_InOutLine iol = lca.getM_InOutLine();
if (iol.getC_OrderLine_ID() > 0)
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();
if (lca.getM_InOutLine_ID() > 0)
{
oCurrencyId = iol.getC_OrderLine().getC_Currency_ID();
oDateAcct = iol.getC_OrderLine().getC_Order().getDateAcct();
MOrderLandedCostAllocation[] allocations = MOrderLandedCostAllocation.getOfOrderLine(iol.getC_OrderLine_ID(), getTrxName());
for(MOrderLandedCostAllocation allocation : allocations)
I_M_InOutLine iol = lca.getM_InOutLine();
if (iol.getC_OrderLine_ID() > 0)
{
if (allocation.getC_OrderLandedCost().getM_CostElement_ID() != lca.getM_CostElement_ID())
continue;
BigDecimal amt = allocation.getAmt();
BigDecimal qty = allocation.getQty();
if (qty.compareTo(iol.getMovementQty()) != 0)
oCurrencyId = iol.getC_OrderLine().getC_Currency_ID();
oDateAcct = iol.getC_OrderLine().getC_Order().getDateAcct();
MOrderLandedCostAllocation[] allocations = MOrderLandedCostAllocation.getOfOrderLine(iol.getC_OrderLine_ID(), getTrxName());
for(MOrderLandedCostAllocation allocation : allocations)
{
amt = amt.multiply(iol.getMovementQty()).divide(qty, 12, RoundingMode.HALF_UP);
if (allocation.getC_OrderLandedCost().getM_CostElement_ID() != lca.getM_CostElement_ID())
continue;
BigDecimal amt = allocation.getAmt();
BigDecimal qty = allocation.getQty();
if (qty.compareTo(iol.getMovementQty()) != 0)
{
amt = amt.multiply(iol.getMovementQty()).divide(qty, 12, RoundingMode.HALF_UP);
}
estimatedAmt = estimatedAmt.add(amt);
}
estimatedAmt = estimatedAmt.add(amt);
}
}
}
if (estimatedAmt.scale() > as.getCostingPrecision())
{
estimatedAmt = estimatedAmt.setScale(as.getCostingPrecision(), RoundingMode.HALF_UP);
}
BigDecimal costAdjustmentAmt = allocationAmt;
if (estimatedAmt.signum() > 0)
{
//get other allocation amt
StringBuilder sql = new StringBuilder("SELECT Sum(Amt) FROM C_LandedCostAllocation WHERE M_InOutLine_ID=? ")
.append("AND C_LandedCostAllocation_ID<>? ")
.append("AND M_CostElement_ID=? ")
.append("AND AD_Client_ID=? ");
BigDecimal otherAmt = DB.getSQLValueBD(getTrxName(), sql.toString(), lca.getM_InOutLine_ID(), lca.getC_LandedCostAllocation_ID(),
lca.getM_CostElement_ID(), lca.getAD_Client_ID());
if (otherAmt != null)
if (estimatedAmt.scale() > as.getCostingPrecision())
{
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
//convert to accounting schema currency
if (estimatedAmt.signum() > 0 && oCurrencyId != getC_Currency_ID())
{
estimatedAmt = MConversionRate.convert(getCtx(), estimatedAmt,
oCurrencyId, as.getC_Currency_ID(),
oDateAcct, getC_ConversionType_ID(),
getAD_Client_ID(), getAD_Org_ID());
allocationAmt = MConversionRate.convert(getCtx(), allocationAmt,
getC_Currency_ID(), as.getC_Currency_ID(),
getDateAcct(), getC_ConversionType_ID(),
getAD_Client_ID(), getAD_Org_ID());
setC_Currency_ID(as.getC_Currency_ID());
usesSchemaCurrency = true;
estimatedAmt = estimatedAmt.setScale(as.getCostingPrecision(), RoundingMode.HALF_UP);
}
costAdjustmentAmt = allocationAmt;
if (estimatedAmt.signum() > 0)
{
if (allocationAmt.signum() > 0)
costAdjustmentAmt = allocationAmt.subtract(estimatedAmt);
else if (allocationAmt.signum() < 0)
costAdjustmentAmt = allocationAmt.add(estimatedAmt);
}
}
if (!dr)
costAdjustmentAmt = costAdjustmentAmt.negate();
{
//get other allocation amt
StringBuilder sql = new StringBuilder("SELECT Sum(Amt) FROM C_LandedCostAllocation WHERE M_InOutLine_ID=? ")
.append("AND C_LandedCostAllocation_ID<>? ")
.append("AND M_CostElement_ID=? ")
.append("AND AD_Client_ID=? ");
BigDecimal otherAmt = DB.getSQLValueBD(getTrxName(), sql.toString(), lca.getM_InOutLine_ID(), lca.getC_LandedCostAllocation_ID(),
lca.getM_CostElement_ID(), lca.getAD_Client_ID());
if (otherAmt != null)
{
estimatedAmt = estimatedAmt.subtract(otherAmt);
}
//added for IDEMPIERE-3014
//convert to accounting schema currency
if (estimatedAmt.signum() > 0 && oCurrencyId != getC_Currency_ID())
{
estimatedAmt = MConversionRate.convert(getCtx(), estimatedAmt,
oCurrencyId, as.getC_Currency_ID(),
oDateAcct, getC_ConversionType_ID(),
getAD_Client_ID(), getAD_Org_ID());
boolean zeroQty = false;
if (costAdjustmentAmt.signum() != 0)
allocationAmt = MConversionRate.convert(getCtx(), allocationAmt,
getC_Currency_ID(), as.getC_Currency_ID(),
getDateAcct(), getC_ConversionType_ID(),
getAD_Client_ID(), getAD_Org_ID());
setC_Currency_ID(as.getC_Currency_ID());
usesSchemaCurrency = true;
}
if (estimatedAmt.signum() > 0)
{
costAdjustmentAmt = allocationAmt.subtract(estimatedAmt);
}
}
if (!dr)
costAdjustmentAmt = costAdjustmentAmt.negate();
}
BigDecimal amtAsset = Env.ZERO;
BigDecimal amtVariance = Env.ZERO;
BigDecimal costDetailQty = lca.getQty();
if (costAdjustmentAmt.signum() != 0 && !reversal)
{
Trx trx = Trx.get(getTrxName(), false);
Savepoint savepoint = null;
try {
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
if (getC_Currency_ID() != as.getC_Currency_ID())
costDetailAmt = MConversionRate.convert(getCtx(), costDetailAmt,
@ -1066,18 +1189,20 @@ public class Doc_Invoice extends Doc
costDetailAmt = costDetailAmt.add(prevAmt);
}
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(),
C_InvoiceLine_ID, lca.getM_CostElement_ID(),
costDetailAmt, lca.getQty(),
costDetailAmt, costDetailQty,
desc, getTrxName())) {
throw new RuntimeException("Failed to create cost detail record.");
}
} catch (SQLException e) {
throw new RuntimeException(e.getLocalizedMessage(), e);
} catch (AverageCostingZeroQtyException e) {
zeroQty = true;
try {
try {
amtAsset = BigDecimal.ZERO;
amtVariance = costAdjustmentAmt;
trx.rollback(savepoint);
savepoint = null;
} catch (SQLException e1) {
@ -1090,16 +1215,113 @@ public class Doc_Invoice extends Doc
} 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();
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;
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());
}
}
}
boolean reversal = false;
if (allocationAmt.signum() < 0) //reversal
{
allocationAmt = allocationAmt.negate();
reversal = true;
}
if (allocationAmt.signum() > 0)
if (allocationAmt.signum() > 0 && !reversal)
{
if (allocationAmt.scale() > as.getStdPrecision())
{
@ -1109,46 +1331,53 @@ public class Doc_Invoice extends Doc
{
estimatedAmt = estimatedAmt.setScale(as.getStdPrecision(), RoundingMode.HALF_UP);
}
int compare = allocationAmt.compareTo(estimatedAmt);
if (compare > 0)
if (allocationAmt.compareTo(estimatedAmt)!=0)
{
drAmt = dr ? (reversal ? null : estimatedAmt): (reversal ? estimatedAmt : null);
crAmt = dr ? (reversal ? estimatedAmt : null): (reversal ? null : estimatedAmt);
account = pc.getAccount(ProductCost.ACCTTYPE_P_LandedCostClearing, as);
FactLine 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 (estimatedAmt.signum() != 0)
{
drAmt = dr ? (reversal ? null : estimatedAmt): (reversal ? estimatedAmt : null);
crAmt = dr ? (reversal ? estimatedAmt : null): (reversal ? null : estimatedAmt);
account = pc.getAccount(ProductCost.ACCTTYPE_P_LandedCostClearing, as);
FactLine 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());
}
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());
if (amtVariance.signum() != 0) {
if (amtVariance.signum() > 0) {
drAmt = dr ? amtVariance : null;
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);
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 ? amtAsset : null;
crAmt = dr ? null : amtAsset;
} 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.setM_Product_ID(lca.getM_Product_ID());
fl.setQty(line.getQty());
}
}
else if (compare < 0)
{
drAmt = dr ? (reversal ? null : estimatedAmt) : (reversal ? estimatedAmt : null);
crAmt = dr ? (reversal ? estimatedAmt : null) : (reversal ? null : estimatedAmt);
account = pc.getAccount(ProductCost.ACCTTYPE_P_LandedCostClearing, as);
FactLine 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());
BigDecimal underAmt = estimatedAmt.subtract(allocationAmt);
drAmt = dr ? (reversal ? underAmt : null) : (reversal ? null : underAmt);
crAmt = dr ? (reversal ? null : underAmt) : (reversal ? underAmt : null);
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
else if (allocationAmt.signum() != 0)
{
drAmt = dr ? (reversal ? null : allocationAmt) : (reversal ? allocationAmt : null);
crAmt = dr ? (reversal ? allocationAmt : null) : (reversal ? null : allocationAmt);
@ -1158,7 +1387,46 @@ public class Doc_Invoice extends Doc
fl.setM_Product_ID(lca.getM_Product_ID());
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)
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.MAcctSchemaElement;
import org.compiere.model.MConversionRate;
import org.compiere.model.MCost;
import org.compiere.model.MCostDetail;
import org.compiere.model.MCostElement;
import org.compiere.model.MCurrency;
import org.compiere.model.MFactAcct;
import org.compiere.model.MInOut;
@ -389,7 +391,8 @@ public class Doc_MatchInv extends Doc
// Invoice Price Variance difference
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());
String error = createMatchInvCostDetail(as);
@ -421,15 +424,70 @@ public class Doc_MatchInv extends Doc
* @param ipv
*/
protected void processInvoicePriceVariance(MAcctSchema as, Fact fact,
BigDecimal ipv) {
BigDecimal ipv, BigDecimal ipvSource) {
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();
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);
Savepoint savepoint = null;
boolean zeroQty = false;
@ -439,7 +497,7 @@ public class Doc_MatchInv extends Doc
if (!MCostDetail.createMatchInvoice(as, m_invoiceLine.getAD_Org_ID(),
m_invoiceLine.getM_Product_ID(), m_invoiceLine.getM_AttributeSetInstance_ID(),
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.");
}
} 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);
if (m_pc.isService())
account = m_pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
if (X_M_Cost.COSTINGMETHOD_AveragePO.equals(costingMethod)) {
if (zeroQty)
account = m_pc.getAccount(ProductCost.ACCTTYPE_P_AverageCostVariance, as);
FactLine line = fact.createLine(null,
m_pc.getAccount(ProductCost.ACCTTYPE_P_IPV, as),
as.getC_Currency_ID(), ipv.negate());
updateFactLine(line);
line.setQty(getQty().negate());
line = fact.createLine(null, account, as.getC_Currency_ID(), ipv);
updateFactLine(line);
FactLine varianceLine = null;
if (amtVariance.compareTo(Env.ZERO) != 0)
{
varianceLine = fact.createLine(null,
m_pc.getAccount(ProductCost.ACCTTYPE_P_AverageCostVariance, as), as.getC_Currency_ID(),
amtVariance);
updateFactLine(varianceLine);
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);
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) {
FactLine line = fact.createLine(null,
m_pc.getAccount(ProductCost.ACCTTYPE_P_IPV, as),
as.getC_Currency_ID(), ipv.negate());
//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);
line.setQty(getQty().negate());
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),
as.getC_Currency_ID(), ipv);
updateFactLine(pv);
if (m_invoiceLine.getParent().getC_Currency_ID() != as.getC_Currency_ID())
{
updateFactLineAmtSource(pv, ipvSource);
}
}
}
/**
* Verify if the posting involves two or more organizations
* @return true if there are more than one org involved on the posting
/** Verify if the posting involves two or more organizations
@return true if there are more than one org involved on the posting
*/
private boolean isInterOrg(MAcctSchema as) {
MAcctSchemaElement elementorg = as.getAcctSchemaElement(MAcctSchemaElement.ELEMENTTYPE_Organization);
@ -907,7 +986,8 @@ public class Doc_MatchInv extends Doc
// Invoice Price Variance difference
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());
String error = createMatchInvCostDetail(as);
@ -1258,6 +1338,29 @@ public class Doc_MatchInv extends Doc
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
* @param as accounting schema

View File

@ -276,6 +276,17 @@ public class MAccount extends X_C_ValidCombination implements ImmutablePOSupport
* @return account
*/
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(),
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.getC_LocFrom_ID(), fa.getC_LocTo_ID(), fa.getC_SalesRegion_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;
} // get

View File

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

View File

@ -24,10 +24,15 @@
**********************************************************************/
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 java.math.RoundingMode;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
@ -35,6 +40,7 @@ import org.adempiere.util.ServerContext;
import org.compiere.Adempiere;
import org.compiere.model.MAcctSchema;
import org.compiere.model.MClientInfo;
import org.compiere.model.MFactAcct;
import org.compiere.model.MRole;
import org.compiere.util.Env;
import org.compiere.util.Language;
@ -239,4 +245,104 @@ public abstract class AbstractTestCase {
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.RoundingMode;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.List;
import org.compiere.acct.Doc;
@ -70,6 +71,7 @@ import org.compiere.wf.MWorkflow;
import org.idempiere.test.AbstractTestCase;
import org.idempiere.test.ConversionRateHelper;
import org.idempiere.test.DictionaryIDs;
import org.idempiere.test.FactAcct;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.ResourceLock;
@ -146,23 +148,14 @@ public class InOutTest extends AbstractTestCase {
doc.setC_BPartner_ID(receipt.getC_BPartner_ID());
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())
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
BigDecimal acctAmount = acctSource.multiply(rate)
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
assertTrue(fa.getAmtSourceCr().compareTo(acctSource) == 0, fa.getAmtSourceCr().toPlainString() + " != " + acctSource.toPlainString());
assertTrue(fa.getAmtAcctCr().compareTo(acctAmount) == 0, fa.getAmtAcctCr().toPlainString() + " != " + acctAmount.toPlainString());
}
}
}
BigDecimal acctSource = orderLine.getPriceActual().multiply(receiptLine.getMovementQty())
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
BigDecimal acctAmount = acctSource.multiply(rate)
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, receipt.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
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);
@ -185,23 +178,14 @@ public class InOutTest extends AbstractTestCase {
doc.setC_BPartner_ID(receipt.getC_BPartner_ID());
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);
BigDecimal acctAmount = acctSource.multiply(rate)
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
assertTrue(fa.getAmtSourceCr().compareTo(acctSource) == 0, fa.getAmtSourceCr().toPlainString() + " != " + acctSource.toPlainString());
assertTrue(fa.getAmtAcctCr().compareTo(acctAmount) == 0, fa.getAmtAcctCr().toPlainString() + " != " + acctAmount.toPlainString());
}
}
}
BigDecimal acctAmount = acctSource.multiply(rate)
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, receipt.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
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 {
rollback();
@ -276,20 +260,14 @@ public class InOutTest extends AbstractTestCase {
doc.setC_BPartner_ID(receipt.getC_BPartner_ID());
MAccount acctNIR = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as);
BigDecimal acctSource = orderLine.getPriceActual().multiply(receiptLine.getMovementQty())
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
BigDecimal acctAmount = acctSource.multiply(rate)
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
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())
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
BigDecimal acctAmount = acctSource.multiply(rate)
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
assertTrue(fa.getAmtSourceCr().compareTo(acctSource) == 0, fa.getAmtSourceCr().toPlainString() + " != " + acctSource.toPlainString());
assertTrue(fa.getAmtAcctCr().compareTo(acctAmount) == 0, fa.getAmtAcctCr().toPlainString() + " != " + acctAmount.toPlainString());
}
}
}
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());
@ -343,19 +321,14 @@ public class InOutTest extends AbstractTestCase {
doc.setC_BPartner_ID(delivery.getC_BPartner_ID());
MAccount acctNIR = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as);
BigDecimal acctSource = orderLine.getPriceActual().multiply(deliveryLine.getMovementQty())
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
BigDecimal acctAmount = acctSource.multiply(rate)
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
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())
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
BigDecimal acctAmount = acctSource.multiply(rate)
.setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP);
assertTrue(fa.getAmtAcctDr().compareTo(acctAmount) == 0, fa.getAmtAcctDr().toPlainString() + " != " + acctAmount.toPlainString());
}
}
}
List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, acctAmount, null, 2, true, deliveryLine.get_ID()));
assertFactAcctEntries(fas, expected);
}
} finally {
rollback();

View File

@ -34,6 +34,7 @@ import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import org.compiere.acct.Doc;
import org.compiere.acct.DocManager;
@ -59,6 +60,7 @@ import org.compiere.model.MProductPrice;
import org.compiere.model.MWarehouse;
import org.compiere.model.PO;
import org.compiere.model.ProductCost;
import org.compiere.model.Query;
import org.compiere.process.DocAction;
import org.compiere.process.DocumentEngine;
import org.compiere.process.ProcessInfo;
@ -1840,12 +1842,9 @@ public class MatchInv2ndAcctSchemaTest extends AbstractTestCase {
BigDecimal totalNIRAmtAcct = Env.ZERO;
BigDecimal totalInvClrAmtAcct = Env.ZERO;
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.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());
Query query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
for (MFactAcct fa : factAccts) {
if (acctNIR.getAccount_ID() == fa.getAccount_ID())
totalNIRAmtAcct = totalNIRAmtAcct.add(fa.getAmtAcctDr()).subtract(fa.getAmtAcctCr());
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.RoundingMode;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.List;
import org.compiere.acct.Doc;
import org.compiere.acct.DocManager;
@ -63,9 +65,11 @@ import org.compiere.process.DocAction;
import org.compiere.process.DocumentEngine;
import org.compiere.process.ProcessInfo;
import org.compiere.util.Env;
import org.compiere.util.TimeUtil;
import org.compiere.wf.MWorkflow;
import org.idempiere.test.AbstractTestCase;
import org.idempiere.test.DictionaryIDs;
import org.idempiere.test.FactAcct;
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());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.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 (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());
}
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, credMatchAmt, 2, false), new FactAcct(acctInvClr, credMatchAmt, 2, true));
assertFactAcctEntries(factAccts, expected);
}
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());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.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 (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());
}
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, invMatchAmt, 2, true), new FactAcct(acctInvClr, invMatchAmt, 2, false));
assertFactAcctEntries(factAccts, expected);
}
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());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.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 (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");
}
}
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(acctInvClr, invMatchAmt, 2, false, mi.getQty().negate()),
new FactAcct(acctNIR, invMatchAmt, 2, true, mi.getQty()));
assertFactAcctEntries(factAccts, expected);
}
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());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
BigDecimal amtAcctDrInvClr = BigDecimal.ZERO;
BigDecimal amtAcctCrInvClr = BigDecimal.ZERO;
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.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 (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);
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(acctInvClr, credMatchAmt, 2, false, mi.getQty()),
new FactAcct(acctInvClr, credMatchAmt, 2, true, mi.getQty().negate()));
assertFactAcctEntries(factAccts, expected);
}
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());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.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 (fa.getAccount_ID() == acctNIR.getAccount_ID()) {
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());
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());
}
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, acctAmount, acctSource, 2, true),
new FactAcct(acctInvClr, acctAmount, acctSource, 2, false));
assertFactAcctEntries(factAccts, expected);
assertTrue(acctAmount.compareTo(Env.ZERO) >= 0);
for (MFactAcct fa : factAccts) {
assertTrue(fa.getC_Currency_ID() == japaneseYen.getC_Currency_ID());
}
}
} finally {
@ -1042,26 +996,205 @@ public class MatchInvTest extends AbstractTestCase {
ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName());
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.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 (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");
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, invMatchAmt, 2, !mi.isReversal(), mi.getQty()),
new FactAcct(acctInvClr, invMatchAmt, 2, mi.isReversal(), mi.getQty().negate()));
assertFactAcctEntries(factAccts, expected);
}
}
@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);
}
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");
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.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import org.compiere.acct.Doc;
import org.compiere.acct.DocManager;
@ -42,6 +47,8 @@ import org.compiere.model.MBPartner;
import org.compiere.model.MClient;
import org.compiere.model.MConversionRate;
import org.compiere.model.MCost;
import org.compiere.model.MCostElement;
import org.compiere.model.MCurrency;
import org.compiere.model.MDocType;
import org.compiere.model.MFactAcct;
import org.compiere.model.MInOut;
@ -53,19 +60,26 @@ import org.compiere.model.MInvoiceLine;
import org.compiere.model.MMatchInv;
import org.compiere.model.MOrder;
import org.compiere.model.MOrderLine;
import org.compiere.model.MPriceList;
import org.compiere.model.MPriceListVersion;
import org.compiere.model.MProduct;
import org.compiere.model.MProductCategory;
import org.compiere.model.MProductCategoryAcct;
import org.compiere.model.MProductPrice;
import org.compiere.model.MWarehouse;
import org.compiere.model.ProductCost;
import org.compiere.model.Query;
import org.compiere.process.DocAction;
import org.compiere.process.DocumentEngine;
import org.compiere.process.ProcessInfo;
import org.compiere.util.CacheMgt;
import org.compiere.util.Env;
import org.compiere.util.TimeUtil;
import org.compiere.wf.MWorkflow;
import org.idempiere.test.AbstractTestCase;
import org.idempiere.test.ConversionRateHelper;
import org.idempiere.test.DictionaryIDs;
import org.idempiere.test.FactAcct;
import org.junit.jupiter.api.Test;
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);
int C_AcctSchema_ID = as.getC_AcctSchema_ID();
String whereClause2 = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + C_AcctSchema_ID;
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause2, getTrxName());
Query query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, mi.get_ID(), C_AcctSchema_ID, getTrxName());
List<MFactAcct> factAccts = query.list();
BigDecimal invMatchAmt = invoiceLine.getMatchedQty().multiply(invoiceLine.getPriceActual()).setScale(as.getStdPrecision(), RoundingMode.HALF_UP);
mulchCost = mulchCost.setScale(as.getStdPrecision(), RoundingMode.HALF_UP);
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), 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), "");
}
List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, mulchCost, 2, true), new FactAcct(acctInvClr, invMatchAmt, 2, false),
new FactAcct(acctIPV, invMatchAmt.subtract(mulchCost), 2, true));
assertFactAcctEntries(factAccts, expected);
}
} finally {
getTrx().rollback();
@ -263,4 +269,617 @@ public class MatchInvTestIsolated extends AbstractTestCase {
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.RoundingMode;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.List;
import org.compiere.acct.Doc;
@ -67,6 +68,7 @@ import org.eevolution.model.MPPProductBOM;
import org.eevolution.model.MPPProductBOMLine;
import org.idempiere.test.AbstractTestCase;
import org.idempiere.test.DictionaryIDs;
import org.idempiere.test.FactAcct;
import org.junit.jupiter.api.Test;
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());
MAccount productExpense = pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
StringBuilder whereClause = new StringBuilder();
whereClause
.append(MFactAcct.COLUMNNAME_AD_Table_ID)
.append("=")
.append(MInOut.Table_ID)
.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), "");
}
}
Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, rLine.getM_InOut_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, BD_20, 2, false, new BigDecimal("-10.00")),
new FactAcct(productExpense, BD_20, 2, true, BigDecimal.TEN));
assertFactAcctEntries(factAccts, expected);
}
finally
{
@ -379,27 +354,11 @@ public class NonStockedExpTypeAvgPOCostingTest extends AbstractTestCase
// get AccPayable of the Invoice
MAccount acctPT = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getV_Liability_Acct(), getTrxName());
String whereClause = "AD_Table_ID = " + MInvoice.Table_ID;
whereClause += " AND Record_ID = " + iLine.getC_Invoice_ID();
whereClause += " AND C_AcctSchema_ID = " + 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), "");
}
}
Query query = MFactAcct.createRecordIdQuery(MInvoice.Table_ID, iLine.getC_Invoice_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctPT, BD_20, 2, false, BigDecimal.ZERO),
new FactAcct(productExpense, BD_20, 2, true, BigDecimal.TEN));
assertFactAcctEntries(factAccts, expected);
// Testing Accounting For MatchInv
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
pc = new ProductCost(Env.getCtx(), matchInvoices[0].getM_Product_ID(), 0, getTrxName());
productExpense = pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
whereClause = null;
whereClause = "AD_Table_ID = " + MMatchInv.Table_ID;
whereClause += " AND Record_ID = " + matchInvoices[0].get_ID();
whereClause += " AND C_AcctSchema_ID = " + 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), "");
}
}
query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, matchInvoices[0].get_ID(), as.getC_AcctSchema_ID(), getTrxName());
factAccts = query.list();
expected = Arrays.asList(new FactAcct(acctNIR, BD_20, 2, true, BigDecimal.TEN),
new FactAcct(productExpense, BD_20, 2, false, BigDecimal.TEN.negate()));
assertFactAcctEntries(factAccts, expected);
}
finally
{

View File

@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.fail;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.List;
import org.compiere.acct.Doc;
@ -68,6 +69,7 @@ import org.eevolution.model.MPPProductBOM;
import org.eevolution.model.MPPProductBOMLine;
import org.idempiere.test.AbstractTestCase;
import org.idempiere.test.DictionaryIDs;
import org.idempiere.test.FactAcct;
import org.junit.jupiter.api.Test;
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());
MAccount productExpense = pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
StringBuilder whereClause = new StringBuilder();
whereClause
.append(MFactAcct.COLUMNNAME_AD_Table_ID)
.append("=")
.append(MInOut.Table_ID)
.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), "");
}
}
Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, rLine.getM_InOut_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctNIR, BD_20, 2, false, BigDecimal.TEN.negate()),
new FactAcct(productExpense, BD_20, 2, true, BigDecimal.TEN));
assertFactAcctEntries(factAccts, expected);
}
finally
{
@ -377,38 +352,11 @@ public class NonStockedExpTypeStdCostingTest extends AbstractTestCase
// get AccPayable of the Invoice
MAccount acctPT = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getV_Liability_Acct(), getTrxName());
StringBuilder whereClause = new StringBuilder();
whereClause
.append(MFactAcct.COLUMNNAME_AD_Table_ID)
.append("=")
.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), "");
}
}
Query query = MFactAcct.createRecordIdQuery(MInvoice.Table_ID, iLine.getC_Invoice_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctPT, BD_20, 2, false, BigDecimal.ZERO),
new FactAcct(productExpense, BD_20, 2, true, BigDecimal.TEN));
assertFactAcctEntries(factAccts, expected);
//Accounting MatchInv
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());
productExpense = pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
whereClause = null;
whereClause = new StringBuilder();
whereClause
.append(MFactAcct.COLUMNNAME_AD_Table_ID)
.append("=")
.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), "");
}
}
query = MFactAcct.createRecordIdQuery(MMatchInv.Table_ID, matchInvoices[0].get_ID(), as.getC_AcctSchema_ID(), getTrxName());
factAccts = query.list();
expected = Arrays.asList(new FactAcct(acctNIR, BD_20, 2, true, BigDecimal.TEN),
new FactAcct(productExpense, BD_20, 2, false, BigDecimal.TEN.negate()));
assertFactAcctEntries(factAccts, expected);
}
finally
{

View File

@ -34,6 +34,7 @@ import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import org.compiere.acct.Doc;
import org.compiere.acct.DocManager;
@ -1453,11 +1454,11 @@ public class Allocation2ndAcctSchemaTest extends AbstractTestCase {
BigDecimal allocAmount = new BigDecimal(1000);
ArrayList<PostingLine> tradeLineList = 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());
tradeLineList.add(new PostingLine(usd, accountedDrAmt, Env.ZERO));
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));
testAllocationPosting(ass, allocList, null, tradeLineList, gainLossLineList, null);
@ -2181,12 +2182,9 @@ public class Allocation2ndAcctSchemaTest extends AbstractTestCase {
BigDecimal totalTradeAmtAcct = Env.ZERO;
BigDecimal totalGainLossAmtAcct = Env.ZERO;
BigDecimal totalCurrBalAmtAcct = Env.ZERO;
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + alloc.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());
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, alloc.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
for (MFactAcct fa : factAccts) {
if (C_Charge_ID != 0 && acctCharge != null && acctCharge.getAccount_ID() == fa.getAccount_ID())
totalPaymentAmtAcct = totalPaymentAmtAcct.add(fa.getAmtAcctDr()).subtract(fa.getAmtAcctCr());
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.RoundingMode;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Properties;
import java.util.logging.LogRecord;
@ -64,6 +66,7 @@ import org.compiere.wf.MWorkflow;
import org.idempiere.test.AbstractTestCase;
import org.idempiere.test.ConversionRateHelper;
import org.idempiere.test.DictionaryIDs;
import org.idempiere.test.FactAcct;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Isolated;
import org.junit.jupiter.api.parallel.ResourceLock;
@ -459,12 +462,9 @@ public class AllocationTest extends AbstractTestCase {
BigDecimal ucAmtAcctCr = new BigDecimal(31000);
BigDecimal lossAmtAcct = new BigDecimal(1000);
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocation.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());
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocation.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
for (MFactAcct fa : factAccts) {
if (acctUC.getAccount_ID() == fa.getAccount_ID()) {
if (fa.getAmtAcctDr().signum() > 0)
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);
BigDecimal tradeAmtAcct = new BigDecimal(2.13).setScale(usd.getStdPrecision(), RoundingMode.HALF_UP);;
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocation.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());
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocation.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
for (MFactAcct fa : factAccts) {
if (acctLiability.getAccount_ID() == fa.getAccount_ID()) {
if (fa.getAmtAcctDr().signum() > 0)
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 lossAmtAcct = new BigDecimal(1000);
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocation.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());
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocation.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
for (MFactAcct fa : factAccts) {
if (acctUC.getAccount_ID() == fa.getAccount_ID()) {
if (fa.getAmtAcctDr().signum() > 0)
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 acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Due_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + alloc.get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID()
+ " 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(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"));
}
}
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, alloc.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctUC, new BigDecimal("102.00"), 2, true),
new FactAcct(acctDEP, new BigDecimal("2.00"), 2, true), new FactAcct(acctDEP, new BigDecimal("0.11"), 2, false),
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(acctTD, new BigDecimal("0.11"), 2, true));
assertFactAcctEntries(factAccts, expected);
}
} finally {
@ -1028,42 +993,14 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctART = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getC_Receivable_Acct(), getTrxName());
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Due_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + alloc.get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID()
+ " 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(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"));
}
}
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, alloc.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctPS, new BigDecimal("-102.00"), 2, true),
new FactAcct(acctDEP, new BigDecimal("2.00").negate(), 2, true), new FactAcct(acctDEP, new BigDecimal("0.11"), 2, true),
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),
new FactAcct(acctTD, new BigDecimal("0.11"), 2, false));
assertFactAcctEntries(factAccts, expected);
}
} finally {
@ -1158,42 +1095,14 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctPS = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getB_PaymentSelect_Acct(), getTrxName());
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Credit_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + alloc.get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID()
+ " 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(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"));
}
}
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, alloc.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctPT, new BigDecimal("106.00"), 2, true),
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),
new FactAcct(acctPS, new BigDecimal("102.00"), 2, false),
new FactAcct(acctTD, new BigDecimal("0.11"), 2, false));
assertFactAcctEntries(factAccts, expected);
}
} finally {
@ -1288,44 +1197,15 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctUC = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getB_UnallocatedCash_Acct(), getTrxName());
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Credit_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + alloc.get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID()
+ " 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(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"));
}
}
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, alloc.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctPT, new BigDecimal("106.00").negate(), 2, true),
new FactAcct(acctDRE, new BigDecimal("2.00").negate(), 2, false), new FactAcct(acctDRE, new BigDecimal("0.11"), 2, false),
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),
new FactAcct(acctTD, new BigDecimal("0.11"), 2, true));
assertFactAcctEntries(factAccts, expected);
}
} finally {
rollback();
@ -1419,43 +1299,14 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctART = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getC_Receivable_Acct(), getTrxName());
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Due_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocationa[0].get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID()
+ " 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(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"));
}
}
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocationa[0].get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctUC, new BigDecimal("102.00"), 2, true),
new FactAcct(acctDEP, new BigDecimal("2.00"), 2, true), new FactAcct(acctDEP, new BigDecimal("0.11"), 2, false),
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(acctTD, new BigDecimal("0.11"), 2, true));
assertFactAcctEntries(factAccts, expected);
}
} finally {
@ -1545,48 +1396,20 @@ public class AllocationTest extends AbstractTestCase {
// 78100_Bad Debts Write-off | 0.11 | 0.00
// 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 acctWO = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getWriteOff_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());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocationa[0].get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID()
+ " 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(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"));
}
}
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocationa[0].get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctPS, new BigDecimal("102.00").negate(), 2, true),
new FactAcct(acctDEP, new BigDecimal("2.00").negate(), 2, true), new FactAcct(acctDEP, new BigDecimal("0.11"), 2, true),
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),
new FactAcct(acctTD, new BigDecimal("0.11"), 2, false));
assertFactAcctEntries(factAccts, expected);
}
} finally {
@ -1682,42 +1505,14 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctPS = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getB_PaymentSelect_Acct(), getTrxName());
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Credit_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocationa[0].get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID()
+ " 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(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"));
}
}
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocationa[0].get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctPT, new BigDecimal("106.00"), 2, true),
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),
new FactAcct(acctPS, new BigDecimal("102.00"), 2, false),
new FactAcct(acctTD, new BigDecimal("0.11"), 2, false));
assertFactAcctEntries(factAccts, expected);
}
} finally {
@ -1810,45 +1605,17 @@ public class AllocationTest extends AbstractTestCase {
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 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());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocationa[0].get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID()
+ " 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(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"));
}
}
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocationa[0].get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctPT, new BigDecimal("106.00").negate(), 2, true),
new FactAcct(acctDRE, new BigDecimal("2.00").negate(), 2, false), new FactAcct(acctDRE, new BigDecimal("0.11"), 2, false),
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),
new FactAcct(acctTD, new BigDecimal("0.11"), 2, true));
assertFactAcctEntries(factAccts, expected);
}
} finally {
@ -1932,60 +1699,29 @@ public class AllocationTest extends AbstractTestCase {
// 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
// 12110 Accounts Receivable - Trade | 0.00 | 106.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
// 78100_Bad Debts Write-off | 0.00 | 0.11
// 12110_Accounts Receivable - Trade | 0.00 | -102.00
// --------------------------------------------------------------------
// ToDo: set Account
MAccount acctDRE = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getPayDiscount_Rev_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());
doc.setC_BPartner_ID(bpartner.getC_BPartner_ID());
MAccount acctDRE = doc.getAccount(Doc.ACCTTYPE_DiscountExp, as);
MAccount acctWO = doc.getAccount(Doc.ACCTTYPE_WriteOff, as);
MAccount acctART = doc.getAccount(Doc.ACCTTYPE_C_Receivable, as);
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Due_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + alloc.get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID()
+ " 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(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"));
}
}
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, alloc.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctDRE, new BigDecimal("2.00"), 2, true),
new FactAcct(acctDRE, new BigDecimal("0.11"), 2, false),
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),
new FactAcct(acctTD, new BigDecimal("0.11"), 2, true));
assertFactAcctEntries(factAccts, expected);
}
} finally {
@ -2085,43 +1821,14 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctWO = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getWriteOff_Acct(), getTrxName());
MAccount acctTD = new MAccount(Env.getCtx(), as.getAcctSchemaDefault().getT_Credit_Acct(), getTrxName());
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + alloc.get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID()
+ " 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(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"));
}
}
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, alloc.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctPT, new BigDecimal("106.00"), 2, true),
new FactAcct(acctPT, new BigDecimal("-102.00"), 2, true),
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),
new FactAcct(acctTD, new BigDecimal("0.11"), 2, false));
assertFactAcctEntries(factAccts, expected);
}
} finally {
@ -2242,18 +1949,10 @@ public class AllocationTest extends AbstractTestCase {
MAccount acctUC = doc.getAccount(Doc.ACCTTYPE_UnallocatedCash, as);
BigDecimal ucAmtAcctDr = new BigDecimal(370.88).setScale(2, RoundingMode.HALF_UP);
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocation.get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID()
+ " 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 (fa.getAmtAcctDr().signum() > 0)
assertTrue(fa.getAmtAcctDr().compareTo(ucAmtAcctDr) == 0, fa.getAmtAcctDr().toPlainString() + "!=" + ucAmtAcctDr.toPlainString());
}
}
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocation.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
List<FactAcct> expected = Arrays.asList(new FactAcct(acctUC, ucAmtAcctDr, 2, true));
assertFactAcctEntries(factAccts, expected);
}
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 ucAmtAcctCr = new BigDecimal(0.01).setScale(2, RoundingMode.HALF_UP);
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MAllocationHdr.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + allocation.get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID()
+ " ORDER BY Created";
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
for (int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
Query query = MFactAcct.createRecordIdQuery(MAllocationHdr.Table_ID, allocation.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
for (MFactAcct fa : factAccts) {
if (acctUC.getAccount_ID() == fa.getAccount_ID()) {
if (fa.getAmtAcctDr().signum() > 0)
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.RoundingMode;
import java.util.List;
import java.util.Properties;
import org.adempiere.base.Core;
@ -58,6 +59,7 @@ import org.compiere.model.MTax;
import org.compiere.model.MTaxCategory;
import org.compiere.model.MWarehouse;
import org.compiere.model.ProductCost;
import org.compiere.model.Query;
import org.compiere.model.Tax;
import org.compiere.model.X_C_Order;
import org.compiere.process.DocAction;
@ -325,13 +327,10 @@ public class MTaxTest extends AbstractTestCase {
assertEquals(expectedCost, averageCost, "Un-expected average cost");
MAccount acctAsset = productCost.getAccount(ProductCost.ACCTTYPE_P_Asset, schema);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MInOut.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + receipt.get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + schema.getC_AcctSchema_ID();
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, receipt.get_ID(), schema.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
BigDecimal totalDebit = new BigDecimal("0.00");
for(int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
for(MFactAcct fa : factAccts) {
if (fa.getAccount_ID() == acctAsset.getAccount_ID()) {
totalDebit = totalDebit.add(fa.getAmtAcctDr());
}
@ -470,13 +469,10 @@ public class MTaxTest extends AbstractTestCase {
assertEquals(expectedCost, averageCost, "Un-expected average cost");
MAccount acctAsset = productCost.getAccount(ProductCost.ACCTTYPE_P_Asset, schema);
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MInOut.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + receipt.get_ID()
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + schema.getC_AcctSchema_ID();
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
Query query = MFactAcct.createRecordIdQuery(MInOut.Table_ID, receipt.get_ID(), schema.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
BigDecimal totalDebit = new BigDecimal("0.00");
for(int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
for(MFactAcct fa : factAccts) {
if (fa.getAccount_ID() == acctAsset.getAccount_ID()) {
totalDebit = totalDebit.add(fa.getAmtAcctDr());
}

View File

@ -33,6 +33,7 @@ import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.util.List;
import java.util.Optional;
import org.compiere.model.MAccount;
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());
MAccount acctVariance = pc.getAccount(ProductCost.ACCTTYPE_P_RateVariance, as);
whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MProduction.Table_ID
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + production.get_ID()
+ " 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());
Query query = MFactAcct.createRecordIdQuery(MProduction.Table_ID, production.get_ID(), as.getC_AcctSchema_ID(), getTrxName());
List<MFactAcct> factAccts = query.list();
BigDecimal variance = BigDecimal.ZERO;
for (int id : ids) {
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
variance = fa.getAmtAcctDr().subtract(fa.getAmtAcctCr());
break;
}
Optional<MFactAcct> optional = factAccts.stream().filter(e -> e.getAccount_ID() == acctVariance.getAccount_ID()).findFirst();
if (optional.isPresent())
variance = optional.get().getAmtAcctDr().subtract(optional.get().getAmtAcctCr());
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.");
} finally {