Improved: Convert TaxAuthority services mini-lang to groovyDSL (OFBIZ-13082)

Convert the following services:
   * createPartyTaxAuthInfo
   * updatePartyTaxAuthInfo
   * createCustomerTaxAuthInfo
diff --git a/applications/accounting/minilang/tax/TaxAuthorityServices.xml b/applications/accounting/minilang/tax/TaxAuthorityServices.xml
deleted file mode 100644
index 4fca860..0000000
--- a/applications/accounting/minilang/tax/TaxAuthorityServices.xml
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License.  You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied.  See the License for the
-specific language governing permissions and limitations
-under the License.
--->
-
-<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xmlns="http://ofbiz.apache.org/Simple-Method" xsi:schemaLocation="http://ofbiz.apache.org/Simple-Method http://ofbiz.apache.org/dtds/simple-methods.xsd">
-
-    <!-- TaxAuthorityCategory methods -->
-    <simple-method method-name="deleteTaxAuthorityCategory" short-description="delete a TaxAuthorityCategory">
-        <set field="taxAuthorityRateProductMap.taxAuthGeoId" from-field="parameters.taxAuthGeoId"/>
-        <set field="taxAuthorityRateProductMap.taxAuthPartyId" from-field="parameters.taxAuthPartyId"/>
-        <set field="taxAuthorityRateProductMap.productCategoryId" from-field="parameters.productCategoryId"/>
-        <find-by-and entity-name="TaxAuthorityRateProduct" map="taxAuthorityRateProductMap" list="taxAuthorityRateProductList"/>
-        <if-empty field="taxAuthorityRateProductList">
-            <entity-one entity-name="TaxAuthorityCategory" value-field="lookedUpValue"/>
-            <remove-value value-field="lookedUpValue"/>
-            <else>
-                <add-error>
-                    <fail-property resource="AccountingUiLabels" property="AccountingTaxAuthorityRateProductUseThisProductCategory"/>
-                </add-error>
-            </else>
-        </if-empty>
-        <check-errors/>
-    </simple-method>
-
-    <!-- PartyTaxAuthInfo methods -->
-    <simple-method method-name="createPartyTaxAuthInfo" short-description="create a PartyTaxAuthInfo">
-        <call-simple-method method-name="validatePartyTaxIdInline"/>
-
-        <entity-one entity-name="TaxAuthority" value-field="taxAuth"/>
-        <if-empty field="taxAuth">
-            <add-error>
-                <fail-property resource="PartyUiLabels" property="PartyTaxAuthPartyAndGeoNotAvailable"/>
-            </add-error>
-        </if-empty>
-
-        <!-- done checking preliminary constraints, see if there are any errors -->
-        <check-errors/>
-
-        <make-value entity-name="PartyTaxAuthInfo" value-field="newEntity"/>
-        <set-pk-fields map="parameters" value-field="newEntity"/>
-        <if-empty field="newEntity.fromDate"><now-timestamp field="newEntity.fromDate"/></if-empty>
-        <set-nonpk-fields map="parameters" value-field="newEntity"/>
-
-        <create-value value-field="newEntity"/>
-    </simple-method>
-    <simple-method method-name="updatePartyTaxAuthInfo" short-description="update a PartyTaxAuthInfo">
-        <call-simple-method method-name="validatePartyTaxIdInline"/>
-
-        <!-- done checking preliminary constraints, see if there are any errors -->
-        <check-errors/>
-
-        <entity-one entity-name="PartyTaxAuthInfo" value-field="lookedUpValue"/>
-        <set-nonpk-fields map="parameters" value-field="lookedUpValue"/>
-        <store-value value-field="lookedUpValue"/>
-    </simple-method>
-    <simple-method method-name="validatePartyTaxIdInline" short-description="validatePartyTaxIdInline">
-        <!-- validate the partyTaxId based on TaxAuthority.taxIdFormatPattern if not empty -->
-        <!-- If the party validated is in the UE, we could to a better job using the SOAP service from http://ec.europa.eu/taxation_customs/vies/faqvies.do#item16 -->
-        <entity-one entity-name="TaxAuthority" value-field="taxAuthority"/>
-        <if>
-            <condition>
-                <and>
-                    <not><if-empty field="taxAuthority.taxIdFormatPattern"/></not>
-                    <not><if-empty field="parameters.partyTaxId"/></not>
-                    <not><if-regexp field="parameters.partyTaxId" expr="${taxAuthority.taxIdFormatPattern}"/></not>
-                </and>
-            </condition>
-            <then>
-                <add-error>
-                    <fail-property resource="AccountingErrorUiLabels" property="AccountingTaxIdInvalidFormat"/>
-                </add-error>
-            </then>
-        </if>
-    </simple-method>
-
-    <simple-method method-name="createCustomerTaxAuthInfo" short-description="Create a Customer PartyTaxAuthInfo">
-        <script>groovy:
-            taxAuthPartyGeoIds = parameters.get("taxAuthPartyGeoIds")
-            parameters.put("taxAuthPartyId", taxAuthPartyGeoIds.substring(0, taxAuthPartyGeoIds.indexOf("::")))
-            parameters.put("taxAuthGeoId", taxAuthPartyGeoIds.substring(taxAuthPartyGeoIds.indexOf("::") + 2))
-        </script>
-        <set-service-fields service-name="createPartyTaxAuthInfo" map="parameters" to-map="createPartyTaxAuthInfoMap"/>
-        <call-service service-name="createPartyTaxAuthInfo" in-map-name="createPartyTaxAuthInfoMap" include-user-login="true"/>
-    </simple-method>
-</simple-methods>
diff --git a/applications/accounting/servicedef/services_tax.xml b/applications/accounting/servicedef/services_tax.xml
index 2718357..ca31d6c 100644
--- a/applications/accounting/servicedef/services_tax.xml
+++ b/applications/accounting/servicedef/services_tax.xml
@@ -119,11 +119,10 @@
         <auto-attributes include="pk" mode="IN" optional="false"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
     </service>
