This is an automated email from the ASF dual-hosted git repository.

nmalin pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 1f84596e20 Improved: Convert FixedAssetServices.xml mini lang to 
groovy (OFBIZ-12852)
1f84596e20 is described below

commit 1f84596e20e9824bd0afbd1d8b1ff9955b9caf23
Author: Nicolas Malin <nicolas.ma...@nereide.fr>
AuthorDate: Fri Sep 1 15:57:21 2023 +0200

    Improved: Convert FixedAssetServices.xml mini lang to groovy (OFBIZ-12852)
    
    Finish to convert FixedAssetServices.xml with migrate service :
       * createFixedAssetMaint
       * updateFixedAssetMaint
       * createMaintsFromTimeInterval
       * autoAssignFixedAssetPartiesToMaintenance
       * createMaintsFromMeterReading
       * createFixedAssetMaintOrder
       * checkUpdateFixedAssetDepreciation
       * straightLineDepreciation
       * doubleDecliningBalanceDepreciation
       * calculateFixedAssetDepreciation
---
 .../accounting/config/AccountingErrorUiLabels.xml  |   4 +
 .../minilang/fixedasset/FixedAssetServices.xml     | 750 ---------------------
 .../accounting/servicedef/services_fixedasset.xml  |  42 +-
 .../fixedasset/FixedAssetServices.groovy           | 464 +++++++++++++
 4 files changed, 492 insertions(+), 768 deletions(-)

diff --git a/applications/accounting/config/AccountingErrorUiLabels.xml 
b/applications/accounting/config/AccountingErrorUiLabels.xml
index 4f1c0a6c70..00da5796fd 100644
--- a/applications/accounting/config/AccountingErrorUiLabels.xml
+++ b/applications/accounting/config/AccountingErrorUiLabels.xml
@@ -391,6 +391,10 @@
         <value xml:lang="zh">找到的补充方法未知</value>
         <value xml:lang="zh-TW">找到的補充方法未知</value>
     </property>
+    <property key="AccountingFixedAssetNotFound">
+        <value xml:lang="en">Fixed asset not found</value>
+        <value xml:lang="fr">Immobilisation non trouvée</value>
+    </property>
     <property key="AccountingGiftCardCannotBeCreated">
         <value xml:lang="ar">خطأ: لا يمكن خلق بطاقة الهدية (فشل توليد 
الدليل)</value>
         <value xml:lang="de">FEHLER: Kann Geschenkkarte nicht erstellen 
(Fehler bei Id Erstellung)</value>
diff --git a/applications/accounting/minilang/fixedasset/FixedAssetServices.xml 
b/applications/accounting/minilang/fixedasset/FixedAssetServices.xml
deleted file mode 100644
index 856b2b2a13..0000000000
--- a/applications/accounting/minilang/fixedasset/FixedAssetServices.xml
+++ /dev/null
@@ -1,750 +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";>
-
-    <!--  create/update/delete FixedAssetMaint -->
-    <simple-method method-name="createFixedAssetMaint" 
short-description="create a FixedAssetMaint">
-        <make-value entity-name="FixedAssetMaint" value-field="newEntity"/>
-        <set-pk-fields map="parameters" value-field="newEntity"/>
-        <make-next-seq-id value-field="newEntity" 
seq-field-name="maintHistSeqId"/> <!-- this finds the next sub-sequence ID -->
-        <field-to-result field="newEntity.maintHistSeqId" 
result-name="maintHistSeqId"/>
-        <set-nonpk-fields map="parameters" value-field="newEntity"/>
-        <if-not-empty field="parameters.productMaintSeqId">
-            <entity-one entity-name="FixedAsset" value-field="fixedAsset"/>
-            <entity-one entity-name="ProductMaint" value-field="productMaint">
-                <field-map field-name="productId" 
from-field="fixedAsset.instanceOfProductId"/>
-                <field-map field-name="productMaintSeqId" 
from-field="parameters.productMaintSeqId"/>
-            </entity-one>
-            <set field="newEntity.productMaintTypeId" 
from-field="productMaint.productMaintTypeId"/>
-        </if-not-empty >
-        <if-not-empty field="productMaint.maintTemplateWorkEffortId">
-            <set field="maintTemplateWorkEffortId" 
from-field="productMaint.maintTemplateWorkEffortId"/>
-            <else>
-                <!-- User can still pick a Template workEffort -->
-                <set field="maintTemplateWorkEffortId" 
from-field="parameters.maintTemplateWorkEffortId"/>
-            </else>
-        </if-not-empty>
-        <if-not-empty field="maintTemplateWorkEffortId">
-
-            <set field="duplicateTemplateWorkEffortMap.oldWorkEffortId" 
from-field="maintTemplateWorkEffortId"/>
-            <sequenced-id sequence-name="WorkEffort" 
field="duplicateTemplateWorkEffortMap.workEffortId"/>
-            <set 
field="duplicateTemplateWorkEffortMap.duplicateWorkEffortAssocs" value="Y"/>
-            <set 
field="duplicateTemplateWorkEffortMap.duplicateWorkEffortNotes" value="Y"/>
-            <set 
field="duplicateTemplateWorkEffortMap.duplicateWorkEffortContents" value="Y"/>
-            <set 
field="duplicateTemplateWorkEffortMap.duplicateWorkEffortAssignmentRates" 
value="Y"/>
-            <call-service service-name="duplicateWorkEffort" 
in-map-name="duplicateTemplateWorkEffortMap"/>
-            <set field="newEntity.scheduleWorkEffortId" 
from-field="duplicateTemplateWorkEffortMap.workEffortId"/>
-
-            <else>
-                <!-- Create the WorkEffort -->
-                <!-- Maintenance WorkEffort entity -->
-                <entity-one entity-name="FixedAsset" value-field="fixedAsset"/>
-                <property-to-field field="workEffortName" 
resource="AccountingUiLabels" 
property="AccountingFixedAssetMaintWorkEffortName"/>
-                <set from-field="workEffortName" 
field="maintWorkEffortMap.workEffortName"/>
-                <set value="TASK" field="maintWorkEffortMap.workEffortTypeId"/>
-                <set value="WEPT_MAINTENANCE" 
field="maintWorkEffortMap.workEffortPurposeTypeId"/>
-                <set value="CAL_TENTATIVE" 
field="maintWorkEffortMap.currentStatusId"/>
-                <set from-field="userLogin.partyId" 
field="maintWorkEffortMap.quickAssignPartyId"/>
-                <set from-field="newEntity.fixedAssetId" 
field="maintWorkEffortMap.fixedAssetId"/>
-                <get-related-one to-value-field="productMaintType" 
relation-name="ProductMaintType" value-field="newEntity"/>
-                <set field="maintWorkEffortMap.description" 
from-field="productMaintType.description"/>
-                <!-- Optional dates supplied by Fixed Asset Calendar -->
-                <set from-field="parameters.estimatedStartDate" 
field="maintWorkEffortMap.estimatedStartDate"/>
-                <set from-field="parameters.estimatedCompletionDate" 
field="maintWorkEffortMap.estimatedCompletionDate"/>
-                <call-service service-name="createWorkEffort" 
in-map-name="maintWorkEffortMap">
-                    <result-to-field result-name="workEffortId" 
field="newEntity.scheduleWorkEffortId"/>
-                </call-service>
-            </else>
-        </if-not-empty>
-        <create-value value-field="newEntity"/>
-        <check-errors/>
-        <set field="workEffortId" from-field="newEntity.scheduleWorkEffortId"/>
-        <call-simple-method 
method-name="autoAssignFixedAssetPartiesToMaintenance"/>
-    </simple-method>
-    <simple-method method-name="updateFixedAssetMaint" 
short-description="Update an existing FixedAsset Maintenance">
-        <entity-one entity-name="FixedAssetMaint" value-field="lookedUpValue"/>
-        <set field="oldStatusId" from-field="lookedUpValue.statusId"/>
-        <field-to-result field="oldStatusId"/>
-        <set-nonpk-fields map="parameters" value-field="lookedUpValue"/>
-        <if-not-empty field="parameters.productMaintSeqId">
-            <entity-one entity-name="FixedAsset" value-field="fixedAsset"/>
-            <entity-one entity-name="ProductMaint" value-field="productMaint">
-                <field-map field-name="productId" 
from-field="fixedAsset.instanceOfProductId"/>
-                <field-map field-name="productMaintSeqId" 
from-field="parameters.productMaintSeqId"/>
-            </entity-one>
-            <set field="lookedUpValue.productMaintTypeId" 
from-field="productMaint.productMaintTypeId"/>
-        </if-not-empty>
-        <store-value value-field="lookedUpValue"/>
-        <check-errors/>
-        <if>
-            <condition>
-                <and>
-                    <if-compare field="lookedUpValue.statusId" 
value="FAM_COMPLETED" operator="equals"/>
-                    <if-compare-field field="oldStatusId" 
to-field="lookedUpValue.statusId" operator="not-equals"/>
-                </and>
-            </condition>
-            <then>
-                <set field="workEffortId" 
from-field="lookedUpValue.scheduleWorkEffortId"/>
-                <entity-one entity-name="WorkEffort" value-field="workEffort"/>
-                <if>
-                    <condition>
-                        <and>
-                            <not><if-empty field="workEffort"/></not>
-                            <if-empty field="workEffort.actualCompletionDate"/>
-                            <if-compare field="workEffort.currentStatusId" 
value="CAL_COMPLETED" operator="not-equals"/>
-                        </and>
-                    </condition>
-                    <then>
-                        <now-timestamp field="nowTimestamp"/>
-                        <set field="updateWorkEffortCtx.workEffortId" 
from-field="workEffortId"/>
-                        <set field="updateWorkEffortCtx.currentStatusId" 
value="CAL_ACCEPTED"/>
-                        <call-service service-name="updateWorkEffort" 
in-map-name="updateWorkEffortCtx"/>
-                        <check-errors/>
-                        <set field="updateWorkEffortCtx.currentStatusId" 
value="CAL_COMPLETED"/>
-                        <set field="updateWorkEffortCtx.actualCompletionDate" 
from-field="nowTimestamp"/>
-                        <call-service service-name="updateWorkEffort" 
in-map-name="updateWorkEffortCtx"/>
-                        <check-errors/>
-                        <entity-condition 
entity-name="WorkEffortPartyAssignment" list="wepas" filter-by-date="true">
-                            <condition-expr field-name="workEffortId" 
operator="equals" from-field="workEffortId"/>
-                        </entity-condition>
-                        <iterate list="wepas" entry="wepa">
-                            <set field="wepa.thruDate" 
from-field="nowTimestamp"/>
-                            <store-value value-field="wepa"/>
-                            <check-errors/>
-                        </iterate>
-                    </then>
-                </if>
-            </then>
-        </if>
-    </simple-method>
-    <simple-method method-name="createMaintsFromMeterReading" 
short-description="Create Fixed Asset Maintenances From A Meter Reading">
-        <set field="meterValue" from-field="parameters"/>
-        <if-not-empty field="meterValue.maintHistSeqId">
-            <return/>
-        </if-not-empty>
-        <entity-one entity-name="FixedAsset" value-field="fixedAssetValue"/>
-        <if-empty field="fixedAssetValue.instanceOfProductId">
-            <return/>
-        </if-empty>
-        <entity-and entity-name="ProductMaint" list="productMaintList">
-            <field-map field-name="productId" 
from-field="fixedAssetValue.instanceOfProductId"/>
-            <field-map field-name="intervalMeterTypeId" 
from-field="meterValue.productMeterTypeId"/>
-        </entity-and>
-        <iterate list="productMaintList" entry="productMaintValue">
-            <set field="repeatCount" 
from-field="productMaintValue.repeatCount" default-value="0" type="Long"/>
-            <entity-condition entity-name="FixedAssetMaint" list="maintList">
-                <condition-list combine="and">
-                    <condition-expr field-name="fixedAssetId" 
operator="equals" from-field="fixedAssetValue.fixedAssetId"/>
-                    <condition-expr field-name="productMaintTypeId" 
operator="equals" from-field="productMaintValue.productMaintTypeId"/>
-                    <condition-expr field-name="intervalMeterTypeId" 
operator="equals" from-field="productMaintValue.intervalMeterTypeId"/>
-                    <condition-expr field-name="statusId" 
operator="not-equals" value="FAM_CANCELLED"/>
-                </condition-list>
-            </entity-condition>
-            <set field="listSize" value="0" type="Long"/>
-            <if-not-empty field="maintList">
-                <set field="listSize" value="${groovy:maintList.size()}" 
type="Long"/>
-            </if-not-empty>
-            <set field="maxIntervalQty" value="0" type="BigDecimal"/>
-            <iterate list="maintList" entry="maintValue">
-                <if-not-empty field="maintValue.intervalQuantity">
-                <if-compare-field field="maintValue.intervalQuantity" 
operator="greater" to-field="maxIntervalQty" type="BigDecimal">
-                    <set field="maxIntervalQty" 
from-field="maintValue.intervalQuantity" type="BigDecimal"/>
-                </if-compare-field>
-                </if-not-empty>
-            </iterate>
-            <set field="nextIntervalQty" 
value="${groovy:maxIntervalQty.add(productMaintValue.getBigDecimal(&quot;intervalQuantity&quot;));}"
 type="BigDecimal"/>
