Author: jacopoc
Date: Wed Dec 23 15:07:06 2009
New Revision: 893541
URL: http://svn.apache.org/viewvc?rev=893541&view=rev
Log:
Enhancements to the support of actual costs in production runs:
* in form definitions: converted (not working) bsh calls into groovy calls
* added cost information to screens showing inventory consumed and produced by
production runs
* added support for actual overhead costs of production runs
Modified:
ofbiz/trunk/applications/manufacturing/src/org/ofbiz/manufacturing/jobshopmgt/ProductionRunServices.java
ofbiz/trunk/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunCosts.groovy
ofbiz/trunk/applications/manufacturing/webapp/manufacturing/jobshopmgt/ProductionRunForms.xml
ofbiz/trunk/applications/product/data/ProductTypeData.xml
ofbiz/trunk/applications/product/script/org/ofbiz/product/cost/CostServices.xml
Modified:
ofbiz/trunk/applications/manufacturing/src/org/ofbiz/manufacturing/jobshopmgt/ProductionRunServices.java
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/manufacturing/src/org/ofbiz/manufacturing/jobshopmgt/ProductionRunServices.java?rev=893541&r1=893540&r2=893541&view=diff
==============================================================================
---
ofbiz/trunk/applications/manufacturing/src/org/ofbiz/manufacturing/jobshopmgt/ProductionRunServices.java
(original)
+++
ofbiz/trunk/applications/manufacturing/src/org/ofbiz/manufacturing/jobshopmgt/ProductionRunServices.java
Wed Dec 23 15:07:06 2009
@@ -845,6 +845,17 @@
Debug.logError(e, "Problem calling the updateWorkEffort
service", module);
return
ServiceUtil.returnError(UtilProperties.getMessage(resource,
"ManufacturingProductionRunStatusNotChanged", locale));
}
+ // Calculate and store the production run task actual costs
+ serviceContext.clear();
+ serviceContext.put("productionRunTaskId", taskId);
+ serviceContext.put("userLogin", userLogin);
+ resultService = null;
+ try {
+ resultService =
dispatcher.runSync("createProductionRunTaskCosts", serviceContext);
+ } catch (GenericServiceException e) {
+ Debug.logError(e, "Problem calling the
createProductionRunTaskCosts service", module);
+ return
ServiceUtil.returnError(UtilProperties.getMessage(resource,
"ManufacturingProductionRunStatusNotChanged", locale));
+ }
// If this is the last task, then the production run is marked as
'completed'
if (allTaskCompleted) {
serviceContext.clear();
@@ -858,17 +869,49 @@
Debug.logError(e, "Problem calling the updateWorkEffort
service", module);
return
ServiceUtil.returnError(UtilProperties.getMessage(resource,
"ManufacturingProductionRunStatusNotChanged", locale));
}
- }
- // Calculate and store the production run task actual costs
- serviceContext.clear();
- serviceContext.put("productionRunTaskId", taskId);
- serviceContext.put("userLogin", userLogin);
- resultService = null;
- try {
- resultService =
dispatcher.runSync("createProductionRunTaskCosts", serviceContext);
- } catch (GenericServiceException e) {
- Debug.logError(e, "Problem calling the
createProductionRunTaskCosts service", module);
- return
ServiceUtil.returnError(UtilProperties.getMessage(resource,
"ManufacturingProductionRunStatusNotChanged", locale));
+ // and compute the overhead costs associated to the finished
product
+ try {
+ // get the currency
+ GenericValue facility =
productionRun.getGenericValue().getRelatedOne("Facility");
+ Map outputMap =
dispatcher.runSync("getPartyAccountingPreferences", UtilMisc.<String,
Object>toMap("userLogin", userLogin, "organizationPartyId",
facility.getString("ownerPartyId")));
+ Map partyAccountingPreference =
(Map)outputMap.get("partyAccountingPreference");
+ if (partyAccountingPreference == null) {
+ return ServiceUtil.returnError("Unable to find a
currency for production run costs");
+ }
+ outputMap = dispatcher.runSync("getProductionRunCost",
UtilMisc.<String, Object>toMap("userLogin", userLogin, "workEffortId",
productionRunId));
+
+ BigDecimal totalCost =
(BigDecimal)outputMap.get("totalCost");
+ if (totalCost == null) {
+ totalCost = ZERO;
+ }
+
+ List productCostComponentCalcs =
delegator.findByAnd("ProductCostComponentCalc", UtilMisc.toMap("productId",
productionRun.getProductProduced().getString("productId")),
UtilMisc.toList("sequenceNum"));
+ for (int i = 0; i < productCostComponentCalcs.size(); i++)
{
+ GenericValue productCostComponentCalc =
(GenericValue)productCostComponentCalcs.get(i);
+ GenericValue costComponentCalc =
productCostComponentCalc.getRelatedOne("CostComponentCalc");
+ GenericValue customMethod =
costComponentCalc.getRelatedOne("CustomMethod");
+ if (customMethod == null) {
+ // TODO: not supported for CostComponentCalc
entries directly associated to a product
+ Debug.logWarning("Unable to create cost component
for cost component calc with id [" +
costComponentCalc.getString("costComponentCalcId") + "] because customMethod is
not set", module);
+ } else {
+ Map costMethodResult =
dispatcher.runSync(customMethod.getString("customMethodName"),
UtilMisc.toMap("productCostComponentCalc", productCostComponentCalc,
+
"costComponentCalc",
costComponentCalc,
+
"costComponentTypePrefix",
"ACTUAL",
+
"baseCost", totalCost,
+
"currencyUomId",
(String)partyAccountingPreference.get("baseCurrencyUomId"),
+
"userLogin", userLogin));
+ BigDecimal productCostAdjustment =
(BigDecimal)costMethodResult.get("productCostAdjustment");
+ totalCost = totalCost.add(productCostAdjustment);
+ Map inMap = UtilMisc.toMap("userLogin", userLogin,
"workEffortId", productionRunId);
+ inMap.put("costComponentTypeId", "ACTUAL_" +
productCostComponentCalc.getString("costComponentTypeId"));
+ inMap.put("costUomId",
(String)partyAccountingPreference.get("baseCurrencyUomId"));
+ inMap.put("cost", productCostAdjustment);
+ dispatcher.runSync("createCostComponent", inMap);
+ }
+ }
+ } catch(Exception e) {
+ return ServiceUtil.returnError("Unable to compute overhead
costs for production run: " + e.getMessage());
+ }
}
result.put("oldStatusId", oldStatusId);
@@ -1551,14 +1594,23 @@
Debug.logWarning(e.getMessage(), module);
return ServiceUtil.returnError(e.getMessage());
}
- // calculate the inventory item unit cost
+ // the inventory item unit cost is the product's standard cost
BigDecimal unitCost = ZERO;
try {
- Map outputMap = dispatcher.runSync("getProductionRunCost",
UtilMisc.<String, Object>toMap("userLogin", userLogin, "workEffortId",
productionRunId));
- BigDecimal totalCost = (BigDecimal)outputMap.get("totalCost");
- // FIXME
- unitCost = totalCost.divide(quantity, decimals, rounding);
- } catch (GenericServiceException e) {
+ // get the currency
+ GenericValue facility =
productionRun.getGenericValue().getRelatedOne("Facility");
+ Map outputMap =
dispatcher.runSync("getPartyAccountingPreferences", UtilMisc.<String,
Object>toMap("userLogin", userLogin, "organizationPartyId",
facility.getString("ownerPartyId")));
+ Map partyAccountingPreference =
(Map)outputMap.get("partyAccountingPreference");
+ if (partyAccountingPreference == null) {
+ return ServiceUtil.returnError("Unable to find a currency for
production run costs");
+ }
+ outputMap = dispatcher.runSync("getProductCost", UtilMisc.<String,
Object>toMap("userLogin", userLogin, "productId",
productionRun.getProductProduced().getString("productId"), "currencyUomId",
(String)partyAccountingPreference.get("baseCurrencyUomId"),
"costComponentTypePrefix", "EST_STD"));
+ unitCost = (BigDecimal)outputMap.get("productCost");
+ if (unitCost == null) {
+ unitCost = ZERO;
+ }
+
+ } catch (Exception e) {
Debug.logWarning(e.getMessage(), module);
return ServiceUtil.returnError(e.getMessage());
}
Modified:
ofbiz/trunk/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunCosts.groovy
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunCosts.groovy?rev=893541&r1=893540&r2=893541&view=diff
==============================================================================
---
ofbiz/trunk/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunCosts.groovy
(original)
+++
ofbiz/trunk/applications/manufacturing/webapp/manufacturing/WEB-INF/actions/jobshopmgt/ProductionRunCosts.groovy
Wed Dec 23 15:07:06 2009
@@ -29,4 +29,11 @@
taskCostsForm.putInContext("taskCosts", costs);
taskCosts.add([task : task ,costsForm : taskCostsForm]);
}
-context.taskCosts = taskCosts;
\ No newline at end of file
+// get the costs directly associated to the production run (e.g. overhead
costs)
+productionRun = delegator.findOne("WorkEffort", [workEffortId:
productionRunId], true);
+costs = EntityUtil.filterByDate(delegator.findByAnd("CostComponent",
[workEffortId : productionRunId]));
+HtmlFormWrapper taskCostsForm = new
HtmlFormWrapper("component://manufacturing/webapp/manufacturing/jobshopmgt/ProductionRunForms.xml",
"ProductionRunTaskCosts", request, response);
+taskCostsForm.putInContext("taskCosts", costs);
+taskCosts.add([task : productionRun ,costsForm : taskCostsForm]);
+
+context.taskCosts = taskCosts;
Modified:
ofbiz/trunk/applications/manufacturing/webapp/manufacturing/jobshopmgt/ProductionRunForms.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/manufacturing/webapp/manufacturing/jobshopmgt/ProductionRunForms.xml?rev=893541&r1=893540&r2=893541&view=diff
==============================================================================
---
ofbiz/trunk/applications/manufacturing/webapp/manufacturing/jobshopmgt/ProductionRunForms.xml
(original)
+++
ofbiz/trunk/applications/manufacturing/webapp/manufacturing/jobshopmgt/ProductionRunForms.xml
Wed Dec 23 15:07:06 2009
@@ -140,13 +140,14 @@
</hyperlink>
</field>
<field name="lotId" entry-name="inventoryItemId"><display-entity
entity-name="InventoryItem" key-field-name="inventoryItemId"
description="${lotId} "/></field>
- <field name="creationDate"
entry-name="inventoryItemId"><display-entity entity-name="InventoryItem"
key-field-name="inventoryItemId" description="${datetimeReceived}"/></field>
+ <field name="unitCost" entry-name="inventoryItemId"><display-entity
entity-name="InventoryItem" key-field-name="inventoryItemId"
description="${unitCost} "/></field>
+\ <field name="creationDate"
entry-name="inventoryItemId"><display-entity entity-name="InventoryItem"
key-field-name="inventoryItemId" description="${datetimeReceived}"/></field>
</form>
<form name="ViewListProductionRunRoutingTasks" type="list" title=""
list-name="productionRunRoutingTasks"
odd-row-style="alternate-row" default-table-style="basic-table
hover-bar">
<row-actions>
- <set field="estimatedTotalMilliSeconds"
value="${bsh:estimatedMilliSeconds * quantity}" type="BigDecimal"/>
+ <set field="estimatedTotalMilliSeconds"
value="${groovy:estimatedMilliSeconds * quantity}" type="BigDecimal"/>
</row-actions>
<field name="priority"
title="${uiLabelMap.CommonSequenceNum}"><display/></field>
<field name="workEffortId"
title="${uiLabelMap.ManufacturingTaskName}"><display
description="${workEffortName} [${workEffortId}]"/></field>
@@ -160,7 +161,7 @@
<form name="ListProductionRunRoutingTasks" type="list"
target="ProductionRunTasks" title="" list-name="productionRunRoutingTasks"
odd-row-style="alternate-row" header-row-style="header-row-2"
default-table-style="basic-table hover-bar">
<row-actions>
- <set field="estimatedTotalMilliSeconds"
value="${bsh:estimatedMilliSeconds * quantity}" type="BigDecimal"/>
+ <set field="estimatedTotalMilliSeconds"
value="${groovy:estimatedMilliSeconds * quantity}" type="BigDecimal"/>
</row-actions>
<field name="priority"
title="${uiLabelMap.CommonSequenceNum}"><display/></field>
<field name="workEffortId"
title="${uiLabelMap.ManufacturingTaskName}"><display
description="${workEffortName} [${workEffortId}]"/></field>
@@ -509,12 +510,12 @@
header-row-style="header-row" default-table-style="basic-table">
<field name="productionRunId"><hidden/></field>
<field name="workEffortId"><hidden/></field>
- <field name="productId" title="${uiLabelMap.ProductProductId}"
use-when="${bsh:delivProducts.size()>0}">
+ <field name="productId" title="${uiLabelMap.ProductProductId}"
use-when="${groovy:delivProducts.size()>0}">
<drop-down allow-empty="false">
<list-options list-name="delivProducts" key-name="productId"
description="${productId}"/>
</drop-down>
</field>
- <field name="productId" title="${uiLabelMap.ProductProductId}"
use-when="${bsh:delivProducts.size()==0}"><lookup
target-form-name="LookupProduct"/></field>
+ <field name="productId" title="${uiLabelMap.ProductProductId}"
use-when="${groovy:delivProducts.size()==0}"><lookup
target-form-name="LookupProduct"/></field>
<field name="quantity"
title="${uiLabelMap.ManufacturingAddQuantityProduced}">
<text/>
</field>
@@ -904,7 +905,7 @@
<form name="ProductionRunTaskActualComponents" type="list"
target="updateProductionRunComponent"
paginate-target="ProductionRunActualComponents" title="" list-name="records"
odd-row-style="alternate-row" default-table-style="basic-table
hover-bar">
<row-actions>
- <set field="quantityOnHandDiff"
value="${bsh:-1*quantityOnHandDiff}" type="BigDecimal"/>
+ <set field="quantityOnHandDiff"
value="${groovy:-1*quantityOnHandDiff}" type="BigDecimal"/>
</row-actions>
<field name="inventoryItemId" widget-style="buttontext">
<hyperlink target="/facility/control/EditInventoryItem"
description="${inventoryItemId}" also-hidden="false" target-type="inter-app">
@@ -917,6 +918,9 @@
<field name="workEffortId"><hidden/></field>
<field name="productionRunId"><hidden/></field>
<field name="quantityOnHandDiff"
title="${uiLabelMap.CommonQuantity}"><display/></field>
+ <field name="unitCost" entry-name="inventoryItemId">
+ <display-entity entity-name="InventoryItem"
key-field-name="inventoryItemId" description="${unitCost}"/>
+ </field>
<field name="reasonEnumId">
<display-entity entity-name="Enumeration" key-field-name="enumId"
description="${description}"/>
</field>
Modified: ofbiz/trunk/applications/product/data/ProductTypeData.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/data/ProductTypeData.xml?rev=893541&r1=893540&r2=893541&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/data/ProductTypeData.xml (original)
+++ ofbiz/trunk/applications/product/data/ProductTypeData.xml Wed Dec 23
15:07:06 2009
@@ -35,6 +35,9 @@
<CostComponentType costComponentTypeId="ACTUAL_ROUTE_COST"
description="Actual Route (fixed asset usage) Cost" hasTable="N"
parentTypeId="ROUTE_COST"/>
<CostComponentType costComponentTypeId="ACTUAL_LABOR_COST"
description="Actual Labor Cost" hasTable="N" parentTypeId="LABOR_COST"/>
<CostComponentType costComponentTypeId="ACTUAL_OTHER_COST"
description="Actual Other Cost" hasTable="N" parentTypeId="OTHER_COST"/>
+ <CostComponentType costComponentTypeId="ACTUAL_GEN_COST"
description="Actual General Cost" hasTable="N" parentTypeId="GEN_COST"/>
+ <CostComponentType costComponentTypeId="ACTUAL_IND_COST"
description="Actual Indirect Cost" hasTable="N" parentTypeId="IND_COST"/>
+ <CostComponentType costComponentTypeId="ACTUAL_OTHER_COST"
description="Actual Other Cost" hasTable="N" parentTypeId="OTHER_COST"/>
<!-- Cost Formulae -->
<CustomMethodType customMethodTypeId="COST_FORMULA" description="Formula
for calculating costs for tasks and products"/>
Modified:
ofbiz/trunk/applications/product/script/org/ofbiz/product/cost/CostServices.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/script/org/ofbiz/product/cost/CostServices.xml?rev=893541&r1=893540&r2=893541&view=diff
==============================================================================
---
ofbiz/trunk/applications/product/script/org/ofbiz/product/cost/CostServices.xml
(original)
+++
ofbiz/trunk/applications/product/script/org/ofbiz/product/cost/CostServices.xml
Wed Dec 23 15:07:06 2009
@@ -390,6 +390,7 @@
<get-related-one relation-name="CustomMethod"
to-value-field="customMethod" value-field="costComponentCalc"/>
<if-empty field="customMethod">
<!-- TODO: not supported for CostComponentCalc entries
directly associated to a product -->
+ <log level="warning" message="Unable to create cost component
for cost component calc with id [${costComponentCalc.costComponentCalcId}]
because customMethod is not set"/>
<else>
<clear-field field="customMethodParameters"/>
<set field="customMethodParameters.productCostComponentCalc"
from-field="productCostComponentCalc"/>