-    <service name="deleteTaxAuthorityCategory" default-entity-name="TaxAuthorityCategory" engine="simple" auth="true"
-        location="component://accounting/minilang/tax/TaxAuthorityServices.xml" invoke="deleteTaxAuthorityCategory">
+    <service name="deleteTaxAuthorityCategory" default-entity-name="TaxAuthorityCategory" engine="entity-auto" invoke="delete" auth="true">
         <description>Delete TaxAuthorityCategory</description>
         <permission-service service-name="acctgBasePermissionCheck" main-action="DELETE"/>
-        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="pk" mode="IN"/>
     </service>
 
     <!-- TaxAuthorityGlAccount -->
@@ -165,19 +164,19 @@
     </service>
 
     <!-- PartyTaxAuthInfo -->
-    <service name="createPartyTaxAuthInfo" default-entity-name="PartyTaxAuthInfo" engine="simple" auth="true"
-        location="component://accounting/minilang/tax/TaxAuthorityServices.xml" invoke="createPartyTaxAuthInfo">
+    <service name="createPartyTaxAuthInfo" default-entity-name="PartyTaxAuthInfo" engine="groovy" auth="true"
+        location="component://accounting/src/main/groovy/org/apache/ofbiz/accounting/tax/TaxAuthorityServicesScript.groovy" invoke="createPartyTaxAuthInfo">
         <description>Create PartyTaxAuthInfo</description>
         <permission-service service-name="acctgBasePermissionCheck" main-action="CREATE"/>
-        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="pk" mode="IN"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
         <override name="fromDate" optional="true"/>
     </service>
-    <service name="updatePartyTaxAuthInfo" default-entity-name="PartyTaxAuthInfo" engine="simple" auth="true"
-        location="component://accounting/minilang/tax/TaxAuthorityServices.xml" invoke="updatePartyTaxAuthInfo">
+    <service name="updatePartyTaxAuthInfo" default-entity-name="PartyTaxAuthInfo" engine="groovy" auth="true"
+        location="component://accounting/src/main/groovy/org/apache/ofbiz/accounting/tax/TaxAuthorityServicesScript.groovy" invoke="updatePartyTaxAuthInfo">
         <description>Update PartyTaxAuthInfo</description>
         <permission-service service-name="acctgBasePermissionCheck" main-action="UPDATE"/>
-        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="pk" mode="IN"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
     </service>
     <service name="deletePartyTaxAuthInfo" default-entity-name="PartyTaxAuthInfo" engine="entity-auto" invoke="delete" auth="true">
@@ -186,12 +185,12 @@
         <auto-attributes include="pk" mode="IN" optional="false"/>
     </service>
 
