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.

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

Thanks

Jacques


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