in applications/manufacturing/src/main/java/org/apache/ofbiz/manufacturing/jobshopmgt/ProductionRunServices.java [1725:2026]
public static Map<String, Object> productionRunProduce(DispatchContext ctx, Map<String, ? extends Object> context) {
Map<String, Object> result = new HashMap<>();
Delegator delegator = ctx.getDelegator();
LocalDispatcher dispatcher = ctx.getDispatcher();
Locale locale = (Locale) context.get("locale");
GenericValue userLogin = (GenericValue) context.get("userLogin");
// Mandatory input fields
String productionRunId = (String) context.get("workEffortId");
// Optional input fields
BigDecimal quantity = (BigDecimal) context.get("quantity");
String inventoryItemTypeId = (String) context.get("inventoryItemTypeId");
String lotId = (String) context.get("lotId");
String uomId = (String) context.get("quantityUomId");
String locationSeqId = (String) context.get("locationSeqId");
Boolean createLotIfNeeded = (Boolean) context.get("createLotIfNeeded");
Boolean autoCreateLot = (Boolean) context.get("autoCreateLot");
// The default is non-serialized inventory item
if (UtilValidate.isEmpty(inventoryItemTypeId)) {
inventoryItemTypeId = "NON_SERIAL_INV_ITEM";
}
// The default is to create a lot if the lotId is given, but the lot doesn't exist
if (createLotIfNeeded == null) {
createLotIfNeeded = Boolean.TRUE;
}
if (autoCreateLot == null) {
autoCreateLot = Boolean.FALSE;
}
List<String> inventoryItemIds = new LinkedList<>();
result.put("inventoryItemIds", inventoryItemIds);
// The production run is loaded
ProductionRun productionRun = new ProductionRun(productionRunId, delegator, dispatcher);
// The last task is loaded
GenericValue lastTask = productionRun.getLastProductionRunRoutingTask();
if (lastTask == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunTaskNotExists", locale));
}
if ("WIP".equals(productionRun.getProductProduced().getString("productTypeId"))) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductIsWIP", locale));
}
BigDecimal quantityProduced = productionRun.getGenericValue().getBigDecimal("quantityProduced");
if (quantityProduced == null) {
quantityProduced = BigDecimal.ZERO;
}
BigDecimal quantityDeclared = lastTask.getBigDecimal("quantityProduced");
if (quantityDeclared == null) {
quantityDeclared = BigDecimal.ZERO;
}
// If the quantity already produced is not lower than the quantity declared, no inventory is created.
BigDecimal maxQuantity = quantityDeclared.subtract(quantityProduced);
if (maxQuantity.compareTo(BigDecimal.ZERO) <= 0) {
return result;
}
// If quantity was not passed, the max quantity is used
if (quantity == null) {
quantity = maxQuantity;
}
//
if (quantity.compareTo(maxQuantity) > 0) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunProductProducedNotStillAvailable", locale));
}
if (lotId == null && autoCreateLot) {
createLotIfNeeded = Boolean.TRUE;
}
try {
// Find the lot
GenericValue lot = EntityQuery.use(delegator).from("Lot").where("lotId", lotId).queryOne();
if (lot == null) {
if (createLotIfNeeded) {
Map<String, Object> createLotCtx = ctx.makeValidContext("createLot", ModelService.IN_PARAM, context);
createLotCtx.put("creationDate", UtilDateTime.nowTimestamp());
Map<String, Object> serviceResults = dispatcher.runSync("createLot", createLotCtx);
if (ServiceUtil.isError(serviceResults)) {
Debug.logError(ServiceUtil.getErrorMessage(serviceResults), MODULE);
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResults));
}
lotId = (String) serviceResults.get("lotId");
} else if (UtilValidate.isNotEmpty(lotId)) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingLotNotExists", locale));
}
}
} catch (GenericEntityException | GenericServiceException e) {
Debug.logWarning(e.getMessage(), MODULE);
return ServiceUtil.returnError(e.getMessage());
}
GenericValue orderItem = null;
try {
// Find the related order item (if exists)
List<GenericValue> orderItems = productionRun.getGenericValue().getRelated("WorkOrderItemFulfillment", null, null, false);
orderItem = EntityUtil.getFirst(orderItems);
} catch (GenericEntityException e) {
Debug.logWarning(e.getMessage(), MODULE);
return ServiceUtil.returnError(e.getMessage());
}
// the inventory item unit cost is the product's standard cost
BigDecimal unitCost = ZERO;
GenericValue facility = null;
try {
// get the currency
facility = productionRun.getGenericValue().getRelatedOne("Facility", false);
Map<String, Object> outputMap = dispatcher.runSync("getPartyAccountingPreferences", UtilMisc.<String, Object>toMap("userLogin",
userLogin, "organizationPartyId", facility.getString("ownerPartyId")));
if (ServiceUtil.isError(outputMap)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(outputMap));
}
GenericValue partyAccountingPreference = (GenericValue) outputMap.get("partyAccountingPreference");
if (partyAccountingPreference == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunUnableToFindCosts", locale));
}
outputMap = dispatcher.runSync("getProductCost", UtilMisc.<String, Object>toMap("userLogin", userLogin, "productId",
productionRun.getProductProduced().getString("productId"), "currencyUomId",
(String) partyAccountingPreference.get("baseCurrencyUomId"), "costComponentTypePrefix", "EST_STD"));
if (ServiceUtil.isError(outputMap)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(outputMap));
}
unitCost = (BigDecimal) outputMap.get("productCost");
if (unitCost != null && unitCost.compareTo(BigDecimal.ZERO) == 0) {
BigDecimal totalCost = ZERO;
List<GenericValue> tasks = productionRun.getProductionRunRoutingTasks();
// generic_cost
List<GenericValue> actualGenCosts = EntityQuery.use(delegator)
.from("CostComponent")
.where("workEffortId", productionRunId,
"costUomId", partyAccountingPreference.get("baseCurrencyUomId"))
.queryList();
for (GenericValue actualGenCost : actualGenCosts) {
totalCost = totalCost.add((BigDecimal) actualGenCost.get("cost"));
}
for (GenericValue task : tasks) {
List<GenericValue> otherCosts = EntityQuery.use(delegator)
.from("CostComponent")
.where("workEffortId", task.get("workEffortId"),
"costUomId", partyAccountingPreference.get("baseCurrencyUomId"))
.queryList();
for (GenericValue otherCost : otherCosts) {
totalCost = totalCost.add((BigDecimal) otherCost.get("cost"));
}
}
if (totalCost != null) {
unitCost = totalCost.divide(quantity);
} else {
unitCost = BigDecimal.ZERO;
}
}
// Before creating InvntoryItem and InventoryItemDetails, check weather the record of ProductFacility exist in the system or not
GenericValue productFacility = EntityQuery.use(delegator).from("ProductFacility").where("productId",
productionRun.getProductProduced().getString("productId"),
"facilityId", facility.get("facilityId")).queryOne();
if (productFacility == null) {
Map<String, Object> createProductFacilityCtx = new HashMap<>();
createProductFacilityCtx.put("productId", productionRun.getProductProduced().getString("productId"));
createProductFacilityCtx.put("facilityId", facility.get("facilityId"));
createProductFacilityCtx.put("userLogin", userLogin);
Map<String, Object> serviceResult = dispatcher.runSync("createProductFacility", createProductFacilityCtx);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
}
} catch (GenericEntityException | GenericServiceException gse) {
Debug.logWarning(gse.getMessage(), MODULE);
return ServiceUtil.returnError(gse.getMessage());
}
if ("SERIALIZED_INV_ITEM".equals(inventoryItemTypeId)) {
try {
int numOfItems = quantity.intValue();
for (int i = 0; i < numOfItems; i++) {
Map<String, Object> serviceContext = UtilMisc.<String, Object>toMap("productId", productionRun.getProductProduced().getString(
"productId"),
"inventoryItemTypeId", "SERIALIZED_INV_ITEM",
"statusId", "INV_AVAILABLE");
serviceContext.put("facilityId", productionRun.getGenericValue().getString("facilityId"));
serviceContext.put("datetimeReceived", UtilDateTime.nowTimestamp());
serviceContext.put("datetimeManufactured", UtilDateTime.nowTimestamp());
serviceContext.put("comments", "Created by production run " + productionRunId);
if (unitCost.compareTo(ZERO) != 0) {
serviceContext.put("unitCost", unitCost);
}
serviceContext.put("lotId", lotId);
serviceContext.put("locationSeqId", locationSeqId);
serviceContext.put("uomId", uomId);
serviceContext.put("userLogin", userLogin);
Map<String, Object> serviceResult = dispatcher.runSync("createInventoryItem", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
String inventoryItemId = (String) serviceResult.get("inventoryItemId");
inventoryItemIds.add(inventoryItemId);
serviceContext.clear();
serviceContext.put("inventoryItemId", inventoryItemId);
serviceContext.put("workEffortId", productionRunId);
serviceContext.put("availableToPromiseDiff", BigDecimal.ONE);
serviceContext.put("quantityOnHandDiff", BigDecimal.ONE);
serviceContext.put("userLogin", userLogin);
serviceResult = dispatcher.runSync("createInventoryItemDetail", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
serviceContext.clear();
serviceContext.put("userLogin", userLogin);
serviceContext.put("workEffortId", productionRunId);
serviceContext.put("inventoryItemId", inventoryItemId);
serviceResult = dispatcher.runSync("createWorkEffortInventoryProduced", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
// Recompute reservations
serviceContext = new HashMap<>();
serviceContext.put("inventoryItemId", inventoryItemId);
serviceContext.put("userLogin", userLogin);
serviceResult = dispatcher.runSync("balanceInventoryItems", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
}
} catch (GenericServiceException exc) {
return ServiceUtil.returnError(exc.getMessage());
}
} else {
try {
Map<String, Object> serviceContext = UtilMisc.<String, Object>toMap("productId", productionRun.getProductProduced().getString(
"productId"),
"inventoryItemTypeId", "NON_SERIAL_INV_ITEM");
serviceContext.put("facilityId", productionRun.getGenericValue().getString("facilityId"));
serviceContext.put("datetimeReceived", UtilDateTime.nowTimestamp());
serviceContext.put("datetimeManufactured", UtilDateTime.nowTimestamp());
serviceContext.put("comments", "Created by production run " + productionRunId);
serviceContext.put("lotId", lotId);
serviceContext.put("locationSeqId", locationSeqId);
serviceContext.put("uomId", uomId);
if (unitCost.compareTo(ZERO) != 0) {
serviceContext.put("unitCost", unitCost);
}
serviceContext.put("userLogin", userLogin);
Map<String, Object> serviceResult = dispatcher.runSync("createInventoryItem", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
String inventoryItemId = (String) serviceResult.get("inventoryItemId");
inventoryItemIds.add(inventoryItemId);
serviceContext.clear();
serviceContext.put("inventoryItemId", inventoryItemId);
serviceContext.put("workEffortId", productionRunId);
serviceContext.put("availableToPromiseDiff", quantity);
serviceContext.put("quantityOnHandDiff", quantity);
serviceContext.put("userLogin", userLogin);
serviceResult = dispatcher.runSync("createInventoryItemDetail", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
serviceContext.clear();
serviceContext.put("userLogin", userLogin);
serviceContext.put("workEffortId", productionRunId);
serviceContext.put("inventoryItemId", inventoryItemId);
serviceResult = dispatcher.runSync("createWorkEffortInventoryProduced", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
// Recompute reservations
serviceContext = new HashMap<>();
serviceContext.put("inventoryItemId", inventoryItemId);
serviceContext.put("userLogin", userLogin);
if (orderItem != null) {
// the reservations of this order item are privileged reservations
serviceContext.put("priorityOrderId", orderItem.getString("orderId"));
serviceContext.put("priorityOrderItemSeqId", orderItem.getString("orderItemSeqId"));
}
serviceResult = dispatcher.runSync("balanceInventoryItems", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
} catch (GenericServiceException exc) {
return ServiceUtil.returnError(exc.getMessage());
}
}
// Now the production run's quantityProduced is updated
Map<String, Object> serviceContext = UtilMisc.<String, Object>toMap("workEffortId", productionRunId);
serviceContext.put("quantityProduced", quantityProduced.add(quantity));
serviceContext.put("actualCompletionDate", UtilDateTime.nowTimestamp());
serviceContext.put("userLogin", userLogin);
try {
Map<String, Object> serviceResult = dispatcher.runSync("updateWorkEffort", serviceContext);
if (ServiceUtil.isError(serviceResult)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
}
} catch (GenericServiceException e) {
Debug.logError(e, "Problem calling the updateWorkEffort service", MODULE);
return ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, "ManufacturingProductionRunStatusNotChanged", locale));
}
result.put("quantity", quantity);
return result;
}