Author: jleroux
Date: Wed Sep 23 20:59:51 2009
New Revision: 818257
URL: http://svn.apache.org/viewvc?rev=818257&view=rev
Log:
A slighlty modified patch from Sumit Pandit
(https://issues.apache.org/jira/browse/OFBIZ-1599) - OFBIZ-1599
A new service that, given an orderId retrieve all OrderAdjustments for
SALES_TAXES and sum and approximate them by tax auth/tax geo.
The list of amounts is returned as an OUT parameter together with the total.
This new service is used in several places, including:
1) the service that computes the order grand total: it gets the total for taxes
by calling the new service
2) the gl posting service get the (summarized) acctg transaction for sales
taxes
Modified:
ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/ledger/GeneralLedgerServices.xml
ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceWorker.java
ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderReadHelper.java
Modified:
ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/ledger/GeneralLedgerServices.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/ledger/GeneralLedgerServices.xml?rev=818257&r1=818256&r2=818257&view=diff
==============================================================================
---
ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/ledger/GeneralLedgerServices.xml
(original)
+++
ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/ledger/GeneralLedgerServices.xml
Wed Sep 23 20:59:51 2009
@@ -1976,7 +1976,14 @@
<entity-one entity-name="Invoice" value-field="invoice"/>
<get-related-one value-field="invoice" relation-name="InvoiceType"
to-value-field="invoiceType"/>
<if-compare field="invoiceType.parentTypeId" operator="equals"
value="PURCHASE_INVOICE">
- <get-related value-field="invoice" relation-name="InvoiceItem"
list="invoiceItems"/>
+ <entity-condition entity-name="InvoiceItem" list="invoiceItems"
use-cache="true">
+ <condition-list>
+ <condition-expr field-name="invoiceItemTypeId"
operator="not-equals" value="PINV_SALES_TAX"/>
+ <condition-expr field-name="invoiceItemTypeId"
operator="not-equals" value="PITM_SALES_TAX"/>
+ <condition-expr field-name="invoiceId" operator="equals"
from-field="parameters.invoiceId"/>
+ </condition-list>
+ </entity-condition>
+
<iterate list="invoiceItems" entry="invoiceItem">
<set field="amountFromOrder" type="BigDecimal" value="0"/>
<set field="amountFromInvoice" type="BigDecimal" value="0"/>
@@ -2052,12 +2059,38 @@
<set field="debitEntry.origCurrencyUomId"
from-field="invoice.currencyUomId"/>
<set field="acctgTransEntries[]" from-field="debitEntry"
type="Object"/>
</iterate>
+ <!-- debit entry for SALES_TAX-->
+ <call-class-method method-name="getInvoiceTaxByTaxAuthGeoAndParty"
class-name="org.ofbiz.accounting.invoice.InvoiceWorker"
+ ret-field="invoiceTaxByTaxAuthGeoAndPartyResult">
+ <field field="invoice" type="org.ofbiz.entity.GenericValue"/>
+ </call-class-method>
+ <set field="taxByTaxAuthGeoAndPartyList"
from-field="invoiceTaxByTaxAuthGeoAndPartyResult.taxByTaxAuthGeoAndPartyList"/>
+ <set field="invoiceTaxTotal"
from-field="invoiceTaxByTaxAuthGeoAndPartyResult.taxGrandTotal"/>
+ <iterate list="taxByTaxAuthGeoAndPartyList"
entry="taxByTaxAuthGeoAndParty">
+ <clear-field field="creditEntry"/>
+ <make-value entity-name="AcctgTransEntry"
value-field="creditEntry"/>
+ <set field="creditEntry.debitCreditFlag" value="D"/>
+ <set field="creditEntry.organizationPartyId"
from-field="invoice.partyIdFrom"/>
+ <set field="creditEntry.origAmount"
from-field="taxByTaxAuthGeoAndParty.totalAmount"/>
+ <set field="creditEntry.origCurrencyUomId"
from-field="invoice.currencyUomId"/>
+ <if-not-empty field="taxByTaxAuthGeoAndParty.taxAuthPartyId">
+ <set field="creditEntry.partyId"
from-field="taxByTaxAuthGeoAndParty.taxAuthPartyId"/>
+ <set field="creditEntry.roleTypeId" value="TAX_AUTHORITY"/>
+ </if-not-empty>
+ <set field="acctgTransEntries[]" from-field="creditEntry"
type="Object"/>
+ </iterate>
<!-- Credit -->
<make-value entity-name="AcctgTransEntry"
value-field="creditEntry"/>
<set field="creditEntry.debitCreditFlag" value="C"/>
<set field="creditEntry.organizationPartyId"
from-field="invoice.partyId"/>
<set field="creditEntry.glAccountTypeId" value="ACCOUNTS_PAYABLE"/>
+ <calculate field="totalAmountFromInvoice" type="BigDecimal"
decimal-scale="${ledgerDecimals}" rounding-mode="${roundingMode}">
+ <calcop operator="add">
+ <calcop operator="get" field="totalAmountFromInvoice"/>
+ <calcop operator="get" field="invoiceTaxTotal"/>
+ </calcop>
+ </calculate>
<set field="creditEntry.origAmount"
from-field="totalAmountFromInvoice"/>
<set field="creditEntry.origCurrencyUomId"
from-field="invoice.currencyUomId"/>
<set field="creditEntry.partyId" from-field="invoice.partyIdFrom"/>
@@ -2081,13 +2114,17 @@
<simple-method method-name="createAcctgTransForSalesInvoice"
short-description="Create an accounting transaction for a sales invoice">
<!-- retrieve ledger rounding properties -->
<call-simple-method method-name="getGlArithmeticSettingsInline"/>
- <set field="totalOrigAmount" value="0"/>
+ <set field="totalOrigAmount" type="BigDecimal" value="0"/>
<entity-one entity-name="Invoice" value-field="invoice"/>
<if-compare field="invoice.invoiceTypeId" value="SALES_INVOICE"
operator="equals">
- <entity-and entity-name="InvoiceItem" list="invoiceItems">
- <field-map field-name="invoiceId"
from-field="parameters.invoiceId"/>
- </entity-and>
+ <entity-condition entity-name="InvoiceItem" list="invoiceItems"
use-cache="true">
+ <condition-list>
+ <condition-expr field-name="invoiceItemTypeId"
operator="not-equals" value="INV_SALES_TAX"/>
+ <condition-expr field-name="invoiceItemTypeId"
operator="not-equals" value="ITM_SALES_TAX"/>
+ <condition-expr field-name="invoiceId" operator="equals"
from-field="parameters.invoiceId"/>
+ </condition-list>
+ </entity-condition>
<iterate list="invoiceItems" entry="invoiceItem">
<!-- TODO: handle serialized inventory -->
<if-empty field="invoiceItem.quantity">
@@ -2121,11 +2158,38 @@
<set field="acctgTransEntries[]" from-field="creditEntry"
type="Object"/>
</iterate>
+ <!-- credit entry for SALES_TAX-->
+ <call-class-method method-name="getInvoiceTaxByTaxAuthGeoAndParty"
class-name="org.ofbiz.accounting.invoice.InvoiceWorker"
+ ret-field="invoiceTaxByTaxAuthGeoAndPartyResult">
+ <field field="invoice" type="org.ofbiz.entity.GenericValue"/>
+ </call-class-method>
+ <set field="taxByTaxAuthGeoAndPartyList"
from-field="invoiceTaxByTaxAuthGeoAndPartyResult.taxByTaxAuthGeoAndPartyList"/>
+ <set field="invoiceTaxTotal"
from-field="invoiceTaxByTaxAuthGeoAndPartyResult.taxGrandTotal"/>
+ <iterate list="taxByTaxAuthGeoAndPartyList"
entry="taxByTaxAuthGeoAndParty">
+ <clear-field field="creditEntry"/>
+ <make-value entity-name="AcctgTransEntry"
value-field="creditEntry"/>
+ <set field="creditEntry.debitCreditFlag" value="C"/>
+ <set field="creditEntry.organizationPartyId"
from-field="invoice.partyIdFrom"/>
+ <set field="creditEntry.origAmount"
from-field="taxByTaxAuthGeoAndParty.totalAmount"/>
+ <set field="creditEntry.origCurrencyUomId"
from-field="invoice.currencyUomId"/>
+ <if-not-empty field="taxByTaxAuthGeoAndParty.taxAuthPartyId">
+ <set field="creditEntry.partyId"
from-field="taxByTaxAuthGeoAndParty.taxAuthPartyId"/>
+ <set field="creditEntry.roleTypeId" value="TAX_AUTHORITY"/>
+ </if-not-empty>
+ <set field="acctgTransEntries[]" from-field="creditEntry"
type="Object"/>
+ </iterate>
+
<!-- Debit -->
<make-value entity-name="AcctgTransEntry"
value-field="debitEntry"/>
<set field="debitEntry.debitCreditFlag" value="D"/>
<set field="debitEntry.glAccountTypeId"
value="ACCOUNTS_RECEIVABLE"/>
<set field="debitEntry.organizationPartyId"
from-field="invoice.partyIdFrom"/>
+ <calculate field="totalOrigAmount" type="BigDecimal"
decimal-scale="${ledgerDecimals}" rounding-mode="${roundingMode}">
+ <calcop operator="add">
+ <calcop operator="get" field="totalOrigAmount"/>
+ <calcop operator="get" field="invoiceTaxTotal"/>
+ </calcop>
+ </calculate>
<set field="debitEntry.origAmount" from-field="totalOrigAmount"/>
<set field="debitEntry.origCurrencyUomId"
from-field="invoice.currencyUomId"/>
<set field="debitEntry.partyId" from-field="invoice.partyId"/>
Modified:
ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceWorker.java
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceWorker.java?rev=818257&r1=818256&r2=818257&view=diff
==============================================================================
---
ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceWorker.java
(original)
+++
ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceWorker.java
Wed Sep 23 20:59:51 2009
@@ -23,8 +23,10 @@
import java.sql.Timestamp;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import javolution.util.FastList;
+import javolution.util.FastMap;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilDateTime;
@@ -37,6 +39,7 @@
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.condition.EntityCondition;
import org.ofbiz.entity.condition.EntityConditionList;
+import org.ofbiz.entity.condition.EntityExpr;
import org.ofbiz.entity.condition.EntityOperator;
import org.ofbiz.entity.util.EntityUtil;
import org.ofbiz.service.LocalDispatcher;
@@ -116,8 +119,8 @@
GenericDelegator delegator = invoice.getDelegator();
EntityConditionList condition =
EntityCondition.makeCondition(UtilMisc.toList(
EntityCondition.makeCondition("invoiceId",
invoice.get("invoiceId")),
- EntityCondition.makeCondition("invoiceItemTypeId",
EntityOperator.IN, getTaxableInvoiceItemTypeIds(delegator))
- ), EntityOperator.AND);
+ EntityCondition.makeCondition("invoiceItemTypeId",
EntityOperator.IN, getTaxableInvoiceItemTypeIds(delegator))),
+ EntityOperator.AND);
invoiceTaxItems = delegator.findList("InvoiceItem", condition,
null, null, null, false);
} catch (GenericEntityException e) {
Debug.logError(e, "Trouble getting InvoiceItem list", module);
@@ -155,9 +158,15 @@
public static BigDecimal getInvoiceTotal(GenericValue invoice, Boolean
actualCurrency) {
BigDecimal invoiceTotal = ZERO;
BigDecimal invoiceTaxTotal = ZERO;
+ Map invoiceTaxByTaxAuthGeoAndPartyResult =
getInvoiceTaxByTaxAuthGeoAndParty(invoice);
+ List taxByTaxAuthGeoAndPartyList = (List)
invoiceTaxByTaxAuthGeoAndPartyResult.get("taxByTaxAuthGeoAndPartyList");
+ invoiceTaxTotal = (BigDecimal)
invoiceTaxByTaxAuthGeoAndPartyResult.get("taxGrandTotal");
+
List invoiceItems = null;
try {
invoiceItems = invoice.getRelated("InvoiceItem");
+ invoiceItems = EntityUtil.filterByAnd(invoiceItems,
UtilMisc.toList(EntityCondition.makeCondition("invoiceItemTypeId",
EntityOperator.NOT_EQUAL, "PINV_SALES_TAX"),
EntityCondition.makeCondition("invoiceItemTypeId", EntityOperator.NOT_EQUAL,
"PITM_SALES_TAX"),
+ EntityCondition.makeCondition("invoiceItemTypeId",
EntityOperator.NOT_EQUAL, "ITM_SALES_TAX"),
EntityCondition.makeCondition("invoiceItemTypeId", EntityOperator.NOT_EQUAL,
"INV_SALES_TAX")));
} catch (GenericEntityException e) {
Debug.logError(e, "Trouble getting InvoiceItem list", module);
}
@@ -171,11 +180,7 @@
amount = ZERO;
if (quantity == null)
quantity = BigDecimal.ONE;
- if
("ITM_SALES_TAX".equals(invoiceItem.get("invoiceItemTypeId"))) {
- invoiceTaxTotal =
invoiceTaxTotal.add(amount.multiply(quantity)).setScale(taxDecimals,
taxRounding);
- } else {
- invoiceTotal =
invoiceTotal.add(amount.multiply(quantity)).setScale(decimals,rounding);
- }
+ invoiceTotal = invoiceTotal.add(
amount.multiply(quantity)).setScale(decimals,rounding);
}
}
invoiceTotal = invoiceTotal.add(invoiceTaxTotal).setScale(decimals,
rounding);
@@ -605,4 +610,54 @@
return getInvoiceCurrencyConversionRate(invoice);
}
+
+ public static Map<String, Object>
getInvoiceTaxByTaxAuthGeoAndParty(GenericValue invoice) {
+ BigDecimal taxGrandTotal = ZERO;
+ List<Map<String, Object>> taxByTaxAuthGeoAndPartyList =
FastList.newInstance();
+ List<GenericValue> invoiceItems = null;
+ if (UtilValidate.isNotEmpty(invoice)) {
+ try {
+ invoiceItems = invoice.getRelated("InvoiceItem");
+ } catch (GenericEntityException e) {
+ Debug.logError(e, "Trouble getting InvoiceItem list", module);
+ }
+ if ("SALES_INVOICE".equals(invoice.get("invoiceTypeId"))) {
+ invoiceItems = EntityUtil.filterByOr(invoiceItems,
UtilMisc.toList(EntityCondition.makeCondition("invoiceItemTypeId",
EntityOperator.EQUALS, "INV_SALES_TAX"),
EntityCondition.makeCondition("invoiceItemTypeId", EntityOperator.EQUALS,
"ITM_SALES_TAX")));
+ } else if
(("PURCHASE_INVOICE".equals(invoice.get("invoiceTypeId")))) {
+ invoiceItems = EntityUtil.filterByOr(invoiceItems,
UtilMisc.toList(EntityCondition.makeCondition("invoiceItemTypeId",
EntityOperator.EQUALS, "PINV_SALES_TAX"),
EntityCondition.makeCondition("invoiceItemTypeId", EntityOperator.EQUALS,
"PITM_SALES_TAX")));
+ } else {
+ invoiceItems = null;
+ }
+ if (UtilValidate.isNotEmpty(invoiceItems)) {
+ invoiceItems = EntityUtil.orderBy(invoiceItems,
UtilMisc.toList("taxAuthGeoId","taxAuthPartyId"));
+ // get the list of all distinct taxAuthGeoId and
taxAuthPartyId. It is for getting the number of taxAuthGeoId and taxAuthPartyId
in invoiceItems.
+ List<String> distinctTaxAuthGeoIdList =
EntityUtil.getFieldListFromEntityList(invoiceItems, "taxAuthGeoId", true);
+ List<String> distinctTaxAuthPartyIdList =
EntityUtil.getFieldListFromEntityList(invoiceItems, "taxAuthPartyId", true);
+ for (String taxAuthGeoId : distinctTaxAuthGeoIdList ) {
+ for (String taxAuthPartyId : distinctTaxAuthPartyIdList) {
+ //get all records for invoices filtered by
taxAuthGeoId and taxAurhPartyId
+ List<GenericValue> invoiceItemsByTaxAuthGeoAndPartyIds
= EntityUtil.filterByAnd(invoiceItems, UtilMisc.toMap("taxAuthGeoId",
taxAuthGeoId, "taxAuthPartyId", taxAuthPartyId));
+ if
(UtilValidate.isNotEmpty(invoiceItemsByTaxAuthGeoAndPartyIds)) {
+ BigDecimal totalAmount = ZERO;
+ //Now for each invoiceItem record get and add
amount.
+ for (GenericValue invoiceItem :
invoiceItemsByTaxAuthGeoAndPartyIds) {
+ BigDecimal amount =
invoiceItem.getBigDecimal("amount");
+ if (amount == null) {
+ amount = ZERO;
+ }
+ totalAmount =
totalAmount.add(amount).setScale(taxDecimals, taxRounding);
+ }
+ totalAmount =
totalAmount.setScale(UtilNumber.getBigDecimalScale("salestax.calc.decimals"),
UtilNumber.getBigDecimalRoundingMode("salestax.rounding"));
+ taxByTaxAuthGeoAndPartyList.add(UtilMisc.<String,
Object>toMap("taxAuthPartyId", taxAuthPartyId, "taxAuthGeoId", taxAuthGeoId,
"totalAmount", totalAmount));
+ taxGrandTotal = taxGrandTotal.add(totalAmount);
+ }
+ }
+ }
+ }
+ }
+ Map<String, Object> result = FastMap.newInstance();
+ result.put("taxByTaxAuthGeoAndPartyList", taxByTaxAuthGeoAndPartyList);
+ result.put("taxGrandTotal", taxGrandTotal);
+ return result;
+ }
}
Modified:
ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderReadHelper.java
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderReadHelper.java?rev=818257&r1=818256&r2=818257&view=diff
==============================================================================
---
ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderReadHelper.java
(original)
+++
ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderReadHelper.java
Wed Sep 23 20:59:51 2009
@@ -1104,8 +1104,7 @@
// get the payments of the desired type for these invoices TODO:
in models where invoices can have many orders, this needs to be refined
List conditions = UtilMisc.toList(
EntityCondition.makeCondition("statusId",
EntityOperator.EQUALS, "PMNT_RECEIVED"),
- EntityCondition.makeCondition("invoiceId",
EntityOperator.IN, invoiceIds)
- );
+ EntityCondition.makeCondition("invoiceId",
EntityOperator.IN, invoiceIds));
if (paymentMethodTypeId != null) {
conditions.add(EntityCondition.makeCondition("paymentMethodTypeId",
EntityOperator.EQUALS, paymentMethodTypeId));
}
@@ -2282,8 +2281,13 @@
}
public static BigDecimal getOrderGrandTotal(List orderItems, List
adjustments) {
+ Map orderTaxByTaxAuthGeoAndParty =
getOrderTaxByTaxAuthGeoAndParty(adjustments);
+ List taxByTaxAuthGeoAndPartyList = (List)
orderTaxByTaxAuthGeoAndParty.get("taxByTaxAuthGeoAndPartyList");
+ BigDecimal taxGrandTotal = (BigDecimal)
orderTaxByTaxAuthGeoAndParty.get("taxGrandTotal");
+ adjustments = EntityUtil.filterByAnd(adjustments,
UtilMisc.toList(EntityCondition.makeCondition("orderAdjustmentTypeId",
EntityOperator.NOT_EQUAL, "SALES_TAX")));
BigDecimal total = getOrderItemsTotal(orderItems, adjustments);
BigDecimal adj = getOrderAdjustmentsTotal(orderItems, adjustments);
+ total = total.add(taxGrandTotal).setScale(scale,rounding);
return total.add(adj).setScale(scale,rounding);
}
@@ -2833,4 +2837,44 @@
return EntityUtil.orderBy(EntityUtil.filterByAnd(newOrderStatuses,
contraints2), UtilMisc.toList("-statusDatetime"));
}
+
+ public static Map<String, Object> getOrderTaxByTaxAuthGeoAndParty(List
orderAdjustments) {
+ BigDecimal taxGrandTotal = BigDecimal.ZERO;
+ List<Map<String, Object>> taxByTaxAuthGeoAndPartyList =
FastList.newInstance();
+ if (UtilValidate.isNotEmpty(orderAdjustments)) {
+ // get orderAdjustment where orderAdjustmentTypeId is SALES_TAX.
+ orderAdjustments = EntityUtil.filterByAnd(orderAdjustments,
UtilMisc.toMap("orderAdjustmentTypeId","SALES_TAX"));
+ orderAdjustments = EntityUtil.orderBy(orderAdjustments,
UtilMisc.toList("taxAuthGeoId","taxAuthPartyId"));
+
+ // get the list of all distinct taxAuthGeoId and taxAuthPartyId. It
is for getting the number of taxAuthGeo and taxAuthPartyId in adjustments.
+ List<String> distinctTaxAuthGeoIdList =
EntityUtil.getFieldListFromEntityList(orderAdjustments, "taxAuthGeoId", true);
+ List<String> distinctTaxAuthPartyIdList =
EntityUtil.getFieldListFromEntityList(orderAdjustments, "taxAuthPartyId", true);
+
+ // For each taxAuthGeoId get and add amount from orderAdjustment
+ for (String taxAuthGeoId : distinctTaxAuthGeoIdList) {
+ for (String taxAuthPartyId : distinctTaxAuthPartyIdList) {
+ //get all records for orderAdjustments filtered by
taxAuthGeoId and taxAurhPartyId
+ List<GenericValue> orderAdjByTaxAuthGeoAndPartyIds =
EntityUtil.filterByAnd(orderAdjustments, UtilMisc.toMap("taxAuthGeoId",
taxAuthGeoId, "taxAuthPartyId", taxAuthPartyId));
+ if
(UtilValidate.isNotEmpty(orderAdjByTaxAuthGeoAndPartyIds)) {
+ BigDecimal totalAmount = BigDecimal.ZERO;
+ //Now for each orderAdjustment record get and add
amount.
+ for (GenericValue orderAdjustment :
orderAdjByTaxAuthGeoAndPartyIds) {
+ BigDecimal amount =
orderAdjustment.getBigDecimal("amount");
+ if (amount == null) {
+ amount = ZERO;
+ }
+ totalAmount =
totalAmount.add(amount).setScale(UtilNumber.getBigDecimalScale("salestax.calc.decimals"),
taxRounding);
+ }
+ totalAmount =
totalAmount.setScale(UtilNumber.getBigDecimalScale("salestax.final.decimals"),
UtilNumber.getBigDecimalRoundingMode("salestax.rounding"));
+ taxByTaxAuthGeoAndPartyList.add(UtilMisc.<String,
Object>toMap("taxAuthPartyId", taxAuthPartyId, "taxAuthGeoId", taxAuthGeoId,
"totalAmount", totalAmount));
+ taxGrandTotal = taxGrandTotal.add(totalAmount);
+ }
+ }
+ }
+ }
+ Map result = FastMap.newInstance();
+ result.put("taxByTaxAuthGeoAndPartyList", taxByTaxAuthGeoAndPartyList);
+ result.put("taxGrandTotal", taxGrandTotal);
+ return result;
+ }
}