On Dec 7, 2010, at 11:58 PM, Jacques Le Roux wrote:

> From: "David E Jones" <[email protected]>
>> 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?
> 
> I thought only the Default Price is really using VAT included price. So to 
> prevent users thinking they can use VAT included price with other price types.

Any price could, and should if applicable, have tax authority settings and have 
VAT tax included.

>>> 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.
> 
> Yes but then I think we need to expose a bit more how to enter a combined ID, 
> I will add a tooltip somewhere in the screen

A user wouldn't generally enter the combined ID manually, that would be a bad 
UI. The combined ID is just meant to be the ID in a drop-down (or perhaps a 
lookup).

-David


>> 
>>> From: "David E Jones" <[email protected]>
>>>> 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: <[email protected]>
>>>>>> 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