/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // The only required parameter is "productionRunId". // The "actionForm" parameter triggers actions (see "ProductionRunSimpleEvents.xml"). import org.ofbiz.entity.util.EntityUtil; import org.ofbiz.entity.GenericValue; import org.ofbiz.widget.html.HtmlFormWrapper; import org.ofbiz.manufacturing.jobshopmgt.ProductionRun; import javolution.util.FastList; productionRunId = parameters.productionRunId ?: parameters.workEffortId; if (productionRunId) { ProductionRun productionRun = new ProductionRun(productionRunId, delegator, dispatcher); if (productionRun.exist()) { productionRunId = productionRun.getGenericValue().workEffortId; context.productionRunId = productionRunId; context.productionRun = productionRun.getGenericValue(); // Find all the order items to which this production run is linked. orderItems = delegator.findByAnd("WorkOrderItemFulfillment", [workEffortId : productionRunId]); if (orderItems) { context.orderItems = orderItems; } // Find all the work efforts that must be completed before this one. mandatoryWorkEfforts = EntityUtil.filterByDate(delegator.findByAnd("WorkEffortAssoc", [workEffortIdTo : productionRunId, workEffortAssocTypeId : "WORK_EFF_PRECEDENCY"])); if (mandatoryWorkEfforts) { context.mandatoryWorkEfforts = mandatoryWorkEfforts; } // Find all the work efforts that can start after this one. dependentWorkEfforts = EntityUtil.filterByDate(delegator.findByAnd("WorkEffortAssoc", [workEffortIdFrom : productionRunId, workEffortAssocTypeId : "WORK_EFF_PRECEDENCY"])); if (dependentWorkEfforts) { context.dependentWorkEfforts = dependentWorkEfforts; } quantityToProduce = productionRun.getGenericValue().get("quantityToProduce") ?: 0.0; // Find the inventory items produced inventoryItems = delegator.findByAnd("WorkEffortInventoryProduced", [workEffortId : productionRunId]); context.inventoryItems = inventoryItems; if (inventoryItems) { lastWorkEffortInventoryProduced = (GenericValue)inventoryItems.get(inventoryItems.size() - 1); lastInventoryItem = lastWorkEffortInventoryProduced.getRelatedOne("InventoryItem"); context.lastLotId = lastInventoryItem.lotId; } // Find if the production run can produce inventory. quantityProduced = productionRun.getGenericValue().quantityProduced ?: 0.0; quantityRejected = productionRun.getGenericValue().quantityRejected ?: 0.0; lastTask = productionRun.getLastProductionRunRoutingTask(); quantityDeclared = lastTask ? (lastTask.quantityProduced ?: 0.0) : 0.0 ; if (lastTask && ("PRUN_RUNNING".equals(lastTask.currentStatusId) || "PRUN_COMPLETED".equals(lastTask.currentStatusId))) { context.canDeclareAndProduce = "Y"; } maxQuantity = quantityDeclared - quantityProduced; productionRunData = [:]; productionRunData.workEffortId = productionRunId; productionRunData.productId = productionRun.getProductProduced().productId; if (maxQuantity > 0 && !"WIP".equals(productionRun.getProductProduced().productTypeId)) { productionRunData.quantity = maxQuantity; context.canProduce = "Y"; } productionRunData.quantityToProduce = quantityToProduce; productionRunData.quantityProduced = quantityProduced; productionRunData.quantityRejected = quantityRejected; productionRunData.quantityRemaining = quantityToProduce - quantityProduced; productionRunData.estimatedCompletionDate = productionRun.getEstimatedCompletionDate(); productionRunData.productionRunName = productionRun.getProductionRunName(); productionRunData.description = productionRun.getDescription(); productionRunData.estimatedStartDate = productionRun.getEstimatedStartDate(); productionRunData.actualStartDate = productionRun.getGenericValue().getTimestamp("actualStartDate"); productionRunData.actualCompletionDate = productionRun.getGenericValue().getTimestamp("actualCompletionDate"); productionRunData.currentStatusId = productionRun.getGenericValue().currentStatusId; context.productionRunData = productionRunData; actionForm = parameters.actionForm ?: "beforeActionProductionRun"; context.actionForm = actionForm; //--------------- // Routing tasks //--------------- // routingTask update sub-screen routingTaskId = parameters.routingTaskId; if (routingTaskId && (actionForm.equals("UpdateRoutingTask") || actionForm.equals("EditRoutingTask"))) { routingTask = delegator.findByPrimaryKey("WorkEffort", [workEffortId : routingTaskId]); Map routingTaskData = routingTask.getAllFields(); routingTaskData.estimatedSetupMillis = routingTask.getDouble("estimatedSetupMillis"); routingTaskData.estimatedMilliSeconds = routingTask.getDouble("estimatedMilliSeconds"); HtmlFormWrapper editPrRoutingTaskWrapper = new HtmlFormWrapper("component://manufacturing/webapp/manufacturing/jobshopmgt/ProductionRunForms.xml", "EditProductionRunDeclRoutingTask", request, response); editPrRoutingTaskWrapper.putInContext("routingTaskData", routingTaskData); editPrRoutingTaskWrapper.putInContext("actionForm", "UpdateRoutingTask"); routingTaskData.partyId = userLogin.partyId; context.editPrRoutingTaskWrapper = editPrRoutingTaskWrapper; context.routingTaskId = routingTaskId; // Get the list of deliverable products, i.e. the WorkEffortGoodStandard entries // with workEffortGoodStdTypeId = "PRUNT_PROD_DELIV": // first of all we get the template task (the routing task) templateTaskAssoc = EntityUtil.getFirst(EntityUtil.filterByDate(delegator.findByAnd("WorkEffortAssoc", [workEffortIdTo : routingTask.workEffortId, workEffortAssocTypeId : "WORK_EFF_TEMPLATE"]))); templateTask = [:]; if (templateTaskAssoc) { templateTask = templateTaskAssoc.getRelatedOne("FromWorkEffort"); } delivProducts = []; if (templateTask) { delivProducts = EntityUtil.filterByDate(templateTask.getRelatedByAnd("WorkEffortGoodStandard", [workEffortGoodStdTypeId : "PRUNT_PROD_DELIV"])); } HtmlFormWrapper createRoutingTaskDelivProductForm = new HtmlFormWrapper("component://manufacturing/webapp/manufacturing/jobshopmgt/ProductionRunForms.xml", "CreateRoutingTaskDelivProduct", request, response); createRoutingTaskDelivProductForm.putInContext("formData", [productionRunId : productionRunId, workEffortId : routingTaskId]); context.createRoutingTaskDelivProductForm = createRoutingTaskDelivProductForm; context.delivProducts = delivProducts; // Get the list of delivered products, i.e. inventory items prunInventoryProduced = delegator.findByAnd("WorkEffortAndInventoryProduced", [workEffortId : routingTaskId]); context.prunInventoryProduced = prunInventoryProduced; HtmlFormWrapper prunInventoryProducedForm = new HtmlFormWrapper("component://manufacturing/webapp/manufacturing/jobshopmgt/ProductionRunForms.xml", "ProductionRunTaskInventoryProducedList", request, response); prunInventoryProducedForm.putInContext("prunInventoryProduced", prunInventoryProduced); context.prunInventoryProducedForm = prunInventoryProducedForm; } // RoutingTasks list List productionRunRoutingTasks = productionRun.getProductionRunRoutingTasks(); String startTaskId = null; // which production run task is ready to start and has the [Start] buton next to it String issueTaskId = null; // which production run task is ready to have products issued with [Issue Components] button String completeTaskId = null; // which task has the [Complete] button next to it productionRunRoutingTasks.each { task -> // only PRUN_RUNNING tasks can have items issued or production run completed if ("PRUN_RUNNING".equals(task.currentStatusId)) { // Use WorkEffortGoodStandard to figure out if there are products which are needed for this task (PRUNT_PRODNEEDED) and which have not been issued (ie, WEGS_CREATED). // If so this task should have products issued components = delegator.findByAnd("WorkEffortGoodStandard", [workEffortId : task.workEffortId, workEffortGoodStdTypeId : "PRUNT_PROD_NEEDED"]); List notIssued = EntityUtil.filterByAnd(components, [statusId : "WEGS_CREATED"]); if (components && notIssued) { issueTaskId = task.workEffortId; } if (!issueTaskId) { completeTaskId = task.workEffortId; } } // the first CREATED and SCHEDULED task will be the startTaskId. As the issue and complete tasks are filled out this condition will no longer be true if (!startTaskId && !issueTaskId && !completeTaskId && ("PRUN_CREATED".equals(task.currentStatusId) || "PRUN_SCHEDULED".equals(task.currentStatusId))) { startTaskId = task.workEffortId; } } context.productionRunRoutingTasks = productionRunRoutingTasks; context.startTaskId = (startTaskId ? startTaskId: "null"); context.issueTaskId = (issueTaskId? issueTaskId: "null"); context.completeTaskId = (completeTaskId != null? completeTaskId: "null"); // Product components list productionRunComponents = productionRun.getProductionRunComponents(); productionRunComponentsData = FastList.newInstance(); productionRunComponentsDataReadyForIssuance = FastList.newInstance(); productionRunComponentsAlreadyIssued = FastList.newInstance(); if (productionRunComponents) { productionRunComponents.each { component -> product = component.getRelatedOne("Product"); componentName = product.getString("internalName"); productionRunTask = component.getRelatedOne("WorkEffort"); workEffortName = productionRunTask.getString("workEffortName"); Map componentData = component.getAllFields(); componentData.internalName = componentName; componentData.workEffortName = workEffortName; componentData.facilityId = productionRunTask.facilityId; issuances = delegator.findByAnd("WorkEffortAndInventoryAssign", [workEffortId : component.workEffortId, productId : product.productId]); totalIssued = 0.0; issuances.each { issuance -> issued = issuance.quantity; if (issued) { totalIssued += issued; } } returns = delegator.findByAnd("WorkEffortAndInventoryProduced", [workEffortId : component.workEffortId , productId : product.productId]); totalReturned = 0.0; returns.each { returned -> returnDetail = EntityUtil.getFirst(delegator.findByAnd("InventoryItemDetail", [inventoryItemId : returned.inventoryItemId], ["inventoryItemDetailSeqId"])); if (returnDetail) { qtyReturned = returnDetail.quantityOnHandDiff; if (qtyReturned) { totalReturned += qtyReturned; } } } componentData.issuedQuantity = totalIssued; componentData.returnedQuantity = totalReturned; componentData.currentStatusId = productionRunTask.currentStatusId; if ("PRUN_RUNNING".equals(productionRunTask.currentStatusId)) { componentData.isRunning = "Y"; } else { componentData.isRunning = "null"; } productionRunComponentsData.add(componentData); if ("PRUN_RUNNING".equals(productionRunTask.currentStatusId) && "WEGS_CREATED".equals(component.getString("statusId"))) { productionRunComponentsDataReadyForIssuance.add(componentData); } else if (totalIssued > 0.0) { productionRunComponentsAlreadyIssued.add(componentData); } } } context.productionRunComponentsData = productionRunComponentsData; context.productionRunComponentsDataReadyForIssuance = productionRunComponentsDataReadyForIssuance; context.productionRunComponentsAlreadyIssued = productionRunComponentsAlreadyIssued; } }