-            <if-not-empty field="meterValue.meterValue">
-            <if-compare-field field="nextIntervalQty" operator="less-equals" 
to-field="meterValue.meterValue" type="BigDecimal">
-                <set field="maintDue" value="false"/>
-                <if-compare field="repeatCount" operator="greater" value="0" 
type="Long">
-                    <if-compare-field field="listSize" operator="less" 
to-field="repeatCount" type="Long">
-                        <set field="maintDue" value="true"/>
-                    </if-compare-field>
-                    <else>
-                        <set field="maintDue" value="true"/>
-                    </else>
-                </if-compare>
-                <if-compare field="maintDue" operator="equals" value="true">
-                    <set-service-fields service-name="createFixedAssetMaint" 
map="productMaintValue" to-map="createMaintCxt"/>
-                    <set field="createMaintCxt.fixedAssetId" 
from-field="fixedAssetValue.fixedAssetId"/>
-                    <set field="createMaintCxt.intervalQuantity" 
from-field="meterValue.meterValue"/>
-                    <set field="createMaintCxt.statusId" value="FAM_CREATED"/>
-                    <call-service service-name="createFixedAssetMaint" 
in-map-name="createMaintCxt"/>
-                    <check-errors/>
-                </if-compare>
-            </if-compare-field>
-            </if-not-empty>
-        </iterate>
-    </simple-method>
-    <simple-method method-name="createMaintsFromTimeInterval" 
short-description="Create Fixed Asset Maintenances From A Product Maint Time 
Interval">
-        <now-timestamp field="nowTimestamp"/>
-        <entity-condition entity-name="FixedAsset" list="fixedAssets">
-            <condition-list combine="and">
-                <condition-expr field-name="instanceOfProductId" 
operator="not-equals" from-field="null"/>
-                <condition-expr field-name="actualEndOfLife" operator="equals" 
from-field="null"/>
-            </condition-list>
-        </entity-condition>
-        <iterate list="fixedAssets" entry="fixedAsset">
-            <entity-condition entity-name="ProductMaint" list="productMaints">
-                <condition-list combine="and">
-                    <condition-expr field-name="productId" 
from-field="fixedAsset.instanceOfProductId"/>
-                    <condition-expr field-name="intervalUomId" operator="like" 
value="TF_%"/>
-                </condition-list>
-            </entity-condition>
-            <iterate list="productMaints" entry="productMaint">
-                <set field="repeatCount" from-field="productMaint.repeatCount" 
default-value="0" type="Long"/>
-                <entity-condition entity-name="FixedAssetMaintWorkEffort" 
list="maintList">
-                    <condition-list combine="and">
-                        <condition-expr field-name="fixedAssetId" 
operator="equals" from-field="fixedAsset.fixedAssetId"/>
-                        <condition-expr field-name="productMaintTypeId" 
operator="equals" from-field="productMaint.productMaintTypeId"/>
-                        <condition-expr field-name="intervalUomId" 
operator="equals" from-field="productMaint.intervalUomId"/>
-                        <condition-expr field-name="statusId" 
operator="not-equals" value="FAM_CANCELLED"/>
-                    </condition-list>
-                    <order-by field-name="maintHistSeqId"/>
-                </entity-condition>
-                <set field="intervalQuantity" 
from-field="productMaint.intervalQuantity" default-value="0" type="Integer"/>
-                <if-compare field="productMaint.intervalUomId" 
operator="equals" value="TF_day">
-                    <set-calendar field="compareDate" 
from-field="nowTimestamp" days="-${intervalQuantity}"/>
-                    <else>
-                        <if-compare field="productMaint.intervalUomId" 
operator="equals" value="TF_mon">
-                            <set-calendar field="compareDate" 
from-field="nowTimestamp" months="-${intervalQuantity}"/>
-                            <else>
-                                <if-compare field="productMaint.intervalUomId" 
operator="equals" value="TF_yr">
-                                    <set-calendar field="compareDate" 
from-field="nowTimestamp" years="-${intervalQuantity}"/>
-                                </if-compare>
-                            </else>
-                        </if-compare>
-                    </else>
-                </if-compare>
-                <if-not-empty field="compareDate">
-                    <set field="listSize" value="0" type="Long"/>
-                    <if-not-empty field="maintList">
-                        <set field="listSize" 
value="${groovy:maintList.size()}" type="Long"/>
-                    </if-not-empty>
-                    <set field="lastSvcLong" value="0" type="Long"/>
-                    <set field="lastSvcDate" from-field="lastSvcLong" 
type="Timestamp"/>
-                    <iterate list="maintList" entry="maintValue">
-                        <set field="lastSvcDate" 
from-field="maintValue.actualCompletionDate" set-if-null="true"/>
-                    </iterate>
-                    <if-not-empty field="lastSvcDate">
-                        <if-compare-field field="lastSvcDate" operator="less" 
to-field="compareDate" type="Timestamp">
-                            <set field="maintDue" value="false"/>
-                            <if-compare field="repeatCount" operator="greater" 
value="0" type="Long">
-                                <if-compare-field field="listSize" 
operator="less" to-field="repeatCount" type="Long">
-                                    <set field="maintDue" value="true"/>
-                                </if-compare-field>
-                                <else>
-                                    <set field="maintDue" value="true"/>
-                                </else>
-                            </if-compare>
-                            <if-compare field="maintDue" operator="equals" 
value="true">
-                                <set-service-fields 
service-name="createFixedAssetMaint" map="productMaint" 
to-map="createMaintCxt"/>
-                                <set field="createMaintCxt.fixedAssetId" 
from-field="fixedAsset.fixedAssetId"/>
-                                <set field="createMaintCxt.statusId" 
value="FAM_CREATED"/>
-                                <call-service 
service-name="createFixedAssetMaint" in-map-name="createMaintCxt"/>
-                                <check-errors/>
-                            </if-compare>
-                        </if-compare-field>
-                    </if-not-empty>
-                </if-not-empty>
-            </iterate>
-        </iterate>
-    </simple-method>
-
-    <!--  create/update/delete FixedAssetMaintOrder -->
-    <simple-method method-name="createFixedAssetMaintOrder" 
short-description="Create a FixedAsset Maintenance Order">
-           <!-- Check, should exist orderId and orderItemId -->
-        <entity-one entity-name="OrderHeader" value-field="lookedUpValue"/>
-        <if-empty field="lookedUpValue">
-            <set field="orderId" from-field="parameters.orderId"/>
-            <add-error>
-                <fail-property resource="AccountingUiLabels" 
property="AccountingOrderWithIdNotFound"/>
-            </add-error>
-        </if-empty>
-        <check-errors/>
-
-        <!-- Check if user has not passed in orderItemSeqId then get list of 
OrderItems from database and default to first item -->
-        <if-empty field="parameters.orderItemSeqId">
-            <entity-and entity-name="OrderItem" list="orderItems">
-                <field-map field-name="orderId" 
from-field="parameters.orderId"/>
-            </entity-and>
-            <if-not-empty field="orderItems">
-                <set field="orderItem" from-field="orderItems[0]"/>
-                <if-not-empty field="orderItem">
-                  <set field="parameters.orderItemSeqId" 
from-field="orderItem.orderItemSeqId"/>
-                </if-not-empty>
-            </if-not-empty>
-
-            <else>
-               <!-- Check, should exist orderId and orderItemId -->
-               <entity-one entity-name="OrderItem" 
value-field="lookedUpValue"/>
-               <if-empty field="lookedUpValue">
-                  <set field="orderItemSeqId" 
from-field="parameters.orderItemSeqId"/>
-                  <add-error>
-                      <fail-property resource="AccountingUiLabels" 
property="AccountingOrderItemWithIdNotFound"/>
-                  </add-error>
-               </if-empty>
-            </else>
-        </if-empty>
-        <check-errors/>
-
-        <make-value entity-name="FixedAssetMaintOrder" 
value-field="newEntity"/>
-        <set-pk-fields map="parameters" value-field="newEntity"/>
-        <set-nonpk-fields map="parameters" value-field="newEntity"/>
-        <create-value value-field="newEntity"/>
-    </simple-method>
-
-    <simple-method method-name="autoAssignFixedAssetPartiesToMaintenance" 
login-required="true"
-        short-description="Auto-assign Fixed Asset Parties to a Fixed Asset 
Maintenance">
-        <if-empty field="maintHistSeqId">
-            <set field="maintHistSeqId" 
from-field="parameters.maintHistSeqId"/>
-        </if-empty>
-        <if-empty field="fixedAssetId">
-            <set field="fixedAssetId" from-field="parameters.fixedAssetId"/>
-        </if-empty>
-        <entity-one entity-name="FixedAssetMaint" value-field="maintValue"/>
-        <if-empty field="workEffortId">
-            <set field="workEffortId" 
from-field="maintValue.scheduleWorkEffortId"/>
-        </if-empty>
-        <entity-and entity-name="PartyFixedAssetAssignAndRole" 
list="assignedParties" filter-by-date="true">
-            <field-map field-name="fixedAssetId" from-field="fixedAssetId"/>
-            <field-map field-name="parentTypeId" value="FAM_ASSIGNEE"/>
-        </entity-and>
-        <iterate list="assignedParties" entry="assignedParty">
-            <set field="assignPartyCtx.partyId" 
from-field="assignedParty.partyId"/>
-            <set field="assignPartyCtx.roleTypeId" 
from-field="assignedParty.roleTypeId"/>
-            <set field="assignPartyCtx.workEffortId" 
from-field="workEffortId"/>
-            <set field="assignPartyCtx.statusId" value="PRTYASGN_ASSIGNED"/>
-            <call-service service-name="assignPartyToWorkEffort" 
in-map-name="assignPartyCtx"/>
-            <check-errors/>
-        </iterate>
-    </simple-method>
-
-    <!-- ==============  Fixed Asset Depreciation methods  ============== -->
-    <simple-method method-name="straightLineDepreciation" 
short-description="Calculate straight line depreciation to Fixed Asset[ 
(PC-SV)/expLife ]">
-        <set field="expEndOfLifeYear" from-field="parameters.expEndOfLifeYear" 
type="Integer"/>
-        <set field="assetAcquiredYear" 
from-field="parameters.assetAcquiredYear" type="Integer"/>
-        <set field="purchaseCost" from-field="parameters.purchaseCost"/>
-        <set field="salvageValue" from-field="parameters.salvageValue"/>
-        <call-object-method obj-field="parameters.usageYears" 
method-name="intValue" ret-field="intUsageYears"/>
-
-        <!-- Past depreciation based on standard formula -->
-        <set field="depreciationTotal" value="0.0" type="BigDecimal"/>
-        <if>
-            <condition>
-                <and>
-                    <if-compare field="intUsageYears" operator="greater" 
value="0.0" type="BigDecimal"/>
-                    <not><if-empty field="parameters.fixedAssetId"/></not>
-                </and>
-            </condition>
-            <then>
-                <set field="depreciation" value="0.0" type="BigDecimal"/>
-                <!--FORMULA :  depreciation = (purchaseCost - salvageValue) / 
(expectedEndOfLife - dateAcquired) -->
-                <calculate field="numberOfYears">
-                    <calcop operator="subtract">
-                        <calcop operator="get" field="expEndOfLifeYear"/>
-                        <calcop operator="get" field="assetAcquiredYear"/>
-                    </calcop>
-                </calculate>
-                <if-compare field="numberOfYears" operator="greater" 
value="0.0" type="BigDecimal">
-                    <calculate field="depreciation" decimal-scale="2">
-                        <calcop operator="divide">
-                            <calcop operator="subtract">
-                                <calcop operator="get" field="purchaseCost"/>
-                                <calcop operator="get" field="salvageValue"/>
-                            </calcop>
-                            <calcop operator="get" field="numberOfYears"/>
-                        </calcop>
-                    </calculate>
-                </if-compare>
-                <set field="depreciationYear" from-field="assetAcquiredYear" 
type="BigDecimal"/>
-                <if-compare-field field="numberOfYears" operator="less" 
to-field="intUsageYears" type="BigDecimal">
-                    <set field="intUsageYears" from-field="numberOfYears" 
type="BigDecimal"/>
-                </if-compare-field>
-                <loop count="${intUsageYears}">
-                    <calculate field="purchaseCost">
-                        <calcop operator="subtract">
-                            <calcop operator="get" field="purchaseCost"/>
-                            <calcop operator="get" field="depreciation"/>
-                        </calcop>
-                    </calculate>
-                    <calculate field="depreciationTotal">
-                        <calcop operator="add">
-                            <calcop operator="get" field="depreciationTotal"/>
-                            <calcop operator="get" field="depreciation"/>
-                        </calcop>
-                    </calculate>
-                    <field-to-list list="assetDepreciationTillDate" 
field="depreciation"/>
-                    <field-to-list list="assetNBVAfterDepreciation" 
field="purchaseCost"/>
-                    <clear-field field="assetDepreciationInfo"/>
-                    <set field="assetDepreciationInfo.year" 
from-field="depreciationYear"/>
-                    <set field="assetDepreciationInfo.depreciation" 
from-field="depreciation"/>
-                    <set field="assetDepreciationInfo.depreciationTotal" 
from-field="depreciationTotal"/>
-                    <set field="assetDepreciationInfo.nbv" 
from-field="purchaseCost"/>
-                    <field-to-list list="assetDepreciationInfoList" 
field="assetDepreciationInfo"/>
-                    <calculate field="depreciationYear">
-                        <calcop operator="add">
-                           <calcop operator="get" field="depreciationYear"/>
-                           <number value="1"/>
-                        </calcop>
-                    </calculate>
-                </loop>
-            </then>
-        </if>
-        <if-empty field="assetDepreciationTillDate">
-            <set field="depreciation" value="0.0" type="BigDecimal"/>
-            <field-to-list list="assetDepreciationTillDate" 
field="depreciation"/>
-            <field-to-list list="assetNBVAfterDepreciation" 
field="purchaseCost"/>
-            <set field="assetDepreciationInfo.year" 
from-field="assetAcquiredYear"/>
-            <set field="assetDepreciationInfo.depreciation" 
from-field="depreciation"/>
-            <set field="assetDepreciationInfo.depreciationTotal" 
from-field="depreciationTotal"/>
-            <set field="assetDepreciationInfo.nbv" from-field="purchaseCost"/>
-            <field-to-list list="assetDepreciationInfoList" 
field="assetDepreciationInfo"/>
-        </if-empty>
-        <log level="info" message="Using straight line formula depreciation 
calculated for fixedAsset (${parameters.fixedAssetId}) is ${depreciation}"/>
-        <field-to-result field="assetDepreciationTillDate"/>
-        <field-to-result field="assetNBVAfterDepreciation"/>
-        <field-to-result field="assetDepreciationInfoList"/>
-
-        <!-- Next depreciation based on actual depreciation history -->
-        <set field="nextDepreciationAmount" value="0.0" type="BigDecimal"/>
-        <if>
-            <condition>
-                <not><if-empty field="parameters.fixedAssetId"/></not>
-            </condition>
-            <then>
-                <entity-one entity-name="FixedAsset" value-field="fixedAsset"/>
-                <!--FORMULA :  depreciation = (purchaseCost - salvageValue - 
pastDepreciations) / remainingYears -->
-                <calculate field="remainingYears">
-                    <calcop operator="subtract">
-                        <calcop operator="get" field="expEndOfLifeYear"/>
-                        <calcop operator="get" field="assetAcquiredYear"/>
-                        <calcop operator="get" field="intUsageYears"/>
-                    </calcop>
-                </calculate>
-                <if-compare field="remainingYears" operator="greater" 
value="0.0" type="BigDecimal">
-                    <calculate field="nextDepreciationAmount" 
decimal-scale="2">
-                        <calcop operator="divide">
-                            <calcop operator="subtract">
-                                <calcop operator="get" 
field="fixedAsset.purchaseCost"/>
-                                <calcop operator="get" field="salvageValue"/>
-                                <calcop operator="get" 
field="fixedAsset.depreciation"/>
-                            </calcop>
-                            <calcop operator="get" field="remainingYears"/>
-                        </calcop>
-                    </calculate>
-                </if-compare>
-            </then>
-        </if>
-        <field-to-result field="nextDepreciationAmount"/>
-        <calculate field="plannedPastDepreciationTotal">
-            <calcop operator="subtract">
-                <calcop operator="get" field="depreciationTotal"/>
-                <calcop operator="get" field="fixedAsset.depreciation"/>
-            </calcop>
-        </calculate>
-        <field-to-result field="plannedPastDepreciationTotal"/>
-    </simple-method>
-
-    <simple-method method-name="doubleDecliningBalanceDepreciation" 
short-description="Calculate double declining balance depreciation to Fixed 
Asset">
-        <set field="expEndOfLifeYear" from-field="parameters.expEndOfLifeYear" 
type="Integer"/>
-        <set field="assetAcquiredYear" 
from-field="parameters.assetAcquiredYear" type="Integer"/>
-        <set field="purchaseCost" from-field="parameters.purchaseCost"/>
-        <set field="salvageValue" from-field="parameters.salvageValue"/>
-        <call-object-method obj-field="parameters.usageYears" 
method-name="intValue" ret-field="intUsageYears"/>
-        <!-- Next depreciation based on actual depreciation history -->
-        <set field="nextDepreciationAmount" value="0.0" type="BigDecimal"/>
-        <if>
-            <condition>
-                <not><if-empty field="parameters.fixedAssetId"/></not>
-            </condition>
-            <then>
-                <entity-one entity-name="FixedAsset" value-field="fixedAsset"/>
-                <!--FORMULA :  depreciation = 2 * (purchaseCost - salvageValue 
- pastDepreciations) / remainingYears -->
-                <calculate field="remainingYears">
-                    <calcop operator="subtract">
-                        <calcop operator="get" field="expEndOfLifeYear"/>
-                        <calcop operator="get" field="assetAcquiredYear"/>
-                        <calcop operator="get" field="intUsageYears"/>
-                    </calcop>
-                </calculate>
-                <if-compare field="remainingYears" operator="greater" 
value="0.0" type="BigDecimal">
-                    <calculate field="nextDepreciationAmount" 
decimal-scale="2">
-                        <calcop operator="multiply">
-                            <calcop operator="divide">
-                                <calcop operator="subtract">
-                                    <calcop operator="get" 
field="fixedAsset.purchaseCost"/>
-                                    <calcop operator="get" 
field="salvageValue"/>
-                                    <calcop operator="get" 
field="fixedAsset.depreciation"/>
-                                </calcop>
-                                <calcop operator="get" field="remainingYears"/>
-                            </calcop>
-                            <number value="2"/>
-                        </calcop>
-                    </calculate>
-                </if-compare>
-            </then>
-        </if>
-        <field-to-result field="nextDepreciationAmount"/>
-
-        <!-- Past depreciation based on standard formula -->
-        <set field="depreciationTotal" value="0.0" type="BigDecimal"/>
-        <if>
-            <condition>
-                <and>
-                    <if-compare field="intUsageYears" operator="greater" 
value="0.0" type="BigDecimal"/>
-                    <not><if-empty field="parameters.fixedAssetId"/></not>
-                </and>
-            </condition>
-            <then>
-                <set field="depreciationYear" from-field="assetAcquiredYear" 
type="BigDecimal"/>
-                <loop count="${intUsageYears}">
-                    <set field="depreciation" value="0.0" type="BigDecimal"/>
-                    <!--FORMULA : depreciation = (NBV - salvageValue) * 2 / 
(expectedEndOfLife - dateAcquired) -->
-                    <calculate field="numberOfYears">
-                        <calcop operator="subtract">
-                            <calcop operator="get" field="expEndOfLifeYear"/>
-                            <calcop operator="get" field="assetAcquiredYear"/>
-                        </calcop>
-                    </calculate>
-                    <if-compare field="numberOfYears" operator="greater" 
value="0.0" type="BigDecimal">
-                        <calculate field="depreciation" decimal-scale="2">
-                            <calcop operator="multiply">
-                                <calcop operator="divide">
-                                   <calcop operator="subtract">
-                                        <calcop operator="get" 
field="purchaseCost"/>
-                                        <calcop operator="get" 
field="salvageValue"/>
-                                    </calcop>
-                                    <calcop operator="get" 
field="numberOfYears"/>
-                                </calcop>
-                                <number value="2"/>
-                            </calcop>
-                        </calculate>
-                    </if-compare>
-                    <calculate field="assetAcquiredYear">
-                        <calcop operator="add">
-                           <calcop operator="get" field="assetAcquiredYear"/>
-                           <number value="1"/>
-                        </calcop>
-                    </calculate>
-                    <calculate field="purchaseCost">
-                       <calcop operator="subtract">
-                           <calcop operator="get" field="purchaseCost"/>
-                           <calcop operator="get" field="depreciation"/>
-                        </calcop>
-                    </calculate>
-                    <calculate field="depreciationTotal">
-                        <calcop operator="add">
-                            <calcop operator="get" field="depreciationTotal"/>
-                            <calcop operator="get" field="depreciation"/>
-                        </calcop>
-                    </calculate>
-                    <field-to-list list="assetDepreciationTillDate" 
field="depreciation"/>
-                    <field-to-list list="assetNBVAfterDepreciation" 
field="purchaseCost"/>
-                    <clear-field field="assetDepreciationInfo"/>
-                    <set field="assetDepreciationInfo.year" 
from-field="depreciationYear"/>
-                    <set field="assetDepreciationInfo.depreciation" 
from-field="depreciation"/>
-                    <set field="assetDepreciationInfo.depreciationTotal" 
from-field="depreciationTotal"/>
-                    <set field="assetDepreciationInfo.nbv" 
from-field="purchaseCost"/>
-                    <field-to-list list="assetDepreciationInfoList" 
field="assetDepreciationInfo"/>
-                    <calculate field="depreciationYear">
-                        <calcop operator="add">
-                           <calcop operator="get" field="depreciationYear"/>
-                           <number value="1"/>
-                        </calcop>
-                    </calculate>
-                </loop>
-            </then>
-        </if>
-        <if-empty field="assetDepreciationTillDate">
-            <set field="depreciation" value="0.0" type="BigDecimal"/>
-            <field-to-list list="assetDepreciationTillDate" 
field="depreciation"/>
-            <field-to-list list="assetNBVAfterDepreciation" 
field="purchaseCost"/>
-            <set field="assetDepreciationInfo.year" 
from-field="assetAcquiredYear"/>
-            <set field="assetDepreciationInfo.depreciation" 
from-field="depreciation"/>
-            <set field="assetDepreciationInfo.depreciationTotal" 
from-field="depreciationTotal"/>
-            <set field="assetDepreciationInfo.nbv" from-field="purchaseCost"/>
-            <field-to-list list="assetDepreciationInfoList" 
field="assetDepreciationInfo"/>
-        </if-empty>
-        <log level="info" message="Using double decline formula depreciation 
calculated for fixedAsset (${parameters.fixedAssetId}) is 
${assetDepreciationTillDate}"/>
-        <field-to-result field="assetDepreciationTillDate"/>
-        <field-to-result field="assetNBVAfterDepreciation"/>
-        <field-to-result field="assetDepreciationInfoList"/>
-        <field-to-result field="depreciationTotal" 
result-name="plannedPastDepreciationTotal"/>
-    </simple-method>
-
-    <simple-method method-name="calculateFixedAssetDepreciation" 
short-description="Service to calculate the yearly depreciation from 
dateAcquired year to current financial year">
-        <entity-one entity-name="FixedAsset" value-field="fixedAsset"/>
-        <if-empty field="fixedAsset">
-            <add-error>
-                <fail-property resource="ManufacturingUiLabels" 
property="ManufacturingFixedAssetNotExist"/>
-            </add-error>
-            <check-errors/>
-        </if-empty>
-        <set field="startIndex" value="0" type="Integer"/>
-        <set field="endIndex" value="4" type="Integer"/>
-
-        <!-- Extract asset end of life year from field expectedEndOfLife -->
-        <if-not-empty field="fixedAsset.expectedEndOfLife">
-            <set field="expectedEndOfLife" 
from-field="fixedAsset.expectedEndOfLife"/>
-            <to-string field="expectedEndOfLife"/>
-            <call-object-method method-name="substring" 
obj-field="expectedEndOfLife" ret-field="expEndOfLifeYear">
-                <field field="startIndex" type="int"/>
-                <field field="endIndex" type="int"/>
-            </call-object-method>
-        <else>
-            <property-to-field resource="AccountingUiLabels" 
property="AccountingExpEndOfLifeIsEmpty" field="successMessageList[]"/>
-            <return/>
-        </else>
-        </if-not-empty>
-
-        <!-- Extract asset acquired year from field dateAcquired -->
-        <if-not-empty field="fixedAsset.dateAcquired">
-            <set field="dateAcquired" from-field="fixedAsset.dateAcquired"/>
-            <to-string field="dateAcquired"/>
-            <call-object-method method-name="substring" 
obj-field="dateAcquired" ret-field="assetAcquiredYear">
-                <field field="startIndex"  type="int"/>
-                <field field="endIndex" type="int"/>
-            </call-object-method>
-        <else>
-            <property-to-field resource="AccountingUiLabels" 
property="AccountingDateAcquiredIsEmpty" field="successMessageList[]"/>
-            <return/>
-        </else>
-        </if-not-empty>
-
-        <!-- if any asset's salvage value is empty then set it by 0 -->
-        <if-empty field="fixedAsset.salvageValue">
-            <set field="salvageValue" value="0.0" type="BigDecimal"/>
-        <else>
-            <set field="salvageValue" from-field="fixedAsset.salvageValue"/>
-        </else>
-        </if-empty>
-
-        <!-- Get running year -->
-        <now-timestamp field="nowTimestamp"/>
-        <to-string field="nowTimestamp"/>
-        <call-object-method method-name="substring" obj-field="nowTimestamp" 
ret-field="currentYear">
-            <field field="startIndex" type="int"/>
-            <field field="endIndex" type="int"/>
-        </call-object-method>
-
-        <!-- Calculate asset's total run in years -->
-        <calculate field="usageYears" type="Integer">
-            <calcop operator="subtract">
-               <calcop operator="get" field="currentYear"/>
-               <calcop operator="get" field="assetAcquiredYear"/>
-            </calcop>
-        </calculate>
-
-        <entity-and entity-name="FixedAssetDepMethod" 
list="fixedAssetDepMethods" filter-by-date="true">
-            <field-map field-name="fixedAssetId" 
from-field="parameters.fixedAssetId"/>
-        </entity-and>
-        <if-not-empty field="fixedAssetDepMethods">
-            <first-from-list list="fixedAssetDepMethods" 
entry="fixedAssetDepMethod"/>
-            <get-related-one relation-name="CustomMethod" 
value-field="fixedAssetDepMethod" to-value-field="customMethod"/>
-            <log level="info" message="Depreciation service name for the 
FixedAsset ${parameters.fixedAssetId} is ${customMethod.customMethodName}"/>
-
-            <set field="serviceInMap.fixedAssetId" 
from-field="parameters.fixedAssetId"/>
-            <set field="serviceInMap.expEndOfLifeYear" 
from-field="expEndOfLifeYear" type="Integer"/>
-            <set field="serviceInMap.assetAcquiredYear" 
from-field="assetAcquiredYear" type="Integer"/>
-            <set field="serviceInMap.purchaseCost" 
from-field="fixedAsset.purchaseCost"/>
-            <set field="serviceInMap.salvageValue" from-field="salvageValue"/>
-            <set field="serviceInMap.usageYears" from-field="usageYears" 
type="Integer"/>
-            <call-service service-name="${customMethod.customMethodName}" 
in-map-name="serviceInMap">
-                <result-to-field result-name="assetDepreciationTillDate"/>
-                <result-to-field result-name="assetNBVAfterDepreciation"/>
-                <result-to-field result-name="assetDepreciationInfoList"/>
-                <result-to-field result-name="nextDepreciationAmount"/>
-                <result-to-field result-name="plannedPastDepreciationTotal"/>
-            </call-service>
-            <log level="info" message="Asset's depreciation calculated till 
date are ${assetDepreciationTillDate}"/>
-            <log level="info" message="Asset's Net Book Values (NBV) from 
acquired date after deducting depreciation are ${assetNBVAfterDepreciation}"/>
-            <field-to-result field="assetDepreciationTillDate"/>
-            <field-to-result field="assetNBVAfterDepreciation"/>
-            <field-to-result field="assetDepreciationInfoList"/>
-            <field-to-result field="nextDepreciationAmount"/>
-            <field-to-result field="plannedPastDepreciationTotal"/>
-        <else>
-            <property-to-field resource="AccountingUiLabels" 
property="AccountingFixedAssetDepreciationMethodNotFound" 
field="successMessageList[]"/>
-            <return/>
-        </else>
-        </if-not-empty>
-    </simple-method>
-
-    <simple-method method-name="checkUpdateFixedAssetDepreciation" 
login-required="true"
-        short-description="If the accounting transaction is a depreciation 
transaction for a fixed asset, update the depreciation amount in the FixedAsset 
entity.">
-        <entity-one entity-name="AcctgTrans" value-field="acctgTrans"/>
-        <if>
-            <condition>
-                <and>
-                    <if-compare field="acctgTrans.acctgTransTypeId" 
operator="equals" value="DEPRECIATION"/>
-                    <not><if-empty field="acctgTrans.fixedAssetId"/></not>
-                </and>
-            </condition>
-            <then>
-                <get-related-one relation-name="FixedAsset" 
value-field="acctgTrans" to-value-field="fixedAsset"/>
-                <set field="creditCondition.debitCreditFlag" value="C"/>
-                <get-related relation-name="AcctgTransEntry" 
value-field="acctgTrans" list="creditTransactions" map="creditCondition"/>
-                <set field="depreciation" value="0.0" type="BigDecimal"/>
-                <iterate list="creditTransactions" entry="creditTransaction">
-                    <if-empty field="fixedAsset.purchaseCostUomId">
-                        <log level="warning" message="Found empty 
purchaseCostUomId for FixedAsset [${fixedAsset.fixedAssetId}]: setting it to 
${creditTransaction.currencyUomId} to match the one used in the gl."/>
-                        <set field="fixedAsset.purchaseCostUomId" 
from-field="creditTransaction.currencyUomId"/>
-                        <store-value value-field="fixedAsset"/>
-                    </if-empty>
-                    <if-compare-field field="fixedAsset.purchaseCostUomId" 
operator="equals" to-field="creditTransaction.currencyUomId">
-                        <calculate field="depreciation">
-                            <calcop operator="add">
-                                <calcop operator="get" field="depreciation"/>
-                                <calcop operator="get" 
field="creditTransaction.amount"/>
-                            </calcop>
-                        </calculate>
-                        <else>
-                            <if-compare-field 
field="fixedAsset.purchaseCostUomId" operator="equals" 
to-field="creditTransaction.origCurrencyUomId">
-                                <calculate field="depreciation">
-                                    <calcop operator="add">
-                                        <calcop operator="get" 
field="depreciation"/>
-                                        <calcop operator="get" 
field="creditTransaction.origAmount"/>
-                                    </calcop>
-                                </calculate>
-                                <else>
-                                    <log level="warning" message="Found an 
accounting transaction for depreciation of FixedAsset 
[${fixedAsset.fixedAssetId}] with a cuurency that doesn't match the currency 
used in the fixed asset: the depreciation total in the fixed asset will not be 
updated."/>
-                                    <return/>
-                                </else>
-                            </if-compare-field>
-                        </else>
-                    </if-compare-field>
-                </iterate>
-                <set field="depreciationTotal" 
from-field="fixedAsset.depreciation" default-value="0.0" type="BigDecimal"/>
-                <calculate field="depreciationTotal">
-                    <calcop operator="add">
-                        <calcop operator="get" field="depreciation"/>
-                        <calcop operator="get" field="depreciationTotal"/>
-                    </calcop>
-                </calculate>
-                <set field="fixedAsset.depreciation" 
from-field="depreciationTotal"/>
-                <store-value value-field="fixedAsset"/>
-            </then>
-        </if>
-    </simple-method>
-
-</simple-methods>
diff --git a/applications/accounting/servicedef/services_fixedasset.xml 
b/applications/accounting/servicedef/services_fixedasset.xml
index 40dbd5f8ec..a577499fc9 100644
--- a/applications/accounting/servicedef/services_fixedasset.xml
+++ b/applications/accounting/servicedef/services_fixedasset.xml
@@ -120,8 +120,8 @@ under the License.
         <auto-attributes include="pk" mode="IN" optional="false"/>
     </service>
     <!-- FixedAsset Maintenance Create/Update/Delete-->
