ilscipio/scipio-erp

View on GitHub
applications/product/servicedef/services.xml

Summary

Maintainability
Test Coverage
<?xml version="1.0" encoding="UTF-8"?>
<!--
This file is subject to the terms and conditions defined in the
files 'LICENSE' and 'NOTICE', which are part of this source
code package.
-->

<services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/services.xsd">
    <description>Product Component Services</description>
    <vendor>OFBiz</vendor>
    <version>1.0</version>

    <!-- ======================================== -->
    <!-- Product Services -->
    <!-- ======================================== -->
    <service name="interfaceProduct" default-entity-name="Product" engine="interface" location="" invoke="">
        <auto-attributes include="nonpk" mode="IN" optional="true">
            <exclude field-name="createdDate"/>
            <exclude field-name="createdByUserLogin"/>
            <exclude field-name="lastModifiedDate"/>
            <exclude field-name="lastModifiedByUserLogin"/>
        </auto-attributes>
        <override name="description" allow-html="any"/>
        <override name="longDescription" allow-html="any"/>
    </service>
    <service name="createProduct" default-entity-name="Product" engine="simple"
                location="component://product/script/org/ofbiz/product/product/ProductServices.xml" 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/script/org/ofbiz/product/product/ProductServices.xml" 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/script/org/ofbiz/product/product/ProductServices.xml" invoke="updateProductQuickAdminName" auth="true">
        <description>Update a Product from Quick Admin</description>
        <implements service="interfaceProduct"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>
    <!-- SCIPIO: 2018-09-10: there is no updateProductQuickAdminShipping method in ProductServices!
        It is in ProductEvents.java.
    <service name="updateProductQuickAdminShipping" default-entity-name="Product" engine="java"
                location="org.ofbiz.product.product.ProductServices" invoke="updateProductQuickAdminShipping" auth="true">
        <description>Update product characteristics from Quick Admin</description>
        <implements service="interfaceProduct"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>
    -->
    <service name="duplicateProduct" engine="simple"
                location="component://product/script/org/ofbiz/product/product/ProductServices.xml" 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"/>
        <attribute name="newInternalName" type="String" mode="IN" optional="true"/>
        <attribute name="newProductName" type="String" mode="IN" optional="true"/>
        <attribute name="newDescription" type="String" mode="IN" optional="true" allow-html="any"/>
        <attribute name="newLongDescription" type="String" mode="IN" optional="true" allow-html="any"/>
        <attribute name="duplicatePrices" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateIDs" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateContent" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateCategoryMembers" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateAssocs" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateAttributes" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateFeatureAppls" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateInventoryItems" type="String" mode="IN" optional="true"/>
        <attribute name="removePrices" type="String" mode="IN" optional="true"/>
        <attribute name="removeIDs" type="String" mode="IN" optional="true"/>
        <attribute name="removeContent" type="String" mode="IN" optional="true"/>
        <attribute name="removeCategoryMembers" type="String" mode="IN" optional="true"/>
        <attribute name="removeAssocs" type="String" mode="IN" optional="true"/>
        <attribute name="removeAttributes" type="String" mode="IN" optional="true"/>
        <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/script/org/ofbiz/product/product/ProductServices.xml" 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"/>
        <attribute name="duplicateProduct" type="String" mode="IN" optional="true"/>
        <attribute name="duplicatePrices" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateIDs" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateContent" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateCategoryMembers" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateAttributes" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateFacilities" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateLocations" type="String" mode="IN" optional="true"/>
    </service>

    <service name="quickAddVariant" engine="java"
            location="org.ofbiz.product.product.ProductServices" invoke="quickAddVariant">
        <description>Create a new product variant</description>
        <attribute name="productId" type="String" mode="IN" optional="false"/>
        <attribute name="productFeatureIds" type="String" mode="IN" optional="false"/>
        <attribute name="productVariantId" type="String" mode="INOUT" optional="false"/>
        <attribute name="sequenceNum" type="Long" mode="IN" optional="true"/>
    </service>

    <service name="createSalesAgreement" engine="group" location="createSalesAgreement" invoke="" auth="true">
        <description>Create a new sales agreement with customer for the product</description>
        <implements service="createAgreement"/>
        <implements service="createAgreementItem"/>
        <implements service="createAgreementProductAppl"/>
    </service>

    <service name="quickCreateVirtualWithVariants" engine="java"
            location="org.ofbiz.product.product.ProductServices" invoke="quickCreateVirtualWithVariants">
        <description>
            This will create a virtual product and return its ID, and associate all of the variants with it.
            It will not put the selectable features on the virtual or standard features on the variant.
        </description>
        <attribute name="productId" type="String" mode="INOUT" optional="true"/>
        <attribute name="variantProductIdsBag" type="String" mode="IN" optional="false"/>
        <attribute name="productFeatureIdOne" type="String" mode="IN" optional="true"/>
        <attribute name="productFeatureIdTwo" type="String" mode="IN" optional="true"/>
        <attribute name="productFeatureIdThree" type="String" mode="IN" optional="true"/>
    </service>

    <!-- Product Keyword Services -->
    <service name="createProductKeyword" default-entity-name="ProductKeyword" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProductKeyword</description>
        <permission-service service-name="productGenericPermission" main-action="CREATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="updateProductKeyword" default-entity-name="ProductKeyword" engine="entity-auto" invoke="update" auth="true">
        <description>Update a ProductKeyword</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductKeyword" default-entity-name="ProductKeyword" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a ProductKeyword</description>
        <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/script/org/ofbiz/product/product/ProductServices.xml" 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/script/org/ofbiz/product/product/ProductServices.xml" 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.ofbiz.entity.GenericValue" mode="IN" optional="true"/>
    </service>
    <service name="forceIndexProductKeywords" engine="simple"
            location="component://product/script/org/ofbiz/product/product/ProductServices.xml" 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/script/org/ofbiz/product/product/ProductServices.xml" 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/script/org/ofbiz/product/product/ProductServices.xml" 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/script/org/ofbiz/product/product/ProductServices.xml" 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"/>
        <override name="productStoreId" optional="false"/>
        <override name="productId" optional="false"/>
        <override name="productRating" optional="false"/>
    </service>
    <service name="updateProductReview" engine="simple" default-entity-name="ProductReview"
            location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="updateProductReview" auth="true">
        <description>Updates a product review record</description>
        <required-permissions join-type="OR">
            <check-permission permission="CATALOG_UPDATE"/>
            <check-permission permission="CATALOG_ADMIN"/>
        </required-permissions>
        <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/script/org/ofbiz/product/product/ProductServices.xml" invoke="setProductReviewStatus" auth="true">
        <description>Updates a product review record</description>
        <required-permissions join-type="OR">
            <check-permission permission="CATALOG_UPDATE"/>
            <check-permission permission="CATALOG_ADMIN"/>
        </required-permissions>
        <attribute name="productReviewId" type="String" mode="INOUT" optional="false"/>
        <attribute name="statusId" type="String" mode="IN" optional="false"/>
    </service>

    <service name="findProductById" engine="java"  auth="true" export="true"
        location="org.ofbiz.product.product.ProductServices" invoke="findProductById">
        <description>Finds productId(s) corresponding to a product reference, productId or a GoodIdentification idValue</description>
        <attribute type="String" mode="IN" name="idToFind" optional="false"/>
        <attribute type="String" mode="IN" name="goodIdentificationTypeId" optional="true"/>
        <attribute type="String" mode="IN" name="searchProductFirst" optional="true"/>
        <attribute type="String" mode="IN" name="searchAllId" optional="true"/>
        <attribute type="org.ofbiz.entity.GenericValue" mode="OUT" name="product" optional="true"/>
        <attribute type="List" mode="OUT" name="productsList" optional="true"/>
    </service>

    <!-- Product Association Services -->

    <service name="createProductAssoc" default-entity-name="ProductAssoc" engine="entity-auto" invoke="create" auth="true" hideResultInLog="true" log="quiet">
        <permission-service service-name="productGenericPermission" main-action="CREATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="updateProductAssoc" default-entity-name="ProductAssoc" engine="entity-auto" invoke="update" auth="true" log="quiet" hideResultInLog="true">
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductAssoc" default-entity-name="ProductAssoc" engine="entity-auto" invoke="delete" auth="true">
        <permission-service service-name="productGenericPermission" main-action="DELETE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- Product Price Services -->
    <service name="createProductPrice" default-entity-name="ProductPrice" engine="simple"
                location="component://product/script/org/ofbiz/product/price/PriceServices.xml" invoke="createProductPrice" auth="true">
        <description>
            Create a Product Price. 
            
            If taxAuthGeoId and taxAuthPartyId are (or taxAuthCombinedId is (SCIPIO)) passed in then the price will be considered a price
            with tax included (the priceWithoutTax, priceWithTax, taxAmount, and taxPercentage fields will also be populated).
            
            If the taxInPrice field is 'Y' then the price field will be left with the tax included (price will be equal to priceWithTax),            
            otherwise tax will be removed from the passed in price and the price field will be equal to the priceWithoutTax field.
            
            If taxAuthGeoId or taxAuthPartyId empty, and taxAuthCombinedId is empty (SCIPIO), then the taxInPrice field will be ignored.
        </description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true">
            <exclude field-name="priceWithoutTax"/>
            <exclude field-name="priceWithTax"/>
            <exclude field-name="taxAmount"/>
            <exclude field-name="createdDate"/>
            <exclude field-name="createdByUserLogin"/>
            <exclude field-name="lastModifiedDate"/>
            <exclude field-name="lastModifiedByUserLogin"/>
        </auto-attributes>
        <attribute name="taxAuthCombinedId" type="String" mode="IN" optional="true"><!-- if passed in value will be split based on: "${taxAuthGeoId}::${taxAuthPartyId}" --></attribute>
        <override name="fromDate" mode="INOUT" optional="true"/>
        <override name="price" optional="false"/>
    </service>
    <service name="updateProductPrice" default-entity-name="ProductPrice" engine="simple"
                location="component://product/script/org/ofbiz/product/price/PriceServices.xml" invoke="updateProductPrice" auth="true">
        <description>Update an ProductPrice</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true">
            <exclude field-name="priceWithoutTax"/>
            <exclude field-name="priceWithTax"/>
            <exclude field-name="taxAmount"/>
            <exclude field-name="createdDate"/>
            <exclude field-name="createdByUserLogin"/>
            <exclude field-name="lastModifiedDate"/>
            <exclude field-name="lastModifiedByUserLogin"/>
        </auto-attributes>
        <attribute name="oldPrice" type="BigDecimal" mode="OUT" optional="false"/>
        <override name="price" optional="false"/>
    </service>
    <service name="deleteProductPrice" default-entity-name="ProductPrice" engine="simple"
                location="component://product/script/org/ofbiz/product/price/PriceServices.xml" invoke="deleteProductPrice" auth="true">
        <description>Delete an ProductPrice</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <attribute name="oldPrice" type="BigDecimal" mode="OUT" optional="false"/>
    </service>

    <!-- called by ECAs on ProductPrice service call events -->
    <service name="saveProductPriceChange" default-entity-name="ProductPrice" engine="simple"
            location="component://product/script/org/ofbiz/product/price/PriceServices.xml" invoke="saveProductPriceChange" auth="true">
        <description>Save History of a ProductPrice Change</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <attribute name="oldPrice" type="BigDecimal" mode="IN" optional="true"/>
        <attribute name="productPriceChangeId" type="String" mode="OUT" optional="true"/>
    </service>

    <!-- Product PaymentMethodType Services -->
    <service name="createProductPaymentMethodType" default-entity-name="ProductPaymentMethodType" engine="simple"
            location="component://product/script/org/ofbiz/product/price/PriceServices.xml" invoke="createProductPaymentMethodType" auth="true">
        <description>Create an ProductPaymentMethodType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <override name="fromDate" optional="true"/>
    </service>
    <service name="updateProductPaymentMethodType" default-entity-name="ProductPaymentMethodType" engine="simple"
            location="component://product/script/org/ofbiz/product/price/PriceServices.xml" invoke="updateProductPaymentMethodType" auth="true">
        <description>Update an ProductPaymentMethodType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductPaymentMethodType" default-entity-name="ProductPaymentMethodType" engine="simple"
            location="component://product/script/org/ofbiz/product/price/PriceServices.xml" invoke="deleteProductPaymentMethodType" auth="true">
        <description>Delete an ProductPaymentMethodType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- GoodIdentification Services -->
    <service name="createGoodIdentification" default-entity-name="GoodIdentification" engine="entity-auto" invoke="create" auth="true">
        <description>Create a GoodIdentification</description>
        <permission-service service-name="productGenericPermission" main-action="CREATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="false"/>
    </service>
    <service name="updateGoodIdentification" default-entity-name="GoodIdentification" engine="entity-auto" invoke="update" auth="true">
        <description>Update a GoodIdentification</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="false"/>
    </service>
    <service name="deleteGoodIdentification" default-entity-name="GoodIdentification" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a GoodIdentification</description>
        <permission-service service-name="productGenericPermission" main-action="DELETE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- ProductGlAccount Services -->
    <service name="createProductGlAccount" default-entity-name="ProductGlAccount" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProductGlAccount</description>
        <permission-service service-name="productGenericPermission" main-action="CREATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="false"/>
    </service>
    <service name="updateProductGlAccount" default-entity-name="ProductGlAccount" engine="entity-auto" invoke="update" auth="true">
        <description>Update a ProductGlAccount</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="false"/>
    </service>
    <service name="deleteProductGlAccount" default-entity-name="ProductGlAccount" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a ProductGlAccount</description>
        <permission-service service-name="productGenericPermission" main-action="DELETE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- Product content services -->
    <service name="createProductContent" default-entity-name="ProductContent" engine="simple"
        location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="createProductContent" auth="true">
        <description>Add Content To Product</description>
        <auto-attributes include="pk" mode="INOUT" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes entity-name="Content" include="nonpk" mode="IN" optional="true"/>
        <override name="fromDate" optional="true"/>
        <!--<override name="contentId" optional="true" mode="INOUT"/>-->
    </service>
    <service name="updateProductContent" default-entity-name="ProductContent" engine="simple"
        location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="updateProductContent" auth="true">
        <description>Update Content To Product</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes entity-name="Content" include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="removeProductContent" default-entity-name="ProductContent" engine="simple"
        location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="removeProductContent" auth="true">
        <description>Remove Content From Product</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="createEmailContentForProduct" default-entity-name="ProductContent" engine="simple"
        location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="createEmailContentForProduct" auth="true">
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes mode="IN" entity-name="Content" optional="true"/>
        <attribute name="subject" type="String" mode="IN" optional="false"/>
        <attribute name="plainBody" type="String" mode="IN" optional="false"/>
        <attribute name="htmlBody" type="String" mode="IN" optional="true" allow-html="any"/>
        <override name="contentId" optional="true" mode="INOUT"/>
    </service>
    <service name="updateEmailContentForProduct" default-entity-name="ProductContent" engine="simple"
        location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="updateEmailContentForProduct" auth="true">
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes entity-name="Content" include="nonpk" mode="IN" optional="true"/>
        <attribute name="subjectDataResourceId" type="String" mode="IN" optional="true"/>
        <attribute name="subject" type="String" mode="IN" optional="true"/>
        <attribute name="plainBodyDataResourceId" type="String" mode="IN" optional="true"/>
        <attribute name="plainBody" type="String" mode="IN" optional="true"/>
        <attribute name="htmlBodyDataResourceId" type="String" mode="IN" optional="true"/>
        <attribute name="htmlBody" type="String" mode="IN" optional="true" allow-html="any"/>
    </service>
    <service name="createDownloadContentForProduct" default-entity-name="ProductContent" engine="simple"
        location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="createDownloadContentForProduct" auth="true">
        <auto-attributes include="pk" mode="IN" optional="true"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes include="nonpk" mode="IN" entity-name="Content" optional="true"/>
        <attribute mode="IN" name="imageData" optional="true" type="java.nio.ByteBuffer"/>
        <attribute mode="IN" name="_imageData_contentType" optional="true" type="String"/>
        <attribute mode="IN" name="_imageData_fileName" optional="true" type="String"/>
        <override name="productContentTypeId" optional="false"/>
    </service>
    <service name="updateDownloadContentForProduct" default-entity-name="ProductContent" engine="simple"
        location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="updateDownloadContentForProduct" auth="true">
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes mode="IN" entity-name="Content" optional="true"/>
        <attribute name="fileDataResourceId" type="String" mode="IN" optional="true"/>
        <attribute name="file" type="String" mode="IN" optional="true"/>
    </service>

    <service name="createSimpleTextContentForProduct" default-entity-name="ProductContent" engine="simple"
        location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="createSimpleTextContentForProduct" auth="true">
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes entity-name="Content" include="nonpk" mode="IN" optional="true"/>
        <attribute name="text" type="String" mode="IN" optional="false" allow-html="any"/>
        <override name="contentId" optional="true"/>
        <override name="fromDate" optional="true"/>
    </service>
    <service name="updateSimpleTextContentForProduct" default-entity-name="ProductContent" engine="simple"
        location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="updateSimpleTextContentForProduct" auth="true">
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes mode="IN" entity-name="Content" optional="true"/>
        <attribute name="textDataResourceId" type="String" mode="IN" optional="true"/>
        <attribute name="text" type="String" mode="IN" optional="true" allow-html="any"/>
    </service>

    <!-- SCIPIO: 2017-12-06: MOVED to component://content/servicedef/services.xml (did not belong here even remotely)
    <service name="createSimpleTextContentForAlternateLocale" engine="simple" location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="createSimpleTextContentForAlternateLocale">
        <auto-attributes mode="IN" entity-name="Content" optional="true"/>
        <attribute name="mainContentId" type="String" mode="IN" optional="false"/>
        <attribute name="text" type="String" mode="IN" optional="false" allow-html="any"/>
        <override name="localeString" optional="false"/>
        <override name="contentId" mode="INOUT"/>
    </service>
    -->

    <service name="addAdditionalViewForProduct" default-entity-name="ProductContent" engine="java"
        location="org.ofbiz.product.product.ProductServices" invoke="addAdditionalViewForProduct" auth="true">
        <implements service="uploadFileInterface"/>
        <auto-attributes include="pk" mode="IN" optional="true"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <attribute mode="IN" name="contentId" optional="true" type="String"/>
        <attribute mode="IN" name="imageProfile" optional="true" type="String"/><!-- SCIPIO -->
        <override name="productContentTypeId" optional="false"/>
        <override name="productId" optional="false"/>
    </service>

    <service name="uploadProductAdditionalViewImages" engine="simple"
        location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="uploadProductAdditionalViewImages" auth="true">
        <description>Upload Additional View Images For Product</description>
        <permission-service service-name="genericContentPermission" main-action="UPDATE"/>
        <attribute name="productId" type="String" mode="INOUT" optional="false"/>
        <attribute name="additionalImageOne" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageOne_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageOne_contentType" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageTwo" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageTwo_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageTwo_contentType" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageThree" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageThree_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageThree_contentType" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageFour" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageFour_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageFour_contentType" type="String" mode="IN" optional="true"/>
        <!-- SCIPIO -->
        <attribute name="additionalImageOne_imageProfile" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageTwo_imageProfile" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageThree_imageProfile" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageFour_imageProfile" type="String" mode="IN" optional="true"/>
    </service>

    <service name="updateContentSEOForProduct" engine="simple"
            location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="updateContentSEOForProduct" auth="true">
        <description>Update Product SEO</description>
        <attribute name="productId" mode="IN" type="String" optional="false"/>
        <attribute name="title" mode="IN" type="String" optional="true"/>
        <attribute name="metaKeyword" mode="IN" type="String" optional="true"/>
        <attribute name="metaDescription" mode="IN" type="String" optional="true"/>
    </service>

    <!-- SupplierProduct Services -->
    <service name="createSupplierProduct" default-entity-name="SupplierProduct" engine="simple"
        location="component://product/script/org/ofbiz/product/supplier/SupplierProductServices.xml" invoke="createSupplierProduct" auth="true">
        <description>Create a new SupplierProduct record</description>
        <required-permissions join-type="AND">
            <check-permission permission="CATALOG" action="_CREATE"/>
        </required-permissions>
        <auto-attributes mode="IN" include="pk" optional="false"/>
        <auto-attributes mode="IN" include="nonpk" optional="true"/>
        <override name="supplierProductId" optional="false"/>
        <override name="lastPrice" optional="false"/>
    </service>
    <service name="updateSupplierProduct" default-entity-name="SupplierProduct" engine="simple"
        location="component://product/script/org/ofbiz/product/supplier/SupplierProductServices.xml" invoke="updateSupplierProduct" auth="true">
        <description>Update a SupplierProduct record</description>
        <required-permissions join-type="AND">
            <check-permission permission="CATALOG" action="_UPDATE"/>
        </required-permissions>
        <auto-attributes mode="IN" include="pk" optional="false"/>
        <auto-attributes mode="IN" include="nonpk" optional="true"/>
    </service>
    <service name="removeSupplierProduct" default-entity-name="SupplierProduct" engine="simple"
        location="component://product/script/org/ofbiz/product/supplier/SupplierProductServices.xml" invoke="removeSupplierProduct" auth="true">
        <description>Remove a SupplierProduct record</description>
        <required-permissions join-type="AND">
            <check-permission permission="CATALOG" action="_DELETE"/>
        </required-permissions>
        <auto-attributes mode="IN" include="pk" optional="false"/>
    </service>

    <!-- supplier product feature services -->
    <service name="createSupplierProductFeature" default-entity-name="SupplierProductFeature" engine="simple"
        location="component://product/script/org/ofbiz/product/supplier/SupplierProductServices.xml" invoke="createSupplierProductFeature" auth="true">
        <description>Create a new SupplierProductFeature record</description>
        <required-permissions join-type="AND">
            <check-permission permission="CATALOG" action="_CREATE"/>
        </required-permissions>
        <auto-attributes mode="IN" include="pk" optional="false"/>
        <auto-attributes mode="IN" include="nonpk" optional="true"/>
    </service>
    <service name="updateSupplierProductFeature" default-entity-name="SupplierProductFeature" engine="simple"
        location="component://product/script/org/ofbiz/product/supplier/SupplierProductServices.xml" invoke="updateSupplierProductFeature" auth="true">
        <description>Update a SupplierProduct record</description>
        <required-permissions join-type="AND">
            <check-permission permission="CATALOG" action="_UPDATE"/>
        </required-permissions>
        <auto-attributes mode="IN" include="pk" optional="false"/>
        <auto-attributes mode="IN" include="nonpk" optional="true"/>
    </service>
    <service name="removeSupplierProductFeature" default-entity-name="SupplierProductFeature" engine="simple"
        location="component://product/script/org/ofbiz/product/supplier/SupplierProductServices.xml" invoke="removeSupplierProductFeature" auth="true">
        <description>Remove a SupplierProduct record</description>
        <required-permissions join-type="AND">
            <check-permission permission="CATALOG" action="_DELETE"/>
        </required-permissions>
        <auto-attributes mode="IN" include="pk" optional="false"/>
    </service>
    <service name="getSupplierProductFeatures" engine="simple"
        location="component://product/script/org/ofbiz/product/supplier/SupplierProductServices.xml" invoke="getSupplierProductFeatures">
        <description>Finds a list of SupplierProductFeature entities based on the productFeatureId.
            If a partyId is given, only product feature information for that supplier party is returned.</description>
        <attribute name="productFeatureId" type="String" mode="IN" optional="false"/>
        <attribute name="partyId" type="String" mode="IN" optional="true"/>
        <attribute name="supplierProductFeatures" type="java.util.List" mode="OUT" optional="false"/>
    </service>

    <service name="createProductMaint" default-entity-name="ProductMaint" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProductMaint</description>
        <permission-service service-name="productGenericPermission" main-action="CREATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <override name="productMaintSeqId" mode="OUT"/> <!-- make this OUT rather than IN, we will automatically generate the next sub-sequence ID -->
    </service>
    <service name="updateProductMaint" default-entity-name="ProductMaint" engine="entity-auto" invoke="update" auth="true">
        <description>Update a ProductMaint</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductMaint" default-entity-name="ProductMaint" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a ProductMaint</description>
        <permission-service service-name="productGenericPermission" main-action="DELETE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>
    <service name="createProductMeter" default-entity-name="ProductMeter" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProductMeter</description>
        <permission-service service-name="productGenericPermission" main-action="CREATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="updateProductMeter" default-entity-name="ProductMeter" engine="entity-auto" invoke="update" auth="true">
        <description>Update a ProductMeter</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductMeter" default-entity-name="ProductMeter" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a ProductMeter</description>
        <permission-service service-name="productGenericPermission" main-action="DELETE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>
    <service name="createProductGeo" default-entity-name="ProductGeo" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProductGeo</description>
        <permission-service service-name="productGenericPermission" main-action="CREATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="updateProductGeo" default-entity-name="ProductGeo" engine="entity-auto" invoke="update" auth="true">
        <description>Update a ProductGeo</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductGeo" default-entity-name="ProductGeo" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a ProductGeo</description>
        <permission-service service-name="productGenericPermission" main-action="DELETE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>
    <service name="createCommunicationEventProduct" engine="simple"
        location="component://product/script/org/ofbiz/product/communication/CommunicationEventServices.xml" invoke="createCommunicationEventProduct" auth="true">
        <description>Create a Communication Event Product</description>
        <auto-attributes entity-name="CommunicationEventProduct" include="pk" mode="IN" optional="false"/>
    </service>
    <service name="removeCommunicationEventProduct" engine="simple"
        location="component://product/script/org/ofbiz/product/communication/CommunicationEventServices.xml" invoke="removeCommunicationEventProduct" auth="true">
        <description>Remove a Communication Event Product</description>
        <auto-attributes entity-name="CommunicationEventProduct" include="pk" mode="IN" optional="false"/>
    </service>

    <!-- ======================================== -->
    <!-- Product Catalog Services -->
    <!-- ======================================== -->
    <service name="createProdCatalog" default-entity-name="ProdCatalog" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProdCatalog</description>
        <permission-service service-name="catalogPermissionCheck" main-action="CREATE"/>
        <auto-attributes include="pk" mode="INOUT" optional="true"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <override name="catalogName" optional="false"/>
    </service>
    <service name="updateProdCatalog" default-entity-name="ProdCatalog" engine="entity-auto" invoke="update" auth="true">
        <description>Update an ProdCatalog</description>
        <permission-service service-name="catalogPermissionCheck" main-action="UPDATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <override name="catalogName" optional="false"/>
    </service>
    <service name="deleteProdCatalog" default-entity-name="ProdCatalog" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete an ProdCatalog</description>
        <permission-service service-name="catalogPermissionCheck" main-action="DELETE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <service name="addProductCategoryToProdCatalog" default-entity-name="ProdCatalogCategory" engine="entity-auto" invoke="create" auth="true">
        <description>Add ProductCategory To ProdCatalog</description>
        <permission-service service-name="catalogPermissionCheck" main-action="CREATE"/>
        <!-- SCIPIO: 2017-10-18: changed pk from IN to INOUT, required because entity-auto engine automatically fill in for empty fromDate, in which case must read output to get PK -->
        <auto-attributes include="pk" mode="INOUT" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <override name="fromDate" optional="true"/>
    </service>
    <service name="updateProductCategoryToProdCatalog" default-entity-name="ProdCatalogCategory" engine="entity-auto" invoke="update" auth="true">
        <description>Add ProductCategory To ProdCatalog</description>
        <permission-service service-name="catalogPermissionCheck" main-action="UPDATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <override name="prodCatalogCategoryTypeId" optional="false"/>
    </service>
    <service name="removeProductCategoryFromProdCatalog" default-entity-name="ProdCatalogCategory" engine="entity-auto" invoke="delete" auth="true">
        <description>Remove ProductCategory From ProdCatalog</description>
        <permission-service service-name="catalogPermissionCheck" main-action="DELETE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <service name="addProdCatalogToParty" default-entity-name="ProdCatalogRole" engine="entity-auto" invoke="create" auth="true">
        <description>Add ProdCatalog To Party</description>
        <permission-service service-name="prodCatalogToPartyPermissionCheck" main-action="CREATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <override name="fromDate" optional="true"/>
    </service>
    <service name="updateProdCatalogToParty" default-entity-name="ProdCatalogRole" engine="entity-auto" invoke="update" auth="true">
        <description>Add ProdCatalog To Party</description>
        <permission-service service-name="prodCatalogToPartyPermissionCheck" main-action="UPDATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="removeProdCatalogFromParty" default-entity-name="ProdCatalogRole" engine="entity-auto" invoke="delete" auth="true">
        <description>Remove ProdCatalog From Party</description>
        <permission-service service-name="prodCatalogToPartyPermissionCheck" main-action="DELETE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- ======================================== -->
    <!-- Product Category Services -->
    <!-- ======================================== -->
    <service name="createProductCategory" default-entity-name="ProductCategory" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="createProductCategory" auth="true">
        <description>Create an ProductCategory</description>
        <auto-attributes include="pk" mode="INOUT" optional="true"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <override name="productCategoryTypeId" optional="false"/>
    </service>
    <service name="updateProductCategory" default-entity-name="ProductCategory" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="updateProductCategory" auth="true">
        <description>Update an ProductCategory</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <override name="productCategoryTypeId" optional="false"/>
    </service>
    <!-- SCIPIO: new (2017-10-20)
        NOTE: category deletion appears frowned upon in stock ofbiz, or perhaps they
        are meant to be expired. However, when building a site, it is common to redesign categories,
        so deletion is sometimes appropriate (and in that case, expiring is not appropriate). -->
    <service name="deleteProductCategory" default-entity-name="ProductCategory" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="deleteProductCategory" auth="true">
        <description>SCIPIO: Delete a ProductCategory record (if no associations or members)</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <service name="duplicateProductCategory" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="duplicateProductCategory" auth="true">
        <description>Duplicate a Product Category using from oldProductCategoryId to a new productCategoryId</description>
        <attribute name="productCategoryId" type="String" mode="IN" optional="false"/>
        <attribute name="oldProductCategoryId" type="String" mode="IN" optional="false"/>
        <attribute name="duplicateContent" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateParentRollup" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateChildRollup" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateMembers" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateCatalogs" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateFeatures" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateAttributes" type="String" mode="IN" optional="true"/>
        <attribute name="duplicateRoles" type="String" mode="IN" optional="true"/>
    </service>

    <service name="safeAddProductToCategory" default-entity-name="ProductCategoryMember" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="addProductToCategory" auth="true">
        <description>Add Product To Category</description>
        <permission-service service-name="checkCategoryPermissionWithViewPurchaseAllow" main-action="CREATE"/>
        <!-- SCIPIO: 2017-10-25: changed PK from IN to INOUT -->
        <auto-attributes include="pk" mode="INOUT" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>

    <service name="addProductToCategories" default-entity-name="ProductCategoryMember" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="addProductToCategories" auth="true">
        <description>Add Product To Multiple Categories</description>
        <permission-service service-name="checkCategoryPermissionWithViewPurchaseAllow" main-action="CREATE"/>
        <auto-attributes include="pk" mode="IN" optional="false">
            <exclude field-name="productCategoryId"/>
        </auto-attributes>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <attribute name="categories" type="Object" mode="IN" optional="false"/>
        <!-- SCIPIO: 2017-10-25: fromDate from IN to INOUT so caller can retrieve correct PK -->
        <override name="fromDate" optional="true" mode="INOUT"/>
    </service>
    <service name="addProductToCategory" default-entity-name="ProductCategoryMember" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="addProductToCategory" auth="true">
        <description>Add Product To Category</description>
        <permission-service service-name="checkCategoryPermissionWithViewPurchaseAllow" main-action="CREATE"/>
        <!-- SCIPIO: 2017-10-25: changed PK from IN to INOUT so caller can retrieve full PK when fromDate empty -->
        <auto-attributes include="pk" mode="INOUT" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <override name="fromDate" optional="true"/>
    </service>
    <service name="updateProductToCategory" default-entity-name="ProductCategoryMember" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="updateProductToCategory" auth="true">
        <description>Update a ProductCategoryMember</description>
        <permission-service service-name="checkCategoryPermissionWithViewPurchaseAllow" main-action="UPDATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="removeProductFromCategory" default-entity-name="ProductCategoryMember" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="removeProductFromCategory" auth="true">
        <description>Remove Product From Category</description>
        <permission-service service-name="checkCategoryPermissionWithViewPurchaseAllow" main-action="DELETE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>
    <service name="createProductInCategory" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="createProductInCategory" auth="true">
        <description></description>
        <auto-attributes entity-name="ProductCategory" include="pk" mode="IN" optional="false"/>
        <auto-attributes entity-name="Product" include="pk" mode="INOUT" optional="true"/>
        <auto-attributes entity-name="Product" include="nonpk" mode="IN" optional="true"/>
        <attribute name="productFeatureIdByType" type="java.util.Map" mode="IN" optional="false" string-map-prefix="pft_"/>
        <attribute name="productFeatureSelectableByType" type="java.util.Map" mode="IN" optional="false" string-map-prefix="pftsel_"/>
        <attribute name="defaultPrice" type="BigDecimal" mode="IN" optional="true"/>
        <attribute name="averageCost" type="BigDecimal" mode="IN" optional="true"/>
        <attribute name="currencyUomId" type="String" mode="IN" optional="true"/>
    </service>

    <!-- SCIPIO: Commented out since image scale for category images feature has been implemented -->
