Skip to content

Commit

Permalink
consider C_Tax_Acct.T_Revenue_Acct if set
Browse files Browse the repository at this point in the history
that account will override product's revenue account when posting sales invoice

more:
* introduced C_Tax_Acct_ID PK because we want to cache invalidate when record is changed
* QA + refactor

#5924
  • Loading branch information
teosarca committed Dec 19, 2019
1 parent 83657f6 commit d063f39
Show file tree
Hide file tree
Showing 13 changed files with 1,053 additions and 421 deletions.
Expand Up @@ -41,10 +41,13 @@

import de.metas.acct.api.AccountId;
import de.metas.acct.api.AcctSchema;
import de.metas.acct.api.AcctSchemaId;
import de.metas.acct.api.IAccountDAO;
import de.metas.acct.api.IProductAcctDAO;
import de.metas.acct.api.ProductAcctType;
import de.metas.acct.doc.PostingException;
import de.metas.acct.tax.ITaxAcctBL;
import de.metas.acct.tax.TaxAcctType;
import de.metas.bpartner.BPartnerId;
import de.metas.costing.CostingLevel;
import de.metas.costing.CostingMethod;
Expand All @@ -60,6 +63,7 @@
import de.metas.product.ProductId;
import de.metas.product.acct.api.ActivityId;
import de.metas.quantity.Quantity;
import de.metas.tax.api.TaxId;
import de.metas.uom.UomId;
import de.metas.util.NumberUtils;
import de.metas.util.Optionals;
Expand All @@ -83,6 +87,7 @@ public class DocLine<DT extends Doc<? extends DocLine<?>>>
protected final transient IProductBL productBL = Services.get(IProductBL.class);
private final transient IProductAcctDAO productAcctDAO = Services.get(IProductAcctDAO.class);
private final transient IProductCostingBL productCostingBL = Services.get(IProductCostingBL.class);
private final ITaxAcctBL taxAcctBL = Services.get(ITaxAcctBL.class);
private final transient IAccountDAO accountDAO = Services.get(IAccountDAO.class);

/** Persistent Object */
Expand Down Expand Up @@ -412,6 +417,17 @@ public MAccount getAccount(final ProductAcctType acctType, final AcctSchema as)