-    <service name="createFixedAssetMaint" 
default-entity-name="FixedAssetMaint" engine="simple"
-                
location="component://accounting/minilang/fixedasset/FixedAssetServices.xml" 
invoke="createFixedAssetMaint" auth="true">
+    <service name="createFixedAssetMaint" 
default-entity-name="FixedAssetMaint" engine="groovy"
+             
location="component://accounting/src/main/groovy/org/apache/ofbiz/accounting/fixedasset/FixedAssetServices.groovy"
 invoke="createFixedAssetMaint" auth="true">
         <description>Create a Fixed Asset Maintenance</description>
         <permission-service service-name="fixedAssetPermissionCheck" 
main-action="CREATE"/>
         <auto-attributes include="pk" mode="IN" optional="false"/>
@@ -131,8 +131,8 @@ under the License.
         <attribute name="maintTemplateWorkEffortId" mode="IN" type="String" 
optional="true"/>
         <override name="maintHistSeqId" mode="OUT"/> <!-- make this OUT rather 
than IN, we will automatically generate the next sub-sequence ID -->
     </service>
-    <service name="updateFixedAssetMaint" 
default-entity-name="FixedAssetMaint" engine="simple"
-                
location="component://accounting/minilang/fixedasset/FixedAssetServices.xml" 
invoke="updateFixedAssetMaint" auth="true">
+    <service name="updateFixedAssetMaint" 
default-entity-name="FixedAssetMaint" engine="groovy"
+             
location="component://accounting/src/main/groovy/org/apache/ofbiz/accounting/fixedasset/FixedAssetServices.groovy"
 invoke="updateFixedAssetMaint" auth="true">
         <description>Update a Fixed Asset Maintenance</description>
         <permission-service service-name="fixedAssetPermissionCheck" 
