This is an automated email from the ASF dual-hosted git repository.
nmalin pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git The following commit(s) were added to refs/heads/trunk by this push: new f6418d5 Improved: Convert OrderReturnService.xml from mini lang to groovy (OFBIZ-11442) f6418d5 is described below commit f6418d52f598e64340268fadf2b22d361bdd2a49 Author: Nicolas Malin <[hidden email]> AuthorDate: Wed Apr 8 14:25:00 2020 +0200 Improved: Convert OrderReturnService.xml from mini lang to groovy (OFBIZ-11442) Thanks to Sebastian Berg for providing the patch --- .../groovyScripts/order/OrderReturnServices.groovy | 988 ++++++++++++++++ .../order/minilang/order/OrderReturnServices.xml | 1186 -------------------- applications/order/servicedef/services_return.xml | 103 +- 3 files changed, 1039 insertions(+), 1238 deletions(-) diff --git a/applications/order/groovyScripts/order/OrderReturnServices.groovy b/applications/order/groovyScripts/order/OrderReturnServices.groovy new file mode 100644 index 0000000..b8bb8ce --- /dev/null +++ b/applications/order/groovyScripts/order/OrderReturnServices.groovy @@ -0,0 +1,988 @@ +/* + * 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. + */ + +import java.sql.Timestamp + +import org.apache.ofbiz.base.util.UtilDateTime +import org.apache.ofbiz.base.util.UtilProperties +import org.apache.ofbiz.entity.GenericValue +import org.apache.ofbiz.entity.util.EntityUtil +import org.apache.ofbiz.service.ServiceUtil + + +/** + * Create a ReturnHeader + * @return + */ +def createReturnHeader() { + Map result = success() + Timestamp nowTimestamp = UtilDateTime.nowTimestamp() + + if (!security.hasEntityPermission("ORDERMGR", "_CREATE", parameters.userLogin) + && userLogin.partyId != parameters.fromPartyId) { + return informError("OrderSecurityErrorToRunCreateReturnHeader") + } + String returnHeaderTypeId = parameters.returnHeaderTypeId + if (!parameters.toPartyId) { + // no toPartyId was specified. use destination facility to determine the party of the return + if ("CUSTOMER_RETURN" == returnHeaderTypeId && parameters.destinationFacilityId) { + GenericValue destinationFacility = from("Facility") + .where(facilityId: parameters.destinationFacilityId) + .cache() + .queryOne() + parameters.toPartyId = destinationFacility.ownerPartyId + } + } else { + // make sure that the party to return to is an INTERNAL_ORGANIZATIO for customer return + // and SUPPLIER for vendor return else stop + if (returnHeaderTypeId.contains("CUSTOMER_")) { + GenericValue partyRole = from("PartyRole") + .where(partyId: parameters.toPartyId, roleTypeId: "INTERNAL_ORGANIZATIO") + .cache() + .queryOne() + if (!partyRole) { + return informError("OrderReturnRequestPartyRoleInternalOrg") + } + } else { + GenericValue partyRole = from("PartyRole") + .where(partyId: parameters.toPartyId, roleTypeId: "SUPPLIER") + .cache() + .queryOne() + if (!partyRole) { + return informError("OrderReturnRequestPartyRoleSupplier") + } + } + } + if (parameters.paymentMethodId) { + GenericValue paymentMethod = from("PaymentMethod") + .where(paymentMethodId: parameters.paymentMethodId) + .cache() + .queryOne() + if (!paymentMethod) { + return informError("OrderReturnRequestPaymentMethodId") + } + } + // check the needs (auto) inventory receive flag + // (default to N, meaning that return won't automatically be considered Received when Accepted) + if (!parameters.needsInventoryReceive) { + parameters.needsInventoryReceive = "N" + } + GenericValue newEntity = makeValue("ReturnHeader") + newEntity.setNonPKFields(parameters) + + // If PartyAcctgPreference.useInvoiceIdForReturns is Y, get the ID from the getNextInvoiceId service + GenericValue systemLogin = from("UserLogin") + .where(userLoginId: "system") + .cache() + .queryOne() + Map serviceResult = run service:"getPartyAccountingPreferences", with: [organizationPartyId: parameters.toPartyId, + userLogin: systemLogin] + GenericValue partyAcctgPreference = serviceResult.partyAccountingPreference + + if ("Y" == partyAcctgPreference.useInvoiceIdForReturns) { + Map serviceResultInvoice = run service: "getNextInvoiceId", with: [partyId: parameters.toPartyId] + newEntity.returnId = serviceResultInvoice.invoiceId + } else { + newEntity.returnId = delegator.getNextSeqId("ReturnHeader") + } + result.returnId = newEntity.returnId + + boolean hasCreatePermission = security.hasEntityPermission("ORDERMGR", "_CREATE", parameters.userLogin) + if (!newEntity.entryDate || !hasCreatePermission) { + newEntity.entryDate = nowTimestamp + } + if (!newEntity.statusId || !hasCreatePermission) { + newEntity.statusId = "CUSTOMER_RETURN" == returnHeaderTypeId ? "RETURN_REQUESTED" : "SUP_RETURN_REQUESTED" + } + newEntity.createdBy = userLogin.userLoginId + newEntity.create() + result.successMessage = "Return Request #[${newEntity.returnId}] was created successfully." + return result +} + +/** + * Update a ReturnHeader + * @return + */ +def updateReturnHeader() { + Map result = success() + GenericValue returnHeader = from("ReturnHeader").where(parameters).queryOne() + // test the total return amount vs the total order amount + if ("RETURN_ACCEPTED" == parameters.statusId) { + // get the list of ReturnItems. Note: return may be associated with many different orders + List returnItems = from("ReturnItem").where(returnId: returnHeader.returnId).distinct().queryList() + + // this is used to make sure we don't return a negative amount + BigDecimal returnTotalAmount = (BigDecimal) 0 + + // check them all to make sure that the return total does not exceed order total. + for (GenericValue returnItem : returnItems) { + if (!returnHeader.paymentMethodId && !parameters.paymentMethodId && + ("RTN_CSREPLACE" == returnItem.returnTypeId || "RTN_REPAIR_REPLACE" == returnItem.returnTypeId)) { + return informError("OrderReturnPaymentMethodNeededForThisTypeOfReturn") + } + // tally up the return total amount + returnTotalAmount += returnItem.returnPrice * returnItem.returnQuantity + // compare return vs order total + if (returnItem.orderId) { + // no adjustment needed: adjustment is passed in to calculate + // the effect of an additional item on return total. + Map serviceResult = run service:"getOrderAvailableReturnedTotal", with: [orderId: returnItem.orderId, + adjustment : (BigDecimal) 0] + BigDecimal availableReturnTotal = serviceResult.availableReturnTotal + BigDecimal returnTotal = serviceResult.returnTotal + BigDecimal orderTotal = serviceResult.returnTotal + logInfo("Available amount for return on order # ${returnItem.orderId} is " + + "[${availableReturnTotal}] (orderTotal = [${orderTotal}] - returnTotal = [${returnTotal}]") + + if (availableReturnTotal < (BigDecimal) -0.01) { + return informError("OrderReturnPriceCannotExceedTheOrderTotal") + } + } else { + logInfo("Not an order based returnItem; uable to check valid amounts!") + } + } + // Checking that the Status change is Valid or Not + if (parameters.statusId && parameters.statusId != returnHeader.statusId) { + GenericValue statusValidChange = from("StatusValidChange") + .where(statusId: returnHeader.statusId, statusIdTo: parameters.statusId) + .cache() + .queryOne() + if (!statusValidChange) { + return informError("OrderErrorReturnHeaderItemStatusNotChangedIsNotAValidChange") + } + } + List returnAdjustments = from("ReturnAdjustment").where(returnId: returnHeader.returnId).queryList() + for (GenericValue returnAdjustment : returnAdjustments) { + returnTotalAmount += returnAdjustment.amount + } + if (returnTotalAmount < 0) { + return informError("OrderReturnTotalCannotLessThanZero") + } + } + result.oldStatusId = returnHeader.statusId + returnHeader.setNonPKFields(parameters) + returnHeader.store() + return result +} + +/** + * Create Return Item + * @return + */ +def createReturnItem() { + Map result = success() + GenericValue orderItem + GenericValue returnHeader = from("ReturnHeader") + .where(returnId: parameters.returnId) + .queryOne() + + if (!security.hasEntityPermission("ORDERMGR", "_CREATE", parameters.userLogin) + && returnHeader.fromPartyId != userLogin.partyId) { + return informError("OrderSecurityErrorToRunCreateReturnItem") + } + if (!parameters.returnItemTypeId) { + return informError("OrderReturnItemTypeIsNotDefined") + } + + if (!returnHeader?.paymentMethodId && "RETURN_ACCEPTED" == returnHeader.statusId + && ("RTN_CSREPLACE" == parameters.returnTypeId || "RTN_REPAIR_REPLACE" == parameters.returnTypeId)) { + return informError("OrderReturnPaymentMethodNeededForThisTypeOfReturn") + } + if (parameters.returnQuantity == (BigDecimal) 0) { + return informError("OrderNoReturnQuantityAvailablePreviousReturnsMayExist") + } + + // setup some default values for protection + BigDecimal returnableQuantity = (BigDecimal) 0 + BigDecimal returnablePrice = (BigDecimal) 0 + + // if an orderItemSeqId is provided, then find the corresponding orderItem + if (parameters.orderItemSeqId) { + Map itemLookup = makeValue("OrderItem") + itemLookup.setPKFields(parameters) + if (parameters.orderItemSeqId) { + orderItem = from("OrderItem").where(itemLookup).queryOne() + logInfo("Return item is an Order Item - " + orderItem.orderItemSeqId) + } + } + /* + * get the returnableQuantity and returnablePrice: + * for orderItems, it's found by getReturnableQuantity; + * for adjustments, either order adjustments or manual adjustments, it's always 1 and based on input parameter + */ + if (orderItem) { + Map serviceResult = run service: "getReturnableQuantity", with: [orderItem: orderItem] + returnableQuantity = serviceResult.returnableQuantity ?: returnableQuantity + returnablePrice = serviceResult.returnablePrice ?: returnablePrice + } + if (returnableQuantity > (BigDecimal) 0) { + // the user is only allowed to set a returnPrice if he has ORDERMGR_CREATE privilege, + // otherwise only the returnablePrice calculated by service is used + if (!security.hasEntityPermission("ORDERMGR", "_CREATE", parameters.userLogin)) { + returnablePrice = parameters.returnPrice + } + // make sure the returnQuantity is not greater than the returnableQuantity + // from service or the quantity on the original orderItem + if (parameters.returnQuantity > returnableQuantity) { + return informError("OrderRequestedReturnQuantityNotAvailablePreviousReturnsMayExist") + } + if (orderItem && parameters.returnQuantity > orderItem.quantity) { + return informError("OrderReturnQuantityCannotExceedTheOrderedQuantity") + } + if (parameters.returnPrice > returnablePrice) { + return informError("OrderReturnPriceCannotExceedThePurchasePrice") + } + } else { + logError("Order ${parameters.orderId} item ${parameters.orderItemSeqId} has been returned in full") + return informError("OrderIllegalReturnItemTypePassed") + } + GenericValue newEntity = makeValue("ReturnItem") + newEntity.returnId = parameters.returnId + delegator.setNextSubSeqId(newEntity, "returnItemSeqId", 5, 1) + newEntity.setNonPKFields(parameters) + newEntity.statusId = "RETURN_REQUESTED" // default status for new return items + result.returnItemSeqId = newEntity.returnItemSeqId + newEntity.create() + newEntity.refresh() + + if (orderItem && !parameters.includeAdjustments || "Y" == parameters.includeAdjustments) { + // create return adjustments for all adjustments associated with the order item + List orderAdjustments = delegator.getRelated("OrderAdjustment", null, null, orderItem, false) + for (GenericValue orderAdjustment : orderAdjustments) { + Map returnAdjCtx = [returnId: parameters.returnId, + returnItemSeqId: newEntity.returnItemSeqId, + returnTypeId: newEntity.returnTypeId, + orderAdjustmentId: orderAdjustment.orderAdjustmentId] + run service:"createReturnAdjustment", with: returnAdjCtx + } + } + return result +} + +/** + * Update Return Item + * @return + */ +def updateReturnItem() { + Map result = success() + Map lookupPKMap = [returnId: parameters.returnId, returnItemSeqId: parameters.returnItemSeqId] + GenericValue returnItem = from("ReturnItem").where(lookupPKMap).queryOne() + BigDecimal originalReturnPrice = returnItem.returnPrice + BigDecimal originalReturnQuantity = returnItem.returnQuantity + result.oldStatusId = returnItem.statusId + + returnItem.setNonPKFields(parameters) + returnItem.store() + returnItem.refresh() + + // now update all return adjustments associated with this return item + List returnAdjustments = from("ReturnAdjustment") + .where(returnId: returnItem.returnId, + returnItemSeqId: returnItem.returnItemSeqId) + .queryList() + for (GenericValue returnAdjustment : returnAdjustments) { + logInfo("updating returnAdjustment with Id:[${returnAdjustment.returnAdjustmentId}]") + Map ctx = returnAdjustment + ctx.originalReturnPrice = originalReturnPrice + ctx.originalReturnQuantity = originalReturnQuantity + ctx.ReturnTypeId = returnItem.returnTypeId + run service: "updateReturnAdjustment", with: ctx + } + return result +} + +/** + * Update Return Items Status + * @return + */ +def updateReturnItemsStatus() { + List returnItems = from("ReturnItem").where(returnId: parameters.returnId).queryList() + for (GenericValue item : returnItems) { + item.statusId = parameters.statusId + Map serviceInMap = [:] + serviceInMap << item + run service:"updateReturnItem", with: serviceInMap + } + return success() +} + +/** + * Remove Return Item + * @return + */ +def removeReturnItem() { + GenericValue returnHeader = from("ReturnHeader").where(parameters).queryOne() + if ("CUSTOMER_RETURN" == returnHeader.returnHeaderTypeId) { + if ("RETURN_REQUESTED" != returnHeader.statusId) { + return informError("OrderCannotRemoveItemsOnceReturnIsApproved") + } + } else { + if ("SUP_RETURN_REQUESTED" != returnHeader.statusId) { + return informError("OrderCannotRemoveItemsOnceReturnIsApproved") + } + } + GenericValue returnItem = from("ReturnItem") + .where(returnId: parameters.returnId, + returnItemSeqId: parameters.returnItemSeqId) + .queryOne() + // remove related adjustments + List returnAdjustments = from("ReturnAdjustment") + .where(returnItemSeqId: returnItem.returnItemSeqId, + returnId: returnItem.returnId) + .queryList() + for (GenericValue returnAdjustment : returnAdjustments) { + run service:"removeReturnAdjustment", with: [returnAdjustmentId: returnAdjustment.returnAdjustmentId] + } + returnItem.remove() + return success() +} + +// note that this service is designed to be called once for each shipment receipt that is created + +/** + * Update Return Status From ShipmentReceipt + * @return + */ +def updateReturnStatusFromReceipt() { + Map result = success() + Map lookupPKMap = [returnId: parameters.returnId] + GenericValue returnHeader = from("ReturnHeader").where(lookupPKMap).queryOne() + List shipmentReceipts = from("ShipmentReceipt").where(lookupPKMap).queryList() + Map totalsMap = [:] + for (GenericValue receipt : shipmentReceipts) { + if (!totalsMap[receipt?.returnItemSeqId]) { + totalsMap[receipt.returnItemSeqId] = (BigDecimal) 0 + } + totalsMap[receipt.returnItemSeqId] += receipt.quantityAccepted + receipt.quantityRejected + } + List returnItems = delegator.getRelated("ReturnItem", null, null, returnHeader, false) + + for (Map.Entry entry : totalsMap.entrySet()) { + Map filterMap = [returnItemSeqId: entry.getKey()] + Map item = EntityUtil.getFirst(EntityUtil.filterByAnd(returnItems, filterMap)) + item.receivedQuantity = entry.getValue() + if (entry.getValue() >= item.returnQuantity) { + // update the status for the item + item.statusId = "RETURN_RECEIVED" + } + // update the returnItem with at least receivedQuantity, and also statusId if applicable + run service: "updateReturnItem", with: item + } + // check to see if all items have been received + boolean allReceived = true + List allReturnItems = from("ReturnItem").where(lookupPKMap).queryList() + for (GenericValue item : allReturnItems) { + if ("RETURN_RECEIVED" != item.statusId) { + if (item.orderItemSeqId) { + // non-order items (i.e. adjustments) are not received + allReceived = false + } + } + } + + // if the items are all received, then update the return header, store the status history change, + // and set the shipment to received + if (allReceived) { + /* + * Go through all the items yet again and set their shipment status to PURCH_SHIP_RECEIVED (if it isn't already) + * This activates SECAS such as creating return invoices. This MUST be done before updating the return header so + * that the ReturnItemBillings are created and then whatever SECA binds to the return header update will have them. + */ + for (GenericValue receipt : shipmentReceipts) { + GenericValue shipment = delegator.getRelatedOne("Shipment", receipt, false) + if (shipment.shipmentId) { + if ("RETURN_RECEIVED" != shipment.statusId) { + run service:"updateShipment", with: [shipmentId: shipment.shipmentId, + statusId: "PURCH_SHIP_RECEIVED"] + } + } + } + // update the return header + run service:"updateReturnHeader", with: [statusId: "RETURN_RECEIVED", + returnId: returnHeader.returnId] + } + result.returnHeaderStatus = returnHeader.statusId + return result +} + +/** + * Create Quick Return From Order + * @return + */ +def quickReturnFromOrder() { + Map result = success() + GenericValue returnItemTypeMapping + + if (!security.hasEntityPermission("ORDERMGR", "_CREATE", parameters.userLogin) + && !parameters.fromPartyId == userLogin.partyId) { + return informError("OrderSecurityErrorToRunQuickReturnFromOrder") + } + + // get primary information from the order header + GenericValue orderHeader = from("OrderHeader").where(orderId: parameters.orderId).queryOne() + String returnHeaderTypeId = parameters.returnHeaderTypeId + String roleTypeId = "CUSTOMER_RETURN" == returnHeaderTypeId ? "BILL_TO_CUSTOMER" : "BILL_FROM_VENDOR" + + // find the bill to customer; for return's fromPartyId + GenericValue orderRole = from("OrderRole").where(orderId: orderHeader.orderId, roleTypeId: roleTypeId).queryFirst() + // create the return header + // changed from minilang: used createHeaderCtx instead of updateHeader on neesInventoryReceive + Map createHeaderCtx = [destinationFacilityId: orderHeader.originFacilityId, + needsInventoryReceive: "Y", + returnHeaderTypeId: returnHeaderTypeId] + // get the return to party for customer return and return from party for vendor return from the product store + GenericValue productStore = delegator.getRelatedOne("ProductStore", orderHeader, false) + if ("CUSTOMER_RETURN" == returnHeaderTypeId) { + createHeaderCtx.fromPartyId = orderRole.partyId + createHeaderCtx.toPartyId = productStore.payToPartyId + if (!createHeaderCtx.destinationFacilityId) { + createHeaderCtx.destinationFacilityId = productStore.inventoryFacilityId + } + } else { + createHeaderCtx.fromPartyId = productStore.paytoPartyId + createHeaderCtx.toPartyId = orderRole.partyId + } + // copy over the currency of the order to the currency of the return + createHeaderCtx.currencyUomId = orderHeader.currencyUom + Map serviceResult = run service: "createReturnHeader", with: createHeaderCtx + String returnId = serviceResult.returnId + // get the available to return order items + List orderItems = from("OrderItem").where(orderId: orderHeader.orderId, statusId: "ITEM_COMPLETED").queryList() + + if (!parameters.returnReasonId) { + parameters.returnReasonId = "RTN_NOT_WANT" + } + if (!parameters.returnTypeId) { + parameters.returnTypeId = "RTN_REFUND" + } + // create the return items + for (GenericValue orderItem : orderItems) { + Map newItemCtx = [returnId: returnId, + returnReasonId: parameters.returnReasonId, + returnTypeId: parameters.returnTypeId] + if (orderItem.productId) { + newItemCtx.productId = orderItem.productId + } + newItemCtx.orderId = orderItem.orderId + newItemCtx.orderItemSeqId = orderItem.orderItemSeqId + newItemCtx.description = orderItem.itemDescription + + // get the returnable price and quantity + Map serviceResultQuantity = run service: "getReturnableQuantity", with: [orderItem: orderItem] + newItemCtx.returnQuantity = serviceResultQuantity.returnableQuantity + newItemCtx.returnPrice = serviceResultQuantity.returnablePrice + + // get the matching return item type from the order item type + String orderItemTypeId = orderItem.orderItemTypeId + if ("PRODUCT_ORDER_ITEM" == orderItemTypeId) { + // Check if orderItemTypeId equals PRODUCT_ORDER_ITEM, + // if so, use ProductType and ReturnItemTypeMap to get ReturnItemType + String productTypeId = from("Product") + .where(productId: orderItem.productId) + .cache() + .getFieldList("productTypeId") + returnItemTypeMapping = from("ReturnItemTypeMap") + .where(returnItemMapKey: productTypeId, returnHeaderTypeId: returnHeaderTypeId) + .queryOne() + } else { + // if not, try the ReturnItemTypeMap, but this may not actually work, so log a warning + logWarning("Trying to find returnItemtype from ReturnItemTypeMap with orderItemtypeId" + + " [${orderItem.orderItemTypeId} for order item [${orderItem}]") + returnItemTypeMapping = from("ReturnItemTypeMap") + .where(returnItemMapKey: orderItemTypeId, returnHeaderTypeId: returnHeaderTypeId) + .queryOne() + } + if (!returnItemTypeMapping.returnItemTypeId) { + return informError("OrderReturnItemTypeOrderItemNoMatching") + } else { + newItemCtx.returnItemTypeId = returnItemTypeMapping.returnItemTypeId + } + // create the return item + if (newItemCtx.orderAdjustmentId) { + logInfo("Found unexpected orderAdjustment: ${newItemCtx.orderAdjustmentId}") + newItemCtx.orderAdjustmentId = null + } + if (newItemCtx.returnQuantity > (BigDecimal) 0) { + // otherwise, items which have been fully returned would still get passed in and then come back with an error + run service:"createReturnItem", with: newItemCtx + } else { + logInfo("This return item is not going to be created because its returnQuantity is zero: ${newItemCtx}") + } + } + + // create a return adjustment for all order adjustments not attached to a particular orderItem (orderItemSeqId = "_NA_") + List orderAdjustments = from("OrderAdjustment") + .where(orderId: orderHeader.orderId, orderItemSeqId: "_NA_") + .queryList() + for (GenericValue orderAdjustment : orderAdjustments) { + Map returnAdjCtx = [:] + returnAdjCtx.returnId = returnId + // filter out orderAdjustment that have been returned + if (from("ReturnAdjustment").where(orderAdjustmentId: orderAdjustment.orderAdjustmentId).queryCount() == 0) { + logInfo("Create new return adjustment: " + returnAdjCtx) + run service:"createReturnAdjustment", with: returnAdjCtx + } + } + // very important: if countNewReturnItemx is not set, + // getOrderAvailableReturnedTotal would not count the return items we just created + Map orderAvailableCtx = [orderId: orderHeader.orderId, countNewReturnItemx: true] + Map serviceResultART = run service:"getOrderAvailableReturnedTotal", with: orderAvailableCtx + BigDecimal availableReturnTotal = serviceResult.availableReturnTotal + BigDecimal returnTotal = serviceResultART.returnTotal + BigDecimal orderTotal = serviceResultART.orderTotal + logInfo("OrderTotal [${orderTotal}] - ReturnTotal [${returnTotal}] = available Return Total [${}]") + + // create a manual balance adjustment based on the difference between order total and return total + if (availableReturnTotal != (BigDecimal) 0) { + logWarning("Creating a balance adjustment of [" + availableReturnTotal + "] for return [" + returnId + "]") + + // create the balance adjustment return item + run service:"createReturnAdjustment", with: [returnId: returnId, + returnAdjustmentTypeId: "RET_MAN_ADJ", + returnItemSeqId: "_NA_", + description: "Balance Adjustment", + amount: availableReturnTotal] + } + // update the header status + Map updateHeaderCtx = [returnId: returnId] + updateHeaderCtx.statusId = "CUSTOMER_RETURN" == returnHeaderTypeId ? "RETURN_ACCEPTED" : "SUP_RETURN_ACCEPTED" + run service:"updateReturnHeader", with: updateHeaderCtx + + if ("CUSTOMER_RETURN" == returnHeaderTypeId) { + // auto-receive this return if we passed in the flag + if (parameters.receiveReturn) { + run service:"quickReceiveReturn", with: [returnId: returnId] + } else { + // update the header status + logInfo("Receive flag not set; will handle receiving on entity-sync") + } + } + result.returnId = returnId + return result +} + +/** + * If returnId is null, create a return; then create Return Item or Adjustment based on the parameters passed in + * @return + */ +def createReturnAndItemOrAdjustment() { + Map result = success() + if (!parameters.returnId) { + Map serviceResultcRH = run service:"createReturnHeader", with: parameters + if (!ServiceUtil.isSuccess(serviceResultcRH)) { + return serviceResultcRH + } + parameters.returnId = serviceResultcRH.returnId + result.returnId = serviceResultcRH.returnId + } + Map serviceResult = run service:"createReturnItemOrAdjustment", with: parameters + if (!ServiceUtil.isSuccess(serviceResult)) { + return serviceResult + } + result.returnAdjustmentId = serviceResult.returnAdjustmentId + result.returnItemSeqId = serviceResult.returnItemSeqId + return result +} + +/** + * Update a ReturnItems + * @return + */ +def cancelReturnItems() { + List returnItems = from("ReturnItem").where(returnId: parameters.returnId).distinct().queryList() + for (GenericValue returnItem : returnItems) { + run service:"updateReturnItem", with: [returnId: parameters.returnId, + returnItemSeqId: returnItem.returnItemSeqId, + statusId: "RETURN_CANCELLED"] + } + return success() +} + +/** + * Cancel the associated OrderItems of the replacement order, if any. + * @return + */ +def cancelReplacementOrderItems() { + GenericValue returnItem = from("ReturnItems").where(parameters).queryOne() + if ("RTN_REPLACE" == returnItem.returnTypeId + || "RTN_CSREPLACE" == returnItem.returnTypeId + || "RTN_REPAIR_REPLACE" == returnItem.returnTypeId) { + // get the returned order item + GenericValue orderItem = delegator.getRelatedOne("OrderItem", returnItem, false) + // get the order items of the replacement order associated to the returned item + Map oiaMap = [orderItemAssocTypeId: "REPLACEMENT"] + List replacementOrderItems = delegator.getRelated("FromOrderItemAssoc", oiaMap, null, orderItem, false) + for (GenericValue replacementOrderItem : replacementOrderItems) { + run service:"cancelOrderItem", with: [orderId: replacementOrderItem.toOrderId, + orderItemSeqId: replacementOrderItem.toOrderItemSeqId] + } + } + return success() +} + +/** + * Process the replacements in a wait return + * @return + */ +def processWaitReplacementReturn() { + run service: "processReplacementReturn", with: [returnId: parameters.returnId, + returnTypeId: "RTN_REPLACE"] + return success() +} + +/** + * Process the replacements in a cross-ship return + * @return + */ +def processCrossShipReplacementReturn() { + run service:"processReplacementReturn", with: [returnId: parameters.returnId, + returnTypeId: "RTN_CSREPLACE"] + return success() +} + +/** + * Process the replacements in a repair return + * @return + */ +def processRepairReplacementReturn() { + run service:"processReplacementReturn", with: [returnId: parameters.returnId, + returnTypeId: "RTN_REPAIR_REPLACE"] + return success() +} + +/** + * Process the replacements in a wait reserved return when the return is accepted and then received + * @return + */ +def processWaitReplacementReservedReturn() { + GenericValue returnHeader = from("ReturnHeader").where(parameters).queryOne() + if ("RETURN_ACCEPTED" == returnHeader.statusId) { + run service:"processReplacementReturn", with: [returnId: parameters.returnId, + returnTypeId: "RTN_WAIT_REPLACE_RES"] + } + if ("RETURN_RECEIVED" == returnHeader.statusId) { + GenericValue returnItem = from("ReturnItem") + .where(returnId: returnHeader.returnId, + returnTypeId: "RTN_WAIT_REPLACE_RES") + .queryFirst() + if (returnItem) { + // Get the replacement order and update its status to Approved + GenericValue returnItemResponse = delegator.getRelatedOne("ReturnItemResponse", returnItem, false) + GenericValue orderHeader = from("OrderHeader").where(orderId: returnItemResponse.replacementOrderId).queryOne() + if (orderHeader) { + if ("ORDER_HOLD" == orderHeader.statusId) { + run service:"changeOrderStatus", with: [statusId: "ORDER_APPROVED", + orderId: returnItemResponse.replacementOrderId, + setItemStatus: "Y"] + } + if ("ORDER_CANCELLED" == orderHeader.statusId) { + run service:"processReplacementReturn", with: [returnId: parameters.returnId, + returnTypeId: "RTN_WAIT_REPLACE_RES"] + } + } + } + } + return success() +} + +/** + * Process the replacements in a immediate return + * @return + */ +def processReplaceImmediatelyReturn() { + run service: "processReplacementReturn", with: [returnId: parameters.returnId, + returnTypeId: "RTN_REPLACE_IMMEDIAT"] + return success() +} + +/** + * Process the refund in a return + * @return + */ +def processRefundOnlyReturn() { + run service: "processRefundReturn", with: [returnId: parameters.returnId, + returnTypeId: "RTN_REFUND"] + return success() +} + +/** + * Process the Immediate refund in a return + * @return + */ +def processRefundImmediatelyReturn() { + run service:"processRefundReturn", with: [returnId: parameters.returnId, + returnTypeId: "RTN_REFUND_IMMEDIATE"] + return success() +} + +/** + * Get the return status associated with customer vs. vendor return + * @return + */ +def getStatusItemsForReturn() { + Map result = success() + if ("CUSTOMER_RETURN" == parameters.returnHeaderTypeId) { + List statusItems = from("StatusItem").where(statusTypeId: "ORDER_RETURN_STTS").queryList() + result.statusItems = statusItems + } else { + List statusItems = from("StatusItem").where(statusTypeId: "PORDER_RETURN_STTS").queryList() + result.statusItems = statusItems + } + return result +} + +/** + * Associate exchange order with original order in OrderItemAssoc entity + * @return + */ +def createExchangeOrderAssoc() { + List returnItems = from("ReturnItem") + .where(orderId: parameters.originOrderId, + returnTypeId: "RTN_REFUND") + .queryList() + Long returnItemSize = returnItems.size() + List orderItems = from("OrderItem").where(orderId: parameters.orderId).queryList() + Long orderItemSize = orderItems.size() + if (returnItemSize > orderItemSize) { + Long returnItemCounter = (Long) 1 + for (GenericValue returnItem : returnItems) { + Map orderItemAssocMap = [orderId: parameters.originOrderId, orderItemSeqId: returnItem.orderItemSeqId] + Long orderItemCounter = (Long) 1 + for (GenericValue orderItem : orderItems) { + if (returnItemCounter == orderItemCounter) { + orderItemAssocMap.toOrderId = parameters.orderId + orderItemAssocMap.toOrderItemSeqId = orderItem.orderItemSeqId + } else if (returnItemCounter > orderItemSize) { + orderItemAssocMap.toOrderId = parameters.orderId + orderItemAssocMap.toOrderItemSeqId = orderItem.orderItemSeqId + } + orderItemCounter++ + } + orderItemAssocMap.shipGroupSeqId = "_NA_" + orderItemAssocMap.toShipGroupSeqId = "_NA_" + orderItemAssocMap.orderItemAssocTypeId = "EXCHANGE" + GenericValue orderItemAssoc = makeValue("OrderItemAssoc") + orderItemAssoc.setPKFields(orderItemAssocMap) + GenericValue orderItemAssocValue = from("OrderItemAssoc").where(orderItemAssoc).queryOne() + if (!orderItemAssocValue) { + orderItemAssoc.create() + orderItemAssoc = null + } + returnItemCounter++ + } + } else { + Long orderItemCounter = (Long) 1 + for (GenericValue orderItem : orderItems) { + Map orderItemAssocMap = [toOrderId: parameters.orderId, toOrderItemSeqId: orderItem.orderItemSeqId] + Long returnItemCounter = (Long) 1 + for (GenericValue returnItem : returnItems) { + if (orderItemCounter == returnItemCounter) { + orderItemAssocMap.orderId = parameters.originOrderId + orderItemAssocMap.orderItemSeqId = returnItem.orderItemSeqId + } else if (orderItemCounter > returnItemSize) { + orderItemAssocMap.orderId = parameters.originOrderId + orderItemAssocMap.orderItemSeqId = returnItem.orderItemSeqId + } + returnItemCounter++ + } + orderItemAssocMap.shipGroupSeqId = "_NA_" + orderItemAssocMap.toShipGroupSeqId = "_NA_" + orderItemAssocMap.orderItemAssocTypeId = "EXCHANGE" + GenericValue orderItemAssoc = makeValue("OrderItemAsscoc") + orderItemAssoc.setPKFields(orderItemAssocMap) + GenericValue orderItemAssocValue = from("OrderItemAssoc").where(orderItemAssoc).queryOne() + if (!orderItemAssocValue) { + orderItemAssoc.create() + orderItemAssocMap = null + } + orderItemCounter++ + } + } + return success() +} + +/** + * When one or more product is received directly through receive inventory or + * refund return then add these product(s) back to category, + * if they does not have any active category + * @return + */ +def addProductsBackToCategory() { + if (parameters.inventoryItemId) { + GenericValue inventoryItem = from("InventoryItem").where(parameters).queryOne() + GenericValue product = delegator.getRelatedOne("Product", inventoryItem, false) + List productCategoryMembers = delegator.getRelated("ProductCategoryMember", + null, ["-thruDate"], product, false) + // check whether this product is associated to any category, if not just skip + if (productCategoryMembers) { + List pcms = EntityUtil.filterByDate(productCategoryMembers) + // check if this product is associated to any active category, + // if not found then activate the most recent inactive category + if (!pcms) { + Map pcm = [:] + pcm << productCategoryMembers.get(0) + pcm.thruDate = null + run service:"updateProductToCategory", with: pcm + } + } + } else { + if (parameters.returnId) { + List returnItems = from("ReturnItem") + .where(returnId: parameters.returnId, + returnTypeId: "RTN_REFUND") + .queryList() + if (returnItems) { + for (GenericValue returnItem : returnItems) { + GenericValue product = delegator.getRelatedOne("Product", returnItem, false) + List productCategoryMembers = delegator.getRelated("ProductCategoryMember", + null, ["-thruDate"], product, false) + // check whether this product is associated to any category, if not just skip + if (productCategoryMembers) { + List pcms = EntityUtil.filterByDate(productCategoryMembers) + // check if this product is associated to any active category, + // if not found then activate the most recent inactive category + if (!pcms) { + Map pcm = [:] + pcm << productCategoryMembers.get(0) + pcm.thruDate = null + run service:"updateProductToCategory", with: pcm + } + } + } + } + } + } + return success() +} + +/** + * Create ReturnHeader and ReturnItem Status + * @return + */ +def createReturnStatus() { + GenericValue newEntity = makeValue("ReturnStatus") + if (!parameters.returnItemSeqId) { + GenericValue returnHeader = from("ReturnHeader").where(parameters).queryOne() + newEntity.statusId = returnHeader.statusId + } else { + GenericValue returnItem = from("ReturnItem").where(parameters).queryOne() + newEntity.returnItemSeqId = returnItem.returnItemSeqId + newEntity.statusId = returnItem.statusId + } + newEntity.returnStatusId = delegator.getNextSeqId("ReturnStatus") + newEntity.returnId = parameters.returnId + newEntity.changeByUserLoginId = userLogin.userLoginId + newEntity.statusDatetime = UtilDateTime.nowTimestamp() + newEntity.create() + return success() +} + +/** + * Update ReturnContactMech + * @return + */ +def updateReturnContactMech() { + GenericValue returnContactMechMap = makeValue("ReturnContactMech") + returnContactMechMap.setPKFields(parameters) + GenericValue returnHeader = from("ReturnHeader").where(parameters).queryOne() + Map createReturnContactMechMap = [returnId: parameters.returnId, + contactMechPurposeTypeId: parameters.contactMechPurposeTypeId, + contactMechId: parameters.contactMechId] + List returnContactMechList = from("ReturnContactMech").where(createReturnContactMechMap).queryList() + // If returnContactMechList value is null then create new entry in ReturnContactMech entity + if (!returnContactMechList) { + if ("SHIPPING_LOCATION" == parameters.contactMechPurposeTypeId) { + returnHeader.originContactMechId = createReturnContactMechMap.contactMechId + returnHeader.store() + } + run service:"createReturnContactMech", with: createReturnContactMechMap + } + returnContactMechMap.store() + return success() +} + +/** + * Create the return item for rental (which items has product type is ASSET_USAGE_OUT_IN) + * @return + */ +def createReturnItemForRental() { + Map result = success() + GenericValue orderHeader = from("OrderHeader").where(orderId: parameters.orderId).queryOne() + + if ("SALES_ORDER" == orderHeader.orderTypeId) { + GenericValue orderRole = from("OrderRole") + .where(orderId: orderHeader.orderId, + roleTypeId: "BILL_TO_CUSTOMER") + .queryFirst() + GenericValue productStore = delegator.getRelatedOne("ProductStore", orderHeader, false) + + Map createReturnCtx = [:] + if (productStore?.inventoryFacilityId) { + createReturnCtx.destinationFacilityId = productStore.inventoryFacilityId + } + + /* + * changed from minilang since there seems to be no purpose + * + * if (productStore?.reqReturnInventoryReceive) { + * updateHeaderCtx.needsInventoryReceive = productStore.reqReturnInventoryReceive + * } else { + * updateHeaderCtx.needsInventoryReceive = "N" + * } + */ + + createReturnCtx.orderId = orderHeader.orderId + createReturnCtx.currencyUomId = orderHeader.currencyUom + createReturnCtx.fromPartyId = orderRole.partyId + createReturnCtx.toPartyId = productStore.payToPartyId + createReturnCtx.returnHeaderTypeId = "CUSTOMER_RETURN" + createReturnCtx.returnReasonId = "RTN_NORMAL_RETURN" + createReturnCtx.returnTypeId = "RTN_RENTAL" + createReturnCtx.returnItemTypeId = "RET_FDPROD_ITEM" + createReturnCtx.expectedItemStatus = "INV_RETURNED" + createReturnCtx.returnPrice = (BigDecimal) 0 + + List orderItems = from("OrderItemAndProduct") + .where(orderId: orderHeader.orderId, + statusId: "ITEM_COMPLETED", + productTypeId: "ASSET_USAGE_OUT_IN") + .queryList() + for (GenericValue orderItem : orderItems) { + createReturnCtx.productId = orderItem.productId + createReturnCtx.orderItemSeqId = orderItem.orderItemSeqId + createReturnCtx.description = orderItem.itemDescription + createReturnCtx.returnQuantity = orderItem.quantity + Map serviceResult = run service:"createReturnAndItemOrAdjustment", with: createReturnCtx + String returnId = serviceResult.returnId + if (returnId) { + createReturnCtx.returnId = returnId + // changed from minilang: added returnId to result since it's a required outgoing parameter + result.returnId = returnId + } + } + } + return result +} + +def private informError(String label) { + String errorMessage = UtilProperties.getMessage("OrderErrorUiLabels", label, parameters.locale) + logError(errorMessage) + return error(errorMessage) +} diff --git a/applications/order/minilang/order/OrderReturnServices.xml b/applications/order/minilang/order/OrderReturnServices.xml deleted file mode 100644 index 1786c0d..0000000 --- a/applications/order/minilang/order/OrderReturnServices.xml +++ /dev/null @@ -1,1186 +0,0 @@ -<?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. ---> - -<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns="http://ofbiz.apache.org/Simple-Method" xsi:schemaLocation="http://ofbiz.apache.org/Simple-Method http://ofbiz.apache.org/dtds/simple-methods.xsd"> - <simple-method method-name="createReturnHeader" short-description="Create a ReturnHeader"> - <now-timestamp field="nowTimestamp"/> - - <if> - <condition> - <and> - <not><if-has-permission permission="ORDERMGR" action="_CREATE"/></not> - <not><if-compare-field field="userLogin.partyId" to-field="parameters.fromPartyId" operator="equals"/></not> - </and> - </condition> - <then> - <add-error><fail-property resource="OrderErrorUiLabels" property="OrderSecurityErrorToRunCreateReturnHeader"/></add-error> - </then> - </if> - <set field="returnHeaderTypeId" from-field="parameters.returnHeaderTypeId"/> - <if-empty field="parameters.toPartyId"> - <!-- no toPartyId was specified. use destination facility to determine the party of the return --> - <if-compare field="returnHeaderTypeId" operator="equals" value="CUSTOMER_RETURN"> - <if-not-empty field="parameters.destinationFacilityId"> - <entity-one entity-name="Facility" value-field="destinationFacility" auto-field-map="false"> - <field-map field-name="facilityId" from-field="parameters.destinationFacilityId"/> - </entity-one> - <set from-field="destinationFacility.ownerPartyId" field="parameters.toPartyId"/> - </if-not-empty> - </if-compare> - <else> - <!-- make sure that the party to return to is an INTERNAL_ORGANIZATIO for customer return and SUPPLIER for vendor return else stop --> - <if-compare field="returnHeaderTypeId" operator="contains" value="CUSTOMER_"> - <entity-one entity-name="PartyRole" value-field="partyRole" use-cache="true" auto-field-map="false"> - <field-map field-name="partyId" from-field="parameters.toPartyId"/> - <field-map field-name="roleTypeId" value="INTERNAL_ORGANIZATIO"/> - </entity-one> - <if-empty field="partyRole"> - <add-error> - <fail-property resource="OrderErrorUiLabels" property="OrderReturnRequestPartyRoleInternalOrg"/> - </add-error> - </if-empty> - <else> - <entity-one entity-name="PartyRole" value-field="partyRole" use-cache="true" auto-field-map="false"> - <field-map field-name="partyId" from-field="parameters.toPartyId"/> - <field-map field-name="roleTypeId" value="SUPPLIER"/> - </entity-one> - <if-empty field="partyRole"> - <add-error> - <fail-property resource="OrderErrorUiLabels" property="OrderReturnRequestPartyRoleSupplier"/> - </add-error> - </if-empty> - </else> - </if-compare> - </else> - </if-empty> - <if-not-empty field="parameters.paymentMethodId"> - <entity-one entity-name="PaymentMethod" value-field="paymentMethod" use-cache="true" auto-field-map="false"> - <field-map field-name="paymentMethodId" from-field="parameters.paymentMethodId"/> - </entity-one> - <if-empty field="paymentMethod"> - <add-error> - <fail-property resource="OrderErrorUiLabels" property="OrderReturnRequestPaymentMethodId"/> - </add-error> - </if-empty> - </if-not-empty> - <check-errors/> - - <!-- check the needs (auto) inventory receive flag (default to N, meaning that return won't automatically be considered Received when Accepted) --> - <if-empty field="parameters.needsInventoryReceive"> - <set field="parameters.needsInventoryReceive" value="N"/> - </if-empty> - - <make-value entity-name="ReturnHeader" value-field="newEntity"/> - <set-nonpk-fields map="parameters" value-field="newEntity"/> - - <!-- If PartyAcctgPreference.useInvoiceIdForReturns is Y, get the ID from the getNextInvoiceId service --> - <set field="partyAccountingPreferencesCallMap.organizationPartyId" from-field="parameters.toPartyId"/> - <set field="systemMap.userLoginId" value="system"/> - <find-by-primary-key entity-name="UserLogin" map="systemMap" value-field="systemLogin"/> - <set field="partyAccountingPreferencesCallMap.userLogin" from-field="systemLogin"/> - <call-service service-name="getPartyAccountingPreferences" in-map-name="partyAccountingPreferencesCallMap"> - <result-to-field result-name="partyAccountingPreference" field="partyAcctgPreference"/> - </call-service> - <if-compare field="partyAcctgPreference.useInvoiceIdForReturns" operator="equals" value="Y"> - <set field="getNextInvoiceIdMap.partyId" from-field="parameters.toPartyId"/> - <call-service service-name="getNextInvoiceId" in-map-name="getNextInvoiceIdMap"> - <result-to-field result-name="invoiceId" field="newEntity.returnId"/> - </call-service> - - <else> - <sequenced-id sequence-name="ReturnHeader" field="newEntity.returnId"/> - </else> - </if-compare> - <field-to-result field="newEntity.returnId" result-name="returnId"/> - - <if> - <condition> - <not><if-has-permission permission="ORDERMGR" action="_CREATE"/></not> - </condition> - <then> - <if-compare field="returnHeaderTypeId" operator="equals" value="CUSTOMER_RETURN"> - <set field="newEntity.statusId" value="RETURN_REQUESTED"/> - <else> - <set field="newEntity.statusId" value="SUP_RETURN_REQUESTED"/> - </else> - </if-compare> - <set from-field="nowTimestamp" field="newEntity.entryDate"/> - </then> - </if> - - <if-empty field="newEntity.entryDate"> - <set from-field="nowTimestamp" field="newEntity.entryDate"/> - </if-empty> - - <if-empty field="newEntity.statusId"> - <if-compare field="returnHeaderTypeId" operator="equals" value="CUSTOMER_RETURN"> - <set field="newEntity.statusId" value="RETURN_REQUESTED"/> - <else> - <set field="newEntity.statusId" value="SUP_RETURN_REQUESTED"/> - </else> - </if-compare> - </if-empty> - <set field="newEntity.createdBy" from-field="userLogin.userLoginId"/> - - <create-value value-field="newEntity"/> - <set field="responseMessage" value="Return Request #${newEntity.returnId} was created successfully."/> - <field-to-result field="responseMessage" result-name="successMessage"/> - </simple-method> - <simple-method method-name="updateReturnHeader" short-description="Update a ReturnHeader"> - <entity-one entity-name="ReturnHeader" value-field="returnHeader"/> - - <!-- test the total return amount vs the total order amount --> - <if-compare field="parameters.statusId" value="RETURN_ACCEPTED" operator="equals"> - <!-- get the list of ReturnItems. Note: return may be associated with many different orders --> - <entity-condition entity-name="ReturnItem" list="returnItems" distinct="true"> - <condition-expr field-name="returnId" from-field="returnHeader.returnId"/> - </entity-condition> - - <!-- this block is for debugging and can be removed later --> - <!-- - <log level="verbose" message="Items and adjustments for return ${returnHeader.returnId}"/> - <entity-condition entity-name="ReturnAdjustment" list="returnAdjustments" distinct="true"> - <condition-expr field-name="returnId" operator="equals" from-field="returnHeader.returnId"/> - </entity-condition> - <iterate list="returnItems" entry="returnItem"> - <log level="verbose" message="item: ${returnItem.returnItemSeqId} ${returnItem.returnItemTypeId} [${returnItem.description}] ${returnItem.productId} ${returnItem.returnQuantity} ${returnItem.returnPrice}"/> - </iterate> - <iterate list="returnAdjustments" entry="returnAdjustment"> - <log level="verbose" message="adjustment: ${returnAdjustment.returnItemSeqId} ${returnAdjustment.returnAdjustmentTypeId} [${returnAdjustment.description}] ${returnAdjustment.amount}"/> - </iterate> - --> - <!-- end debugging block --> - - <!-- this is used to make sure we don't return a negative amount --> - <calculate field="returnTotalAmount"><number value="0.0"/></calculate> - - <!-- check them all to make sure that the return total does not exceed order total. --> - <iterate list="returnItems" entry="returnItem"> - <!-- check, for cross-ship returns, if a payment method is set to guarantee the cross-shipped item(s).. --> - <if> - <condition> - <and> - <if-empty field="returnHeader.paymentMethodId"/> - <if-empty field="parameters.paymentMethodId"/><!-- because we haven't done the set-nonpk-fields yet, check this too --> - <or> - <if-compare field="returnItem.returnTypeId" operator="equals" value="RTN_CSREPLACE"/> - <if-compare field="returnItem.returnTypeId" operator="equals" value="RTN_REPAIR_REPLACE"/> - </or> - </and> - </condition> - <then> - <add-error><fail-property resource="OrderErrorUiLabels" property="OrderReturnPaymentMethodNeededForThisTypeOfReturn"/></add-error> - </then> - </if> - <check-errors/> - <!-- tally up the return total amount --> - <calculate field="returnTotalAmount"> - <calcop operator="add" field="returnTotalAmount"> - <calcop operator="multiply"> - <calcop operator="get" field="returnItem.returnPrice"/> - <calcop operator="get" field="returnItem.returnQuantity"/> - </calcop> - </calcop> - </calculate> - - <!-- compare return vs order total --> - <if-not-empty field="returnItem.orderId"> - <set field="returnTotalCtx.orderId" from-field="returnItem.orderId"/> - <!-- no adjustment needed: adjustment is passed in to calculate the effect of an additional item on return total. --> - <calculate field="returnTotalCtx.adjustment" type="BigDecimal"><number value="0.0"/></calculate> - <call-service service-name="getOrderAvailableReturnedTotal" in-map-name="returnTotalCtx"> - <result-to-field result-name="availableReturnTotal" field="availableReturnTotal"/> - <result-to-field result-name="returnTotal" field="returnTotal"/> - <result-to-field result-name="orderTotal" field="orderTotal"/> - </call-service> - <log level="info" message="Available amount for return on order #${returnItem.orderId} is [${availableReturnTotal}] (orderTotal = [${orderTotal}] - returnTotal = [${returnTotal}]"/> - - <if-compare field="availableReturnTotal" operator="less" value="-0.01" type="BigDecimal"> - <add-error><fail-property resource="OrderErrorUiLabels" property="OrderReturnPriceCannotExceedTheOrderTotal"/></add-error> - </if-compare> - <check-errors/> - <else> - <log level="info" message="Not an order based returnItem; unable to check valid amounts!"/> - </else> - </if-not-empty> - </iterate> - <!-- Checking that the Status change is Valid or Not--> - <if> - <condition> - <and> - <not><if-empty field="parameters.statusId"></if-empty></not> - <if-compare-field operator="not-equals" field="parameters.statusId" to-field="returnHeader.statusId"/> - </and> - </condition> - <then> - <set field="statusIdTo" from-field="parameters.statusId"/> - <set field="statusId" from-field="returnHeader.statusId"/> - <entity-one entity-name="StatusValidChange" value-field="statusValidChange"/> - <if-empty field="statusValidChange"> - <add-error><fail-property resource="OrderErrorUiLabels" property="OrderErrorReturnHeaderItemStatusNotChangedIsNotAValidChange"/></add-error> - </if-empty> - <check-errors/> - </then> - </if> - <entity-and entity-name="ReturnAdjustment" list="returnAdjustments"> - <field-map field-name="returnId" from-field="returnHeader.returnId"/> - </entity-and> - <iterate list="returnAdjustments" entry="returnAdjustment"> - <calculate field="returnTotalAmount"> - <calcop operator="add" field="returnTotalAmount"> - <calcop operator="get" field="returnAdjustment.amount"/> - </calcop> - </calculate> - </iterate> - <if-compare field="returnTotalAmount" operator="less" value="0" type="BigDecimal"> - <add-error><fail-property resource="OrderErrorUiLabels" property="OrderReturnTotalCannotLessThanZero"/></add-error> - </if-compare> - <check-errors/> - </if-compare> - - <field-to-result field="returnHeader.statusId" result-name="oldStatusId"/> - <set-nonpk-fields map="parameters" value-field="returnHeader"/> - <store-value value-field="returnHeader"/> - </simple-method> - - <simple-method method-name="createReturnItem" short-description="Create Return Item"> - - <set field="lookupPKMap.returnId" from-field="parameters.returnId"/> - <find-by-primary-key entity-name="ReturnHeader" map="lookupPKMap" value-field="returnHeader"/> - - <if> - <condition> - <and> - <not> - <if-has-permission permission="ORDERMGR" action="_CREATE"/> - </not> - <not> - <if-compare-field field="userLogin.partyId" to-field="returnHeader.fromPartyId" operator="equals"/> - </not> - </and> - </condition> - <then> - <add-error> - <fail-property resource="OrderErrorUiLabels" property="OrderSecurityErrorToRunCreateReturnItem"/> - </add-error> - </then> - </if> - <check-errors/> - - <if-empty field="parameters.returnItemTypeId"> - <add-error> - <fail-property resource="OrderErrorUiLabels" property="OrderReturnItemTypeIsNotDefined"/> - </add-error> - <check-errors/> - </if-empty> - - <if> - <condition> - <and> - <if-empty field="returnHeader.paymentMethodId"/> - <if-compare field="returnHeader.statusId" operator="equals" value="RETURN_ACCEPTED"/> - <or> - <if-compare field="parameters.returnTypeId" operator="equals" value="RTN_CSREPLACE"/> - <if-compare field="parameters.returnTypeId" operator="equals" value="RTN_REPAIR_REPLACE"/> - </or> - </and> - </condition> - <then> - <add-error> - <fail-property resource="OrderErrorUiLabels" property="OrderReturnPaymentMethodNeededForThisTypeOfReturn"/> - </add-error> - </then> - </if> - <check-errors/> - - <if-compare field="parameters.returnQuantity" operator="equals" value="0" type="BigDecimal"> - <add-error> - <fail-property resource="OrderErrorUiLabels" property="OrderNoReturnQuantityAvailablePreviousReturnsMayExist"/> - </add-error> - <check-errors/> - </if-compare> - - <!-- setup some default values for protection --> - <set field="returnableQuantity" value="0" type="BigDecimal"/> - <set field="returnablePrice" value="0" type="BigDecimal"/> - - <!-- if an orderItemSeqId is provided, then find the corresponding orderItem --> - <if-not-empty field="parameters.orderItemSeqId"> - <make-value entity-name="OrderItem" value-field="itemLookup"/> - <set-pk-fields map="parameters" value-field="itemLookup"/> - <if-not-empty field="parameters.orderItemSeqId"> - <find-by-primary-key entity-name="OrderItem" value-field="orderItem" map="itemLookup"/> - <log level="info" message="Return item is an OrderItem - ${orderItem.orderItemSeqId}"/> - </if-not-empty> - </if-not-empty> - - <!-- get the returnableQuantity and returnablePrice: - for orderItems, it's found by getReturnableQuantity; - for adjustments, either order adjustments or manual adjustments, it's always 1 and based on input parameter --> - <if-not-empty field="orderItem"> - <set field="serviceContext.orderItem" from-field="orderItem"/> - <call-service service-name="getReturnableQuantity" in-map-name="serviceContext"> - <result-to-field result-name="returnableQuantity" field="returnableQuantity"/> - <result-to-field result-name="returnablePrice" field="returnablePrice"/> - </call-service> - </if-not-empty> - - <if-compare field="returnableQuantity" value="0" operator="greater" type="BigDecimal"> - <!-- the user is only allowed to set a returnPrice if he has ORDERMGR_CREATE privilege, otherwise only the returnablePrice calculated by service is used --> - <if> - <condition> - <not> - <if-has-permission permission="ORDERMGR" action="_CREATE"/> - </not> - </condition> - <then> - <set from-field="returnablePrice" field="parameters.returnPrice"/> - </then> - </if> - - <!-- make sure the returnQuantity is not greater than the returnableQuantity from service or the quantity on the original orderItem --> - <if-compare-field field="parameters.returnQuantity" to-field="returnableQuantity" operator="greater" type="BigDecimal"> - <add-error> - <fail-property resource="OrderErrorUiLabels" property="OrderRequestedReturnQuantityNotAvailablePreviousReturnsMayExist"/> - </add-error> - </if-compare-field> - <if-not-empty field="orderItem"> - <if-compare-field field="parameters.returnQuantity" to-field="orderItem.quantity" operator="greater" type="BigDecimal"> - <add-error> - <fail-property resource="OrderErrorUiLabels" property="OrderReturnQuantityCannotExceedTheOrderedQuantity"/> - </add-error> - </if-compare-field> - </if-not-empty> - <if-compare-field field="parameters.returnPrice" to-field="returnablePrice" operator="greater" type="BigDecimal"> - <add-error> - <fail-property resource="OrderErrorUiLabels" property="OrderReturnPriceCannotExceedThePurchasePrice"/> - </add-error> - </if-compare-field> - <check-errors/> - - <else> - <set from-field="parameters.orderId" field="orderId"/> - <set from-field="parameters.orderItemSeqId" field="orderItemSeqId"/> - <log level="error" message="Order ${orderId} item ${orderItemSeqId} has been returned in full"/> - <add-error> - <fail-property resource="OrderErrorUiLabels" property="OrderIllegalReturnItemTypePassed"/> - </add-error> - <check-errors/> - </else> - </if-compare> - - <make-value entity-name="ReturnItem" value-field="newEntity"/> - <set from-field="parameters.returnId" field="newEntity.returnId"/> - <make-next-seq-id seq-field-name="returnItemSeqId" value-field="newEntity"/> - <set-nonpk-fields map="parameters" value-field="newEntity"/> - <set field="newEntity.statusId" value="RETURN_REQUESTED"/> <!-- default status for new return items --> - <field-to-result field="newEntity.returnItemSeqId" result-name="returnItemSeqId"/> - <create-value value-field="newEntity"/> - <refresh-value value-field="newEntity"/> - - <if> - <condition> - <or> - <if-empty field="parameters.includeAdjustments"/> - <if-compare field="parameters.includeAdjustments" operator="equals" value="Y"/> - </or> - </condition> - <then> - <!-- create return adjustments for all adjustments associated with the order item --> - <if-not-empty field="orderItem"> - <get-related value-field="orderItem" relation-name="OrderAdjustment" list="orderAdjustments"/> - <iterate list="orderAdjustments" entry="orderAdjustment"> - <clear-field field="returnAdjCtx"/> - <set field="returnAdjCtx.returnId" from-field="parameters.returnId"/> - <set field="returnAdjCtx.returnItemSeqId" from-field="newEntity.returnItemSeqId"/> - <set field="returnAdjCtx.returnTypeId" from-field="newEntity.returnTypeId"/> - <set field="returnAdjCtx.orderAdjustmentId" from-field="orderAdjustment.orderAdjustmentId"/> - <call-service service-name="createReturnAdjustment" in-map-name="returnAdjCtx"/> - </iterate> - </if-not-empty> - </then> - </if> - - </simple-method> - - <simple-method method-name="updateReturnItem" short-description="Update Return Item"> - <set from-field="parameters.returnId" field="lookupPKMap.returnId"/> - <set from-field="parameters.returnItemSeqId" field="lookupPKMap.returnItemSeqId"/> - <find-by-primary-key entity-name="ReturnItem" map="lookupPKMap" value-field="returnItem"/> - <set field="originalReturnPrice" from-field="returnItem.returnPrice"/> - <set field="originalReturnQuantity" from-field="returnItem.returnQuantity"/> - <field-to-result field="returnItem.statusId" result-name="oldStatusId"/> - - <set-nonpk-fields map="parameters" value-field="returnItem"/> - <store-value value-field="returnItem"/> - <refresh-value value-field="returnItem"/> - - <!-- now update all return adjustments associated with this return item --> - <entity-and entity-name="ReturnAdjustment" list="returnAdjustments"> - <field-map field-name="returnId" from-field="returnItem.returnId"/> - <field-map field-name="returnItemSeqId" from-field="returnItem.returnItemSeqId"/> - </entity-and> - <iterate list="returnAdjustments" entry="returnAdjustment"> - <log level="info" message="updating returnAdjustment with Id:[${returnAdjustment.returnAdjustmentId}]"/> - <set-service-fields service-name="updateReturnAdjustment" map="returnAdjustment" to-map="ctx"/> - <set field="ctx.originalReturnPrice" from-field="originalReturnPrice"/> - <set field="ctx.originalReturnQuantity" from-field="originalReturnQuantity"/> - <set field="ctx.returnTypeId" from-field="returnItem.returnTypeId"/> - <call-service service-name="updateReturnAdjustment" in-map-name="ctx" include-user-login="true"/> - </iterate> - - </simple-method> - <simple-method method-name="updateReturnItemsStatus" short-description="Update Return Items Status"> - <set from-field="parameters.returnId" field="lookupPKMap.returnId"/> - <find-by-and entity-name="ReturnItem" map="lookupPKMap" list="returnItems"/> - <iterate list="returnItems" entry="item"> - <set field="item.statusId" from-field="parameters.statusId"/> - <set-service-fields service-name="updateReturnItem" map="item" to-map="serviceInMap"/> - <call-service service-name="updateReturnItem" in-map-name="serviceInMap"/> - <clear-field field="serviceInMap"/> - <clear-field field="item"/> - </iterate> - </simple-method> - <simple-method method-name="removeReturnItem" short-description="Remove Return Item"> - <entity-one entity-name="ReturnHeader" value-field="returnHeader"/> - <if-compare field="returnHeader.returnHeaderTypeId" operator="equals" value="CUSTOMER_RETURN"> - <if-compare field="returnHeader.statusId" operator="not-equals" type="String" value="RETURN_REQUESTED"> - <add-error><fail-property resource="OrderErrorUiLabels" property="OrderCannotRemoveItemsOnceReturnIsApproved"/></add-error> - </if-compare> - <else> - <if-compare field="returnHeader.statusId" operator="not-equals" type="String" value="SUP_RETURN_REQUESTED"> - <add-error><fail-property resource="OrderErrorUiLabels" property="OrderCannotRemoveItemsOnceReturnIsApproved"/></add-error> - </if-compare> - </else> - </if-compare> - <check-errors/> - - <set from-field="parameters.returnId" field="lookupPKMap.returnId"/> - <set from-field="parameters.returnItemSeqId" field="lookupPKMap.returnItemSeqId"/> - <find-by-primary-key entity-name="ReturnItem" map="lookupPKMap" value-field="returnItem"/> - <!--remove related adjustments--> - <entity-and entity-name="ReturnAdjustment" list="returnAdjustments"> - <field-map field-name="returnItemSeqId" from-field="returnItem.returnItemSeqId"/> - <field-map field-name="returnId" from-field="returnItem.returnId"/> - </entity-and> - <iterate list="returnAdjustments" entry="returnAdjustment"> - <set field="removeCtx.returnAdjustmentId" from-field="returnAdjustment.returnAdjustmentId"/> - <call-service service-name="removeReturnAdjustment" in-map-name="removeCtx"/> - </iterate> - <remove-value value-field="returnItem"/> - </simple-method> - - <simple-method method-name="createReturnAdjustment" short-description="Create Return Adjustment"> - <if> - <condition> - <not><if-has-permission permission="ORDERMGR" action="_CREATE"/></not> - </condition> - <then> - <add-error> - <fail-property resource="OrderErrorUiLabels" property="OrderErrorCreatePermissionError"/> - </add-error> - </then> - </if> - <check-errors/> - - <make-value entity-name="ReturnAdjustment" value-field="newEntity"/> - <set-nonpk-fields map="parameters" value-field="newEntity"/> - <sequenced-id sequence-name="ReturnAdjustment" field="newEntity.returnAdjustmentId"/> - <field-to-result field="newEntity.returnAdjustmentId" result-name="returnAdjustmentId"/> - <create-value value-field="newEntity"/> - <set field="responseMessage" value="Return Adjustment #${newEntity.returnAdjustmentId} was created successfully."/> - <field-to-result field="responseMessage" result-name="successMessage"/> - </simple-method> - <simple-method method-name="removeReturnAdjustment" short-description="Remove Return Adjustment"> - <set from-field="parameters.returnAdjustmentId" field="lookupPKMap.returnAdjustmentId"/> - <find-by-primary-key entity-name="ReturnAdjustment" map="lookupPKMap" value-field="returnAdjustment"/> - <if-not-empty field="returnAdjustment"> - <remove-value value-field="returnAdjustment"/> - </if-not-empty> - </simple-method> - <!-- note that this service is designed to be called once for each shipment receipt that is created --> - <simple-method method-name="updateReturnStatusFromReceipt" short-description="Update Return Status From ShipmentReceipt"> - <set from-field="parameters.returnId" field="lookupPKMap.returnId"/> - <find-by-primary-key entity-name="ReturnHeader" map="lookupPKMap" value-field="returnHeader"/> - <find-by-and entity-name="ShipmentReceipt" map="lookupPKMap" list="shipmentReceipts"/> - <iterate list="shipmentReceipts" entry="receipt"> - <if-empty field="totalsMap[receipt.returnItemSeqId]"> - <set field="totalsMap[receipt.returnItemSeqId]" value="0" type="BigDecimal"/> - </if-empty> - <set field="totalsMap[receipt.returnItemSeqId]" from="totalsMap[receipt.returnItemSeqId] + (receipt.quantityAccepted + receipt.quantityRejected)"/> - </iterate> - <get-related relation-name="ReturnItem" list="returnItems" value-field="returnHeader"/> - <iterate-map key="returnItemSeqId" value="value" map="totalsMap"> - <set field="filterMap.returnItemSeqId" from="returnItemSeqId"/> - <filter-list-by-and list="returnItems" map="filterMap" to-list="items"/> - <first-from-list list="items" entry="item"/> - <set field="item.receivedQuantity" from="value" type="BigDecimal"/> - <set-service-fields service-name="updateReturnItem" map="item" to-map="serviceInMap"/> - <if-compare-field field="value" to-field="item.returnQuantity" operator="greater-equals" type="BigDecimal"> - <!-- update the status for the item --> - <set field="serviceInMap.statusId" value="RETURN_RECEIVED"/> - </if-compare-field> - - <!-- update the returnItem with at least receivedQuantity, and also statusId if applicable --> - <call-service service-name="updateReturnItem" in-map-name="serviceInMap"/> - <clear-field field="serviceInMap"/> - <clear-field field="filterMap"/> - </iterate-map> - <!-- check to see if all items have been received --> - <set field="allReceived" value="true"/> - <find-by-and entity-name="ReturnItem" map="lookupPKMap" list="allReturnItems"/> - <iterate list="allReturnItems" entry="item"> - <if-compare field="item.statusId" operator="not-equals" value="RETURN_RECEIVED"> - <if-not-empty field="item.orderItemSeqId"> - <!-- non-order items (i.e. adjustments) are not received --> - <set value="false" field="allReceived"/> - </if-not-empty> - </if-compare> - </iterate> - - <!-- if the items are all received, then update the return header, store the status history change, and set the shipment to received --> - <if-compare field="allReceived" operator="equals" value="true"> - - <!-- Go through all the items yet again and set their shipment status to PURCH_SHIP_RECEIVED (if it isn't already) - This activates SECAS such as creating return invoices. This MUST be done before updating the return header so that - the ReturnItemBillings are created and then whatever SECA binds to the return header update will have them. . --> - <iterate list="shipmentReceipts" entry="receipt"> - <get-related-one relation-name="Shipment" value-field="receipt" to-value-field="shipment"/> - <if-not-empty field="shipment.shipmentId"> - <if-compare field="shipment.statusId" operator="not-equals" value="RETURN_RECEIVED"> - <set field="serviceInput.shipmentId" from-field="shipment.shipmentId"/> - <set field="serviceInput.statusId" value="PURCH_SHIP_RECEIVED"/> - <call-service service-name="updateShipment" in-map-name="serviceInput"/> - </if-compare> - </if-not-empty> - </iterate> - - <!-- update the return header --> - <set field="returnHeaderCtx.statusId" value="RETURN_RECEIVED"/> - <set from-field="returnHeader.returnId" field="returnHeaderCtx.returnId"/> - <call-service service-name="updateReturnHeader" in-map-name="returnHeaderCtx"/> - </if-compare> - - <!-- return the current return header status --> - <field-to-result field="returnHeader.statusId" result-name="returnHeaderStatus"/> - </simple-method> - - <simple-method method-name="quickReturnFromOrder" short-description="Create Quick Return From Order"> - <if> - <condition> - <and> - <not><if-has-permission permission="ORDERMGR" action="_CREATE"/></not> - <not><if-compare-field field="userLogin.partyId" to-field="parameters.fromPartyId" operator="equals"/></not> - </and> - </condition> - <then> - <add-error><fail-property resource="OrderErrorUiLabels" property="OrderSecurityErrorToRunQuickReturnFromOrder"/></add-error> - </then> - </if> - <check-errors/> - - <!-- get primary information from the order header --> - <entity-one entity-name="OrderHeader" value-field="orderHeader"> - <field-map field-name="orderId" from-field="parameters.orderId"/> - </entity-one> - <set field="returnHeaderTypeId" from-field="parameters.returnHeaderTypeId"/> - <if-compare field="returnHeaderTypeId" operator="equals" value="CUSTOMER_RETURN"> - <set field="roleTypeId" value="BILL_TO_CUSTOMER"/> - <else> - <set field="roleTypeId" value="BILL_FROM_VENDOR"/> - </else> - </if-compare> - - <!-- find the bill to customer; for return's fromPartyId --> - <entity-condition entity-name="OrderRole" list="orderRoles"> - <condition-list combine="and"> - <condition-expr field-name="orderId" operator="equals" from-field="orderHeader.orderId"/> - <condition-expr field-name="roleTypeId" operator="equals" from-field="roleTypeId"/> - </condition-list> - </entity-condition> - <first-from-list list="orderRoles" entry="orderRole"/> - <!-- create the return header --> - <set from-field="orderHeader.originFacilityId" field="createHeaderCtx.destinationFacilityId"/> - <set value="Y" field="updateHeaderCtx.needsInventoryReceive"/> - <set from-field="returnHeaderTypeId" field="createHeaderCtx.returnHeaderTypeId"/> - - <!-- get the return to party for customer return and return from party for vendor return from the product store --> - <get-related-one relation-name="ProductStore" value-field="orderHeader" to-value-field="productStore"/> - <if-compare field="returnHeaderTypeId" operator="equals" value="CUSTOMER_RETURN"> - <set field="createHeaderCtx.fromPartyId" from-field="orderRole.partyId"/> - <set field="createHeaderCtx.toPartyId" from-field="productStore.payToPartyId"/> - <if-empty field="createHeaderCtx.destinationFacilityId"> - <set field="createHeaderCtx.destinationFacilityId" from-field="productStore.inventoryFacilityId"/> - </if-empty> - <else> - <set field="createHeaderCtx.fromPartyId" from-field="productStore.payToPartyId"/> - <set field="createHeaderCtx.toPartyId" from-field="orderRole.partyId"/> - </else> - </if-compare> - <!-- copy over the currency of the order to the currency of the return --> - <set from-field="orderHeader.currencyUom" field="createHeaderCtx.currencyUomId"/> - - <call-service service-name="createReturnHeader" in-map-name="createHeaderCtx" include-user-login="true"> - <result-to-field result-name="returnId"/> - </call-service> - - <!-- get the available to return order items --> - <entity-condition entity-name="OrderItem" list="orderItems"> - <condition-list combine="and"> - <condition-expr field-name="orderId" operator="equals" from-field="orderHeader.orderId"/> - <condition-expr field-name="statusId" operator="equals" value="ITEM_COMPLETED"/> - </condition-list> - </entity-condition> - - <if-empty field="parameters.returnReasonId"> - <set value="RTN_NOT_WANT" field="parameters.returnReasonId"/> - </if-empty> - <if-empty field="parameters.returnTypeId"> - <set value="RTN_REFUND" field="parameters.returnTypeId"/> - </if-empty> - - <!-- create the return items --> - <iterate list="orderItems" entry="orderItem"> - <set from-field="returnId" field="newItemCtx.returnId"/> - <set from-field="parameters.returnReasonId" field="newItemCtx.returnReasonId"/> - <set from-field="parameters.returnTypeId" field="newItemCtx.returnTypeId"/> - - <if-not-empty field="orderItem.productId"> - <set from-field="orderItem.productId" field="newItemCtx.productId"/> - </if-not-empty> - - <set from-field="orderItem.orderId" field="newItemCtx.orderId"/> - <set from-field="orderItem.orderItemSeqId" field="newItemCtx.orderItemSeqId"/> - <set from-field="orderItem.itemDescription" field="newItemCtx.description"/> - - <!-- get the returnable price and quantity --> - <set from-field="orderItem" field="itemCheckMap.orderItem"/> - <call-service service-name="getReturnableQuantity" in-map-name="itemCheckMap"> - <result-to-field result-name="returnableQuantity" field="newItemCtx.returnQuantity"/> - <result-to-field result-name="returnablePrice" field="newItemCtx.returnPrice"/> - </call-service> - - <!-- get the matching return item type from the order item type --> - - <set from-field="orderItem.orderItemTypeId" field="orderItemTypeId"/> - <if-compare field="orderItemTypeId" value="PRODUCT_ORDER_ITEM" operator="equals"> - <!-- Check if orderItemTypeId equals PRODUCT_ORDER_ITEM, if so, use ProductType and ReturnItemTypeMap to get ReturnItemType--> - <entity-one entity-name="Product" value-field="product"> - <field-map field-name="productId" from-field="orderItem.productId"/> - <select-field field-name="productTypeId"/> - </entity-one> - <entity-one entity-name="ReturnItemTypeMap" value-field="returnItemTypeMapping"> - <field-map field-name="returnItemMapKey" from-field="product.productTypeId"/> - <field-map field-name="returnHeaderTypeId" from-field="returnHeaderTypeId"/> - </entity-one> - <else> - <!-- if not, try the ReturnItemTypeMap, but this may not actually work, so log a warning --> - <log level="warning" message="Trying to find returnItemtype from ReturnItemTypeMap with orderItemtypeId [${orderItem.orderItemTypeId}] for order item [${orderItem}]"/> - <entity-one entity-name="ReturnItemTypeMap" value-field="returnItemTypeMapping"> - <field-map field-name="returnItemMapKey" from-field="orderItemTypeId"/> - <field-map field-name="returnHeaderTypeId" from-field="returnHeaderTypeId"/> - </entity-one> - </else> - </if-compare> - - <if-empty field="returnItemTypeMapping.returnItemTypeId"> - <add-error> - <fail-property resource="OrderErrorUiLabels" property="OrderReturnItemTypeOrderItemNoMatching"/> - </add-error> - <check-errors/> - <else> - <set from-field="returnItemTypeMapping.returnItemTypeId" field="newItemCtx.returnItemTypeId"/> - </else> - </if-empty> - - <!-- create the return item --> - <if-not-empty field="newItemCtx.orderAdjustmentId"> - <log level="info" message="Found unexpected orderAdjustment:${newItemCtx.orderAdjustmentId}"/> - <clear-field field="newItemCtx.orderAdjustmentId"/> - </if-not-empty> - <if-compare field="newItemCtx.returnQuantity" value="0" operator="greater" type="BigDecimal"> - <!-- otherwise, items which have been fully returned would still get passed in and then come back with an error --> - <call-service service-name="createReturnItem" in-map-name="newItemCtx" include-user-login="true"/> - <else> - <log level="info" message="This return item is not going to be created because its returnQuantity is zero: ${newItemCtx}"/> - </else> - </if-compare> - </iterate> - - <!-- create a return adjustment for all order adjustments not attached to a particular orderItem (orderItemSeqId = "_NA_") --> - <entity-condition entity-name="OrderAdjustment" list="orderAdjustments"> - <condition-list combine="and"> - <condition-expr field-name="orderId" operator="equals" from-field="orderHeader.orderId"/> - <condition-expr field-name="orderItemSeqId" operator="equals" value="_NA_"/> - </condition-list> - </entity-condition> - <iterate list="orderAdjustments" entry="orderAdjustment"> - <clear-field field="returnAdjCtx"/> - <set from-field="orderAdjustment.orderAdjustmentId" field="returnAdjCtx.orderAdjustmentId"/> - <set from-field="returnId" field="returnAdjCtx.returnId"/> - <!--filter out orderAdjustment that have been returned--> - <entity-count entity-name="ReturnAdjustment" count-field="returnCount"> - <condition-expr field-name="orderAdjustmentId" operator="equals" from-field="orderAdjustment.orderAdjustmentId"/> - </entity-count> - <if-compare field="returnCount" value="0" operator="equals"> - <log level="info" message="Create new return adjustment: ${returnAdjCtx}"/> - <call-service service-name="createReturnAdjustment" in-map-name="returnAdjCtx" include-user-login="true"/> - </if-compare> - </iterate> - <set field="orderAvailableCtx.orderId" from-field="orderHeader.orderId"/> - <set field="orderAvailableCtx.countNewReturnItems" value="true" type="Boolean"/> <!-- very important: if this is not set, getOrderAvailableReturnedTotal would not count the return items we just created --> - <call-service service-name="getOrderAvailableReturnedTotal" in-map-name="orderAvailableCtx"> - <result-to-field result-name="availableReturnTotal" field="availableReturnTotal"/> - <result-to-field result-name="returnTotal" field="returnTotal"/> - <result-to-field result-name="orderTotal" field="orderTotal"/> - </call-service> - <log level="info" message="OrderTotal [${orderTotal}] - ReturnTotal [${returnTotal}] = available Return Total [${availableReturnTotal}]"/> - - <!-- create a manual balance adjustment based on the difference between order total and return total --> - <if-compare field="availableReturnTotal" operator="not-equals" value="0.00" type="BigDecimal"> - <set value="Balance Adjustment" field="balanceItemCtx.description"/> - <set value="RET_MAN_ADJ" field="balanceItemCtx.returnAdjustmentTypeId"/> - - <set from-field="returnId" field="balanceItemCtx.returnId"/> - <set field="balanceItemCtx.returnItemSeqId" value="_NA_"/> - <set from-field="availableReturnTotal" field="balanceItemCtx.amount" type="BigDecimal"/> - <log level="warning" message="Creating a balance adjustment of [${availableReturnTotal}] for return [${returnId}]"/> - - <!-- create the balance adjustment return item --> - <call-service service-name="createReturnAdjustment" in-map-name="balanceItemCtx" include-user-login="true"/> - </if-compare> - - <!-- update the header status --> - <if-compare field="returnHeaderTypeId" operator="equals" value="CUSTOMER_RETURN"> - <set field="updateHeaderCtx.statusId" value="RETURN_ACCEPTED"/> - <else> - <set field="updateHeaderCtx.statusId" value="SUP_RETURN_ACCEPTED"/> - </else> - </if-compare> - <set from-field="returnId" field="updateHeaderCtx.returnId"/> - <call-service service-name="updateReturnHeader" in-map-name="updateHeaderCtx" include-user-login="true"/> - - <if-compare field="returnHeaderTypeId" operator="equals" value="CUSTOMER_RETURN"> - <!-- auto-receive this return if we passed in the flag --> - <if-compare field="parameters.receiveReturn" operator="equals" value="true" type="Boolean"> - <set from-field="returnId" field="receiveCtx.returnId"/> - <call-service service-name="quickReceiveReturn" in-map-name="receiveCtx"/> - <else> - <!-- update the header status --> - <log level="info" message="Receive flag not set; will handle receiving on entity-sync"/> - </else> - </if-compare> - </if-compare> - <field-to-result field="returnId"/> - </simple-method> - - <simple-method method-name="createReturnAndItemOrAdjustment" short-description="If returnId is null, create a return; then create Return Item or Adjustment based on the parameters passed in"> - <if-empty field="parameters.returnId"> - <set-service-fields service-name="createReturnHeader" map="parameters" to-map="returnHeaderInMap"/> - <call-service service-name="createReturnHeader" in-map-name="returnHeaderInMap"> - <result-to-field result-name="returnId" field="returnId"/> - </call-service> - <check-errors/> - <set field="parameters.returnId" from-field="returnId"/> - <field-to-result field="returnId" result-name="returnId"/> - </if-empty> - <set-service-fields service-name="createReturnItemOrAdjustment" map="parameters" to-map="createReturnItemOrAdjustmentInMap"/> - <call-service service-name="createReturnItemOrAdjustment" in-map-name="createReturnItemOrAdjustmentInMap"> - <result-to-field result-name="returnAdjustmentId" field="returnAdjustmentId"/> - <result-to-field result-name="returnItemSeqId" field="returnItemSeqId"/> - </call-service> - <check-errors/> - <field-to-result field="returnAdjustmentId" result-name="returnAdjustmentId"/> - <field-to-result field="returnItemSeqId" result-name="returnItemSeqId"/> - </simple-method> - - <simple-method method-name="cancelReturnItems" short-description="Update a ReturnItems"> - <entity-condition entity-name="ReturnItem" list="returnItems" distinct="true"> - <condition-expr field-name="returnId" operator="equals" from-field="parameters.returnId"/> - </entity-condition> - <iterate list="returnItems" entry="returnItem"> - <set field="returnItemMap.returnId" from-field="parameters.returnId"/> - <set field="returnItemMap.returnItemSeqId" from-field="returnItem.returnItemSeqId"/> - <set field="returnItemMap.statusId" value="RETURN_CANCELLED"/> - <call-service service-name="updateReturnItem" in-map-name="returnItemMap"/> - </iterate> - </simple-method> - - <simple-method method-name="cancelReplacementOrderItems" short-description="Cancel the associated OrderItems of the replacement order, if any."> - <entity-one entity-name="ReturnItem" value-field="returnItem"/> - <if> - <condition> - <or> - <if-compare field="returnItem.returnTypeId" operator="equals" value="RTN_REPLACE"/> - <if-compare field="returnItem.returnTypeId" operator="equals" value="RTN_CSREPLACE"/> - <if-compare field="returnItem.returnTypeId" operator="equals" value="RTN_REPAIR_REPLACE"/> - </or> - </condition> - <then> - <!-- get the returned order item --> - <get-related-one value-field="returnItem" relation-name="OrderItem" to-value-field="orderItem"/> - <!-- get the order items of the replacement order associated to the returned item --> - <set field="oiaMap.orderItemAssocTypeId" value="REPLACEMENT"/> - <get-related value-field="orderItem" relation-name="FromOrderItemAssoc" map="oiaMap" list="replacementOrderItems"/> - <iterate list="replacementOrderItems" entry="replacementOrderItem"> - <set field="orderItemMap.orderId" from-field="replacementOrderItem.toOrderId"/> - <set field="orderItemMap.orderItemSeqId" from-field="replacementOrderItem.toOrderItemSeqId"/> - <call-service service-name="cancelOrderItem" in-map-name="orderItemMap"/> - </iterate> - </then> - </if> - </simple-method> - - <simple-method method-name="processWaitReplacementReturn" short-description="Process the replacements in a wait return"> - <set field="inMap.returnId" from-field="parameters.returnId"/> - <set field="inMap.returnTypeId" value="RTN_REPLACE"/> - <call-service service-name="processReplacementReturn" in-map-name="inMap"/> - </simple-method> - <simple-method method-name="processCrossShipReplacementReturn" short-description="Process the replacements in a cross-ship return"> - <set field="inMap.returnId" from-field="parameters.returnId"/> - <set field="inMap.returnTypeId" value="RTN_CSREPLACE"/> - <call-service service-name="processReplacementReturn" in-map-name="inMap"/> - </simple-method> - <simple-method method-name="processRepairReplacementReturn" short-description="Process the replacements in a repair return"> - <set field="inMap.returnId" from-field="parameters.returnId"/> - <set field="inMap.returnTypeId" value="RTN_REPAIR_REPLACE"/> - <call-service service-name="processReplacementReturn" in-map-name="inMap"/> - </simple-method> - <simple-method method-name="processWaitReplacementReservedReturn" short-description="Process the replacements in a wait reserved return when the return is accepted and then received"> - <entity-one entity-name="ReturnHeader" value-field="returnHeader"/> - <if-compare field="returnHeader.statusId" operator="equals" value="RETURN_ACCEPTED"> - <set field="inMap.returnId" from-field="parameters.returnId"/> - <set field="inMap.returnTypeId" value="RTN_WAIT_REPLACE_RES"/> - <call-service service-name="processReplacementReturn" in-map-name="inMap"/> - </if-compare> - <if-compare field="returnHeader.statusId" operator="equals" value="RETURN_RECEIVED"> - <entity-and entity-name="ReturnItem" list="returnItems"> - <field-map field-name="returnId" from-field="returnHeader.returnId"/> - <field-map field-name="returnTypeId" value="RTN_WAIT_REPLACE_RES"/> - </entity-and> - <if-not-empty field="returnItems"> - <!-- Get the replacement order and update its status to Approved --> - <first-from-list list="returnItems" entry="returnItem"/> - <get-related-one relation-name="ReturnItemResponse" value-field="returnItem" to-value-field="returnItemResponse"/> - <entity-one entity-name="OrderHeader" value-field="orderHeader" > - <field-map field-name="orderId" from-field="returnItemResponse.replacementOrderId"/> - </entity-one> - <if-not-empty field="orderHeader"> - <if-compare field="orderHeader.statusId" operator="equals" value="ORDER_HOLD"> - <set field="changeOrderStatusMap.statusId" value="ORDER_APPROVED"/> - <set field="changeOrderStatusMap.orderId" from-field="returnItemResponse.replacementOrderId"/> - <set field="changeOrderStatusMap.setItemStatus" value="Y"/> - <call-service service-name="changeOrderStatus" in-map-name="changeOrderStatusMap"/> - </if-compare> - <if-compare field="orderHeader.statusId" operator="equals" value="ORDER_CANCELLED"> - <set field="createOrderMap.returnId" from-field="parameters.returnId"/> - <set field="createOrderMap.returnTypeId" value="RTN_WAIT_REPLACE_RES"/> - <call-service service-name="processReplacementReturn" in-map-name="createOrderMap"/> - </if-compare> - </if-not-empty> - </if-not-empty> - </if-compare> - </simple-method> - - <simple-method method-name="processReplaceImmediatelyReturn" short-description="Process the replacements in a immediate return"> - <set field="inMap.returnId" from-field="parameters.returnId"/> - <set field="inMap.returnTypeId" value="RTN_REPLACE_IMMEDIAT"/> - <call-service service-name="processReplacementReturn" in-map-name="inMap"/> - </simple-method> - <simple-method method-name="processRefundOnlyReturn" short-description="Process the refund in a return"> - <set field="inMap.returnId" from-field="parameters.returnId"/> - <set field="inMap.returnTypeId" value="RTN_REFUND"/> - <call-service service-name="processRefundReturn" in-map-name="inMap"/> - </simple-method> - <simple-method method-name="processRefundImmediatelyReturn" short-description="Process the Immediate refund in a return"> - <set field="inMap.returnId" from-field="parameters.returnId"/> - <set field="inMap.returnTypeId" value="RTN_REFUND_IMMEDIATE"/> - <call-service service-name="processRefundReturn" in-map-name="inMap"/> - </simple-method> - - <simple-method method-name="createReturnItemShipment" short-description="Create a ReturnItemShipment"> - <make-value entity-name="ReturnItemShipment" value-field="newEntity"/> - <set-pk-fields map="parameters" value-field="newEntity"/> - <set-nonpk-fields map="parameters" value-field="newEntity"/> - <create-value value-field="newEntity"/> - </simple-method> - - <simple-method method-name="getStatusItemsForReturn" short-description="Get the return status associated with customer vs. vendor return"> - <if-compare field="parameters.returnHeaderTypeId" operator="equals" value="CUSTOMER_RETURN"> - <entity-and entity-name="StatusItem" list="statusItems"> - <field-map field-name="statusTypeId" value="ORDER_RETURN_STTS"/> - </entity-and> - <field-to-result field="statusItems"/> - <else> - <entity-and entity-name="StatusItem" list="statusItems"> - <field-map field-name="statusTypeId" value="PORDER_RETURN_STTS"/> - </entity-and> - <field-to-result field="statusItems"/> - </else> - </if-compare> - </simple-method> - - <simple-method method-name="createExchangeOrderAssoc" short-description="Associate exchange order with original order in OrderItemAssoc entity"> - <entity-and entity-name="ReturnItem" list="returnItems"> - <field-map field-name="orderId" from-field="parameters.originOrderId"/> - <field-map field-name="returnTypeId" value="RTN_REFUND"/> - </entity-and> - <set field="returnItemSize" value="${groovy:returnItems.size()}" type="Long"/> - <entity-and entity-name="OrderItem" list="orderItems"> - <field-map field-name="orderId" from-field="parameters.orderId"/> - </entity-and> - <set field="orderItemSize" value="${groovy:orderItems.size()}" type="Long"/> - <if> - <condition> - <if-compare-field field="returnItemSize" operator="greater" to-field="orderItemSize" type="Long"/> - </condition> - <then> - <set field="returnItemCounter" value="1" type="Long"/> - <iterate list="returnItems" entry="returnItem"> - <set field="orderItemAssocMap.orderId" from-field="parameters.originOrderId"/> - <set field="orderItemAssocMap.orderItemSeqId" from-field="returnItem.orderItemSeqId"/> - <set field="orderItemCounter" value="1" type="Long"/> - <iterate list="orderItems" entry="orderItem"> - <if> - <condition> - <if-compare-field field="returnItemCounter" operator="equals" to-field="orderItemCounter" type="Long"/> - </condition> - <then> - <set field="orderItemAssocMap.toOrderId" from-field="parameters.orderId"/> - <set field="orderItemAssocMap.toOrderItemSeqId" from-field="orderItem.orderItemSeqId"/> - </then> - <else-if> - <condition> - <if-compare-field field="returnItemCounter" operator="greater" to-field="orderItemSize" type="Long"/> - </condition> - <then> - <set field="orderItemAssocMap.toOrderId" from-field="parameters.orderId"/> - <set field="orderItemAssocMap.toOrderItemSeqId" from-field="orderItem.orderItemSeqId"/> - </then> - </else-if> - </if> - <set field="orderItemCounter" value="${orderItemCounter+1}" type="Long"/> - </iterate> - <set field="orderItemAssocMap.shipGroupSeqId" value="_NA_"/> - <set field="orderItemAssocMap.toShipGroupSeqId" value="_NA_"/> - <set field="orderItemAssocMap.orderItemAssocTypeId" value="EXCHANGE"/> - <make-value entity-name="OrderItemAssoc" value-field="orderItemAssoc"/> - <set-pk-fields map="orderItemAssocMap" value-field="orderItemAssoc"/> - <find-by-primary-key entity-name="OrderItemAssoc" map="orderItemAssoc" value-field="orderItemAssocValue"/> - <if-empty field="orderItemAssocValue"> - <create-value value-field="orderItemAssoc"/> - <clear-field field="orderItemAssoc"/> - </if-empty> - <set field="returnItemCounter" value="${returnItemCounter+1}" type="Long"/> - </iterate> - </then> - <else> - <set field="orderItemCounter" value="1" type="Long"/> - <iterate list="orderItems" entry="orderItem"> - <set field="orderItemAssocMap.toOrderId" from-field="parameters.orderId"/> - <set field="orderItemAssocMap.toOrderItemSeqId" from-field="orderItem.orderItemSeqId"/> - <set field="returnItemCounter" value="1" type="Long"/> - <iterate list="returnItems" entry="returnItem"> - <if> - <condition> - <if-compare-field field="orderItemCounter" operator="equals" to-field="returnItemCounter" type="Long"/> - </condition> - <then> - <set field="orderItemAssocMap.orderId" from-field="parameters.originOrderId"/> - <set field="orderItemAssocMap.orderItemSeqId" from-field="returnItem.orderItemSeqId"/> - </then> - <else-if> - <condition> - <if-compare-field field="orderItemCounter" operator="greater" to-field="returnItemSize" type="Long"/> - </condition> - <then> - <set field="orderItemAssocMap.orderId" from-field="parameters.originOrderId"/> - <set field="orderItemAssocMap.orderItemSeqId" from-field="returnItem.orderItemSeqId"/> - </then> - </else-if> - </if> - <set field="returnItemCounter" value="${returnItemCounter+1}" type="Long"/> - </iterate> - <set field="orderItemAssocMap.shipGroupSeqId" value="_NA_"/> - <set field="orderItemAssocMap.toShipGroupSeqId" value="_NA_"/> - <set field="orderItemAssocMap.orderItemAssocTypeId" value="EXCHANGE"/> - <make-value entity-name="OrderItemAssoc" value-field="orderItemAssoc"/> - <set-pk-fields map="orderItemAssocMap" value-field="orderItemAssoc"/> - <find-by-primary-key entity-name="OrderItemAssoc" map="orderItemAssoc" value-field="orderItemAssocValue"/> - <if-empty field="orderItemAssocValue"> - <create-value value-field="orderItemAssoc"/> - <clear-field field="orderItemAssocMap"/> - </if-empty> - <set field="orderItemCounter" value="${orderItemCounter+1}" type="Long"/> - </iterate> - </else> - </if> - </simple-method> - - <simple-method method-name="addProductsBackToCategory" short-description="When one or more product is received directly through receive inventory or refund return then add these product(s) back to category, if they does not have any active category"> - <if-not-empty field="parameters.inventoryItemId"> - <entity-one entity-name="InventoryItem" value-field="inventoryItem"/> - <get-related-one relation-name="Product" value-field="inventoryItem" to-value-field="product"/> - <set field="orderBy[]" value="-thruDate"/> - <get-related relation-name="ProductCategoryMember" value-field="product" list="productCategoryMembers" order-by-list="orderBy"/> - <!-- check whether this product is associated to any category, if not just skip --> - <if-not-empty field="productCategoryMembers"> - <filter-list-by-date list="productCategoryMembers" to-list="pcms"/> - <!-- check if this product is associated to any active category, if not found then activate the most recent inactive category --> - <if-empty field="pcms"> - <first-from-list list="productCategoryMembers" entry="pcm"/> - <clear-field field="pcm.thruDate"/> - <set-service-fields service-name="updateProductToCategory" map="pcm" to-map="updateProductToCategoryMap"/> - <call-service service-name="updateProductToCategory" in-map-name="updateProductToCategoryMap"/> - </if-empty> - </if-not-empty> - <else> - <if-not-empty field="parameters.returnId"> - <entity-and entity-name="ReturnItem" list="returnItems"> - <field-map field-name="returnId" from-field="parameters.returnId"/> - <field-map field-name="returnTypeId" value="RTN_REFUND"/> - </entity-and> - <if-not-empty field="returnItems"> - <iterate list="returnItems" entry="returnItem"> - <get-related-one relation-name="Product" value-field="returnItem" to-value-field="product"/> - <set field="orderBy[]" value="-thruDate"/> - <get-related relation-name="ProductCategoryMember" value-field="product" list="productCategoryMembers" order-by-list="orderBy"/> - <!-- check whether this product is associated to any category, if not just skip --> - <if-not-empty field="productCategoryMembers"> - <filter-list-by-date list="productCategoryMembers" to-list="pcms"/> - <!-- check if this product is associated to any active category, if not found then activate the most recent inactive category --> - <if-empty field="pcms"> - <first-from-list list="productCategoryMembers" entry="pcm"/> - <clear-field field="pcm.thruDate"/> - <set-service-fields service-name="updateProductToCategory" map="pcm" to-map="updateProductToCategoryMap"/> - <call-service service-name="updateProductToCategory" in-map-name="updateProductToCategoryMap"/> - </if-empty> - </if-not-empty> - </iterate> - </if-not-empty> - </if-not-empty> - </else> - </if-not-empty> - </simple-method> - - <simple-method method-name="createReturnStatus" short-description="Create ReturnHeader and ReturnItem Status"> - <make-value entity-name="ReturnStatus" value-field="newEntity"/> - <if-empty field="parameters.returnItemSeqId"> - <entity-one entity-name="ReturnHeader" value-field="returnHeader"/> - <set field="newEntity.statusId" from-field="returnHeader.statusId"/> - <else> - <entity-one entity-name="ReturnItem" value-field="returnItem"/> - <set field="newEntity.returnItemSeqId" from-field="returnItem.returnItemSeqId"/> - <set field="newEntity.statusId" from-field="returnItem.statusId"/> - </else> - </if-empty> - <sequenced-id sequence-name="ReturnStatus" field="newEntity.returnStatusId"/> - <set field="newEntity.returnId" from-field="parameters.returnId"/> - <set field="newEntity.changeByUserLoginId" from-field="userLogin.userLoginId"/> - <now-timestamp field="newEntity.statusDatetime"/> - <create-value value-field="newEntity"/> - </simple-method> - - <simple-method method-name="updateReturnContactMech" short-description="Update ReturnContactMech"> - <make-value entity-name="ReturnContactMech" value-field="returnContactMechMap"/> - - <set-pk-fields map="parameters" value-field="returnContactMechMap"/> - <entity-one entity-name="ReturnHeader" value-field="returnHeader"/> - <set from-field="parameters.returnId" field="createReturnContactMechMap.returnId"/> - <set from-field="parameters.contactMechPurposeTypeId" field="createReturnContactMechMap.contactMechPurposeTypeId"/> - <set from-field="parameters.contactMechId" field="createReturnContactMechMap.contactMechId"/> - - <find-by-and entity-name="ReturnContactMech" map="createReturnContactMechMap" list="returnContactMechList"/> - <!-- If returnContactMechList value is null then create new entry in ReturnContactMech entity--> - <if-empty field="returnContactMechList"> - <if-compare field="parameters.contactMechPurposeTypeId" operator="equals" value="SHIPPING_LOCATION"> - <set field="returnHeader.originContactMechId" from-field="createReturnContactMechMap.contactMechId"/> - <store-value value-field="returnHeader"/> - </if-compare> - <call-service service-name="createReturnContactMech" in-map-name="createReturnContactMechMap" include-user-login="true"/> - <set from-field="parameters.returnId" field="deleteReturnContactMechMap.returnId"/> - <set from-field="parameters.oldContactMechId" field="deleteReturnContactMechMap.contactMechId"/> - <set from-field="parameters.contactMechPurposeTypeId" field="deleteReturnContactMechMap.contactMechPurposeTypeId"/> - <call-service service-name="deleteReturnContactMech" in-map-name="deleteReturnContactMechMap" include-user-login="true"/> - </if-empty> - <store-value value-field="returnContactMechMap"/> - </simple-method> - - <simple-method method-name="createReturnItemForRental" short-description="Create the return item for rental (which items has product type is ASSET_USAGE_OUT_IN)"> - <entity-one entity-name="OrderHeader" value-field="orderHeader"> - <field-map field-name="orderId" from-field="parameters.orderId"/> - </entity-one> - - <if-compare operator="equals" value="SALES_ORDER" field="orderHeader.orderTypeId"> - <entity-condition entity-name="OrderRole" list="orderRoles"> - <condition-list combine="and"> - <condition-expr field-name="orderId" operator="equals" from-field="orderHeader.orderId"/> - <condition-expr field-name="roleTypeId" operator="equals" value="BILL_TO_CUSTOMER"/> - </condition-list> - </entity-condition> - <first-from-list list="orderRoles" entry="orderRole"/> - - <get-related-one relation-name="ProductStore" value-field="orderHeader" to-value-field="productStore"/> - - <if-not-empty field="productStore.inventoryFacilityId"> - <set field="createReturnCtx.destinationFacilityId" from-field="productStore.inventoryFacilityId"/> - </if-not-empty> - - <if-not-empty field="productStore.reqReturnInventoryReceive"> - <set field="updateHeaderCtx.needsInventoryReceive" from-field="productStore.reqReturnInventoryReceive"/> - <else> - <set field="updateHeaderCtx.needsInventoryReceive" value="N"/> - </else> - </if-not-empty> - - <set field="createReturnCtx.orderId" from-field="orderHeader.orderId"/> - <set field="createReturnCtx.currencyUomId" from-field="orderHeader.currencyUom"/> - <set field="createReturnCtx.fromPartyId" from-field="orderRole.partyId"/> - <set field="createReturnCtx.toPartyId" from-field="productStore.payToPartyId"/> - <set field="createReturnCtx.returnHeaderTypeId" value="CUSTOMER_RETURN"/> - <set field="createReturnCtx.returnReasonId" value="RTN_NORMAL_RETURN"/> - <set field="createReturnCtx.returnTypeId" value="RTN_RENTAL"/> - <set field="createReturnCtx.returnItemTypeId" value="RET_FDPROD_ITEM"/> - <set field="createReturnCtx.expectedItemStatus" value="INV_RETURNED"/> - <set field="createReturnCtx.returnPrice" value="0.00" type="BigDecimal"/> - - <entity-condition entity-name="OrderItemAndProduct" list="orderItems"> - <condition-list combine="and"> - <condition-expr field-name="orderId" operator="equals" from-field="orderHeader.orderId"/> - <condition-expr field-name="statusId" operator="equals" value="ITEM_COMPLETED"/> - <condition-expr field-name="productTypeId" operator="equals" value="ASSET_USAGE_OUT_IN"/> - </condition-list> - </entity-condition> - <iterate list="orderItems" entry="orderItem"> - <set field="createReturnCtx.productId" from-field="orderItem.productId"/> - <set field="createReturnCtx.orderItemSeqId" from-field="orderItem.orderItemSeqId"/> - <set field="createReturnCtx.description" from-field="orderItem.itemDescription"/> - <set field="createReturnCtx.returnQuantity" from-field="orderItem.quantity"/> - <call-service service-name="createReturnAndItemOrAdjustment" in-map-name="createReturnCtx" include-user-login="true"> - <result-to-field result-name="returnId" field="returnId"/> - </call-service> - <if-not-empty field="returnId"> - <set field="createReturnCtx.returnId" from-field="returnId"/> - </if-not-empty> - </iterate> - </if-compare> - </simple-method> -</simple-methods> diff --git a/applications/order/servicedef/services_return.xml b/applications/order/servicedef/services_return.xml index c64296f..c9cb8b5 100644 --- a/applications/order/servicedef/services_return.xml +++ b/applications/order/servicedef/services_return.xml @@ -24,8 +24,8 @@ under the License. <version>1.0</version> <!-- Order Return Services --> - <service name="quickReturnOrder" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="quickReturnFromOrder"> + <service name="quickReturnOrder" engine="groovy" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="quickReturnFromOrder"> <description>Quick Return Order</description> <attribute name="orderId" type="String" mode="IN" optional="false"/> <attribute name="returnReasonId" type="String" mode="IN" optional="true"/> @@ -34,15 +34,15 @@ under the License. <attribute name="receiveReturn" type="Boolean" mode="IN" optional="true"/> <attribute name="returnId" type="String" mode="OUT" optional="false"/> </service> - <service name="createReturnHeader" default-entity-name="ReturnHeader" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="createReturnHeader"> + <service name="createReturnHeader" default-entity-name="ReturnHeader" engine="groovy" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="createReturnHeader"> <description>Create a new ReturnHeader</description> <auto-attributes include="pk" mode="OUT" optional="false"/> <auto-attributes include="nonpk" mode="IN" optional="true"/> <override name="returnHeaderTypeId" optional="false"/> </service> - <service name="updateReturnHeader" default-entity-name="ReturnHeader" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="updateReturnHeader"> + <service name="updateReturnHeader" default-entity-name="ReturnHeader" engine="groovy" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="updateReturnHeader"> <description>Update a ReturnHeader</description> <permission-service service-name="returnPermissionCheck" main-action="UPDATE"/> <auto-attributes include="pk" mode="IN" optional="false"/> @@ -55,8 +55,8 @@ under the License. <auto-attributes include="nonpk" mode="IN" optional="true"/> </service> - <service name="createReturnItem" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="createReturnItem"> + <service name="createReturnItem" engine="groovy" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="createReturnItem"> <description>Create a new ReturnItem in the RETURN_REQUESTED status, based on returnableQuantity and returnablePrice from the getReturnableQuantity service. This can be called by the customer to request a return for himself or by a user with ORDERMGR_CREATE, but, if the former, the returnPrice will be overriden by the returnablePrice from getReturnableQuantity.</description> @@ -71,23 +71,23 @@ under the License. <override name="orderId" optional="false"/> <override name="returnQuantity" optional="false"/> </service> - <service name="updateReturnItem" engine="simple" default-entity-name="ReturnItem" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="updateReturnItem"> + <service name="updateReturnItem" engine="groovy" default-entity-name="ReturnItem" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="updateReturnItem"> <description>Update a ReturnItem and related adjustments</description> <permission-service service-name="returnPermissionCheck" main-action="UPDATE"/> <auto-attributes include="pk" mode="IN" optional="false"/> <auto-attributes include="nonpk" mode="IN" optional="true"/> <attribute name="oldStatusId" type="String" mode="OUT" optional="false"/> </service> - <service name="updateReturnItemsStatus" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="updateReturnItemsStatus"> + <service name="updateReturnItemsStatus" engine="groovy" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="updateReturnItemsStatus"> <description>Update ReturnItem(s) Status</description> <permission-service service-name="returnPermissionCheck" main-action="UPDATE"/> <attribute name="returnId" type="String" mode="IN" optional="false"/> <attribute name="statusId" type="String" mode="IN" optional="false"/> </service> - <service name="removeReturnItem" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="removeReturnItem"> + <service name="removeReturnItem" engine="groovy" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="removeReturnItem"> <description>Remove a ReturnItem and related adjustments</description> <permission-service service-name="returnPermissionCheck" main-action="DELETE"/> <auto-attributes entity-name="ReturnItem" include="pk" mode="IN" optional="false"/> @@ -103,15 +103,15 @@ under the License. the responseAmount is reached or all items are paid.</description> <attribute name="returnItemResponseId" type="String" mode="IN" optional="false"/> </service> - <service name="cancelReturnItems" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="cancelReturnItems"> + <service name="cancelReturnItems" engine="groovy" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="cancelReturnItems"> <description>Cancel ReturnItems and set their status to "RETURN_CANCELLED"</description> <permission-service service-name="returnPermissionCheck" main-action="UPDATE"/> <attribute name="returnId" type="String" mode="IN" optional="false"/> </service> - <service name="cancelReplacementOrderItems" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="cancelReplacementOrderItems"> + <service name="cancelReplacementOrderItems" engine="groovy" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="cancelReplacementOrderItems"> <description>Cancel the associated OrderItems of the replacement order, if any.</description> <permission-service service-name="returnPermissionCheck" main-action="UPDATE"/> <auto-attributes entity-name="ReturnItem" include="pk" mode="IN" optional="false"/> @@ -136,13 +136,13 @@ under the License. <attribute name="originalReturnQuantity" type="BigDecimal" mode="IN" optional="true"/> <override name="returnAdjustmentId" optional="false"/> </service> - <service name="removeReturnAdjustment" engine="simple" location="component://order/minilang/order/OrderReturnServices.xml" - invoke="removeReturnAdjustment"> + <service name="removeReturnAdjustment" engine="entity-auto" default-entity-name="ReturnAdjustment" + invoke="delete"> <description>Simple remove service</description> <permission-service service-name="returnPermissionCheck" main-action="DELETE"/> <auto-attributes entity-name="ReturnAdjustment" include="pk" mode="IN" optional="false"/> </service> - <service name="createReturnAndItemOrAdjustment" engine="simple" location="component://order/minilang/order/OrderReturnServices.xml" + <service name="createReturnAndItemOrAdjustment" engine="groovy" location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="createReturnAndItemOrAdjustment"> <description>If returnId is null, create a return; then create Return Item or Adjustment based on the parameters passed in</description> <auto-attributes mode="IN" include="nonpk" entity-name="ReturnHeader" optional="true"/> @@ -238,38 +238,38 @@ under the License. <attribute name="returnId" type="String" mode="IN" optional="false"/> <attribute name="returnTypeId" type="String" mode="IN" optional="false"/> </service> - <service name="processWaitReplacementReturn" engine="simple" auth="true" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="processWaitReplacementReturn"> + <service name="processWaitReplacementReturn" engine="groovy" auth="true" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="processWaitReplacementReservedReturn"> <description>Process the replacements in a wait return</description> <attribute name="returnId" type="String" mode="IN" optional="false"/> </service> - <service name="processWaitReplacementReservedReturn" engine="simple" auth="true" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="processWaitReplacementReservedReturn"> + <service name="processWaitReplacementReservedReturn" engine="groovy" auth="true" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="processWaitReplacementReservedReturn"> <description>Process the replacements in a wait reserved return when the return is accepted and then received</description> <attribute name="returnId" type="String" mode="IN" optional="false"/> </service> - <service name="processCrossShipReplacementReturn" engine="simple" auth="true" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="processCrossShipReplacementReturn"> + <service name="processCrossShipReplacementReturn" engine="groovy" auth="true" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="processCrossShipReplacementReturn"> <description>Process the replacements in a cross-ship return</description> <attribute name="returnId" type="String" mode="IN" optional="false"/> </service> - <service name="processRepairReplacementReturn" engine="simple" auth="true" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="processRepairReplacementReturn"> + <service name="processRepairReplacementReturn" engine="groovy" auth="true" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="processRepairReplacementReturn"> <description>Process the replacements in a repair return</description> <attribute name="returnId" type="String" mode="IN" optional="false"/> </service> - <service name="processReplaceImmediatelyReturn" engine="simple" auth="true" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="processReplaceImmediatelyReturn"> + <service name="processReplaceImmediatelyReturn" engine="groovy" auth="true" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="processReplaceImmediatelyReturn"> <description>Process the replacements in a Immediate Return</description> <attribute name="returnId" type="String" mode="IN" optional="false"/> </service> - <service name="processRefundOnlyReturn" engine="simple" auth="true" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="processRefundOnlyReturn"> + <service name="processRefundOnlyReturn" engine="groovy" auth="true" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="processRefundOnlyReturn"> <description>Process the Refund in a return</description> <attribute name="returnId" type="String" mode="IN" optional="false"/> </service> - <service name="processRefundImmediatelyReturn" engine="simple" auth="true" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="processRefundImmediatelyReturn"> + <service name="processRefundImmediatelyReturn" engine="groovy" auth="true" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="processRefundImmediatelyReturn"> <description>Process the Immediate Refund in a return</description> <attribute name="returnId" type="String" mode="IN" optional="false"/> </service> @@ -285,8 +285,8 @@ under the License. </service> <!-- other return services --> - <service name="updateReturnStatusFromReceipt" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="updateReturnStatusFromReceipt"> + <service name="updateReturnStatusFromReceipt" engine="groovy" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="updateReturnStatusFromReceipt"> <description>Update return/item status when items have been received</description> <permission-service service-name="returnPermissionCheck" main-action="UPDATE"/> <attribute name="returnId" type="String" mode="IN" optional="false"/> @@ -325,35 +325,34 @@ under the License. <attribute name="paymentId" type="String" mode="OUT" optional="false"/> </service> - <service name="createReturnItemShipment" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="createReturnItemShipment"> + <service name="createReturnItemShipment" engine="entity-auto" default-entity-name="ReturnItemShipment" invoke="create"> <description>Create a new ReturnItemShipment</description> <permission-service service-name="returnPermissionCheck" main-action="CREATE"/> - <auto-attributes entity-name="ReturnItemShipment" include="all" mode="IN" optional="false"/> + <auto-attributes include="all" mode="IN" optional="false"/> </service> - <service name="getStatusItemsForReturn" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="getStatusItemsForReturn"> + <service name="getStatusItemsForReturn" engine="groovy" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="getStatusItemsForReturn"> <description>Get the return status associated with customer/vendor return</description> <attribute name="returnHeaderTypeId" type="String" mode="IN" optional="false"/> <attribute name="statusItems" type="List" mode="OUT" optional="false"/> </service> - <service name="createExchangeOrderAssoc" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="createExchangeOrderAssoc"> + <service name="createExchangeOrderAssoc" engine="groovy" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="createExchangeOrderAssoc"> <description>Associate exchange order with original order in OrderItemAssoc entity</description> <attribute name="orderId" type="String" mode="IN" optional="false"/> <attribute name="originOrderId" type="String" mode="IN" optional="false"/> </service> - <service name="addProductsBackToCategory" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="addProductsBackToCategory"> + <service name="addProductsBackToCategory" engine="groovy" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="addProductsBackToCategory"> <description>Add product(s) back to category if it has no active category</description> <attribute name="returnId" type="String" mode="IN" optional="true"/> <attribute name="inventoryItemId" type="String" mode="IN" optional="true"/> </service> - <service name="createReturnStatus" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="createReturnStatus"> + <service name="createReturnStatus" engine="groovy" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="createReturnStatus"> <description>Create Return Status</description> <attribute name="returnId" type="String" mode="IN" optional="false"/> <attribute name="returnItemSeqId" type="String" mode="IN" optional="true"/> @@ -365,8 +364,8 @@ under the License. <auto-attributes include="pk" mode="IN" optional="false"/> <auto-attributes include="nonpk" mode="IN" optional="true"/> </service> - <service name="updateReturnContactMech" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="updateReturnContactMech" auth="true" default-entity-name="ReturnContactMech"> + <service name="updateReturnContactMech" engine="groovy" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="updateReturnContactMech" auth="true" default-entity-name="ReturnContactMech"> <description>Update Return Contact Mech</description> <permission-service service-name="returnPermissionCheck" main-action="UPDATE"/> <auto-attributes include="pk" mode="IN" optional="false"/> @@ -378,8 +377,8 @@ under the License. </service> <!-- Item Return Service --> - <service name="createReturnItemForRental" engine="simple" - location="component://order/minilang/order/OrderReturnServices.xml" invoke="createReturnItemForRental"> + <service name="createReturnItemForRental" engine="groovy" + location="component://order/groovyScripts/order/OrderReturnServices.groovy" invoke="createReturnItemForRental"> <description>Create the return item for rental (which items has product type is ASSET_USAGE_OUT_IN)</description> <attribute name="orderId" type="String" mode="IN" optional="false"/> <attribute name="returnId" type="String" mode="OUT" optional="false"/> |
Free forum by Nabble | Edit this page |