On Dec 7, 2010, at 3:39 AM, Jacques Le Roux wrote:

> If there are no plans to prevent the use of the new fields for the other 
> types Price Types than Default, I'd like latter to add a small js script to 
> handle it. Of course being able to use it with Price Rules and Promo would be 
> great.

Why would we want to prevent using these fields for other price types? 

> Also what for is used taxAuthCombinedId? I don't see an use at the UI level.

With a combined ID you can select the tax authority in a drop-down instead of 
forcing the user to handle two separate fields that are not correlated, making 
the UI significantly more cumbersome and difficult to use.

-David



> From: "David E Jones" <d...@me.com>
>> I commented before that my previous efforts only made calculations more 
>> accurate, and those efforts made it clear that the only way to be sure is to 
>> calculate things based on prices with tax included.
>> 
>> So, now OFBiz has low-level support for prices with tax included and 
>> calculating VAT instead of sales tax with adjustments that represent amounts 
>> already included in the prices.
>> 
>> Note that this does not include any UI changes, and so unless changes are 
>> done to allow entry of prices with tax included and to show the VAT_TAX 
>> adjustments (specifically the new amountAlreadyIncluded field, which was 
>> added so that it wouldn't interfere with the current amount field).
>> 
>> -David
>> 
>> 
>> On Dec 6, 2010, at 8:39 AM, Jacques Le Roux wrote:
>> 
>>> Hi David,
>>> 
>>> Interesting, what decided you to finally shift your ground?
>>> 
>>> Is it still true that only Default Price can be used, and if yes is there 
>>> any blocking reasons?
>>> 
>>> Thanks
>>> 
>>> Jacques
>>> 
>>> From: <jone...@apache.org>
>>>> Author: jonesde
>>>> Date: Mon Dec  6 08:05:44 2010
>>>> New Revision: 1042542
>>>> 
>>>> URL: http://svn.apache.org/viewvc?rev=1042542&view=rev
>>>> Log:
>>>> Implemented alternative way of saving ProductPrices with tax included in 
>>>> the price, and then calculating VAT tax as an exclusive instead of 
>>>> inclusive amount that goes on a new field on OrderAdjustment; also added a 
>>>> method to OrderReadHelper to get tax for display; there are various 
>>>> changes to service descriptions and entity fields to describe these changes
>>>> 
>>>> Modified:
>>>>  
>>>> ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/tax/TaxAuthorityServices.java
>>>>  ofbiz/trunk/applications/order/data/OrderTypeData.xml
>>>>  ofbiz/trunk/applications/order/entitydef/entitymodel.xml
>>>>  
>>>> ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderReadHelper.java
>>>>  ofbiz/trunk/applications/product/entitydef/entitymodel.xml
>>>>  
>>>> ofbiz/trunk/applications/product/script/org/ofbiz/product/price/PriceServices.xml
>>>>  ofbiz/trunk/applications/product/servicedef/services.xml
>>>> 
>>>> Modified: 
>>>> ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/tax/TaxAuthorityServices.java
>>>> URL: 
>>>> http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/tax/TaxAuthorityServices.java?rev=1042542&r1=1042541&r2=1042542&view=diff
>>>> ==============================================================================
>>>> --- 
>>>> ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/tax/TaxAuthorityServices.java
>>>>  (original)
>>>> +++ 
>>>> ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/tax/TaxAuthorityServices.java
>>>>  Mon Dec  6 08:05:44 2010
>>>> @@ -391,11 +391,38 @@ public class TaxAuthorityServices {
>>>>                   // TODO: what to do if no TaxAuthorityGlAccount found? 
>>>> Use some default, or is that done elsewhere later on?
>>>>               }
>>>> 
>>>> +                GenericValue productPrice = null;
>>>> +                if (product != null && taxAuthPartyId != null && 
>>>> taxAuthGeoId != null) {
>>>> +                    // find a ProductPrice for the productId and taxAuth* 
>>>> valxues, and see if it has a priceWithTax value
>>>> +                    Map<String, String> priceFindMap = 
>>>> UtilMisc.toMap("productId", product.getString("productId"),
>>>> +                            "taxAuthPartyId", taxAuthPartyId, 
>>>> "taxAuthGeoId", taxAuthGeoId,
>>>> +                            "productPriceTypeId", "DEFAULT_PRICE", 
>>>> "productPricePurposeId", "PURCHASE");
>>>> +                    List<GenericValue> productPriceList = 
>>>> delegator.findByAnd("ProductPrice", priceFindMap, 
>>>> UtilMisc.toList("-fromDate"));
>>>> +                    productPriceList = 
>>>> EntityUtil.filterByDate(productPriceList, true);
>>>> +                    productPrice = (productPriceList != null && 
>>>> productPriceList.size() > 0) ? productPriceList.get(0): null;
>>>> +                    //Debug.logInfo("=================== productId=" + 
>>>> product.getString("productId"), module);
>>>> +                    //Debug.logInfo("=================== productPrice=" + 
>>>> productPrice, module);
>>>> +
>>>> +                }
>>>> +
>>>>               GenericValue taxAdjValue = 
>>>> delegator.makeValue("OrderAdjustment");
>>>> -                taxAdjValue.set("taxAuthorityRateSeqId", 
>>>> taxAuthorityRateProduct.getString("taxAuthorityRateSeqId"));
>>>> -                taxAdjValue.set("amount", taxAmount);
>>>> +
>>>> +                if ("Y".equals(productPrice.getString("taxInPrice"))) {
>>>> +                    // tax is in the price already, so we want the 
>>>> adjustment to be a VAT_TAX adjustment to be subtracted instead of a 
>>>> SALES_TAX adjustment to be added
>>>> +                    taxAdjValue.set("orderAdjustmentTypeId", "VAT_TAX");
>>>> +
>>>> +                    // the amount will be different because we want to 
>>>> figure out how much of the price was tax, and not how much tax needs to be 
>>>> added
>>>> +                    // the formula is: taxAmount = priceWithTax - 
>>>> (priceWithTax/(1+taxPercentage/100))
>>>> +                    BigDecimal taxAmountIncluded = 
>>>> itemAmount.subtract(itemAmount.divide(BigDecimal.ONE.add(taxRate.divide(PERCENT_SCALE,
>>>>  4, BigDecimal.ROUND_HALF_UP)), 3, BigDecimal.ROUND_HALF_UP));
>>>> +                    taxAdjValue.set("amountAlreadyIncluded", 
>>>> taxAmountIncluded);
>>>> +                    taxAdjValue.set("amount", BigDecimal.ZERO);
>>>> +                } else {
>>>> +                    taxAdjValue.set("orderAdjustmentTypeId", "SALES_TAX");
>>>> +                    taxAdjValue.set("amount", taxAmount);
>>>> +                }
>>>> +
>>>>               taxAdjValue.set("sourcePercentage", taxRate);
>>>> -                taxAdjValue.set("orderAdjustmentTypeId", "SALES_TAX");
>>>> +                taxAdjValue.set("taxAuthorityRateSeqId", 
>>>> taxAuthorityRateProduct.getString("taxAuthorityRateSeqId"));
>>>>               // the primary Geo should be the main jurisdiction that the 
>>>> tax is for, and the secondary would just be to define a parent or wrapping 
>>>> jurisdiction of the primary
>>>>               taxAdjValue.set("primaryGeoId", taxAuthGeoId);
>>>>               taxAdjValue.set("comments", 
>>>> taxAuthorityRateProduct.getString("description"));
>>>> @@ -421,62 +448,50 @@ public class TaxAuthorityServices {
>>>>               }
>>>> 
>>>>               adjustments.add(taxAdjValue);
>>>> -
>>>> -                // for VAT taxes if the calculated total item price plus 
>>>> calculated taxes is different from what would be
>>>> -                // expected based on the original entered price with 
>>>> taxes (if the price was entered this way), then create
>>>> -                // an adjustment that corrects for the difference, and 
>>>> this correction will be effectively subtracted from the
>>>> -                // price and not from the tax (the tax is meant to be 
>>>> calculated based on Tax Authority rules and so should
>>>> -                // not be shorted)
>>>> -
>>>> -                // TODO get this to work with price rules changing the 
>>>> default price (right now only works where itemPrice==defaultPrice
>>>> -                // TODO (don't think this is needed, but just to keep it 
>>>> in mind): get this to work with multiple VAT tax authorities instead of 
>>>> just one (right now will get incorrect totals if there are multiple taxes 
>>>> included in the price)
>>>> -                // TODO add constraint to ProductPrice lookup by any 
>>>> productStoreGroupId associated with the current productStore
>>>> -
>>>> -                //Debug.logInfo("=================== itemQuantity=" + 
>>>> itemQuantity, module);
>>>> -                //Debug.logInfo("=================== taxAuthPartyId=" + 
>>>> taxAuthPartyId, module);
>>>> -                //Debug.logInfo("=================== taxAuthGeoId=" + 
>>>> taxAuthGeoId, module);
>>>> -                if (product != null && itemQuantity != null && 
>>>> taxAuthPartyId != null && taxAuthGeoId != null) {
>>>> -                    // find a ProductPrice for the productId and taxAuth* 
>>>> valxues, and see if it has a priceWithTax value
>>>> -                    Map<String, String> priceFindMap = 
>>>> UtilMisc.toMap("productId", product.getString("productId"),
>>>> -                            "taxAuthPartyId", taxAuthPartyId, 
>>>> "taxAuthGeoId", taxAuthGeoId,
>>>> -                            "productPriceTypeId", "DEFAULT_PRICE", 
>>>> "productPricePurposeId", "PURCHASE");
>>>> -                    List<GenericValue> productPriceList = 
>>>> delegator.findByAnd("ProductPrice", priceFindMap, 
>>>> UtilMisc.toList("-fromDate"));
>>>> -                    productPriceList = 
>>>> EntityUtil.filterByDate(productPriceList, true);
>>>> -                    GenericValue productPrice = (productPriceList != null 
>>>> && productPriceList.size() > 0) ? productPriceList.get(0): null;
>>>> -                    //Debug.logInfo("=================== productId=" + 
>>>> product.getString("productId"), module);
>>>> -                    //Debug.logInfo("=================== productPrice=" + 
>>>> productPrice, module);
>>>> +
>>>> +                if (productPrice != null && itemQuantity != null &&
>>>> +                        productPrice.getBigDecimal("priceWithTax") != 
>>>> null &&
>>>> +                        
>>>> !"Y".equals(productPrice.getString("taxInPrice"))) {
>>>> +                    BigDecimal priceWithTax = 
>>>> productPrice.getBigDecimal("priceWithTax");
>>>> +                    BigDecimal price = 
>>>> productPrice.getBigDecimal("price");
>>>> +                    BigDecimal baseSubtotal = 
>>>> price.multiply(itemQuantity);
>>>> +                    BigDecimal baseTaxAmount = 
>>>> (baseSubtotal.multiply(taxRate)).divide(PERCENT_SCALE, 
>>>> salestaxCalcDecimals, salestaxRounding);
>>>> +                    //Debug.logInfo("=================== priceWithTax=" + 
>>>> priceWithTax, module);
>>>> +                    //Debug.logInfo("=================== 
>>>> enteredTotalPriceWithTax=" + enteredTotalPriceWithTax, module);
>>>> +                    //Debug.logInfo("=================== 
>>>> calcedTotalPriceWithTax=" + calcedTotalPriceWithTax, module);
>>>> +
>>>> +                    // tax is not already in price so we want to add it 
>>>> in, but this is a VAT situation so adjust to make it as accurate as 
>>>> possible
>>>> +
>>>> +                    // for VAT taxes if the calculated total item price 
>>>> plus calculated taxes is different from what would be
>>>> +                    // expected based on the original entered price with 
>>>> taxes (if the price was entered this way), then create
>>>> +                    // an adjustment that corrects for the difference, 
>>>> and this correction will be effectively subtracted from the
>>>> +                    // price and not from the tax (the tax is meant to be 
>>>> calculated based on Tax Authority rules and so should
>>>> +                    // not be shorted)
>>>> +
>>>> +                    // TODO (don't think this is needed, but just to keep 
>>>> it in mind): get this to work with multiple VAT tax authorities instead of 
>>>> just one (right now will get incorrect totals if there are multiple taxes 
>>>> included in the price)
>>>> +                    // TODO add constraint to ProductPrice lookup by any 
>>>> productStoreGroupId associated with the current productStore
>>>> 
>>>> -                    if (productPrice != null && 
>>>> productPrice.getBigDecimal("priceWithTax") != null) {
>>>> -                        BigDecimal priceWithTax = 
>>>> productPrice.getBigDecimal("priceWithTax");
>>>> -                        BigDecimal price = 
>>>> productPrice.getBigDecimal("price");
>>>> -                        BigDecimal baseSubtotal = 
>>>> price.multiply(itemQuantity);
>>>> -                        BigDecimal baseTaxAmount = 
>>>> (baseSubtotal.multiply(taxRate)).divide(PERCENT_SCALE, 
>>>> salestaxCalcDecimals, salestaxRounding);
>>>> -                        BigDecimal enteredTotalPriceWithTax = 
>>>> priceWithTax.multiply(itemQuantity);
>>>> -                        BigDecimal calcedTotalPriceWithTax = 
>>>> (baseSubtotal).add(baseTaxAmount);
>>>> -                        //Debug.logInfo("=================== 
>>>> priceWithTax=" + priceWithTax, module);
>>>> -                        //Debug.logInfo("=================== 
>>>> enteredTotalPriceWithTax=" + enteredTotalPriceWithTax, module);
>>>> -                        //Debug.logInfo("=================== 
>>>> calcedTotalPriceWithTax=" + calcedTotalPriceWithTax, module);
>>>> +                    BigDecimal enteredTotalPriceWithTax = 
>>>> priceWithTax.multiply(itemQuantity);
>>>> +                    BigDecimal calcedTotalPriceWithTax = 
>>>> (baseSubtotal).add(baseTaxAmount);
>>>> +                    if 
>>>> (!enteredTotalPriceWithTax.equals(calcedTotalPriceWithTax)) {
>>>> +                        // if the calced amount is higher than the 
>>>> entered amount we want the value to be negative
>>>> +                        //     to get it down to match the entered amount
>>>> +                        // so, subtract the calced amount from the 
>>>> entered amount (ie: correction = entered - calced)
>>>> +                        BigDecimal correctionAmount = 
>>>> enteredTotalPriceWithTax.subtract(calcedTotalPriceWithTax);
>>>> +                        //Debug.logInfo("=================== 
>>>> correctionAmount=" + correctionAmount, module);
>>>> 
>>>> -                        if 
>>>> (!enteredTotalPriceWithTax.equals(calcedTotalPriceWithTax)) {
>>>> -                            // if the calced amount is higher than the 
>>>> entered amount we want the value to be negative
>>>> -                            //     to get it down to match the entered 
>>>> amount
>>>> -                            // so, subtract the calced amount from the 
>>>> entered amount (ie: correction = entered - calced)
>>>> -                            BigDecimal correctionAmount = 
>>>> enteredTotalPriceWithTax.subtract(calcedTotalPriceWithTax);
>>>> -                            //Debug.logInfo("=================== 
>>>> correctionAmount=" + correctionAmount, module);
>>>> -
>>>> -                            GenericValue correctionAdjValue = 
>>>> delegator.makeValue("OrderAdjustment");
>>>> -                            
>>>> correctionAdjValue.set("taxAuthorityRateSeqId", 
>>>> taxAuthorityRateProduct.getString("taxAuthorityRateSeqId"));
>>>> -                            correctionAdjValue.set("amount", 
>>>> correctionAmount);
>>>> -                            // don't set this, causes a doubling of the 
>>>> tax rate because calling code adds up all tax rates: 
>>>> correctionAdjValue.set("sourcePercentage", taxRate);
>>>> -                            
>>>> correctionAdjValue.set("orderAdjustmentTypeId", "VAT_PRICE_CORRECT");
>>>> -                            // the primary Geo should be the main 
>>>> jurisdiction that the tax is for, and the secondary would just be to 
>>>> define a parent or wrapping jurisdiction of the primary
>>>> -                            correctionAdjValue.set("primaryGeoId", 
>>>> taxAuthGeoId);
>>>> -                            correctionAdjValue.set("comments", 
>>>> taxAuthorityRateProduct.getString("description"));
>>>> -                            if (taxAuthPartyId != null) 
>>>> correctionAdjValue.set("taxAuthPartyId", taxAuthPartyId);
>>>> -                            if (taxAuthGlAccountId != null) 
>>>> correctionAdjValue.set("overrideGlAccountId", taxAuthGlAccountId);
>>>> -                            if (taxAuthGeoId != null) 
>>>> correctionAdjValue.set("taxAuthGeoId", taxAuthGeoId);
>>>> -                            adjustments.add(correctionAdjValue);
>>>> -                        }
>>>> +                        GenericValue correctionAdjValue = 
>>>> delegator.makeValue("OrderAdjustment");
>>>> +                        correctionAdjValue.set("taxAuthorityRateSeqId", 
>>>> taxAuthorityRateProduct.getString("taxAuthorityRateSeqId"));
>>>> +                        correctionAdjValue.set("amount", 
>>>> correctionAmount);
>>>> +                        // don't set this, causes a doubling of the tax 
>>>> rate because calling code adds up all tax rates: 
>>>> correctionAdjValue.set("sourcePercentage", taxRate);
>>>> +                        correctionAdjValue.set("orderAdjustmentTypeId", 
>>>> "VAT_PRICE_CORRECT");
>>>> +                        // the primary Geo should be the main 
>>>> jurisdiction that the tax is for, and the secondary would just be to 
>>>> define a parent or wrapping jurisdiction of the primary
>>>> +                        correctionAdjValue.set("primaryGeoId", 
>>>> taxAuthGeoId);
>>>> +                        correctionAdjValue.set("comments", 
>>>> taxAuthorityRateProduct.getString("description"));
>>>> +                        if (taxAuthPartyId != null) 
>>>> correctionAdjValue.set("taxAuthPartyId", taxAuthPartyId);
>>>> +                        if (taxAuthGlAccountId != null) 
>>>> correctionAdjValue.set("overrideGlAccountId", taxAuthGlAccountId);
>>>> +                        if (taxAuthGeoId != null) 
>>>> correctionAdjValue.set("taxAuthGeoId", taxAuthGeoId);
>>>> +                        adjustments.add(correctionAdjValue);
>>>>                   }
>>>>               }
>>>>           }
>>>> 
>>>> Modified: ofbiz/trunk/applications/order/data/OrderTypeData.xml
>>>> URL: 
>>>> http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/data/OrderTypeData.xml?rev=1042542&r1=1042541&r2=1042542&view=diff
>>>> ==============================================================================
>>>> --- ofbiz/trunk/applications/order/data/OrderTypeData.xml (original)
>>>> +++ ofbiz/trunk/applications/order/data/OrderTypeData.xml Mon Dec  6 
>>>> 08:05:44 2010
>>>> @@ -42,6 +42,7 @@ under the License.
>>>>   <OrderAdjustmentType description="Fee" hasTable="N" 
>>>> orderAdjustmentTypeId="FEE" parentTypeId=""/>
>>>>   <OrderAdjustmentType description="Miscellaneous Charges" hasTable="N" 
>>>> orderAdjustmentTypeId="MISCELLANEOUS_CHARGE" parentTypeId=""/>
>>>>   <OrderAdjustmentType description="Sales Tax" hasTable="N" 
>>>> orderAdjustmentTypeId="SALES_TAX" parentTypeId=""/>
>>>> +    <OrderAdjustmentType description="VAT Tax (not added to totals)" 
>>>> hasTable="N" orderAdjustmentTypeId="VAT_TAX" parentTypeId=""/>
>>>>   <OrderAdjustmentType description="VAT Price Correction" hasTable="N" 
>>>> orderAdjustmentTypeId="VAT_PRICE_CORRECT" parentTypeId=""/>
>>>>   <OrderAdjustmentType description="Shipping and Handling" hasTable="N" 
>>>> orderAdjustmentTypeId="SHIPPING_CHARGES" parentTypeId=""/>
>>>>   <OrderAdjustmentType description="Surcharge" hasTable="N" 
>>>> orderAdjustmentTypeId="SURCHARGE_ADJUSTMENT" parentTypeId=""/>
>>>> 
>>>> Modified: ofbiz/trunk/applications/order/entitydef/entitymodel.xml
>>>> URL: 
>>>> http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/entitydef/entitymodel.xml?rev=1042542&r1=1042541&r2=1042542&view=diff
>>>> ==============================================================================
>>>> --- ofbiz/trunk/applications/order/entitydef/entitymodel.xml (original)
>>>> +++ ofbiz/trunk/applications/order/entitydef/entitymodel.xml Mon Dec  6 
>>>> 08:05:44 2010
>>>> @@ -59,6 +59,7 @@ under the License.
>>>>     <field name="description" type="description"></field>
>>>>     <field name="amount" type="currency-precise"></field>
>>>>     <field name="recurringAmount" type="currency-precise"></field>
>>>> +      <field name="amountAlreadyIncluded" 
>>>> type="currency-precise"><description>The amount here is already 
>>>> represented in the price, such as VAT taxes.</description></field>
>>>>     <field name="productPromoId" type="id"></field>
>>>>     <field name="productPromoRuleId" type="id"></field>
>>>>     <field name="productPromoActionSeqId" type="id"></field>
>>>> 
>>>> 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=1042542&r1=1042541&r2=1042542&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
>>>>  Mon Dec  6 08:05:44 2010
>>>> @@ -2920,4 +2920,62 @@ public class OrderReadHelper {
>>>>      result.put("taxGrandTotal", taxGrandTotal);
>>>>      return result;
>>>>  }
>>>> +
>>>> +   public static Map<String, Object> 
>>>> getOrderTaxByTaxAuthGeoAndPartyForDisplay(List<GenericValue> 
>>>> orderAdjustmentsOriginal) {
>>>> +       BigDecimal taxGrandTotal = BigDecimal.ZERO;
>>>> +       List<Map<String, Object>> taxByTaxAuthGeoAndPartyList = 
>>>> FastList.newInstance();
>>>> +       List<GenericValue> orderAdjustmentsToUse = FastList.newInstance();
>>>> +       if (UtilValidate.isNotEmpty(orderAdjustmentsOriginal)) {
>>>> +           // get orderAdjustment where orderAdjustmentTypeId is 
>>>> SALES_TAX.
>>>> +           
>>>> orderAdjustmentsToUse.addAll(EntityUtil.filterByAnd(orderAdjustmentsOriginal,
>>>>  UtilMisc.toMap("orderAdjustmentTypeId", "SALES_TAX")));
>>>> +           
>>>> orderAdjustmentsToUse.addAll(EntityUtil.filterByAnd(orderAdjustmentsOriginal,
>>>>  UtilMisc.toMap("orderAdjustmentTypeId", "VAT_TAX")));
>>>> +           orderAdjustmentsToUse = 
>>>> EntityUtil.orderBy(orderAdjustmentsToUse, 
>>>> 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(orderAdjustmentsToUse, 
>>>> "taxAuthGeoId", true);
>>>> +           List<String> distinctTaxAuthPartyIdList = 
>>>> EntityUtil.getFieldListFromEntityList(orderAdjustmentsToUse, 
>>>> "taxAuthPartyId", true);
>>>> +
>>>> +           // Keep a list of amount that have been added to make sure 
>>>> none are missed (if taxAuth* information is missing)
>>>> +           List<GenericValue> processedAdjustments = 
>>>> FastList.newInstance();
>>>> +           // 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(orderAdjustmentsToUse, 
>>>> 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) {
>>>> +                               totalAmount = totalAmount.add(amount);
>>>> +                           }
>>>> +                           if 
>>>> ("VAT_TAX".equals(orderAdjustment.getString("orderAdjustmentTypeId")) &&
>>>> +                                   
>>>> orderAdjustment.get("amountAlreadyIncluded") != null) {
>>>> +                               // this is the only case where the VAT_TAX 
>>>> amountAlreadyIncluded should be added in, and should just be for display 
>>>> and not to calculate the order grandTotal
>>>> +                               totalAmount = 
>>>> totalAmount.add(orderAdjustment.getBigDecimal("amountAlreadyIncluded"));
>>>> +                           }
>>>> +                           totalAmount = 
>>>> totalAmount.setScale(taxCalcScale, taxRounding);
>>>> +                           processedAdjustments.add(orderAdjustment);
>>>> +                       }
>>>> +                       totalAmount = totalAmount.setScale(taxFinalScale, 
>>>> taxRounding);
>>>> +                       taxByTaxAuthGeoAndPartyList.add(UtilMisc.<String, 
>>>> Object>toMap("taxAuthPartyId", taxAuthPartyId, "taxAuthGeoId", 
>>>> taxAuthGeoId, "totalAmount", totalAmount));
>>>> +                       taxGrandTotal = taxGrandTotal.add(totalAmount);
>>>> +                   }
>>>> +               }
>>>> +           }
>>>> +           // Process any adjustments that got missed
>>>> +           List<GenericValue> missedAdjustments = FastList.newInstance();
>>>> +           missedAdjustments.addAll(orderAdjustmentsToUse);
>>>> +           missedAdjustments.removeAll(processedAdjustments);
>>>> +           for (GenericValue orderAdjustment : missedAdjustments) {
>>>> +               taxGrandTotal = 
>>>> taxGrandTotal.add(orderAdjustment.getBigDecimal("amount").setScale(taxCalcScale,
>>>>  taxRounding));
>>>> +           }
>>>> +           taxGrandTotal = taxGrandTotal.setScale(taxFinalScale, 
>>>> taxRounding);
>>>> +       }
>>>> +       Map<String, Object> result = FastMap.newInstance();
>>>> +       result.put("taxByTaxAuthGeoAndPartyList", 
>>>> taxByTaxAuthGeoAndPartyList);
>>>> +       result.put("taxGrandTotal", taxGrandTotal);
>>>> +       return result;
>>>> +   }
>>>> }
>>>> 
>>>> Modified: ofbiz/trunk/applications/product/entitydef/entitymodel.xml
>>>> URL: 
>>>> http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/entitydef/entitymodel.xml?rev=1042542&r1=1042541&r2=1042542&view=diff
>>>> ==============================================================================
>>>> --- ofbiz/trunk/applications/product/entitydef/entitymodel.xml (original)
>>>> +++ ofbiz/trunk/applications/product/entitydef/entitymodel.xml Mon Dec  6 
>>>> 08:05:44 2010
>>>> @@ -2375,11 +2375,13 @@ under the License.
>>>>     <field name="price" type="currency-precise"></field>
>>>>     <field name="termUomId" type="id"><description>Mainly used for 
>>>> recurring and usage prices to specify a time/freq measure, or a usage unit 
>>>> measure (bits, minutes, etc)</description></field>
>>>>     <field name="customPriceCalcService" type="id"><description>Points to 
>>>> a CustomMethod used to specify a service for the calculation of the unit 
>>>> price of the product (NOTE: a better name for this field might be 
>>>> priceCalcCustomMethodId)</description></field>
>>>> -      <field name="priceWithTax" type="currency-precise"/>
>>>> +      <field name="priceWithoutTax" 
>>>> type="currency-precise"><description>Always without tax if populated, 
>>>> regardless of if price does or does not include tax.</description></field>
>>>> +      <field name="priceWithTax" 
>>>> type="currency-precise"><description>Always with tax if populated, 
>>>> regardless of if price does or does not include tax.</description></field>
>>>>     <field name="taxAmount" type="currency-precise"/>
>>>>     <field name="taxPercentage" type="fixed-point"/>
>>>>     <field name="taxAuthPartyId" type="id-ne"/>
>>>>     <field name="taxAuthGeoId" type="id-ne"/>
>>>> +      <field name="taxInPrice" type="indicator"><description>If Y the 
>>>> price field has tax included for the given taxAuthPartyId/taxAuthGeoId at 
>>>> the taxPercentage.</description></field>
>>>>     <field name="createdDate" type="date-time"></field>
>>>>     <field name="createdByUserLogin" type="id-vlong"></field>
>>>>     <field name="lastModifiedDate" type="date-time"></field>
>>>> 
>>>> Modified: 
>>>> ofbiz/trunk/applications/product/script/org/ofbiz/product/price/PriceServices.xml
>>>> URL: 
>>>> http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/script/org/ofbiz/product/price/PriceServices.xml?rev=1042542&r1=1042541&r2=1042542&view=diff
>>>> ==============================================================================
>>>> --- 
>>>> ofbiz/trunk/applications/product/script/org/ofbiz/product/price/PriceServices.xml
>>>>  (original)
>>>> +++ 
>>>> ofbiz/trunk/applications/product/script/org/ofbiz/product/price/PriceServices.xml
>>>>  Mon Dec  6 08:05:44 2010
>>>> @@ -106,6 +106,7 @@ under the License.
>>>>           </condition>
>>>>           <then>
>>>>               <set field="parameters.priceWithTax" 
>>>> from-field="parameters.price"/>
>>>> +
>>>>               <!-- if taxPercentage not passed in look it up based on 
>>>> taxAuthGeoId and taxAuthPartyId -->
>>>>               <if-empty field="parameters.taxPercentage">
>>>>                   <!-- we only have basic data to constrain by here, so 
>>>> assume that if it is a VAT tax setup it should be pretty simple -->
>>>> @@ -127,6 +128,7 @@ under the License.
>>>>                   <check-errors/>
>>>>               </if-empty>
>>>> 
>>>> +                <!-- in short the formula is: taxAmount = priceWithTax - 
>>>> (priceWithTax/(1+taxPercentage/100)) -->
>>>>               <calculate field="parameters.taxAmount" type="BigDecimal" 
>>>> decimal-scale="3" rounding-mode="HalfUp">
>>>>                   <calcop operator="subtract">
>>>>                       <calcop operator="get" 
>>>> field="parameters.priceWithTax"/>
>>>> @@ -142,12 +144,23 @@ under the License.
>>>>                       </calcop>
>>>>                   </calcop>
>>>>               </calculate>
>>>> -                <calculate field="parameters.price" type="BigDecimal" 
>>>> decimal-scale="3" rounding-mode="HalfUp">
>>>> +
>>>> +                <calculate field="parameters.priceWithoutTax" 
>>>> type="BigDecimal" decimal-scale="3" rounding-mode="HalfUp">
>>>>                   <calcop operator="subtract">
>>>>                       <calcop operator="get" 
>>>> field="parameters.priceWithTax"/>
>>>>                       <calcop operator="get" 
>>>> field="parameters.taxAmount"></calcop>
>>>>                   </calcop>
>>>>               </calculate>
>>>> +
>>>> +                <if-compare field="parameters.taxInPrice" 
>>>> operator="equals" value="Y">
>>>> +                    <!-- the price passed in has tax included, and we 
>>>> want to store it with tax included -->
>>>> +                    <set field="parameters.price" 
>>>> from-field="parameters.priceWithTax"/>
>>>> +
>>>> +                    <else>
>>>> +                        <!-- the price passed in has tax included, but we 
>>>> want to store it without tax included -->
>>>> +                        <set field="parameters.price" 
>>>> from-field="parameters.priceWithoutTax"/>
>>>> +                    </else>
>>>> +                </if-compare>
>>>>           </then>
>>>>       </if>
>>>>   </simple-method>
>>>> 
>>>> Modified: ofbiz/trunk/applications/product/servicedef/services.xml
>>>> URL: 
>>>> http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/servicedef/services.xml?rev=1042542&r1=1042541&r2=1042542&view=diff
>>>> ==============================================================================
>>>> --- ofbiz/trunk/applications/product/servicedef/services.xml (original)
>>>> +++ ofbiz/trunk/applications/product/servicedef/services.xml Mon Dec  6 
>>>> 08:05:44 2010
>>>> @@ -242,12 +242,15 @@ under the License.
>>>>       <description>
>>>>           Create an ProductPrice.
>>>>           Price is always stored without tax.
>>>> -            If a taxAuthGeoId and taxAuthPartyId are (or 
>>>> taxAuthCombinedId is) passed in then the price will be considered a price
>>>> -                with tax included and the tax will be removed before 
>>>> storing to the database
>>>> -                (the priceWithTax, taxAmount, and taxPercentage fields 
>>>> will also be populated).
>>>> +            If taxAuthGeoId and taxAuthPartyId are (or taxAuthCombinedId 
>>>> is) passed in then the price will be considered a price
>>>> +            with tax included (the priceWithoutTax, priceWithTax, 
>>>> taxAmount, and taxPercentage fields will also be populated).
>>>> +            If the taxInPrice field is 'Y' then the price field will be 
>>>> left with the price included (price will be equal to priceWithTax),
>>>> +            otherwise tax will be removed from the passed in price and 
>>>> the price field will be equal to the priceWithoutTax field.
>>>> +            If taxAuthGeoId or taxAuthPartyId empty, and 
>>>> taxAuthCombinedId is empty, then the taxInPrice field will be ignored.
>>>>       </description>
>>>>       <auto-attributes include="pk" mode="IN" optional="false"/>
>>>>       <auto-attributes include="nonpk" mode="IN" optional="true">
>>>> +            <exclude field-name="priceWithoutTax"/>
>>>>           <exclude field-name="priceWithTax"/>
>>>>           <exclude field-name="taxAmount"/>
>>>>           <exclude field-name="createdDate"/>
>>>> @@ -264,6 +267,7 @@ under the License.
>>>>       <description>Update an ProductPrice</description>
>>>>       <auto-attributes include="pk" mode="IN" optional="false"/>
>>>>       <auto-attributes include="nonpk" mode="IN" optional="true">
>>>> +            <exclude field-name="priceWithoutTax"/>
>>>>           <exclude field-name="priceWithTax"/>
>>>>           <exclude field-name="taxAmount"/>
>>>>           <exclude field-name="createdDate"/>
>>>> 
>>> 
>>> 
> 
> 

Reply via email to