main-action="UPDATE"/>
         <auto-attributes include="pk" mode="IN" optional="false"/>
@@ -144,13 +144,19 @@ under the License.
         <permission-service service-name="fixedAssetPermissionCheck" 
main-action="DELETE"/>
         <auto-attributes include="pk" mode="IN" optional="false"/>
     </service>
-    <service name="createMaintsFromTimeInterval" engine="simple" 
use-transaction="false"
-                
location="component://accounting/minilang/fixedasset/FixedAssetServices.xml" 
invoke="createMaintsFromTimeInterval" auth="true">
+    <service name="createMaintsFromTimeInterval"  engine="groovy"
+             
location="component://accounting/src/main/groovy/org/apache/ofbiz/accounting/fixedasset/FixedAssetServices.groovy"
+             use-transaction="false" invoke="createMaintsFromTimeInterval" 
auth="true">
         <description>Create Fixed Asset Maintenances from ProductMaint time 
intervals. Currently works
         with day, month, and year interval types. This service is intended to 
be run as a regularly
         scheduled job.</description>
         <permission-service service-name="fixedAssetPermissionCheck" 
main-action="CREATE"/>
     </service>
+    <service name="autoAssignFixedAssetPartiesToMaintenance" engine="groovy"
+             
location="component://accounting/src/main/groovy/org/apache/ofbiz/accounting/fixedasset/FixedAssetServices.groovy"
 invoke="autoAssignFixedAssetPartiesToMaintenance" auth="true">
