From: "David E Jones" <d...@me.com>
On Dec 7, 2010, at 11:58 PM, Jacques Le Roux wrote:

From: "David E Jones" <d...@me.com>
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.

Does this means that Price Rules and Promo work with Gross Prices?

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).

OK, we need to amend the OOTB UI anyway

BTW, thanks for this improvement David, I believe it's really a good base for next step. I mean I really prefer that it's you, who already designed and wrote the Tax Auth stuff, who wrote this new part!

Jacques

-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