001: /*
002: * $Id: ProductionRunServices.java,v 1.2 2003/12/09 20:49:17 holivier Exp $
003: *
004: * Copyright (c) 2001, 2002, 2003 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: *
024: */
025: package org.ofbiz.manufacturing.jobshopmgt;
026:
027: import java.sql.Timestamp;
028: import java.util.Collection;
029: import java.util.HashMap;
030: import java.util.Iterator;
031: import java.util.LinkedList;
032: import java.util.List;
033: import java.util.Locale;
034: import java.util.Map;
035:
036: import org.ofbiz.base.util.Debug;
037: import org.ofbiz.base.util.UtilDateTime;
038: import org.ofbiz.base.util.UtilMisc;
039: import org.ofbiz.base.util.UtilProperties;
040: import org.ofbiz.base.util.UtilValidate;
041: import org.ofbiz.entity.GenericDelegator;
042: import org.ofbiz.entity.GenericEntityException;
043: import org.ofbiz.entity.GenericValue;
044: import org.ofbiz.entity.condition.EntityExpr;
045: import org.ofbiz.entity.condition.EntityOperator;
046: import org.ofbiz.entity.util.EntityTypeUtil;
047: import org.ofbiz.entity.util.EntityUtil;
048: import org.ofbiz.security.Security;
049: import org.ofbiz.service.DispatchContext;
050: import org.ofbiz.service.ModelService;
051: import org.ofbiz.service.ServiceUtil;
052: import org.ofbiz.service.LocalDispatcher;
053: import org.ofbiz.service.GenericServiceException;
054:
055: import org.ofbiz.manufacturing.techdata.TechDataServices;
056:
057: /**
058: * Services for Production Run maintenance
059: *
060: * @author <a href="mailto:olivier.heintz@nereide.biz">Olivier Heintz</a>
061: * @version $Revision: 1.2 $
062: * @since 3.0
063: */
064: public class ProductionRunServices {
065:
066: public static final String module = ProductionRunServices.class
067: .getName();
068: public static final String resource = "ManufacturingUiLabels";
069:
070: /**
071: * Deletes a ProductionRun.
072: * @param ctx The DispatchContext that this service is operating in.
073: * @param context Map containing the input parameters.
074: * @return Map with the result of the service, the output parameters.
075: */
076: public static Map deleteProductionRun(DispatchContext ctx,
077: Map context) {
078:
079: /*
080: * pretty serious operation, status depending would delete:
081: * - task
082: * - goods
083: * - inventoryItem
084: * - ...
085: *
086: * The analyse is plan but I don't know when ;-) ...
087: */
088: return ServiceUtil
089: .returnError("Cannot delete productionRun , operation not yet implemented");
090: }
091:
092: /**
093: * Creates a Production Run.
094: * - check if routing - product link exist
095: * - check if product have a Bill Of Material
096: * - check if routing have routingTask
097: * - create the workEffort for ProductionRun
098: * - for each valid routingTask of the routing create a workeffort-task
099: * - for the first routingTask, create for all the valid productIdTo with no associateRoutingTask a WorkEffortGoodStandard
100: * - for each valid routingTask of the routing and valid productIdTo associate with this RoutingTask create a WorkEffortGoodStandard
101: * @param ctx The DispatchContext that this service is operating in.
102: * @param context Map containing the input parameters, productId, routingId, pRQuantity, startDate, workEffortName, description
103: * @return Map with the result of the service, the output parameters.
104: */
105: public static Map createProductionRun(DispatchContext ctx,
106: Map context) {
107: Map result = new HashMap();
108: GenericDelegator delegator = ctx.getDelegator();
109: LocalDispatcher dispatcher = ctx.getDispatcher();
110: Security security = ctx.getSecurity();
111: Timestamp now = UtilDateTime.nowTimestamp();
112: List msgResult = new LinkedList();
113: Locale locale = (Locale) context.get("locale");
114: GenericValue userLogin = (GenericValue) context
115: .get("userLogin");
116: /* TODO: security management and finishing cleaning (ex copy from PartyServices.java)
117: if (!security.hasEntityPermission(secEntity, secOperation, userLogin)) {
118: result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_ERROR);
119: result.put(ModelService.ERROR_MESSAGE, "You do not have permission to perform this operation for this party");
120: return partyId;
121: }
122: */
123: String productId = (String) context.get("productId");
124: String workEffortId = (String) context.get("routingId");
125: java.sql.Timestamp startDate = (java.sql.Timestamp) context
126: .get("startDate");
127: String statusId = "PRUN_CREATED";
128: GenericValue routing = null, product = null;
129: List workEffortProducts = null, productBoms = null, routingTaskAssocs = null;
130:
131: try {
132: workEffortProducts = delegator.findByAnd(
133: "WorkEffortGoodStandard", UtilMisc.toMap(
134: "productId", productId, "workEffortId",
135: workEffortId));
136: routing = delegator.findByPrimaryKey("WorkEffort", UtilMisc
137: .toMap("workEffortId", workEffortId));
138: product = delegator.findByPrimaryKey("Product", UtilMisc
139: .toMap("productId", productId));
140: // TODO: sort by seq and filter by date, pour ne prendre que les composants valide à la date de lancement de l'OF
141: productBoms = delegator.findByAnd("ProductAssoc", UtilMisc
142: .toMap("productId", productId,
143: "productAssocTypeId", "MANUF_COMPONENT"));
144: // TODO: filter by date, pour ne prendre que les opérations valide à la date de lancement de l'OF
145: routingTaskAssocs = delegator.findByAnd("WorkEffortAssoc",
146: UtilMisc.toMap("workEffortIdFrom", workEffortId,
147: "workEffortAssocTypeId",
148: "ROUTING_COMPONENT"), UtilMisc.toList(
149: "sequenceNum", "fromDate"));
150: } catch (GenericEntityException e) {
151: Debug.logWarning(e.getMessage(), module);
152: }
153: //TODO: test sur quantité vide et choix de la bonne gamme
154: if (workEffortProducts == null)
155: return ServiceUtil.returnError(UtilProperties.getMessage(
156: resource, "ManufacturingProductRoutingNotExist",
157: locale));
158: if (productBoms == null)
159: return ServiceUtil.returnError(UtilProperties.getMessage(
160: resource, "ManufacturingProductHasNoBom", locale));
161: if (routingTaskAssocs == null)
162: return ServiceUtil.returnError(UtilProperties.getMessage(
163: resource, "ManufacturingRoutingHasNoRoutingTask",
164: locale));
165:
166: // ProductionRun header creation,
167: //TODO: Calculate the estimatedCompletionDate
168: String workEffortName = (String) context.get("workEffortName");
169: String description = (String) context.get("description");
170: Double pRQuantity = (Double) context.get("pRQuantity");
171: if (workEffortName == null)
172: workEffortName = product.getString("productName") + "-"
173: + routing.getString("workEffortName");
174: Map serviceContext = new HashMap();
175: serviceContext.put("workEffortTypeId", "PROD_ORDER_HEADER");
176: serviceContext.put("workEffortPurposeTypeId",
177: "WEPT_PRODUCTION_RUN");
178: serviceContext.put("currentStatusId", "PRUN_CREATED");
179: serviceContext.put("workEffortName", workEffortName);
180: serviceContext.put("description", description);
181: serviceContext.put("estimatedStartDate", startDate);
182: serviceContext.put("quantityToProduce", pRQuantity);
183: serviceContext.put("userLogin", userLogin);
184: Map resultService = null;
185: try {
186: resultService = dispatcher.runSync("createWorkEffort",
187: serviceContext);
188: } catch (GenericServiceException e) {
189: Debug.logError(e,
190: "Problem calling the createWorkEffort service",
191: module);
192: }
193: String productionRunId = (String) resultService
194: .get("workEffortId");
195: if (Debug.infoOn())
196: Debug.logInfo("ProductioRun created: " + productionRunId,
197: module);
198:
199: // Multi creation ProductionRunTask and GoodAssoc
200: Iterator rt = routingTaskAssocs.iterator();
201: boolean first = true;
202: while (rt.hasNext()) {
203: GenericValue routingTaskAssoc = (GenericValue) rt.next();
204: if (TechDataServices.routingTaskAssocIsValid(
205: routingTaskAssoc, startDate)) {
206: GenericValue routingTask = null;
207: try {
208: routingTask = routingTaskAssoc
209: .getRelatedOne("ToWorkEffort");
210: } catch (GenericEntityException e) {
211: Debug.logError(e.getMessage(), module);
212: }
213: // TODO: Calculate the estimatedCompletionDate
214: serviceContext.clear();
215: serviceContext.put("workEffortTypeId",
216: "PROD_ORDER_TASK");
217: serviceContext.put("workEffortPurposeTypeId",
218: routingTask
219: .getString("workEffortPurposeTypeId"));
220: serviceContext.put("currentStatusId", "PRUN_CREATED");
221: serviceContext.put("workEffortParentId",
222: productionRunId);
223: serviceContext.put("workEffortName", routingTask
224: .getString("workEffortName"));
225: serviceContext.put("description", routingTask
226: .getString("description"));
227: serviceContext.put("estimatedStartDate", startDate);
228: serviceContext.put("quantityToProduce", pRQuantity);
229: serviceContext.put("userLogin", userLogin);
230: resultService = null;
231: try {
232: resultService = dispatcher.runSync(
233: "createWorkEffort", serviceContext);
234: } catch (GenericServiceException e) {
235: Debug
236: .logError(
237: e,
238: "Problem calling the createWorkEffort service",
239: module);
240: }
241: String productionRunTaskId = (String) resultService
242: .get("workEffortId");
243: if (Debug.infoOn())
244: Debug.logInfo("ProductionRunTaskId created: "
245: + productionRunTaskId, module);
246: if (first) {
247: first = false;
248: Iterator pb = productBoms.iterator();
249: while (pb.hasNext()) {
250: GenericValue productBom = (GenericValue) pb
251: .next();
252: if (TechDataServices.productBomIsValid(
253: productBom, startDate)
254: && productBom
255: .getString("routingWorkEffortId") == null) {
256: serviceContext.clear();
257: serviceContext.put("workEffortId",
258: productionRunTaskId);
259: serviceContext.put("productId", productBom
260: .getString("productIdTo"));
261: serviceContext.put("statusId",
262: "WIP_INCOMING_FULFIL");
263: serviceContext.put("fromDate", productBom
264: .getTimestamp("fromDate"));
265: double scrapFactor = (productBom
266: .get("scrapFactor") != null) ? productBom
267: .getDouble("scrapFactor")
268: .doubleValue()
269: : 0;
270: serviceContext
271: .put(
272: "estimatedQuantity",
273: new Double(
274: Math
275: .floor((productBom
276: .getDouble(
277: "quantity")
278: .doubleValue()
279: * pRQuantity
280: .doubleValue() / (1 - (scrapFactor / 100))) + 0.5)));
281: serviceContext.put("userLogin", userLogin);
282: resultService = null;
283: try {
284: resultService = dispatcher.runSync(
285: "createWorkEffortGoodStandard",
286: serviceContext);
287: } catch (GenericServiceException e) {
288: Debug
289: .logError(
290: e,
291: "Problem calling the createWorkEffortGoodStandard service",
292: module);
293: }
294: if (Debug.infoOn())
295: Debug
296: .logInfo(
297: "ProductLink created for productId: "
298: + productBom
299: .getString("productIdTo"),
300: module);
301: }
302: }
303: }
304: // TODO: generate the WorkEffortGoodStandard if there are some BOM at this RoutingTask pour ça il faut une jointure de table BOM et ROU
305: // TODO: startDate = estimatedCompletionDate
306: }
307: }
308: // TODO: out param must be productionRunId and not list of message
309: msgResult.add("réussi");
310:
311: result.put("msgResult", msgResult);
312: result.put(ModelService.SUCCESS_MESSAGE, UtilProperties
313: .getMessage(resource,
314: "ManufacturingProductionRunCreated", UtilMisc
315: .toMap("productionRunId",
316: productionRunId), locale));
317: return result;
318: }
319:
320: }
|