This is an automated email from the ASF dual-hosted git repository.
mbrohl 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 e0a26fc Improved: Convert ProductServices.xml mini lang to groovy
(OFBIZ-10231)
e0a26fc is described below
commit e0a26fce43eec7c84d87c0d5055ff0a87f2af796
Author: Michael Brohl <[email protected]>
AuthorDate: Fri Feb 21 16:59:37 2020 +0100
Improved: Convert ProductServices.xml mini lang to groovy
(OFBIZ-10231)
Thanks Dennis Balkir for reporting and Sebastian Berg for the
implementation.
---
.../product/product/ProductServices.groovy | 1095 ++++++++++++++++++++
.../minilang/product/product/ProductServices.xml | 1051 -------------------
applications/product/servicedef/services.xml | 112 +-
3 files changed, 1151 insertions(+), 1107 deletions(-)
diff --git
a/applications/product/groovyScripts/product/product/ProductServices.groovy
b/applications/product/groovyScripts/product/product/ProductServices.groovy
new file mode 100644
index 0000000..b4be894
--- /dev/null
+++ b/applications/product/groovyScripts/product/product/ProductServices.groovy
@@ -0,0 +1,1095 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+import java.sql.Timestamp
+
+import org.apache.ofbiz.base.util.UtilDateTime
+import org.apache.ofbiz.base.util.UtilProperties
+import org.apache.ofbiz.base.util.UtilValidate
+import org.apache.ofbiz.entity.GenericValue
+import org.apache.ofbiz.entity.serialize.XmlSerializer
+import org.apache.ofbiz.entity.util.EntityUtil
+import org.apache.ofbiz.product.product.KeywordIndex
+import org.apache.ofbiz.product.product.ProductWorker
+import org.apache.ofbiz.service.ServiceUtil
+
+
+
+ module = "ProductServices.groovy" // this is used for logging
+
+ /**
+ * Create a Product
+ */
+ def createProduct() {
+ Map result = success()
+ if (!(security.hasEntityPermission("CATALOG", "_CREATE",
parameters.userLogin)
+ || security.hasEntityPermission("CATALOG_ROLE", "_CREATE",
parameters.userLogin))) {
+ return error(UtilProperties.getMessage("ProductUiLabels",
"ProductCatalogCreatePermissionError", parameters.locale))
+ }
+
+ GenericValue newEntity = makeValue("Product")
+ newEntity.setNonPKFields(parameters)
+
+ newEntity.productId = parameters.productId
+
+ if (UtilValidate.isEmpty(newEntity.productId)) {
+ newEntity.productId = delegator.getNextSeqId("Product")
+ } else {
+ String errorMessage =
UtilValidate.checkValidDatabaseId(newEntity.productId)
+ if(errorMessage != null) {
+ logError(errorMessage)
+ return error(errorMessage)
+ }
+ GenericValue dummyProduct = findOne("Product", ["productId":
parameters.productId], false)
+ if (UtilValidate.isNotEmpty(dummyProduct)) {
+ errorMessage = UtilProperties.getMessage("CommonErrorUiLabels",
CommonErrorDuplicateKey, parameters.locale)
+ logError(errorMessage)
+ return error(errorMessage)
+ }
+ }
+ result.productId = newEntity.productId
+
+ Timestamp nowTimestamp = UtilDateTime.nowTimestamp()
+
+ newEntity.createdDate = nowTimestamp
+ newEntity.lastModifiedDate = nowTimestamp
+ newEntity.lastModifiedByUserLogin = userLogin.userLoginId
+ newEntity.createdByUserLogin = userLogin.userLoginId
+
+ if (UtilValidate.isEmpty(newEntity.isVariant)) {
+ newEntity.isVariant = "N"
+ }
+ if (UtilValidate.isEmpty(newEntity.isVirtual)) {
+ newEntity.isVirtual = "N"
+ }
+ if (UtilValidate.isEmpty(newEntity.billOfMaterialLevel)) {
+ newEntity.billOfMaterialLevel = (Long) 0
+ }
+
+ newEntity.create()
+
+ /*
+ * 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 (security.hasEntityPermission("CATALOG_ROLE","_CREATE",
parameters.userLogin)) {
+ List productCategoryRoles =
from("ProductCategoryRole").where("partyId": userLogin.partyId, "roleTypeId":
"LTD_ADMIN").queryList()
+
+ for (GenericValue productCategoryRole : productCategoryRoles) {
+ // add this new product to the category
+ GenericValue newLimitMember = makeValue("ProductCategoryMember")
+ newLimitMember.productId = newEntity.productId
+ newLimitMember.productCateogryId =
productCategoryRole.productCategoryId
+ newLimitMember.fromDate = nowTimestamp
+ newLimitMember.create()
+ }
+ }
+
+ return result
+}
+
+/**
+ * Update a product
+ */
+def updateProduct() {
+ Map res = checkProductRelatedPermission("updateProduct", "UPDATE")
+ if (!ServiceUtil.isSuccess(res)) {
+ return res
+ }
+ GenericValue lookedUpValue = findOne("Product", ["productId":
parameters.productId], false)
+ // save this value before overwriting it so we can compare it later
+ Map saveIdMap = ["primaryProductCategoryId":
lookedUpValue.primaryProductCategoryId]
+
+ lookedUpValue.setNonPKFields(parameters)
+ lookedUpValue.lastModifiedDate = UtilDateTime.nowTimestamp()
+ lookedUpValue.lastModifiedByUserLogin = userLogin.userLoginId
+ lookedUpValue.store()
+
+ return success()
+ }
+
+ /**
+ * Update a Product Name from quick admin
+ */
+def updateProductQuickAdminName() {
+ Map res = checkProductRelatedPermission("updateQuickAdminName", "UPDATE")
+
+ if (!ServiceUtil.isSuccess(res)) {
+ return res
+ }
+
+ GenericValue lookedUpValue = findOne("Product", ["productId":
parameters.productId], false)
+ lookedUpValue.productName = parameters.productName
+ if ("Y".equals(lookedUpValue.isVirtual)) {
+ lookedUpValue.internalName = lookedUpValue.productName
+ }
+
+ lookedUpValue.lastModifiedDate = UtilDateTime.nowTimestamp();
+ lookedUpValue.lastModifiedByUserLogin = userLogin.userLoginId
+
+ lookedUpValue.store()
+
+ if ("Y".equals(lookedUpValue.isVirtual)) {
+ // get all variant products, to update their productNames
+ Map variantProductAssocMap = ["productId": parameters.productId,
"productAssocTypeId": "PRODUCT_VARIANT"]
+
+ // get all productAssocs, then get the actual product to update
+ List variantProductAssocs =
from("ProductAssoc").where(variantProductAssocMap).queryList()
+ variantProductAssocs = EntityUtil.filterByDate(variantProductAssocs)
+ for(GenericValue variantProductAssoc : variantProductAssocs) {
+ GenericValue variantProduct = null
+ variantProduct = findOne("Product", ["productId":
variantProductAssoc.productIdTo], false)
+
+ variantProduct.productName = parameters.productName
+ variantProduct.lastModifiedDate = UtilDateTime.nowTimestamp()
+ variantProduct.lastModifiedByUserLogin = userLogin.userLoginId
+ variantProduct.store()
+ }
+ }
+ return success()
+}
+
+/**
+ * Duplicate a Product
+ */
+def duplicateProduct() {
+ String callingMethodName = "duplicateProduct"
+ String checkAction = "CREATE"
+ Map res = checkProductRelatedPermission(callingMethodName, checkAction)
+ if (!ServiceUtil.isSuccess(res)) {
+ return res
+ }
+ checkAction = "DELETE"
+ res = checkProductRelatedPermission(callingMethodName, checkAction)
+ if (!ServiceUtil.isSuccess(res)) {
+ return res
+ }
+ GenericValue dummyProduct = findOne("Product", ["productId":
parameters.productId], false)
+ if (UtilValidate.isNotEmpty(dummyProduct)) {
+ String errorMessage = UtilProperties.getMessage("CommonErrorUiLabels",
CommonErrorDuplicateKey, parameters.locale)
+ logError(errorMessage)
+ return error(errorMessage)
+ }
+
+ // look up the old product and clone it
+ GenericValue oldProduct = findOne("Product", ["productId":
parameters.oldProductId], false)
+ GenericValue newProduct = oldProduct.clone()
+
+ // set the productId, and write it to the datasource
+ newProduct.productId = parameters.productId
+
+ // if requested, set the new internalName field
+ if (UtilValidate.isNotEmpty(parameters.newInternalName)) {
+ newProduct.internalName = parameters.newInternalName
+ }
+
+ // if requested, set the new productName field
+ if (UtilValidate.isNotEmpty(parameters.newProductName)) {
+ newProduct.productName = parameters.newProductName
+ }
+
+ // if requested, set the new description field
+ if (UtilValidate.isNotEmpty(parameters.newDescription)) {
+ newProduct.description = parameters.newDescription
+ }
+
+ // if requested, set the new longDescription field
+ if (UtilValidate.isNotEmpty(parameters.newLongDescription)) {
+ newProduct.longDescription = parameters.newLongDescription
+ }
+
+ newProduct.create()
+
+ // set up entity filter
+ Map productFindContext = ["productId": parameters.oldProductId]
+ Map reverseProductFindContext = ["productIdTo": parameters.oldProductId]
+
+ // if requested, duplicate related data as well
+ if (UtilValidate.isNotEmpty(parameters.duplicatePrices)) {
+ List foundValues =
from("ProductPrice").where(productFindContext).queryList()
+ for (GenericValue foundValue : foundValues) {
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productId = parameters.productId
+ newTempValue.create()
+ }
+ }
+ if (UtilValidate.isNotEmpty(parameters.duplicateIDs)) {
+ List foundValues =
from("GoodIdentification").where(productFindContext).queryList()
+ for (GenericValue foundValue : foundValues) {
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productId = parameters.productId
+ newTempValue.create()
+ }
+ }
+ if (UtilValidate.isNotEmpty(parameters.duplicateContent)) {
+ List foundValues =
from("ProductContent").where(productFindContext).queryList()
+ for (GenericValue foundValue : foundValues) {
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productId = parameters.productId
+ newTempValue.create()
+ }
+ }
+ if (UtilValidate.isNotEmpty(parameters.duplicateCategoryMembers)) {
+ List foundValues =
from("ProductCategoryMember").where(productFindContext).queryList()
+ for (GenericValue foundValue : foundValues) {
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productId = parameters.productId
+
+ newTempValue.create()
+ }
+ }
+ if (UtilValidate.isNotEmpty(parameters.duplicateAssocs)) {
+ List foundValues =
from("ProductAssoc").where(productFindContext).queryList()
+ for (GenericValue foundValue : foundValues) {
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productId = parameters.productId
+ newTempValue.create()
+ }
+
+ // small difference here, also do the reverse assocs...
+ foundValues = from("ProductAssoc").where("productIdTo":
parameters.oldProductId).queryList()
+ for (GenericValue foundValue : foundValues) {
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productIdTo = parameters.productId
+ newTempValue.create()
+ }
+ }
+ if (UtilValidate.isNotEmpty(parameters.duplicateAttributes)) {
+ List foundValues =
from("ProductAttribute").where(productFindContext).queryList()
+ for (GenericValue foundValue : foundValues) {
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productId = parameters.productId
+ newTempValue.create()
+ }
+ }
+ if (UtilValidate.isNotEmpty(parameters.duplicateFeatureAppls)) {
+ List foundValues =
from("ProductFeatureAppl").where(productFindContext).queryList()
+ for (GenericValue foundValue : foundValues) {
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productId = parameters.productId
+ newTempValue.create()
+ }
+ }
+ if (UtilValidate.isNotEmpty(parameters.duplicateInventoryItems)) {
+ List foundValues =
from("InventoryItem").where(productFindContext).queryList()
+ for (GenericValue foundValue : foundValues) {
+ /*
+ * 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?
+ */
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productId = parameters.productId
+ // this one is slightly different because it needs a new sequenced
inventoryItemId
+ newTempValue.inventoryItemId =
delegator.getNextSeqId("InventoryItem")
+ newTempValue.create()
+ }
+ }
+
+ // if requested, remove related data as well
+ if (UtilValidate.isNotEmpty(parameters.removePrices)) {
+ delegator.removeByAnd("ProductPrice", productFindContext)
+ }
+ if (UtilValidate.isNotEmpty(parameters.removeIDs)) {
+ delegator.removeByAnd("GoodIdentification", productFindContext)
+ }
+ if (UtilValidate.isNotEmpty(parameters.removeContent)) {
+ delegator.removeByAnd("ProductContent", productFindContext)
+ }
+ if (UtilValidate.isNotEmpty(parameters.removeCategoryMembers)) {
+ delegator.removeByAnd("ProductCategoryMember", productFindContext)
+ }
+ if (UtilValidate.isNotEmpty(parameters.removeAssocs)) {
+ delegator.removeByAnd("ProductAssoc", productFindContext)
+ // small difference here, also do the reverse assocs...
+ delegator.removeByAnd("ProductAssoc", reverseProductFindContext)
+ }
+ if (UtilValidate.isNotEmpty(parameters.removeAttributes)) {
+ delegator.removeByAnd("ProductAttribute", productFindContext)
+ }
+ if (UtilValidate.isNotEmpty(parameters.removeFeatureAppls)) {
+ delegator.removeByAnd("ProductFeatureAppl", productFindContext)
+ }
+ if (UtilValidate.isNotEmpty(parameters.removeInventoryItems)) {
+ delegator.removeByAnd("InventoryItem", productFindContext)
+ }
+ return success()
+}
+
+// Product Keyword Services
+
+/**
+ * induce all the keywords of a product
+ */
+def forceIndexProductKeywords() {
+ GenericValue product = findOne("Product", [productId:
parameters.productId], false)
+ KeywordIndex.forceIndexKeywords(product)
+ return success()
+}
+
+/**
+ * delete all the keywords of a produc
+ */
+def deleteProductKeywords() {
+ GenericValue product = findOne("Product", [productId:
parameters.productId], false)
+ delegator.removeRelated("ProductKeyword", product)
+ return success()
+}
+
+/**
+ * Index the Keywords for a Product
+ */
+def indexProductKeywords() {
+ //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
+ GenericValue productInstance = parameters.productInstance
+ if (productInstance == null) {
+ Map findProductMap = [productId: parameters.productId]
+ productInstance = findOne("Product", findProductMap, false)
+ }
+ //induce keywords if autoCreateKeywords is empty or Y
+ if (UtilValidate.isEmpty(productInstance.autoCreateKeywords) ||
"Y".equals(productInstance.autoCreateKeywords)) {
+ KeywordIndex.indexKeywords(productInstance)
+ }
+ return success()
+}
+
+/**
+ * Discontinue Product Sales
+ * set sales discontinuation date to now
+ */
+def discontinueProductSales() {
+ // set sales discontinuation date to now
+ Timestamp nowTimestamp = UtilDateTime.nowTimestamp()
+ GenericValue product = findOne("Product", parameters, false)
+ product.salesDiscontinuationDate = nowTimestamp
+ product.store()
+
+ // expire product from all categories
+ List productCategoryMembers =
delegator.getRelated("ProductCategoryMember", null, null, product, false)
+ for (GenericValue productCategoryMember : productCategoryMembers) {
+ if (UtilValidate.isEmpty(productCategoryMember.thruDate)) {
+ productCategoryMember.thruDate = UtilDateTime.nowTimestamp()
+ productCategoryMember.store()
+ }
+ }
+ // expire product from all associations going to it
+ List assocProductAssocs = delegator.getRelated("AssocProductAssoc", null,
null, product, false)
+ for (GenericValue assocProductAssoc : assocProductAssocs) {
+ if (UtilValidate.isEmpty(assocProductAssoc.thruDate)) {
+ assocProductAssoc.thruDate = UtilDateTime.nowTimestamp()
+ assocProductAssoc.store()
+ }
+ }
+ return success()
+}
+
+
+def countProductView() {
+ if (UtilValidate.isEmpty(parameters.weight)) {
+ parameters.weight = (Long) 1
+ }
+ GenericValue productCalculatedInfo = findOne("ProductCalculatedInfo",
["productId": parameters.productId], false)
+ if (UtilValidate.isEmpty(productCalculatedInfo)) {
+ // go ahead and create it
+ productCalculatedInfo = makeValue("ProductCalculatedInfo")
+ productCalculatedInfo.productId = parameters.productId
+ productCalculatedInfo.totalTimesViewed = parameters.weight
+ productCalculatedInfo.create()
+ } else {
+ productCalculatedInfo.totalTimesViewed =
productCalculatedInfo.totalTimesViewed + parameters.weight
+ productCalculatedInfo.store()
+ }
+
+ // do the same for the virtual product...
+ GenericValue product = findOne("Product", ["productId":
parameters.productId], true)
+ ProductWorker productWorker = new ProductWorker()
+ String virtualProductId = productWorker.getVariantVirtualId(product)
+ if (UtilValidate.isNotEmpty(virtualProductId)) {
+ Map callSubMap = ["productId": virtualProductId, "weight":
parameters.weight]
+ run service: "countProductView", with: callSubMap
+ }
+ return success()
+
+}
+
+/**
+ * Create a ProductReview
+ */
+def createProductReview() {
+ GenericValue newEntity = makeValue("ProductReview", parameters)
+ newEntity.userLoginId = userLogin.userLoginId
+ newEntity.statusId = "PRR_PENDING"
+
+ // code to check for auto-approved reviews (store setting)
+ GenericValue productStore = findOne("ProductStore", ["productStoreId":
parameters.productStoreId], false)
+
+ if (!UtilValidate.isEmpty(productStore)) {
+ if ("Y".equals(productStore.autoApproveReviews)) {
+ newEntity.statusId = "PRR_APPROVED"
+ }
+ }
+
+ // create the new ProductReview
+ newEntity.productReviewId = delegator.getNextSeqId("ProductReview")
+ Map result = success()
+ result.productReviewId = newEntity.productReviewId
+
+ if (UtilValidate.isEmpty(newEntity.postedDateTime)) {
+ newEntity.postedDateTime = UtilDateTime.nowTimestamp()
+ }
+
+ newEntity.create()
+
+ String productId = newEntity.productId
+ String successMessage = UtilProperties.getMessage("ProductUiLabels",
"ProductCreateProductReviewSuccess", parameters.locale)
+ updateProductWithReviewRatingAvg(productId)
+
+ return result
+}
+
+/**
+ * Update ProductReview
+ */
+def updateProductReview() {
+ Map res = checkProductRelatedPermission("updateProductReview", "UPDATE")
+ if (!ServiceUtil.isSuccess(res)) {
+ return res
+ }
+
+ GenericValue lookupPKMap = makeValue("ProductReview")
+ lookupPKMap.setPKFields(parameters)
+ GenericValue lookedUpValue = findOne("ProductReview", lookupPKMap, false)
+ lookupPKMap.setNonPKFields(parameters)
+ lookupPKMap.store()
+
+ String productId = lookedUpValue.productId
+ updateProductWithReviewRatingAvg(productId)
+
+ return success()
+}
+
+/**
+ * change the product review Status
+ */
+def setProductReviewStatus(){
+ Map res = checkProductRelatedPermission("setProductReviewStatus", "UPDATE")
+ if (!ServiceUtil.isSuccess(res)) {
+ return res
+ }
+
+ GenericValue productReview = findOne("ProductReview", parameters, false)
+ if (UtilValidate.isNotEmpty(productReview)) {
+ if (!productReview.statusId.equals(parameters.statusId)) {
+ GenericValue statusChange = from("StatusValidChange")
+ .where("statusId", productReview.statusId, "statusIdTo",
parameters.statusId)
+ .queryOne()
+ if (UtilValidate.isEmpty(statusChange)) {
+ String msg = "Status is not a valid change: from " +
productReview.statusId + " to " + parameters.statusId
+ logError(msg)
+ String errorMessage =
UtilProperties.getMessage("ProductErrorUiLabels",
ProductReviewErrorCouldNotChangeOrderStatusFromTo, parameters.locale)
+ logError(errorMessage)
+ return error(errorMessage)
+ }
+ }
+ }
+
+ productReview.statusId = parameters.statusId
+ productReview.store()
+ Map result = success()
+ result.productReviewId = productReview.productReviewId
+
+ return result
+}
+
+/**
+ * Update Product with new Review Rating Avg
+ * this method is meant to be called in-line and depends in a productId
parameter
+ */
+def updateProductWithReviewRatingAvg(String productId) {
+ ProductWorker productWorker = new ProductWorker()
+ BigDecimal averageCustomerRating =
productWorker.getAverageProductRating(delegator, productId)
+ logInfo("Got new average customer rating "+ averageCustomerRating)
+
+ if (averageCustomerRating == 0) {
+ return success()
+ }
+
+ // update the review average on the ProductCalculatedInfo entity
+ GenericValue productCalculatedInfo = findOne("ProductCalculatedInfo",
parameters, false)
+ if (UtilValidate.isEmpty(productCalculatedInfo)) {
+ // go ahead and create it
+ productCalculatedInfo = makeValue("ProductCalculatedInfo")
+ productCalculatedInfo.productId = productId
+ productCalculatedInfo.averageCustomerRating = averageCustomerRating
+ productCalculatedInfo.create()
+ } else {
+ productCalculatedInfo.averageCustomerRating = averageCustomerRating
+ productCalculatedInfo.store()
+ }
+
+ return success()
+}
+
+/**
+ * Updates the Product's Variants
+ */
+def copyToProductVariants() {
+ String callingMethodName = "copyToProductVariants"
+ String checkAction = "CREATE"
+ Map res = checkProductRelatedPermission(callingMethodName, checkAction)
+ if (!ServiceUtil.isSuccess(res)) {
+ return res
+ }
+ checkAction = "DELETE"
+ res = checkProductRelatedPermission(callingMethodName, checkAction)
+ if (!ServiceUtil.isSuccess(res)) {
+ return res
+ }
+
+ Map productFindContext = ["productId": parameters.virtualProductId]
+ GenericValue oldProduct = findOne("Product", productFindContext, false)
+
+ Map variantsFindContext = ["productId": parameters.virtualProductId,
"productAssocTypeId": "PRODUCT_VARIANT"]
+
+ List variants =
from("ProductAssoc").where(variantsFindContext).filterByDate().queryList()
+ List foundVariantValues = []
+ List foundValues = []
+ for (GenericValue newProduct : variants) {
+ Map productVariantContext = ["productId": newProduct.productIdTo]
+ // if requested, duplicate related data
+ if (UtilValidate.isNotEmpty(parameters.duplicatePrices)) {
+ if (UtilValidate.isNotEmpty(parameters.removeBefore)) {
+ foundVariantValues =
from("ProductPrice").where(productVariantContext).queryList()
+ for (GenericValue foundVariantValue : foundVariantValues) {
+ foundVariantValue.remove()
+ }
+ }
+ foundValues =
from("ProductPrice").where(productFindContext).queryList()
+ for (GenericValue foundValue : foundValues) {
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productId = newProduct.productIdTo
+ newTempValue.create()
+ }
+ }
+ if (UtilValidate.isNotEmpty(parameters.duplicateIDs)) {
+ if (UtilValidate.isNotEmpty(parameters.removeBefore)) {
+ foundVariantValues =
from("GoodIdentification").where(productVariantContext).queryList()
+ for (GenericValue foundVariantValue : foundVariantValues) {
+ foundVariantValue.remove()
+ }
+ }
+ foundValues =
from("GoodIdentification").where(productFindContext).queryList()
+ for (GenericValue foundValue : foundValues) {
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productId = newProduct.productIdTo
+ newTempValue.create()
+ }
+
+ }
+ if (UtilValidate.isNotEmpty(parameters.duplicateContent)) {
+ if (UtilValidate.isNotEmpty(parameters.removeBefore)) {
+ foundVariantValues =
from("ProductContent").where(productVariantContext).queryList()
+ for (GenericValue foundVariantValue : foundVariantValues) {
+ foundVariantValue.remove()
+ }
+ }
+ foundValues =
from("ProductContent").where(productFindContext).queryList()
+ for (GenericValue foundValue : foundValues) {
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productId = newProduct.productIdTo
+ newTempValue.create()
+ }
+ }
+ if (UtilValidate.isNotEmpty(parameters.duplicateCategoryMembers)) {
+ if (UtilValidate.isNotEmpty(parameters.removeBefore)) {
+ foundVariantValues =
from("ProductCategoryMember").where(productVariantContext).queryList()
+ for (GenericValue foundVariantValue : foundVariantValues) {
+ foundVariantValue.remove()
+ }
+ }
+ foundValues =
from("ProductCategoryMember").where(productFindContext).queryList()
+ for (GenericValue foundValue : foundValues) {
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productId = newProduct.productIdTo
+ newTempValue.create()
+ }
+ }
+ if (UtilValidate.isNotEmpty(parameters.duplicateAttributes)) {
+ if (UtilValidate.isNotEmpty(parameters.removeBefore)) {
+ foundVariantValues =
from("ProductAttribute").where(productVariantContext).queryList()
+ for (GenericValue foundVariantValue : foundVariantValues) {
+ foundVariantValue.remove()
+ }
+ }
+ foundValues =
from("ProductAttribute").where(productFindContext).queryList()
+ for (GenericValue foundValue : foundValues) {
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productId = newProduct.productIdTo
+ newTempValue.create()
+ }
+ }
+ if (UtilValidate.isNotEmpty(parameters.duplicateFacilities)) {
+ if (UtilValidate.isNotEmpty(parameters.removeBefore)) {
+ foundVariantValues =
from("ProductFacility").where(productVariantContext).queryList()
+ for (GenericValue foundVariantValue : foundVariantValues) {
+ foundVariantValue.remove()
+ }
+ }
+ foundValues =
from("ProductFacility").where(productFindContext).queryList()
+ for (GenericValue foundValue : foundValues) {
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productId = newProduct.productIdTo
+ newTempValue.create()
+ }
+ }
+ if (UtilValidate.isNotEmpty(parameters.duplicateLocations)) {
+ if (UtilValidate.isNotEmpty(parameters.removeBefore)) {
+ foundVariantValues =
from("ProductFacilityLocation").where(productVariantContext).queryList()
+ for (GenericValue foundVariantValue : foundVariantValues) {
+ foundVariantValue.remove()
+ }
+ }
+ foundValues =
from("ProductFacilityLocation").where(productFindContext).queryList()
+ for (GenericValue foundValue : foundValues) {
+ GenericValue newTempValue = foundValue.clone()
+ newTempValue.productId = newProduct.productIdTo
+ newTempValue.create()
+ }
+ }
+ }
+ return success()
+}
+
+/**
+ * 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 (UtilValidate.isEmpty(callingMethodName)) {
+ callingMethodName = UtilProperties.getMessage("CommonUiLabels",
"CommonPermissionThisOperation", parameters.locale)
+ }
+ if (UtilValidate.isEmpty(checkAction)) {
+ checkAction = "UPDATE"
+ }
+ List roleCategories = []
+ // find all role-categories that this product is a member of
+ if (!security.hasEntityPermission("CATALOG", "_${checkAction}",
parameters.userLogin)) {
+ Map lookupRoleCategoriesMap = ["productId": parameters.productId,
"partyId": userLogin.partyId, "roleTypeId": "LTD_ADMIN"]
+ roleCategories =
from("ProductCategoryMemberAndRole").where(lookupRoleCategoriesMap).filterByDate("roleFromDate",
"roleThruDate").queryList()
+ }
+
+ if (! ((security.hasEntityPermission("CATALOG", "_${checkAction}",
parameters.userLogin))
+ || (security.hasEntityPermission("CATALOG_ROLE", "_${checkAction}",
parameters.userLogin) && !UtilValidate.isEmpty(roleCategories))
+ || (!UtilValidate.isEmpty(parameters.alternatePermissionRoot) &&
security.hasEntityPermission(parameters.alternatePermissionRoot, checkAction,
parameters.userLogin)))) {
+ String checkActionLabel = "ProductCatalog" + checkAction.charAt(0)
+ checkAction.substring(1).toLowerCase() + "PermissionError"
+ String resourceDescription = callingMethodName
+
+ String errorMessage = UtilProperties.getMessage("ProductUiLabels",
checkActionLabel, parameters.locale)
+ logError(errorMessage)
+ return error(errorMessage)
+ }
+ return success()
+}
+
+/**
+ * Main permission logic
+ */
+def productGenericPermission(){
+ String mainAction = parameters.mainAction
+ Map result = success()
+ if (UtilValidate.isEmpty(mainAction)) {
+ String errorMessage = UtilProperties.getMessage("ProductUiLabels",
"ProductMissingMainActionInPermissionService", parameters.locale)
+ logError(errorMessage)
+ return error(errorMessage)
+ }
+ Map res = checkProductRelatedPermission(parameters.resourceDescription,
parameters.mainAction)
+ if (!ServiceUtil.isSuccess(res)) {
+ String failMessage = UtilProperties.getMessage("ProductUiLabels",
"ProductPermissionError", parameters.locale)
+ Boolean hasPermission = false
+ result = fail(failMessage)
+ result.hasPermission = hasPermission
+ } else {
+ Boolean hasPermission = true
+ result.hasPermission = hasPermission
+ }
+ return result
+}
+
+/**
+ * product price permission logic
+ */
+def productPriceGenericPermission(){
+ String mainAction = parameters.mainAction
+ if (UtilValidate.isEmpty(mainAction)) {
+ String errorMessage = UtilProperties.getMessage("ProductUiLabels",
"ProductMissingMainActionInPermissionService", parameters.locale)
+ logError(errorMessage)
+ return error(errorMessage)
+ }
+ Map result = success()
+ if (!security.hasEntityPermission("CATALOG_PRICE_MAINT", null,
parameters.userLogin)) {
+ String errorMessage = UtilProperties.getMessage("ProductUiLabels",
"ProductPriceMaintPermissionError", parameters.locale)
+ logError(errorMessage)
+ result = error(errorMessage)
+ }
+ Map res = checkProductRelatedPermission(null, null)
+ if (ServiceUtil.isSuccess(result) && ServiceUtil.isSuccess(res)) {
+ result.hasPermission = true
+ } else {
+ String failMessage = UtilProperties.getMessage("ProductUiLabels",
"ProductPermissionError", parameters.locale)
+ result = fail(failMessage)
+ result.hasPermission = false
+ }
+ return result
+}
+
+/**
+ * ================================================================
+ * ProductRole Services
+ * ================================================================
+ */
+
+
+/**
+ * Add Party to Product
+ */
+def addPartyToProduct(){
+ Map result = checkProductRelatedPermission("addPartyToProduct", "CREATE")
+ if (!ServiceUtil.isSuccess(result)) {
+ return result
+ }
+ GenericValue newEntity = makeValue("ProductRole", parameters)
+
+ if (UtilValidate.isEmpty(newEntity.fromDate)) {
+ newEntity.fromDate = UtilDateTime.nowTimestamp()
+ }
+ newEntity.create()
+ return success()
+}
+
+/**
+ * Update Party to Product
+ */
+def updatePartyToProduct(){
+ Map result = checkProductRelatedPermission("updatePartyToProduct",
"UPDATE")
+ if (!ServiceUtil.isSuccess(result)) {
+ return result
+ }
+ GenericValue lookupPKMap = makeValue("ProductRole")
+ lookupPKMap.setPKFields(parameters)
+ GenericValue lookedUpValue = findOne("ProductRole", lookupPKMap, false)
+ lookedUpValue.setNonPKFields(parameters)
+ lookedUpValue.store()
+ return success()
+}
+
+/**
+ * Remove Party From Product
+ */
+def removePartyFromProduct(){
+ Map res = checkProductRelatedPermission("removePartyFromProduct", "DELETE")
+ if (!ServiceUtil.isSuccess(res)) {
+ return res
+ }
+ Map lookupPKMap = makeValue("ProductRole")
+ lookupPKMap.setPKFields(parameters)
+ GenericValue lookedUpValue = findOne("ProductRole", lookupPKMap, false)
+ lookedUpValue.remove()
+
+ return success()
+}
+
+// ProductCategoryGlAccount methods
+ /**
+ * Create a ProductCategoryGlAccount
+ */
+def createProductCategoryGlAccount(){
+ Map res = checkProductRelatedPermission("createProductCategoryGlAccount",
"CREATE")
+ if (!ServiceUtil.isSuccess(res)) {
+ return res
+ }
+
+ GenericValue newEntity = makeValue("ProductCategoryGlAccount", parameters)
+ newEntity.create()
+
+ return success()
+}
+
+/**
+ * Update a ProductCategoryGlAccount
+ */
+def updateProductCategoryGlAccount(){
+ Map res = checkProductRelatedPermission("updateProductCategoryGlAccount",
"UPDATE")
+ if (!ServiceUtil.isSuccess(res)) {
+ return res
+ }
+
+ GenericValue lookedUpValue = findOne("ProductCategoryGlAccount",
parameters, false)
+ lookedUpValue.setNonPKFields(parameters)
+ lookedUpValue.store()
+
+ return success()
+}
+
+/**
+ * Delete a ProductCategoryGlAccount
+ */
+def deleteProductCategoryGlAccount(){
+ Map res = checkProductRelatedPermission("deleteProductCategorGLAccount",
"DELETE")
+ if (!ServiceUtil.isSuccess(res)) {
+ return res
+ }
+ GenericValue lookedUpValue = findOne("ProductCategoryGlAccount",
parameters, false)
+ lookedUpValue.remove()
+
+ return success()
+}
+
+// Product GroupOrder Services -->
+
+/**
+ * Create ProductGroupOrder
+ */
+def createProductGroupOrder(){
+ GenericValue newEntity = makeValue("ProductGroupOrder")
+ delegator.setNextSubSeqId(newEntity, "groupOrderId", 5, 1)
+ Map result = success()
+ result.groupOrderId = newEntity.groupOrderId
+ newEntity.setNonPKFields(parameters)
+ newEntity.create()
+
+ return result
+}
+
+/**
+ * Update ProductGroupOrder
+ */
+def updateProductGroupOrder(){
+ GenericValue productGroupOrder = findOne("ProductGroupOrder",
["groupOrderId": parameters.groupOrderId], false)
+ productGroupOrder.setNonPKFields(parameters)
+ productGroupOrder.store()
+
+ if ("GO_CREATED".equals(productGroupOrder.statusId)) {
+ GenericValue jobSandbox = findOne("JobSandbox", ["jobId":
productGroupOrder.jobId], false)
+ if (UtilValidate.isNotEmpty(jobSandbox)) {
+ jobSandbox.runTime = parameters.thruDate
+ jobSandbox.store()
+ }
+ }
+ return success()
+}
+
+/**
+ * Delete ProductGroupOrder
+ */
+def deleteProductGroupOrder(){
+ List orderItemGroupOrders =
from("OrderItemGroupOrder").where("groupOrderId":
parameters.groupOrderId).queryList()
+ for (GenericValue orderItemGroupOrder : orderItemGroupOrders) {
+ orderItemGroupOrder.remove()
+ }
+ GenericValue productGroupOrder = findOne("ProductGroupOrder",
["groupOrderId": parameters.groupOrderId], false)
+ if (UtilValidate.isEmpty(productGroupOrder)) {
+ return error("Entity value not found with name: " + productGroupOrder)
+ }
+ productGroupOrder.remove()
+
+ GenericValue jobSandbox = findOne("JobSandbox", ["jobId":
productGroupOrder.jobId], false)
+ if (UtilValidate.isEmpty(jobSandbox)) {
+ return error("Entity value not found with name: " + jobSandbox)
+ }
+ jobSandbox.remove()
+
+ List jobSandboxList = from("JobSandbox").where("runtimeDataId":
jobSandbox.runtimeDataId).queryList()
+ for (GenericValue jobSandboxRelatedRuntimeData : jobSandboxList) {
+ jobSandboxRelatedRuntimeData.remove()
+ }
+
+ GenericValue runtimeData = findOne("RuntimeData", ["runtimeDataId":
jobSandbox.runtimeDataId], false)
+ if (UtilValidate.isEmpty(runtimeData)) {
+ return error("Entity value not found with name: " + runtimeData)
+ }
+ runtimeData.remove()
+
+ return success()
+}
+
+/**
+ * Create ProductGroupOrder
+ */
+def createJobForProductGroupOrder(){
+ GenericValue productGroupOrder = findOne("ProductGroupOrder",
["groupOrderId": parameters.groupOrderId], false)
+ if (UtilValidate.isEmpty(productGroupOrder.jobId)) {
+ // Create RuntimeData For ProductGroupOrder
+ Map runtimeDataMap = ["groupOrderId": parameters.groupOrderId]
+ XmlSerializer xmlSerializer = new XmlSerializer()
+ String runtimeInfo = xmlSerializer.serialize(runtimeDataMap)
+
+ GenericValue runtimeData = makeValue("RuntimeData")
+ runtimeData.runtimeDataId = delegator.getNextSeqId("RuntimeData")
+ String runtimeDataId = runtimeData.runtimeDataId
+ runtimeData.runtimeInfo = runtimeInfo
+ runtimeData.create()
+
+ // Create Job For ProductGroupOrder
+ // FIXME: Jobs should not be manually created
+ GenericValue jobSandbox = makeValue("JobSandbox")
+ jobSandbox.jobId = delegator.getNextSeqId("JobSandbox")
+ String jobId = jobSandbox.jobId
+ jobSandbox.jobName = "Check ProductGroupOrder Expired"
+ jobSandbox.runTime = parameters.thruDate
+ jobSandbox.poolId = "pool"
+ jobSandbox.statusId = "SERVICE_PENDING"
+ jobSandbox.serviceName = "checkProductGroupOrderExpired"
+ jobSandbox.runAsUser = "system"
+ jobSandbox.runtimeDataId = runtimeDataId
+ jobSandbox.maxRecurrenceCount = (Long) 1
+ jobSandbox.priority = (Long) 50
+ jobSandbox.create()
+
+ productGroupOrder.jobId = jobId
+ productGroupOrder.store()
+ }
+ return success()
+}
+
+/**
+ * Check OrderItem For ProductGroupOrder
+ */
+def checkOrderItemForProductGroupOrder(){
+ List orderItems = from("OrderItem").where("orderId":
parameters.orderId).queryList()
+ for (GenericValue orderItem : orderItems) {
+ String productId = orderItem.productId
+ GenericValue product = findOne("Product", ["productId":
orderItem.productId], false)
+ if ("Y".equals(product.isVariant)) {
+ List variantProductAssocs =
from("ProductAssoc").where("productIdTo": orderItem.productId,
"productAssocTypeId": "PRODUCT_VARIANT").queryList()
+ variantProductAssocs =
EntityUtil.filterByDate(variantProductAssocs)
+ GenericValue variantProductAssoc = variantProductAssocs.get(0)
+ productId = variantProductAssoc.productId
+ }
+ List productGroupOrders = from("ProductGroupOrder").where("productId":
productId).queryList()
+ if (UtilValidate.isNotEmpty(productGroupOrders)) {
+ productGroupOrders = EntityUtil.filterByDate(productGroupOrders)
+ GenericValue productGroupOrder = productGroupOrders.get(0)
+ if (UtilValidate.isEmpty(productGroupOrder.soldOrderQty)) {
+ productGroupOrder.soldOrderQty = orderItem.quantity
+ } else {
+ productGroupOrder.soldOrderQty = productGroupOrder.soldOrderQty +
orderItem.quantity
+ }
+ productGroupOrder.store()
+
+ Map createOrderItemGroupOrderMap = ["orderId": orderItem.orderId,
"orderItemSeqId": orderItem.orderItemSeqId, "groupOrderId":
productGroupOrder.groupOrderId]
+
+ run service: "createOrderItemGroupOrder", with:
createOrderItemGroupOrderMap
+ }
+ }
+ return success()
+}
+
+/**
+ * Cancle OrderItemGroupOrder
+ */
+def cancleOrderItemGroupOrder(){
+ List orderItems = []
+ if (UtilValidate.isNotEmpty(parameters.orderItemSeqId)) {
+ orderItems = from("OrderItem")
+ .where("orderId", parameters.orderId, "orderItemSeqId",
parameters.orderItemSeqId)
+ .queryList()
+ } else {
+ orderItems = from("OrderItem")
+ .where("orderId", parameters.orderId)
+ .queryList()
+ }
+ for(GenericValue orderItem : orderItems) {
+ List orderItemGroupOrders = from("OrderItemGroupOrder")
+ .where("orderId", orderItem.orderId, "orderItemSeqId",
orderItem.orderItemSeqId)
+ .queryList()
+ if (UtilValidate.isNotEmpty(orderItemGroupOrders)) {
+ GenericValue orderItemGroupOrder = orderItemGroupOrders.get(0)
+ GenericValue productGroupOrder = findOne("ProductGroupOrder",
[groupOrderId: orderItemGroupOrder.groupOrderId], false)
+
+ if (UtilValidate.isNotEmpty(productGroupOrder)) {
+ if ("GO_CREATED".equals(productGroupOrder.statusId)) {
+ if ("ITEM_CANCELLED".equals(orderItem.statusId)) {
+ BigDecimal cancelQuantity
+ if (UtilValidate.isNotEmpty(orderItem.cancelQuantity))
{
+ cancelQuantity = orderItem.cancelQuantity
+ } else {
+ cancelQuantity = orderItem.quantity
+ }
+ productGroupOrder.soldOrderQty =
productGroupOrder.soldOrderQty - cancelQuantity
+ }
+ productGroupOrder.store()
+ orderItemGroupOrder.remove()
+ }
+ }
+ }
+ }
+ return success()
+}
+
+/**
+ * Check ProductGroupOrder Expired
+ */
+def checkProductGroupOrderExpired(){
+ GenericValue productGroupOrder = findOne("ProductGroupOrder", parameters,
false)
+ if (UtilValidate.isNotEmpty(productGroupOrder)) {
+ String groupOrderStatusId
+ String newItemStatusId
+ if (productGroupOrder.soldOrderQty >= productGroupOrder.reqOrderQty) {
+ newItemStatusId = "ITEM_APPROVED"
+ groupOrderStatusId = "GO_SUCCESS"
+ } else {
+ newItemStatusId = "ITEM_CANCELLED"
+ groupOrderStatusId = "GO_CANCELLED"
+ }
+ Map updateProductGroupOrderMap = [:]
+ updateProductGroupOrderMap.groupOrderId = productGroupOrder.groupOrderId
+ updateProductGroupOrderMap.statusId = groupOrderStatusId
+ run service: "updateProductGroupOrder", with: updateProductGroupOrderMap
+
+ List orderItemGroupOrders = from("OrderItemGroupOrder")
+ .where("groupOrderId", productGroupOrder.groupOrderId)
+ .queryList()
+ for(GenericValue orderItemGroupOrder : orderItemGroupOrders) {
+ Map changeOrderItemStatusMap = ["orderId":
orderItemGroupOrder.orderId, "orderItemSeqId":
orderItemGroupOrder.orderItemSeqId, "statusId": newItemStatusId]
+ run service: "changeOrderItemStatus", with: changeOrderItemStatusMap
+ }
+ return success()
+ }
+}
+
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 4e821b4..b44cba7 100644
--- a/applications/product/servicedef/services.xml
+++ b/applications/product/servicedef/services.xml
@@ -37,22 +37,22 @@ under the License.
<override name="description" allow-html="safe"/>
<override name="longDescription" allow-html="safe"/>
</service>
- <service name="createProduct" default-entity-name="Product" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="createProduct" auth="true">
+ <service name="createProduct" default-entity-name="Product" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="createProduct" auth="true">
<description>Create a Product</description>
<implements service="interfaceProduct"/>
<auto-attributes include="pk" mode="INOUT" optional="true"/>
<override name="productTypeId" optional="false"/>
<override name="internalName" optional="false"/>
</service>
- <service name="updateProduct" default-entity-name="Product" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="updateProduct" auth="true">
+ <service name="updateProduct" default-entity-name="Product" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="updateProduct" auth="true">
<description>Update a Product</description>
<implements service="interfaceProduct"/>
<auto-attributes include="pk" mode="IN" optional="false"/>
</service>
- <service name="updateProductQuickAdminName" default-entity-name="Product"
engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="updateProductQuickAdminName" auth="true">
+ <service name="updateProductQuickAdminName" default-entity-name="Product"
engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="updateProductQuickAdminName" auth="true">
<description>Update a Product from Quick Admin</description>
<implements service="interfaceProduct"/>
<auto-attributes include="pk" mode="IN" optional="false"/>
@@ -63,8 +63,8 @@ under the License.
<implements service="interfaceProduct"/>
<auto-attributes include="pk" mode="IN" optional="false"/>
</service>
- <service name="duplicateProduct" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="duplicateProduct" auth="true">
+ <service name="duplicateProduct" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="duplicateProduct" auth="true">
<description>Duplicate a Product using a new productId</description>
<attribute name="productId" type="String" mode="IN" optional="false"/>
<attribute name="oldProductId" type="String" mode="IN"
optional="false"/>
@@ -89,8 +89,8 @@ under the License.
<attribute name="removeFeatureAppls" type="String" mode="IN"
optional="true"/>
<attribute name="removeInventoryItems" type="String" mode="IN"
optional="true"/>
</service>
- <service name="copyToProductVariants" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="copyToProductVariants" auth="true">
+ <service name="copyToProductVariants" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="copyToProductVariants" auth="true">
<description>Copy Virtual Product's data to the Variant
Products</description>
<attribute name="virtualProductId" type="String" mode="IN"
optional="false"/>
<attribute name="removeBefore" type="String" mode="IN"
optional="true"/>
@@ -151,40 +151,40 @@ under the License.
<permission-service service-name="productGenericPermission"
main-action="DELETE"/>
<auto-attributes include="pk" mode="IN" optional="false"/>
</service>
- <service name="deleteProductKeywords" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="deleteProductKeywords" auth="true">
+ <service name="deleteProductKeywords" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="deleteProductKeywords" auth="true">
<description>Delete all the keywords of a product</description>
<permission-service service-name="productGenericPermission"
main-action="DELETE"/>
<attribute name="productId" type="String" mode="IN" optional="false"/>
</service>
- <service name="indexProductKeywords" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="indexProductKeywords" auth="false">
+ <service name="indexProductKeywords" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="indexProductKeywords" auth="false">
<description>Index the Keywords for a Product</description>
<attribute name="productId" type="String" mode="IN" optional="false"/>
<attribute name="productInstance"
type="org.apache.ofbiz.entity.GenericValue" mode="IN" optional="true"/>
</service>
- <service name="forceIndexProductKeywords" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="forceIndexProductKeywords" auth="true">
+ <service name="forceIndexProductKeywords" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="forceIndexProductKeywords" auth="true">
<description>Induce all the keywords of a product, ignoring the flag
in the Product.autoCreateKeywords flag</description>
<permission-service service-name="productGenericPermission"
main-action="CREATE"/>
<attribute name="productId" type="String" mode="IN" optional="false"/>
</service>
- <service name="discontinueProductSales" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="discontinueProductSales" auth="false">
+ <service name="discontinueProductSales" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="discontinueProductSales" auth="false">
<description>Discontinue Product Sales</description>
<attribute name="productId" type="String" mode="IN" optional="false"/>
</service>
- <service name="countProductView" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="countProductView" auth="false">
+ <service name="countProductView" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="countProductView" auth="false">
<description>count Product View</description>
<attribute name="productId" type="String" mode="IN" optional="false"/>
<attribute name="weight" type="Long" mode="IN" optional="true"/>
</service>
- <service name="createProductReview" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="createProductReview" auth="true">
+ <service name="createProductReview" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="createProductReview" auth="true">
<description>Create a product review entity</description>
<auto-attributes entity-name="ProductReview" mode="IN" include="nonpk"
optional="true"/>
<attribute name="productReviewId" type="String" mode="OUT"
optional="false"/>
@@ -192,8 +192,8 @@ under the License.
<override name="productId" optional="false"/>
<override name="productRating" optional="false"/>
</service>
- <service name="updateProductReview" engine="simple"
default-entity-name="ProductReview"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="updateProductReview" auth="true">
+ <service name="updateProductReview" engine="groovy"
default-entity-name="ProductReview"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="updateProductReview" auth="true">
<description>Updates a product review record</description>
<required-permissions join-type="OR">
<check-permission permission="CATALOG_UPDATE"/>
@@ -202,8 +202,8 @@ under the License.
<auto-attributes mode="IN" include="pk" optional="false"/>
<auto-attributes mode="IN" include="nonpk" optional="true"/>
</service>
- <service name="setProductReviewStatus" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="setProductReviewStatus" auth="true">
+ <service name="setProductReviewStatus" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="setProductReviewStatus" auth="true">
<description>Updates a product review record</description>
<required-permissions join-type="OR">
<check-permission permission="CATALOG_UPDATE"/>
@@ -784,8 +784,8 @@ under the License.
<attribute name="fromDate" type="Timestamp" mode="IN"
optional="false"/>
</service>
- <service name="addPartyToProduct" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="addPartyToProduct" auth="true">
+ <service name="addPartyToProduct" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="addPartyToProduct" auth="true">
<description>Add Party To Product</description>
<attribute name="productId" type="String" mode="IN" optional="false"/>
<attribute name="partyId" type="String" mode="IN" optional="false"/>
@@ -795,8 +795,8 @@ under the License.
<attribute name="sequenceNum" type="Long" mode="IN" optional="true"/>
<attribute name="comments" type="String" mode="IN" optional="true"/>
</service>
- <service name="updatePartyToProduct" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="updatePartyToProduct" auth="true">
+ <service name="updatePartyToProduct" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="updatePartyToProduct" auth="true">
<description>Update Party To Product</description>
<attribute name="productId" type="String" mode="IN" optional="false"/>
<attribute name="partyId" type="String" mode="IN" optional="false"/>
@@ -806,8 +806,8 @@ under the License.
<attribute name="sequenceNum" type="Long" mode="IN" optional="true"/>
<attribute name="comments" type="String" mode="IN" optional="true"/>
</service>
- <service name="removePartyFromProduct" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="removePartyFromProduct" auth="true">
+ <service name="removePartyFromProduct" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="removePartyFromProduct" auth="true">
<description>Remove Party From Product</description>
<attribute name="productId" type="String" mode="IN" optional="false"/>
<attribute name="partyId" type="String" mode="IN" optional="false"/>
@@ -1240,16 +1240,16 @@ under the License.
</service>
<!-- Permission Services -->
- <service name="productGenericPermission" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="productGenericPermission">
+ <service name="productGenericPermission" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="productGenericPermission">
<implements service="permissionInterface"/>
</service>
<service name="productCategoryGenericPermission" engine="groovy"
location="component://product/groovyScripts/product/category/CategoryServices.groovy"
invoke="productCategoryGenericPermission">
<implements service="permissionInterface"/>
</service>
- <service name="productPriceGenericPermission" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="productPriceGenericPermission">
+ <service name="productPriceGenericPermission" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="productPriceGenericPermission">
<implements service="permissionInterface"/>
</service>
<service name="checkCategoryPermissionWithViewPurchaseAllow"
engine="groovy"
@@ -1285,20 +1285,20 @@ under the License.
</service>
<!-- ProductCategoryGlAccount Services -->
- <service name="createProductCategoryGlAccount"
default-entity-name="ProductCategoryGlAccount" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="createProductCategoryGlAccount" auth="true">
+ <service name="createProductCategoryGlAccount"
default-entity-name="ProductCategoryGlAccount" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="createProductCategoryGlAccount" auth="true">
<description>Create a ProductCategoryGlAccount</description>
<auto-attributes include="pk" mode="IN" optional="false"/>
<auto-attributes include="nonpk" mode="IN" optional="false"/>
</service>
- <service name="updateProductCategoryGlAccount"
default-entity-name="ProductCategoryGlAccount" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="updateProductCategoryGlAccount" auth="true">
+ <service name="updateProductCategoryGlAccount"
default-entity-name="ProductCategoryGlAccount" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="updateProductCategoryGlAccount" auth="true">
<description>Update a ProductCategoryGlAccount</description>
<auto-attributes include="pk" mode="IN" optional="false"/>
<auto-attributes include="nonpk" mode="IN" optional="false"/>
</service>
- <service name="deleteProductCategoryGlAccount"
default-entity-name="ProductCategoryGlAccount" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="deleteProductCategoryGlAccount" auth="true">
+ <service name="deleteProductCategoryGlAccount"
default-entity-name="ProductCategoryGlAccount" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="deleteProductCategoryGlAccount" auth="true">
<description>Delete a ProductCategoryGlAccount</description>
<auto-attributes include="pk" mode="IN" optional="false"/>
</service>
@@ -1608,48 +1608,48 @@ under the License.
</service>
<!-- Product GroupOrder Services -->
- <service name="createProductGroupOrder"
default-entity-name="ProductGroupOrder" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="createProductGroupOrder" auth="true">
+ <service name="createProductGroupOrder"
default-entity-name="ProductGroupOrder" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="createProductGroupOrder" auth="true">
<description>Create ProductGroupOrder</description>
<auto-attributes include="pk" mode="OUT" optional="false"/>
<auto-attributes include="nonpk" mode="IN" optional="true"/>
</service>
- <service name="updateProductGroupOrder"
default-entity-name="ProductGroupOrder" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="updateProductGroupOrder" auth="true">
+ <service name="updateProductGroupOrder"
default-entity-name="ProductGroupOrder" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="updateProductGroupOrder" auth="true">
<description>Update ProductGroupOrder</description>
<auto-attributes include="pk" mode="IN" optional="false"/>
<auto-attributes include="nonpk" mode="IN" optional="true"/>
</service>
- <service name="deleteProductGroupOrder"
default-entity-name="ProductGroupOrder" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="deleteProductGroupOrder" auth="true">
+ <service name="deleteProductGroupOrder"
default-entity-name="ProductGroupOrder" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="deleteProductGroupOrder" auth="true">
<description>Delete ProductGroupOrder</description>
<auto-attributes include="pk" mode="IN" optional="false"/>
</service>
- <service name="createJobForProductGroupOrder"
default-entity-name="ProductGroupOrder" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="createJobForProductGroupOrder" auth="true">
+ <service name="createJobForProductGroupOrder"
default-entity-name="ProductGroupOrder" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="createJobForProductGroupOrder" auth="true">
<description>Create Job For ProductGroupOrder</description>
<auto-attributes include="pk" mode="IN" optional="false"/>
<auto-attributes include="nonpk" mode="IN" optional="true"/>
</service>
- <service name="checkOrderItemForProductGroupOrder" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="checkOrderItemForProductGroupOrder" auth="true">
+ <service name="checkOrderItemForProductGroupOrder" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="checkOrderItemForProductGroupOrder" auth="true">
<description>Check OrderItem For ProductGroupOrder</description>
<attribute name="orderId" mode="IN" type="String" optional="false"/>
</service>
- <service name="cancleOrderItemGroupOrder" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="cancleOrderItemGroupOrder" auth="true">
+ <service name="cancleOrderItemGroupOrder" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="cancleOrderItemGroupOrder" auth="true">
<description>Cancle OrderItemGroupOrder</description>
<attribute name="orderId" mode="IN" type="String" optional="false"/>
<attribute name="orderItemSeqId" type="String" mode="IN"
optional="true"/>
</service>
- <service name="checkProductGroupOrderExpired" engine="simple"
-
location="component://product/minilang/product/product/ProductServices.xml"
invoke="checkProductGroupOrderExpired" auth="true">
+ <service name="checkProductGroupOrderExpired" engine="groovy"
+
location="component://product/groovyScripts/product/product/ProductServices.groovy"
invoke="checkProductGroupOrderExpired" auth="true">
<description>Check ProductGroupOrder Expired</description>
<attribute name="groupOrderId" mode="IN" type="String"
optional="false"/>
</service>