+        <attribute name="fixedAssetId" type="String" mode="IN"/>
+        <attribute name="workEffortId" type="String" mode="IN"/>
+    </service>
     <!-- FixedAsset Maintenance Meter Create/Update/Delete-->
     <service name="createFixedAssetMeter" 
default-entity-name="FixedAssetMeter" engine="entity-auto" invoke="create" 
auth="true">
         <description>Create a Fixed asset Meter</description>
@@ -164,8 +170,8 @@ under the License.
         <auto-attributes include="pk" mode="IN" optional="false"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
     </service>
-    <service name="createMaintsFromMeterReading" 
default-entity-name="FixedAssetMeter" engine="simple"
-             
location="component://accounting/minilang/fixedasset/FixedAssetServices.xml" 
invoke="createMaintsFromMeterReading" auth="true">
+    <service name="createMaintsFromMeterReading" 
default-entity-name="FixedAssetMeter" engine="groovy"
+             
location="component://accounting/src/main/groovy/org/apache/ofbiz/accounting/fixedasset/FixedAssetServices.groovy"
 invoke="createMaintsFromMeterReading" auth="true">
         <description>Create Maints From Meter Reading</description>
         <auto-attributes include="pk" mode="IN" optional="false"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
@@ -176,8 +182,8 @@ under the License.
         <auto-attributes include="pk" mode="IN" optional="false"/>
     </service>
     <!-- FixedAsset Maintenance Order Create/Update/Delete-->