private MAccount getProductAccount(final ProductAcctType acctType, final AcctSchema as)
{
//
// Product Revenue: check/use the override defined on tax level
if (acctType == ProductAcctType.Revenue)
{
final MAccount productRevenueAcct = getTaxAccount(TaxAcctType.ProductRevenue_Override, as.getId()).orElse(null);
if (productRevenueAcct != null)
{
return productRevenueAcct;
}
}

// No Product - get Default from Product Category
final ProductId productId = getProductId();
if (productId == null)
Expand Down Expand Up @@ -448,6 +464,14 @@ private final MAccount getAccountDefault(final ProductAcctType acctType, final A
return accountDAO.getById(validCombinationId);
}

private final Optional<MAccount> getTaxAccount(@NonNull final TaxAcctType taxAcctType, final AcctSchemaId acctSchemaId)
{
final TaxId taxId = TaxId.ofRepoIdOrNull(getC_Tax_ID());
return taxId != null
? taxAcctBL.getAccountIfExists(taxId, acctSchemaId, taxAcctType)
: Optional.empty();
}

/**
* Get Charge
*
Expand Down
Expand Up @@ -17,13 +17,15 @@
package org.compiere.acct;

import java.math.BigDecimal;
import java.util.Properties;

import org.compiere.model.MAccount;

import de.metas.acct.api.AcctSchema;
import de.metas.acct.tax.ITaxAcctBL;
import de.metas.acct.tax.TaxAcctType;
import de.metas.tax.api.TaxId;
import de.metas.util.Services;
import lombok.NonNull;

/**
* Document Tax Line
Expand All @@ -38,29 +40,16 @@ public final class DocTax

// private static final transient Logger log = CLogMgt.getLogger(DocTax.class);

/**
* Create Tax
*
* @param C_Tax_ID tax
* @param taxName tax name
* @param taxRate rate
* @param taxBaseAmt tax base amount
* @param taxAmt tax amount
* @param salesTax sales tax flag
* @param taxIncluded
*/
public DocTax(final Properties ctx,
final int C_Tax_ID,
public DocTax(
@NonNull final TaxId taxId,
final String taxName,
final BigDecimal taxRate,
final BigDecimal taxBaseAmt, final BigDecimal taxAmt,
final BigDecimal taxBaseAmt,
final BigDecimal taxAmt,
final boolean salesTax,
final boolean taxIncluded)
{
super();

m_ctx = ctx;
m_C_Tax_ID = C_Tax_ID;
this.taxId = taxId;
m_taxName = taxName;
m_taxRate = taxRate;
m_taxBaseAmt = taxBaseAmt;
Expand All @@ -69,9 +58,7 @@ public DocTax(final Properties ctx,
this.m_taxIncluded = taxIncluded;
} // DocTax

private final Properties m_ctx;
/** Tax ID */
private final int m_C_Tax_ID;
private final TaxId taxId;
/** Amount */
private final BigDecimal m_taxAmt;
/** Tax Rate */
Expand All @@ -86,42 +73,14 @@ public DocTax(final Properties ctx,
private final boolean m_salesTax;
private final boolean m_taxIncluded;

/** Tax Due Acct */
public static final int ACCTTYPE_TaxDue = ITaxAcctBL.ACCTTYPE_TaxDue;
/** Tax Liability */
public static final int ACCTTYPE_TaxLiability = ITaxAcctBL.ACCTTYPE_TaxLiability;
/** Tax Credit */
public static final int ACCTTYPE_TaxCredit = ITaxAcctBL.ACCTTYPE_TaxCredit;
/** Tax Receivables */
public static final int ACCTTYPE_TaxReceivables = ITaxAcctBL.ACCTTYPE_TaxReceivables;
/** Tax Expense */
public static final int ACCTTYPE_TaxExpense = ITaxAcctBL.ACCTTYPE_TaxExpense;

private final Properties getCtx()
{
return m_ctx;
}

/**
* Get Account
*
* @param acctType see ACCTTYPE_*
* @param as account schema
* @return Account
*/
public MAccount getAccount(final int acctType, final AcctSchema as)
{
return taxAcctBL.getAccount(getCtx(), getC_Tax_ID(), as.getId(), acctType);
} // getAccount

public MAccount getAccount(final AcctSchema as)
{
return taxAcctBL.getAccount(getCtx(), getC_Tax_ID(), as.getId(), getAPTaxType());
return taxAcctBL.getAccount(getTaxId(), as.getId(), getAPTaxType());
}

public MAccount getTaxDueAcct(final AcctSchema as)
{
return taxAcctBL.getAccount(getCtx(), getC_Tax_ID(), as.getId(), ACCTTYPE_TaxDue);
return taxAcctBL.getAccount(getTaxId(), as.getId(), TaxAcctType.TaxDue);
}

/**
Expand Down Expand Up @@ -162,15 +121,15 @@ public String getTaxName()
return m_taxName;
}

/**
* Get C_Tax_ID
*
* @return tax id
*/
public TaxId getTaxId()
{
return taxId;
}

public int getC_Tax_ID()
{
return m_C_Tax_ID;
} // getC_Tax_ID
return getTaxId().getRepoId();
}

/**
* Get Description (Tax Name and Base Amount)
Expand Down Expand Up @@ -213,16 +172,12 @@ public boolean isIncludedTaxDifference()
} // isIncludedTaxDifference

/**
* Get AP Tax Type
*
* @return AP tax type (Credit or Expense)
*/
public int getAPTaxType()
private TaxAcctType getAPTaxType()
{
if (isSalesTax())
return ACCTTYPE_TaxExpense;
return ACCTTYPE_TaxCredit;
} // getAPTaxAcctType
return isSalesTax() ? TaxAcctType.TaxExpense : TaxAcctType.TaxCredit;
}

/**
* Is Sales Tax
Expand Down
Expand Up @@ -41,7 +41,6 @@
import org.compiere.model.MPeriod;
import org.compiere.util.DB;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;

import com.google.common.collect.ImmutableList;

Expand All @@ -52,6 +51,7 @@
import de.metas.acct.api.ProductAcctType;
import de.metas.acct.doc.AcctDocContext;
import de.metas.acct.doc.DocLine_Invoice;
import de.metas.tax.api.TaxId;
import de.metas.util.Services;

/**
Expand Down Expand Up @@ -126,7 +126,7 @@ private List<DocTax> loadTaxes()
final ImmutableList.Builder<DocTax> docTaxes = ImmutableList.builder();
while (rs.next())
{
final int C_Tax_ID = rs.getInt(1);
final TaxId taxId = TaxId.ofRepoId(rs.getInt(1));
final String taxName = rs.getString(2);
final BigDecimal rate = rs.getBigDecimal(3);
final BigDecimal taxBaseAmt = rs.getBigDecimal(4);
Expand All @@ -135,8 +135,7 @@ private List<DocTax> loadTaxes()
final boolean taxIncluded = DisplayType.toBoolean(rs.getString(7));
//
final DocTax taxLine = new DocTax(
Env.getCtx(),
C_Tax_ID, taxName, rate,
taxId, taxName, rate,
taxBaseAmt, taxAmt, salesTax, taxIncluded);
docTaxes.add(taxLine);
}
Expand Down
Expand Up @@ -41,6 +41,7 @@
import de.metas.order.IOrderLineBL;
import de.metas.quantity.Quantity;
import de.metas.tax.api.ITaxBL;
import de.metas.tax.api.TaxId;
import de.metas.util.Services;

/**
Expand Down Expand Up @@ -177,16 +178,16 @@ private List<DocTax> loadTaxes()
final ImmutableList.Builder<DocTax> list = ImmutableList.builder();
while (rs.next())
{
int C_Tax_ID = rs.getInt(1);
final TaxId taxId = TaxId.ofRepoId(rs.getInt(1));
String name = rs.getString(2);
BigDecimal rate = rs.getBigDecimal(3);
BigDecimal taxBaseAmt = rs.getBigDecimal(4);
BigDecimal amount = rs.getBigDecimal(5);
boolean salesTax = DisplayType.toBoolean(rs.getString(6));
final boolean taxIncluded = DisplayType.toBoolean(rs.getString(7));
//
final DocTax taxLine = new DocTax(Env.getCtx(),
C_Tax_ID, name, rate,
final DocTax taxLine = new DocTax(
taxId, name, rate,
taxBaseAmt, amount, salesTax, taxIncluded);
list.add(taxLine);
}
Expand Down
Expand Up @@ -13,29 +13,29 @@
*
* 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
* 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, see
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/


import java.math.BigDecimal;
import java.util.Properties;

import org.compiere.model.I_C_ElementValue;
import org.compiere.model.I_C_Tax;
import org.compiere.model.I_C_ValidCombination;
import org.compiere.util.Env;
import org.compiere.model.MAccount;

import de.metas.acct.api.AcctSchemaId;
import de.metas.acct.tax.ITaxAccountable;
import de.metas.acct.tax.ITaxAcctBL;
import de.metas.acct.tax.TaxAcctType;
import de.metas.currency.CurrencyPrecision;
import de.metas.tax.api.ITaxBL;
import de.metas.tax.api.TaxId;
import de.metas.util.Services;

/**
Expand Down Expand Up @@ -144,15 +144,15 @@ public void onTaxTotalAmt(final ITaxAccountable taxAccountable)
*/
public void onC_Tax_ID(final ITaxAccountable taxAccountable)
{
final int taxAcctType;
final TaxAcctType taxAcctType;
if (taxAccountable.isAccountSignDR())
{
taxAcctType = ITaxAcctBL.ACCTTYPE_TaxCredit;
// taxAcctType = ITaxAcctBL.ACCTTYPE_TaxExpense; // used for booking services tax
taxAcctType = TaxAcctType.TaxCredit;
// taxAcctType = TaxAcctType.TaxExpense; // used for booking services tax
}
else if (taxAccountable.isAccountSignCR())
{
taxAcctType = ITaxAcctBL.ACCTTYPE_TaxDue;
taxAcctType = TaxAcctType.TaxDue;
}
else
{
Expand All @@ -161,14 +161,13 @@ else if (taxAccountable.isAccountSignCR())

//
// Set DR/CR Tax Account
final int taxId = taxAccountable.getC_Tax_ID();
if (taxId > 0)
final TaxId taxId = TaxId.ofRepoIdOrNull(taxAccountable.getC_Tax_ID());
if (taxId != null)
{
final Properties ctx = Env.getCtx();
final AcctSchemaId acctSchemaId = taxAccountable.getAcctSchemaId();
final ITaxAcctBL taxAcctBL = Services.get(ITaxAcctBL.class);
final I_C_ValidCombination taxAcct = taxAcctBL.getC_ValidCombination(ctx, taxId, acctSchemaId, taxAcctType);
taxAccountable.setTax_Acct(taxAcct);
final MAccount taxAccount = taxAcctBL.getAccount(taxId, acctSchemaId, taxAcctType);
taxAccountable.setTax_Acct(taxAccount);
}
else
{
Expand Down

0 comments on commit d063f39

Please sign in to comment.