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"/>


Reply via email to