-    <service name="createFixedAssetMaintOrder" 
default-entity-name="FixedAssetMaintOrder" engine="simple"
-                
location="component://accounting/minilang/fixedasset/FixedAssetServices.xml" 
invoke="createFixedAssetMaintOrder" auth="true">
+    <service name="createFixedAssetMaintOrder" 
default-entity-name="FixedAssetMaintOrder" engine="groovy"
+                
location="component://accounting/src/main/groovy/org/apache/ofbiz/accounting/fixedasset/FixedAssetServices.groovy"
 invoke="createFixedAssetMaintOrder" auth="true">
         <description>Create a Fixed Asset Maintenance Order</description>
         <permission-service service-name="fixedAssetPermissionCheck" 
main-action="CREATE"/>
         <attribute name="fixedAssetId" type="String" mode="IN" 
optional="false"/>
@@ -230,8 +236,8 @@ under the License.
         <permission-service service-name="fixedAssetPermissionCheck" 
main-action="DELETE"/>
         <auto-attributes include="pk" mode="IN" optional="false"/>
     </service>
-    <service name="checkUpdateFixedAssetDepreciation" 
default-entity-name="AcctgTrans" engine="simple"
-              
location="component://accounting/minilang/fixedasset/FixedAssetServices.xml" 
invoke="checkUpdateFixedAssetDepreciation" auth="true">
+    <service name="checkUpdateFixedAssetDepreciation" 
default-entity-name="AcctgTrans" engine="groovy" auth="true"
+                
location="component://accounting/src/main/groovy/org/apache/ofbiz/accounting/fixedasset/FixedAssetServices.groovy"
 invoke="checkUpdateFixedAssetDepreciation">
         <description>If the accounting transaction is a depreciation 
transaction for a fixed asset, update the depreciation amount in the FixedAsset 
entity.</description>
         <permission-service service-name="fixedAssetPermissionCheck" 
main-action="UPDATE"/>
         <auto-attributes include="pk" mode="IN" optional="false"/>
@@ -249,20 +255,20 @@ under the License.
         <attribute name="nextDepreciationAmount" type="BigDecimal" mode="OUT" 
optional="false"/>
         <attribute name="plannedPastDepreciationTotal" type="BigDecimal" 
mode="OUT" optional="false"/>
     </service>
-    <service name="straightLineDepreciation" engine="simple" 
default-entity-name="FixedAsset"
-                
location="component://accounting/minilang/fixedasset/FixedAssetServices.xml" 
invoke="straightLineDepreciation" auth="true">
+    <service name="straightLineDepreciation" default-entity-name="FixedAsset" 
engine="groovy" auth="true"
+             
location="component://accounting/src/main/groovy/org/apache/ofbiz/accounting/fixedasset/FixedAssetServices.groovy"
 invoke="straightLineDepreciation">
         <description>Straight line depreciation service to Fixed 
Asset</description>
         <implements service="fixedAssetDepCalcInterface"/>
         <auto-attributes include="pk" mode="IN" optional="false"/>
     </service>
-    <service name="doubleDecliningBalanceDepreciation" engine="simple" 
default-entity-name="FixedAsset"
-                
location="component://accounting/minilang/fixedasset/FixedAssetServices.xml" 
invoke="doubleDecliningBalanceDepreciation" auth="true">
+    <service name="doubleDecliningBalanceDepreciation" 
default-entity-name="FixedAsset" engine="groovy" auth="true"
+             
location="component://accounting/src/main/groovy/org/apache/ofbiz/accounting/fixedasset/FixedAssetServices.groovy"
 invoke="doubleDecliningBalanceDepreciation">
         <description>Double declining balance depreciation service to Fixed 
Asset</description>
         <implements service="fixedAssetDepCalcInterface"/>
         <auto-attributes include="pk" mode="IN" optional="false"/>
     </service>
-    <service name="calculateFixedAssetDepreciation" engine="simple" 
default-entity-name="FixedAssetDepMethod"
-                
location="component://accounting/minilang/fixedasset/FixedAssetServices.xml" 
invoke="calculateFixedAssetDepreciation" auth="true">
+    <service name="calculateFixedAssetDepreciation" 
default-entity-name="FixedAssetDepMethod" engine="groovy" auth="true"
+             
location="component://accounting/src/main/groovy/org/apache/ofbiz/accounting/fixedasset/FixedAssetServices.groovy"
 invoke="calculateFixedAssetDepreciation">
         <description>Select the depreciation method according to the entry in 
FixedAssetDepMethod</description>
         <attribute name="fixedAssetId" type="String" mode="IN"/>
         <attribute name="assetDepreciationTillDate" type="List" mode="OUT" 
optional="true"/>
diff --git 
a/applications/accounting/src/main/groovy/org/apache/ofbiz/accounting/fixedasset/FixedAssetServices.groovy
 
