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 c0054e9 Improved: Convert ProductStoreServices.xml file from mini-lang to groovy DSL (OFBIZ-11449) c0054e9 is described below commit c0054e97ea8d5baf09fc10613c96a7bb3381640a Author: Nicolas Malin <[hidden email]> AuthorDate: Wed Sep 16 09:34:22 2020 +0200 Improved: Convert ProductStoreServices.xml file from mini-lang to groovy DSL (OFBIZ-11449) Thanks to Sebastian Berg for this patch --- .../product/store/ProductStoreServices.groovy | 464 ++++++++++++++++++ .../product/store/ProductStoreServices.xml | 542 --------------------- applications/product/servicedef/services_store.xml | 32 +- 3 files changed, 480 insertions(+), 558 deletions(-) diff --git a/applications/product/groovyScripts/product/store/ProductStoreServices.groovy b/applications/product/groovyScripts/product/store/ProductStoreServices.groovy new file mode 100644 index 0000000..9f05ebb --- /dev/null +++ b/applications/product/groovyScripts/product/store/ProductStoreServices.groovy @@ -0,0 +1,464 @@ +/* + * 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 org.apache.ofbiz.base.util.Debug +import org.apache.ofbiz.entity.condition.EntityCondition +import org.apache.ofbiz.entity.condition.EntityConditionBuilder + +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.EntityTypeUtil +import org.apache.ofbiz.entity.util.EntityUtil +import org.apache.ofbiz.service.ServiceUtil + + +/** + * Create a Product Store + * @return + */ +def createProductStore() { + Map result = success() + if (!security.hasEntityPermission("CATALOG", "_CREATE", parameters.userLogin)) { + return error(UtilProperties.getMessage("ProductUiLabels", "ProductCatalogCreatePermissionError", parameters.locale)) + } + if ("Y" == parameters.oneInventoryFacility + && !parameters.inventoryFacilityId) { + return error(UtilProperties.getMessage("ProductUiLabels", "InventoryFacilityIdRequired", parameters.locale)) + } + if ("Y" == parameters.showPriceWithVatTax) { + if (!parameters.vatTaxAuthGeoId) { + return error(UtilProperties.getMessage("ProductUiLabels", "ProductVatTaxAuthGeoNotSet", parameters.locale)) + } + if (!parameters.vatTaxAuthPartyId) { + return error(UtilProperties.getMessage("ProductUiLabels", "ProductVatTaxAuthPartyNotSet", parameters.locale)) + } + } + GenericValue newEntity = makeValue("ProductStore") + newEntity.setNonPKFields(parameters) + String productStoreId = delegator.getNextSeqId("ProductStore") + newEntity.productStoreId = productStoreId + newEntity.create() + + // create the ProductStoreFacility record + if (newEntity.inventoryFacilityId) { + makeValue("ProductStoreFacility", [ + facilityId: newEntity.inventoryFacilityId, + productStoreId: newEntity.productStoreId, + fromDate: UtilDateTime.nowTimestamp()]) + .create() + } + result.productStoreId = productStoreId + return result +} + +/** + * Update a Product Store + * @return + */ +def updateProductStore() { + if (!security.hasEntityPermission("CATALOG", "_UPDATE", parameters.userLogin)) { + return error(UtilProperties.getMessage("ProductUiLabels", "ProductCatalogUpdatePermissionError", parameters.locale)) + } + if ("Y" == parameters.oneInventoryFacility + && !parameters.inventoryFacilityId) { + return error(UtilProperties.getMessage("ProductUiLabels", "InventoryFacilityIdRequired", parameters.locale)) + } + GenericValue store = from("ProductStore").where(productStoreId: parameters.productStoreId).queryOne() + String oldFacilityId = store.inventoryFacilityId + store.setNonPKFields(parameters) + + // visualThemeId must be replaced by ecomThemeId because of Entity.field names conflict. See OFBIZ-10567 + store.visualThemeId = parameters.ecomThemeId + if ("Y" == store.showPricesWithVatTax) { + if (!store.vatTaxAuthGeoId) { + return error(UtilProperties.getMessage("ProductUiLabels", "ProductVatTaxAuthGeoNotSet", parameters.locale)) + } + if (!store.vatTaxAuthPartyId) { + return error(UtilProperties.getMessage("ProductUiLabels", "ProductVatTaxAuthPartyNotSet", parameters.locale)) + } + } + store.store() + + // update the ProductStoreFacility record + Timestamp nowTimestamp = UtilDateTime.nowTimestamp() + if (oldFacilityId != store.inventoryFacilityId) { + if ("Y" == store.oneInventoryFacility) { + // expire all the facilities + EntityConditionBuilder exprBldr = new EntityConditionBuilder() + EntityCondition thruDateCondition = exprBldr.OR() { + EQUALS(thruDate: null) + GREATER_THAN_EQUAL_TO(thruDate: nowTimestamp) + } + EntityCondition condition = exprBldr.AND(thruDateCondition) { + EQUALS(productStoreId: store.productStoreId) + LESS_THAN_EQUAL_TO(fromDate: nowTimestamp) + } + delegator.storeByCondition("ProductStoreFacility", condition, [thruDate: nowTimestamp]) + } + // create the new entry + makeValue("ProductStoreFacility", [ + facilityId: store.inventoryFacilityId, + productStoreId: store.productStoreId, + fromDate: nowTimestamp]) + .create() + } + return success() +} + +// Store Inventory Services + +/** + * Reserve Store Inventory + * @return + */ +def reserveStoreInventory() { + Map result = success() + BigDecimal quantityNotReserved + + GenericValue productStore = from("ProductStore").where(parameters).cache().queryOne() + if (!productStore) { + return error(UtilProperties.getMessage("ProductUiLabels", "ProductProductStoreNotFound", parameters.locale)) + } + + GenericValue product = from("Product").where(parameters).cache().queryOne() + GenericValue orderHeader = from("OrderHeader").where(parameters).cache().queryOne() + parameters.priority = orderHeader.priority + + // if prodCatalog is set to not reserve inventory, break here + if ("N" == productStore.reserveInventory) { + // note: if not set, defaults to yes, reserve inventory + logVerbose("ProductStore with id [" + productStore.productStoreId + "], is set to NOT reserve inventory, not reserving inventory") + result.quantityNotReserved = parameters.quantity + return result + } + String requireInventory = isStoreInventoryRequiredInline(product, productStore) + String facilityId = parameters.facilityId + if (!facilityId) { + if ("Y" == productStore.oneInventoryFacility) { + if (!productStore.inventoryFacilityId) { + return error(UtilProperties.getMessage("ProductUiLabels", "ProductProductStoreNoSpecifiedInventoryFacility", parameters.locale)) + } + Map serviceResult = run service: "reserveProductInventoryByFacility", with: [*: parameters, + facilityId: productStore.inventoryFacilityId, + requireInventory: requireInventory, + reserveOrderEnumId: productStore.reserveOrderEnumId] + quantityNotReserved = serviceResult.quantityNotReserved + + if (Debug.infoOn()) { + if (quantityNotReserved == (BigDecimal) 0) { + logInfo("Inventory IS reserved in facility with id [${productStore.inventoryFacilityId}] for product id [${parameters.productId}]; desired quantity was ${parameters.quantity}") + } else { + logInfo("There is insufficient inventory available in facility with id [${productStore.inventoryFacilityId}] for product id [${parameters.productId}]; desired quantity is ${parameters.quantity}, amount could not reserve is ${quantityNotReserved}") + } + } + } else { + GenericValue storeFound + List productStoreFacilities = from("ProductStoreFacility") + .where(productStoreId: productStore.productStoreId) + .orderBy("sequenceNum") + .cache() + .queryList() + for (GenericValue productStoreFacility : productStoreFacilities) { + // in this case quantityNotReserved will always be empty until it finds a facility it can totally reserve from, then it will be 0.0 and we are done + if (!storeFound) { + // TODO: must entire quantity be available in one location? + // Right now the answer is yes, it only succeeds if one facility has sufficient inventory for the order. + Map callServiceMapIABF = [productId: parameters.productId, facilityId: productStoreFacility.facilityId] + logInfo("ProductStoreService:In productStoreFacilities loop: [" + parameters.facilityId + "]") + Map serviceResultIABF = run service: "getInventoryAvailableByFacility", with: callServiceMapIABF + BigDecimal availableToPromiseTotal = serviceResultIABF.availableToPromiseTotal + + if (availableToPromiseTotal >= parameters.quantity) { + storeFound = productStoreFacility + } + } + } + // didn't find anything? Take the first facility from list + if (!storeFound) { + storeFound = productStoreFacilities.get(0) + } + facilityId = storeFound.facilityId ?: "" + Map serviceResult = run service: "reserveProductInventoryByFacility", with: [*: parameters, + facilityId: facilityId, + requireInventory: requireInventory, + reserveOrderEnumId: productStore.reserveOrderEnumId] + quantityNotReserved = serviceResult.quantityNotReserved + logInfo("Inventory IS reserved in facility with id [${storeFound.facilityId}] for product id [${parameters.productId}]; desired quantity was ${parameters.quantity}") + } + } else { + List productStoreFacilities = from("ProductStoreFacility").where(productStoreId: productStore.productStoreId, facilityId: facilityId).cache().orderBy("sequenceNum").queryList() + GenericValue facilityFound + for (GenericValue productStoreFacility : productStoreFacilities) { + // Search Product Store Facilities to insure the facility passed in is associated to the Product Store passed in + facilityFound = productStoreFacility + logInfo("ProductStoreService:Facility Found : [" + facilityFound + "]") + } + if (!facilityFound) { + return error(UtilProperties.getMessage("ProductUiLabels", "FacilityNoAssociatedWithProcuctStore", parameters.locale)) + } + Map serviceResult = run service: "reserveProductInventoryByFacility", with: [*: parameters, + facilityId: facilityId, + requireInventory: requireInventory, + reserveOrderEnumId: productStore.reserveOrderEnumId] + quantityNotReserved = serviceResult.quantityNotReserved + if (Debug.infoOn()) { + if (quantityNotReserved == (BigDecimal) 0) { + logInfo("Inventory IS reserved in facility with id [${facilityId}] for product id [${parameters.productId}]; desired quantity was ${parameters.quantity}") + } else { + logInfo("There is insufficient inventory available in facility with id [${facilityId}] for product id [${parameters.productId}]; desired quantity is ${parameters.quantity}, amount could not reserve is ${quantityNotReserved}") + } + } + } + result.quantityNotReserved = quantityNotReserved + return result +} + +/** + * Is Store Inventory Required + * @return + */ +def isStoreInventoryRequired() { + GenericValue productStore = parameters.productStore ?: from("ProductStore").where(parameters).cache().queryOne() + GenericValue product = parameters.product ?: from("Product").where(parameters).cache().queryOne() + + Map result = success() + result.requireInventory = isStoreInventoryRequiredInline(product, productStore) + return result +} + +/** + * Is Store Inventory Required + * @param product + * @param productStore + * @return + */ +def isStoreInventoryRequiredInline(GenericValue product, GenericValue productStore) { + String requireInventory = product.requireInventory + requireInventory = requireInventory ?: productStore.requireInventory + requireInventory = requireInventory ?: "Y" + return requireInventory +} + +/** + * Is Store Inventory Available + * @return + */ +def isStoreInventoryAvailable() { + Map result = success() + GenericValue productStore = parameters.productStore ?: from("ProductStore").where(parameters).cache().queryOne() + GenericValue product = parameters.product ?: from("Product").where(parameters).cache().queryOne() + + BigDecimal availableToPromiseTotal + String available + + // If the given product is a SERVICE or DIGITAL_GOOD + if (product.productTypeId == "SERVICE" || product.productTypeId == "DIGITAL_GOOD") { + logVerbose("Product with id ${product.productId}, is of type ${product.productTypeId}, returning true for inventory available check") + result.available = "Y" + return result + } + + // TODO: what to do with ASSET_USAGE? Only done elsewhere? Would need date/time range info to check availability + + // if prodCatalog is set to not check inventory break here + if ("N" == productStore.checkInventory) { + logVerbose("ProductStore with id ${productStore.productStoreId}, is set to NOT check inventory," + + " returning true for inventory available check") + result.available = "Y" + return result + } + if ("Y" == productStore.oneInventoryFacility) { + if (!productStore.inventoryFacilityId) { + return error(UtilProperties.getMessage("ProductUiLabels", "ProductProductStoreNotCheckAvailability", parameters.locale)) + } + boolean isMarketingPkg = EntityTypeUtil.hasParentType(delegator, 'ProductType', 'productTypeId', + product.productTypeId, 'parentTypeId', 'MARKETING_PKG') + String serviceName = isMarketingPkg ? "getMktgPackagesAvailable" : "getInventoryAvailableByFacility" + Map serviceResult = run service: serviceName, with: [productId: parameters.productId, + facilityId: productStore.inventoryFacilityId] + availableToPromiseTotal = serviceResult.availableToPromiseTotal + + // check to see if we got enough back... + if (availableToPromiseTotal >= parameters.quantity) { + available = "Y" + logInfo("Inventory IS available in facility with id ${productStore.inventoryFacilityId} for " + + "product id ${parameters.productId}; desired quantity is ${parameters.quantity}," + + "available quantity is ${availableToPromiseTotal}") + } else { + available = "N" + logInfo("Returning false because there is insufficient inventory available in facility with id " + + "${productStore.inventoryFacilityId} for product id ${parameters.productId}; desired quantity" + + " is ${parameters.quantity}, available quantity is ${availableToPromiseTotal}") + } + } else { + List productStoreFacilities = from("ProductStoreFacility") + .where(productStoreId: productStore.productStoreId) + .orderBy("sequenceNum") + .cache() + .queryList() + available = "N" + for (GenericValue productStoreFacility : productStoreFacilities) { + // TODO: must entire quantity be available in one location? + // Right now the answer is yes, it only succeeds if one facility has sufficient inventory for the order. + boolean isMarketingPkg = EntityTypeUtil.hasParentType(delegator, 'ProductType', 'productTypeId' + , product.productTypeId, 'parentTypeId', 'MARKETING_PKG') + String serviceName = isMarketingPkg ? "getMktgPackagesAvailable" : "getInventoryAvailableByFacility" + Map serviceResult = run service: serviceName, with: [productId: parameters.productId, + facilityId: productStoreFacility.facilityId] + availableToPromiseTotal = serviceResult.availableToPromiseTotal + + if (availableToPromiseTotal >= parameters.quantity) { + available = "Y" + logInfo("Inventory IS available in facility with id ${productStoreFacility.facilityId}" + + " for product id ${parameters.productId}; desired quantity is ${parameters.quantity}," + + " available quantity is ${availableToPromiseTotal}") + } + } + } + result.available = available + + /* TODO: must entire quantity be available in one location? + * Right now the answer is yes, it only succeeds if one facility has sufficient inventory for the order. + * When we get into splitting options it is much more complicated. There are various options like: + * - allow split between facilities + * - in split order facilities by highest quantities + * - in split order facilities by lowest quantities + * - in split order facilities by order in database, ie sequence numbers on facility-store join table + * - in split order facilities by nearest locations to customer (not an easy one there...) + */ + // loop through all facilities attached to this catalog and check for individual or cumulative sufficient inventory + return result +} + +/** + * Is Store Inventory Available or Not Required + * @return + */ +def isStoreInventoryAvailableOrNotRequired() { + Map result = success() + GenericValue productStore = parameters.productStore ?: from("ProductStore").where(parameters).cache().queryOne() + GenericValue product = parameters.product ?: from("Product").where(parameters).cache().queryOne() + if ("Y" != isStoreInventoryRequiredInline(product, productStore)) { + result.availableOrNotRequired = "Y" + } else { + Map serviceResult = run service: "isStoreInventoryAvailable", with: parameters + result.availableOrNotRequired = serviceResult.available + } + return result +} + +/* + * ============================= + * Permission Methods + * ============================= + */ + +// a methods to centralize product security code, meant to be called in-line with +// call-simple-method, and the checkAction and callingMethodName attributes should be in the method context + +/** + * Check ProductStore Related Permission + * @return + */ +def checkProductStoreRelatedPermission(Map inputParameter) { + List roleStores + String callingMethodName = inputParameter.resourceDescription + String checkAction = inputParameter.mainAction + String productStoreIdName = inputParameter.productStoreIdName + String productStoreIdToCheck = inputParameter.productStoreIdToCheck + if (!callingMethodName) { + callingMethodName = UtilProperties.getMessage("CommonUiLabels", "CommonPermissionThisOperation", locale) + } + if (!checkAction) { + checkAction = "UPDATE" + } + if (!productStoreIdName) { + productStoreIdName = inputParameter.productStoreId + } + if (!productStoreIdToCheck) { + productStoreIdToCheck = inputParameter.productstoreIdName + } + + // find all role-store that this productStore is a member of + if (!security.hasEntityPermission("CATALOG", ("_" + checkAction), userLogin)) { + roleStores = from("ProductStoreRole").where(productStoreId: productStoreIdToCheck, partyId: userLogin.partyId, roleTypeId: "LTD_ADMIN").filterByDate().queryList() + roleStores = EntityUtil.filterByDate(roleStores, UtilDateTime.nowTimestamp(), "roleFromDate", "roleThruDate", true) + } + logInfo("Checking store permission, roleStores=${roleStores}") + if (!(security.hasEntityPermission("CATALOG", ("_" + checkAction), userLogin) || + (security.hasEntityPermission("CATALOG_ROLE", ("_" + checkAction), userLogin) && roleStores))) { + logVerbose("Permission check failed, user does not have permission") + String checkActionLabel = 'ProductCatalog' + checkAction.charAt(0) + checkAction.substring(1).toLowerCase() + 'PermissionError' + return error(UtilProperties.getMessage("ProductUiLabels", checkActionLabel, locale)) + } + return success() +} + +/** + * Main permission logic + * @return + */ +def productStoreGenericPermission() { + Map result = success() + if (!parameters.mainAction) { + String errorMessage = UtilProperties.getMessage("ProductUiLabels", "ProductMissingMainActionInPermissionService", parameters.locale) + logError(errorMessage) + return error(errorMessage) + } + Map serviceInMap = parameters + Map serviceResult = checkProductStoreRelatedPermission(serviceInMap) + if (ServiceUtil.isSuccess(serviceResult)) { + result.hasPermission = true + } else { + String failMessage = UtilProperties.getMessage("ProductUiLabels", "ProductPermissionError", parameters.locale) + result.failMessage = failMessage + result.hasPermission = false + } + return result +} + +/** + * When product store group hierarchy has been operate, synchronize primaryParentGroupId with ProductStoreGroupRollup + * @return + */ +def checkProductStoreGroupRollup() { + GenericValue productStoreGroup = from("ProductStoreGroup").where(parameters).queryOne() + if (!parameters.primaryParentGroupId) { + GenericValue productStoreGroupRollup = from("ProductStoreGroupRollup").where(parameters).queryOne() + if (productStoreGroupRollup) { + productStoreGroup.primaryParentGroupId = productStoreGroupRollup.parentGroupId + run service: "updateProductStoreGroup", with: productStoreGroup.getAllFields() + } + } else { + if (from("ProductStoreGroupRollup") + .where(productStoreGroupId: productStoreGroup.productStoreGroupId, + parentGroupId: parameters.primaryParentGroupId) + .filterByDate() + .queryCount() == 0) { + run service: "createProductStoreGroupRollup", with: [productStoreGroupId: productStoreGroup.productStoreGroupId, + parentGroupId: parameters.primaryParentGroupId, + fromDate: UtilDateTime.nowTimestamp()] + } + } + return success() +} \ No newline at end of file diff --git a/applications/product/minilang/product/store/ProductStoreServices.xml b/applications/product/minilang/product/store/ProductStoreServices.xml deleted file mode 100644 index e5baab4..0000000 --- a/applications/product/minilang/product/store/ProductStoreServices.xml +++ /dev/null @@ -1,542 +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="createProductStore" short-description="Create a Product Store"> - <check-permission permission="CATALOG" action="_CREATE"> - <fail-property resource="ProductUiLabels" property="ProductCatalogCreatePermissionError"/> - </check-permission> - <check-errors/> - - <if-compare field="parameters.oneInventoryFacility" operator="equals" value="Y"> - <if-empty field="parameters.inventoryFacilityId"> - <add-error> - <fail-property resource="ProductUiLabels" property="InventoryFacilityIdRequired"/> - </add-error> - </if-empty> - <check-errors/> - </if-compare> - - <if-compare field="parameters.showPricesWithVatTax" operator="equals" value="Y"> - <if-empty field="parameters.vatTaxAuthGeoId"> - <add-error> - <fail-property resource="ProductUiLabels" property="ProductVatTaxAuthGeoNotSet"/> - </add-error> - </if-empty> - <if-empty field="parameters.vatTaxAuthPartyId"> - <add-error> - <fail-property resource="ProductUiLabels" property="ProductVatTaxAuthPartyNotSet"/> - </add-error> - </if-empty> - <check-errors/> - </if-compare> - - <make-value entity-name="ProductStore" value-field="newEntity"/> - <set-nonpk-fields map="parameters" value-field="newEntity"/> - - <sequenced-id sequence-name="ProductStore" field="productStoreId"/> - <set from-field="productStoreId" field="newEntity.productStoreId"/> - - <field-to-result field="productStoreId" result-name="productStoreId"/> - <create-value value-field="newEntity"/> - - <!-- create the ProductStoreFacility record --> - <now-timestamp field="nowTimestamp"/> - - <if-not-empty field="newEntity.inventoryFacilityId"> - <make-value entity-name="ProductStoreFacility" value-field="storeFacility"/> - <set from-field="newEntity.inventoryFacilityId" field="storeFacility.facilityId"/> - <set from-field="newEntity.productStoreId" field="storeFacility.productStoreId"/> - <set from-field="nowTimestamp" field="storeFacility.fromDate"/> - <create-value value-field="storeFacility"/> - </if-not-empty> - </simple-method> - <simple-method method-name="updateProductStore" short-description="Update a Product Store"> - <check-permission permission="CATALOG" action="_UPDATE"> - <fail-property resource="ProductUiLabels" property="ProductCatalogUpdatePermissionError"/> - </check-permission> - <check-errors/> - - <if-compare field="parameters.oneInventoryFacility" operator="equals" value="Y"> - <if-empty field="parameters.inventoryFacilityId"> - <add-error> - <fail-property resource="ProductUiLabels" property="InventoryFacilityIdRequired"/> - </add-error> - </if-empty> - <check-errors/> - </if-compare> - - <set from-field="parameters.productStoreId" field="lookupPKMap.productStoreId"/> - <find-by-primary-key entity-name="ProductStore" map="lookupPKMap" value-field="store"/> - <set from-field="store.inventoryFacilityId" field="oldFacilityId"/> - <set-nonpk-fields map="parameters" value-field="store"/> - - <!-- visualThemeId must be replaced by ecomThemeId because of Entity.field names conflict. See OFBIZ-10567 --> - <set field="store.visualThemeId" from-field="parameters.ecomThemeId"/> - - <if-compare field="store.showPricesWithVatTax" operator="equals" value="Y"> - <if-empty field="store.vatTaxAuthGeoId"> - <add-error> - <fail-property resource="ProductUiLabels" property="ProductVatTaxAuthGeoNotSet"/> - </add-error> - </if-empty> - <if-empty field="store.vatTaxAuthPartyId"> - <add-error> - <fail-property resource="ProductUiLabels" property="ProductVatTaxAuthPartyNotSet"/> - </add-error> - </if-empty> - <check-errors/> - </if-compare> - - <store-value value-field="store"/> - - <!-- update the ProductStoreFacility record --> - <now-timestamp field="nowTimestamp"/> - <if-compare-field field="store.inventoryFacilityId" to-field="oldFacilityId" operator="not-equals"> - <if-compare field="store.oneInventoryFacility" operator="equals" value="Y"> - <!-- expire all the facilities --> - <set from-field="store.productStoreId" field="lookupPFMap.productStoreId"/> - <find-by-and entity-name="ProductStoreFacility" map="lookupPFMap" list="storeFacilities"/> - <filter-list-by-date list="storeFacilities"/> - <iterate list="storeFacilities" entry="facility"> - <set from-field="nowTimestamp" field="facility.thruDate"/> - <store-value value-field="facility"/> - </iterate> - </if-compare> - <!-- create the new entry --> - <make-value entity-name="ProductStoreFacility" value-field="storeFacility"/> - <set from-field="store.inventoryFacilityId" field="storeFacility.facilityId"/> - <set from-field="store.productStoreId" field="storeFacility.productStoreId"/> - <set from-field="nowTimestamp" field="storeFacility.fromDate"/> - <create-value value-field="storeFacility"/> - </if-compare-field> - </simple-method> - - <!-- Store Inventory Services --> - <simple-method method-name="reserveStoreInventory" short-description="Reserve Store Inventory"> - <entity-one entity-name="Product" value-field="product" use-cache="true"/> - <entity-one entity-name="ProductStore" value-field="productStore" use-cache="true"/> - <entity-one entity-name="OrderHeader" value-field="orderHeader"/> - <set field="parameters.priority" from-field="orderHeader.priority"/> - <if-empty field="productStore"> - <add-error> - <fail-property resource="ProductUiLabels" property="ProductProductStoreNotFound"/> - </add-error> - <check-errors/> - </if-empty> - - <!-- if prodCatalog is set to not reserve inventory, break here --> - <if-compare value="N" operator="equals" field="productStore.reserveInventory"> - <!-- note: if not set, defaults to yes, reserve inventory --> - <log level="verbose" message="ProductStore with id ${productStore.productStoreId}, is set to NOT reserve inventory, not reserving inventory"/> - <field-to-result field="parameters.quantity" result-name="quantityNotReserved"/> - <return response-code="success"/> - </if-compare> - - <call-simple-method method-name="isStoreInventoryRequiredInline"/> - - <set from-field="parameters.facilityId" field="facilityId"/> - <if-empty field="facilityId"> - <if-compare field="productStore.oneInventoryFacility" operator="equals" value="Y"> - <if-empty field="productStore.inventoryFacilityId"> - <add-error> - <fail-property resource="ProductUiLabels" property="ProductProductStoreNoSpecifiedInventoryFacility"/> - </add-error> - <check-errors/> - </if-empty> - <set-service-fields service-name="reserveProductInventoryByFacility" map="parameters" to-map="callServiceMap"/> - <set from-field="productStore.inventoryFacilityId" field="callServiceMap.facilityId"/> - <set from-field="requireInventory" field="callServiceMap.requireInventory"/> - <set from-field="productStore.reserveOrderEnumId" field="callServiceMap.reserveOrderEnumId"/> - <call-service service-name="reserveProductInventoryByFacility" in-map-name="callServiceMap"> - <result-to-field result-name="quantityNotReserved"/> - </call-service> - - <if-compare field="quantityNotReserved" operator="equals" value="0" type="BigDecimal"> - <log level="info" message="Inventory IS reserved in facility with id [${productStore.inventoryFacilityId}] for product id [${parameters.productId}]; desired quantity was ${parameters.quantity}"/> - <else> - <log level="info" message="There is insufficient inventory available in facility with id [${productStore.inventoryFacilityId}] for product id [${parameters.productId}]; desired quantity is ${parameters.quantity}, amount could not reserve is ${quantityNotReserved}"/> - </else> - </if-compare> - <else> - <entity-and entity-name="ProductStoreFacility" list="productStoreFacilities" use-cache="true"> - <field-map field-name="productStoreId" from-field="productStore.productStoreId"/> - <order-by field-name="sequenceNum"/> - </entity-and> - <iterate list="productStoreFacilities" entry="productStoreFacility"> - <!-- in this case quantityNotReserved will always be empty until it finds a facility it can totally reserve from, then it will be 0.0 and we are done --> - <if-empty field="storeFound"> - <!-- TODO: must entire quantity be available in one location? --> - <!-- Right now the answer is yes, it only succeeds if one facility has sufficient inventory for the order. --> - <set from-field="parameters.productId" field="callServiceMap.productId"/> - <set from-field="productStoreFacility.facilityId" field="callServiceMap.facilityId"/> - <log level="info" message="ProductStoreService:In productStoreFacilities loop: [${parameters.facilityId}]"/> - <call-service service-name="getInventoryAvailableByFacility" in-map-name="callServiceMap"> - <result-to-field result-name="availableToPromiseTotal"/> - </call-service> - <clear-field field="callServiceMap"/> - - <if-compare-field field="availableToPromiseTotal" to-field="parameters.quantity" operator="greater-equals" type="BigDecimal"> - <set field="storeFound" from-field="productStoreFacility"/> - </if-compare-field> - <clear-field field="availableToPromiseTotal"/> - </if-empty> - </iterate> - - <!-- didn't find anything? Take the first facility from list --> - <if-empty field="storeFound"> - <first-from-list list="productStoreFacilities" entry="storeFound"/> - </if-empty> - <set from-field="storeFound.facilityId" field="facilityId" default-value=""/> - <set-service-fields service-name="reserveProductInventoryByFacility" map="parameters" to-map="callServiceMap"/> - <set from-field="facilityId" field="callServiceMap.facilityId"/> - <set from-field="requireInventory" field="callServiceMap.requireInventory"/> - <set from-field="productStore.reserveOrderEnumId" field="callServiceMap.reserveOrderEnumId"/> - <call-service service-name="reserveProductInventoryByFacility" in-map-name="callServiceMap"> - <result-to-field result-name="quantityNotReserved"/> - </call-service> - <log level="info" message="Inventory IS reserved in facility with id [${storeFound.facilityId}] for product id [${parameters.productId}]; desired quantity was ${parameters.quantity}"/> - </else> - </if-compare> - <else> - <entity-and entity-name="ProductStoreFacility" list="productStoreFacilities" use-cache="true"> - <field-map field-name="productStoreId" from-field="productStore.productStoreId"/> - <field-map field-name="facilityId" from-field="facilityId"/> - <order-by field-name="sequenceNum"/> - </entity-and> - <iterate list="productStoreFacilities" entry="productStoreFacility"> - <!-- Search Product Store Facilities to insure the facility passed in is associated to the Product Store passed in --> - <set field="facilityFound" from-field="productStoreFacility"/> - <log level="info" message="ProductStoreService:Facility Found : [${facilityFound}]"/> - </iterate> - <if-empty field="facilityFound"> - <add-error> - <fail-property resource="ProductUiLabels" property="FacilityNoAssociatedWithProcuctStore"/> - </add-error> - <check-errors/> - </if-empty> - <set-service-fields service-name="reserveProductInventoryByFacility" map="parameters" to-map="callServiceMap"/> - <set from-field="facilityId" field="callServiceMap.facilityId"/> - <set from-field="requireInventory" field="callServiceMap.requireInventory"/> - <set from-field="productStore.reserveOrderEnumId" field="callServiceMap.reserveOrderEnumId"/> - <call-service service-name="reserveProductInventoryByFacility" in-map-name="callServiceMap"> - <result-to-field result-name="quantityNotReserved"/> - </call-service> - <if-compare field="quantityNotReserved" operator="equals" value="0" type="BigDecimal"> - <log level="info" message="Inventory IS reserved in facility with id [${facilityId}] for product id [${parameters.productId}]; desired quantity was ${parameters.quantity}"/> - <else> - <log level="info" message="There is insufficient inventory available in facility with id [${facilityId}] for product id [${parameters.productId}]; desired quantity is ${parameters.quantity}, amount could not reserve is ${quantityNotReserved}"/> - </else> - </if-compare> - </else> - </if-empty> - <field-to-result field="quantityNotReserved"/> - </simple-method> - - <simple-method method-name="isStoreInventoryRequired" short-description="Is Store Inventory Required" login-required="false"> - <if-empty field="parameters.productStore"> - <entity-one entity-name="ProductStore" value-field="productStore" use-cache="true"/> - <else> - <set from-field="parameters.productStore" field="productStore"/> - </else> - </if-empty> - <if-empty field="parameters.product"> - <entity-one entity-name="Product" value-field="product" use-cache="true"/> - <else> - <set from-field="parameters.product" field="product"/> - </else> - </if-empty> - - <call-simple-method method-name="isStoreInventoryRequiredInline"/> - <field-to-result field="requireInventory"/> - </simple-method> - <simple-method method-name="isStoreInventoryRequiredInline" short-description="Is Store Inventory Required" login-required="false"> - <set from-field="product.requireInventory" field="requireInventory"/> - <if-empty field="requireInventory"> - <set from-field="productStore.requireInventory" field="requireInventory"/> - </if-empty> - <if-empty field="requireInventory"> - <set value="Y" field="requireInventory"/> - </if-empty> - </simple-method> - - <simple-method method-name="isStoreInventoryAvailable" short-description="Is Store Inventory Available" login-required="false"> - <if-empty field="parameters.productStore"> - <entity-one entity-name="ProductStore" value-field="productStore" use-cache="true"/> - <else> - <set from-field="parameters.productStore" field="productStore"/> - </else> - </if-empty> - <if-empty field="parameters.product"> - <entity-one entity-name="Product" value-field="product" use-cache="true"/> - <else> - <set from-field="parameters.product" field="product"/> - </else> - </if-empty> - - <!-- If the given product is a SERVICE or DIGITAL_GOOD --> - <if> - <condition> - <or> - <if-compare field="product.productTypeId" operator="equals" value="SERVICE"/> - <if-compare field="product.productTypeId" operator="equals" value="DIGITAL_GOOD"/> - </or> - </condition> - <then> - <log level="verbose" message="Product with id ${product.productId}, is of type ${product.productTypeId}, returning true for inventory available check"/> - <set value="Y" field="available"/> - <field-to-result field="available"/> - <return/> - </then> - </if> - - <!-- TODO: what to do with ASSET_USAGE? Only done elsewhere? Would need date/time range info to check availability --> - - <!-- if prodCatalog is set to not check inventory break here --> - <if-compare field="productStore.checkInventory" operator="equals" value="N"> - <!-- note: if not set, defaults to yes, check inventory --> - <log level="verbose" message="ProductStore with id ${productStore.productStoreId}, is set to NOT check inventory, returning true for inventory available check"/> - <set value="Y" field="available"/> - <field-to-result field="available"/> - <return/> - </if-compare> - - <if-compare value="Y" operator="equals" field="productStore.oneInventoryFacility"> - <if-empty field="productStore.inventoryFacilityId"> - <add-error> - <fail-property resource="ProductUiLabels" property="ProductProductStoreNotCheckAvailability"/> - </add-error> - <check-errors/> - </if-empty> - - <set from-field="parameters.productId" field="callServiceMap.productId"/> - <set from-field="productStore.inventoryFacilityId" field="callServiceMap.facilityId"/> - <set field="isMarketingPkg" value="${groovy: org.apache.ofbiz.entity.util.EntityTypeUtil.hasParentType(delegator, 'ProductType', 'productTypeId', product.productTypeId, 'parentTypeId', 'MARKETING_PKG')}" type="Boolean"/> - <if-compare field="isMarketingPkg" operator="equals" value="true" type="Boolean"> - <call-service service-name="getMktgPackagesAvailable" in-map-name="callServiceMap"> - <result-to-field result-name="availableToPromiseTotal"/> - </call-service> - <else> - <call-service service-name="getInventoryAvailableByFacility" in-map-name="callServiceMap"> - <result-to-field result-name="availableToPromiseTotal"/> - </call-service> - </else> - </if-compare> - <!-- check to see if we got enough back... --> - <if-compare-field field="availableToPromiseTotal" to-field="parameters.quantity" operator="greater-equals" type="BigDecimal"> - <set value="Y" field="available"/> - <log level="info" message="Inventory IS available in facility with id ${productStore.inventoryFacilityId} for product id ${parameters.productId}; desired quantity is ${parameters.quantity}, available quantity is ${availableToPromiseTotal}"/> - <else> - <set value="N" field="available"/> - <log level="info" message="Returning false because there is insufficient inventory available in facility with id ${productStore.inventoryFacilityId} for product id ${parameters.productId}; desired quantity is ${parameters.quantity}, available quantity is ${availableToPromiseTotal}"/> - </else> - </if-compare-field> - <else> - <entity-and entity-name="ProductStoreFacility" list="productStoreFacilities" use-cache="true"> - <field-map field-name="productStoreId" from-field="productStore.productStoreId"/> - <order-by field-name="sequenceNum"/> - </entity-and> - - <set value="N" field="available"/> - <iterate list="productStoreFacilities" entry="productStoreFacility"> - <if-compare field="available" operator="equals" value="N"> - <!-- TODO: must entire quantity be available in one location? --> - <!-- Right now the answer is yes, it only succeeds if one facility has sufficient inventory for the order. --> - <set from-field="parameters.productId" field="callServiceMap.productId"/> - <set from-field="productStoreFacility.facilityId" field="callServiceMap.facilityId"/> - <set field="isMarketingPkg" value="${groovy: org.apache.ofbiz.entity.util.EntityTypeUtil.hasParentType(delegator, 'ProductType', 'productTypeId', product.productTypeId, 'parentTypeId', 'MARKETING_PKG')}" type="Boolean"/> - <if-compare field="isMarketingPkg" operator="equals" value="true" type="Boolean"> - <call-service service-name="getMktgPackagesAvailable" in-map-name="callServiceMap"> - <result-to-field result-name="availableToPromiseTotal"/> - </call-service> - <else> - <call-service service-name="getInventoryAvailableByFacility" in-map-name="callServiceMap"> - <result-to-field result-name="availableToPromiseTotal"/> - </call-service> - </else> - </if-compare> - - <clear-field field="callServiceMap"/> - - <if-compare-field field="availableToPromiseTotal" to-field="parameters.quantity" operator="greater-equals" type="BigDecimal"> - <set value="Y" field="available"/> - <log level="info" message="Inventory IS available in facility with id ${productStoreFacility.facilityId} for product id ${parameters.productId}; desired quantity is ${parameters.quantity}, available quantity is ${availableToPromiseTotal}"/> - </if-compare-field> - <clear-field field="availableToPromiseTotal"/> - </if-compare> - </iterate> - </else> - </if-compare> - - <field-to-result field="available"/> - - <!-- - /* TODO: must entire quantity be available in one location? - * Right now the answer is yes, it only succeeds if one facility has sufficient inventory for the order. - * When we get into splitting options it is much more complicated. There are various options like: - * - allow split between facilities - * - in split order facilities by highest quantities - * - in split order facilities by lowest quantities - * - in split order facilities by order in database, ie sequence numbers on facility-store join table - * - in split order facilities by nearest locations to customer (not an easy one there...) - */ - - // loop through all facilities attached to this catalog and check for individual or cumulative sufficient inventory - --> - </simple-method> - - <simple-method method-name="isStoreInventoryAvailableOrNotRequired" short-description="Is Store Inventory Available or Not Required" login-required="false"> - <if-empty field="parameters.productStore"> - <entity-one entity-name="ProductStore" value-field="productStore" use-cache="true"/> - <else> - <set from-field="parameters.productStore" field="productStore"/> - </else> - </if-empty> - <if-empty field="parameters.product"> - <entity-one entity-name="Product" value-field="product" use-cache="true"/> - <else> - <set from-field="parameters.product" field="product"/> - </else> - </if-empty> - - <call-simple-method method-name="isStoreInventoryRequiredInline"/> - - <if-compare field="requireInventory" operator="not-equals" value="Y"> - <set value="Y" field="availableOrNotRequired"/> - <field-to-result field="availableOrNotRequired"/> - <else> - <set-service-fields service-name="isStoreInventoryAvailable" map="parameters" to-map="callServiceMap"/> - <call-service service-name="isStoreInventoryAvailable" in-map-name="callServiceMap"> - <result-to-result result-name="available" service-result-name="availableOrNotRequired"/> - </call-service> - </else> - </if-compare> - </simple-method> - - <!-- ============================= --> - <!-- Permission Methods --> - <!-- ============================= --> - - <!-- a methods to centralize product security code, meant to be called in-line with - call-simple-method, and the checkAction and callingMethodName attributes should be in the method context --> - <simple-method method-name="checkProductStoreRelatedPermission" short-description="Check ProductStore Related Permission"> - <if-empty field="callingMethodName"> - <property-to-field resource="CommonUiLabels" property="CommonPermissionThisOperation" field="callingMethodName"/> - </if-empty> - <if-empty field="checkAction"> - <set field="checkAction" value="UPDATE"/> - </if-empty> - <if-empty field="productStoreIdName"> - <set field="productStoreIdName" value="productStoreId"/> - </if-empty> - <if-empty field="productStoreIdToCheck"> - <set field="productStoreIdToCheck" from-field="parameters.${productStoreIdName}"/> - </if-empty> - - <!-- find all role-store that this productStore is a member of --> - <if> - <condition> - <not><if-has-permission permission="CATALOG" action="_${checkAction}"/></not> - </condition> - <then> - <entity-and entity-name="ProductStoreRole" list="roleStores" filter-by-date="true"> - <field-map field-name="productStoreId" from-field="productStoreIdToCheck"/> - <field-map field-name="partyId" from-field="userLogin.partyId"/> - <field-map field-name="roleTypeId" value="LTD_ADMIN"/> - </entity-and> - <filter-list-by-date list="roleStores" from-field-name="roleFromDate" thru-field-name="roleThruDate"/> - </then> - </if> - <log level="info" message="Checking store permission, roleStores=${roleStores}"/> - <if> - <condition> - <not> - <or> - <if-has-permission permission="CATALOG" action="_${checkAction}"/> - <and> - <if-has-permission permission="CATALOG_ROLE" action="_${checkAction}"/> - <not><if-empty field="roleStores"/></not> - </and> - </or> - </not> - </condition> - <then> - <log level="verbose" message="Permission check failed, user does not have permission"/> - <set field="checkActionLabel" value="${groovy: 'ProductCatalog' + checkAction.charAt(0) + checkAction.substring(1).toLowerCase() + 'PermissionError'}"/> - <set field="resourceDescription" from-field="callingMethodName"/> - <add-error> - <fail-property resource="ProductUiLabels" property="${checkActionLabel}"/> - </add-error> - <set field="hasPermission" type="Boolean" value="false"/> - </then> - </if> - </simple-method> - <simple-method method-name="productStoreGenericPermission" short-description="Main permission logic"> - <set field="mainAction" from-field="parameters.mainAction"/> - <if-empty field="mainAction"> - <add-error> - <fail-property resource="ProductUiLabels" property="ProductMissingMainActionInPermissionService"/> - </add-error> - <check-errors/> - </if-empty> - - <set field="callingMethodName" from-field="parameters.resourceDescription"/> - <set field="checkAction" from-field="parameters.mainAction"/> - <call-simple-method method-name="checkProductStoreRelatedPermission"/> - - <if-empty field="error_list"> - <set field="hasPermission" type="Boolean" value="true"/> - <field-to-result field="hasPermission"/> - - <else> - <property-to-field resource="ProductUiLabels" property="ProductPermissionError" field="failMessage"/> - <set field="hasPermission" type="Boolean" value="false"/> - <field-to-result field="hasPermission"/> - <field-to-result field="failMessage"/> - </else> - </if-empty> - </simple-method> - - <simple-method method-name="checkProductStoreGroupRollup" short-description="When product store group hierarchy has been operate, synchronize primaryParentGroupId with ProductStoreGroupRollup"> - <entity-one entity-name="ProductStoreGroup" value-field="productStoreGroup"/> - <if-empty field="parameters.primaryParentGroupId"> - <entity-one entity-name="ProductStoreGroupRollup" value-field="productStoreGroupRollup"/> - <if-not-empty field="productStoreGroupRollup"> - <set field="productStoreGroup.primaryParentGroupId"/> - <set-service-fields service-name="updateProductStoreGroup" map="productStoreGroup" to-map="productStoreGroupMap"/> - <call-service service-name="updateProductStoreGroup" in-map-name="productStoreGroupMap"/> - </if-not-empty> - <else> - <entity-and entity-name="ProductStoreGroupRollup" list="productStoreGroupRollups" filter-by-date="true"> - <field-map field-name="productStoreGroupId" from-field="productStoreGroup.productStoreGroupId"/> - <field-map field-name="parentGroupId" from-field="parameters.primaryParentGroupId"/> - </entity-and> - <if-empty field="productStoreGroupRollups"> - <set field="productStoreGroupRollupMap.productStoreGroupId" from="productStoreGroup.productStoreGroupId"/> - <set field="productStoreGroupRollupMap.parentGroupId" from="parameters.primaryParentGroupId"/> - <set field="productStoreGroupRollupMap.fromDate" from="date:nowTimestamp()"/> - <call-service service-name="createProductStoreGroupRollup" in-map-name="productStoreGroupRollupMap"/> - </if-empty> - </else> - </if-empty> - </simple-method> -</simple-methods> - diff --git a/applications/product/servicedef/services_store.xml b/applications/product/servicedef/services_store.xml index fd06ffb..8dfe986 100644 --- a/applications/product/servicedef/services_store.xml +++ b/applications/product/servicedef/services_store.xml @@ -25,15 +25,15 @@ under the License. <version>1.0</version> <!-- Product Store Services --> - <service name="createProductStore" default-entity-name="ProductStore" engine="simple" - location="component://product/minilang/product/store/ProductStoreServices.xml" invoke="createProductStore"> + <service name="createProductStore" default-entity-name="ProductStore" engine="groovy" + location="component://product/groovyScripts/product/store/ProductStoreServices.groovy" invoke="createProductStore"> <description>Create a Product Store</description> <auto-attributes include="nonpk" mode="IN" optional="true"/> <auto-attributes include="pk" mode="OUT" optional="false"/> <override name="storeName" optional="false"/> </service> - <service name="updateProductStore" default-entity-name="ProductStore" engine="simple" - location="component://product/minilang/product/store/ProductStoreServices.xml" invoke="updateProductStore"> + <service name="updateProductStore" default-entity-name="ProductStore" engine="groovy" + location="component://product/groovyScripts/product/store/ProductStoreServices.groovy" invoke="updateProductStore"> <description>Update a Product Store</description> <auto-attributes include="pk" mode="IN" optional="false"/> <!-- visualThemeId must be replaced by ecomThemeId because of Entity.field names conflict. See OFBIZ-10567 --> @@ -43,8 +43,8 @@ under the License. <attribute name="ecomThemeId" mode="IN" type="String" optional="true"/> </service> - <service name="reserveStoreInventory" engine="simple" - location="component://product/minilang/product/store/ProductStoreServices.xml" invoke="reserveStoreInventory"> + <service name="reserveStoreInventory" engine="groovy" + location="component://product/groovyScripts/product/store/ProductStoreServices.groovy" invoke="reserveStoreInventory"> <description>Reserve Inventory in a Product Store</description> <attribute name="productStoreId" type="String" mode="IN" optional="false"> <type-validate> @@ -72,8 +72,8 @@ under the License. </attribute> </service> - <service name="isStoreInventoryRequired" engine="simple" - location="component://product/minilang/product/store/ProductStoreServices.xml" invoke="isStoreInventoryRequired" auth="false"> + <service name="isStoreInventoryRequired" engine="groovy" + location="component://product/groovyScripts/product/store/ProductStoreServices.groovy" invoke="isStoreInventoryRequired" auth="false"> <description>Checks if Store Inventory is Required</description> <attribute name="productStoreId" type="String" mode="IN" optional="false"> <type-validate> @@ -93,8 +93,8 @@ under the License. </type-validate> </attribute> </service> - <service name="isStoreInventoryAvailable" engine="simple" - location="component://product/minilang/product/store/ProductStoreServices.xml" invoke="isStoreInventoryAvailable" auth="false"> + <service name="isStoreInventoryAvailable" engine="groovy" + location="component://product/groovyScripts/product/store/ProductStoreServices.groovy" invoke="isStoreInventoryAvailable" auth="false"> <description>Checks if Store Inventory is Required</description> <attribute name="productStoreId" type="String" mode="IN" optional="false"> <type-validate> @@ -119,8 +119,8 @@ under the License. </type-validate> </attribute> </service> - <service name="isStoreInventoryAvailableOrNotRequired" engine="simple" - location="component://product/minilang/product/store/ProductStoreServices.xml" invoke="isStoreInventoryAvailableOrNotRequired" auth="false"> + <service name="isStoreInventoryAvailableOrNotRequired" engine="groovy" + location="component://product/groovyScripts/product/store/ProductStoreServices.groovy" invoke="isStoreInventoryAvailableOrNotRequired" auth="false"> <description>Checks if Store Inventory is Required</description> <attribute name="productStoreId" type="String" mode="IN" optional="false"> <type-validate> @@ -412,8 +412,8 @@ under the License. <description>Delete a ProductStoreGroupRollup</description> <auto-attributes include="pk" mode="IN" optional="false"/> </service> - <service name="checkProductStoreGroupRollup" engine="simple" - location="component://product/minilang/product/store/ProductStoreServices.xml" invoke="checkProductStoreGroupRollup" auth="true"> + <service name="checkProductStoreGroupRollup" engine="groovy" + location="component://product/groovyScripts/product/store/ProductStoreServices.groovy" invoke="checkProductStoreGroupRollup" auth="true"> <description>Check if a productStoreGroupId with a primaryParentGroupId has related productStoreGroupRollup or for first ProductStoreGroupRollup on a ProductStoreGroup set relation on primaryParentGroupId</description> <attribute name="productStoreGroupId" mode="IN" type="String"/> <attribute name="primaryParentGroupId" mode="IN" type="String" optional="true"/> @@ -422,8 +422,8 @@ under the License. </service> <!-- Permission Services --> - <service name="productStoreGenericPermission" engine="simple" - location="component://product/minilang/product/store/ProductStoreServices.xml" invoke="productStoreGenericPermission"> + <service name="productStoreGenericPermission" engine="groovy" + location="component://product/groovyScripts/product/store/ProductStoreServices.groovy" invoke="productStoreGenericPermission"> <implements service="permissionInterface"/> </service> <service name="createProductStoreGroupRole" default-entity-name="ProductStoreGroupRole" engine="entity-auto" invoke="create" auth="true"> |
Free forum by Nabble | Edit this page |