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 <[email protected]>
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">