blob: 27514d061eac49873384d6ea92e258fd4120213c [file] [log] [blame]
<?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"
xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/simple-methods-v2.xsd">
<!-- ItemIssuance services -->
<simple-method method-name="createItemIssuance" short-description="Create ItemIssuance">
<set value="Create ItemIssuance" field="operationName"/>
<call-simple-method method-name="checkCanChangeShipmentStatusPacked" xml-resource="component://product/script/org/ofbiz/shipment/shipment/ShipmentServices.xml"/>
<check-errors/>
<make-value value-field="newEntity" entity-name="ItemIssuance"/>
<sequenced-id sequence-name="ItemIssuance" field="newEntity.itemIssuanceId"/>
<field-to-result field="newEntity.itemIssuanceId" result-name="itemIssuanceId"/>
<set-nonpk-fields map="parameters" value-field="newEntity"/>
<if-empty field="newEntity.issuedDateTime">
<now-timestamp field="newEntity.issuedDateTime"/>
</if-empty>
<create-value value-field="newEntity"/>
<set field="affectAccounting" type="Boolean" value="true"/>
<!-- if the InventoryItem issued is serialized, then change its status to DELIVERED -->
<get-related-one value-field="newEntity" relation-name="InventoryItem" to-value-field="inventoryItem"/>
<if-not-empty field="inventoryItem">
<if-compare field="inventoryItem.inventoryItemTypeId" operator="equals" value="SERIALIZED_INV_ITEM">
<set field="updateContext.inventoryItemId" from-field="inventoryItem.inventoryItemId"/>
<set field="updateContext.statusId" value="INV_DELIVERED"/>
<call-service service-name="updateInventoryItem" in-map-name="updateContext"/>
<entity-one value-field="product" entity-name="Product">
<field-map field-name="productId" from-field="inventoryItem.productId"/>
</entity-one>
<if>
<condition>
<or>
<if-compare field="product.productTypeId" operator="equals" value="SERVICE_PRODUCT"/>
<if-compare field="product.productTypeId" operator="equals" value="ASSET_USAGE_OUT_IN"/>
<if-compare field="product.productTypeId" operator="equals" value="AGGREGATEDSERV_CONF"/>
</or>
</condition>
<then>
<set field="affectAccounting" type="Boolean" value="false"/>
</then>
</if>
</if-compare>
</if-not-empty>
<field-to-result field="affectAccounting" result-name="affectAccounting"/>
</simple-method>
<simple-method method-name="updateItemIssuance" short-description="Update ItemIssuance">
<set value="Update ItemIssuance" field="operationName"/>
<call-simple-method method-name="checkCanChangeShipmentStatusPacked" xml-resource="component://product/script/org/ofbiz/shipment/shipment/ShipmentServices.xml"/>
<check-errors/>
<entity-one entity-name="ItemIssuance" value-field="lookedUpValue"/>
<set-nonpk-fields map="parameters" value-field="lookedUpValue"/>
<store-value value-field="lookedUpValue"/>
</simple-method>
<simple-method method-name="deleteItemIssuance" short-description="Delete ItemIssuance">
<set value="Delete ItemIssuance" field="operationName"/>
<call-simple-method method-name="checkCanChangeShipmentStatusPacked" xml-resource="component://product/script/org/ofbiz/shipment/shipment/ShipmentServices.xml"/>
<check-errors/>
<entity-one entity-name="ItemIssuance" value-field="lookedUpValue"/>
<remove-value value-field="lookedUpValue"/>
</simple-method>
<!-- ItemIssuanceRole services -->
<simple-method method-name="createItemIssuanceRole" short-description="Create ItemIssuanceRole">
<set value="Create ItemIssuanceRole" field="operationName"/>
<call-simple-method method-name="checkCanChangeShipmentStatusPacked" xml-resource="component://product/script/org/ofbiz/shipment/shipment/ShipmentServices.xml"/>
<check-errors/>
<make-value value-field="newEntity" entity-name="ItemIssuanceRole"/>
<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="deleteItemIssuanceRole" short-description="Delete ItemIssuanceRole">
<set value="Delete ItemIssuanceRole" field="operationName"/>
<call-simple-method method-name="checkCanChangeShipmentStatusPacked" xml-resource="component://product/script/org/ofbiz/shipment/shipment/ShipmentServices.xml"/>
<check-errors/>
<entity-one entity-name="ItemIssuanceRole" value-field="lookedUpValue"/>
<remove-value value-field="lookedUpValue"/>
</simple-method>
<!-- the actual issuance services -->
<simple-method method-name="issueOrderItemToShipment" short-description="Issue OrderItem to Shipment">
<set value="Issue OrderItem to Shipment" field="operationName"/>
<call-simple-method method-name="checkCanChangeShipmentStatusPacked" xml-resource="component://product/script/org/ofbiz/shipment/shipment/ShipmentServices.xml"/>
<!-- get orderHeader -->
<entity-one entity-name="OrderHeader" value-field="orderHeader" auto-field-map="true"/>
<!-- make sure the order is NOT of orderTypeId: SALES_ORDER -->
<if-compare field="orderHeader.orderTypeId" operator="equals" value="SALES_ORDER">
<string-to-list string="Not issuing Order Item to shipment [${parameters.shipmentId}] because the order is a Sales Order for order [${orderHeader.orderId}] order item [${parameters.orderItemSeqId}] (should call the issueOrderItemShipGrpInvResToShipment service)" list="error_list"/>
</if-compare>
<check-errors/>
<!-- get orderItem -->
<entity-one entity-name="OrderItem" value-field="orderItem" auto-field-map="true"/>
<!-- get orderItemShipGroupAssoc -->
<entity-one entity-name="OrderItemShipGroupAssoc" value-field="orderItemShipGroupAssoc" auto-field-map="true"/>
<!-- get shipment -->
<entity-one entity-name="Shipment" value-field="shipment" auto-field-map="true"/>
<call-simple-method method-name="findCreateIssueShipmentItem"/>
<!--
TODO: if we want to record the role of the facility operation we have to re-implement this using ShipmentReceiptRole
<call-simple-method method-name="findCreateItemIssuance"/>
<call-simple-method method-name="associateIssueRoles"/>
-->
</simple-method>
<simple-method method-name="issueOrderItemShipGrpInvResToShipment" short-description="Issue OrderItemShipGrpInvRes to Shipment">
<set value="Issue OrderItemShipGrpInvRes to Shipment" field="operationName"/>
<call-simple-method method-name="checkCanChangeShipmentStatusPacked" xml-resource="component://product/script/org/ofbiz/shipment/shipment/ShipmentServices.xml"/>
<!-- get orderItemShipGrpInvRes -->
<make-value entity-name="OrderItemShipGrpInvRes" value-field="OrderItemShipGrpInvResLookupPk"/>
<set-pk-fields value-field="OrderItemShipGrpInvResLookupPk" map="parameters"/>
<find-by-primary-key map="OrderItemShipGrpInvResLookupPk" value-field="orderItemShipGrpInvRes"/>
<log level="info" message="order item ship grp inv res info: ${orderItemShipGrpInvRes}"/>
<!-- get orderHeader -->
<make-value entity-name="OrderHeader" value-field="orderHeaderLookupPk"/>
<set-pk-fields value-field="orderHeaderLookupPk" map="parameters"/>
<find-by-primary-key map="orderHeaderLookupPk" value-field="orderHeader"/>
<!-- make sure the order is of orderTypeId: SALES_ORDER -->
<if-compare field="orderHeader.orderTypeId" operator="not-equals" value="SALES_ORDER">
<string-to-list string="Not issuing Order Item Ship Group Inventory Reservation to shipment [${parameters.shipmentId}] because the order is not a Sales Order for order [${orderItemShipGrpInvRes.orderId}] order item [${orderItemShipGrpInvRes.orderItemSeqId}] inventoryItem [${orderItemShipGrpInvRes.inventoryItemId}] (should call the issueOrderItemToShipment service)" list="error_list"/>
</if-compare>
<!-- make sure specified quantity is not empty -->
<if-empty field="parameters.quantity">
<add-error>
<fail-property resource="ProductUiLabels" property="ProductNotIssueOrderToShipment"/>
</add-error>
</if-empty>
<if-empty field="orderItemShipGrpInvRes.quantity">
<log level="info" message="Order item reservation amount is null! PK lookup: ${OrderItemShipGrpInvResLookupPk}"/>
</if-empty>
<!-- make sure specified quantity is not less than or equal to 0 -->
<if-compare field="parameters.quantity" operator="less-equals" value="0" type="BigDecimal">
<add-error>
<fail-property resource="ProductUiLabels" property="ProductNotIssueOrderToShipmentQuantityLess"/>
</add-error>
</if-compare>
<!-- make sure specified quantity is not greater than reserved quantity left to be issued, ie orderItemShipGrpInvRes.quantity -->
<if-compare-field field="parameters.quantity" to-field="orderItemShipGrpInvRes.quantity" operator="greater" type="BigDecimal">
<add-error>
<fail-property resource="ProductUiLabels" property="ProductNotIssueOrderToShipmentQuantityGreater"/>
</add-error>
</if-compare-field>
<check-errors/>
<!-- get orderItem -->
<entity-one entity-name="OrderItem" value-field="orderItem"/>
<!-- get inventoryItem -->
<entity-one entity-name="InventoryItem" value-field="inventoryItem"/>
<!-- get shipment -->
<entity-one entity-name="Shipment" value-field="shipment"/>
<!-- get orderShipment -->
<make-value entity-name="OrderShipment" value-field="orderShipmentLookupPk"/>
<set-pk-fields value-field="orderShipmentLookupPk" map="parameters"/>
<find-by-and entity-name="OrderShipment" map="orderShipmentLookupPk" list="orderShipments"/>
<first-from-list entry="orderShipment" list="orderShipments"/>
<!-- will create qtyForShipmentItem -->
<!-- jacopoc: a weird error is happening here during testMultipleInventoryItemIssuance -->
<call-simple-method method-name="calcQtyForShipmentItemInline"/>
<log level="info" message="qtyForShipmentItem: ${qtyForShipmentItem}"/>
<if-compare value="0" operator="greater-equals" field="qtyForShipmentItem" type="BigDecimal">
<if-not-empty field="orderShipment">
<field-to-result field="orderShipment.shipmentItemSeqId" result-name="shipmentItemSeqId"/>
<make-value entity-name="ShipmentItem" value-field="shipmentItemLookupPk"/>
<set-pk-fields value-field="shipmentItemLookupPk" map="parameters"/>
<set from-field="orderShipment.shipmentItemSeqId" field="shipmentItemLookupPk.shipmentItemSeqId"/>
<find-by-primary-key map="shipmentItemLookupPk" value-field="shipmentItem"/>
</if-not-empty>
<if-compare value="0" operator="not-equals" field="qtyForShipmentItem" type="BigDecimal">
<!-- add the qtyForShipmentItem to the shipmentItem -->
<set from-field="parameters.quantity" field="originalQuantity"/>
<set from-field="qtyForShipmentItem" field="parameters.quantity"/>
<call-simple-method method-name="findCreateIssueShipmentItem"/>
<set from-field="originalQuantity" field="parameters.quantity"/>
</if-compare>
<else>
<!-- A reduction in the quantity, so OrderShipment must exist. -->
<calculate field="orderShipment.quantity">
<calcop field="orderShipment.quantity" operator="subtract">
<calcop operator="get" field="parameters.quantity"/>
</calcop>
</calculate>
<store-value value-field="orderShipment"/>
<field-to-result field="orderShipment.shipmentItemSeqId" result-name="shipmentItemSeqId"/>
<make-value entity-name="ShipmentItem" value-field="shipmentItemLookupPk"/>
<set-pk-fields value-field="shipmentItemLookupPk" map="parameters"/>
<set from-field="orderShipment.shipmentItemSeqId" field="shipmentItemLookupPk.shipmentItemSeqId"/>
<find-by-primary-key map="shipmentItemLookupPk" value-field="shipmentItem"/>
</else>
</if-compare>
<set field="eventDate" from-field="parameters.eventDate"/>
<set field="shipmentId" from-field="parameters.shipmentId"/>
<call-simple-method method-name="findCreateItemIssuance"/>
<call-simple-method method-name="associateIssueRoles"/>
<!-- decrement quantity still reserved -->
<calculate field="orderItemShipGrpInvRes.quantity">
<calcop operator="subtract">
<calcop operator="get" field="orderItemShipGrpInvRes.quantity"/>
<calcop operator="get" field="parameters.quantity"/>
</calcop>
</calculate>
<if-compare value="0" operator="equals" field="orderItemShipGrpInvRes.quantity" type="BigDecimal">
<!-- if none left reserved, remove OIIR -->
<remove-value value-field="orderItemShipGrpInvRes"/>
<if-compare field="shipment.statusId" operator="not-equals" value="SHIPMENT_SCHEDULED">
<!-- if there are no more OIIRs for the orderItem, set the orderItem.statusId to ITEM_COMPLETED -->
<get-related value-field="orderItem" relation-name="OrderItemShipGrpInvRes" list="otherOiirs"/>
<if-empty field="otherOiirs">
<set value="ITEM_COMPLETED" field="changeOrderItemStatusMap.statusId"/>
<set from-field="orderItem.orderId" field="changeOrderItemStatusMap.orderId"/>
<set from-field="orderItem.orderItemSeqId" field="changeOrderItemStatusMap.orderItemSeqId"/>
<call-service service-name="changeOrderItemStatus" in-map-name="changeOrderItemStatusMap"/>
</if-empty>
<else>
<log level="info" message="orderId: ${orderItem.orderId} orderItemSeqId: ${orderItem.orderItemSeqId}"/>
<log level="info" message="Items issued but can't set order item status to ITEM_COMPLETED because shipment status is SHIPMENT_SCHEDULED" />
</else>
</if-compare>
<else>
<store-value value-field="orderItemShipGrpInvRes"/>
</else>
</if-compare>
<!-- Decrement InventoryItem quantityOnHand -->
<!-- instead of updating InventoryItem, add an InventoryItemDetail -->
<set from-field="inventoryItem.inventoryItemId" field="createDetailMap.inventoryItemId"/>
<set from-field="orderItem.orderId" field="createDetailMap.orderId"/>
<set from-field="orderItem.orderItemSeqId" field="createDetailMap.orderItemSeqId"/>
<set from-field="orderItemShipGrpInvRes.shipGroupSeqId" field="createDetailMap.shipGroupSeqId"/>
<set from-field="shipmentItem.shipmentId" field="createDetailMap.shipmentId"/>
<set from-field="shipmentItem.shipmentItemSeqId" field="createDetailMap.shipmentItemSeqId"/>
<set from-field="itemIssuanceId" field="createDetailMap.itemIssuanceId"/>
<calculate field="createDetailMap.quantityOnHandDiff" decimal-scale="6">
<calcop field="parameters.quantity" operator="negative"/>
</calculate>
<call-service service-name="createInventoryItemDetail" in-map-name="createDetailMap"/>
<clear-field field="createDetailMap"/>
<entity-and list="oisgirs" entity-name="OrderItemShipGrpInvRes">
<field-map field-name="orderId" from-field="orderItemShipGrpInvRes.orderId"/>
<field-map field-name="orderItemSeqId" from-field="orderItemShipGrpInvRes.orderItemSeqId"/>
</entity-and>
<!-- Need to Cancel and re-reserve oisgir to fix OFBIZ-5364 issue, while there are multiple ship groups for an order item associated with same inventory and you are issuing items from one ship group to another, then quantityNotAvailable will be incorrect if we do not cancel and reserve all oisgir of order item -->
<iterate entry="oisgir" list="oisgirs">
<set field="cancelOrderItemShipGrpInvResMap.orderId" from-field="oisgir.orderId"/>
<set field="cancelOrderItemShipGrpInvResMap.orderItemSeqId" from-field="oisgir.orderItemSeqId"/>
<set field="cancelOrderItemShipGrpInvResMap.shipGroupSeqId" from-field="oisgir.shipGroupSeqId"/>
<set field="cancelOrderItemShipGrpInvResMap.inventoryItemId" from-field="oisgir.inventoryItemId"/>
<set field="cancelOrderItemShipGrpInvResMap.cancelQuantity" from-field="oisgir.quantity"/>
<call-service service-name="cancelOrderItemShipGrpInvRes" in-map-name="cancelOrderItemShipGrpInvResMap"/>
</iterate>
<!-- Re-reserve cancelled oisgirs again so that shipped quantity will be subtract from oisgir.quantity and oisgir.quantityNotAvailable will be calculated accordingly -->
<iterate entry="oisgir" list="oisgirs">
<get-related-one value-field="oisgir" relation-name="InventoryItem" to-value-field="tmpInventoryItem"/>
<set field="reserveProductInventoryByFacilityMap.quantity" from-field="oisgir.quantity"/>
<set field="reserveProductInventoryByFacilityMap.facilityId" from-field="tmpInventoryItem.facilityId"/>
<set field="reserveProductInventoryByFacilityMap.orderId" from-field="oisgir.orderId"/>
<set field="reserveProductInventoryByFacilityMap.orderItemSeqId" from-field="oisgir.orderItemSeqId"/>
<set field="reserveProductInventoryByFacilityMap.productId" from-field="orderItem.productId"/>
<set field="reserveProductInventoryByFacilityMap.shipGroupSeqId" from-field="oisgir.shipGroupSeqId"/>
<set field="reserveProductInventoryByFacilityMap.requireInventory" value="N"/><!-- requireInventory should be N to create backordered oisgir if ATP is negative -->
<call-service service-name="reserveProductInventoryByFacility" in-map-name="reserveProductInventoryByFacilityMap" />
</iterate>
</simple-method>
<!-- some inline methods for the issuance process -->
<simple-method method-name="calcQtyForShipmentItemInline" short-description="Calculate quantity for a shipment item - meant to be called in-line">
<!-- If our order has reserved a particular inventoryItemId, other InventoryItemIds
should not contribute to the adjustment calculation here
-->
<if-not-empty field="parameters.inventoryItemId">
<entity-and list="itemIssuances" entity-name="ItemIssuance">
<field-map field-name="orderId" from-field="parameters.orderId"/>
<field-map field-name="orderItemSeqId" from-field="parameters.orderItemSeqId"/>
<field-map field-name="shipGroupSeqId" from-field="parameters.shipGroupSeqId"/>
<field-map field-name="shipmentId" from-field="parameters.shipmentId"/>
<order-by field-name="-issuedDateTime"/>
</entity-and>
<set field="otherInventoryItemQuantity" value="0" />
<iterate list="itemIssuances" entry="itemIssuance">
<if-compare-field field="itemIssuance.inventoryItemId" operator="not-equals" to-field="parameters.inventoryItemId">
<calculate field="otherInventoryItemQuantity">
<calcop field="otherInventoryItemQuantity" operator="add">
<calcop operator="get" field="itemIssuance.quantity"/>
</calcop>
</calculate>
</if-compare-field>
</iterate>
</if-not-empty>
<!-- If the shipmentItem includes products from more than one inventoryItemId, any items that came from a different inventoryItemId
from the current one should be ignored as we calculate the adjustment to make.
-->
<calculate field="orderShipmentAmount">
<calcop field="orderShipment.quantity" operator="subtract">
<calcop operator="get" field="otherInventoryItemQuantity"/>
</calcop>
</calculate>
<!-- qtyForShipmentItem is the quantity we will add to the ShipmentItem -->
<calculate field="qtyForShipmentItem">
<calcop field="parameters.quantity" operator="subtract">
<calcop operator="get" field="orderShipmentAmount"/>
</calcop>
</calculate>
</simple-method>
<simple-method method-name="findCreateIssueShipmentItem" short-description="Find or Create ShipmentItem to Issue To - meant to be called in-line">
<!-- try to find an existing shipmentItem and attach to it, if none found create a new shipmentItem -->
<!-- if there is NO productId on the orderItem, ALWAYS create a new shipmentItem -->
<if-not-empty field="orderItem.productId">
<entity-condition entity-name="ShipmentItem" list="shipmentItems">
<condition-list combine="and">
<condition-expr field-name="productId" from-field="orderItem.productId"/>
<condition-expr field-name="shipmentId" from-field="parameters.shipmentId"/>
<condition-expr field-name="shipmentItemSeqId" from-field="parameters.shipmentItemSeqId" ignore-if-empty="true"/>
</condition-list>
<order-by field-name="shipmentItemSeqId"/>
</entity-condition>
<first-from-list entry="shipmentItem" list="shipmentItems"/>
</if-not-empty>
<if-empty field="shipmentItem">
<set from-field="orderItem.productId" field="shipmentItemCreate.productId"/>
<set from-field="parameters.shipmentId" field="shipmentItemCreate.shipmentId"/>
<set from-field="parameters.quantity" field="shipmentItemCreate.quantity"/>
<call-service service-name="createShipmentItem" in-map-name="shipmentItemCreate">
<result-to-field result-name="shipmentItemSeqId" field="shipmentItemLookupPk.shipmentItemSeqId"/>
</call-service>
<set from-field="parameters.shipmentId" field="shipmentItemLookupPk.shipmentId"/>
<find-by-primary-key entity-name="ShipmentItem" map="shipmentItemLookupPk" value-field="shipmentItem"/>
<else>
<calculate field="shipmentItem.quantity">
<calcop operator="add" field="shipmentItem.quantity">
<calcop operator="get" field="parameters.quantity"/>
</calcop>
</calculate>
<store-value value-field="shipmentItem"/>
</else>
</if-empty>
<call-simple-method method-name="createOrUpdateOrderShipmentInline" />
<field-to-result field="shipmentItem.shipmentItemSeqId" result-name="shipmentItemSeqId"/>
</simple-method>
<simple-method method-name="createOrUpdateOrderShipmentInline" short-description="Create or update the OrderShipment - meant to be called in-line">
<set from-field="parameters.shipmentId" field="orderShipmentCreate.shipmentId"/>
<set from-field="shipmentItem.shipmentItemSeqId" field="orderShipmentCreate.shipmentItemSeqId"/>
<set from-field="orderItem.orderId" field="orderShipmentCreate.orderId"/>
<set from-field="orderItem.orderItemSeqId" field="orderShipmentCreate.orderItemSeqId"/>
<if-not-empty field="orderItemShipGroupAssoc">
<set from-field="orderItemShipGroupAssoc.shipGroupSeqId" field="orderShipmentCreate.shipGroupSeqId"/>
</if-not-empty>
<if-not-empty field="orderItemShipGrpInvRes">
<set from-field="orderItemShipGrpInvRes.shipGroupSeqId" field="orderShipmentCreate.shipGroupSeqId"/>
</if-not-empty>
<make-value entity-name="OrderShipment" value-field="orderShipmentLookupPk"/>
<set-pk-fields value-field="orderShipmentLookupPk" map="orderShipmentCreate"/>
<find-by-and entity-name="OrderShipment" map="orderShipmentLookupPk" list="orderShipments"/>
<first-from-list entry="orderShipment" list="orderShipments"/>
<if-empty field="orderShipment">
<set from-field="parameters.quantity" field="orderShipmentCreate.quantity"/>
<call-service service-name="createOrderShipment" in-map-name="orderShipmentCreate"/>
<else>
<calculate field="orderShipment.quantity">
<calcop field="orderShipment.quantity" operator="add">
<calcop operator="get" field="parameters.quantity"/>
</calcop>
</calculate>
<store-value value-field="orderShipment"/>
</else>
</if-empty>
</simple-method>
<simple-method method-name="findCreateItemIssuance" short-description="Find Create ItemIssuance - meant to be called in-line">
<!-- If a non-sales order find ItemIssuance for orderItemSeqId-shimentItemSeqId-shipGroupSeqId pair, update it and return -->
<if-compare field="orderHeader.orderTypeId" operator="not-equals" value="SALES_ORDER">
<entity-and list="itemIssuances" entity-name="ItemIssuance">
<field-map field-name="orderId" from-field="orderItem.orderId"/>
<field-map field-name="orderItemSeqId" from-field="orderItem.orderItemSeqId"/>
<field-map field-name="shipmentId" from-field="shipmentItem.shipmentId"/>
<field-map field-name="shipmentItemSeqId" from-field="shipmentItem.shipmentItemSeqId"/>
<field-map field-name="shipGroupSeqId" from-field="orderItemShipGroupAssoc.shipGroupSeqId"/>
<order-by field-name="-issuedDateTime"/>
</entity-and>
<if-not-empty field="itemIssuances">
<first-from-list entry="itemIssuance" list="itemIssuances"/>
<set field="itemIssuance.quantity" value="${itemIssuance.quantity$bigDecimal + parameters.quantity$bigDecimal}" type="BigDecimal"/>
<store-value value-field="itemIssuance"/>
<set field="itemIssuanceId" from-field="itemIssuance.itemIssuanceId"/>
<field-to-result field="itemIssuanceId"/>
<return/>
</if-not-empty>
</if-compare>
<!-- create the ItemIssuance -->
<set from-field="parameters.quantity" field="itemIssuanceCreate.quantity"/>
<set from-field="shipmentItem.shipmentId" field="itemIssuanceCreate.shipmentId"/>
<set from-field="shipmentItem.shipmentItemSeqId" field="itemIssuanceCreate.shipmentItemSeqId"/>
<set from-field="orderItem.orderId" field="itemIssuanceCreate.orderId"/>
<set from-field="orderItem.orderItemSeqId" field="itemIssuanceCreate.orderItemSeqId"/>
<set from-field="eventDate" field="itemIssuanceCreate.issuedDateTime"/>
<if-not-empty field="orderItemShipGrpInvRes">
<!-- if this is coming from an OrderItem issue instead of an OrderItemShipGrpInvRes issue, we won't have this info -->
<set from-field="orderItemShipGrpInvRes.inventoryItemId" field="itemIssuanceCreate.inventoryItemId"/>
<set from-field="orderItemShipGrpInvRes.shipGroupSeqId" field="itemIssuanceCreate.shipGroupSeqId"/>
</if-not-empty>
<if-not-empty field="orderItemShipGroupAssoc">
<!-- If we have a ShipGroup Assoc for this Item to focus on, set that; this is mostly the case for purchase orders and such -->
<set from-field="orderItemShipGroupAssoc.shipGroupSeqId" field="itemIssuanceCreate.shipGroupSeqId"/>
</if-not-empty>
<set from-field="userLogin.userLoginId" field="itemIssuanceCreate.issuedByUserLoginId"/>
<call-service service-name="createItemIssuance" in-map-name="itemIssuanceCreate">
<result-to-field result-name="itemIssuanceId"/>
</call-service>
<field-to-result field="itemIssuanceId"/>
</simple-method>
<simple-method method-name="associateIssueRoles" short-description="Associate Roles for ItemIssuance - meant to be called in-line">
<!-- make sure the party is in the PACKER role -->
<make-value entity-name="PartyRole" value-field="partyRole"/>
<set field="partyRole.partyId" from-field="userLogin.partyId"/>
<set field="partyRole.roleTypeId" value="PACKER"/>
<find-by-primary-key entity-name="PartyRole" map="partyRole" value-field="checkPartyRole"/>
<if-empty field="checkPartyRole">
<create-value value-field="partyRole"/>
</if-empty>
<!-- Add ItemIssuanceRole for party that issues this... -->
<entity-one value-field="itemIssuanceRole" entity-name="ItemIssuanceRole">
<field-map field-name="itemIssuanceId" from-field="itemIssuanceId"/>
<field-map field-name="partyId" from-field="userLogin.partyId"/>
<field-map field-name="roleTypeId" value="PACKER"/>
</entity-one>
<if-empty field="itemIssuanceRole">
<set from-field="itemIssuanceId" field="itemIssuanceRoleCreate.itemIssuanceId"/>
<set from-field="userLogin.partyId" field="itemIssuanceRoleCreate.partyId"/>
<set value="PACKER" field="itemIssuanceRoleCreate.roleTypeId"/>
<set from-field="shipmentId" field="itemIssuanceRoleCreate.shipmentId"/>
<call-service service-name="createItemIssuanceRole" in-map-name="itemIssuanceRoleCreate"/>
</if-empty>
</simple-method>
<simple-method method-name="issueInventoryItemToFixedAssetMaint" short-description="Issue InventoryItem To FixedAssetMaint">
<entity-one entity-name="InventoryItem" value-field="inventoryItem"/>
<entity-one entity-name="FixedAssetMaint" value-field="fixedAssetMaint"/>
<!-- make sure specified quantity is not less than or equal to 0 -->
<if-compare field="parameters.quantity" operator="less-equals" value="0" type="BigDecimal">
<add-error>
<fail-property resource="ProductUiLabels" property="ProductNotIssueToFixedAssetMaintQuantityLess"/>
</add-error>
</if-compare>
<!-- make sure specified quantity is not greater than available quantity left to be issued, ie intentoryItem.availableToPromiseTotal -->
<if-compare-field field="parameters.quantity" to-field="inventoryItem.availableToPromiseTotal" operator="greater" type="BigDecimal">
<add-error>
<fail-property resource="ProductUiLabels" property="ProductNotIssueToFixedAssetMaintQuantityGreater"/>
</add-error>
</if-compare-field>
<check-errors/>
<!-- create the ItemIssuance -->
<set from-field="parameters.quantity" field="itemIssuanceCreate.quantity"/>
<set from-field="parameters.inventoryItemId" field="itemIssuanceCreate.inventoryItemId"/>
<set from-field="fixedAssetMaint.fixedAssetId" field="itemIssuanceCreate.fixedAssetId"/>
<set from-field="fixedAssetMaint.maintHistSeqId" field="itemIssuanceCreate.maintHistSeqId"/>
<set from-field="userLogin.userLoginId" field="itemIssuanceCreate.issuedByUserLoginId"/>
<call-service service-name="createItemIssuance" in-map-name="itemIssuanceCreate">
<result-to-field result-name="itemIssuanceId"/>
</call-service>
<field-to-result field="itemIssuanceId"/>
<!-- Decrement InventoryItem quantityOnHand AND availableToPromise since there was no reservation -->
<!-- instead of updating InventoryItem, add an InventoryItemDetail -->
<set from-field="inventoryItem.inventoryItemId" field="createDetailMap.inventoryItemId"/>
<set from-field="fixedAssetMaint.fixedAssetId" field="createDetailMap.fixedAssetId"/>
<set from-field="fixedAssetMaint.maintHistSeqId" field="createDetailMap.maintHistSeqId"/>
<set from-field="itemIssuanceId" field="createDetailMap.itemIssuanceId"/>
<calculate field="createDetailMap.quantityOnHandDiff" decimal-scale="6">
<calcop field="parameters.quantity" operator="negative"/>
</calculate>
<calculate field="createDetailMap.availableToPromiseDiff" decimal-scale="6">
<calcop field="parameters.quantity" operator="negative"/>
</calculate>
<call-service service-name="createInventoryItemDetail" in-map-name="createDetailMap"/>
</simple-method>
<simple-method method-name="returnInventoryItemIssuedToFixedAssetMaint" short-description="Return the InventoryItem Issued To FixedAssetMaint">
<entity-one entity-name="ItemIssuance" value-field="itemIssuance"/>
<set field="oldQuantity" from-field="itemIssuance.quantity"/>
<!-- Update the ItemIssuance -->
<set value="0" field="itemIssuanceUpdate.quantity" type="BigDecimal"/>
<set from-field="parameters.itemIssuanceId" field="itemIssuanceUpdate.itemIssuanceId"/>
<call-service service-name="updateItemIssuance" in-map-name="itemIssuanceUpdate"/>
<!-- Increment InventoryItem quantityOnHand AND availableToPromise since there was no reservation -->
<!-- instead of updating InventoryItem, add an InventoryItemDetail -->
<set from-field="itemIssuance.inventoryItemId" field="createDetailMap.inventoryItemId"/>
<set from-field="itemIssuance.fixedAssetId" field="createDetailMap.fixedAssetId"/>
<set from-field="itemIssuance.maintHistSeqId" field="createDetailMap.maintHistSeqId"/>
<set from-field="itemIssuance.itemIssuanceId" field="createDetailMap.itemIssuanceId"/>
<calculate field="createDetailMap.quantityOnHandDiff" decimal-scale="6">
<calcop field="oldQuantity" operator="add"/>
</calculate>
<calculate field="createDetailMap.availableToPromiseDiff" decimal-scale="6">
<calcop field="oldQuantity" operator="add"/>
</calculate>
<call-service service-name="createInventoryItemDetail" in-map-name="createDetailMap"/>
</simple-method>
<simple-method method-name="cancelOrderItemIssuanceFromSalesShipment" short-description="Cancel an ItemIssuance quantity from Sales Shipment">
<!-- get ItemIssuance and related entities-->
<entity-one entity-name="ItemIssuance" value-field="itemIssuance"/>
<get-related-one value-field="itemIssuance" relation-name="OrderHeader" to-value-field="orderHeader"/>
<get-related-one value-field="itemIssuance" relation-name="InventoryItem" to-value-field="inventoryItem"/>
<get-related-one value-field="itemIssuance" relation-name="Shipment" to-value-field="shipment"/>
<!-- issuance can be canceled only if the sales shipment is not packed -->
<if-compare field="shipment.statusId" operator="not-equals" value="SHIPMENT_CANCELLED">
<set from-field="itemIssuance.shipmentId" field="shipmentId"/>
<call-simple-method method-name="checkCanChangeShipmentStatusPacked" xml-resource="component://product/script/org/ofbiz/shipment/shipment/ShipmentServices.xml"/>
<check-errors/>
</if-compare>
<!-- make sure the order is of orderTypeId: SALES_ORDER -->
<if-compare field="orderHeader.orderTypeId" operator="not-equals" value="SALES_ORDER">
<add-error>
<fail-property resource="ProductUiLabels" property="ProductNotIssueOrderForNotSalesOrders"/>
</add-error>
</if-compare>
<!-- get the quantity that can be cancelled ItemIssuance -->
<calculate field="qtyIssuedLeft">
<calcop field="itemIssuance.quantity" operator="subtract">
<calcop operator="get" field="itemIssuance.cancelQuantity"/>
</calcop>
</calculate>
<!-- if not provided, get the left issued quantity -->
<set from-field="parameters.cancelQuantity" field="toCancelQuantity"/>
<if-empty field="toCancelQuantity">
<set from-field="qtyIssuedLeft" field="toCancelQuantity"/>
</if-empty>
<!-- make sure specified cancel Quantity is not less than or equal to 0 -->
<if-compare field="toCancelQuantity" operator="less" value="0" type="BigDecimal">
<add-error>
<fail-property resource="ProductUiLabels" property="ProductNotIssueOrderQuantityCancelLess"/>
</add-error>
</if-compare>
<if-compare field="toCancelQuantity" operator="equals" value="0" type="BigDecimal">
<return response-code="success"/>
</if-compare>
<!-- make sure specified quantity is not greater than issued quantity left -->
<if-compare-field field="toCancelQuantity" to-field="qtyIssuedLeft" operator="greater" type="BigDecimal">
<add-error>
<fail-property resource="ProductUiLabels" property="ProductNotIssueOrderQuantityCancelGreater"/>
</add-error>
</if-compare-field>
<check-errors/>
<!-- update ItemIssuance -->
<calculate field="totalCancelQty">
<calcop operator="add" field="itemIssuance.cancelQuantity"/>
<calcop operator="add" field="toCancelQuantity"/>
</calculate>
<set from-field="totalCancelQty" field="itemIssuanceUpdate.cancelQuantity"/>
<set from-field="parameters.itemIssuanceId" field="itemIssuanceUpdate.itemIssuanceId"/>
<call-service service-name="updateItemIssuance" in-map-name="itemIssuanceUpdate"/>
<!-- increment InventoryItem quantityOnHand AND availableToPromise -->
<!-- instead of updating InventoryItem, add an InventoryItemDetail -->
<set from-field="itemIssuance.inventoryItemId" field="createDetailMap.inventoryItemId"/>
<set from-field="itemIssuance.itemIssuanceId" field="createDetailMap.itemIssuanceId"/>
<set from-field="toCancelQuantity" field="createDetailMap.availableToPromiseDiff"/>
<set from-field="toCancelQuantity" field="createDetailMap.quantityOnHandDiff"/>
<call-service service-name="createInventoryItemDetail" in-map-name="createDetailMap"/>
<!-- reassign inventory reservations -->
<set field="reassignInventoryReservationsCtx.productId" from-field="inventoryItem.productId"/>
<set field="reassignInventoryReservationsCtx.facilityId" from-field="inventoryItem.facilityId"/>
<call-service service-name="reassignInventoryReservations" in-map-name="reassignInventoryReservationsCtx"/>
<!-- reserve the order item -->
<entity-one entity-name="ProductStore" value-field="productStore" auto-field-map="false">
<field-map field-name="productStoreId" from-field="orderHeader.productStoreId"/>
</entity-one>
<if-compare value="Y" operator="equals" field="productStore.isImmediatelyFulfilled">
<log level="verbose" message="ProductStore with id ${productStore.productStoreId}, is immediatly fulfilled. Not reserving inventory"/>
<else>
<set field="reserveStoreInventoryMap.productId" from-field="inventoryItem.productId"/>
<set field="reserveStoreInventoryMap.orderId" from-field="itemIssuance.orderId"/>
<set field="reserveStoreInventoryMap.orderItemSeqId" from-field="itemIssuance.orderItemSeqId"/>
<set field="reserveStoreInventoryMap.shipGroupSeqId" from-field="itemIssuance.shipGroupSeqId"/>
<set field="reserveStoreInventoryMap.quantity" from-field="toCancelQuantity"/>
<set field="reserveStoreInventoryMap.productStoreId" from-field="orderHeader.productStoreId"/>
<call-service service-name="reserveStoreInventory" in-map-name="reserveStoreInventoryMap"/>
</else>
</if-compare>
<field-to-result field="toCancelQuantity" result-name="canceledQuantity"/>
</simple-method>
<simple-method method-name="issueInventoryItemToShipment" short-description="Issue InventoryItem To Shipment">
<set field="shipmentId" from-field="parameters.shipmentId"/>
<set field="shipmentItemSeqId" from-field="parameters.shipmentItemSeqId"/>
<entity-one entity-name="InventoryItem" value-field="inventoryItem"/>
<entity-and entity-name="ReturnItemShipment" list="returnItemShipments">
<field-map field-name="shipmentId" from-field="parameters.shipmentId"/>
<field-map field-name="shipmentItemSeqId" from-field="parameters.shipmentItemSeqId"/>
</entity-and>
<first-from-list list="returnItemShipments" entry="returnItemShipment"/>
<calculate field="quantityNotIssued">
<calcop operator="subtract" field="returnItemShipment.quantity">
<calcop operator="get" field="parameters.totalIssuedQty"/>
</calcop>
</calculate>
<!-- make sure specified quantity is not less than or equal to 0 -->
<if-compare field="parameters.quantity" operator="less-equals" value="0" type="BigDecimal">
<add-error>
<fail-property resource="ProductUiLabels" property="ProductNotIssueOrderToShipmentQuantityLess"/>
</add-error>
</if-compare>
<!-- make sure specified quantity is not greater than available quantity left to be issued, i.e. intentoryItem.availableToPromiseTotal -->
<if-compare-field field="parameters.quantity" to-field="inventoryItem.availableToPromiseTotal" operator="greater" type="BigDecimal">
<add-error>
<fail-property resource="ProductUiLabels" property="ProductNotIssueOrderToShipmentQuantityGreater"/>
</add-error>
</if-compare-field>
<!-- make sure specified quantity is not greater than total return quantity -->
<if-compare-field field="parameters.quantity" to-field="quantityNotIssued" operator="greater" type="BigDecimal">
<add-error>
<fail-property resource="ProductUiLabels" property="ProductNotIssueOrderToShipmentQuantityReturnGreater"/>
</add-error>
</if-compare-field>
<check-errors/>
<!-- create the ItemIssuance -->
<set field="itemIssuanceCreate.quantity" from-field="parameters.quantity"/>
<set field="itemIssuanceCreate.inventoryItemId" from-field="parameters.inventoryItemId"/>
<set field="itemIssuanceCreate.shipmentId" from-field="shipmentId"/>
<set field="itemIssuanceCreate.shipmentItemSeqId" from-field="shipmentItemSeqId"/>
<set field="itemIssuanceCreate.issuedByUserLoginId" from-field="userLogin.userLoginId"/>
<call-service service-name="createItemIssuance" in-map-name="itemIssuanceCreate">
<result-to-field result-name="itemIssuanceId"/>
</call-service>
<field-to-result field="itemIssuanceId"/>
<set field="createDetailMap.inventoryItemId" from-field="inventoryItem.inventoryItemId"/>
<set field="createDetailMap.itemIssuanceId" from-field="itemIssuanceId"/>
<set field="createDetailMap.shipmentId" from-field="shipmentId"/>
<set field="createDetailMap.shipmentItemSeqId" from-field="shipmentItemSeqId"/>
<calculate field="createDetailMap.quantityOnHandDiff" decimal-scale="6">
<calcop field="parameters.quantity" operator="negative"/>
</calculate>
<calculate field="createDetailMap.availableToPromiseDiff" decimal-scale="6">
<calcop field="parameters.quantity" operator="negative"/>
</calculate>
<call-service service-name="createInventoryItemDetail" in-map-name="createDetailMap"/>
</simple-method>
<simple-method method-name="getTotalIssuedQuantityForOrderItem" short-description="Computes the total quantity assigned to shipment for a purchase order item">
<set field="totalIssuedQuantity" type="BigDecimal" value="0"/>
<entity-and list="orderShipments" entity-name="OrderShipment">
<field-map field-name="orderId" from-field="orderItem.orderId"/>
<field-map field-name="orderItemSeqId" from-field="orderItem.orderItemSeqId"/>
</entity-and>
<if-not-empty field="orderShipments">
<iterate entry="orderShipment" list="orderShipments">
<set field="totalIssuedQuantity" value="${totalIssuedQuantity$bigDecimal + orderShipment.quantity$bigDecimal}" type="BigDecimal"/>
</iterate>
<else>
<!-- This is here for backward compatibility only: ItemIssuances are no more created for purchase orders -->
<entity-and list="allItemIssuances" entity-name="ItemIssuance">
<field-map field-name="orderId" from-field="orderItem.orderId"/>
<field-map field-name="orderItemSeqId" from-field="orderItem.orderItemSeqId"/>
</entity-and>
<iterate entry="itemIssuance" list="allItemIssuances">
<set field="totalIssuedQuantity" value="${totalIssuedQuantity$bigDecimal + itemIssuance.quantity$bigDecimal}" type="BigDecimal"/>
</iterate>
</else>
</if-not-empty>
</simple-method>
</simple-methods>