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; + } } |
Free forum by Nabble | Edit this page |