-    <service name="createCustomerTaxAuthInfo" default-entity-name="PartyTaxAuthInfo" engine="simple" auth="true"
-        location="component://accounting/minilang/tax/TaxAuthorityServices.xml" invoke="createCustomerTaxAuthInfo">
+    <service name="createCustomerTaxAuthInfo" default-entity-name="PartyTaxAuthInfo" engine="groovy" auth="true"
+        location="component://accounting/src/main/groovy/org/apache/ofbiz/accounting/tax/TaxAuthorityServicesScript.groovy" invoke="createCustomerTaxAuthInfo">
         <description>Create Customer PartyTaxAuthInfo</description>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
-        <attribute name="partyId" type="String" mode="IN" optional="false"/>
-        <attribute name="taxAuthPartyGeoIds" type="String" mode="IN" optional="false"/>
+        <attribute name="partyId" type="String" mode="IN"/>
+        <attribute name="taxAuthPartyGeoIds" type="String" mode="IN"/>
         <attribute name="fromDate" type="String" mode="IN" optional="true"/>
     </service>
 
diff --git a/applications/accounting/src/main/groovy/org/apache/ofbiz/accounting/tax/TaxAuthorityServicesScript.groovy b/applications/accounting/src/main/groovy/org/apache/ofbiz/accounting/tax/TaxAuthorityServicesScript.groovy
new file mode 100644
index 0000000..8ce21a8
--- /dev/null
+++ b/applications/accounting/src/main/groovy/org/apache/ofbiz/accounting/tax/TaxAuthorityServicesScript.groovy
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+*/
+package org.apache.ofbiz.accounting.tax
+
+import org.apache.ofbiz.base.util.UtilDateTime
+import org.apache.ofbiz.entity.GenericValue
+
+import java.util.regex.Pattern
+
+/**
+ * create a PartyTaxAuthInfo
+ * @return Success, error response otherwise.
+ */
+Map createPartyTaxAuthInfo() {
+    GenericValue taxAuthority = from('TaxAuthority').where(parameters).queryOne()
+    if (!taxAuthority) {
+        return error(label('PartyUiLabels', 'PartyTaxAuthPartyAndGeoNotAvailable'))
+    }
+    String errorMesg = validatePartyTaxIdInline()
+    if (errorMesg) {
+        return error(errorMesg)
+    }
+    GenericValue partyAuthInfo = makeValue('PartyTaxAuthInfo', parameters)
+    partyAuthInfo.fromDate = partyAuthInfo.fromDate ?: UtilDateTime.nowTimestamp()
+    partyAuthInfo.create()
+    return success()
+}
+/**
+ * update a PartyTaxAuthInfo
+ * @return Success, error response otherwise.
+ */
+Map updatePartyTaxAuthInfo() {
+    String errorMesg = validatePartyTaxIdInline()
+    if (errorMesg) {
+        return error(errorMesg)
+    }
+    GenericValue partyAuthInfo = from('PartyTaxAuthInfo').where(parameters).queryOne()
+    if (partyAuthInfo) {
+        partyAuthInfo.setNonPKFields(parameters, false)
+        partyAuthInfo.store()
+    }
+    return success()
+}
+
+/**
+ * @return error message if party tax id not match the tax pattern
+ */
+String validatePartyTaxIdInline() {
+    GenericValue taxAuthority = from('TaxAuthority').where(parameters).queryOne()
+    if (taxAuthority && taxAuthority.taxIdFormatPattern && parameters.partyTaxId &&
+            !Pattern.compile(taxAuthority.taxIdFormatPattern).matcher(parameters.partyTaxId).find()) {
+        return label('AccountingErrorUiLabels', 'AccountingTaxIdInvalidFormat', [parameters: parameters, taxAuthority: taxAuthority])
+    }
+    return ''
+}
+
+/**
+ * Create a Customer PartyTaxAuthInfo
+ * @return Success, error response otherwise.
+ */
+Map createCustomerTaxAuthInfo() {
+    List taxAuthPartyGeoIds = org.apache.ofbiz.base.util.StringUtil.split(parameters.taxAuthPartyGeoIds, '::')
+    parameters.taxAuthPartyId = taxAuthPartyGeoIds[0]
+    parameters.taxAuthGeoId = taxAuthPartyGeoIds[1]
+    run service: 'createPartyTaxAuthInfo', with: parameters
+    return success()
+}