<!--    <service name="uploadProductCategoryImage" engine="groovy"-->
<!--                location="component://product/script/com/ilscipio/category/ProductCategoryContentServices.groovy" default-entity-name="ProductCategory" invoke="uploadProductCategoryImage" auth="true">-->
<!--        <implements service="uploadFileInterface"/>                -->
<!--        <auto-attributes entity-name="ProductCategory" include="pk" mode="IN" optional="false"/>-->
<!--        <attribute name="upload_file_type" mode="IN" type="String" optional="false" />-->
<!--    </service>-->

    <service name="addPartyToCategory" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="addPartyToCategory" auth="true">
        <description>Add Party To Category</description>
        <attribute name="productCategoryId" type="String" mode="IN" optional="false"/>
        <attribute name="partyId" type="String" mode="IN" optional="false"/>
        <attribute name="roleTypeId" type="String" mode="IN" optional="false"/>
        <attribute name="fromDate" type="Timestamp" mode="IN" optional="true"/>
        <attribute name="thruDate" type="Timestamp" mode="IN" optional="true"/>
        <attribute name="comments" type="String" mode="IN" optional="true"/>
    </service>
    <service name="updatePartyToCategory" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="updatePartyToCategory" auth="true">
        <description>Update Party To Category</description>
        <attribute name="productCategoryId" type="String" mode="IN" optional="false"/>
        <attribute name="partyId" type="String" mode="IN" optional="false"/>
        <attribute name="roleTypeId" type="String" mode="IN" optional="false"/>
        <attribute name="fromDate" type="Timestamp" mode="IN" optional="false"/>
        <attribute name="thruDate" type="Timestamp" mode="IN" optional="true"/>
        <attribute name="comments" type="String" mode="IN" optional="true"/>
    </service>
    <service name="removePartyFromCategory" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="removePartyFromCategory" auth="true">
        <description>Remove Party From Category</description>
        <attribute name="productCategoryId" type="String" mode="IN" optional="false"/>
        <attribute name="partyId" type="String" mode="IN" optional="false"/>
        <attribute name="roleTypeId" type="String" mode="IN" optional="false"/>
        <attribute name="fromDate" type="Timestamp" mode="IN" optional="false"/>
    </service>

    <service name="addPartyToProduct" engine="simple"
                location="component://product/script/org/ofbiz/product/product/ProductServices.xml" 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"/>
        <attribute name="roleTypeId" type="String" mode="IN" optional="false"/>
        <attribute name="fromDate" type="Timestamp" mode="IN" optional="true"/>
        <attribute name="thruDate" type="Timestamp" mode="IN" optional="true"/>
        <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/script/org/ofbiz/product/product/ProductServices.xml" 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"/>
        <attribute name="roleTypeId" type="String" mode="IN" optional="false"/>
        <attribute name="fromDate" type="Timestamp" mode="IN" optional="false"/>
        <attribute name="thruDate" type="Timestamp" mode="IN" optional="true"/>
        <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/script/org/ofbiz/product/product/ProductServices.xml" 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"/>
        <attribute name="roleTypeId" type="String" mode="IN" optional="false"/>
        <attribute name="fromDate" type="Timestamp" mode="IN" optional="false"/>
    </service>

    <service name="safeAddProductCategoryToCategory" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="addProductCategoryToCategory" auth="true">
        <description>Safe Add ProductCategory To Category (requires fromDate)</description>
        <!-- SCIPIO: 2017-10-18: changed PK fields to INOUT -->
        <attribute name="productCategoryId" type="String" mode="INOUT" optional="false"/>
        <attribute name="parentProductCategoryId" type="String" mode="INOUT" optional="false"/>
        <attribute name="fromDate" type="Timestamp" mode="INOUT" optional="false"/>
        <attribute name="thruDate" type="Timestamp" mode="IN" optional="true"/>
        <attribute name="sequenceNum" type="Long" mode="IN" optional="true"/>
    </service>

    <service name="addProductCategoryToCategory" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="addProductCategoryToCategory" auth="true">
        <description>Add ProductCategory To Category</description>
        <!-- SCIPIO: 2017-10-18: changed PK fields to INOUT, otherwise can't get PK back due to optional fromDate -->
        <attribute name="productCategoryId" type="String" mode="INOUT" optional="false"/>
        <attribute name="parentProductCategoryId" type="String" mode="INOUT" optional="false"/>
        <attribute name="fromDate" type="Timestamp" mode="INOUT" optional="true"/>
        <attribute name="thruDate" type="Timestamp" mode="IN" optional="true"/>
        <attribute name="sequenceNum" type="Long" mode="IN" optional="true"/>
    </service>
    <service name="addProductCategoryToCategories" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="addProductCategoryToCategories" auth="true">
        <description>Add ProductCategory To Categories</description>
        <attribute name="productCategoryId" type="String" mode="IN" optional="false"/>
        <attribute name="categories" type="Object" mode="IN" optional="false"/>
        <!-- SCIPIO: 2017-10-18: changed fromDate to INOUT, otherwise can't get exact PK back out -->
        <attribute name="fromDate" type="Timestamp" mode="INOUT" optional="true"/>
        <attribute name="thruDate" type="Timestamp" mode="IN" optional="true"/>
        <attribute name="sequenceNum" type="Long" mode="IN" optional="true"/>
    </service>
    <service name="updateProductCategoryToCategory" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="updateProductCategoryToCategory" auth="true">
        <description>Update ProductCategory To Category</description>
        <attribute name="productCategoryId" type="String" mode="INOUT" optional="false"/>        
        <attribute name="parentProductCategoryId" type="String" mode="IN" optional="false"/>
        <attribute name="fromDate" type="Timestamp" mode="IN" optional="false"/>
        <attribute name="thruDate" type="Timestamp" mode="IN" optional="true"/>
        <attribute name="sequenceNum" type="Long" mode="IN" optional="true"/>
        <attribute name="originalProductCategoryId" type="String" mode="IN" optional="true"/>
    </service>
    <service name="removeProductCategoryFromCategory" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="removeProductCategoryFromCategory" auth="true">
        <description>Remove ProductCategory From Category</description>
        <attribute name="productCategoryId" type="String" mode="INOUT" optional="false"/>
        <attribute name="parentProductCategoryId" type="String" mode="IN" optional="false"/>
        <attribute name="fromDate" type="Timestamp" mode="IN" optional="false"/>
        <attribute name="originalProductCategoryId" type="String" mode="IN" optional="true"/>
    </service>

    <!-- Product Category Attribute Services -->
    <service name="createProductCategoryAttribute" default-entity-name="ProductCategoryAttribute" engine="simple"
            location="component://product/script/org/ofbiz/product/category/CategoryServices.xml"
            invoke="createProductCategoryAttribute" auth="true">
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="updateProductCategoryAttribute" default-entity-name="ProductCategoryAttribute" engine="simple"
            location="component://product/script/org/ofbiz/product/category/CategoryServices.xml"
            invoke="updateProductCategoryAttribute" auth="true">
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductCategoryAttribute" default-entity-name="ProductCategoryAttribute" engine="simple"
            location="component://product/script/org/ofbiz/product/category/CategoryServices.xml"
            invoke="deleteProductCategoryAttribute" auth="true">
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- Product Category Link Services -->
    <service name="createProductCategoryLink" default-entity-name="ProductCategoryLink" engine="simple"
            location="component://product/script/org/ofbiz/product/category/CategoryServices.xml"
            invoke="createProductCategoryLink" auth="true">
        <description>Create a ProductCategoryLink</description>
        <permission-service service-name="productCategoryGenericPermission" main-action="CREATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <override name="fromDate" optional="true"/>
        <override name="linkSeqId" optional="true"/>
    </service>
    <service name="updateProductCategoryLink" default-entity-name="ProductCategoryLink" engine="simple"
            location="component://product/script/org/ofbiz/product/category/CategoryServices.xml"
            invoke="updateProductCategoryLink" auth="true">
        <description>Update a ProductCategoryLink</description>
        <permission-service service-name="productCategoryGenericPermission" main-action="UPDATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductCategoryLink" default-entity-name="ProductCategoryLink" engine="simple"
            location="component://product/script/org/ofbiz/product/category/CategoryServices.xml"
            invoke="deleteProductCategoryLink" auth="true">
        <description>Delete a ProductCategoryLink</description>
        <permission-service service-name="productCategoryGenericPermission" main-action="DELETE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <service name="duplicateCategoryEntities" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="duplicateCategoryEntities" auth="true">
        <description>Duplicates a named entity from one productCategoryId to another</description>
        <attribute name="productCategoryId" type="String" mode="IN" optional="false"/>
        <attribute name="productCategoryIdTo" type="String" mode="IN" optional="false"/>
        <attribute name="entityName" type="String" mode="IN" optional="false"/>
        <attribute name="validDate" type="Timestamp" mode="IN" optional="true"/>
    </service>


    <!-- Category content services -->
    <service name="createCategoryContent" default-entity-name="ProductCategoryContent" engine="simple"
            location="component://product/script/org/ofbiz/product/category/CategoryContentServices.xml" invoke="createCategoryContent" auth="true">
        <description>Add Content To Category</description>
        <auto-attributes include="pk" mode="INOUT" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes entity-name="Content" include="nonpk" mode="IN" optional="true"/>
        <override name="fromDate" optional="true"/>
        <override name="contentId" optional="true" mode="INOUT"/>
    </service>
    <service name="updateCategoryContent" default-entity-name="ProductCategoryContent" engine="simple"
            location="component://product/script/org/ofbiz/product/category/CategoryContentServices.xml" invoke="updateCategoryContent" auth="true">
        <description>Update Content To Category</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes entity-name="Content" include="nonpk" mode="IN" optional="true"/>
        <override name="contentId" optional="true" mode="INOUT"/><!-- SCIPIO: TODO: REVIEW: this was added for Scipio, but optional="true" makes no sense for an update service -->
    </service>
    <service name="removeCategoryContent" default-entity-name="ProductCategoryContent" engine="simple"
            location="component://product/script/org/ofbiz/product/category/CategoryContentServices.xml" invoke="removeCategoryContent" auth="true">
        <description>Remove Content From Category</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- SCIPIO: new service to add category additional images, based on addAdditionalViewForProduct -->
    <service name="addAdditionalViewForCategory" default-entity-name="ProductCategoryContent" engine="java"
             location="org.ofbiz.product.product.ProductServices" invoke="addAdditionalViewForCategory" auth="true">
        <implements service="uploadFileInterface"/>
        <auto-attributes include="pk" mode="IN" optional="true"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <attribute mode="IN" name="contentId" optional="true" type="String"/>
        <attribute mode="IN" name="imageProfile" optional="true" type="String"/><!-- SCIPIO -->
        <override name="prodCatContentTypeId" optional="false"/>
        <override name="productCategoryId" optional="false"/>
    </service>

    <!-- SCIPIO: new service to upload category additional images, based on uploadProductAdditionalViewImages -->
    <service name="uploadCategoryAdditionalViewImages" engine="simple"
             location="component://product/script/org/ofbiz/product/category/CategoryContentServices.xml" invoke="uploadCategoryAdditionalViewImages" auth="true">
        <description>Upload Additional View Images For ProductCategory</description>
        <permission-service service-name="genericContentPermission" main-action="UPDATE"/>
        <attribute name="productCategoryId" type="String" mode="INOUT" optional="false"/>
        <attribute name="additionalImageOne" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageOne_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageOne_contentType" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageTwo" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageTwo_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageTwo_contentType" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageThree" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageThree_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageThree_contentType" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageFour" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageFour_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageFour_contentType" type="String" mode="IN" optional="true"/>
        <!-- SCIPIO -->
        <attribute name="additionalImageOne_imageProfile" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageTwo_imageProfile" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageThree_imageProfile" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageFour_imageProfile" type="String" mode="IN" optional="true"/>
    </service>

    <service name="createSimpleTextContentForCategory" default-entity-name="ProductCategoryContent" engine="simple"
            location="component://product/script/org/ofbiz/product/category/CategoryContentServices.xml" invoke="createSimpleTextContentForCategory" auth="true">
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes entity-name="Content" include="nonpk" mode="IN" optional="true"/>
        <attribute name="text" type="String" mode="IN" optional="false" allow-html="any"/>
        <override name="contentId" optional="true" mode="INOUT"/>
        <override name="fromDate" optional="true"/>
    </service>
    <service name="updateSimpleTextContentForCategory" default-entity-name="ProductCategoryContent" engine="simple"
            location="component://product/script/org/ofbiz/product/category/CategoryContentServices.xml" invoke="updateSimpleTextContentForCategory" auth="true">
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes entity-name="Content" include="nonpk" mode="IN" optional="true"/>
        <attribute name="textDataResourceId" type="String" mode="IN" optional="true"/>
        <attribute name="text" type="String" mode="IN" optional="true" allow-html="any"/>
        <override name="contentId" optional="true" mode="INOUT"/><!-- SCIPIO: TODO: REVIEW: this was added for Scipio, but optional="true" makes no sense for an update service -->
    </service>

    <service name="updateContentSEOForCategory" engine="simple"
            location="component://product/script/org/ofbiz/product/category/CategoryContentServices.xml" invoke="updateContentSEOForCategory" auth="true">
        <description>Update SEO Content For Product Category</description>
        <attribute name="contentId" optional="true" type="String" mode="INOUT"/><!-- SCIPIO: TODO: REVIEW: this was added by Scipio, but optional="true" makes no sense for an update service -->
        <attribute name="productCategoryId" mode="IN" type="String" optional="false"/>
        <attribute name="title" mode="IN" type="String" optional="true"/>
        <attribute name="metaKeyword" mode="IN" type="String" optional="true"/>
        <attribute name="metaDescription" mode="IN" type="String" optional="true"/>
    </service>

    <service name="createRelatedUrlContentForCategory" engine="simple" default-entity-name="ProductCategoryContent"
            location="component://product/script/org/ofbiz/product/category/CategoryContentServices.xml" invoke="createRelatedUrlContentForCategory" auth="true">
        <description>Create Related URL Content For Product Category</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <attribute name="title" type="String" mode="IN" optional="false"/>
        <attribute name="description" type="String" mode="IN" optional="false"/>
        <attribute name="url" type="String" mode="IN" optional="false"/>
        <attribute name="localeString" type="String" mode="IN" optional="true"/>
        <override name="contentId" optional="true" mode="INOUT"/>
        <override name="fromDate" optional="true"/>
    </service>
    <service name="updateRelatedUrlContentForCategory" engine="simple" default-entity-name="ProductCategoryContent"
            location="component://product/script/org/ofbiz/product/category/CategoryContentServices.xml" invoke="updateRelatedUrlContentForCategory" auth="true">
        <description>Update Related URL Content For Product Category</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <attribute name="contentId" type="String" mode="IN" optional="false"/>
        <attribute name="dataResourceId" type="String" mode="IN" optional="false"/>
        <attribute name="title" type="String" mode="IN" optional="true"/>
        <attribute name="description" type="String" mode="IN" optional="true"/>
        <attribute name="url" type="String" mode="IN" optional="true"/>
        <attribute name="localeString" type="String" mode="IN" optional="true"/>
        <override name="contentId" optional="true" mode="INOUT"/><!-- SCIPIO: TODO: REVIEW: this was added by Scipio, but optional="true" makes no sense for an update service -->
    </service>

    <service name="createDownloadContentForCategory" default-entity-name="ProductCategoryContent" engine="simple"
        location="component://product/script/org/ofbiz/product/category/CategoryContentServices.xml" invoke="createDownloadContentForCategory" auth="true">
        <auto-attributes include="pk" mode="IN" optional="true"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes include="nonpk" mode="IN" entity-name="Content" optional="true"/>
        <attribute mode="IN" name="imageData" optional="true" type="java.nio.ByteBuffer"/>
        <attribute mode="IN" name="_imageData_contentType" optional="true" type="String"/>
        <attribute mode="IN" name="_imageData_fileName" optional="true" type="String"/>
        <attribute name="dataResourceTypeId" type="String" mode="IN" optional="true"/>
        <override name="contentId" optional="true" mode="INOUT"/>
        <override name="prodCatContentTypeId" optional="false"/>
    </service>
    <service name="updateDownloadContentForCategory" default-entity-name="ProductCategoryContent" engine="simple"
        location="component://product/script/org/ofbiz/product/category/CategoryContentServices.xml" invoke="updateDownloadContentForCategory" auth="true">
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes mode="IN" entity-name="Content" optional="true"/>
        <attribute mode="IN" name="imageData" optional="true" type="java.nio.ByteBuffer"/>
        <attribute mode="IN" name="_imageData_contentType" optional="true" type="String"/>
        <attribute mode="IN" name="_imageData_fileName" optional="true" type="String"/>
        <attribute name="fileDataResourceId" type="String" mode="IN" optional="true"/>
        <override name="contentId" optional="true" mode="INOUT"/><!-- SCIPIO: TODO: REVIEW: this was added by Scipio, but optional="true" makes no sense for an update service -->
    </service>

    <!-- ProductFeatureDataResource services -->
    <service name="createProductFeatureDataResource" default-entity-name="ProductFeatureDataResource" engine="simple"
            location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="createProductFeatureDataResource" auth="true">
        <description>Create ProductFeature-DataResource</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>
    <service name="removeProductFeatureDataResource" default-entity-name="ProductFeatureDataResource" engine="simple"
            location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="removeProductFeatureDataResource" auth="true">
        <description>Remove ProductFeature-DataResource</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- Customer driven (customers are suppliers) digital download product services -->
    <service name="createCustomerDigitalDownloadProduct" auth="true" engine="simple"
        location="component://product/script/org/ofbiz/product/product/CustomerDigitalDownloadServices.xml" invoke="createCustomerDigitalDownloadProduct">
        <description></description>
        <attribute name="productName" type="String" mode="IN" optional="false"/>
        <attribute name="productStoreId" type="String" mode="IN" optional="false"/>
        <attribute name="price" type="BigDecimal" mode="IN" optional="false"/>
        <attribute name="description" type="String" mode="IN" optional="true"/>
        <attribute name="currencyUomId" type="String" mode="IN" optional="true"/>
        <attribute name="productId" type="String" mode="OUT" optional="false"/>
        <attribute name="currencyUomId" type="String" mode="OUT" optional="false"/>
        <attribute name="minimumOrderQuantity" type="BigDecimal" mode="OUT" optional="false"/>
        <attribute name="availableFromDate" type="Timestamp" mode="OUT" optional="false"/>
    </service>
    <service name="updateCustomerDigitalDownloadProduct" auth="true" engine="simple"
        location="component://product/script/org/ofbiz/product/product/CustomerDigitalDownloadServices.xml" invoke="updateCustomerDigitalDownloadProduct">
        <description></description>
        <attribute name="productId" type="String" mode="IN" optional="false"/>
        <attribute name="currencyUomId" type="String" mode="IN" optional="false"/>
        <attribute name="minimumOrderQuantity" type="BigDecimal" mode="IN" optional="false"/>
        <attribute name="availableFromDate" type="Timestamp" mode="IN" optional="false"/>
        <attribute name="productName" type="String" mode="IN" optional="true"/>
        <attribute name="description" type="String" mode="IN" optional="true"/>
        <attribute name="price" type="BigDecimal" mode="IN" optional="true"/>
    </service>
    <service name="deleteCustomerDigitalDownloadProduct" auth="true" engine="simple"
        location="component://product/script/org/ofbiz/product/product/CustomerDigitalDownloadServices.xml" invoke="deleteCustomerDigitalDownloadProduct">
        <description></description>
        <attribute name="productId" type="String" mode="IN" optional="false"/>
    </service>

    <service name="addCustomerDigitalDownloadProductFile" auth="true" engine="simple"
        location="component://product/script/org/ofbiz/product/product/CustomerDigitalDownloadServices.xml" invoke="addCustomerDigitalDownloadProductFile">
        <description></description>
        <attribute name="contentId" type="String" mode="IN" optional="false"/>
        <attribute name="productId" type="String" mode="IN" optional="false"/>
    </service>
    <service name="removeCustomerDigitalDownloadProductFile" auth="true" engine="simple"
        location="component://product/script/org/ofbiz/product/product/CustomerDigitalDownloadServices.xml" invoke="removeCustomerDigitalDownloadProductFile">
        <description></description>
        <attribute name="contentId" type="String" mode="IN" optional="false"/>
        <attribute name="productId" type="String" mode="IN" optional="false"/>
        <attribute name="productContentTypeId" type="String" mode="IN" optional="false"/>
        <attribute name="fromDate" type="Timestamp" mode="IN" optional="false"/>
    </service>

    <!-- Product Configuration Services -->
    <service name="createProductConfig" default-entity-name="ProductConfig" engine="simple"
                location="component://product/script/org/ofbiz/product/config/ConfigServices.xml" invoke="createProductConfig" auth="true">
        <description>Create a ProductConfig</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <override name="fromDate" mode="INOUT" optional="true"/>
    </service>
    <service name="updateProductConfig" default-entity-name="ProductConfig" engine="simple"
                location="component://product/script/org/ofbiz/product/config/ConfigServices.xml" invoke="updateProductConfig" auth="true">
        <description>Update a ProductConfig</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductConfig" default-entity-name="ProductConfig" engine="simple"
                location="component://product/script/org/ofbiz/product/config/ConfigServices.xml" invoke="deleteProductConfig" auth="true">
        <description>Delete a ProductConfig</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- Product Config Items Services -->
    <service name="createProductConfigItem" default-entity-name="ProductConfigItem" auth="true" engine="simple"
        location="component://product/script/org/ofbiz/product/config/ConfigServices.xml" invoke="createProductConfigItem">
        <description>Create a Config Item</description>
        <auto-attributes include="pk" mode="OUT" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <override name="configItemId" mode="OUT"/>
    </service>
    <service name="updateProductConfigItem" default-entity-name="ProductConfigItem" auth="true" engine="simple"
        location="component://product/script/org/ofbiz/product/config/ConfigServices.xml" invoke="updateProductConfigItem">
        <description>Update a Config Item</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductConfigItem" default-entity-name="ProductConfigItem" auth="true" engine="simple"
        location="component://product/script/org/ofbiz/product/config/ConfigServices.xml" invoke="deleteProductConfigItem">
        <description>Delete a Config Item</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- Product Config Options Services -->
    <service name="createProductConfigOption" default-entity-name="ProductConfigOption" auth="true" engine="simple"
        location="component://product/script/org/ofbiz/product/config/ConfigServices.xml" invoke="createProductConfigOption">
        <description>Create a Config Option</description>
        <auto-attributes include="pk" mode="OUT" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <attribute name="configItemId" type="String" mode="IN" optional="false"/><!-- FIXME -->
    </service>
    <service name="updateProductConfigOption" default-entity-name="ProductConfigOption" auth="true" engine="simple"
        location="component://product/script/org/ofbiz/product/config/ConfigServices.xml" invoke="updateProductConfigOption">
        <description>Update a Config Option</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductConfigOption" default-entity-name="ProductConfigOption" auth="true" engine="simple"
        location="component://product/script/org/ofbiz/product/config/ConfigServices.xml" invoke="deleteProductConfigOption">
        <description>Delete a Config Option</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- Product Config Product Services -->
    <service name="createProductConfigProduct" default-entity-name="ProductConfigProduct" auth="true" engine="simple"
        location="component://product/script/org/ofbiz/product/config/ConfigServices.xml" invoke="createProductConfigProduct">
        <description>Create a ProductConfigProduct</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="updateProductConfigProduct" default-entity-name="ProductConfigProduct" auth="true" engine="simple"
        location="component://product/script/org/ofbiz/product/config/ConfigServices.xml" invoke="updateProductConfigProduct">
        <description>Update a ProductConfigProduct</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductConfigProduct" default-entity-name="ProductConfigProduct" auth="true" engine="simple"
        location="component://product/script/org/ofbiz/product/config/ConfigServices.xml" invoke="deleteProductConfigProduct">
        <description>Delete ProductConfigProduct</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- Product Config Item content services -->
    <service name="createProductConfigItemContent" default-entity-name="ProdConfItemContent" engine="simple"
                location="component://product/script/org/ofbiz/product/config/ProductConfigItemContentServices.xml" invoke="createProductConfigItemContent" auth="true">
        <description>Add Content To ProductConfigItem</description>
        <auto-attributes include="pk" mode="INOUT" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes entity-name="Content" include="nonpk" mode="IN" optional="true"/>
        <override name="fromDate" optional="true"/>
        <!--<override name="contentId" optional="true" mode="INOUT"/>-->
    </service>
    <service name="updateProductConfigItemContent" default-entity-name="ProdConfItemContent" engine="simple"
                location="component://product/script/org/ofbiz/product/config/ProductConfigItemContentServices.xml" invoke="updateProductConfigItemContent" auth="true">
        <description>Update Content To ProductConfigItem</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes entity-name="Content" include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="removeProductConfigItemContent" default-entity-name="ProdConfItemContent" engine="simple"
                location="component://product/script/org/ofbiz/product/config/ProductConfigItemContentServices.xml" invoke="removeProductConfigItemContent" auth="true">
        <description>Remove Content From ProductConfigItem</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="createSimpleTextContentForProductConfigItem" default-entity-name="ProdConfItemContent" engine="simple"
            location="component://product/script/org/ofbiz/product/config/ProductConfigItemContentServices.xml" invoke="createSimpleTextContentForProductConfigItem" auth="true">
        <attribute name="configItemId" type="String" mode="IN" optional="false"></attribute>
        <attribute name="contentId" type="String" mode="IN" optional="true"></attribute>
        <auto-attributes include="pk" mode="IN" optional="true"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes mode="IN" entity-name="Content" optional="true"/>
        <attribute name="text" type="String" mode="IN" optional="false" allow-html="any"/>
        <override name="contentId" optional="true"/>
    </service>
    <service name="updateSimpleTextContentForProductConfigItem" default-entity-name="ProdConfItemContent" engine="simple"
            location="component://product/script/org/ofbiz/product/config/ProductConfigItemContentServices.xml" invoke="updateSimpleTextContentForProductConfigItem" auth="true">
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes mode="IN" entity-name="Content" optional="true"/>
        <attribute name="textDataResourceId" type="String" mode="IN" optional="true"/>
        <attribute name="text" type="String" mode="IN" optional="true" allow-html="any"/>
    </service>
    <service name="getProductFeaturesByType" engine="java"
            location="org.ofbiz.product.feature.ProductFeatureServices" invoke="getProductFeaturesByType">
        <description>
            Returns a map of productFeatureTypeId -> List of ProductFeatures.  If supplied with a productFeatureCategoryId,
            the returned result is that of all product features in that category.  Otherwise, if supplied with a productFeatureGroupId,
            the result is all features of that feature group.  Otherwise, if there is a productId, the returned result is that of all features
            applied to that product.  If the optional productFeatureApplTypeId is specified, only features with application of that type
            will be returned (this would only make sense along with a productId parameter.)
        </description>
        <attribute type="String" mode="IN" name="productFeatureCategoryId" optional="true"/>
        <attribute type="String" mode="IN" name="productFeatureGroupId" optional="true"/>
        <attribute type="String" mode="IN" name="productId" optional="true"/>
        <attribute type="String" mode="IN" name="productFeatureApplTypeId" optional="true"/>
        <attribute type="List" mode="OUT" name="productFeatureTypes" optional="false"/>
        <attribute type="Map" mode="OUT" name="productFeaturesByType" optional="false"/>
    </service>
    <service name="getAllExistingVariants" engine="java"
        location="org.ofbiz.product.feature.ProductFeatureServices" invoke="getAllExistingVariants">
        <description>
            Takes a productId and a List of ProductFeatureAndAppl entities and returns a List of productIds which are
            existing varaints with those features applied.
        </description>
        <attribute type="String" mode="IN" name="productId" optional="false"/>
        <attribute type="List" mode="IN" name="productFeatureAppls" optional="false"/>
        <attribute type="List" mode="OUT" name="variantProductIds" optional="false"/>
    </service>
    <service name="getVariantCombinations" engine="java"
        location="org.ofbiz.product.feature.ProductFeatureServices" invoke="getVariantCombinations">
        <description>
            For a product, returns a List of all possible product feature combinations, based on all SELECTABLE features which
            are applied to the product.  featureCombinations is a List of Maps with the following fields:
                defaultVariantProductId -> default productId for the variant, based on idCodes of the features
                curProductFeatureAndAppls -> List of product features to be applied to this variant
                existingVariantProductIds -> List of productIds of variants which already have these features
        </description>
        <attribute type="String" mode="IN" name="productId" optional="false"/>
        <attribute type="List" mode="OUT" name="featureCombinations" optional="false"/>
    </service>
     <service name="getCategoryVariantProducts" engine="java" auth="false"
         location="org.ofbiz.product.feature.ProductFeatureServices" invoke="getCategoryVariantProducts">
         <description>Takes a productCategoryId and a list of product features and resolves all the product category's
             product members from virtual to variant</description>
         <attribute type="String" mode="IN" name="productCategoryId" optional="false"/>
         <attribute type="java.util.List" mode="IN" name="productFeatures" optional="false"/>
         <attribute type="java.util.List" mode="OUT" name="products"/>
     </service>
    <service name="updateProductIfAvailableFromShipment" engine="java"
            location="org.ofbiz.product.product.ProductServices" invoke="updateProductIfAvailableFromShipment">
        <description>
            If property is set (catalog.properties) this will re-activate (null discountinue date) on the product
            if inventory is available. Triggered via ECA by shipment receipt services
        </description>
        <attribute type="String" mode="IN" name="inventoryItemId" optional="false"/>
    </service>

    <!-- Permission Services -->
    <service name="productGenericPermission" engine="simple" log="quiet" hideResultInLog="true"
        location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="productGenericPermission">
        <implements service="permissionInterface"/>
    </service>
    <service name="productCategoryGenericPermission" engine="simple"
        location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="productCategoryGenericPermission">
        <implements service="permissionInterface"/>
    </service>
    <service name="productPriceGenericPermission" engine="simple"
        location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="productPriceGenericPermission">
        <implements service="permissionInterface"/>
    </service>
    <service name="checkCategoryPermissionWithViewPurchaseAllow" engine="simple"
        location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="checkCategoryPermissionWithViewPurchaseAllow">
        <implements service="permissionInterface"/>
        <attribute type="String" mode="IN" name="productCategoryId" optional="true"/>
    </service>
    <!-- Product Attribute Services -->
    <service name="createProductAttribute" default-entity-name="ProductAttribute" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProductAttribute</description>
        <permission-service service-name="productGenericPermission" main-action="CREATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="updateProductAttribute" default-entity-name="ProductAttribute" engine="entity-auto" invoke="update" auth="true">
        <description>Update a ProductAttribute</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductAttribute" default-entity-name="ProductAttribute" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a ProductAttribute</description>
        <permission-service service-name="productGenericPermission" main-action="DELETE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!--VendorProduct Services -->
    <service name="createVendorProduct" engine="simple" default-entity-name="VendorProduct"
            location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="createVendorProduct" auth="true">
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>
    <service name="deleteVendorProduct" engine="simple" default-entity-name="VendorProduct"
            location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="deleteVendorProduct" auth="true">
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- ProductCategoryGlAccount Services -->
    <service name="createProductCategoryGlAccount" default-entity-name="ProductCategoryGlAccount" engine="simple"
                location="component://product/script/org/ofbiz/product/product/ProductServices.xml" 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/script/org/ofbiz/product/product/ProductServices.xml" 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/script/org/ofbiz/product/product/ProductServices.xml" invoke="deleteProductCategoryGlAccount" auth="true">
        <description>Delete a ProductCategoryGlAccount</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <service name="catalogPermissionCheck" engine="simple"
        location="component://product/script/org/ofbiz/product/catalog/CatalogServices.xml" invoke="catalogPermissionCheck" auth="true">
        <description>Catalog Permission Checking Logic</description>
        <implements service="permissionInterface"/>
    </service>

    <service name="prodCatalogToPartyPermissionCheck" engine="simple"
            location="component://product/script/org/ofbiz/product/catalog/CatalogServices.xml" invoke="prodCatalogToPartyPermissionCheck">
        <description>ProdCatalogToParty Permission Checking Logic</description>
        <implements service="permissionInterface"/>
    </service>

    <service name="productImportFromSpreadsheet" engine="java"
            location="org.ofbiz.product.spreadsheetimport.ImportProductServices" invoke="productImportFromSpreadsheet" auth="true">
        <description>Create product and inventory item</description>
        <attribute name="dirName" type="java.lang.String" mode="IN" optional="true"/>
    </service>
    
    <!-- Start Web Analytics configuration services -->
    <service name="createWebAnalyticsConfig" default-entity-name="WebAnalyticsConfig" engine="entity-auto" invoke="create" auth="true">
        <description>Create a WebAnalyticsConfig</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="updateWebAnalyticsConfig" default-entity-name="WebAnalyticsConfig" engine="entity-auto" invoke="update" auth="true">
        <description>Update a WebAnalyticsConfig</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteWebAnalyticsConfig" default-entity-name="WebAnalyticsConfig" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a WebAnalyticsConfig</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>
    
    <service name="createWebAnalyticsType" default-entity-name="WebAnalyticsType" engine="entity-auto" invoke="create" auth="true">
        <description>Create a WebAnalyticsType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="updateWebAnalyticsType" default-entity-name="WebAnalyticsType" engine="entity-auto" invoke="update" auth="true">
        <description>Update a WebAnalyticsType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteWebAnalyticsType" default-entity-name="WebAnalyticsType" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a WebAnalyticsType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>
    
    <!-- Product Promo Content services -->
    <service name="createProductPromoContent" default-entity-name="ProductPromoContent" engine="simple"
            location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="createProductPromoContent" auth="true">
        <description>Create Product Promo Content</description>
        <auto-attributes include="pk" mode="INOUT" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <override name="fromDate" optional="true"/>
    </service>
    <service name="updateProductPromoContent" default-entity-name="ProductPromoContent" engine="simple"
            location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="updateProductPromoContent" auth="true">
        <description>Update Product Promo Content</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="removeProductPromoContent" default-entity-name="ProductPromoContent" engine="simple"
            location="component://product/script/org/ofbiz/product/product/ProductContentServices.xml" invoke="removeProductPromoContent" auth="true">
        <description>Cancel by the thru date a Product Promo Content</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="addImageForProductPromo" default-entity-name="ProductPromoContent" engine="java"
            location="org.ofbiz.product.product.ProductServices" invoke="addImageForProductPromo" auth="true">
        <implements service="uploadFileInterface"/>
        <auto-attributes include="pk" mode="IN" optional="true"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <attribute name="contentId" mode="IN" optional="true" type="String"/>
        <override name="productPromoContentTypeId" optional="false"/>
        <override name="productPromoId" optional="false"/>
    </service>

    <!-- Image Management Services -->
    <service name="addMultipleuploadForProduct" default-entity-name="ProductContent" engine="java"
        location="org.ofbiz.product.imagemanagement.ImageManagementServices" invoke="addMultipleuploadForProduct" auth="true">
        <implements service="uploadFileInterface"/>
        <auto-attributes include="pk" mode="IN" optional="true"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <attribute mode="INOUT" name="contentId" optional="true" type="String"/>
        <attribute mode="INOUT" name="dataResourceId" optional="true" type="String"/>
        <attribute mode="IN" name="imageResize" optional="true" type="String"/>
        <attribute mode="OUT" name="contentFrameId" optional="true" type="String"/>
        <attribute mode="OUT" name="dataResourceFrameId" optional="true" type="String"/>
        <override name="productContentTypeId" optional="false"/>
        <override name="productId" optional="false"/>
    </service>

    <service name="multipleUploadProductImages" engine="simple"
        location="component://product/script/org/ofbiz/product/imagemanagement/ImageManagementServices.xml" invoke="UploadProductImages" auth="true">
        <description>Multiple upload Images For Product</description>
        <permission-service service-name="genericContentPermission" main-action="CREATE"/>
        <attribute name="productId" type="String" mode="INOUT" optional="false"/>
        <attribute name="imageResize" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageOne" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageOne_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageOne_contentType" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageTwo" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageTwo_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageTwo_contentType" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageThree" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageThree_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageThree_contentType" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageFour" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageFour_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageFour_contentType" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageFive" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageFive_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageFive_contentType" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageSix" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageSix_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageSix_contentType" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageSeven" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageSeven_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageSeven_contentType" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageEight" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageEight_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageEight_contentType" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageNine" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageNine_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageNine_contentType" type="String" mode="IN" optional="true"/>
        <attribute name="additionalImageTen" type="java.nio.ByteBuffer" mode="IN" optional="true"/>
        <attribute name="_additionalImageTen_fileName" type="String" mode="IN" optional="true"/>
        <attribute name="_additionalImageTen_contentType" type="String" mode="IN" optional="true"/>
    </service>

    <service name="removeProductContentAndImageFile" default-entity-name="ProductContent" engine="simple"
        location="component://product/script/org/ofbiz/product/imagemanagement/ImageManagementServices.xml" invoke="removeProductContentAndImageFile" auth="true">
        <description>Remove Content From Product and File Image</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>

    <service name="removeProductContentForImageManagement" engine="simple"
        location="component://product/script/org/ofbiz/product/imagemanagement/ImageManagementServices.xml" invoke="removeProductContentForImageManagement" auth="true">
        <description>Delete Product Content Relationship Entity</description>
        <attribute mode="IN" name="contentId" optional="false" type="String"/>
        <attribute mode="IN" name="productId" optional="false" type="String"/>
    </service>

    <service name="removeImageFileForImageManagement" engine="java"
        location="org.ofbiz.product.imagemanagement.ImageManagementServices" invoke="removeImageFileForImageManagement" auth="true">
        <description>Delete Image File</description>
        <attribute mode="IN" name="productId" optional="false" type="String"/>
        <attribute mode="IN" name="contentId" optional="false" type="String"/>
        <attribute mode="IN" name="objectInfo" optional="false" type="String"/>
        <attribute mode="IN" name="dataResourceName" optional="false" type="String"/>
    </service>

    <service name="addImageFrame" engine="java"
        location="org.ofbiz.product.imagemanagement.FrameImage" invoke="addImageFrame" auth="true">
        <description>Create Image Frame For Product.</description>
        <attribute mode="IN" name="productId" optional="false" type="String"/>
        <attribute mode="IN" name="imageName" optional="false" type="String"/>
        <attribute mode="IN" name="imageWidth" optional="false" type="String"/>
        <attribute mode="IN" name="imageHeight" optional="false" type="String"/>
        <attribute mode="IN" name="frameContentId" optional="false" type="String"/>
        <attribute mode="IN" name="frameDataResourceId" optional="false" type="String"/>
    </service>

    <!-- SCIPIO: FIXME?: FrameImage.uploadFrame is an event, not a service...
    <service name="uploadFrame" engine="java"
        location="org.ofbiz.product.imagemanagement.FrameImage" invoke="uploadFrame" auth="true">
        <description>Upload Image Frame.</description>
        <attribute mode="IN" name="uploadedFile" optional="false" type="java.nio.ByteBuffer"/>
    </service>
    -->

    <service name="imageCrop" engine="java"
        location="org.ofbiz.product.imagemanagement.CropImage" invoke="imageCrop" auth="true">
        <description>Crop Image</description>
        <attribute mode="IN" name="productId" optional="false" type="String"/>
        <attribute mode="IN" name="imageName" optional="false" type="String"/>
        <attribute mode="IN" name="imageX" optional="false" type="String"/>
        <attribute mode="IN" name="imageY" optional="false" type="String"/>
        <attribute mode="IN" name="imageW" optional="false" type="String"/>
        <attribute mode="IN" name="imageH" optional="false" type="String"/>
    </service>

    <service name="imageRotate" engine="java"
        location="org.ofbiz.product.imagemanagement.RotateImage" invoke="imageRotate" auth="true">
        <description>Rotate Image</description>
        <attribute mode="IN" name="productId" optional="false" type="String"/>
        <attribute mode="IN" name="imageName" optional="false" type="String"/>
        <attribute mode="IN" name="angle" optional="false" type="String"/>
    </service>

    <service name="setImageDetail" engine="simple" default-entity-name="ProductContent"
        location="component://product/script/org/ofbiz/product/imagemanagement/ImageManagementServices.xml" invoke="setImageDetail" auth="true">
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <attribute name="sequenceNum" mode="IN" type="Integer" optional="true"/>
        <attribute name="drIsPublic" mode="IN" type="String" optional="true" default-value="N"/>
        <attribute name="description" mode="IN" type="String" optional="true"/>
    </service>

    <service name="updateStatusImageManagement" engine="simple"
        location="component://product/script/org/ofbiz/product/imagemanagement/ImageManagementServices.xml" invoke="updateStatusImageManagement" auth="true">
        <attribute name="contentId" mode="IN" type="String" optional="false"/>
        <attribute name="checkStatusId" mode="IN" type="String" optional="true"/>
    </service>

    <service name="addRejectedReasonImageManagement" engine="simple"
        location="component://product/script/org/ofbiz/product/imagemanagement/ImageManagementServices.xml" invoke="addRejectedReasonImageManagement" auth="true">
        <attribute name="contentId" mode="IN" type="String" optional="false"/>
        <attribute name="description" mode="IN" type="String" optional="true"/>
    </service>

    <service name="createImageContentApproval" engine="simple"
        location="component://product/script/org/ofbiz/product/imagemanagement/ImageManagementServices.xml" invoke="createImageContentApproval" auth="true">
        <attribute name="contentId" mode="IN" type="String" optional="false"/>
    </service>
    
    <service name="removeImageContentApproval" engine="simple"
        location="component://product/script/org/ofbiz/product/imagemanagement/ImageManagementServices.xml" invoke="removeImageContentApproval" auth="true">
        <attribute name="partyId" mode="IN" type="String" optional="false"/>
    </service>
    
    <service name="resizeImages" engine="simple"
        location="component://product/script/org/ofbiz/product/imagemanagement/ImageManagementServices.xml" invoke="resizeImages" auth="true">
        <description>Resize Images.</description>
        <attribute name="resizeOption" mode="IN" type="String" optional="false"/>
        <attribute name="productId" mode="IN" type="String" optional="false"/>
        <attribute name="size" mode="IN" type="String" optional="false"/>
    </service>
    
    <service name="resizeImageOfProduct" engine="java"
        location="org.ofbiz.product.imagemanagement.ImageManagementServices" invoke="resizeImageOfProduct" auth="true">
        <description>Resize Image Of Product.</description>
        <attribute name="productId" mode="IN" type="String" optional="false"/>
        <attribute name="dataResourceName" mode="IN" type="String" optional="false"/>
        <attribute name="resizeWidth" mode="IN" type="String" optional="false"/>
    </service>
    
    <service name="createNewImageThumbnail" engine="java"
        location="org.ofbiz.product.imagemanagement.ImageManagementServices" invoke="createNewImageThumbnail" auth="true">
        <description>Create New Image Thumbnail.</description>
        <attribute name="productId" mode="IN" type="String" optional="false"/>
        <attribute name="contentId" mode="IN" type="String" optional="false"/>
        <attribute name="dataResourceName" mode="IN" type="String" optional="false"/>
        <attribute name="drObjectInfo" mode="IN" type="String" optional="false"/>
        <attribute name="sizeWidth" mode="IN" type="String" optional="false"/>
    </service>
    
    <service name="removeImageBySize" engine="simple"
        location="component://product/script/org/ofbiz/product/imagemanagement/ImageManagementServices.xml" invoke="removeImageBySize" auth="true">
        <description>Remove Image By Size.</description>
        <attribute name="productId" mode="IN" type="String" optional="false"/>
        <attribute name="mapKey" mode="IN" type="String" optional="false"/>
    </service>
    
    <service name="replaceImageToExistImage" engine="java"
        location="org.ofbiz.product.imagemanagement.ReplaceImage" invoke="replaceImageToExistImage" auth="true">
        <description>Resize Image Of Product.</description>
        <attribute name="productId" mode="IN" type="String" optional="false"/>
        <attribute name="contentIdExist" mode="IN" type="String" optional="false"/>
        <attribute name="contentIdReplace" mode="IN" type="String" optional="false"/>
        <attribute name="dataResourceNameExist" mode="IN" type="String" optional="false"/>
        <attribute name="dataResourceNameReplace" mode="IN" type="String" optional="false"/>
    </service>
    
    <service name="renameImage" engine="java"
        location="org.ofbiz.product.imagemanagement.ImageManagementServices" invoke="renameImage" auth="true">
        <description>Rename Image.</description>
        <attribute name="productId" mode="IN" type="String" optional="false"/>
        <attribute name="contentId" mode="IN" type="String" optional="false"/>
        <attribute name="drDataResourceName" mode="IN" type="String" optional="false"/>
    </service>
    
    <!-- Best Selling Category Services -->
    <service name="loadBestSellingCategory" engine="simple"
        location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="loadBestSellingCategory" auth="true">
        <description>Load data of best selling category by week.</description>
        <attribute name="productStoreId" mode="IN" type="String" optional="false"/>
    </service>
    
    <service name="RemoveProductFromBestSellCategory" engine="simple"
        location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="RemoveProductFromBestSellCategory" auth="true">
        <description>Remove products from best selling category.</description>
        <attribute name="prodCatalogId" mode="IN" type="String" optional="false"/>
    </service>
    
    <service name="AddProductToBestSellCategory" engine="simple"
        location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="AddProductToBestSellCategory" auth="true">
        <description>Add products to best selling category.</description>
        <attribute name="productStoreId" mode="IN" type="String" optional="false"/>
        <attribute name="prodCatalogId" mode="IN" type="String" optional="false"/>
        <attribute name="week" mode="IN" type="Long" optional="false"/>
        <attribute name="year" mode="IN" type="Long" optional="false"/>
    </service>
    
    <service name="FindCategoryChild" engine="simple"
        location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="FindCategoryChild" auth="true">
        <description>Find category child.</description>
        <attribute name="productStoreId" mode="IN" type="String" optional="false"/>
        <attribute name="productCategoryId" mode="IN" type="String" optional="false"/>
        <attribute name="primaryProductCategoryId" mode="IN" type="String" optional="false"/>
        <attribute name="week" mode="IN" type="Long" optional="false"/>
        <attribute name="year" mode="IN" type="Long" optional="false"/>
    </service>
    
    <service name="FindBestSellingProduct" engine="simple"
        location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="FindBestSellingProduct" auth="true">
        <description>Find best selling product.</description>
        <attribute name="productStoreId" mode="IN" type="String" optional="false"/>
        <attribute name="productCategoryId" mode="IN" type="String" optional="false"/>
        <attribute name="primaryProductCategoryId" mode="IN" type="String" optional="false"/>
        <attribute name="week" mode="IN" type="Long" optional="false"/>
        <attribute name="year" mode="IN" type="Long" optional="false"/>
        <attribute name="productCategoryId" mode="OUT" type="String" optional="true"/>
    </service>
    
    <!-- Alternative URLs -->
    <service name="createMissingCategoryAndProductAltUrls" engine="simple"
                location="component://product/script/org/ofbiz/product/catalog/CatalogServices.xml" invoke="createMissingCategoryAndProductAltUrls" auth="true" use-transaction="false">
        <description>Create missing Category and Product Alternative URLs</description>
        <attribute name="prodCatalogId" mode="INOUT" type="String" optional="false"/>
        <attribute name="category" mode="IN" type="String" optional="true"/>
        <attribute name="product" mode="IN" type="String" optional="true"/>
        <attribute name="categoriesNotUpdated" mode="OUT" type="Integer" optional="true"/>
        <attribute name="categoriesUpdated" mode="OUT" type="Integer" optional="true"/>
        <attribute name="productsNotUpdated" mode="OUT" type="Integer" optional="true"/>
        <attribute name="productsUpdated" mode="OUT" type="Integer" optional="true"/>
    </service>

   <service name="createMarketInterest" default-entity-name="MarketInterest" engine="entity-auto" invoke="create" auth="true">
        <description>Create a Market Interest</description>
        <permission-service service-name="productGenericPermission" main-action="CREATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    
    <service name="updateMarketInterest" default-entity-name="MarketInterest" engine="entity-auto" invoke="update" auth="true">
        <description>Update a Market Interest</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>

    <service name="deleteMarketInterest" default-entity-name="MarketInterest" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a Market Interest</description>
        <permission-service service-name="productGenericPermission" main-action="DELETE"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- Product GroupOrder Services -->
    <service name="createProductGroupOrder" default-entity-name="ProductGroupOrder" engine="simple"
        location="component://product/script/org/ofbiz/product/product/ProductServices.xml" 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/script/org/ofbiz/product/product/ProductServices.xml" 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/script/org/ofbiz/product/product/ProductServices.xml" 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/script/org/ofbiz/product/product/ProductServices.xml" 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/script/org/ofbiz/product/product/ProductServices.xml" 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/script/org/ofbiz/product/product/ProductServices.xml" 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/script/org/ofbiz/product/product/ProductServices.xml" invoke="checkProductGroupOrderExpired" auth="true">
        <description>Check ProductGroupOrder Expired</description>
        <attribute name="groupOrderId" mode="IN" type="String" optional="false"/>
    </service>

    <service name="createGoodIdentificationType" default-entity-name="GoodIdentificationType" engine="entity-auto" invoke="create" auth="true">
        <description>Create a GoodIdentificationType</description>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes include="pk" mode="INOUT" optional="true"/>
    </service>
    <service name="updateGoodIdentificationType" default-entity-name="GoodIdentificationType" engine="entity-auto" invoke="update" auth="true">
        <description>Update a GoodIdentificationType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteGoodIdentificationType" default-entity-name="GoodIdentificationType" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a GoodIdentificationType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <service name="createProdCatalogCategoryType" default-entity-name="ProdCatalogCategoryType" engine="entity-auto" invoke="create" auth="true">
        <description>Create ProdCatalogCategoryType Record</description>
        <auto-attributes mode="INOUT" include="pk" optional="true"/>
        <auto-attributes mode="IN" include="nonpk" optional="true"/>
    </service>
    <service name="updateProdCatalogCategoryType" default-entity-name="ProdCatalogCategoryType" engine="entity-auto" invoke="update" auth="true">
        <description>Update ProdCatalogCategoryType record</description>
        <auto-attributes include="pk" mode="IN"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProdCatalogCategoryType" default-entity-name="ProdCatalogCategoryType" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete ProdCatalogCategoryType Record</description>
        <auto-attributes mode="IN" include="pk"/>
    </service>

    <service name="createProductAssocType" default-entity-name="ProductAssocType" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProductAssocType</description>
        <auto-attributes include="pk" mode="INOUT" optional="true"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="updateProductAssocType" default-entity-name="ProductAssocType" engine="entity-auto" invoke="update" auth="true">
        <description>Update a ProductAssocType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductAssocType" default-entity-name="ProductAssocType" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a ProductAssocType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- ProductCategoryContentType services -->
    <service name="createProductCategoryContentType" default-entity-name="ProductCategoryContentType" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProductCategoryContentType</description>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes include="pk" mode="INOUT" optional="true"/>
    </service>
    <service name="updateProductCategoryContentType" default-entity-name="ProductCategoryContentType" engine="entity-auto" invoke="update" auth="true">
        <description>Update a ProductCategoryContentType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductCategoryContentType" default-entity-name="ProductCategoryContentType" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a ProductCategoryContentType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- ProductCategoryType services -->
    <service name="createProductCategoryType" default-entity-name="ProductCategoryType" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProductCategoryType</description>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes include="pk" mode="INOUT" optional="true"/>
    </service>
    <service name="updateProductCategoryType" default-entity-name="ProductCategoryType" engine="entity-auto" invoke="update" auth="true">
        <description>Update a GlFiscalType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductCategoryType" default-entity-name="ProductCategoryType" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a ProductCategoryType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- ProductCategoryTypeAttr services -->
    <service name="createProductCategoryTypeAttr" default-entity-name="ProductCategoryTypeAttr" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProductCategoryTypeAttr</description>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes include="pk" mode="INOUT" optional="false"/>
    </service>
    <service name="updateProductCategoryTypeAttr" default-entity-name="ProductCategoryTypeAttr" engine="entity-auto" invoke="update" auth="true">
        <description>Update a ProductCategoryTypeAttr</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductCategoryTypeAttr" default-entity-name="ProductCategoryTypeAttr" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a ProductCategoryTypeAttr</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- ProductContentType services -->
    <service name="createProductContentType" default-entity-name="ProductContentType" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProductContentType</description>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes include="pk" mode="INOUT" optional="true"/>
    </service>
    <service name="updateProductContentType" default-entity-name="ProductContentType" engine="entity-auto" invoke="update" auth="true">
        <description>Update a ProductContentType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductContentType" default-entity-name="ProductContentType" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a ProductContentType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- ProductMaintType services -->
    <service name="createProductMaintType" default-entity-name="ProductMaintType" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProductMaintType</description>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes include="pk" mode="INOUT" optional="true"/>
    </service>
    <service name="updateProductMaintType" default-entity-name="ProductMaintType" engine="entity-auto" invoke="update" auth="true">
        <description>Update a ProductMaintType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductMaintType" default-entity-name="ProductMaintType" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a ProductMaintType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <!-- ProductMeterType services -->
    <service name="createProductMeterType" default-entity-name="ProductMeterType" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProductMeterType</description>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
        <auto-attributes include="pk" mode="INOUT" optional="true"/>
    </service>
    <service name="updateProductMeterType" default-entity-name="ProductMeterType" engine="entity-auto" invoke="update" auth="true">
        <description>Update a ProductMeterType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductMeterType" default-entity-name="ProductMeterType" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a ProductMeterType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <service name="createProductType" default-entity-name="ProductType" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProductType</description>
        <auto-attributes include="pk" mode="INOUT" optional="true"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="updateProductType" default-entity-name="ProductType" engine="entity-auto" invoke="update" auth="true">
        <description>Update a ProductType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductType" default-entity-name="ProductType" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a ProductType</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <service name="createProductTypeAttr" default-entity-name="ProductTypeAttr" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProductTypeAttr</description>
        <auto-attributes include="pk" mode="INOUT" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="updateProductTypeAttr" default-entity-name="ProductTypeAttr" engine="entity-auto" invoke="update" auth="true">
        <description>Update a ProductTypeAttr</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="deleteProductTypeAttr" default-entity-name="ProductTypeAttr" engine="entity-auto" invoke="delete" auth="true">
        <description>Delete a ProductTypeAttr</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
    </service>

    <service name="createProdCatalogInvFacility" default-entity-name="ProdCatalogInvFacility" engine="entity-auto" invoke="create" auth="true">
        <description>Create a ProdCatalogInvFacility</description>
        <auto-attributes include="pk" mode="INOUT" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="updateProdCatalogInvFacility" default-entity-name="ProdCatalogInvFacility" engine="entity-auto" invoke="update" auth="true">
        <description>Update a ProdCatalogInvFacility</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <auto-attributes include="nonpk" mode="IN" optional="true"/>
    </service>
    <service name="expireProdCatalogInvFacility" default-entity-name="ProdCatalogInvFacility" engine="entity-auto" invoke="expire" auth="true">
        <description>Expire a ProdCatalogInvFacility Record</description>
        <auto-attributes mode="IN" include="pk"/>
    </service>

    <!-- ======================================== -->
    <!-- SCIPIO: New Services (stock-like) -->
    <!-- ======================================== -->

    <service name="createProdCatalogAndStoreAssoc" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="createProdCatalogAndStoreAssoc" auth="true">
        <description>SCIPIO: Create a ProdCatalog and ProductStoreCatalog association</description>
        <implements service="createProdCatalog"/>
        <implements service="createProductStoreCatalog"/>
    </service>
    
    <service name="updateProdCatalogAndStoreAssoc" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="updateProdCatalogAndStoreAssoc" auth="true">
        <description>SCIPIO: Update a ProdCatalog and ProductStoreCatalog association</description>
        <implements service="updateProdCatalog"/>
        <implements service="updateProductStoreCatalog"/>
    </service>

    <service name="deleteProdCatalogAndStoreAssoc" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="deleteProdCatalogAndStoreAssoc" auth="true">
        <description>SCIPIO: Delete a ProdCatalog and ProductStoreCatalog association</description>
        <implements service="deleteProdCatalog"/>
        <implements service="deleteProductStoreCatalog"/>
    </service>
    
    <service name="createProductCategoryAndCatalogAssoc" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="createProductCategoryAndCatalogAssoc" auth="true">
        <description>SCIPIO: Create a ProductCategory and its top association to catalog</description>
        <implements service="createProductCategory"/>
        <implements service="addProductCategoryToProdCatalog"/>
    </service>
    
    <service name="updateProductCategoryAndCatalogAssoc" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="updateProductCategoryAndCatalogAssoc" auth="true">
        <description>SCIPIO: Update a ProductCategory and its top association to catalog</description>
        <implements service="updateProductCategory"/>
        <implements service="updateProductCategoryToProdCatalog"/>
    </service>

    <service name="createProductCategoryAndCategoryAssoc" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="createProductCategoryAndCategoryAssoc" auth="true">
        <description>SCIPIO: Create a ProductCategory and add as child of another category</description>
        <implements service="createProductCategory"/>
        <implements service="addProductCategoryToCategory"/>
    </service>
    
    <service name="updateProductCategoryAndCategoryAssoc" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="updateProductCategoryAndCategoryAssoc" auth="true">
        <description>SCIPIO: Update a ProductCategory and its association to another category (as child)</description>
        <implements service="updateProductCategory"/>
        <implements service="updateProductCategoryToCategory"/>
        <override name="productCategoryId" mode="IN"/><!-- SCIPIO: for some reason this is INOUT in the ofbiz interface, not needed... -->
    </service>
    
    <service name="getProductCategoryContentLocalizedSimpleTextViews" engine="java"
                location="org.ofbiz.product.category.CategoryServices" invoke="getProductCategoryContentLocalizedSimpleTextViews" auth="true">
        <description>SCIPIO: For each simple-text-compatible prodCatContentTypeId, returns a list of complex record views, 
            where the first entry is ProductCategoryContentAndElectronicText and the following entries (if any) are ContentAssocToElectronicText views.</description>
        <permission-service service-name="productGenericPermission" main-action="VIEW"/>
        <attribute name="productCategoryId" mode="IN" type="String" optional="false"/>
        <attribute name="prodCatContentTypeIdList" mode="IN" type="List" optional="false"/>
        <attribute name="filterByDate" mode="IN" type="Boolean" optional="true" default-value="true"/>
        <attribute name="useCache" mode="IN" type="Boolean" optional="true" default-value="false"/>
        <attribute name="getViewsByType" mode="IN" type="Boolean" optional="true" default-value="true"/>
        <attribute name="getViewsByTypeAndLocale" mode="IN" type="Boolean" optional="true" default-value="false"/>
        <attribute name="getTextByTypeAndLocale" mode="IN" type="Boolean" optional="true" default-value="false"/>
        <attribute name="viewsByType" mode="OUT" type="Map" optional="true"/>
        <attribute name="viewsByTypeAndLocale" mode="OUT" type="Map" optional="true"/>
        <attribute name="textByTypeAndLocale" mode="OUT" type="Map" optional="true"/>
    </service>
    
    <service name="getProductContentLocalizedSimpleTextViews" engine="java"
                location="org.ofbiz.product.product.ProductServices" invoke="getProductContentLocalizedSimpleTextViews" auth="true">
        <description>SCIPIO: For each simple-text-compatible productContentTypeIdList, returns a list of complex record views, 
            where the first entry is ProductContentAndElectronicText and the following entries (if any) are ContentAssocToElectronicText views.</description>
        <permission-service service-name="productGenericPermission" main-action="VIEW"/>
        <attribute name="productId" mode="IN" type="String" optional="false"/>
        <attribute name="productContentTypeIdList" mode="IN" type="List" optional="false"/>
        <attribute name="filterByDate" mode="IN" type="Boolean" optional="true" default-value="true"/>
        <attribute name="useCache" mode="IN" type="Boolean" optional="true" default-value="false"/>
        <attribute name="getViewsByType" mode="IN" type="Boolean" optional="true" default-value="true"/>
        <attribute name="getViewsByTypeAndLocale" mode="IN" type="Boolean" optional="true" default-value="false"/>
        <attribute name="getTextByTypeAndLocale" mode="IN" type="Boolean" optional="true" default-value="false"/>
        <attribute name="viewsByType" mode="OUT" type="Map" optional="true"/>
        <attribute name="viewsByTypeAndLocale" mode="OUT" type="Map" optional="true"/>
        <attribute name="textByTypeAndLocale" mode="OUT" type="Map" optional="true"/>
    </service>
    
    <service name="replaceProductCategoryContentLocalizedSimpleTexts" engine="java" location="org.ofbiz.product.category.CategoryServices" invoke="replaceProductCategoryContentLocalizedSimpleTexts">
        <description>SCIPIO: Intelligently creates, updates and deletes ProductCategoryContent ALTERNATE_LOCALE simple text contents (wrapper around replaceContentLocalizedSimpleTexts)</description>
        <implements service="replaceEntityContentLocalizedSimpleTextsInterface"/>
        <attribute name="productCategoryId" type="String" mode="IN" optional="false"/>
    </service>
    
    <service name="replaceProductContentLocalizedSimpleTexts" engine="java" location="org.ofbiz.product.product.ProductServices" invoke="replaceProductContentLocalizedSimpleTexts">
        <description>SCIPIO: Intelligently creates, updates and deletes ProductContent ALTERNATE_LOCALE simple text contents (wrapper around replaceContentLocalizedSimpleTexts)</description>
        <implements service="replaceEntityContentLocalizedSimpleTextsInterface"/>
        <attribute name="productId" type="String" mode="IN" optional="false"/>
    </service>

    <!-- ======================================== -->
    <!-- SCIPIO: New Versatile Services (stock-like) -->
    <!-- ======================================== -->
    <!-- These versatile service eliminates need for copy-pasting controller defs and events - 
        form params control behavior if this is set in an event. Originally designed for catalog tree. 
        NOTE: The ProductCategory services all check whether catalog or category assoc change is needed
            by check if parentProductCategoryId is empty or non-empty, respectively. -->

    <!-- CATALOG -->
    
    <service name="createProdCatalogAndStoreAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/catalog/CatalogServices.xml" invoke="createProdCatalogAndStoreAssocVersatile" auth="true">
        <description>SCIPIO: Create a ProdCatalog and ProductStoreCatalog association (versatile)</description>
        <implements service="createProdCatalogAndStoreAssoc"/>
    </service>
    
    <service name="updateProdCatalogAndStoreAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/catalog/CatalogServices.xml" invoke="updateProdCatalogAndStoreAssocVersatile" auth="true">
        <description>SCIPIO: Update a ProdCatalog and ProductStoreCatalog association (versatile)</description>
        <implements service="updateProdCatalogAndStoreAssoc"/>
    </service>
    
    <service name="deleteProdCatalogStoreAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/catalog/CatalogServices.xml" invoke="deleteProdCatalogStoreAssocVersatile" auth="true">
        <description>SCIPIO: Delete a ProductStoreCatalog association(s) (versatile)</description>
        <implements service="deleteProductStoreCatalog"/>
        <attribute name="deleteAssocMode" mode="IN" type="String" optional="true" default-value="remove">
            <description>(remove|expire, default: remove)</description>
        </attribute>
    </service>
    
    <service name="deleteProdCatalogAndRelatedVersatile" default-entity-name="ProdCatalog" engine="simple"
                location="component://product/script/org/ofbiz/product/catalog/CatalogServices.xml" invoke="deleteProdCatalogAndRelatedVersatile" auth="true">
        <description>SCIPIO: Delete a ProdCatalog record and various related records [WARN: may be dangerous - best-effort] (versatile)</description>
        <permission-service service-name="catalogPermissionCheck" main-action="DELETE"/><!-- no delegated check, needs explicit -->
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <attribute name="deleteParentAssocSelect" mode="IN" type="String" optional="true" default-value="all">
            <description>(none|expired|all, default: expired) Controls whether deletes all (default)
                or only expired ProductStoreCatalog records to this category's parents</description>
        </attribute>
        <attribute name="deleteChildAssocSelect" mode="IN" type="String" optional="true" default-value="expired">
            <description>(none|expired|all, default: expired) If "expired" (default), removes children assoc records
                such as ProdCatalogCategory that are expired; 
                if "all", removes all such records even if destructive.
                WARN: "all" mode may leave products/categories as orphans!</description>
        </attribute>
        <attribute name="deleteSpecialAssocSelect" mode="IN" type="String" optional="true" default-value="none">
            <description>(none|expired|all, default: expired) Special-purpose association deletion mode
                WARN: may currently be destructive (TODO: REVIEW) - "expired" is safe but only if no expired records are still needed.</description>
        </attribute>
        <!-- TODO: not implemented
        <attribute name="deleteChildrenSelect" mode="IN" type="String" optional="true" default-value="none">
            <description>(none|recursive) Delete the child categories and products of this category (most destructive)</description>
        </attribute>-->
    </service>
    
    <service name="deleteProdCatalogAndStoreAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/catalog/CatalogServices.xml" invoke="deleteProdCatalogAndStoreAssocVersatile" auth="true">
        <description>SCIPIO: Delete a ProdCatalog AND/OR ProductStoreCatalog association(s) (versatile)</description>
        <implements service="deleteProdCatalogStoreAssocVersatile"/>
        <attribute name="deleteRecordAndRelated" mode="IN" type="Boolean" optional="true" default-value="true">
            <description>If true, attempts to delete ProdCatalog; if false only deletes store association</description>
        </attribute>
    </service>
    
    <service name="addProdCatalogStoreAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/catalog/CatalogServices.xml" invoke="addProdCatalogStoreAssocVersatile" auth="true">
        <description>SCIPIO: Adds a ProductStoreCatalog association, first checking to make sure doesn't already exist (versatile)</description>
        <implements service="createProductStoreCatalog"/>
    </service>

    <!-- CATEGORY -->
    
    <service name="createProductCategoryAndCatAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="createProductCategoryAndCatAssocVersatile" auth="true">
        <description>SCIPIO: Create a ProductCategory and add as a top catalog category (if parentProductCategoryId is empty) 
            or as child of another category (if parentProductCategoryId is set) (versatile)</description>
        <implements service="createProductCategory"/>
        <implements service="addProductCategoryToProdCatalog"/>
        <implements service="addProductCategoryToCategory"/>
        <implements service="replaceProductCategoryContentLocalizedSimpleTexts"/>
        <attribute name="updateLocalizedTexts" mode="IN" type="Boolean" optional="true" default-value="false"/>
        <!-- make all PK optional because it's one-interface-or-the-other (and fromDate auto-populated) -->
        <override name="productCategoryId" optional="true"/>
        <override name="fromDate" optional="true"/>
        <override name="prodCatalogId" optional="true"/><!-- addProductCategoryToProdCatalog -->
        <override name="prodCatalogCategoryTypeId" optional="true"/><!-- addProductCategoryToProdCatalog -->
        <override name="parentProductCategoryId" optional="true"/><!-- addProductCategoryToCategory -->
    </service>
    
    <service name="updateProductCategoryAndCatAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="updateProductCategoryAndCatAssocVersatile" auth="true">
        <description>SCIPIO: Update a ProductCategory and its top association to catalog (if parentProductCategoryId is empty) or 
            its association to another category (if parentProductCategoryId is set) (versatile)</description>
        <implements service="updateProductCategory"/>
        <implements service="updateProductCategoryToProdCatalog"/>
        <implements service="updateProductCategoryToCategory"/>
        <implements service="replaceProductCategoryContentLocalizedSimpleTexts"/>
        <attribute name="updateLocalizedTexts" mode="IN" type="Boolean" optional="true" default-value="false"/>
        <override name="productCategoryId" mode="IN"/><!-- WORKAROUND: for some reason this is INOUT in the ofbiz interface, not needed... -->
        <override name="fromDate" optional="false"/>
        <!-- make PART of PK optional because it's one-interface-or-the-other -->
        <override name="prodCatalogId" optional="true"/><!-- addProductCategoryToProdCatalog -->
        <override name="prodCatalogCategoryTypeId" optional="true"/><!-- addProductCategoryToProdCatalog -->
        <override name="parentProductCategoryId" optional="true"/><!-- addProductCategoryToCategory -->
    </service>
    
    <service name="deleteProductCategoryCatAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="deleteProductCategoryCatAssocVersatile" auth="true">
        <description>SCIPIO: Delete a ProductCategory catalog (if parentProductCategoryId empty) or 
            category (if parentProductCategoryId set) association (versatile)</description>
        <auto-attributes entity-name="ProductCategory" include="pk" mode="IN" optional="false"/>
        <auto-attributes entity-name="ProdCatalogCategory" include="pk" mode="IN" optional="true"/>
        <auto-attributes entity-name="ProductCategoryRollup" include="pk" mode="IN" optional="true"/>
        <attribute name="deleteAssocMode" mode="IN" type="String" optional="true" default-value="remove">
            <description>(remove|expire, default: remove)</description>
        </attribute>
        <override name="productCategoryId" optional="false"/>
    </service>
    
    <!-- SCIPIO: new (2017-10-20)
        This attempts to delete a ProductCategory and related records.
        By default it only removes related records of low importance and relatively "safe" to remove
        such as ProductCategoryAttribute, ProductCategoryContent and expired ProdCatalogCategory/ProductCategoryRollup/ProductCategoryMember records.
        See service attributes for more destructive options.
        TODO: 2017-10-20: partial functionality only -->
    <service name="deleteProductCategoryAndRelatedVersatile" default-entity-name="ProductCategory" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="deleteProductCategoryAndRelatedVersatile" auth="true">
        <description>SCIPIO: Delete a ProductCategory record and various related records [WARN: may be dangerous - best-effort] (versatile)</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <attribute name="deleteParentAssocSelect" mode="IN" type="String" optional="true" default-value="all">
            <description>(none|expired|all, default: expired) Controls whether deletes all (default)
                or only expired ProductCategoryRollup and ProdCatalogCategory records to this category's parents</description>
        </attribute>
        <attribute name="deleteChildAssocSelect" mode="IN" type="String" optional="true" default-value="expired">
            <description>(none|expired|all, default: expired) If "expired" (default), removes children assoc records
                such as ProductCategoryMember and ProductCategoryRollup that are expired; 
                if "all", removes all such records even if destructive.
                WARN: "all" mode may leave products/categories as orphans!</description>
        </attribute>
        <attribute name="deleteContentRecursive" mode="IN" type="String" optional="true" default-value="all">
            <description>(none|active|all, default: all) Controls whether and which Content records are deleted
                recursively. If none, only the associations are deleted. "active" means non-expired.
                WARN: This function only makes sense if the Content records were meant to be product-specific
                    and not standalone; if standalone content is linked to the product then this may cause collateral damage!</description>
        </attribute>
        <attribute name="deleteSpecialAssocSelect" mode="IN" type="String" optional="true" default-value="none">
            <description>(none|expired|all, default: expired) Special-purpose association deletion mode,
                e.g. TaxAuthorityRateProduct and TaxAuthorityCategory
                WARN: may currently be destructive (TODO: REVIEW) - "expired" is safe but only if no expired records are still needed.</description>
        </attribute>
        <!-- TODO: not implemented
        <attribute name="deleteChildrenSelect" mode="IN" type="String" optional="true" default-value="none">
            <description>(none|recursive) Delete the child categories and products of this category (most destructive)</description>
        </attribute>-->
    </service>
    
    <service name="deleteProductCategoryAndCatAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="deleteProductCategoryAndCatAssocVersatile" auth="true">
        <description>SCIPIO: Delete a ProductCategory record (if no members) AND/OR a catalog/category association 
            based on wether parentProductCategoryId set (versatile)</description>
        <implements service="deleteProductCategoryCatAssocVersatile"/>
        <implements service="deleteProductCategoryAndRelatedVersatile"/>
        <attribute name="deleteRecordAndRelated" mode="IN" type="Boolean" optional="true" default-value="true">
            <description>If true, attempts to delete ProductCategory (using deleteProductCategoryAndRelatedVersatile); if false only deletes catalog or category association</description>
        </attribute>
    </service>
    
    <service name="addProductCategoryCatAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="addProductCategoryCatAssocVersatile" auth="true">
        <description>SCIPIO: Adds a category to catalog or category, attempting to prevent multiple associations (versatile)</description>
        <auto-attributes entity-name="ProductCategory" include="pk" mode="IN" optional="false"/>
        <auto-attributes entity-name="ProdCatalogCategory" include="pk" mode="INOUT" optional="true"/>
        <auto-attributes entity-name="ProdCatalogCategory" include="nonpk" mode="IN" optional="true"/>
        <auto-attributes entity-name="ProductCategoryRollup" include="pk" mode="INOUT" optional="true"/>
        <auto-attributes entity-name="ProductCategoryRollup" include="nonpk" mode="IN" optional="true"/>
        <override name="productCategoryId" optional="false"/>
        <override name="fromDate" optional="true" mode="INOUT"/><!-- may be empty on input -->
    </service>
    
    <service name="copyProductCategoryCatAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="copyProductCategoryCatAssocVersatile" auth="true">
        <description>SCIPIO: Copies a ProductCategory assoc by creating a new assoc (catalog or category assoc), basically a special wrapper around addProductCategoryCatAssocVersatile (versatile)</description>
        <!-- source category and assoc -->
        <auto-attributes entity-name="ProductCategory" include="pk" mode="IN" optional="false"/>
        <auto-attributes entity-name="ProdCatalogCategory" include="pk" mode="INOUT" optional="true"/>
        <auto-attributes entity-name="ProdCatalogCategory" include="nonpk" mode="IN" optional="true"/>
        <auto-attributes entity-name="ProductCategoryRollup" include="pk" mode="INOUT" optional="true"/>
        <auto-attributes entity-name="ProductCategoryRollup" include="nonpk" mode="IN" optional="true"/>
        <!-- service behavior -->
        <attribute name="returnAssocFields" mode="IN" type="String" optional="true" default-value="false">
            <description>If true, the assoc fields for the new assoc will be outputted back to the
                prefix-less fields in addition to the "to_"-prefixed ones (i.e., fromDate will
                be output in both "fromDate" and "to_fromDate").
                If false, the new assoc fields are output only to the "to_"-prefixed fields.
                This can be used in events for switching the target easily after the update.</description>
        </attribute>
        <!-- target catalog or category  -->
        <!-- common -->
        <attribute name="to_fromDate" mode="INOUT" type="Timestamp" optional="true"/><!-- may be left empty -->
        <attribute name="to_sequenceNum" mode="INOUT" type="Long" optional="true"/>
        <!-- ProdCatalogCategory -->
        <attribute name="to_prodCatalogId" mode="INOUT" type="String" optional="true"/>
        <attribute name="to_prodCatalogCategoryTypeId" mode="INOUT" type="String" optional="true"/>
        <!-- ProductCategoryRollup -->
        <attribute name="to_parentProductCategoryId" mode="INOUT" type="String" optional="true"/>
        <attribute name="to_productCategoryId" mode="OUT" type="String" optional="true"/>
        <override name="productCategoryId" optional="false"/>      
    </service>
    
    <service name="moveProductCategoryCatAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="moveProductCategoryCatAssocVersatile" auth="true">
        <description>SCIPIO: Moves a ProductCategory assoc by creating a new assoc (catalog or category assoc) and removing or expiring the original (versatile)</description>
        <implements service="copyProductCategoryCatAssocVersatile"/>
        <attribute name="deleteAssocMode" mode="IN" type="String" optional="true" default-value="remove">
            <description>(remove|expire, default: remove)</description>
        </attribute>     
    </service>
    
    <service name="getProductCategoryExtendedDataVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/category/CategoryServices.xml" invoke="getProductCategoryExtendedDataVersatile" auth="true">
        <description>SCIPIO: Gets extended ProductCategory data (originally written for catalog tree edit form) (versatile)</description>
        <implements service="getProductCategoryContentLocalizedSimpleTextViews"/>
        <attribute name="productCategory" mode="OUT" type="GenericValue" optional="false"/>
    </service>
    
    <!-- PRODUCT -->
    
    <service name="createProductAndCatAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="createProductAndCatAssocVersatile" auth="true">
        <description>SCIPIO: Create a Product and add to category (specialized variant of createProductInCategory) (versatile)</description>
        <implements service="createProduct"/>
        <implements service="addProductToCategory"/>
        <implements service="replaceProductContentLocalizedSimpleTexts"/>
        <attribute name="updateLocalizedTexts" mode="IN" type="Boolean" optional="true" default-value="false"/>
    </service>
    
    <service name="updateProductAndCatAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="updateProductAndCatAssocVersatile" auth="true">
        <description>SCIPIO: Update a Product and category assoc (versatile)</description>
        <implements service="updateProduct"/>
        <implements service="updateProductToCategory"/>
        <implements service="replaceProductContentLocalizedSimpleTexts"/>
        <attribute name="updateLocalizedTexts" mode="IN" type="Boolean" optional="true" default-value="false"/>
    </service>
    
    <service name="deleteProductCatAssocVersatile" default-entity-name="Product" engine="simple"
                location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="deleteProductCatAssocVersatile" auth="true">
        <description>SCIPIO: Delete a Product and category assoc (versatile)</description>
        <implements service="removeProductFromCategory"/>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <attribute name="deleteAssocMode" mode="IN" type="String" optional="true" default-value="remove">
            <description>(remove|expire, default: remove)</description>
        </attribute>
    </service>
    
    <!-- SCIPIO: new (2017-10-20)
        This attempts to delete a Product and related records.
        By default it only removes related records of low importance and relatively "safe" to remove
        such as ProductAttribute, ProductContent and expired ProductCategoryMember records.
        See service attributes for more destructive options.
        TODO: 2017-10-20: partial functionality only -->
    <service name="deleteProductAndRelatedVersatile" default-entity-name="Product" engine="simple"
                location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="deleteProductAndRelatedVersatile" auth="true">
        <description>SCIPIO: Delete a Product record and various related records [WARN: may be dangerous - best-effort] (versatile)</description>
        <auto-attributes include="pk" mode="IN" optional="false"/>
        <attribute name="deleteParentAssocSelect" mode="IN" type="String" optional="true" default-value="all">
            <description>(none|expired|all, default: expired) Controls whether deletes all (default)
                or only expired ProductCategoryMember records to this category's parents</description>
        </attribute>
        <attribute name="deleteChildAssocSelect" mode="IN" type="String" optional="true" default-value="expired">
            <description>(none|expired|all, default: expired) If "expired" (default), removes children assoc records
                that are expired; if "all", removes all such records even if destructive.
                WARN: "all" mode may leave products/categories as orphans!</description>
        </attribute>
        <attribute name="deleteContentRecursive" mode="IN" type="String" optional="true" default-value="all">
            <description>(none|active|all, default: all) Controls whether and which Content records are deleted
                recursively. If none, only the associations are deleted. "active" means non-expired.
                WARN: This function only makes sense if the Content records were meant to be product-specific
                    and not standalone; if standalone content is linked to the product then this may cause collateral damage!</description>
        </attribute>
        <attribute name="deleteAssocProductRecursive" mode="IN" type="String" optional="true" default-value="all">
            <description>(none|active|all, default: all) Controls whether and which associated "to"/"child" Products are deleted
                recursively. If none, only the associations are deleted. "active" means non-expired.
                WARN: Risk of collateral damage</description>
        </attribute>
        <attribute name="deleteSpecialAssocSelect" mode="IN" type="String" optional="true" default-value="none">
            <description>(none|expired|all, default: expired) Special-purpose association deletion mode
                WARN: may currently be destructive (TODO: REVIEW) - "expired" is safe but only if no expired records are still needed.</description>
        </attribute>
    </service>
    
    <service name="deleteProductAndCatAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="deleteProductAndCatAssocVersatile" auth="true">
        <description>SCIPIO: Delete a Product record (if no members) and category assoc (versatile)</description>
        <implements service="deleteProductCatAssocVersatile"/>
        <implements service="deleteProductAndRelatedVersatile"/>
        <attribute name="deleteRecordAndRelated" mode="IN" type="Boolean" optional="true" default-value="true">
            <description>If true, attempts to delete Product (using deleteProductAndRelatedVersatile); if false only deletes catalog or category association</description>
        </attribute>
    </service>
    
    <service name="addProductCatAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="addProductCatAssocVersatile" auth="true">
        <description>SCIPIO: Adds a category to category, attempting to prevent multiple associations (versatile)</description>
        <auto-attributes entity-name="Product" include="pk" mode="IN" optional="false"/>
        <auto-attributes entity-name="ProductCategoryMember" include="pk" mode="INOUT" optional="false"/>
        <auto-attributes entity-name="ProductCategoryMember" include="nonpk" mode="IN" optional="true"/>
        <override name="fromDate" optional="true" mode="INOUT"/><!-- may be empty on input -->
    </service>
    
    <service name="copyProductCatAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="copyProductCatAssocVersatile" auth="true">
        <description>SCIPIO: Copies a Product assoc by creating a new assoc, basically a special wrapper around addProductCatAssocVersatile (versatile)</description>
        <!-- source category and assoc -->
        <auto-attributes entity-name="Product" include="pk" mode="IN" optional="false"/>
        <auto-attributes entity-name="ProductCategoryMember" include="pk" mode="IN" optional="false"/>
        <auto-attributes entity-name="ProductCategoryMember" include="pk" mode="OUT" optional="true"/>
        <!-- service behavior -->
        <attribute name="returnAssocFields" mode="IN" type="String" optional="true" default-value="false">
            <description>If true, the assoc fields for the new assoc will be outputted back to the
                prefix-less fields in addition to the "to_"-prefixed ones (i.e., fromDate will
                be output in both "fromDate" and "to_fromDate").
                If false, the new assoc fields are output only to the "to_"-prefixed fields.
                This can be used in events for switching the target easily after the update.</description>
        </attribute>
        <!-- target -->
        <attribute name="to_productCategoryId" mode="INOUT" type="String" optional="false"/>
        <attribute name="to_fromDate" mode="INOUT" type="Timestamp" optional="false"/><!-- may be left empty -->
        <attribute name="to_sequenceNum" mode="INOUT" type="Long" optional="false"/>
        <attribute name="to_productId" mode="OUT" type="String" optional="false"/>
        <override name="productId" optional="false"/>      
    </service>
    
    <service name="moveProductCatAssocVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="moveProductCatAssocVersatile" auth="true">
        <description>SCIPIO: Moves a Product assoc by creating a new assoc and removing or expiring the original (versatile)</description>
        <implements service="copyProductCatAssocVersatile"/>
        <attribute name="deleteAssocMode" mode="IN" type="String" optional="true" default-value="remove">
            <description>(remove|expire, default: remove)</description>
        </attribute>     
    </service>
    
    <service name="getProductExtendedDataVersatile" engine="simple"
                location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="getProductExtendedDataVersatile" auth="true">
        <description>SCIPIO: Gets extended Product data (originally written for catalog tree edit form) (versatile)</description>
        <implements service="getProductContentLocalizedSimpleTextViews"/>
        <attribute name="product" mode="OUT" type="GenericValue" optional="false"/>
    </service>
    
    <!-- ======================================== -->
    <!-- SCIPIO: New Services (novel functionality) -->
    <!-- ======================================== -->
    
    <!-- SCIPIO: New service to build catalog/category/product tree-like structure according to the library being passed (currently jsTree supported only) -->
    <service name="buildCatalogTree" engine="java" default-entity-name="ProdCatalog" location="com.ilscipio.scipio.product.category.CategoryServices" invoke="buildCatalogTree">
        <description>SCIPIO: Builds a tree containing catalogs, categories and products using catalogs as starting point</description>
        <auto-attributes mode="IN" include="pk" optional="false" />
        <attribute name="library" mode="IN" type="String" optional="true" default-value="jsTree" />
        <attribute name="mode" mode="IN" type="String" optional="true" default-value="full" />
        <attribute name="state" mode="IN" type="Map" optional="true">
            <description>Map of state attributes for top node: opened, selected, disabled. (added 2017-10-11)</description>
        </attribute>
        <attribute name="categoryStates" mode="IN" type="Map" optional="true">
            <description>Map of categoryIds to maps of state attributes (added 2017-10-11).
                WARN: can't specify specific path for many-parents</description>
        </attribute>
        <attribute name="useCategoryCache" mode="IN" type="Boolean" optional="true"/>
        <attribute name="useProductCache" mode="IN" type="Boolean" optional="true"/>
        <attribute name="includeEntityData" mode="IN" type="Map" optional="true">
            <description>Map of names to entity-like field names to include in each tree item as "[name]Entity" entries (e.g. "productEntity").
                Available names: prodCatalog, productStoreCatalog, productCategory, productCategoryRollup, prodCatalogCategory, product, productCategoryMember
                Map values may be:
                * Boolean or boolean as String - true means include all fields, false none
                * Collection of field names to include
                * Map of options. Supported keys:
                  * use - boolean, whether to use
                  * inclFields - Collection of field names to include
                  * exclFields - Collection of field names to exclude
            </description>
        </attribute>
        <attribute name="includeAllEntityData" mode="IN" type="Boolean" optional="true" default-value="false">
            <description>If true, simply includes all available entity data; includeEntityData can still be set to specialize selection.</description>
        </attribute>
        <attribute name="maxProductsPerCat" mode="IN" type="Integer" optional="true"/><!-- default: no limit (same as -1) -->
        <attribute name="includeEmptyTop" mode="IN" type="Boolean" optional="true" default-value="false">
            <description>If false (default), empty catalog or top node is omitted</description>
        </attribute>
        <attribute name="productStoreCatalog" mode="IN" type="GenericValue" optional="true"/>
        <attribute name="categoryEntityOutMap" mode="INOUT" type="Map" optional="true">
            <description>Map of categoryIds to ProductCategory GenericValues; if non-null, 
                all categories found are added to this map (needed to avoid performing expensive traversal twice)</description>
        </attribute>
        <attribute name="treeList" mode="OUT" type="List" optional="false" />
    </service>
    
    <!-- SCIPIO: Service to discontinue a product 
        NOTE: This is redundant if solr ECAs are enabled and should not be used in that case. -->    
    <service name="discontinueProduct" engine="java" auth="true"
        location="com.ilscipio.scipio.product.product.ProductServices" invoke="setProductToSalesDiscontinued">
        <description>SCIPIO: Discontinues (manually disables) a product and updates solr.</description>
        <attribute name="productId" mode="IN" type="String" />
    </service>

    <service name="generateProductAlternativeUrlsCore" engine="java" auth="true"
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="generateProductAlternativeUrls">
        <description>SCIPIO: Re-generates alternative urls for product based on the ruleset outlined in SeoConfig.xml [core only - no perm check]</description>
        <!-- WARN: DO NOT EXPOSE AS EVENT - no perm check -->
        <!--<permission-service service-name="productGenericPermission" main-action="UPDATE"/>-->
        <!-- can pass either productId or product instance or GenericPk -->
        <attribute name="productId" mode="IN" type="String" optional="true"/>
        <attribute name="product" mode="IN" type="GenericEntity" optional="true"/>
        <attribute name="doChildProducts" mode="IN" type="Boolean" optional="true" default-value="false">
            <description>If true and virtual, also updates the variants (NOTE: parent and children done in the same transaction)</description>
        </attribute>
        <attribute name="includeVariant" mode="IN" type="Boolean" optional="true" default-value="true">
            <description>Does NOT apply self, only consulted if doChildProducts true (need mostly for consistency with callers)</description>
        </attribute>
        <attribute name="skipProductIds" mode="IN" type="Collection" optional="true"/>
        <attribute name="replaceExisting" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="removeOldLocales" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="genFixedIds" type="Boolean" mode="IN" optional="true" default-value="false">
            <description>Generate fixed IDs with pattern "${idTrim}-ALT${localeStrUp}" (idTrim is id trimmed so total length under 20), mainly for demo data generation - high risk of failure if set to true in any other case</description>
        </attribute>
        <attribute name="fixedIdPat" type="String" mode="IN" optional="true"/>
        <attribute name="webSiteId" type="String" mode="IN" optional="true">
                <description>Website for URL generation configuration via SeoConfig.xml</description>
        </attribute>
        <attribute name="mainContentId" mode="OUT" type="String" optional="true"/>
        <attribute name="numUpdated" mode="OUT" type="Integer" optional="true"/>
        <attribute name="numSkipped" mode="OUT" type="Integer" optional="true"/>
        <attribute name="numError" mode="OUT" type="Integer" optional="true"/>
        <attribute name="visitedProductIds" mode="OUT" type="Set" optional="true"/>
    </service>
    <service name="generateProductAlternativeUrls" engine="java" auth="true"
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="generateProductAlternativeUrls">
        <description>SCIPIO: Re-generates alternative urls for product based on the ruleset outlined in SeoConfig.xml
            WARN/TODO?: this service does not run for variant or other child products</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <implements service="generateProductAlternativeUrlsCore"/>
    </service>
    <service name="generateProductCategoryAlternativeUrlsCore" engine="java" auth="true"
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="generateProductCategoryAlternativeUrls">
        <description>SCIPIO: Re-generates alternative urls for category based on the ruleset outlined in SeoConfig.xml [core only - no perm check]</description>
        <!-- WARN: DO NOT EXPOSE AS EVENT - no perm check -->
        <!--<permission-service service-name="productGenericPermission" main-action="UPDATE"/>-->
        <!-- can pass either productCategoryId or productCategory instance or GenericPk -->
        <attribute name="productCategoryId" mode="IN" type="String" optional="true"/>
        <attribute name="productCategory" mode="IN" type="GenericEntity" optional="true"/>
        <attribute name="replaceExisting" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="removeOldLocales" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="genFixedIds" type="Boolean" mode="IN" optional="true" default-value="false">
            <description>Generate fixed IDs with pattern "${idTrim}-ALT${localeStrUp}" (idTrim is id trimmed so total length under 20), mainly for demo data generation - high risk of failure if set to true in any other case</description>
        </attribute>
        <attribute name="fixedIdPat" type="String" mode="IN" optional="true"/>
        <attribute name="webSiteId" type="String" mode="IN" optional="true">
            <description>Website for URL generation configuration via SeoConfig.xml</description>
        </attribute>
        <attribute name="mainContentId" mode="OUT" type="String" optional="true"/>
        <attribute name="categoryUpdated" mode="OUT" type="Boolean" optional="true"/>
    </service>
    <service name="generateProductCategoryAlternativeUrls" engine="java" auth="true"
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="generateProductCategoryAlternativeUrls">
        <description>SCIPIO: Re-generates alternative urls for category based on the ruleset outlined in SeoConfig.xml</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <implements service="generateProductCategoryAlternativeUrlsCore"/>
    </service>
    <!-- TODO?: future, no replacement for stock yet
    <service name="generateContentAlternativeUrls" engine="java" auth="true"
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="generateAlternativeProductUrls">
        <description>SCIPIO: Generates alternative urls for single conent based on the ruleset outlined in SeoConfig.xml</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <attribute name="contentId" mode="IN" type="String" optional="false"/>
        <attribute name="replaceExisting" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="removeOldLocales" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="mainContentId" mode="OUT" type="String" optional="true"/>
    </service>
    -->
    <service name="websiteAlternativeUrlsCatalogInterface" engine="interface">
        <attribute name="webSiteId" type="String" mode="IN" optional="true">
            <description>May pass webSiteId OR productStoreId</description>
        </attribute>
        <attribute name="productStoreId" type="String" mode="IN" optional="true">
            <description>May pass webSiteId OR productStoreId</description>
        </attribute>
        <attribute name="prodCatalogId" type="String" mode="IN" optional="true">
            <description>Limits to a specific catalog</description>
        </attribute>
        <attribute name="prodCatalogIdList" type="List" mode="IN" optional="true">
            <description>Limits to specific catalogs</description>
        </attribute>
    </service>
    <service name="generateWebsiteAlternativeUrls" engine="java" auth="true"
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="generateWebsiteAlternativeUrls" transaction-timeout="72000">
        <description>SCIPIO: Re-generates alternative urls for store/website based on ruleset outlined in SeoConfig.xml - replaces old generateMissingSeoUrlForWebsite service
            FIXME?: this can include variant products, but does not yet recognize other ProductAssoc types</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <implements service="websiteAlternativeUrlsCatalogInterface"/>
        <attribute name="typeGenerate" type="List" mode="IN" optional="true" default-value="[all]">
            <description>Currently supports: product, category, all.</description>
        </attribute>
        <attribute name="replaceExisting" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="removeOldLocales" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="includeVariant" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="preventDuplicates" type="Boolean" mode="IN" optional="true" default-value="true">
            <description>Tries to prevent regenerating the same URLs for the same categories and products more than once</description>
        </attribute>
        <attribute name="useCache" type="Boolean" mode="IN" optional="true" default-value="false">
            <description>May be slightly faster iterating if true, but not recommended</description>
        </attribute>
        <attribute name="genFixedIds" type="Boolean" mode="IN" optional="true" default-value="false">
            <description>Generate fixed IDs with pattern "${id}-ALT", mainly for demo data generation - high risk of failure if set to true in any other case</description>
        </attribute>
        <attribute name="prodFixedIdPat" type="String" mode="IN" optional="true"/>
        <attribute name="catFixedIdPat" type="String" mode="IN" optional="true"/>
        <attribute name="sepTrans" type="Boolean" mode="IN" optional="true" default-value="false"/>
    </service>
    <service name="generateAllAlternativeUrls" engine="java" auth="true"
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="generateAllAlternativeUrls" transaction-timeout="72000">
        <description>SCIPIO: Re-generates alternative urls for ALL stores/websites based on ruleset outlined in SeoConfig.xml</description>
        <!-- NOTE: This service may be unable to use WebSite-specific configuration such as WebSite-specific SeoConfig.xml files.
            Currently this is only an issue if have more than one SeoConfig.xml configurations. -->
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <attribute name="typeGenerate" type="List" mode="IN" optional="true" default-value="[all]">
            <description>Currently supports: product, category, all.</description>
        </attribute>
        <attribute name="replaceExisting" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="removeOldLocales" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="includeVariant" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="useCache" type="Boolean" mode="IN" optional="true" default-value="false">
            <description>May be slightly faster iterating if true, but not recommended</description>
        </attribute>
        <attribute name="genFixedIds" type="Boolean" mode="IN" optional="true" default-value="false">
            <description>Generate fixed IDs with pattern "${id}-ALT", mainly for demo data generation - high risk of failure if set to true in any other case</description>
        </attribute>
        <attribute name="prodFixedIdPat" type="String" mode="IN" optional="true"/>
        <attribute name="catFixedIdPat" type="String" mode="IN" optional="true"/>
        <attribute name="sepTrans" type="Boolean" mode="IN" optional="true" default-value="false"/>
    </service>
    
    <!-- WARN: DO NOT EXPOSE AS EVENT - no perm check -->
    <service name="removeProductAlternativeUrlsCore" engine="java" auth="true"
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="removeProductAlternativeUrls">
        <description>SCIPIO: Removes alternative urls for product [core only - no perm check]</description>
        <!--<permission-service service-name="productGenericPermission" main-action="UPDATE"/>-->
        <!-- can pass either productId or product instance or GenericPk -->
        <attribute name="productId" mode="IN" type="String" optional="true"/>
        <attribute name="product" mode="IN" type="GenericEntity" optional="true"/>
        <attribute name="doChildProducts" mode="IN" type="Boolean" optional="true" default-value="false">
            <description>If true and virtual, also updates the variants (NOTE: parent and children done in the same transaction)</description>
        </attribute>
        <attribute name="includeVariant" mode="IN" type="Boolean" optional="true" default-value="true">
            <description>Does NOT apply self, only consulted if doChildProducts true (need mostly for consistency with callers)</description>
        </attribute>
        <attribute name="skipProductIds" mode="IN" type="Collection" optional="true"/>
        <attribute name="numUpdated" mode="OUT" type="Integer" optional="true"/>
        <attribute name="numSkipped" mode="OUT" type="Integer" optional="true"/>
        <attribute name="numError" mode="OUT" type="Integer" optional="true"/>
        <attribute name="visitedProductIds" mode="OUT" type="Set" optional="true"/>
    </service>
    <service name="removeProductAlternativeUrls" engine="java" auth="true"
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="removeProductAlternativeUrls">
        <description>SCIPIO: Removes alternative urls for product</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <implements service="removeProductAlternativeUrlsCore"/>
    </service>
    <!-- WARN: DO NOT EXPOSE AS EVENT - no perm check -->
    <service name="removeProductCategoryAlternativeUrlsCore" engine="java" auth="true"
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="removeProductCategoryAlternativeUrls">
        <description>SCIPIO: Remove alternative urls for category [core only - no perm check]</description>
        <!--<permission-service service-name="productGenericPermission" main-action="UPDATE"/>-->
        <!-- can pass either productCategoryId or productCategory instance or GenericPk -->
        <attribute name="productCategoryId" mode="IN" type="String" optional="true"/>
        <attribute name="productCategory" mode="IN" type="GenericEntity" optional="true"/>
        <attribute name="categoryUpdated" mode="OUT" type="Boolean" optional="true"/>
    </service>
    <service name="removeProductCategoryAlternativeUrls" engine="java" auth="true"
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="removeProductCategoryAlternativeUrls">
        <description>SCIPIO: Remove alternative urls for category</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <implements service="removeProductCategoryAlternativeUrlsCore"/>
    </service>
    
    <service name="removeWebsiteAlternativeUrls" engine="java" auth="true"
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="removeWebsiteAlternativeUrls" transaction-timeout="72000">
        <description>SCIPIO: Removes alternative URLs for the website
            FIXME?: this can include variant products, but does not yet recognize other ProductAssoc types</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <implements service="websiteAlternativeUrlsCatalogInterface"/>
        <attribute name="targetTypes" type="List" mode="IN" optional="true" default-value="[all]">
            <description>Currently supports: product, category, all.</description>
        </attribute>
        <attribute name="includeVariant" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="sepTrans" type="Boolean" mode="IN" optional="true" default-value="false"/>
    </service>
    <service name="removeAllAlternativeUrls" engine="java" auth="true"
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="removeAllAlternativeUrls" transaction-timeout="72000">
        <description>SCIPIO: Removes alternative urls from all products and categories</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <attribute name="targetTypes" type="List" mode="IN" optional="true" default-value="[all]">
            <description>Currently supports: product, category, all.</description>
        </attribute>
        <attribute name="includeVariant" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="sepTrans" type="Boolean" mode="IN" optional="true" default-value="false"/>
    </service>
    
    <service name="generateWebsiteAlternativeUrlSitemapFiles" engine="java" 
        location="com.ilscipio.scipio.product.seo.sitemap.SitemapServices" invoke="generateWebsiteAlternativeUrlSitemapFiles" 
        transaction-timeout="72000">
        <description>Creates sitemaps in filesystem using product/category alternative URLs, for WebSite, using configurations from sitemaps.properties</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <attribute name="webSiteId" type="String" mode="IN" optional="false"/>
        <attribute name="useCache" type="Boolean" mode="IN" optional="true" default-value="false">
            <description>May be slightly faster iterating if true, but not recommended</description>
        </attribute>
    </service>
    <service name="generateAllAlternativeUrlSitemapFiles" engine="java" 
        location="com.ilscipio.scipio.product.seo.sitemap.SitemapServices" invoke="generateAllAlternativeUrlSitemapFiles" 
        transaction-timeout="72000">
        <description>Creates sitemaps in filesystem using product/category alternative URLs, for all WebSites that have it enabled, using configurations from sitemaps.properties</description>
        <permission-service service-name="productGenericPermission" main-action="UPDATE"/>
        <attribute name="useCache" type="Boolean" mode="IN" optional="true" default-value="false">
            <description>May be slightly faster iterating if true, but not recommended</description>
        </attribute>
    </service>

    <service name="exportAlternativeUrlsEntityXmlOptionsInterface" engine="interface">
        <description>Traversal options for alt URL entity XML services</description>
        <attribute name="typeExport" type="List" mode="IN" optional="true" default-value="[all]">
            <description>Currently supports: product, category, all.</description>
        </attribute>
        <attribute name="includeVariant" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="preventDuplicates" type="Boolean" mode="IN" optional="true" default-value="true">
            <description>Tries to prevent regenerating the same URLs for the same categories and products more than one</description>
        </attribute>
        <attribute name="useCache" type="Boolean" mode="IN" optional="true" default-value="false">
            <description>May be slightly faster iterating if true, but not recommended</description>
        </attribute>
        <attribute name="linePrefix" type="String" mode="IN" optional="true">
            <description>String prefix for each line, typically an indent</description>
        </attribute>
        <attribute name="recordGrouping" type="String" mode="IN" optional="true">
            <description>Supported values: NONE/MAJOR_OBJECT (default), ENTITY_TYPE</description>
        </attribute>
    </service>
    <service name="exportAlternativeUrlsEntityXmlWriterInterface" engine="interface">
        <description>Output options for alt URL entity XML services</description>
        <attribute name="asString" type="Boolean" mode="IN" optional="true" default-value="false">
            <description>If true, will return result as a string in outString in addition
                to outputting to the passed outWriter if any was passed (if none, also returns a new StringWriter)</description>
        </attribute>
        <attribute name="outFlush" type="Boolean" mode="IN" optional="true" default-value="true"/>
        <attribute name="outWriter" type="java.io.Writer" mode="INOUT" optional="true">
            <description>Writer to output the formatted XML records to</description>
        </attribute>
        <attribute name="outString" type="String" mode="OUT" optional="true" allow-html="any">
            <description>If this is set to "Y" or "true" on input and the outWriter is either
                not set or a StringWriter, this will contain the output as a string upon success.</description>
        </attribute>
    </service>
    <service name="exportWebsiteAlternativeUrlsEntityXml" engine="java" auth="true"
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="exportWebsiteAlternativeUrlsEntityXml" transaction-timeout="72000">
        <description>Exports alternative urls for given website to entity XML data out writer</description>
        <permission-service service-name="productGenericPermission" main-action="VIEW"/>
        <implements service="exportAlternativeUrlsEntityXmlOptionsInterface"/>
        <implements service="exportAlternativeUrlsEntityXmlWriterInterface"/>
        <implements service="websiteAlternativeUrlsCatalogInterface"/>
    </service>
    <service name="exportAllAlternativeUrlsEntityXml" engine="java" 
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="exportAllAlternativeUrlsEntityXml" 
        transaction-timeout="72000">
        <description>Export all alternative URLs into a single output to entity XML data out writer</description>
        <permission-service service-name="productGenericPermission" main-action="VIEW"/>
        <implements service="exportAlternativeUrlsEntityXmlOptionsInterface"/>
        <implements service="exportAlternativeUrlsEntityXmlWriterInterface"/>
    </service>
    <service name="exportWebsiteAlternativeUrlsEntityXmlFile" engine="java" 
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="exportWebsiteAlternativeUrlsEntityXmlFile" 
        transaction-timeout="72000">
        <description>Exports alternative urls for given website or all websites to entity XML data file</description>
        <permission-service service-name="productGenericPermission" main-action="VIEW"/>
        <implements service="exportAlternativeUrlsEntityXmlOptionsInterface"/>
        <implements service="websiteAlternativeUrlsCatalogInterface"/>
        <attribute name="outFile" type="String" mode="IN" optional="false">
            <description>Should begin with component://</description>
        </attribute>
        <attribute name="templateType" type="String" mode="IN" optional="false">
            <description>Supported: comment-delimited (TODO: ftl)</description>
        </attribute>
        <attribute name="dataBeginMarker" type="String" mode="IN" optional="true" allow-html="any">
            <description>All file contents before this marker is copied from the template to the outFile</description>
        </attribute>
        <attribute name="templateFile" type="String" mode="IN" optional="true">
            <description>Should begin with component://</description>
        </attribute>
    </service>
    <service name="exportAlternativeUrlsEntityXmlFileFromConfig" engine="java" 
        location="com.ilscipio.scipio.product.seo.SeoCatalogServices" invoke="exportAlternativeUrlsEntityXmlFileFromConfig" 
        transaction-timeout="72000">
        <description>Exports alternative urls for given website or all websites to entity XML data file,
            from config in seo-urls.properties files</description>
        <permission-service service-name="productGenericPermission" main-action="VIEW"/>
        <attribute name="configName" type="String" mode="IN" optional="true">
            <description>Name of config in seo-urls.properties, in format: seourl.datafile.[configName].[params]</description>
        </attribute>
        <attribute name="configNameList" type="List" mode="IN" optional="true">
            <description>List of config names in seo-urls.properties, in format: seourl.datafile.[configName].[params]</description>
        </attribute>
    </service>

    <!-- SCIPIO: 2.1.0: Added for testing purposes (TODO: add filters) -->
    <service name="precacheProductContentWrapper" engine="java"
             location="com.ilscipio.scipio.product.product.ProductServices$PrecacheProductContentWrapper" invoke="exec">
        <description>Pre-caches ProductContentWrapper records for all found products</description>
        <attribute name="productContentTypeIdList" type="List" mode="IN" optional="false"/>
        <attribute name="partyIdList" type="List" mode="IN" optional="true"/>
        <attribute name="roleTypeIdList" type="List" mode="IN" optional="true"/>
        <attribute name="encoderTypeList" type="List" mode="IN" optional="true"/>
        <attribute name="mimeTypeIdList" type="List" mode="IN" optional="true"/>
        <attribute name="localeList" type="List" mode="IN" optional="true"/>
    </service>

    <service name="createUpdateProductSimpleTextContentForAlternateLocale" engine="java"
             location="com.ilscipio.scipio.product.product.ProductServices$CreateUpdateProductSimpleTextContentForAlternateLocale" invoke="exec">
        <description>Creates or updates simple text content for alternate locale for product
            - supports either explicit contentId or relying on localeString to find record to update
            - WARN: For high-level operation, use replaceContentLocalizedSimpleTexts</description>
        <implements service="createUpdateSimpleTextContentForAlternateLocale"/>
        <attribute name="productId" type="String" mode="IN" optional="false"/>
        <attribute name="productContentTypeId" type="String" mode="IN" optional="false"/>
        <attribute name="productContentFromDate" type="Timestamp" mode="INOUT" optional="true"/>
        <!-- DEV NOTE: Be careful adding parameters for ProductContent since they may end up passed to ContentAssoc instead -->
    </service>

    <service name="createUpdateProductCategorySimpleTextContentForAlternateLocale" engine="java"
             location="com.ilscipio.scipio.product.category.CategoryServices$CreateUpdateProductCategorySimpleTextContentForAlternateLocale" invoke="exec">
        <description>Creates or updates simple text content for alternate locale for product category
            - supports either explicit contentId or relying on localeString to find record to update
            - WARN: For high-level operation, use replaceContentLocalizedSimpleTexts</description>
        <implements service="createUpdateSimpleTextContentForAlternateLocale"/>
        <attribute name="productCategoryId" type="String" mode="IN" optional="false"/>
        <attribute name="prodCatContentTypeId" type="String" mode="IN" optional="false"/>
        <attribute name="prodCatContentFromDate" type="Timestamp" mode="INOUT" optional="true"/>
        <!-- DEV NOTE: Be careful adding parameters for ProductContent since they may end up passed to ContentAssoc instead -->
    </service>
</services>