Author: jacopoc
Date: Wed Mar 24 11:20:53 2010
New Revision: 927011
URL: http://svn.apache.org/viewvc?rev=927011&view=rev
Log:
More enhancements in the LIFO/FIFO implementation: now I have re-enabled the
original "average cost" costing method (that was, and is, only partially
implemented btw); I have also added a "new" costing method based on real
inventory item unit costs: this was actually the only method (implicitly)
supported before the implementation of LIFO and FIFO.
Modified:
ofbiz/trunk/applications/accounting/data/AccountingTypeData.xml
ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/ledger/GeneralLedgerServices.xml
Modified: ofbiz/trunk/applications/accounting/data/AccountingTypeData.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/data/AccountingTypeData.xml?rev=927011&r1=927010&r2=927011&view=diff
==============================================================================
--- ofbiz/trunk/applications/accounting/data/AccountingTypeData.xml (original)
+++ ofbiz/trunk/applications/accounting/data/AccountingTypeData.xml Wed Mar 24
11:20:53 2010
@@ -955,6 +955,7 @@ under the License.
<Enumeration description="LIFO" enumCode="LIFO" enumId="COGS_LIFO"
sequenceId="01" enumTypeId="COGS_METHODS"/>
<Enumeration description="FIFO" enumCode="FIFO" enumId="COGS_FIFO"
sequenceId="02" enumTypeId="COGS_METHODS"/>
<Enumeration description="Average Cost" enumCode="AVG_COST"
enumId="COGS_AVG_COST" sequenceId="03" enumTypeId="COGS_METHODS"/>
+ <Enumeration description="Inventory Item Cost" enumCode="INV_COST"
enumId="COGS_INV_COST" sequenceId="04" enumTypeId="COGS_METHODS"/>
<!-- inventory sequencing mode for accounting preferences -->
<EnumerationType description="Invoice Sequence Mode"
enumTypeId="INVOICE_SEQMD" hasTable="N" parentTypeId=""/>
Modified:
ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/ledger/GeneralLedgerServices.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/ledger/GeneralLedgerServices.xml?rev=927011&r1=927010&r2=927011&view=diff
==============================================================================
---
ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/ledger/GeneralLedgerServices.xml
(original)
+++
ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/ledger/GeneralLedgerServices.xml
Wed Mar 24 11:20:53 2010
@@ -1097,71 +1097,35 @@ under the License.
<field-map field-name="roleTypeId" value="BILL_TO_CUSTOMER"/>
</entity-and>
<first-from-list list="billToCustomers" entry="billToCustomer"/>
- <!-- TODO: handle serialized inventory -->
- <!--
- <set field="getProdAvgCostMap.inventoryItem"
from-field="inventoryItem"/>
- <call-service service-name="getProductAverageCost"
in-map-name="getProdAvgCostMap">
- <result-to-field result-name="unitCost"/>
- </call-service>
- <calculate field="origAmount" decimal-scale="${ledgerDecimals}"
rounding-mode="${roundingMode}">
- <calcop operator="multiply">
- <calcop operator="get" field="itemIssuance.quantity"/>
- <calcop operator="get" field="unitCost"/>
- </calcop>
- </calculate>
- -->
<!-- prepare the double posting (D/C) entries (AcctgTransEntry) -->
<!-- Credit -->
+ <!-- TODO: handle serialized inventory -->
<set field="partyAccountingPreferencesCallMap.organizationPartyId"
from-field="inventoryItem.ownerPartyId"/>
<call-service service-name="getPartyAccountingPreferences"
in-map-name="partyAccountingPreferencesCallMap">
<result-to-field result-name="partyAccountingPreference"
field="partyAcctgPreference"/>
</call-service>
- <if-compare field="partyAcctgPreference.cogsMethodId"
operator="equals" value="COGS_FIFO" type="String">
- <set value="+datetimeReceived" field="orderByString"/>
- </if-compare>
- <if-compare field="partyAcctgPreference.cogsMethodId"
operator="equals" value="COGS_LIFO" type="String">
- <set value="-datetimeReceived" field="orderByString"/>
- </if-compare>
- <if-empty field="orderByString">
- <add-error><fail-message message="COGS costing method is not
supported: ${partyAcctgPreference.cogsMethodId}"/></add-error>
- <check-errors/>
- </if-empty>
- <entity-condition entity-name="InventoryItem"
list="costInventoryItems">
- <condition-list combine="and">
- <condition-expr field-name="ownerPartyId" operator="equals"
from-field="inventoryItem.ownerPartyId"/>
- <condition-expr field-name="facilityId" operator="equals"
from-field="inventoryItem.facilityId"/>
- <condition-expr field-name="productId" operator="equals"
from-field="inventoryItem.productId"/>
- <condition-expr field-name="accountingQuantityTotal"
operator="greater" value="0.0"/>
- </condition-list>
- <order-by field-name="${orderByString}"/>
- </entity-condition>
- <set field="remainingQuantity" from-field="itemIssuance.quantity"/>
<set field="totalAmount" value="0.0" type="BigDecimal"/>
- <iterate list="costInventoryItems" entry="costInventoryItem">
- <if-compare field="remainingQuantity" operator="greater"
value="0.0" type="BigDecimal">
- <if-compare-field field="remainingQuantity"
operator="less-equals" to-field="costInventoryItem.accountingQuantityTotal"
type="BigDecimal">
- <set field="costInventoryItemQuantity"
from-field="remainingQuantity"/>
- <set field="remainingQuantity" value="0.0"
type="BigDecimal"/>
+ <if>
+ <condition>
+ <or>
+ <if-compare field="partyAcctgPreference.cogsMethodId"
operator="equals" value="COGS_INV_COST" type="String"/>
+ <if-compare field="partyAcctgPreference.cogsMethodId"
operator="equals" value="COGS_AVG_COST" type="String"/>
+ </or>
+ </condition>
+ <then>
+ <if-compare field="partyAcctgPreference.cogsMethodId"
operator="equals" value="COGS_AVG_COST" type="String">
+ <set field="getProdAvgCostMap.inventoryItem"
from-field="inventoryItem"/>
+ <call-service service-name="getProductAverageCost"
in-map-name="getProdAvgCostMap">
+ <result-to-field result-name="unitCost"/>
+ </call-service>
<else>
- <set field="costInventoryItemQuantity"
from-field="costInventoryItem.accountingQuantityTotal"/>
- <set field="remainingQuantity"
value="${remainingQuantity - costInventoryItem.accountingQuantityTotal}"
type="BigDecimal"/>
+ <set field="unitCost"
from-field="inventoryItem.unitCost"/>
</else>
- </if-compare-field>
- <!-- An inventory item detail record is created to keep track
of the units (value) that we are going to add to the inventory account -->
- <set from-field="costInventoryItem.inventoryItemId"
field="createDetailMap.inventoryItemId"/>
- <set value="${-1 * costInventoryItemQuantity}"
field="createDetailMap.accountingQuantityDiff" type="BigDecimal"/>
- <call-service service-name="createInventoryItemDetail"
in-map-name="createDetailMap"/>
-
- <calculate field="costInventoryItemAmount"
decimal-scale="${ledgerDecimals}" rounding-mode="${roundingMode}">
- <calcop operator="multiply">
- <calcop operator="get"
field="costInventoryItemQuantity"/>
- <calcop operator="get"
field="costInventoryItem.unitCost"/>
- </calcop>
- </calculate>
+ </if-compare>
<calculate field="totalAmount"
decimal-scale="${ledgerDecimals}" rounding-mode="${roundingMode}">
- <calcop operator="sum">
- <calcop operator="get"
field="costInventoryItemAmount"/>
- <calcop operator="get" field="totalAmount"/>
+ <calcop operator="multiply">
+ <calcop operator="get" field="itemIssuance.quantity"/>
+ <calcop operator="get" field="unitCost"/>
</calcop>
</calculate>
<make-value entity-name="AcctgTransEntry"
value-field="creditEntry"/>
@@ -1169,21 +1133,85 @@ under the License.
<set field="creditEntry.glAccountTypeId"
value="INVENTORY_ACCOUNT"/>
<set field="creditEntry.organizationPartyId"
from-field="inventoryItem.ownerPartyId"/>
<set field="creditEntry.productId"
from-field="inventoryItem.productId"/>
- <set field="creditEntry.inventoryItemId"
from-field="costInventoryItem.inventoryItemId"/>
- <set field="creditEntry.origAmount"
from-field="costInventoryItemAmount"/>
+ <set field="creditEntry.inventoryItemId"
from-field="inventoryItem.inventoryItemId"/>
+ <set field="creditEntry.origAmount" from-field="totalAmount"/>
<set field="creditEntry.origCurrencyUomId"
from-field="inventoryItem.currencyUomId"/>
<if-not-empty field="billToCustomer">
<set field="creditEntry.partyId"
from-field="billToCustomer.partyId"/>
<set field="creditEntry.roleTypeId"
from-field="billToCustomer.roleTypeId"/>
</if-not-empty>
<set field="acctgTransEntries[]" from-field="creditEntry"
type="Object"/>
- <clear-field field="creditEntry"/>
- </if-compare>
- </iterate>
- <if-compare field="remainingQuantity" operator="greater" value="0.0"
type="BigDecimal">
- <add-error><fail-message message="Could not find enough accounting
inventory for product [${inventoryItem.productId}]; remaining quantity:
${remainingQuantity}"/></add-error>
- <check-errors/>
- </if-compare>
+ </then>
+ <else>
+ <if-compare field="partyAcctgPreference.cogsMethodId"
operator="equals" value="COGS_FIFO" type="String">
+ <set value="+datetimeReceived" field="orderByString"/>
+ </if-compare>
+ <if-compare field="partyAcctgPreference.cogsMethodId"
operator="equals" value="COGS_LIFO" type="String">
+ <set value="-datetimeReceived" field="orderByString"/>
+ </if-compare>
+ <if-empty field="orderByString">
+ <add-error><fail-message message="COGS costing method is
not supported: ${partyAcctgPreference.cogsMethodId}"/></add-error>
+ <check-errors/>
+ </if-empty>
+ <entity-condition entity-name="InventoryItem"
list="costInventoryItems">
+ <condition-list combine="and">
+ <condition-expr field-name="ownerPartyId"
operator="equals" from-field="inventoryItem.ownerPartyId"/>
+ <condition-expr field-name="facilityId"
operator="equals" from-field="inventoryItem.facilityId"/>
+ <condition-expr field-name="productId"
operator="equals" from-field="inventoryItem.productId"/>
+ <condition-expr field-name="accountingQuantityTotal"
operator="greater" value="0.0"/>
+ </condition-list>
+ <order-by field-name="${orderByString}"/>
+ </entity-condition>
+ <set field="remainingQuantity"
from-field="itemIssuance.quantity"/>
+ <iterate list="costInventoryItems" entry="costInventoryItem">
+ <if-compare field="remainingQuantity" operator="greater"
value="0.0" type="BigDecimal">
+ <if-compare-field field="remainingQuantity"
operator="less-equals" to-field="costInventoryItem.accountingQuantityTotal"
type="BigDecimal">
+ <set field="costInventoryItemQuantity"
from-field="remainingQuantity"/>
+ <set field="remainingQuantity" value="0.0"
type="BigDecimal"/>
+ <else>
+ <set field="costInventoryItemQuantity"
from-field="costInventoryItem.accountingQuantityTotal"/>
+ <set field="remainingQuantity"
value="${remainingQuantity - costInventoryItem.accountingQuantityTotal}"
type="BigDecimal"/>
+ </else>
+ </if-compare-field>
+ <!-- An inventory item detail record is created to
keep track of the units (value) that we are going to add to the inventory
account -->
+ <set from-field="costInventoryItem.inventoryItemId"
field="createDetailMap.inventoryItemId"/>
+ <set value="${-1 * costInventoryItemQuantity}"
field="createDetailMap.accountingQuantityDiff" type="BigDecimal"/>
+ <call-service service-name="createInventoryItemDetail"
in-map-name="createDetailMap"/>
+
+ <calculate field="costInventoryItemAmount"
decimal-scale="${ledgerDecimals}" rounding-mode="${roundingMode}">
+ <calcop operator="multiply">
+ <calcop operator="get"
field="costInventoryItemQuantity"/>
+ <calcop operator="get"
field="costInventoryItem.unitCost"/>
+ </calcop>
+ </calculate>
+ <calculate field="totalAmount"
decimal-scale="${ledgerDecimals}" rounding-mode="${roundingMode}">
+ <calcop operator="add">
+ <calcop operator="get"
field="costInventoryItemAmount"/>
+ <calcop operator="get" field="totalAmount"/>
+ </calcop>
+ </calculate>
+ <make-value entity-name="AcctgTransEntry"
value-field="creditEntry"/>
+ <set field="creditEntry.debitCreditFlag" value="C"/>
+ <set field="creditEntry.glAccountTypeId"
value="INVENTORY_ACCOUNT"/>
+ <set field="creditEntry.organizationPartyId"
from-field="inventoryItem.ownerPartyId"/>
+ <set field="creditEntry.productId"
from-field="inventoryItem.productId"/>
+ <set field="creditEntry.inventoryItemId"
from-field="costInventoryItem.inventoryItemId"/>
+ <set field="creditEntry.origAmount"
from-field="costInventoryItemAmount"/>
+ <set field="creditEntry.origCurrencyUomId"
from-field="inventoryItem.currencyUomId"/>
+ <if-not-empty field="billToCustomer">
+ <set field="creditEntry.partyId"
from-field="billToCustomer.partyId"/>
+ <set field="creditEntry.roleTypeId"
from-field="billToCustomer.roleTypeId"/>
+ </if-not-empty>
+ <set field="acctgTransEntries[]"
from-field="creditEntry" type="Object"/>
+ <clear-field field="creditEntry"/>
+ </if-compare>
+ </iterate>
+ <if-compare field="remainingQuantity" operator="greater"
value="0.0" type="BigDecimal">
+ <add-error><fail-message message="Could not find enough
accounting inventory for product [${inventoryItem.productId}]; remaining
quantity: ${remainingQuantity}"/></add-error>
+ <check-errors/>
+ </if-compare>
+ </else>
+ </if>
<!-- Debit -->
<make-value entity-name="AcctgTransEntry" value-field="debitEntry"/>
<set field="debitEntry.debitCreditFlag" value="D"/>
@@ -1284,11 +1312,34 @@ under the License.
</else>
</if-not-empty>
<!-- TODO: handle serialized inventory -->
+ <set field="partyAccountingPreferencesCallMap.organizationPartyId"
from-field="inventoryItem.ownerPartyId"/>
+ <call-service service-name="getPartyAccountingPreferences"
in-map-name="partyAccountingPreferencesCallMap">
+ <result-to-field result-name="partyAccountingPreference"
field="partyAcctgPreference"/>
+ </call-service>
<if-not-empty field="shipmentReceipt.returnId">
- <set field="getProdAvgCostMap.inventoryItem"
from-field="inventoryItem"/>
- <call-service service-name="getProductAverageCost"
in-map-name="getProdAvgCostMap">
- <result-to-field result-name="unitCost"/>
- </call-service>
+ <if>
+ <condition>
+ <or>
+ <if-compare field="partyAcctgPreference.cogsMethodId"
operator="equals" value="COGS_INV_COST" type="String"/>
+ <if-compare field="partyAcctgPreference.cogsMethodId"
operator="equals" value="COGS_AVG_COST" type="String"/>
+ </or>
+ </condition>
+ <then>
+ <if-compare field="partyAcctgPreference.cogsMethodId"
operator="equals" value="COGS_AVG_COST" type="String">
+ <set field="getProdAvgCostMap.inventoryItem"
from-field="inventoryItem"/>
+ <call-service service-name="getProductAverageCost"
in-map-name="getProdAvgCostMap">
+ <result-to-field result-name="unitCost"/>
+ </call-service>
+ <else>
+ <set field="unitCost"
from-field="inventoryItem.unitCost"/>
+ </else>
+ </if-compare>
+ </then>
+ <else>
+ <!-- LIFO and FIFO-->
+ <set field="unitCost" from-field="inventoryItem.unitCost"/>
+ </else>
+ </if>
<else>
<set field="unitCost" from-field="inventoryItem.unitCost"/>
</else>