b/applications/accounting/src/main/groovy/org/apache/ofbiz/accounting/fixedasset/FixedAssetServices.groovy
new file mode 100644
index 0000000000..f85e67e1ae
--- /dev/null
+++ 
b/applications/accounting/src/main/groovy/org/apache/ofbiz/accounting/fixedasset/FixedAssetServices.groovy
@@ -0,0 +1,464 @@
+import org.apache.ofbiz.base.util.UtilDateTime
+import org.apache.ofbiz.entity.GenericValue
+import org.apache.ofbiz.entity.condition.EntityCondition
+import org.apache.ofbiz.entity.condition.EntityConditionBuilder
+
+import java.math.RoundingMode
+import java.sql.Timestamp
+
+/*
+ * 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.
+ */
+
+/**
+ * create a FixedAssetMaint
+ */
+Map createFixedAssetMaint() {
+    GenericValue newEntity = makeValue('FixedAssetMaint', parameters)
+    String maintTemplateWorkEffortId
+    newEntity.maintHistSeqId = delegator.getNextSeqId('FixedAssetMaint')
+    GenericValue fixedAsset = from('FixedAsset').where(parameters).queryOne()
+    if (parameters.productMaintSeqId) {
+        GenericValue productMaint = from('ProductMaint')
+                .where(productId: fixedAsset.instanceOfProductId,
+                        productMaintSeqId: parameters.productMaintSeqId)
+                .queryOne()
+        newEntity.productMaintTypeId = productMaint.productMaintTypeId
+        maintTemplateWorkEffortId = productMaint.maintTemplateWorkEffortId ?: 
parameters.maintTemplateWorkEffortId
+    }
+    if (maintTemplateWorkEffortId) {
+        String workEffortId = delegator.getNextSeqId('WorkEffort')
+        run service: 'duplicateWorkEffort', with:
+                [oldWorkEffortId: maintTemplateWorkEffortId,
+                 workEffortId: workEffortId,
+                 duplicateWorkEffortAssocs: 'Y',
+                 duplicateWorkEffortNotes: 'Y',
+                 duplicateWorkEffortContents: 'Y',
+                 duplicateWorkEffortAssignmentRates: 'Y']
+        newEntity.scheduleWorkEffortId = workEffortId
+    } else {
+        // Create the WorkEffort and Maintenance WorkEffort entity
+        Map maintWorkEffortMap = [workEffortTypeId: 'TASK',
+                                  workEffortName: label('AccountingUiLabels', 
'AccountingFixedAssetMaintWorkEffortName'),
+                                  workEffortPurposeTypeId: 'WEPT_MAINTENANCE',
+                                  currentStatusId: 'CAL_TENTATIVE',
+                                  quickAssignPartyId: userLogin.partyId,
+                                  fixedAssetId: fixedAsset.fixedAssetId,
+                                  estimatedStartDate: 
parameters.estimatedStartDate,
+                                  estimatedCompletionDate: 
parameters.estimatedCompletionDate]
+        maintWorkEffortMap.description = 
delegator.getRelatedOne('ProductMaintType', newEntity, true)?.description
+        Map serviceResult = run service: 'createWorkEffort', with: 
maintWorkEffortMap
+        newEntity.scheduleWorkEffortId = serviceResult.workEffortId
+    }
+    newEntity.create()
+    run service: 'autoAssignFixedAssetPartiesToMaintenance', with: 
[fixedAssetId: fixedAsset.fixedAssetId,
+                                                                    
workEffortId: newEntity.scheduleWorkEffortId]
+    return success([maintHistSeqId: newEntity.maintHistSeqId])
+}
+
+/**
+ * update an existing FixedAsset Maintenance
+ */
+Map updateFixedAssetMaint() {
+    GenericValue lookedUpValue = 
from('FixedAssetMaint').where(parameters).queryOne()
+    String oldStatusId = lookedUpValue.statusId
+    lookedUpValue.setNonPKFields(parameters)
+    GenericValue fixedAsset = 
from('FixedAsset').where(parameters).cache().queryOne()
+    if (parameters.productMaintSeqId) {
+        GenericValue productMaint = from('ProductMaint')
+                .where(productId: fixedAsset.instanceOfProductId,
+                        productMaintSeqId: parameters.productMaintSeqId)
+                .queryOne()
+        lookedUpValue.productMaintTypeId = productMaint.productMaintTypeId
+    }
+    lookedUpValue.store()
+    if (lookedUpValue.statusId == 'FAM_COMPLETED'
+            && oldStatusId != lookedUpValue.statusId) {
+        GenericValue workEffort = from('WorkEffort')
+                .where(workEffortId: lookedUpValue.scheduleWorkEffortId)
+                .cache()
+                .queryOne()
+        if (workEffort && !workEffort.actualCompletionDate && 
workEffort.currentStatusId != 'CAL_COMPLETED') {
+            Timestamp nowTimestamp = UtilDateTime.nowTimestamp()
+            run service: 'updateWorkEffort', with: [workEffortId: 
workEffort.workEffortId,
+                                                    currentStatusId: 
'CAL_ACCEPTED']
+            run service: 'updateWorkEffort', with: [workEffortId: 
workEffort.workEffortId,
+                                                    actualCompletionDate: 
nowTimestamp,
+                                                    currentStatusId: 
'CAL_COMPLETED']
+            delegator.storeByCondition('WorkEffortPartyAssignment',
+                    [thruDate: nowTimestamp],
+                    EntityCondition.makeCondition([
+                            EntityCondition.makeCondition('workEffortId', 
workEffort.workEffortId),
+                            EntityCondition.makeConditionDate('fromDate', 
'thruDate')]))
+        }
+    }
+    return success()
+}
+
+/**
+ * Create Fixed Asset Maintenances From A Meter Reading
+ */
+Map createMaintsFromMeterReading() {
+    if (parameters.maintHistSeqId) {
+        return success()
+    }
+    GenericValue fixedAsset = 
from('FixedAsset').where(parameters).cache().queryOne()
+    if (!fixedAsset.instanceOfProductId) {
+        return success()
+    }
+    from('ProductMaint')
+            .where(productId: fixedAsset.instanceOfProductId,
+                    intervalMeterTypeId: parameters.productMeterTypeId)
+            .queryList()
+            .each {p ->
+                long repeatCount = p.repeatCount ?: 0l
+                EntityCondition cond = new EntityConditionBuilder().AND {
+                    EQUALS(fixedAssetId: fixedAsset.fixedAssetId)
+                    EQUALS(intervalMeterTypeId: p.intervalMeterTypeId)
+                    EQUALS(productMaintTypeId: p.productMaintTypeId)
+                    NOT_EQUAL(statusId: 'FAM_CANCELLED')
+                }
+                List maintList = from('FixedAssetMaint')
+                        .where(cond)
+                        .queryList()
+                long listSize = maintList ? maintList.size(): 0l
+
+                BigDecimal maxIntervalQty = maintList ? maintList.stream()
+                        .map { v -> v.intervalQuantity ?: 0 }
+                        .collect()
+                        .max(): 0
+
+                BigDecimal nextIntervalQty = maxIntervalQty + 
p.intervalQuantity
+                if (parameters.meterValue &&
+                        (nextIntervalQty > parameters.meterValue ||
+                            (repeatCount > 0 && listSize < repeatCount))) {
+                    run service: 'createFixedAssetMaint', with: [*  : 
p.getAllFields(),
+                                                                 fixedAssetId: 
fixedAsset.fixedAssetId,
+                                                                 
intervalQuantity: parameters.meterValue,
+                                                                 statusId: 
'FAM_CREATED']
+                }
+            }
+    return success()
+}
+
+/**
+ * Create Fixed Asset Maintenances From A Product Maint Time Interval
+ */
+Map createMaintsFromTimeInterval() {
+    Timestamp nowTimestamp = UtilDateTime.nowTimestamp()
+    EntityCondition cond = new EntityConditionBuilder().AND {
+        NOT_EQUAL(instanceOfProductId: null)
+        EQUALS(actualEndOfLife: null)
+    }
+    Map timeSwitch = [TF_day: Calendar.DAY_OF_MONTH,
+                      TF_mon: Calendar.MONTH,
+                      TF_yr: Calendar.YEAR]
+    from('FixedAsset')
+    .where(cond)
+    .queryList()
+    .each {f ->
+        cond = new EntityConditionBuilder().AND {
+            EQUALS(productId: f.instanceOfProductId)
+            LIKE(intervalUomId: 'TF_%')
+        }
+        from('ProductMaint')
+        .where(cond)
+        .queryList()
+        .each {p ->
+            if (timeSwitch.containsKey(p.intervalUomId)) {
+                long repeatCount = p.repeatCount ?: 0
+                long intervalQuantity = p.intervalQuantity ?: 0
+                Calendar calendar = Calendar.instance()
+                calendar.setTime(nowTimestamp)
+                calendar.add(timeSwitch[p.intervalUomId], -p.intervalQuantity)
+                cond = new EntityConditionBuilder().AND {
+                    EQUALS(fixedAssetId: f.fixedAssetId)
+                    EQUALS(intervalUomId: p.intervalUomId)
+                    EQUALS(productMaintTypeId: p.productMaintTypeId)
+                    NOT_EQUAL(statusId: 'FAM_CANCELLED')
+                }
+                List<GenericValue> maintList = 
from('FixedAssetMaintWorkEffort')
+                        .where(cond)
+                        .orderBy('maintHistSeqId')
+                        .queryList()
+                long listSize = maintList ? maintList.size(): 0
+                Timestamp lastSvcDate = maintList ? 
maintList.last().actualCompletionDate: null
+                if (lastSvcDate && lastSvcDate.before(calendar.getTime())
+                        && (repeatCount <= 0 || listSize < repeatCount)) {
+                    run service: 'createFixedAssetMaint', with: [*: 
p.getAllFields(),
+                                                                 fixedAssetId: 
f.fixedAssetId,
+                                                                 statusId: 
'FAM_CREATED']
+                }
+            }
+        }
+    }
+    return success()
+}
+
+/**
+ * Create a FixedAsset Maintenance Order
+ * @return
+ */
+Map createFixedAssetMaintOrder() {
+    GenericValue lookedUpValue = 
from('OrderHeader').where(parameters).queryOne()
+    if (!lookedUpValue) {
+        return error(label('AccountingUiLabels', 
'AccountingOrderWithIdNotFound', parameters))
+    }
+
+    // Check if user has not passed in orderItemSeqId then get list of 
OrderItems from database and default to first item
+    if (!parameters.orderItemSeqId) {
+        parameters.orderItemSeqId = from('OrderItem').where(orderId: 
lookedUpValue.orderId).queryList()?.orderItemSeqId
+    } else {
+        lookedUpValue = from('OrderItem').where(parameters).queryOne()
+        if (!lookedUpValue) {
+            return error(label('AccountingUiLabels', 
'AccountingOrderItemWithIdNotFound', parameters))
+        }
+    }
+    delegator.create('FixedAssetMaintOrder', parameters)
+    return success()
+}
+
+/**
+ * Auto-assign Fixed Asset Parties to a Fixed Asset Maintenance
+ */
+Map autoAssignFixedAssetPartiesToMaintenance() {
+    from('PartyFixedAssetAssignAndRole')
+            .where(fixedAssetId: parameters.fixedAssetId,
+                    parentTypeId: 'FAM_ASSIGNEE')
+            .filterByDate()
+            .queryList()
+    .each {
+        run service: 'assignPartyToWorkEffort', with: [partyId: it.partyId,
+                                                       roleTypeId: 
it.roleTypeId,
+                                                       workEffortId: 
parameters.workEffortId,
+                                                       statusId: 
'PRTYASGN_ASSIGNED']
+    }
+    return success()
+}
+
+
+/**
+ * Calculate straight line depreciation to Fixed Asset[ (PC-SV)/expLife ]
+ */
+Map straightLineDepreciation() {
+    BigDecimal depreciationTotal = 0
+    BigDecimal depreciation = 0
+    List assetDepreciationInfoList = []
+    List assetDepreciationTillDate = []
+    List assetNBVAfterDepreciation = []
+    BigDecimal purchaseCost = parameters.purchaseCost
+    GenericValue fixedAsset = from('FixedAsset').where(parameters).queryOne()
+    if (! fixedAsset) {
+        return error(label('AccountingErrorUiLabels', 
'AccountingFixedAssetNotFound'))
+    }
+    if (parameters.usageYears > 0) {
+        //FORMULA :  depreciation = (purchaseCost - salvageValue) / 
(expectedEndOfLife - dateAcquired)
+        int numberOfYears = parameters.expEndOfLifeYear - 
parameters.assetAcquiredYear
+        if (numberOfYears > 0) {
+            depreciation = (purchaseCost - parameters.salvageValue) / 
numberOfYears
+            depreciation.setScale(2, RoundingMode.HALF_EVEN)
+            int intUsageYears =  (numberOfYears < parameters.intUsageYears) ? 
parameters.intUsageYears : numberOfYears
+            for (int i = 1; i++; i <intUsageYears) {
+                purchaseCost -= depreciation
+                depreciationTotal += depreciation
+                assetDepreciationTillDate << depreciation
+                assetNBVAfterDepreciation << purchaseCost
+                assetDepreciationInfoList << [year: i,
+                                              depreciation: depreciation,
+                                              depreciationTotal: 
depreciationTotal,
+                                              nbv: purchaseCost]
+            }
+        }
+    }
+
+    if (! assetDepreciationTillDate) {
+        assetDepreciationTillDate << depreciation
+        assetNBVAfterDepreciation << purchaseCost
+        assetDepreciationInfoList << [year: parameters.assetAcquiredYear,
+                                      depreciation: depreciation,
+                                      depreciationTotal: depreciationTotal,
+                                      nbv: purchaseCost]
+    }
+    logInfo "Using straight line formula depreciation calculated for 
fixedAsset (${parameters.fixedAssetId}) is ${depreciation}"
+
+    // Next depreciation based on actual depreciation history
+    BigDecimal nextDepreciationAmount = 0
+
+    // FORMULA : depreciation = (purchaseCost - salvageValue - 
pastDepreciations) / remainingYears
+    int remainingYears  = parameters.expEndOfLifeYear - 
parameters.assetAcquiredYear - parameters.intUsageYears
+    if (remainingYears > 0) {
+        nextDepreciationAmount = (fixedAsset.purchaseCost - 
parameters.salvageValue - fixedAsset.depreciation) / remainingYears
+        nextDepreciationAmount.setScale(2, RoundingMode.HALF_EVEN)
+    }
+    return success([assetDepreciationTillDate: assetDepreciationTillDate,
+                    assetNBVAfterDepreciation: assetNBVAfterDepreciation,
+                    assetDepreciationInfoList: assetDepreciationInfoList,
+                    nextDepreciationAmount: nextDepreciationAmount,
+                    plannedPastDepreciationTotal: depreciationTotal - 
fixedAsset.depreciation])
+}
+
+/**
+ * Calculate double declining balance depreciation to Fixed Asset
+ */
+Map doubleDecliningBalanceDepreciation() {
+    String expEndOfLifeYear = parameters.expEndOfLifeYear
+    String assetAcquiredYear = parameters.assetAcquiredYear
+    String purchaseCost = parameters.purchaseCost
+    String salvageValue = parameters.salvageValue
+
+    // Next depreciation based on actual depreciation history
+    BigDecimal nextDepreciationAmount = 0
+    GenericValue fixedAsset = from('FixedAsset').where(parameters).queryOne()
+    if (fixedAsset) {
+        int remainingYears = expEndOfLifeYear - assetAcquiredYear - 
parameters.usageYears
+        if (remainingYears > 0) {
+            nextDepreciationAmount = 2 * (purchaseCost - salvageValue - 
fixedAsset.depreciation) / remainingYears
+        }
+    }
+
+    List assetDepreciationTillDate = []
+    List assetNBVAfterDepreciation = []
+    List assetDepreciationInfoList = []
+    BigDecimal depreciationTotal = 0
+    if (parameters.usageYears > 0 && fixedAsset) {
+        BigDecimal depreciationYear = assetAcquiredYear
+        for (int i = 0; i < parameters.usageYears; i++) {
+            BigDecimal depreciation = 0
+            int numberOfYears = expEndOfLifeYear - assetAcquiredYear
+            if (numberOfYears > 0) {
+                depreciation = (purchaseCost - salvageValue) * 2 / 
numberOfYears
+            }
+            assetAcquiredYear++
+            purchaseCost -= depreciation
+            depreciationTotal += depreciation
+            assetDepreciationTillDate << depreciation
+            assetNBVAfterDepreciation << purchaseCost
+            assetDepreciationInfoList << [nbv: purchaseCost,
+                                          year: depreciationYear,
+                                          depreciation: depreciation,
+                                          depreciationTotal: depreciationTotal]
+        }
+
+        if (!assetDepreciationTillDate) {
+            assetDepreciationTillDate << 0
+            assetNBVAfterDepreciation << purchaseCost
+            assetDepreciationInfoList << [nbv: purchaseCost,
+                                          year: assetAcquiredYear,
+                                          depreciation: 0,
+                                          depreciationTotal: depreciationTotal]
+        }
+    }
+    logInfo "Using double decline formula depreciation calculated for 
fixedAsset (${parameters.fixedAssetId}) is ${assetDepreciationTillDate}"
+    return success([assetDepreciationTillDate: assetDepreciationTillDate,
+                    assetNBVAfterDepreciation: assetNBVAfterDepreciation,
+                    assetDepreciationInfoList: assetDepreciationInfoList,
+                    nextDepreciationAmount: nextDepreciationAmount,
+                    plannedPastDepreciationTotal: depreciationTotal - 
fixedAsset.depreciation])
+}
+
+/**
+ * Service to calculate the yearly depreciation from dateAcquired year to 
current financial year
+ */
+Map calculateFixedAssetDepreciation() {
+    GenericValue fixedAsset = from('FixedAsset').where(parameters).queryOne()
+    if (!fixedAsset) {
+        return error(label('ManufacturingUiLabels', 
'ManufacturingFixedAssetNotExist'))
+    }
+    String expEndOfLifeYear, assetAcquiredYear
+
+    // Extract asset end of life year from field expectedEndOfLife
+    if (fixedAsset.expectedEndOfLife) {
+        expEndOfLifeYear = 
fixedAsset.expectedEndOfLife.toString().substring(0, 4)
+    } else {
+        return success(label('AccountingUiLabels', 
'AccountingExpEndOfLifeIsEmpty'))
+    }
+
+    // Extract asset acquired year from field dateAcquired
+    if (fixedAsset.expectedEndOfLife) {
+        assetAcquiredYear = fixedAsset.dateAcquired.toString().substring(0, 4)
+    } else {
+        return success(label('AccountingUiLabels', 
'AccountingDateAcquiredIsEmpty'))
+    }
+
+    // if any asset's salvage value is empty then set it by 0
+    BigDecimal salvageValue = fixedAsset.salvageValue ?: 0.0
+
+    // Get running year
+    String currentYear = UtilDateTime.nowAsString().substring(0, 4)
+
+    // Calculate asset's total run in years
+    int usageYears = currentYear - assetAcquiredYear
+
+    GenericValue fixedAssetDepMethod = from('FixedAssetDepMethod')
+            .where(fixedAssetId: parameters.fixedAssetId)
+            .filterByDate()
+            .queryFirst()
+    if (fixedAssetDepMethod) {
+        GenericValue customMethod = 
fixedAssetDepMethod.getRelatedOne('CustomMethod', true)
+        logInfo "Depreciation service name for the FixedAsset 
${parameters.fixedAssetId} is ${customMethod.customMethodName}"
+        Map serviceResult = run service: customMethod.customMethodName, with: [
+                fixedAssetId: parameters.fixedAssetId,
+                expEndOfLifeYear: expEndOfLifeYear,
+                assetAcquiredYear: assetAcquiredYear,
+                purchaseCost: fixedAsset.purchaseCost,
+                salvageValue: salvageValue,
+                usageYears: usageYears]
+        logInfo "Asset's depreciation calculated till date are 
${serviceResult.assetDepreciationTillDate}"
+        logInfo "Asset's Net Book Values (NBV) from acquired date after 
deducting depreciation are ${serviceResult.assetNBVAfterDepreciation}"
+        return serviceResult
+    }
+    return error(label('AccountingUiLabels', 
'AccountingFixedAssetDepreciationMethodNotFound'))
+}
+
+/**
+ * If the accounting transaction is a depreciation transaction for a fixed 
asset, update the depreciation amount in the FixedAsset entity.
+ */
+Map checkUpdateFixedAssetDepreciation() {
+    GenericValue acctgTrans = from('AcctgTrans').where(parameters).queryOne()
+    if (!acctgTrans &&
+            acctgTrans.acctgTransTypeId == 'DEPRECIATION'
+            && acctgTrans.fixedAssetId) {
+        GenericValue fixedAsset = acctgTrans.getRelatedOne('FixedAsset', true)
+        BigDecimal depreciation = 0
+        boolean nonValidUom = false
+        from('AcctgTransEntry')
+                .where(debitCreditFlag: 'C',
+                        acctgTransId: acctgTrans.acctgTransId)
+                .queryList()
+                .each {
+                    if (!fixedAsset.purchaseCostUomId) {
+                        logWarning "Found empty purchaseCostUomId for 
FixedAsset [${fixedAsset.fixedAssetId}]: setting it to 
${creditTransaction.currencyUomId} to match the one used in the gl."
+                        fixedAsset.purchaseCostUomId = it.currencyUomId
+                        fixedAsset.store()
+                    }
+                    if (fixedAsset.purchaseCostUomId == it.currencyUomId) {
+                        depreciation += it.amount
+                    } else {
+                        nonValidUom = true
+                    }
+                }
+        if (nonValidUom) {
+            return failure("Found an accounting transaction for depreciation 
of FixedAsset [${fixedAsset.fixedAssetId}] with a currency that doesn't match 
the currency used in the fixed asset: the depreciation total in the fixed asset 
will not be updated.")
+        }
+
+        fixedAsset.depreciation = fixedAsset.depreciation ?: 0
+        fixedAsset.depreciation += depreciation
+        fixedAsset.store()
+    }
+    return success()
+}

Reply via email to