Modified: ofbiz/ofbiz-framework/trunk/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderServices.java
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderServices.java?rev=1858270&r1=1858269&r2=1858270&view=diff ============================================================================== --- ofbiz/ofbiz-framework/trunk/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderServices.java (original) +++ ofbiz/ofbiz-framework/trunk/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderServices.java Sat Apr 27 13:05:30 2019 @@ -1205,6 +1205,13 @@ public class OrderServices { } GenericValue orderItem = itemValuesBySeqId.get(orderItemShipGroupAssoc.get("orderItemSeqId")); if ("SALES_ORDER".equals(orderTypeId) && orderItem != null) { + //If the 'autoReserve' flag is not set for the order item, don't reserve the inventory + String autoReserve = OrderReadHelper.getOrderItemAttribute(orderItem, "autoReserve"); + if (autoReserve == null || !"true".equals(autoReserve)) { + continue; + } + } + if ("SALES_ORDER".equals(orderTypeId) && orderItem != null) { //If the 'reserveAfterDate' is not yet come don't reserve the inventory Timestamp reserveAfterDate = orderItem.getTimestamp("reserveAfterDate"); if (UtilValidate.isNotEmpty(reserveAfterDate) && reserveAfterDate.after(UtilDateTime.nowTimestamp())) { @@ -4285,7 +4292,6 @@ public class OrderServices { toStore.addAll(cart.makeAllShipGroupInfos(dispatcher)); toStore.addAll(cart.makeAllOrderPaymentInfos(dispatcher)); toStore.addAll(cart.makeAllOrderItemAttributes(orderId, ShoppingCart.FILLED_ONLY)); - List<GenericValue> toRemove = new LinkedList<>(); if (deleteItems) { // flag to delete existing order items and adjustments @@ -6475,4 +6481,724 @@ public class OrderServices { } return ServiceUtil.returnSuccess(); } + + public static Map<String, Object> associateOrderWithAllocationPlans(DispatchContext dctx, Map<String, ? extends Object> context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue)context.get("userLogin"); + String orderId = (String) context.get("orderId"); + Map<String, String> productPlanMap = new HashMap<String, String>(); + Map<String, Object> serviceResult = new HashMap<String, Object>(); + try { + String userLoginId = null; + if (userLogin != null) { + userLoginId = userLogin.getString("userLoginId"); + } + //Get the list of associated products + OrderReadHelper orderReadHelper = new OrderReadHelper(delegator, orderId); + List<GenericValue> orderItems = orderReadHelper.getOrderItems(); + Map<String, Object> serviceCtx = new HashMap<String, Object>(); + for (GenericValue orderItem : orderItems) { + String orderItemSeqId = orderItem.getString("orderItemSeqId"); + String productId = orderItem.getString("productId"); + String planMethodEnumId = null; + GenericValue orderItemAttribute = EntityQuery.use(delegator).from("OrderItemAttribute").where("orderId", orderId, "orderItemSeqId", orderItemSeqId, "attrName", "autoReserve").queryOne(); + if (orderItemAttribute != null && "true".equals(orderItemAttribute.getString("attrValue"))) { + planMethodEnumId = "AUTO"; + } else { + planMethodEnumId = "MANUAL"; + } + //Look for any existing open allocation plan, if not available create a new one + String planId = null; + List<EntityCondition> headerConditions = new ArrayList<>(); + headerConditions.add(EntityCondition.makeCondition("productId", productId)); + headerConditions.add(EntityCondition.makeCondition("planTypeId", "SALES_ORD_ALLOCATION")); + headerConditions.add(EntityCondition.makeCondition("statusId", EntityOperator.IN, UtilMisc.toList("ALLOC_PLAN_CREATED", "ALLOC_PLAN_APPROVED"))); + GenericValue allocationPlanHeader = EntityQuery.use(delegator).from("AllocationPlanHeader").where(headerConditions).queryFirst(); + if (allocationPlanHeader == null) { + planId = delegator.getNextSeqId("AllocationPlanHeader"); + serviceCtx.put("planId", planId); + serviceCtx.put("productId", productId); + serviceCtx.put("planTypeId", "SALES_ORD_ALLOCATION"); + serviceCtx.put("planName", "Allocation Plan For Product #"+productId); + serviceCtx.put("statusId", "ALLOC_PLAN_CREATED"); + serviceCtx.put("createdByUserLogin", userLoginId); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("createAllocationPlanHeader", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + } else { + planId = allocationPlanHeader.getString("planId"); + serviceCtx.put("planId", planId); + serviceCtx.put("productId", productId); + //If an item added to already approved plan, it should be moved to created status + serviceCtx.put("statusId", "ALLOC_PLAN_CREATED"); + serviceCtx.put("lastModifiedByUserLogin", userLoginId); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("updateAllocationPlanHeader", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + } + serviceCtx.clear(); + List<EntityCondition> itemConditions = new ArrayList<>(); + itemConditions.add(EntityCondition.makeCondition("planId", planId)); + itemConditions.add(EntityCondition.makeCondition("orderId", orderId)); + itemConditions.add(EntityCondition.makeCondition("orderItemSeqId", EntityOperator.EQUALS, orderItemSeqId)); + itemConditions.add(EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, "ALLOC_PLAN_ITEM_CRTD")); + GenericValue allocationPlanItem = EntityQuery.use(delegator).from("AllocationPlanItem").where(itemConditions).queryFirst(); + String planItemSeqId = null; + if (allocationPlanItem == null) { + //Add the orderItem to the allocation plan + serviceCtx.put("planId", planId); + serviceCtx.put("planMethodEnumId", planMethodEnumId); + if ("AUTO".equals(planMethodEnumId)) { + serviceCtx.put("allocatedQuantity", orderItem.getBigDecimal("quantity")); + serviceCtx.put("statusId", "ALLOC_PLAN_ITEM_APRV"); + } else { + serviceCtx.put("statusId", "ALLOC_PLAN_ITEM_CRTD"); + } + serviceCtx.put("orderId", orderId); + serviceCtx.put("orderItemSeqId", orderItemSeqId); + serviceCtx.put("productId", productId); + serviceCtx.put("createdByUserLogin", userLoginId); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("createAllocationPlanItem", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + planItemSeqId = (String) serviceResult.get("planItemSeqId"); + } else { + planItemSeqId = allocationPlanItem.getString("planItemSeqId"); + serviceCtx.put("planId", planId); + serviceCtx.put("planItemSeqId", planItemSeqId); + serviceCtx.put("productId", productId); + serviceCtx.put("planMethodEnumId", planMethodEnumId); + if ("AUTO".equals(planMethodEnumId)) { + serviceCtx.put("allocatedQuantity", orderItem.getBigDecimal("quantity")); + serviceCtx.put("statusId", "ALLOC_PLAN_ITEM_APRV"); + } else { + serviceCtx.put("statusId", "ALLOC_PLAN_ITEM_CRTD"); + } + serviceCtx.put("lastModifiedByUserLogin", userLoginId); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("updateAllocationPlanItem", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + } + serviceCtx.clear(); + + //Enter the values in productPlanMap + productPlanMap.put(productId, planId); + } + } catch (GenericEntityException e) { + return ServiceUtil.returnError(e.getMessage()); + } catch (GenericServiceException e) { + return ServiceUtil.returnError(e.getMessage()); + } + serviceResult.clear(); + serviceResult.put("productPlanMap", productPlanMap); + return serviceResult; + } + + public static Map<String, Object> approveAllocationPlanItems(DispatchContext dctx, Map<String, ? extends Object> context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue)context.get("userLogin"); + String planId = (String) context.get("planId"); + Map<String, Object> serviceCtx = new HashMap<String, Object>(); + Map<String, Object> serviceResult = new HashMap<String, Object>(); + try { + String userLoginId = null; + if (userLogin != null) { + userLoginId = userLogin.getString("userLoginId"); + } + //Get the list of plan items in created status + List<EntityCondition> itemConditions = new ArrayList<>(); + itemConditions.add(EntityCondition.makeCondition("planId", planId)); + itemConditions.add(EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, "ALLOC_PLAN_ITEM_CRTD")); + List<GenericValue> allocationPlanItems = EntityQuery.use(delegator).from("AllocationPlanItem").where(itemConditions).queryList(); + + String facilityId = null; + String productId = null; + for (GenericValue allocationPlanItem : allocationPlanItems) { + productId = allocationPlanItem.getString("productId"); + serviceCtx.put("planId", planId); + serviceCtx.put("planItemSeqId", allocationPlanItem.getString("planItemSeqId")); + serviceCtx.put("productId", allocationPlanItem.getString("productId")); + serviceCtx.put("statusId", "ALLOC_PLAN_ITEM_APRV"); + serviceCtx.put("lastModifiedByUserLogin", userLoginId); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("updateAllocationPlanItem", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + serviceCtx.clear(); + GenericValue orderHeader = EntityQuery.use(delegator).from("OrderHeader").where("orderId", allocationPlanItem.getString("orderId")).queryOne(); + if (orderHeader != null) { + //For now considering single facility case only + facilityId = orderHeader.getString("originFacilityId"); + } + } + + //Get the list of plan items in approved status + itemConditions.clear(); + itemConditions.add(EntityCondition.makeCondition("planId", planId)); + itemConditions.add(EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, "ALLOC_PLAN_ITEM_APRV")); + allocationPlanItems = EntityQuery.use(delegator).from("AllocationPlanItem").where(itemConditions).queryList(); + + if (allocationPlanItems.size() > 0) { + //Rereserve the inventory + serviceCtx.put("productId", productId); + serviceCtx.put("facilityId", facilityId); + serviceCtx.put("allocationPlanAndItemList", allocationPlanItems); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("reassignInventoryReservationsByAllocationPlan", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + } + + } catch (GenericEntityException e) { + return ServiceUtil.returnError(e.getMessage()); + } catch (GenericServiceException e) { + return ServiceUtil.returnError(e.getMessage()); + } + return ServiceUtil.returnSuccess(); + } + + public static Map<String, Object> cancelAllocationPlanItems(DispatchContext dctx, Map<String, ? extends Object> context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue)context.get("userLogin"); + String planId = (String) context.get("planId"); + Map<String, Object> serviceCtx = new HashMap<String, Object>(); + Map<String, Object> serviceResult = new HashMap<String, Object>(); + try { + String userLoginId = null; + if (userLogin != null) { + userLoginId = userLogin.getString("userLoginId"); + } + //Get the list of plan items + List<EntityCondition> itemConditions = new ArrayList<>(); + itemConditions.add(EntityCondition.makeCondition("planId", planId)); + itemConditions.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "ALLOC_PLAN_ITEM_CNCL")); + List<GenericValue> allocationPlanItems = EntityQuery.use(delegator).from("AllocationPlanItem").where(itemConditions).queryList(); + + for (GenericValue allocationPlanItem : allocationPlanItems) { + serviceCtx.put("planId", planId); + serviceCtx.put("planItemSeqId", allocationPlanItem.getString("planItemSeqId")); + serviceCtx.put("productId", allocationPlanItem.getString("productId")); + serviceCtx.put("statusId", "ALLOC_PLAN_ITEM_CNCL"); + serviceCtx.put("lastModifiedByUserLogin", userLoginId); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("updateAllocationPlanItem", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + serviceCtx.clear(); + } + } catch (GenericEntityException e) { + return ServiceUtil.returnError(e.getMessage()); + } catch (GenericServiceException e) { + return ServiceUtil.returnError(e.getMessage()); + } + return ServiceUtil.returnSuccess(); + } + + public static Map<String, Object> changeAllocationPlanStatus(DispatchContext dctx, Map<String, ? extends Object> context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue)context.get("userLogin"); + Locale locale = (Locale) context.get("locale"); + String planId = (String) context.get("planId"); + String statusId = (String) context.get("statusId"); + String oldStatusId = null; + Map<String, Object> serviceResult = new HashMap<String, Object>(); + try { + List<GenericValue> allocationPlanHeaders = EntityQuery.use(delegator).from("AllocationPlanHeader").where("planId", planId).queryList(); + if (allocationPlanHeaders == null || UtilValidate.isEmpty(allocationPlanHeaders)) { + return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, + "OrderErrorAllocationPlanIsNotAvailable", locale) + ": [" + planId + "]"); + } + for (GenericValue allocationPlanHeader : allocationPlanHeaders) { + oldStatusId = allocationPlanHeader.getString("statusId"); + try { + GenericValue statusChange = EntityQuery.use(delegator).from("StatusValidChange").where("statusId", oldStatusId, "statusIdTo", statusId).queryOne(); + if (statusChange == null) { + return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, + "OrderErrorCouldNotChangeAllocationPlanStatusStatusIsNotAValidChange", locale) + ": [" + oldStatusId + "] -> [" + statusId + "]"); + } + } catch (GenericEntityException e) { + return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, + "OrderErrorCouldNotChangeAllocationPlanStatus",locale) + e.getMessage() + ")."); + } + String userLoginId = null; + if (userLogin != null) { + userLoginId = userLogin.getString("userLoginId"); + } + Map<String, Object> serviceCtx = new HashMap<String, Object>(); + serviceCtx.put("planId", planId); + serviceCtx.put("productId", allocationPlanHeader.getString("productId")); + serviceCtx.put("statusId", statusId); + serviceCtx.put("lastModifiedByUserLogin", userLoginId); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("updateAllocationPlanHeader", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + } + } catch (GenericEntityException e) { + return ServiceUtil.returnError(e.getMessage()); + } catch (GenericServiceException e) { + return ServiceUtil.returnError(e.getMessage()); + } + serviceResult.clear(); + serviceResult.put("planId", planId); + serviceResult.put("oldStatusId", oldStatusId); + return serviceResult; + } + + public static Map<String, Object> changeAllocationPlanItemStatus(DispatchContext dctx, Map<String, ? extends Object> context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue)context.get("userLogin"); + Locale locale = (Locale) context.get("locale"); + String planId = (String) context.get("planId"); + String planItemSeqId = (String) context.get("planItemSeqId"); + String statusId = (String) context.get("statusId"); + String oldStatusId = null; + Map<String, Object> serviceResult = new HashMap<String, Object>(); + try { + GenericValue allocationPlanItem = EntityQuery.use(delegator).from("AllocationPlanItem").where("planId", planId, "planItemSeqId", planItemSeqId).queryOne(); + if (allocationPlanItem == null) { + return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, + "OrderErrorAllocationPlanIsNotAvailable", locale) + ": [" + planId + ":"+ planItemSeqId + "]"); + } + oldStatusId = allocationPlanItem.getString("statusId"); + try { + GenericValue statusChange = EntityQuery.use(delegator).from("StatusValidChange").where("statusId", oldStatusId, "statusIdTo", statusId).queryOne(); + if (statusChange == null) { + return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, + "OrderErrorCouldNotChangeAllocationPlanItemStatusStatusIsNotAValidChange", locale) + ": [" + oldStatusId + "] -> [" + statusId + "]"); + } + } catch (GenericEntityException e) { + return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, + "OrderErrorCouldNotChangeAllocationPlanItemStatus",locale) + e.getMessage() + ")."); + } + String userLoginId = null; + if (userLogin != null) { + userLoginId = userLogin.getString("userLoginId"); + } + Map<String, Object> serviceCtx = new HashMap<String, Object>(); + serviceCtx.put("planId", planId); + serviceCtx.put("planItemSeqId", planItemSeqId); + serviceCtx.put("productId", allocationPlanItem.getString("productId")); + serviceCtx.put("statusId", statusId); + serviceCtx.put("lastModifiedByUserLogin", userLoginId); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("updateAllocationPlanItem", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + } catch (GenericEntityException e) { + return ServiceUtil.returnError(e.getMessage()); + } catch (GenericServiceException e) { + return ServiceUtil.returnError(e.getMessage()); + } + serviceResult.clear(); + serviceResult.put("oldStatusId", oldStatusId); + return serviceResult; + } + + public static Map<String, Object> completeAllocationPlanItemByOrderItem(DispatchContext dctx, Map<String, ? extends Object> context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue)context.get("userLogin"); + Locale locale = (Locale) context.get("locale"); + String orderId = (String) context.get("orderId"); + String orderItemSeqId = (String) context.get("orderItemSeqId"); + try { + List<EntityExpr> exprs = new ArrayList<>(); + exprs.add(EntityCondition.makeCondition("orderId", orderId)); + if (orderItemSeqId != null) { + exprs.add(EntityCondition.makeCondition("orderItemSeqId", orderItemSeqId)); + } else { + exprs.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_IN, UtilMisc.toList("ALLOC_PLAN_ITEM_CMPL", "ALLOC_PLAN_ITEM_CNCL"))); + } + + List<GenericValue> allocationPlanItems = EntityQuery.use(delegator).from("AllocationPlanItem").where(exprs).queryList(); + if (allocationPlanItems == null || UtilValidate.isEmpty(allocationPlanItems)) { + return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, + "OrderErrorAllocationPlanIsNotAvailable", locale) + ": [" + orderId + ":"+ orderItemSeqId + "]"); + } + List<String> planIds = new ArrayList<String>(); + Map<String, Object> serviceCtx = new HashMap<String, Object>(); + Map<String, Object> serviceResult = new HashMap<String, Object>(); + for (GenericValue allocationPlanItem : allocationPlanItems) { + String planId = allocationPlanItem.getString("planId"); + serviceCtx.put("planId", planId); + serviceCtx.put("planItemSeqId", allocationPlanItem.getString("planItemSeqId")); + serviceCtx.put("statusId", "ALLOC_PLAN_ITEM_CMPL"); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("changeAllocationPlanItemStatus", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + if (!planIds.contains(planId)) { + planIds.add(planId); + } + serviceCtx.clear(); + serviceResult.clear(); + } + //If all the allocation plan items are completed then complete the allocation plan header(s) as well + for (String planId : planIds) { + allocationPlanItems = EntityQuery.use(delegator).from("AllocationPlanItem").where("planId", planId).queryList(); + Boolean completeAllocationPlan = true; + for (GenericValue allocationPlanItem : allocationPlanItems) { + if (!"ALLOC_PLAN_ITEM_CMPL".equals(allocationPlanItem.getString("statusId"))) { + completeAllocationPlan = false; + break; + } + } + if (completeAllocationPlan) { + serviceCtx.put("planId", planId); + serviceCtx.put("statusId", "ALLOC_PLAN_COMPLETED"); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("changeAllocationPlanStatus", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + serviceCtx.clear(); + serviceResult.clear(); + } + } + } catch (GenericEntityException e) { + return ServiceUtil.returnError(e.getMessage()); + } catch (GenericServiceException e) { + return ServiceUtil.returnError(e.getMessage()); + } + return ServiceUtil.returnSuccess(); + } + + public static Map<String, Object> cancelAllocationPlanItemByOrderItem(DispatchContext dctx, Map<String, ? extends Object> context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue)context.get("userLogin"); + Locale locale = (Locale) context.get("locale"); + String orderId = (String) context.get("orderId"); + String orderItemSeqId = (String) context.get("orderItemSeqId"); + try { + List<EntityExpr> exprs = new ArrayList<>(); + exprs.add(EntityCondition.makeCondition("orderId", orderId)); + if (orderItemSeqId != null) { + exprs.add(EntityCondition.makeCondition("orderItemSeqId", orderItemSeqId)); + } else { + exprs.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_IN, UtilMisc.toList("ALLOC_PLAN_ITEM_CMPL", "ALLOC_PLAN_ITEM_CNCL"))); + } + + List<GenericValue> allocationPlanItems = EntityQuery.use(delegator).from("AllocationPlanItem").where(exprs).queryList(); + if (allocationPlanItems == null || UtilValidate.isEmpty(allocationPlanItems)) { + return ServiceUtil.returnError(UtilProperties.getMessage(resource_error, + "OrderErrorAllocationPlanIsNotAvailable", locale) + ": [" + orderId + ":"+ orderItemSeqId + "]"); + } + List<String> planIds = new ArrayList<String>(); + Map<String, Object> serviceCtx = new HashMap<String, Object>(); + Map<String, Object> serviceResult = new HashMap<String, Object>(); + for (GenericValue allocationPlanItem : allocationPlanItems) { + String planId = allocationPlanItem.getString("planId"); + serviceCtx.put("planId", planId); + serviceCtx.put("planItemSeqId", allocationPlanItem.getString("planItemSeqId")); + serviceCtx.put("statusId", "ALLOC_PLAN_ITEM_CNCL"); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("changeAllocationPlanItemStatus", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + if (!planIds.contains(planId)) { + planIds.add(planId); + } + serviceCtx.clear(); + serviceResult.clear(); + } + //If all the allocation plan items are cancelled then cancel the allocation plan header(s) as well. + for (String planId : planIds) { + allocationPlanItems = EntityQuery.use(delegator).from("AllocationPlanItem").where("planId", planId).queryList(); + Boolean cancelAllocationPlan = true; + for (GenericValue allocationPlanItem : allocationPlanItems) { + if (!"ALLOC_PLAN_ITEM_CNCL".equals(allocationPlanItem.getString("statusId"))) { + cancelAllocationPlan = false; + break; + } + } + if (cancelAllocationPlan) { + serviceCtx.put("planId", planId); + serviceCtx.put("statusId", "ALLOC_PLAN_CANCELLED"); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("changeAllocationPlanStatus", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + serviceCtx.clear(); + serviceResult.clear(); + } + } + } catch (GenericEntityException e) { + return ServiceUtil.returnError(e.getMessage()); + } catch (GenericServiceException e) { + return ServiceUtil.returnError(e.getMessage()); + } + return ServiceUtil.returnSuccess(); + } + public static Map<String, Object> updateAllocatedQuantityOnOrderItemChange(DispatchContext dctx, Map<String, ? extends Object> context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue)context.get("userLogin"); + Locale locale = (Locale) context.get("locale"); + String orderId = (String) context.get("orderId"); + try { + OrderReadHelper orderReadHelper = new OrderReadHelper(delegator, orderId); + List<GenericValue> orderItems = orderReadHelper.getOrderItems(); + for (GenericValue orderItem : orderItems) { + String orderItemSeqId = orderItem.getString("orderItemSeqId"); + List<EntityExpr> exprs = new ArrayList<>(); + exprs.add(EntityCondition.makeCondition("orderId", orderId)); + exprs.add(EntityCondition.makeCondition("orderItemSeqId", orderItemSeqId)); + exprs.add(EntityCondition.makeCondition("changeTypeEnumId", "ODR_ITM_UPDATE")); + exprs.add(EntityCondition.makeCondition("quantity", EntityOperator.NOT_EQUAL, null)); + GenericValue orderItemChange = EntityQuery.use(delegator).from("OrderItemChange").where(exprs).orderBy("-changeDatetime").queryFirst(); + if (orderItemChange != null) { + BigDecimal quantityChanged = orderItemChange.getBigDecimal("quantity"); + if (quantityChanged.compareTo(BigDecimal.ZERO) < 0) { + Debug.log("=========quantity decreased==========="+quantityChanged); + GenericValue allocationPlanItem = EntityQuery.use(delegator).from("AllocationPlanItem").where("orderId", orderId, "orderItemSeqId", orderItemSeqId, "statusId", "ALLOC_PLAN_ITEM_CRTD", "productId", orderItem.getString("productId")).queryFirst(); + if (allocationPlanItem != null) { + BigDecimal revisedQuantity = orderItem.getBigDecimal("quantity"); + BigDecimal allocatedQuantity = allocationPlanItem.getBigDecimal("allocatedQuantity"); + if (allocatedQuantity != null && allocatedQuantity.compareTo(revisedQuantity) > 0) { + //Allocated Quantity is more than the revisedQuantity quantity, reduce it and release the excess reservations + Map<String, Object> serviceCtx = new HashMap<String, Object>(); + serviceCtx.put("planId", allocationPlanItem.getString("planId")); + serviceCtx.put("planItemSeqId", allocationPlanItem.getString("planItemSeqId")); + serviceCtx.put("productId", allocationPlanItem.getString("productId")); + serviceCtx.put("allocatedQuantity", revisedQuantity); + serviceCtx.put("lastModifiedByUserLogin", userLogin.getString("userLoginId")); + serviceCtx.put("userLogin", userLogin); + Map<String, Object> serviceResult = dispatcher.runSync("updateAllocationPlanItem", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + } + } + } else if (quantityChanged.compareTo(BigDecimal.ZERO) > 0) { + Debug.log("=========quantity increased==========="+quantityChanged); + } + } + } + } catch (GenericEntityException e) { + return ServiceUtil.returnError(e.getMessage()); + } catch (GenericServiceException e) { + return ServiceUtil.returnError(e.getMessage()); + } + return ServiceUtil.returnSuccess(); + } + + public static Map<String, Object> createAllocationPlanAndItems(DispatchContext dctx, Map<String, ? extends Object> context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue)context.get("userLogin"); + Locale locale = (Locale) context.get("locale"); + String productId = (String) context.get("productId"); + String planName = (String) context.get("planName"); + Integer itemListSize = (Integer) context.get("itemListSize"); + Map<String, String> itemOrderIdMap = UtilGenerics.checkMap(context.get("itemOrderIdMap")); + Map<String, String> itemOrderItemSeqIdMap = UtilGenerics.checkMap(context.get("itemOrderItemSeqIdMap")); + Map<String, String> itemAllocatedQuantityMap = UtilGenerics.checkMap(context.get("itemAllocatedQuantityMap")); + Map<String, Object> serviceResult = new HashMap<String, Object>(); + Map<String, Object> serviceCtx = new HashMap<String, Object>(); + String planId = null; + + try { + if (itemListSize > 0) { + String userLoginId = userLogin.getString("userLoginId"); + //Create Allocation Plan Header + serviceCtx = new HashMap<String, Object>(); + planId = delegator.getNextSeqId("AllocationPlanHeader"); + serviceCtx.put("planId", planId); + serviceCtx.put("productId", productId); + serviceCtx.put("planTypeId", "SALES_ORD_ALLOCATION"); + serviceCtx.put("statusId", "ALLOC_PLAN_CREATED"); + serviceCtx.put("createdByUserLogin", userLoginId); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("createAllocationPlanHeader", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + serviceCtx.clear(); + + //Create Allocation Plan Items + for (int i=0; i<itemListSize; i++) { + String orderId = itemOrderIdMap.get(String.valueOf(i)); + String orderItemSeqId = itemOrderItemSeqIdMap.get(String.valueOf(i)); + String allocatedQuantityStr = itemAllocatedQuantityMap.get(String.valueOf(i)); + BigDecimal allocatedQuantity = null; + if (allocatedQuantityStr != null) { + try { + allocatedQuantity = (BigDecimal) ObjectType.simpleTypeOrObjectConvert(allocatedQuantityStr, "BigDecimal", null, locale); + } catch (GeneralException e) { + return ServiceUtil.returnError(e.getMessage()); + } + } + serviceCtx.put("planId", planId); + serviceCtx.put("statusId", "ALLOC_PLAN_ITEM_CRTD"); + serviceCtx.put("planMethodEnumId", "MANUAL"); + serviceCtx.put("orderId", orderId); + serviceCtx.put("orderItemSeqId", orderItemSeqId); + serviceCtx.put("productId", productId); + serviceCtx.put("allocatedQuantity", allocatedQuantity); + serviceCtx.put("prioritySeqId", String.valueOf(i+1)); + serviceCtx.put("createdByUserLogin", userLoginId); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("createAllocationPlanItem", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + serviceCtx.clear(); + } + } else { + return ServiceUtil.returnError("Item list is empty."); + } + } catch (GenericServiceException e) { + return ServiceUtil.returnError(e.getMessage()); + } + serviceResult.clear(); + serviceResult.put("planId", planId); + return serviceResult; + } + + public static Map<String, Object> isInventoryAllocationRequired(DispatchContext dctx, Map<String, ? extends Object> context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + Boolean allocateInventory = false; + Map<String, Object> serviceContext = UtilGenerics.checkMap(context.get("serviceContext")); + String orderId = (String) serviceContext.get("orderId"); + + OrderReadHelper orderReadHelper = new OrderReadHelper(delegator, orderId); + GenericValue productStore = orderReadHelper.getProductStore(); + if (productStore != null && "Y".equals(productStore.getString("allocateInventory"))) { + allocateInventory = true; + } + Map<String, Object> serviceResult = new HashMap<String, Object>(); + serviceResult.put("conditionReply", allocateInventory); + return serviceResult; + } + + public static Map<String, Object> updateAllocationPlanItems(DispatchContext dctx, Map<String, ? extends Object> context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue) context.get("userLogin"); + Locale locale = (Locale) context.get("locale"); + String planId = (String) context.get("planId"); + Map<String, String> orderIdMap = UtilGenerics.checkMap(context.get("orderIdMap")); + Map<String, String> productIdMap = UtilGenerics.checkMap(context.get("productIdMap")); + Map<String, String> allocatedQuantityMap = UtilGenerics.checkMap(context.get("allocatedQuantityMap")); + Map<String, String> prioritySeqIdMap = UtilGenerics.checkMap(context.get("prioritySeqIdMap")); + Map<String, String> rowSubmitMap = UtilGenerics.checkMap(context.get("rowSubmitMap")); + Map<String, Object> serviceCtx = new HashMap<String, Object>(); + Map<String, Object> serviceResult = new HashMap<String, Object>(); + Boolean changeHeaderStatus = false; + String productId = null; + String facilityId = null; + List<String> reReservePlanItemSeqIdList = new ArrayList<String>(); + + try { + for (String planItemSeqId : productIdMap.keySet()) { + String rowSubmit = rowSubmitMap.get(planItemSeqId); + productId = productIdMap.get(planItemSeqId); + String prioritySeqId = prioritySeqIdMap.get(planItemSeqId); + String allocatedQuantityStr = allocatedQuantityMap.get(planItemSeqId); + BigDecimal allocatedQuantity = null; + if (allocatedQuantityStr != null) { + try { + allocatedQuantity = (BigDecimal) ObjectType.simpleTypeOrObjectConvert(allocatedQuantityStr, "BigDecimal", null, locale); + } catch (GeneralException e) { + return ServiceUtil.returnError(e.getMessage()); + } + } + + GenericValue allocationPlanItem = EntityQuery.use(delegator).from("AllocationPlanItem").where("planId", planId, "planItemSeqId", planItemSeqId, "productId", productId).queryOne(); + if (allocationPlanItem != null) { + BigDecimal oldAllocatedQuantity = allocationPlanItem.getBigDecimal("allocatedQuantity"); + if (oldAllocatedQuantity != null && oldAllocatedQuantity.compareTo(allocatedQuantity) > 0) { + reReservePlanItemSeqIdList.add(planItemSeqId); + } + + serviceCtx.put("planId", planId); + serviceCtx.put("prioritySeqId", prioritySeqId); + serviceCtx.put("planItemSeqId", planItemSeqId); + serviceCtx.put("productId", productId); + serviceCtx.put("lastModifiedByUserLogin", userLogin.getString("userLoginId")); + serviceCtx.put("userLogin", userLogin); + if (rowSubmit != null && "Y".equals(rowSubmit)) { + serviceCtx.put("allocatedQuantity", allocatedQuantity); + serviceCtx.put("planMethodEnumId", "MANUAL"); + serviceCtx.put("statusId", "ALLOC_PLAN_ITEM_CRTD"); + changeHeaderStatus = true; + } + serviceResult = dispatcher.runSync("updateAllocationPlanItem", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + serviceCtx.clear(); + } + + //Get the facility id from order id + String orderId = orderIdMap.get(planItemSeqId); + GenericValue orderHeader = EntityQuery.use(delegator).from("OrderHeader").where("orderId", orderId).queryOne(); + if (orderHeader != null && facilityId == null) { + facilityId = orderHeader.getString("originFacilityId"); + } + } + + //If any item got updated, change the header status to created + if (changeHeaderStatus) { + serviceCtx.put("planId", planId); + serviceCtx.put("productId", productId); + serviceCtx.put("statusId", "ALLOC_PLAN_CREATED"); + serviceCtx.put("lastModifiedByUserLogin", userLogin.getString("userLoginId")); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("updateAllocationPlanHeader", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + serviceCtx.clear(); + } + + //Get the list of plan items in the created status + List<EntityCondition> itemConditions = new ArrayList<>(); + itemConditions.add(EntityCondition.makeCondition("planId", planId)); + itemConditions.add(EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, "ALLOC_PLAN_ITEM_CRTD")); + itemConditions.add(EntityCondition.makeCondition("planItemSeqId", EntityOperator.IN, reReservePlanItemSeqIdList)); + List<GenericValue> allocationPlanItems = EntityQuery.use(delegator).from("AllocationPlanItem").where(itemConditions).queryList(); + + if (allocationPlanItems.size() > 0) { + //Rereserve the inventory + serviceCtx.put("productId", productId); + serviceCtx.put("facilityId", facilityId); + serviceCtx.put("allocationPlanAndItemList", allocationPlanItems); + serviceCtx.put("userLogin", userLogin); + serviceResult = dispatcher.runSync("reassignInventoryReservationsByAllocationPlan", serviceCtx); + if (ServiceUtil.isError(serviceResult)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult)); + } + } + } catch (GenericServiceException gse) { + return ServiceUtil.returnError(gse.getMessage()); + } catch (GenericEntityException gee) { + return ServiceUtil.returnError(gee.getMessage()); + } + return ServiceUtil.returnSuccess(); + } } Modified: ofbiz/ofbiz-framework/trunk/applications/order/template/entry/cart/ShowCart.ftl URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/order/template/entry/cart/ShowCart.ftl?rev=1858270&r1=1858269&r2=1858270&view=diff ============================================================================== --- ofbiz/ofbiz-framework/trunk/applications/order/template/entry/cart/ShowCart.ftl (original) +++ ofbiz/ofbiz-framework/trunk/applications/order/template/entry/cart/ShowCart.ftl Sat Apr 27 13:05:30 2019 @@ -172,6 +172,21 @@ under the License. </div> </td> </tr> + <#if "SALES_ORDER" == shoppingCart.getOrderType()> + <#assign productStore = Static["org.apache.ofbiz.product.store.ProductStoreWorker"].getProductStore(shoppingCart.getProductStoreId(), delegator) /> + <#if productStore?has_content && (productStore.allocateInventory)?has_content && (productStore.allocateInventory).equals('Y')> + <tr> + <td align="right"><div>${uiLabelMap.OrderAutoReserve}</div></td> + <td> + <div> + <label> + <input type="checkbox" name="order_item_attr_autoReserve" value="true" <#if autoReserve??>checked="checked"</#if> /> + </label> + </div> + </td> + </tr> + </#if> + </#if> <tr> <td></td> <td><input type="submit" class="smallSubmit" value="${uiLabelMap.OrderAddToOrder}"/></td> Added: ofbiz/ofbiz-framework/trunk/applications/order/template/order/CreateAllocationPlan.ftl URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/order/template/order/CreateAllocationPlan.ftl?rev=1858270&view=auto ============================================================================== --- ofbiz/ofbiz-framework/trunk/applications/order/template/order/CreateAllocationPlan.ftl (added) +++ ofbiz/ofbiz-framework/trunk/applications/order/template/order/CreateAllocationPlan.ftl Sat Apr 27 13:05:30 2019 @@ -0,0 +1,158 @@ +<#-- +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. +--> +<#if !requestParameters.productId?has_content && requestParameters.editMode! == "N"> + <div class="alert alert-light" role="alert"> + Please enter product id. + </div> +</#if> +<#if allocationPlanInfo.isPlanAlreadyExists> + <div class="alert alert-light" role="alert"> + Allocation Plan Already Exists. + </div> +</#if> +<#if requestParameters.productId?has_content && (allocationPlanInfo.itemList.size() == 0)> + <div class="alert alert-light" role="alert"> + ${uiLabelMap.OrderNoOrderFound} + </div> +</#if> + +<#if requestParameters.editMode?exists> + <#assign editMode=parameters.editMode> +<#else> + <#assign editMode="N"> +</#if> +<form class="basic-form" method="post" name="CreateAllocationPlan" id="CreateAllocationPlan" + action="<@ofbizUrl><#if !requestParameters.productId?has_content || (allocationPlanInfo.itemList.size() == 0)>CreateAllocationPlan?editMode=N<#else>createAllocationPlanAndItems</#if></@ofbizUrl>"> + <div class="screenlet"> + <div class="screenlet-title-bar"> + <ul> + <li class="h3"> + <#if requestParameters.productId?has_content> + ${uiLabelMap.OrderPlanHeader} + <#else> + ${uiLabelMap.PageTitleCreateAllocationPlan} + </#if> + </li> + <#if (allocationPlanInfo.itemList.size() > 0)> + <li><input type="submit" id="saveItemsButton" class="buttontext" value="${uiLabelMap.OrderCreatePlan}"></li> + </#if> + </ul> + <br class="clear"/> + </div> + <div class="screenlet-body"> + <table class="basic-table" cellspacing="0"> + <tr> + <td align="center" width="100%"> + <table class="basic-table" cellspacing="0"> + <tr> + <td class="label">${uiLabelMap.ProductProductId}</td> + <td> + <@htmlTemplate.lookupField value="${requestParameters.productId!}" formName="CreateAllocationPlan" name="productId" id="productId" fieldFormName="LookupProduct"/> + </td> + </tr> + <tr> + <td class="label">${uiLabelMap.OrderPlanName}</td> + <td ><input type="text" name="planName" id="planName" value="${requestParameters.planName!}"/></td> + </tr> + <tr> + <td class="label"/> + <td> + <#if !requestParameters.productId?has_content || allocationPlanInfo.itemList.size() == 0 || allocationPlanInfo.isPlanAlreadyExists> + <input type="submit" value="${uiLabelMap.CommonNext}"/> + </#if> + </td> + </tr> + </table> + </td> + </tr> + </table> + </div> + </div> + <#if requestParameters.productId?has_content && allocationPlanInfo.itemList.size() > 0 && !allocationPlanInfo.isPlanAlreadyExists> + <div class="screenlet"> + <div class="screenlet-title-bar"> + <ul> + <li class="h3">${uiLabelMap.OrderPlanItems}</li> + <#if (allocationPlanInfo.itemList.size() > 0)> + <#if editMode=="Y"> + <li><a href="/ordermgr/control/CreateAllocationPlan?productId=${requestParameters.productId!}&planName=${requestParameters.planName!}&editMode=N" class="buttontext">${uiLabelMap.OrderCancelEdit}</a></li> + <#else> + <li><a href="/ordermgr/control/CreateAllocationPlan?productId=${requestParameters.productId!}&planName=${requestParameters.planName!}&editMode=Y" class="buttontext">${uiLabelMap.CommonEdit}</a></li> + </#if> + </#if> + </ul> + <br class="clear"/> + </div> + <div class="screenlet-body"> + <table class="basic-table" cellspacing="0"> + <tr class="header-row"> + <td width="10%">${uiLabelMap.OrderSalesChannel}</td> + <td width="10%">${uiLabelMap.OrderCustomer}</td> + <td width="10%">${uiLabelMap.FormFieldTitle_orderId}</td> + <td width="10%">${uiLabelMap.FormFieldTitle_orderItemSeqId}</td> + <td width="10%">${uiLabelMap.FormFieldTitle_estimatedShipDate}</td> + <td align="right" width="10%">${uiLabelMap.OrderOrdered}</td> + <td align="right" width="10%">${uiLabelMap.ProductReserved}</td> + <td align="right" width="10%">${uiLabelMap.OrderExtValue}</td> + <td align="right" width="10%">${uiLabelMap.OrderAllocated}</td> + <#if editMode=="Y"> + <td align="right" width="5%">${uiLabelMap.FormFieldTitle_actionEnumId}</td> + </#if> + </tr> + <input type="hidden" name="itemListSize" value="${allocationPlanInfo.itemList.size()}"/> + <#list allocationPlanInfo.itemList as item> + <tr> + <input type="hidden" name="ioim_${item_index}" value="${item.orderId}"/> + <input type="hidden" name="ioisim_${item_index}" value="${item.orderItemSeqId}"/> + <input type="hidden" name="ipsim_${item_index}" value="${item_index+1}"/> + <td>${item.salesChannel!}</td> + <td><a href="/partymgr/control/viewprofile?partyId=${item.partyId!}" title="${item.partyId!}">${item.partyName!}</a></td> + <td><a href="/ordermgr/control/orderview?orderId=${item.orderId!}" title="${item.orderId!}">${item.orderId!}</a></td> + <td>${item.orderItemSeqId!}</td> + <td>${item.estimatedShipDate!}</td> + <td align="right">${item.orderedQuantity!}</td> + <td align="right">${item.reservedQuantity!}</td> + <td align="right">${item.orderedValue!}</td> + <#if editMode=="Y"> + <td><input type="text" name="iaqm_${item_index}" value="${item.allocatedQuantity!}"></td> + <td align="right"> + <a href="#" class="up"><img src="/images/arrow-single-up-green.png"/></a> + <a href="#" class="down"><img src="/images/arrow-single-down-green.png"/></a> + </td> + <#else> + <td align="right">${item.allocatedQuantity!}</td> + <input type="hidden" name="iaqm_${item_index}" value="${item.allocatedQuantity!}"/> + </#if> + </tr> + </#list> + <tr> + <td colspan="5"><b>${uiLabelMap.CommonTotal}</b></td> + <td align="right"><b>${allocationPlanInfo.orderedQuantityTotal!}</b></td> + <td align="right"><b>${allocationPlanInfo.reservedQuantityTotal!}</b></td> + <td align="right"><b>${allocationPlanInfo.orderedValueTotal!}</b></td> + <td align="right"></td> + <#if editMode=="Y"> + <td></td> + </#if> + </tr> + </table> + </div> + </div> + </#if> +</form> \ No newline at end of file Propchange: ofbiz/ofbiz-framework/trunk/applications/order/template/order/CreateAllocationPlan.ftl ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/ofbiz-framework/trunk/applications/order/template/order/CreateAllocationPlan.ftl ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/ofbiz-framework/trunk/applications/order/template/order/CreateAllocationPlan.ftl ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/ofbiz-framework/trunk/applications/order/template/order/ViewAllocationPlan.ftl URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/order/template/order/ViewAllocationPlan.ftl?rev=1858270&view=auto ============================================================================== --- ofbiz/ofbiz-framework/trunk/applications/order/template/order/ViewAllocationPlan.ftl (added) +++ ofbiz/ofbiz-framework/trunk/applications/order/template/order/ViewAllocationPlan.ftl Sat Apr 27 13:05:30 2019 @@ -0,0 +1,279 @@ +<#-- +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. +--> + +<script type="application/javascript"> + function toggleAllItems(master) { + var form = document.updateAllocationPlanItems; + var length = form.elements.length; + for (var i = 0; i < length; i++) { + var element = form.elements[i]; + if (element.name.match(/rsm_.*/)) { + element.checked = master.checked; + } + } + if (master.checked) { + jQuery('#saveItemsButton').attr("href", "javascript:runAction();"); + } else { + jQuery('#saveItemsButton').attr("href", "javascript: void(0);"); + } + } + + function runAction() { + var form = document.updateAllocationPlanItems; + form.submit(); + } + + function toggleItem() { + var form = document.updateAllocationPlanItems; + var length = form.elements.length; + var isAllSelected = true; + var isAnyOneSelected = false; + for (var i = 0; i < length; i++) { + var element = form.elements[i]; + if (element.name.match(/rsm_.*/)) { + if (element.checked) { + isAnyOneSelected = true; + } else { + isAllSelected = false; + } + } + } + jQuery('#checkAllItems').attr("checked", isAllSelected); + if (isAnyOneSelected || isAllSelected) { + jQuery('#saveItemsButton').attr("href", "javascript:runAction();"); + } else { + jQuery('#saveItemsButton').attr("href", "javascript: void(0);"); + } + } + + $(document).ready(function(){ + $(".up,.down").click(function(){ + var rowCount = $('#allocatioPlanItemsTable tr').length; + var row = $(this).parents("tr:first"); + if ($(this).is(".up")) { + if (row.index() != 1) { + row.insertBefore(row.prev()); + } + } else { + row.insertAfter(row.next()); + } + + //run through each row and reassign the priority + $('#allocatioPlanItemsTable tr').each(function (i, row) { + if (i != 0) { + var prioritySeqInput = $(row).find('.prioritySeqId'); + prioritySeqInput.attr("value", i); + } + }); + }); + }); +</script> +<#if security.hasPermission("ALLOCPLAN_VIEW", session)> + <#if allocationPlanInfo.allocationPlanHeader?has_content> + <#assign statusItem = delegator.findOne("StatusItem", {"statusId" : allocationPlanInfo.statusId!}, false)!/> + <#if !editMode?exists> + <#assign editMode = false/> + </#if> + <#-- Overview Section --> + <div id="allocationPlanOverview" class="screenlet"> + <div class="screenlet-title-bar"> + <ul> + <li class="h3">${uiLabelMap.OrderOverview} [${uiLabelMap.CommonId}:${allocationPlanInfo.planId!}]</li> + <#if (allocationPlanInfo.statusId! == "ALLOC_PLAN_CREATED" || allocationPlanInfo.statusId! == "ALLOC_PLAN_APPROVED") && security.hasPermission("ALLOCPLAN_CANCEL", session)> + <li> + <a href="javascript:document.CancelPlan.submit()">${uiLabelMap.OrderCancelPlan}</a> + <form class="basic-form" name="CancelPlan" method="post" action="<@ofbizUrl>changeAllocationPlanStatus/orderview</@ofbizUrl>"> + <input type="hidden" name="planId" value="${allocationPlanInfo.planId!}"/> + <input type="hidden" name="statusId" value="ALLOC_PLAN_CANCELLED"/> + </form> + </li> + </#if> + <#if (allocationPlanInfo.statusId! == "ALLOC_PLAN_CREATED") && security.hasPermission("ALLOCPLAN_APPROVE", session)> + <li> + <a href="javascript:document.ApprovePlan.submit()">${uiLabelMap.OrderApprovePlan}</a> + <form class="basic-form" name="ApprovePlan" method="post" action="<@ofbizUrl>changeAllocationPlanStatus/orderview</@ofbizUrl>"> + <input type="hidden" name="planId" value="${allocationPlanInfo.planId!}"/> + <input type="hidden" name="statusId" value="ALLOC_PLAN_APPROVED"/> + </form> + </li> + </#if> + </ul> + <br class="clear"/> + </div> + <div class="screenlet-body"> + <table class="basic-table form-table" cellspacing="0"> + <tbody> + <tr> + <td align="center"><label><b>${uiLabelMap.CommonName}</b></label></td> + <td align="left"><a href="/ordermgr/control/ViewAllocationPlan?planId=${allocationPlanInfo.planId!}" title="${allocationPlanInfo.planId!}"> ${allocationPlanInfo.planName!}</a></td> + <td align="center"><label><b>${uiLabelMap.OrderProduct}</b></label></td> + <td align="left"><a href="/catalog/control/EditProduct?productId=${allocationPlanInfo.productId!}" title="${allocationPlanInfo.productId!}">${allocationPlanInfo.productName!}</a></td> + <td align="center"><label><b>${uiLabelMap.CommonCreatedBy}</b></label></td> + <td align="left">${allocationPlanInfo.createdBy!}</td> + </tr> + <tr> + <td align="center"><label><b>${uiLabelMap.CommonStatus}</b></label></td> + <td align="left">${statusItem.get("description")!}</td> + <td align="center"><label><b>${uiLabelMap.ProductAtp}/${uiLabelMap.ProductQoh}</b></label></td> + <td align="left">${allocationPlanInfo.totalATP!}/${allocationPlanInfo.totalQOH!}</td> + <td align="center"><label><b>${uiLabelMap.OrderRequestCreatedDate}</b></label></td> + <td align="left">${allocationPlanInfo.createdDate!}</td> + </tr> + </tbody> + </table> + </div> + </div> + <#-- Summary Section --> + <div id="allocationPlanSummary" class="screenlet"> + <div class="screenlet-title-bar"> + <ul> + <li class="h3">${uiLabelMap.CommonSummary}</li> + </ul> + <br class="clear"/> + </div> + <div class="screenlet-body"> + <table class="basic-table hover-bar" cellspacing='0'> + <tr class="header-row"> + <td width="20%">${uiLabelMap.OrderOrderingChannel}</td> + <td align="right" width="16%">${uiLabelMap.OrderOrderedUnits}</td> + <td align="right" width="16%">${uiLabelMap.OrderOrderedValue}</td> + <td align="right" width="16%">${uiLabelMap.OrderAllocatedUnits}</td> + <td align="right" width="16%">${uiLabelMap.OrderAllocatedValue}</td> + <td align="right" width="16%">${uiLabelMap.OrderAllocation} %</td> + </tr> + <#list allocationPlanInfo.summaryMap.keySet() as key> + <#assign summary = allocationPlanInfo.summaryMap.get(key)/> + <tr> + <td>${summary.salesChannel!}</td> + <td align="right">${summary.orderedQuantity!}</td> + <td align="right"><@ofbizCurrency amount=summary.orderedValue!?default(0.00) isoCode=currencyUomId/></td> + <td align="right">${summary.allocatedQuantity!}</td> + <td align="right"><@ofbizCurrency amount=summary.allocatedValue!?default(0.00) isoCode=currencyUomId/></td> + <td align="right">${summary.allocationPercentage!?string("0.####")}</td> + </tr> + </#list> + <tr> + <td ><b>${uiLabelMap.CommonTotal}</b></td> + <td align="right"><b>${allocationPlanInfo.orderedQuantityTotal!}</b></td> + <td align="right"><b><@ofbizCurrency amount=allocationPlanInfo.orderedValueTotal!?default(0.00) isoCode=currencyUomId/></td> + <td align="right"><b>${allocationPlanInfo.allocatedQuantityTotal!}</b></td> + <td align="right"><b><@ofbizCurrency amount=allocationPlanInfo.allocatedValueTotal!?default(0.00) isoCode=currencyUomId/></b></td> + <td align="right"><b>${allocationPlanInfo.allocationPercentageTotal!?string("0.####")}</b></td> + </tr> + </table> + </div> + </div> + <#-- Items Section --> + <div id="allocationPlanItems" class="screenlet"> + <div class="screenlet-title-bar"> + <ul> + <li class="h3">${uiLabelMap.CommonItems}</li> + <#if editMode> + <li><a href="/ordermgr/control/ViewAllocationPlan?planId=${allocationPlanInfo.planId!}" class="buttontext">${uiLabelMap.CommonCancel}</a></li> + <li><a id="saveItemsButton" href="javascript: void(0);" class="buttontext">${uiLabelMap.CommonSave}</a></li> + <#elseif allocationPlanInfo.statusId! != "ALLOC_PLAN_COMPLETED" && allocationPlanInfo.statusId! != "ALLOC_PLAN_CANCELLED" && security.hasPermission("ALLOCPLAN_UPDATE", session)> + <li><a href="/ordermgr/control/EditAllocationPlan?planId=${allocationPlanInfo.planId!}" class="buttontext">${uiLabelMap.CommonEdit}</a></li> + </#if> + </ul> + <br class="clear"/> + </div> + <div class="screenlet-body"> + <#assign rowCount = 0> + <table id="allocatioPlanItemsTable" class="basic-table hover-bar" cellspacing='0'> + <form class="basic-form" name="updateAllocationPlanItems" id="updateAllocationPlanItems" method="post" action="<@ofbizUrl>updateAllocationPlanItems</@ofbizUrl>"> + <input type="hidden" name="planId" value="${allocationPlanInfo.planId!}"/> + <tr class="header-row"> + <#if editMode> + <td width="5%"><input type="checkbox" id="checkAllItems" name="checkAllItems" onchange="javascript:toggleAllItems(this);"></td> + </#if> + <td width="8%">${uiLabelMap.OrderSalesChannel}</td> + <td width="8%">${uiLabelMap.OrderCustomer}</td> + <td width="8%">${uiLabelMap.Status}</td> + <td width="8%">${uiLabelMap.FormFieldTitle_orderId}</td> + <td width="8%">${uiLabelMap.FormFieldTitle_orderItemSeqId}</td> + <td width="10%">${uiLabelMap.FormFieldTitle_estimatedShipDate}</td> + <td align="right" width="8%">${uiLabelMap.OrderOrdered}</td> + <td align="right" width="8%">${uiLabelMap.ProductReserved}</td> + <td align="right" width="8%">${uiLabelMap.OrderExtValue}</td> + <td align="right" width="8%">${uiLabelMap.OrderAllocated}</td> + <td align="right" width="8%">${uiLabelMap.OrderAllocation} %</td> + <#if editMode> + <td align="right" width="5%">${uiLabelMap.FormFieldTitle_actionEnumId}</td> + </#if> + </tr> + <#list allocationPlanInfo.itemList as item> + <tr> + <input type="hidden" name="psim_${item.planItemSeqId}" value="${rowCount+1}" class="prioritySeqId"/> + <input type="hidden" name="pim_${item.planItemSeqId}" value="${item.productId}"/> + <input type="hidden" name="oim_${item.planItemSeqId}" value="${item.orderId}"/> + <input type="hidden" name="oisim_${item.planItemSeqId}" value="${item.orderItemSeqId}"/> + <#if editMode> + <td> + <input type="checkbox" name="rsm_${item.planItemSeqId}" value="Y" onchange="javascript:toggleItem();"> + </td> + </#if> + <td>${item.salesChannel!}</td> + <td><a href="/partymgr/control/viewprofile?partyId=${item.partyId!}" title="${item.partyId!}">${item.partyName!}</a></td> + <#assign statusItem = delegator.findOne("StatusItem", {"statusId" : item.statusId!}, false)!/> + <td>${statusItem.get("description")}</td> + <td><a href="/ordermgr/control/orderview?orderId=${item.orderId!}" title="${item.orderId!}">${item.orderId!}</a></td> + <td>${item.orderItemSeqId!}</td> + <td>${item.estimatedShipDate!}</td> + <td align="right">${item.orderedQuantity!}</td> + <td align="right">${item.reservedQuantity!}</td> + <td align="right"><@ofbizCurrency amount=item.orderedValue!?default(0.00) isoCode=currencyUomId/></td> + <#if editMode> + <td><input type="text" name="aqm_${item.planItemSeqId}" value="${item.allocatedQuantity!}"/></td> + <td align="right">${item.allocationPercentage!?string("0.####")}</td> + <td align="right"> + <a href="#" class="up"><img src="/images/arrow-single-up-green.png"/></a> + <a href="#" class="down"><img src="/images/arrow-single-down-green.png"/></a> + </td> + <#else> + <td align="right">${item.allocatedQuantity!}</td> + <td align="right">${item.allocationPercentage!?string("0.####")}</td> + </#if> + </tr> + <#assign rowCount = rowCount + 1> + </#list> + <tr> + <#if editMode> + <td></td> + </#if> + <td colspan="6"><b>${uiLabelMap.CommonTotal}</b></td> + <td align="right"><b>${allocationPlanInfo.orderedQuantityTotal!}</b></td> + <td align="right"><b>${allocationPlanInfo.reservedQuantityTotal!}</b></td> + <td align="right"><b><@ofbizCurrency amount=allocationPlanInfo.orderedValueTotal!?default(0.00) isoCode=currencyUomId/> + <td align="right"><b>${allocationPlanInfo.allocatedQuantityTotal!}</b></td> + <td align="right"><b>${allocationPlanInfo.allocationPercentageTotal!?string("0.####")}</b></td> + <#if editMode> + <td></td> + </#if> + </tr> + <input type="hidden" name="_rowCount" value="${rowCount}" /> + </form> + </table> + </div> + </div> + <#else> + <b>${uiLabelMap.OrderAllocationPlanNotFound}</b> + </#if> +<#else> + ${uiLabelMap.OrderAllocationPlanViewPermissionError} +</#if> \ No newline at end of file Propchange: ofbiz/ofbiz-framework/trunk/applications/order/template/order/ViewAllocationPlan.ftl ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/ofbiz-framework/trunk/applications/order/template/order/ViewAllocationPlan.ftl ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/ofbiz-framework/trunk/applications/order/template/order/ViewAllocationPlan.ftl ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: ofbiz/ofbiz-framework/trunk/applications/order/webapp/ordermgr/WEB-INF/controller.xml URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/order/webapp/ordermgr/WEB-INF/controller.xml?rev=1858270&r1=1858269&r2=1858270&view=diff ============================================================================== --- ofbiz/ofbiz-framework/trunk/applications/order/webapp/ordermgr/WEB-INF/controller.xml (original) +++ ofbiz/ofbiz-framework/trunk/applications/order/webapp/ordermgr/WEB-INF/controller.xml Sat Apr 27 13:05:30 2019 @@ -1274,6 +1274,58 @@ under the License. <response name="success" type="view" value="RequirementsForSupplier"/> </request-map> + <!-- Allocation Plan Request Mappings --> + <request-map uri="CreateAllocationPlan"> + <security https="true" auth="true"/> + <response name="success" type="view" value="CreateAllocationPlan"/> + </request-map> + <request-map uri="createAllocationPlanAndItems"> + <security https="true" auth="true"/> + <event type="service" invoke="createAllocationPlanAndItems"/> + <response name="success" type="request-redirect" value="CreateAllocationPlan"> + <redirect-parameter name="planId"/> + </response> + <response name="error" type="view" value="CreateAllocationPlan"/> + </request-map> + <request-map uri="FindAllocationPlan"> + <security https="true" auth="true"/> + <response name="success" type="view" value="FindAllocationPlan"/> + </request-map> + <request-map uri="ViewAllocationPlan"> + <security https="true" auth="true"/> + <response name="success" type="view" value="ViewAllocationPlan"/> + </request-map> + <request-map uri="EditAllocationPlan"> + <security https="true" auth="true"/> + <response name="success" type="view" value="EditAllocationPlan"/> + </request-map> + <request-map uri="updateAllocationPlanItems"> + <security https="true" auth="true"/> + <event type="service" invoke="updateAllocationPlanItems"/> + <response name="success" type="request-redirect" value="ViewAllocationPlan"> + <redirect-parameter name="planId"/> + </response> + <response name="error" type="request-redirect" value="EditAllocationPlan"> + <redirect-parameter name="planId"/> + </response> + </request-map> + <request-map uri="deleteAllocationPlanItem"> + <security https="true" auth="true"/> + <event type="service" invoke="deleteAllocationPlanItem"/> + <response name="success" type="view" value="FindAllocationPlan"/> + <response name="error" type="view" value="FindAllocationPlan"/> + </request-map> + <request-map uri="changeAllocationPlanStatus"> + <security https="true" auth="true"/> + <event type="service" invoke="changeAllocationPlanStatus"/> + <response name="success" type="request-redirect" value="ViewAllocationPlan"> + <redirect-parameter name="planId"/> + </response> + <response name="error" type="request-redirect" value="ViewAllocationPlan"> + <redirect-parameter name="planId"/> + </response> + </request-map> + <!-- =============== CustRequest mapping =================--> <request-map uri="FindRequest"><security https="true" auth="true"/><response name="success" type="view" value="FindRequest"/></request-map> <request-map uri="ViewRequest"><security https="true" auth="true"/><response name="success" type="view" value="ViewRequest"/></request-map> @@ -1997,6 +2049,11 @@ under the License. <view-map name="RequirementsForSupplier" type="screen" page="component://order/widget/ordermgr/OrderEntryScreens.xml#RequirementsForSupplier"/> <view-map name="FindQuoteForCart" type="screen" page="component://order/widget/ordermgr/OrderEntryScreens.xml#FindQuoteForCart"/> + <view-map name="CreateAllocationPlan" type="screen" page="component://order/widget/ordermgr/AllocationPlanScreens.xml#CreateAllocationPlan"/> + <view-map name="FindAllocationPlan" type="screen" page="component://order/widget/ordermgr/AllocationPlanScreens.xml#FindAllocationPlan"/> + <view-map name="ViewAllocationPlan" type="screen" page="component://order/widget/ordermgr/AllocationPlanScreens.xml#ViewAllocationPlan"/> + <view-map name="EditAllocationPlan" type="screen" page="component://order/widget/ordermgr/AllocationPlanScreens.xml#EditAllocationPlan"/> + <view-map name="FindQuote" type="screen" page="component://order/widget/ordermgr/QuoteScreens.xml#FindQuote"/> <view-map name="ViewQuote" type="screen" page="component://order/widget/ordermgr/QuoteScreens.xml#ViewQuote"/> <view-map name="QuoteReport" type="screenfop" page="component://order/widget/ordermgr/QuoteScreens.xml#QuoteReport" content-type="application/pdf" encoding="none"/> Added: ofbiz/ofbiz-framework/trunk/applications/order/widget/ordermgr/AllocationPlanForms.xml URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/order/widget/ordermgr/AllocationPlanForms.xml?rev=1858270&view=auto ============================================================================== --- ofbiz/ofbiz-framework/trunk/applications/order/widget/ordermgr/AllocationPlanForms.xml (added) +++ ofbiz/ofbiz-framework/trunk/applications/order/widget/ordermgr/AllocationPlanForms.xml Sat Apr 27 13:05:30 2019 @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +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. +--> + +<forms xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://ofbiz.apache.org/Widget-Form" xsi:schemaLocation="http://ofbiz.apache.org/Widget-Form http://ofbiz.apache.org/dtds/widget-form.xsd"> + <form name="FindAllocationPlan" type="single" target="FindAllocationPlan" title="" + header-row-style="header-row" default-table-style="basic-table"> + <field name="noConditionFind"><hidden value="Y"/><!-- if this isn't there then with all fields empty no query will be done --></field> + <field name="planId"><text-find/></field> + <field name="planName"><text-find/></field> + <field name="planTypeId"> + <drop-down allow-empty="true"> + <entity-options entity-name="AllocationPlanType"/> + </drop-down> + </field> + <field name="statusId"> + <drop-down allow-empty="true"> + <entity-options entity-name="StatusItem"> + <entity-constraint name="statusTypeId" operator="equals" value="ALLOC_PLAN_STATUS"/> + <entity-order-by field-name="sequenceId"/> + </entity-options> + </drop-down> + </field> + <field name="productId"> + <lookup target-form-name="LookupProduct"/> + </field> + <field name="orderId"> + <lookup target-form-name="LookupOrderHeader"/> + </field> + <field name="submitButton" title="${uiLabelMap.CommonFind}" widget-style="smallSubmit"> + <submit button-type="button"/> + </field> + </form> + + <grid name="ListAllocationPlan" list-name="allocationPlans" target="" title="" paginate-target="FindAllocationPlan" + odd-row-style="alternate-row" default-table-style="basic-table hover-bar" header-row-style="header-row-2"> + <field name="planId" widget-style="buttontext" sort-field="true"> + <hyperlink target-type="inter-app" description="${planId}" target="/ordermgr/control/ViewAllocationPlan"> + <parameter param-name="planId"/> + </hyperlink> + </field> + <field name="statusId"><display-entity entity-name="StatusItem"/></field> + <field name="planTypeId"> + <display-entity entity-name="AllocationPlanType"/> + </field> + <field name="productId" sort-field="true"> + <display-entity entity-name="Product" key-field-name="productId" description="${productId} - ${internalName}"/> + </field> + <field name="orderId" sort-field="true" > + <display/> + </field> + <field name="orderItemSeqId"> + <display/> + </field> + <field name="planMethodEnumId"> + <display-entity entity-name="Enumeration" key-field-name="enumId" description="${description}"/> + </field> + <field name="allocatedQuantity" sort-field="true"> + <display/> + </field> + <field name="deleteLink" widget-style="buttontext" title=" "> + <hyperlink description="${uiLabelMap.CommonRemove}" target="deleteAllocationPlanItem"> + <parameter param-name="planId"/> + <parameter param-name="planItemSeqId"/> + <parameter param-name="productId"/> + </hyperlink> + </field> + </grid> +</forms> \ No newline at end of file Propchange: ofbiz/ofbiz-framework/trunk/applications/order/widget/ordermgr/AllocationPlanForms.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/ofbiz-framework/trunk/applications/order/widget/ordermgr/AllocationPlanForms.xml ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/ofbiz-framework/trunk/applications/order/widget/ordermgr/AllocationPlanForms.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml |
Free forum by Nabble | Edit this page |