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
commit 80026c76c066f589a652bd00bb7699108cd66163 Author: Nicolas Malin <[email protected]> AuthorDate: Wed Mar 4 21:44:11 2020 +0100 Improved: Convert ProductServices.xml mini lang to groovy (OFBIZ-10231) After groovy conversion the method checkProductRelatedPermission has been broken for other minilang method that didn't converted. To solve this problem, I created new permission service checkProductRelatedPermission and convert all previous minilang method call by a permission service on the related service call --- .../product/product/ProductServices.groovy | 13 +- .../product/feature/ProductFeatureServices.xml | 5 - .../product/inventory/InventoryServices.xml | 9 +- .../minilang/product/price/PriceServices.xml | 9 - .../minilang/product/product/ProductServices.xml | 1051 -------------------- applications/product/servicedef/services.xml | 12 + .../product/servicedef/services_feature.xml | 1 + 7 files changed, 29 insertions(+), 1071 deletions(-) diff --git a/applications/product/groovyScripts/product/product/ProductServices.groovy b/applications/product/groovyScripts/product/product/ProductServices.groovy index 706e6eb..3182f16 100644 --- a/applications/product/groovyScripts/product/product/ProductServices.groovy +++ b/applications/product/groovyScripts/product/product/ProductServices.groovy @@ -527,7 +527,6 @@ def copyToProductVariants() { /** * Check Product Related Permission * a method 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 */ def checkProductRelatedPermission(String callingMethodName, String checkAction) { if (!callingMethodName) { @@ -538,7 +537,7 @@ def checkProductRelatedPermission(String callingMethodName, String checkAction) } List roleCategories = [] // find all role-categories that this product is a member of - if (!security.hasEntityPermission("CATALOG", "_${checkAction}", parameters.userLogin)) { + if (parameters.productId && !security.hasEntityPermission("CATALOG", "_${checkAction}", parameters.userLogin)) { Map lookupRoleCategoriesMap = [productId : parameters.productId, partyId : userLogin.partyId, roleTypeId: "LTD_ADMIN"] @@ -560,6 +559,16 @@ def checkProductRelatedPermission(String callingMethodName, String checkAction) } /** + * call checkProductRelatedPermission function with support permission service interface + */ +def checkProductRelatedPermissionService() { + parameters.alternatePermissionRoot = parameters.altPermission + Map result = checkProductRelatedPermission(parameters.resourceDescription, parameters.mainAction) + result.hasPermission = ServiceUtil.isSuccess(result) + return result +} + +/** * Main permission logic */ def productGenericPermission() { diff --git a/applications/product/minilang/product/feature/ProductFeatureServices.xml b/applications/product/minilang/product/feature/ProductFeatureServices.xml index 835d6bc..6810a6a 100644 --- a/applications/product/minilang/product/feature/ProductFeatureServices.xml +++ b/applications/product/minilang/product/feature/ProductFeatureServices.xml @@ -22,11 +22,6 @@ under the License. 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="applyFeatureToProductFromTypeAndCode" short-description="Apply Feature to Product using Feature Type and ID Code"> - <set field="callingMethodName" value="applyFeatureToProductFromTypeAndCode"/> - <set field="checkAction" value="CREATE"/> - <call-simple-method method-name="checkProductRelatedPermission" xml-resource="component://product/minilang/product/product/ProductServices.xml"/> - <check-errors/> - <!-- find the ProductFeatures by type and id code --> <entity-and entity-name="ProductFeature" list="productFeatures"> <field-map field-name="productFeatureTypeId" from-field="parameters.productFeatureTypeId"/> diff --git a/applications/product/minilang/product/inventory/InventoryServices.xml b/applications/product/minilang/product/inventory/InventoryServices.xml index 56d15a3..64a01d5 100644 --- a/applications/product/minilang/product/inventory/InventoryServices.xml +++ b/applications/product/minilang/product/inventory/InventoryServices.xml @@ -90,10 +90,11 @@ under the License. <if-empty field="resourceDescription"> <property-to-field resource="CommonUiLabels" property="CommonPermissionThisOperation" field="resourceDescription"/> </if-empty> - <set field="callingMethodName" from-field="resourceDescription"/> - <set field="checkAction" from-field="mainAction"/> - <set field="alternatePermissionRoot" value="FACILITY"/> - <call-simple-method method-name="checkProductRelatedPermission" xml-resource="component://product/minilang/product/product/ProductServices.xml"/> + <set field="parameters.altPermission" value="FACILITY"/> + <call-service service-name="checkProductRelatedPermission" in-map-name="parameters"> + <result-to-result result-name="hasPermission"/> + </call-service> + <check-errors/> <if-empty field="error_list"> <set field="hasPermission" type="Boolean" value="true"/> <field-to-result field="hasPermission"/> diff --git a/applications/product/minilang/product/price/PriceServices.xml b/applications/product/minilang/product/price/PriceServices.xml index b9ecfa7..cf67c4a 100644 --- a/applications/product/minilang/product/price/PriceServices.xml +++ b/applications/product/minilang/product/price/PriceServices.xml @@ -22,9 +22,6 @@ under the License. xmlns="http://ofbiz.apache.org/Simple-Method" xsi:schemaLocation="http://ofbiz.apache.org/Simple-Method http://ofbiz.apache.org/dtds/simple-methods.xsd"> <!-- ProductPrice methods --> <simple-method method-name="createProductPrice" short-description="Create a Product Price"> - <set field="callingMethodName" value="createProductPrice"/> - <set field="checkAction" value="CREATE"/> - <call-simple-method method-name="checkProductRelatedPermission" xml-resource="component://product/minilang/product/product/ProductServices.xml"/> <check-permission permission="CATALOG_PRICE_MAINT"> <fail-property resource="ProductUiLabels" property="ProductPriceMaintPermissionError"/> </check-permission> @@ -51,9 +48,6 @@ under the License. <create-value value-field="newEntity"/> </simple-method> <simple-method method-name="updateProductPrice" short-description="Update an ProductPrice"> - <set field="callingMethodName" value="updateProductPrice"/> - <set field="checkAction" value="UPDATE"/> - <call-simple-method method-name="checkProductRelatedPermission" xml-resource="component://product/minilang/product/product/ProductServices.xml"/> <check-permission permission="CATALOG_PRICE_MAINT"> <fail-property resource="ProductUiLabels" property="ProductPriceMaintPermissionError"/> </check-permission> @@ -75,9 +69,6 @@ under the License. <store-value value-field="lookedUpValue"/> </simple-method> <simple-method method-name="deleteProductPrice" short-description="Delete an ProductPrice"> - <set field="callingMethodName" value="deleteProductPrice"/> - <set field="checkAction" value="DELETE"/> - <call-simple-method method-name="checkProductRelatedPermission" xml-resource="component://product/minilang/product/product/ProductServices.xml"/> <check-permission permission="CATALOG_PRICE_MAINT"> <fail-property resource="ProductUiLabels" property="ProductPriceMaintPermissionError"/> </check-permission> diff --git a/applications/product/minilang/product/product/ProductServices.xml b/applications/product/minilang/product/product/ProductServices.xml deleted file mode 100644 index b331b32..0000000 --- a/applications/product/minilang/product/product/ProductServices.xml +++ /dev/null @@ -1,1051 +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="createProduct" short-description="Create a Product"> - <check-permission permission="CATALOG" action="_CREATE"> - <alt-permission permission="CATALOG_ROLE" action="_CREATE"/> - <fail-property resource="ProductUiLabels" property="ProductCatalogCreatePermissionError"/> - </check-permission> - <check-errors/> - - <make-value entity-name="Product" value-field="newEntity"/> - <set-nonpk-fields map="parameters" value-field="newEntity"/> - - <set from-field="parameters.productId" field="newEntity.productId"/> - <if-empty field="newEntity.productId"> - <sequenced-id sequence-name="Product" field="newEntity.productId"/> - <else> - <check-id field="newEntity.productId"/> - <check-errors /> - <entity-one entity-name="Product" value-field="dummyProduct"><field-map field-name="productId" from-field="parameters.productId"/></entity-one> - <if-not-empty field="dummyProduct"> - <add-error ><fail-property resource="CommonErrorUiLabels" property="CommonErrorDuplicateKey" /></add-error> - </if-not-empty> - <check-errors /> - </else> - </if-empty> - <field-to-result field="newEntity.productId" result-name="productId"/> - - <now-timestamp field="nowTimestamp"/> - <set from-field="nowTimestamp" field="newEntity.createdDate"/> - <set from-field="nowTimestamp" field="newEntity.lastModifiedDate"/> - <set from-field="userLogin.userLoginId" field="newEntity.lastModifiedByUserLogin"/> - <set from-field="userLogin.userLoginId" field="newEntity.createdByUserLogin"/> - <if-empty field="newEntity.isVariant"> - <set field="newEntity.isVariant" value="N"/> - </if-empty> - <if-empty field="newEntity.isVirtual"> - <set field="newEntity.isVirtual" value="N"/> - </if-empty> - <if-empty field="newEntity.billOfMaterialLevel"> - <set field="newEntity.billOfMaterialLevel" value="0" type="Long"/> - </if-empty> - - <create-value value-field="newEntity"/> - - <!-- if setting the primaryProductCategoryId create a member entity too --> - <!-- THIS IS REMOVED BECAUSE IT CAUSES PROBLEMS FOR WORKING ON PRODUCTION SITES - <if-not-empty field="newEntity.primaryProductCategoryId"> - <make-value entity-name="ProductCategoryMember" value-field="newMember"/> - <set from-field="productId" map-name="newEntity" to-field-name="productId" to-map-name="newMember"/> - <set from-field="primaryProductCategoryId" map-name="newEntity" to-field-name="productCategoryId" to-map-name="newMember"/> - <now-timestamp field="nowStamp"/> - <set from-field="nowStamp" field="newMember.fromDate"/> - <create-value value-field="newMember"/> - </if-not-empty> - --> - - <!-- if the user has the role limited position, add this product to the limit category/ies --> - <if-has-permission permission="CATALOG_ROLE" action="_CREATE"> - <entity-and entity-name="ProductCategoryRole" list="productCategoryRoles" filter-by-date="true"> - <field-map field-name="partyId" from-field="userLogin.partyId"/> - <field-map field-name="roleTypeId" value="LTD_ADMIN"/> - </entity-and> - - <iterate list="productCategoryRoles" entry="productCategoryRole"> - <!-- add this new product to the category --> - <make-value entity-name="ProductCategoryMember" value-field="newLimitMember"/> - <set from-field="newEntity.productId" field="newLimitMember.productId"/> - <set from-field="productCategoryRole.productCategoryId" field="newLimitMember.productCategoryId"/> - <set from-field="nowTimestamp" field="newLimitMember.fromDate"/> - <create-value value-field="newLimitMember"/> - </iterate> - </if-has-permission> - </simple-method> - <simple-method method-name="updateProduct" short-description="Update a Product"> - <set value="updateProduct" field="callingMethodName"/> - <set value="UPDATE" field="checkAction"/> - <call-simple-method method-name="checkProductRelatedPermission"/> - <check-errors/> - - <entity-one entity-name="Product" value-field="lookedUpValue"/> - <!-- save this value before overwriting it so we can compare it later --> - <set from-field="lookedUpValue.primaryProductCategoryId" field="saveIdMap.primaryProductCategoryId"/> - <set-nonpk-fields map="parameters" value-field="lookedUpValue"/> - - <now-timestamp field="lookedUpValue.lastModifiedDate"/> - <set from-field="userLogin.userLoginId" field="lookedUpValue.lastModifiedByUserLogin"/> - - <store-value value-field="lookedUpValue"/> - - <!-- if setting the primaryParentCategoryId, create a rollup entity too --> - <!-- THIS IS REMOVED BECAUSE IT CAUSES PROBLEMS FOR WORKING ON PRODUCTION SITES - <if-not-empty field="lookedUpValue.primaryProductCategoryId"> - <if-compare-field to-field="saveIdMap.primaryProductCategoryId" field="lookedUpValue.primaryProductCategoryId" operator="equals"> - <make-value entity-name="ProductCategoryMember" value-field="newMember"/> - <set from-field="productId" map-name="newEntity" to-field-name="productId" to-map-name="newMember"/> - <set from-field="primaryProductCategoryId" map-name="newEntity" to-field-name="productCategoryId" to-map-name="newMember"/> - <now-timestamp field="newMember.fromDate"/> - <create-value value-field="newMember"/> - </if-compare-field> - </if-not-empty> - --> - </simple-method> - - <!-- update the name of a product - handles real , virtual and variant products --> - <simple-method method-name="updateProductQuickAdminName" short-description="Update a Product Name from quick admin"> - <set value="updateProductQuickAdminName" field="callingMethodName"/> - <set value="UPDATE" field="checkAction"/> - <call-simple-method method-name="checkProductRelatedPermission"/> - <check-errors/> - - <entity-one entity-name="Product" value-field="lookedUpValue"/> - <set from-field="parameters.productName" field="lookedUpValue.productName"/> - <if-compare field="lookedUpValue.isVirtual" operator="equals" value="Y"> - <set from-field="lookedUpValue.productName" field="lookedUpValue.internalName"/> - </if-compare> - - <now-timestamp field="lookedUpValue.lastModifiedDate"/> - <set from-field="userLogin.userLoginId" field="lookedUpValue.lastModifiedByUserLogin"/> - - <store-value value-field="lookedUpValue"/> - - <if-compare field="lookedUpValue.isVirtual" operator="equals" value="Y"> - <!-- get all variant products, to update their productNames --> - <set from-field="parameters.productId" field="variantProductAssocMap.productId"/> - <set value="PRODUCT_VARIANT" field="variantProductAssocMap.productAssocTypeId"/> - - <!-- get all productAssocs, then get the actual product to update --> - <find-by-and entity-name="ProductAssoc" map="variantProductAssocMap" list="variantProductAssocs"/> - <filter-list-by-date list="variantProductAssocs"/> - <iterate list="variantProductAssocs" entry="variantProductAssoc"> - <clear-field field="variantProduct"/> - <entity-one entity-name="Product" value-field="variantProduct" auto-field-map="false"> - <field-map field-name="productId" from-field="variantProductAssoc.productIdTo"/> - </entity-one> - - <set from-field="parameters.productName" field="variantProduct.productName"/> - <now-timestamp field="variantProduct.lastModifiedDate"/> - <set from-field="userLogin.userLoginId" field="variantProduct.lastModifiedByUserLogin"/> - <store-value value-field="variantProduct"/> - </iterate> - </if-compare> - </simple-method> - - <simple-method method-name="duplicateProduct" short-description="Duplicate a Product"> - <set value="duplicateProduct" field="callingMethodName"/> - <set value="CREATE" field="checkAction"/> - <call-simple-method method-name="checkProductRelatedPermission"/> - <set value="DELETE" field="checkAction"/> - <call-simple-method method-name="checkProductRelatedPermission"/> - <entity-one entity-name="Product" value-field="dummyProduct"> - <field-map field-name="productId" from-field="parameters.productId"/> - </entity-one> - <if-not-empty field="dummyProduct"> - <add-error ><fail-property resource="CommonErrorUiLabels" property="CommonErrorDuplicateKey" /></add-error> - </if-not-empty> - <check-errors/> - - <!-- look up the old product and clone it --> - <entity-one entity-name="Product" value-field="oldProduct" auto-field-map="false"> - <field-map field-name="productId" from-field="parameters.oldProductId"/> - </entity-one> - <clone-value value-field="oldProduct" new-value-field="newProduct"/> - - <!-- set the productId, and write it to the datasource --> - <set from-field="parameters.productId" field="newProduct.productId"/> - - <!-- if requested, set the new internalName field --> - <if-not-empty field="parameters.newInternalName"> - <set from-field="parameters.newInternalName" field="newProduct.internalName"/> - </if-not-empty> - - <!-- if requested, set the new productName field --> - <if-not-empty field="parameters.newProductName"> - <set from-field="parameters.newProductName" field="newProduct.productName"/> - </if-not-empty> - - <!-- if requested, set the new description field --> - <if-not-empty field="parameters.newDescription"> - <set from-field="parameters.newDescription" field="newProduct.description"/> - </if-not-empty> - - <!-- if requested, set the new longDescription field --> - <if-not-empty field="parameters.newLongDescription"> - <set from-field="parameters.newLongDescription" field="newProduct.longDescription"/> - </if-not-empty> - - <create-value value-field="newProduct"/> - - <!-- set up entity filter --> - <set field="productFindContext.productId" from-field="parameters.oldProductId"/> - <set field="reverseProductFindContext.productIdTo" from-field="parameters.oldProductId"/> - - <!-- if requested, duplicate related data as well --> - <if-not-empty field="parameters.duplicatePrices"> - <find-by-and entity-name="ProductPrice" map="productFindContext" list="foundValues"/> - <iterate list="foundValues" entry="foundValue"> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="parameters.productId" field="newTempValue.productId"/> - <create-value value-field="newTempValue"/> - </iterate> - </if-not-empty> - <if-not-empty field="parameters.duplicateIDs"> - <find-by-and entity-name="GoodIdentification" map="productFindContext" list="foundValues"/> - <iterate list="foundValues" entry="foundValue"> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="parameters.productId" field="newTempValue.productId"/> - <create-value value-field="newTempValue"/> - </iterate> - </if-not-empty> - <if-not-empty field="parameters.duplicateContent"> - <find-by-and entity-name="ProductContent" map="productFindContext" list="foundValues"/> - <iterate list="foundValues" entry="foundValue"> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="parameters.productId" field="newTempValue.productId"/> - <create-value value-field="newTempValue"/> - </iterate> - </if-not-empty> - <if-not-empty field="parameters.duplicateCategoryMembers"> - <find-by-and entity-name="ProductCategoryMember" map="productFindContext" list="foundValues"/> - <iterate list="foundValues" entry="foundValue"> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="parameters.productId" field="newTempValue.productId"/> - <!-- Clone Content --> - <sequenced-id sequence-name="Content" field="newContentId"/> - <entity-one entity-name="Content" value-field="oldContent" use-cache="false"> - <field-map field-name="contentId" value="${newTempValue.contentId}"/> - </entity-one> - <if-not-empty field="oldContent"> - <clone-value value-field="oldContent" new-value-field="clonedContent"/> - <set from-field="newContentId" field="clonedContent.contentId"/> - <set from-field="newContentId" field="newTempValue.contentId"/> - <!-- Clone DataResource --> - <entity-one entity-name="DataResource" value-field="oldDataResource" use-cache="false"> - <field-map field-name="dataResourceId" value="${clonedContent.dataResourceId}"/> - </entity-one> - <if-not-empty field="oldDataResource"> - <sequenced-id sequence-name="DataResource" field="newDataResourceId"/> - <clone-value new-value-field="clonedDataresource" value-field="oldDataResource"/> - <set from-field="newDataResourceId" field="clonedDataresource.dataResourceId"/> - <!-- set new data resource id in cloned content --> - <set from-field="newDataResourceId" field="clonedContent.dataResourceId"/> - <create-value value-field="clonedDataresource"/> - <!-- Clone Electronic Text if exists --> - <get-related-one value-field="oldDataResource" relation-name="ElectronicText" to-value-field="oldElectronicText"/> - <if-not-empty field="oldElectronicText"> - <clone-value value-field="oldElectronicText" new-value-field="clonedElectronicText"/> - <set from-field="newDataResourceId" field="clonedElectronicText.dataResourceId"/> - <create-value value-field="clonedElectronicText"/> - </if-not-empty> - </if-not-empty> - <create-value value-field="clonedContent"/> - </if-not-empty> - <!-- End Clone Contet --> - <create-value value-field="newTempValue"/> - </iterate> - </if-not-empty> - <if-not-empty field="parameters.duplicateAssocs"> - <find-by-and entity-name="ProductAssoc" map="productFindContext" list="foundValues"/> - <iterate list="foundValues" entry="foundValue"> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="parameters.productId" field="newTempValue.productId"/> - <create-value value-field="newTempValue"/> - </iterate> - - <!-- small difference here, also do the reverse assocs... --> - <entity-and entity-name="ProductAssoc" list="foundValues"> - <field-map field-name="productIdTo" from-field="parameters.oldProductId"/> - </entity-and> - <iterate list="foundValues" entry="foundValue"> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="parameters.productId" field="newTempValue.productIdTo"/> - <create-value value-field="newTempValue"/> - </iterate> - </if-not-empty> - <if-not-empty field="parameters.duplicateAttributes"> - <find-by-and entity-name="ProductAttribute" map="productFindContext" list="foundValues"/> - <iterate list="foundValues" entry="foundValue"> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="parameters.productId" field="newTempValue.productId"/> - <create-value value-field="newTempValue"/> - </iterate> - </if-not-empty> - <if-not-empty field="parameters.duplicateFeatureAppls"> - <find-by-and entity-name="ProductFeatureAppl" map="productFindContext" list="foundValues"/> - <iterate list="foundValues" entry="foundValue"> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="parameters.productId" field="newTempValue.productId"/> - <create-value value-field="newTempValue"/> - </iterate> - </if-not-empty> - <if-not-empty field="parameters.duplicateInventoryItems"> - <find-by-and entity-name="InventoryItem" map="productFindContext" list="foundValues"/> - <iterate list="foundValues" entry="foundValue"> - <!-- - NOTE: new inventory items should always be created calling the - createInventoryItem service because in this way we are sure - that all the relevant fields are filled with default values. - However, the code here should work fine because all the values - for the new inventory item are inerited from the existing item. - TODO: is this code correct? What is the meaning of duplicating inventory items? - What about the InventoryItemDetail entries? - --> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="parameters.productId" field="newTempValue.productId"/> - <!-- this one is slightly different because it needs a new sequenced inventoryItemId --> - <sequenced-id sequence-name="InventoryItem" field="newTempValue.inventoryItemId"/> - <create-value value-field="newTempValue"/> - </iterate> - </if-not-empty> - - <!-- if requested, remove related data as well --> - <if-not-empty field="parameters.removePrices"> - <remove-by-and entity-name="ProductPrice" map="productFindContext"/> - </if-not-empty> - <if-not-empty field="parameters.removeIDs"> - <remove-by-and entity-name="GoodIdentification" map="productFindContext"/> - </if-not-empty> - <if-not-empty field="parameters.removeContent"> - <remove-by-and entity-name="ProductContent" map="productFindContext"/> - </if-not-empty> - <if-not-empty field="parameters.removeCategoryMembers"> - <remove-by-and entity-name="ProductCategoryMember" map="productFindContext"/> - </if-not-empty> - <if-not-empty field="parameters.removeAssocs"> - <remove-by-and entity-name="ProductAssoc" map="productFindContext"/> - <!-- small difference here, also do the reverse assocs... --> - <remove-by-and entity-name="ProductAssoc" map="reverseProductFindContext"/> - </if-not-empty> - <if-not-empty field="parameters.removeAttributes"> - <remove-by-and entity-name="ProductAttribute" map="productFindContext"/> - </if-not-empty> - <if-not-empty field="parameters.removeFeatureAppls"> - <remove-by-and entity-name="ProductFeatureAppl" map="productFindContext"/> - </if-not-empty> - <if-not-empty field="parameters.removeInventoryItems"> - <remove-by-and entity-name="InventoryItem" map="productFindContext"/> - </if-not-empty> - </simple-method> - - <!-- Product Keyword Services --> - <simple-method method-name="forceIndexProductKeywords" short-description="induce all the keywords of a product"> - <entity-one entity-name="Product" value-field="product"/> - <call-class-method class-name="org.apache.ofbiz.product.product.KeywordIndex" method-name="forceIndexKeywords"> - <field field="product" type="org.apache.ofbiz.entity.GenericValue"/> - </call-class-method> - </simple-method> - <simple-method method-name="deleteProductKeywords" short-description="delete all the keywords of a product"> - <entity-one entity-name="Product" value-field="product"/> - <remove-related value-field="product" relation-name="ProductKeyword"/> - </simple-method> - - <simple-method method-name="indexProductKeywords" short-description="Index the Keywords for a Product" login-required="false"> - <!-- this service is meant to be called from an entity ECA for entities that include a productId --> - <!-- if it is the Product entity itself triggering this action, then a [productInstance] parameter - will be passed and we can save a few cycles looking that up --> - <set from-field="parameters.productInstance" field="productInstance"/> - <if-empty field="productInstance"> - <set from-field="parameters.productId" field="findProductMap.productId"/> - <find-by-primary-key entity-name="Product" map="findProductMap" value-field="productInstance"/> - </if-empty> - - <!-- induce keywords if autoCreateKeywords is emtpy or Y--> - <if> - <condition> - <or> - <if-empty field="productInstance.autoCreateKeywords"/> - <if-compare field="productInstance.autoCreateKeywords" operator="equals" value="Y"/> - </or> - </condition> - <then> - <call-class-method class-name="org.apache.ofbiz.product.product.KeywordIndex" method-name="indexKeywords"> - <field field="productInstance" type="org.apache.ofbiz.entity.GenericValue"/> - </call-class-method> - </then> - </if> - </simple-method> - - <simple-method method-name="discontinueProductSales" short-description="Discontinue Product Sales" login-required="false"> - <!-- set sales discontinuation date to now --> - <now-timestamp field="nowTimestamp"/> - <entity-one entity-name="Product" value-field="product"/> - <set from-field="nowTimestamp" field="product.salesDiscontinuationDate"/> - <store-value value-field="product"/> - <!-- expire product from all categories --> - <get-related value-field="product" relation-name="ProductCategoryMember" list="productCategoryMembers"/> - <iterate list="productCategoryMembers" entry="productCategoryMember"> - <if-empty field="productCategoryMember.thruDate"> - <set from-field="nowTimestamp" field="productCategoryMember.thruDate"/> - <store-value value-field="productCategoryMember"/> - </if-empty> - </iterate> - <!-- expire product from all associations going to it --> - <get-related value-field="product" relation-name="AssocProductAssoc" list="assocProductAssocs"/> - <iterate list="assocProductAssocs" entry="assocProductAssoc"> - <if-empty field="assocProductAssoc.thruDate"> - <set from-field="nowTimestamp" field="assocProductAssoc.thruDate"/> - <store-value value-field="assocProductAssoc"/> - </if-empty> - </iterate> - </simple-method> - - <simple-method method-name="countProductView" short-description="Count Product View" login-required="false"> - <if-empty field="parameters.weight"> - <calculate field="parameters.weight" type="Long"><number value="1"/></calculate> - </if-empty> - <entity-one entity-name="ProductCalculatedInfo" value-field="productCalculatedInfo"/> - <if-empty field="productCalculatedInfo"> - <!-- go ahead and create it --> - <make-value entity-name="ProductCalculatedInfo" value-field="productCalculatedInfo"/> - <set from-field="parameters.productId" field="productCalculatedInfo.productId"/> - <set from-field="parameters.weight" field="productCalculatedInfo.totalTimesViewed"/> - <create-value value-field="productCalculatedInfo"/> - <else> - <calculate field="productCalculatedInfo.totalTimesViewed" type="Long"> - <calcop operator="add" field="productCalculatedInfo.totalTimesViewed"> - <calcop operator="get" field="parameters.weight"></calcop> - </calcop> - </calculate> - <store-value value-field="productCalculatedInfo"/> - </else> - </if-empty> - - <!-- do the same for the virtual product... --> - <entity-one entity-name="Product" value-field="product" use-cache="true"/> - <call-class-method class-name="org.apache.ofbiz.product.product.ProductWorker" method-name="getVariantVirtualId" ret-field="virtualProductId"> - <field field="product" type="GenericValue"/> - </call-class-method> - <if-not-empty field="virtualProductId"> - <set from-field="virtualProductId" field="callSubMap.productId"/> - <set from-field="parameters.weight" field="callSubMap.weight"/> - <call-service service-name="countProductView" in-map-name="callSubMap"></call-service> - </if-not-empty> - </simple-method> - - <simple-method method-name="createProductReview" short-description="Create a ProductReview" login-required="false"> - <make-value entity-name="ProductReview" value-field="newEntity"/> - <set-nonpk-fields map="parameters" value-field="newEntity"/> - <set from-field="userLogin.userLoginId" field="newEntity.userLoginId"/> - <set value="PRR_PENDING" field="newEntity.statusId"/> - - <!-- code to check for auto-approved reviews (store setting) --> - <entity-one entity-name="ProductStore" value-field="productStore"/> - - <if-not-empty field="productStore"> - <if-compare field="productStore.autoApproveReviews" operator="equals" value="Y"> - <set value="PRR_APPROVED" field="newEntity.statusId"/> - </if-compare> - </if-not-empty> - - <!-- auto approve the review if it is just a rating and has no review text --> - <if-empty field="parameters.productReview"> - <set value="PRR_APPROVED" field="newEntity.statusId"/> - </if-empty> - - <!-- create the new ProductReview --> - <sequenced-id sequence-name="ProductReview" field="newEntity.productReviewId"/> - <field-to-result field="newEntity.productReviewId" result-name="productReviewId"/> - - <if-empty field="newEntity.postedDateTime"> - <now-timestamp field="newEntity.postedDateTime"/> - </if-empty> - - <create-value value-field="newEntity"/> - - <set from-field="newEntity.productId" field="productId"/> - <property-to-field resource="ProductUiLabels" property="ProductCreateProductReviewSuccess" field="successMessage"/> - <call-simple-method method-name="updateProductWithReviewRatingAvg"/> - </simple-method> - <simple-method method-name="updateProductReview" short-description="Update ProductReview"> - <set value="updateProductReview" field="callingMethodName"/> - <set value="UPDATE" field="checkAction"/> - <call-simple-method method-name="checkProductRelatedPermission"/> - <check-errors/> - - <make-value entity-name="ProductReview" value-field="lookupPKMap"/> - <set-pk-fields map="parameters" value-field="lookupPKMap"/> - <find-by-primary-key map="lookupPKMap" value-field="lookedUpValue"/> - <set-nonpk-fields map="parameters" value-field="lookedUpValue"/> - <store-value value-field="lookedUpValue"/> - - <set from-field="lookedUpValue.productId" field="productId"/> - <call-simple-method method-name="updateProductWithReviewRatingAvg"/> - </simple-method> - <simple-method method-name="updateProductWithReviewRatingAvg" short-description="Update Product with new Review Rating Avg" login-required="false"> - <!-- this method is meant to be called in-line and depends in a productId parameter --> - <call-class-method class-name="org.apache.ofbiz.product.product.ProductWorker" method-name="getAverageProductRating" ret-field="averageCustomerRating"> - <field field="delegator" type="org.apache.ofbiz.entity.Delegator"/> - <field field="productId" type="java.lang.String"/> - </call-class-method> - <log level="info" message="Got new average customer rating ${averageCustomerRating}"/> - <if-compare field="averageCustomerRating" operator="equals" value="0" type="BigDecimal"> - <return/> - </if-compare> - <!-- update the review average on the ProductCalculatedInfo entity --> - <entity-one entity-name="ProductCalculatedInfo" value-field="productCalculatedInfo"/> - <if-empty field="productCalculatedInfo"> - <!-- go ahead and create it --> - <make-value entity-name="ProductCalculatedInfo" value-field="productCalculatedInfo"/> - <set from-field="productId" field="productCalculatedInfo.productId"/> - <set from-field="averageCustomerRating" field="productCalculatedInfo.averageCustomerRating"/> - <create-value value-field="productCalculatedInfo"/> - <else> - <set from-field="averageCustomerRating" field="productCalculatedInfo.averageCustomerRating"/> - <store-value value-field="productCalculatedInfo"/> - </else> - </if-empty> - </simple-method> - <simple-method method-name="copyToProductVariants" short-description="Updates the Product's Variants"> - <set value="copyToProductVariants" field="callingMethodName"/> - <set value="CREATE" field="checkAction"/> - <call-simple-method method-name="checkProductRelatedPermission"/> - <set value="DELETE" field="checkAction"/> - <call-simple-method method-name="checkProductRelatedPermission"/> - <check-errors/> - - <set from-field="parameters.virtualProductId" field="productFindContext.productId"/> - <find-by-primary-key entity-name="Product" map="productFindContext" value-field="oldProduct"/> - - <set from-field="parameters.virtualProductId" field="variantsFindContext.productId"/> - <set value="PRODUCT_VARIANT" field="variantsFindContext.productAssocTypeId"/> - <find-by-and entity-name="ProductAssoc" map="variantsFindContext" list="variants"/> - <filter-list-by-date list="variants"/> - <iterate list="variants" entry="newProduct"> - <set from-field="newProduct.productIdTo" field="productVariantContext.productId"/> - <!-- if requested, duplicate related data --> - <if-not-empty field="parameters.duplicatePrices"> - <if-not-empty field="parameters.removeBefore"> - <find-by-and entity-name="ProductPrice" map="productVariantContext" list="foundVariantValues"/> - <iterate list="foundVariantValues" entry="foundVariantValue"> - <remove-value value-field="foundVariantValue"/> - </iterate> - </if-not-empty> - <find-by-and entity-name="ProductPrice" map="productFindContext" list="foundValues"/> - <iterate list="foundValues" entry="foundValue"> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="newProduct.productIdTo" field="newTempValue.productId"/> - <create-value value-field="newTempValue"/> - </iterate> - </if-not-empty> - <if-not-empty field="parameters.duplicateIDs"> - <if-not-empty field="parameters.removeBefore"> - <find-by-and entity-name="GoodIdentification" map="productVariantContext" list="foundVariantValues"/> - <iterate list="foundVariantValues" entry="foundVariantValue"> - <remove-value value-field="foundVariantValue"/> - </iterate> - </if-not-empty> - <find-by-and entity-name="GoodIdentification" map="productFindContext" list="foundValues"/> - <iterate list="foundValues" entry="foundValue"> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="newProduct.productIdTo" field="newTempValue.productId"/> - <create-value value-field="newTempValue"/> - </iterate> - </if-not-empty> - <if-not-empty field="parameters.duplicateContent"> - <if-not-empty field="parameters.removeBefore"> - <find-by-and entity-name="ProductContent" map="productVariantContext" list="foundVariantValues"/> - <iterate list="foundVariantValues" entry="foundVariantValue"> - <remove-value value-field="foundVariantValue"/> - </iterate> - </if-not-empty> - <find-by-and entity-name="ProductContent" map="productFindContext" list="foundValues"/> - <iterate list="foundValues" entry="foundValue"> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="newProduct.productIdTo" field="newTempValue.productId"/> - <create-value value-field="newTempValue"/> - </iterate> - </if-not-empty> - <if-not-empty field="parameters.duplicateCategoryMembers"> - <if-not-empty field="parameters.removeBefore"> - <find-by-and entity-name="ProductCategoryMember" map="productVariantContext" list="foundVariantValues"/> - <iterate list="foundVariantValues" entry="foundVariantValue"> - <remove-value value-field="foundVariantValue"/> - </iterate> - </if-not-empty> - <find-by-and entity-name="ProductCategoryMember" map="productFindContext" list="foundValues"/> - <iterate list="foundValues" entry="foundValue"> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="newProduct.productIdTo" field="newTempValue.productId"/> - <create-value value-field="newTempValue"/> - </iterate> - </if-not-empty> - <if-not-empty field="parameters.duplicateAttributes"> - <if-not-empty field="parameters.removeBefore"> - <find-by-and entity-name="ProductAttribute" map="productVariantContext" list="foundVariantValues"/> - <iterate list="foundVariantValues" entry="foundVariantValue"> - <remove-value value-field="foundVariantValue"/> - </iterate> - </if-not-empty> - <find-by-and entity-name="ProductAttribute" map="productFindContext" list="foundValues"/> - <iterate list="foundValues" entry="foundValue"> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="newProduct.productIdTo" field="newTempValue.productId"/> - <create-value value-field="newTempValue"/> - </iterate> - </if-not-empty> - <if-not-empty field="parameters.duplicateFacilities"> - <if-not-empty field="parameters.removeBefore"> - <find-by-and entity-name="ProductFacility" map="productVariantContext" list="foundVariantValues"/> - <iterate list="foundVariantValues" entry="foundVariantValue"> - <remove-value value-field="foundVariantValue"/> - </iterate> - </if-not-empty> - <find-by-and entity-name="ProductFacility" map="productFindContext" list="foundValues"/> - <iterate list="foundValues" entry="foundValue"> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="newProduct.productIdTo" field="newTempValue.productId"/> - <create-value value-field="newTempValue"/> - </iterate> - </if-not-empty> - <if-not-empty field="parameters.duplicateLocations"> - <if-not-empty field="parameters.removeBefore"> - <find-by-and entity-name="ProductFacilityLocation" map="productVariantContext" list="foundVariantValues"/> - <iterate list="foundVariantValues" entry="foundVariantValue"> - <remove-value value-field="foundVariantValue"/> - </iterate> - </if-not-empty> - <find-by-and entity-name="ProductFacilityLocation" map="productFindContext" list="foundValues"/> - <iterate list="foundValues" entry="foundValue"> - <clone-value value-field="foundValue" new-value-field="newTempValue"/> - <set from-field="newProduct.productIdTo" field="newTempValue.productId"/> - <create-value value-field="newTempValue"/> - </iterate> - </if-not-empty> - </iterate> - </simple-method> - - <!-- a method 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="checkProductRelatedPermission" short-description="Check Product Related Permission"> - <if-empty field="callingMethodName"> - <property-to-field resource="CommonUiLabels" property="CommonPermissionThisOperation" field="callingMethodName"/> - </if-empty> - <if-empty field="checkAction"> - <set value="UPDATE" field="checkAction"/> - </if-empty> - - <!-- find all role-categories that this product is a member of --> - <if> - <condition> - <not><if-has-permission permission="CATALOG" action="_${checkAction}"/></not> - </condition> - <then> - <set from-field="parameters.productId" field="lookupRoleCategoriesMap.productId"/> - <set from-field="userLogin.partyId" field="lookupRoleCategoriesMap.partyId"/> - <set value="LTD_ADMIN" field="lookupRoleCategoriesMap.roleTypeId"/> - <find-by-and entity-name="ProductCategoryMemberAndRole" map="lookupRoleCategoriesMap" list="roleCategories"/> - <filter-list-by-date list="roleCategories"/> - <filter-list-by-date list="roleCategories" from-field-name="roleFromDate" thru-field-name="roleThruDate"/> - </then> - </if> - <if> - <condition> - <not> - <or> - <if-has-permission permission="CATALOG" action="_${checkAction}"/> - <and> - <if-has-permission permission="CATALOG_ROLE" action="_${checkAction}"/> - <not><if-empty field="roleCategories"/></not> - </and> - <and> - <not><if-empty field="alternatePermissionRoot"/></not> - <if-has-permission permission="${alternatePermissionRoot}" action="_${checkAction}"/> - </and> - </or> - </not> - </condition> - <then> - <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> - </then> - </if> - </simple-method> - <simple-method method-name="productGenericPermission" 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="checkProductRelatedPermission"/> - - <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="productPriceGenericPermission" short-description="product price 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> - <check-permission permission="CATALOG_PRICE_MAINT"> - <fail-property resource="ProductUiLabels" property="ProductPriceMaintPermissionError"/> - </check-permission> - <call-simple-method method-name="checkProductRelatedPermission"/> - <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> - - <!-- ================================================================ --> - <!-- ProductRole Services --> - <!-- ================================================================ --> - - <simple-method method-name="addPartyToProduct" short-description="Add Party to Product"> - <set value="addPartyToProduct" field="callingMethodName"/> - <set value="CREATE" field="checkAction"/> - <call-simple-method method-name="checkProductRelatedPermission"/> - <check-errors/> - - <make-value entity-name="ProductRole" value-field="newEntity"/> - <set-pk-fields map="parameters" value-field="newEntity"/> - <set-nonpk-fields map="parameters" value-field="newEntity"/> - - <if-empty field="newEntity.fromDate"> - <now-timestamp field="newEntity.fromDate"/> - </if-empty> - - <create-value value-field="newEntity"/> - </simple-method> - <simple-method method-name="updatePartyToProduct" short-description="Update Party to Product"> - <set value="updatePartyToProduct" field="callingMethodName"/> - <set value="UPDATE" field="checkAction"/> - <call-simple-method method-name="checkProductRelatedPermission"/> - <check-errors/> - - <make-value entity-name="ProductRole" value-field="lookupPKMap"/> - <set-pk-fields map="parameters" value-field="lookupPKMap"/> - <find-by-primary-key entity-name="ProductRole" map="lookupPKMap" value-field="lookedUpValue"/> - <set-nonpk-fields map="parameters" value-field="lookedUpValue"/> - <store-value value-field="lookedUpValue"/> - </simple-method> - <simple-method method-name="removePartyFromProduct" short-description="Remove Party From Product"> - <set value="removePartyFromProduct" field="callingMethodName"/> - <set value="DELETE" field="checkAction"/> - <call-simple-method method-name="checkProductRelatedPermission"/> - <check-errors/> - - <make-value entity-name="ProductRole" value-field="lookupPKMap"/> - <set-pk-fields map="parameters" value-field="lookupPKMap"/> - <find-by-primary-key entity-name="ProductRole" map="lookupPKMap" value-field="lookedUpValue"/> - <remove-value value-field="lookedUpValue"/> - </simple-method> - - <!-- ProductCategoryGlAccount methods --> - <simple-method method-name="createProductCategoryGlAccount" short-description="Create a ProductCategoryGlAccount"> - <set value="createProductCategoryGlAccount" field="callingMethodName"/> - <set value="CREATE" field="checkAction"/> - <call-simple-method method-name="checkProductRelatedPermission"/> - <check-errors/> - - <make-value entity-name="ProductCategoryGlAccount" value-field="newEntity"/> - <set-nonpk-fields map="parameters" value-field="newEntity"/> - <set-pk-fields map="parameters" value-field="newEntity"/> - <create-value value-field="newEntity"/> - </simple-method> - - <simple-method method-name="updateProductCategoryGlAccount" short-description="Update a ProductCategoryGlAccount"> - <set value="updateProductCategoryGlAccount" field="callingMethodName"/> - <set value="UPDATE" field="checkAction"/> - <call-simple-method method-name="checkProductRelatedPermission"/> - <check-errors/> - - <entity-one entity-name="ProductCategoryGlAccount" value-field="lookedUpValue"/> - <set-nonpk-fields map="parameters" value-field="lookedUpValue"/> - <store-value value-field="lookedUpValue"/> - </simple-method> - - <simple-method method-name="deleteProductCategoryGlAccount" short-description="Delete a ProductCategoryGlAccount"> - <set value="deleteProductCategoryGlAccount" field="callingMethodName"/> - <set value="DELETE" field="checkAction"/> - <call-simple-method method-name="checkProductRelatedPermission"/> - <check-errors/> - - <entity-one entity-name="ProductCategoryGlAccount" value-field="lookedUpValue"/> - <remove-value value-field="lookedUpValue"/> - </simple-method> - - <!-- Product GroupOrder Services --> - <simple-method method-name="createProductGroupOrder" short-description="Create ProductGroupOrder"> - <make-value entity-name="ProductGroupOrder" value-field="newEntity"/> - <make-next-seq-id value-field="newEntity" seq-field-name="groupOrderId"/> - <field-to-result field="newEntity.groupOrderId" result-name="groupOrderId"/> - <set-nonpk-fields map="parameters" value-field="newEntity"/> - <create-value value-field="newEntity"/> - </simple-method> - - <simple-method method-name="updateProductGroupOrder" short-description="Update ProductGroupOrder"> - <entity-one entity-name="ProductGroupOrder" value-field="productGroupOrder"/> - <set-nonpk-fields map="parameters" value-field="productGroupOrder"/> - <store-value value-field="productGroupOrder"/> - - <if-compare field="productGroupOrder.statusId" operator="equals" value="GO_CREATED"> - <entity-one entity-name="JobSandbox" value-field="jobSandbox"> - <field-map field-name="jobId" from-field="productGroupOrder.jobId"/> - </entity-one> - <if-not-empty field="jobSandbox"> - <set field="jobSandbox.runTime" from-field="parameters.thruDate"/> - <store-value value-field="jobSandbox"/> - </if-not-empty> - </if-compare> - </simple-method> - - <simple-method method-name="deleteProductGroupOrder" short-description="Delete ProductGroupOrder"> - <entity-and entity-name="OrderItemGroupOrder" list="orderItemGroupOrders"> - <field-map field-name="groupOrderId" from-field="parameters.groupOrderId"/> - </entity-and> - <iterate list="orderItemGroupOrders" entry="orderItemGroupOrder"> - <remove-value value-field="orderItemGroupOrder"/> - </iterate> - - <entity-one entity-name="ProductGroupOrder" value-field="productGroupOrder"/> - <remove-value value-field="productGroupOrder"/> - - <entity-one entity-name="JobSandbox" value-field="jobSandbox"> - <field-map field-name="jobId" from-field="productGroupOrder.jobId"/> - </entity-one> - <remove-value value-field="jobSandbox"/> - - <entity-and entity-name="JobSandbox" list="jobSandboxList"> - <field-map field-name="runtimeDataId" from-field="jobSandbox.runtimeDataId"/> - </entity-and> - <iterate list="jobSandboxList" entry="jobSandboxRelatedRuntimeData"> - <remove-value value-field="jobSandboxRelatedRuntimeData"/> - </iterate> - - <entity-one entity-name="RuntimeData" value-field="runtimeData"> - <field-map field-name="runtimeDataId" from-field="jobSandbox.runtimeDataId"/> - </entity-one> - <remove-value value-field="runtimeData"/> - </simple-method> - - <simple-method method-name="createJobForProductGroupOrder" short-description="Create ProductGroupOrder"> - <entity-one entity-name="ProductGroupOrder" value-field="productGroupOrder"/> - <if-empty field="productGroupOrder.jobId"> - <!-- Create RuntimeData For ProductGroupOrder --> - <set field="runtimeDataMap.groupOrderId" from-field="parameters.groupOrderId"/> - <call-class-method class-name="org.apache.ofbiz.entity.serialize.XmlSerializer" method-name="serialize" ret-field="runtimeInfo"> - <field field="runtimeDataMap" type="Object"/> - </call-class-method> - <make-value entity-name="RuntimeData" value-field="runtimeData"/> - <sequenced-id sequence-name="RuntimeData" field="runtimeData.runtimeDataId"/> - <set field="runtimeDataId" from-field="runtimeData.runtimeDataId"/> - <set field="runtimeData.runtimeInfo" from-field="runtimeInfo"/> - <create-value value-field="runtimeData"/> - - <!-- Create Job For ProductGroupOrder --> - <!-- FIXME: Jobs should not be manually created --> - <make-value entity-name="JobSandbox" value-field="jobSandbox"/> - <sequenced-id sequence-name="JobSandbox" field="jobSandbox.jobId"/> - <set field="jobId" from-field="jobSandbox.jobId"/> - <set field="jobSandbox.jobName" value="Check ProductGroupOrder Expired"/> - <set field="jobSandbox.runTime" from-field="parameters.thruDate"/> - <set field="jobSandbox.poolId" value="pool"/> - <set field="jobSandbox.statusId" value="SERVICE_PENDING"/> - <set field="jobSandbox.serviceName" value="checkProductGroupOrderExpired"/> - <set field="jobSandbox.runAsUser" value="system"/> - <set field="jobSandbox.runtimeDataId" from-field="runtimeDataId"/> - <set field="jobSandbox.maxRecurrenceCount" value="1" type="Long"/> - <set field="jobSandbox.priority" value="50" type="Long"/> - <create-value value-field="jobSandbox"/> - - <set field="productGroupOrder.jobId" from-field="jobId"/> - <store-value value-field="productGroupOrder"/> - </if-empty> - </simple-method> - - <simple-method method-name="checkOrderItemForProductGroupOrder" short-description="Check OrderItem For ProductGroupOrder"> - <entity-and entity-name="OrderItem" list="orderItems"> - <field-map field-name="orderId" from-field="parameters.orderId"/> - </entity-and> - <iterate list="orderItems" entry="orderItem"> - <set field="productId" from-field="orderItem.productId"/> - <entity-one entity-name="Product" value-field="product"> - <field-map field-name="productId" from-field="orderItem.productId"/> - </entity-one> - <if-compare field="product.isVariant" operator="equals" value="Y"> - <entity-and entity-name="ProductAssoc" list="variantProductAssocs" filter-by-date="true"> - <field-map field-name="productIdTo" from-field="orderItem.productId"/> - <field-map field-name="productAssocTypeId" value="PRODUCT_VARIANT"/> - </entity-and> - <first-from-list list="variantProductAssocs" entry="variantProductAssoc"/> - <set field="productId" from-field="variantProductAssoc.productId"/> - </if-compare> - - <entity-and entity-name="ProductGroupOrder" list="productGroupOrders" filter-by-date="true"> - <field-map field-name="productId" from-field="productId"/> - </entity-and> - <if-not-empty field="productGroupOrders"> - <first-from-list list="productGroupOrders" entry="productGroupOrder"/> - <calculate field="productGroupOrder.soldOrderQty"> - <calcop operator="add" field="productGroupOrder.soldOrderQty"> - <calcop operator="get" field="orderItem.quantity"/> - </calcop> - </calculate> - <store-value value-field="productGroupOrder"/> - - <set field="createOrderItemGroupOrderMap.orderId" from-field="orderItem.orderId"/> - <set field="createOrderItemGroupOrderMap.orderItemSeqId" from-field="orderItem.orderItemSeqId"/> - <set field="createOrderItemGroupOrderMap.groupOrderId" from-field="productGroupOrder.groupOrderId"/> - <call-service service-name="createOrderItemGroupOrder" in-map-name="createOrderItemGroupOrderMap"/> - </if-not-empty> - </iterate> - </simple-method> - - <simple-method method-name="cancleOrderItemGroupOrder" short-description="Cancle OrderItemGroupOrder"> - <if-not-empty field="parameters.orderItemSeqId"> - <entity-and entity-name="OrderItem" list="orderItems"> - <field-map field-name="orderId" from-field="parameters.orderId"/> - <field-map field-name="orderItemSeqId" from-field="parameters.orderItemSeqId" /> - </entity-and> - <else> - <entity-and entity-name="OrderItem" list="orderItems"> - <field-map field-name="orderId" from-field="parameters.orderId"/> - </entity-and> - </else> - </if-not-empty> - <iterate list="orderItems" entry="orderItem"> - <entity-and entity-name="OrderItemGroupOrder" list="orderItemGroupOrders"> - <field-map field-name="orderId" from-field="orderItem.orderId"/> - <field-map field-name="orderItemSeqId" from-field="orderItem.orderItemSeqId"/> - </entity-and> - <if-not-empty field="orderItemGroupOrders"> - <first-from-list list="orderItemGroupOrders" entry="orderItemGroupOrder"/> - <entity-one entity-name="ProductGroupOrder" value-field="productGroupOrder"> - <field-map field-name="groupOrderId" from-field="orderItemGroupOrder.groupOrderId"/> - </entity-one> - <if-not-empty field="productGroupOrder"> - <if-compare field="productGroupOrder.statusId" operator="equals" value="GO_CREATED"> - <if-compare field="orderItem.statusId" operator="equals" value="ITEM_CANCELLED"> - <if-not-empty field="orderItem.cancelQuantity"> - <set field="cancelQuantity" from-field="orderItem.cancelQuantity"/> - <else> - <set field="cancelQuantity" from-field="orderItem.quantity"/> - </else> - </if-not-empty> - <calculate field="productGroupOrder.soldOrderQty"> - <calcop operator="subtract" field="productGroupOrder.soldOrderQty"> - <calcop operator="get" field="cancelQuantity"/> - </calcop> - </calculate> - </if-compare> - <store-value value-field="productGroupOrder"/> - <remove-value value-field="orderItemGroupOrder"/> - </if-compare> - </if-not-empty> - </if-not-empty> - </iterate> - </simple-method> - - <simple-method method-name="checkProductGroupOrderExpired" short-description="Check ProductGroupOrder Expired"> - <entity-one entity-name="ProductGroupOrder" value-field="productGroupOrder"/> - <if-not-empty field="productGroupOrder"> - <if-compare field="productGroupOrder.soldOrderQty" operator="greater-equals" value="${productGroupOrder.reqOrderQty}"> - <set field="newItemStatusId" value="ITEM_APPROVED"/> - <set field="groupOrderStatusId" value="GO_SUCCESS"/> - <else> - <set field="newItemStatusId" value="ITEM_CANCELLED"/> - <set field="groupOrderStatusId" value="GO_CANCELLED"/> - </else> - </if-compare> - - <set field="updateProductGroupOrderMap.groupOrderId" from-field="productGroupOrder.groupOrderId"/> - <set field="updateProductGroupOrderMap.statusId" from-field="groupOrderStatusId"/> - <call-service service-name="updateProductGroupOrder" in-map-name="updateProductGroupOrderMap"/> - - <entity-and entity-name="OrderItemGroupOrder" list="orderItemGroupOrders"> - <field-map field-name="groupOrderId" from-field="productGroupOrder.groupOrderId"/> - </entity-and> - <iterate list="orderItemGroupOrders" entry="orderItemGroupOrder"> - <set field="changeOrderItemStatusMap.orderId" from-field="orderItemGroupOrder.orderId"/> - <set field="changeOrderItemStatusMap.orderItemSeqId" from-field="orderItemGroupOrder.orderItemSeqId"/> - <set field="changeOrderItemStatusMap.statusId" from-field="newItemStatusId"/> - <call-service service-name="changeOrderItemStatus" in-map-name="changeOrderItemStatusMap"/> - </iterate> - </if-not-empty> - </simple-method> - - <simple-method method-name="setProductReviewStatus" short-description="change the product review Status"> - <set value="setProductReviewStatus" field="callingMethodName"/> - <set value="UPDATE" field="checkAction"/> - <call-simple-method method-name="checkProductRelatedPermission"/> - <check-errors/> - - <entity-one entity-name="ProductReview" value-field="productReview"/> - <if-not-empty field="productReview"> - <if-compare-field field="productReview.statusId" to-field="parameters.statusId" operator="not-equals"> - <entity-one entity-name="StatusValidChange" value-field="statusChange"> - <field-map field-name="statusId" from-field="productReview.statusId"/> - <field-map field-name="statusIdTo" from-field="parameters.statusId"/> - </entity-one> - <if-empty field="statusChange"> - <set field="msg" value="Status is not a valid change: from ${productReview.statusId} to ${parameters.statusId}"/> - <log level="error" message="${msg}"/> - <add-error> - <fail-property resource="ProductErrorUiLabels" property="ProductReviewErrorCouldNotChangeOrderStatusFromTo"/> - </add-error> - </if-empty> - </if-compare-field> - </if-not-empty> - <check-errors/> - - <set field="productReview.statusId" from-field="parameters.statusId"/> - <store-value value-field="productReview"/> - <field-to-result field="productReview.productReviewId" result-name="productReviewId"/> - </simple-method> -</simple-methods> diff --git a/applications/product/servicedef/services.xml b/applications/product/servicedef/services.xml index 249750a..999e479 100644 --- a/applications/product/servicedef/services.xml +++ b/applications/product/servicedef/services.xml @@ -255,6 +255,7 @@ under the License. If taxAuthGeoId or taxAuthPartyId empty then the taxInPrice field will be ignored. </description> + <permission-service service-name="checkProductRelatedPermission" main-action="CREATE"/> <auto-attributes include="pk" mode="IN" optional="false"/> <auto-attributes include="nonpk" mode="IN" optional="true"> <exclude field-name="priceWithoutTax"/> @@ -271,6 +272,7 @@ under the License. <service name="updateProductPrice" default-entity-name="ProductPrice" engine="simple" location="component://product/minilang/product/price/PriceServices.xml" invoke="updateProductPrice" auth="true"> <description>Update an ProductPrice</description> + <permission-service service-name="checkProductRelatedPermission" main-action="UPDATE"/> <auto-attributes include="pk" mode="IN" optional="false"/> <auto-attributes include="nonpk" mode="IN" optional="true"> <exclude field-name="priceWithoutTax"/> @@ -287,6 +289,7 @@ under the License. <service name="deleteProductPrice" default-entity-name="ProductPrice" engine="simple" location="component://product/minilang/product/price/PriceServices.xml" invoke="deleteProductPrice" auth="true"> <description>Delete an ProductPrice</description> + <permission-service service-name="checkProductRelatedPermission" main-action="DELETE"/> <auto-attributes include="pk" mode="IN" optional="false"/> <attribute name="oldPrice" type="BigDecimal" mode="OUT" optional="false"/> </service> @@ -1834,4 +1837,13 @@ under the License. <description>Expire a ProdCatalogInvFacility Record</description> <auto-attributes mode="IN" include="pk"/> </service> + + <!--Permission services --> + + <service name="checkProductRelatedPermission" engine="groovy" + location="component://product/groovyScripts/product/product/ProductServices.groovy" invoke="checkProductRelatedPermissionService"> + <description>Check Product Related Permission, a service to centralize product security code</description> + <implements service="permissionInterface"/> + <attribute name="productId" mode="IN" type="String" optional="true"/> + </service> </services> diff --git a/applications/product/servicedef/services_feature.xml b/applications/product/servicedef/services_feature.xml index a6c7395..f7e2320 100644 --- a/applications/product/servicedef/services_feature.xml +++ b/applications/product/servicedef/services_feature.xml @@ -80,6 +80,7 @@ under the License. <service name="applyFeatureToProductFromTypeAndCode" engine="simple" location="component://product/minilang/product/feature/ProductFeatureServices.xml" invoke="applyFeatureToProductFromTypeAndCode" auth="true"> <description>Apply a ProductFeature to a Product</description> + <permission-service service-name="checkProductRelatedPermission" main-action="CREATE"/> <attribute name="productId" type="String" mode="IN" optional="false"/> <attribute name="productFeatureTypeId" type="String" mode="IN" optional="false"/> <attribute name="idCode" type="String" mode="IN" optional="false"/>

