<?xml version="1.0" encoding="UTF-8"?>
<!--
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.
-->

<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://ofbiz.apache.org/Simple-Method" xsi:schemaLocation="http://ofbiz.apache.org/Simple-Method http://ofbiz.apache.org/dtds/simple-methods.xsd">

    <simple-method method-name="createProject" short-description="Create a project">
        <if-not-empty field="parameters.templateId">
            <set field="parameters.projectId" from-field="parameters.templateId"/>
            <call-simple-method method-name="copyProject"/>
            <else>
                <set field="parameters.currentStatusId" value="PRJ_ACTIVE"/>
                <call-simple-method method-name="createWorkEffort" xml-resource="component://workeffort/minilang/workeffort/WorkEffortSimpleServices.xml"/>
            </else>
        </if-not-empty>
        <set field="parameters.workEffortId" from-field="newEntity.workEffortId"/>
        <if-not-empty field="parameters.organizationPartyId">
            <set field="updProjectRole.newPartyId" from-field="parameters.organizationPartyId"/>
            <set field="updProjectRole.roleTypeId" value="INTERNAL_ORGANIZATIO"/>
            <call-simple-method method-name="updProjectRole"/>
        </if-not-empty>
        <if-not-empty field="parameters.clientBillingPartyId">
            <set field="updProjectRole.newPartyId" from-field="parameters.clientBillingPartyId"/>
            <set field="updProjectRole.roleTypeId" value="CLIENT_BILLING"/>
            <call-simple-method method-name="updProjectRole"/>
        </if-not-empty>
        <if-not-empty field="parameters.emailAddress">
            <if-validate-method field="parameters.emailAddress" method="isEmail">
                <else><add-error><fail-property resource="PartyUiLabels" property="PartyEmailAddressNotFormattedCorrectly"/></add-error></else>
            </if-validate-method>
            <check-errors/>
            
            <!-- create new work effort's e-mail address -->
            <set field="emailAddressIn.emailAddress" from-field="parameters.emailAddress"/>
            <set field="emailAddressIn.contactMechTypeId" value="EMAIL_ADDRESS"/>
            <call-service service-name="createEmailAddress" in-map-name="emailAddressIn">
                <result-to-field result-name="contactMechId"/>
            </call-service>
            <set field="workEffortContactMechIn.workEffortId" from-field="parameters.workEffortId"/>
            <set field="workEffortContactMechIn.contactMechId" from-field="contactMechId"/>
            <set field="workEffortContactMechIn.contactMechTypeId" value="EMAIL_ADDRESS"/>
            <set field="workEffortContactMechIn.infoString" from-field="parameters.emailAddress"/>
            <call-service service-name="createWorkEffortContactMech" in-map-name="workEffortContactMechIn"/>
        </if-not-empty>
    </simple-method>

    <simple-method method-name="updateProject" short-description="Update a project">
        <set-service-fields service-name="updateWorkEffort" map="parameters" to-map="updWorkEffort"/>
        <call-service service-name="updateWorkEffort" in-map-name="updWorkEffort"/>
        <if-not-empty field="parameters.organizationPartyId">
            <set field="updProjectRole.newPartyId" from-field="parameters.organizationPartyId"/>
            <set field="updProjectRole.roleTypeId" value="INTERNAL_ORGANIZATIO"/>
            <call-simple-method method-name="updProjectRole"/>
        </if-not-empty>
        <if-not-empty field="parameters.clientBillingPartyId">
            <set field="updProjectRole.newPartyId" from-field="parameters.clientBillingPartyId"/>
            <set field="updProjectRole.roleTypeId" value="CLIENT_BILLING"/>
            <call-simple-method method-name="updProjectRole"/>
        </if-not-empty>
        <if-not-empty field="parameters.emailAddress">
            <if-validate-method field="parameters.emailAddress" method="isEmail">
                <else><add-error><fail-property resource="PartyUiLabels" property="PartyEmailAddressNotFormattedCorrectly"/></add-error></else>
            </if-validate-method>
            <check-errors/>
            
            <!-- find exist e-mail address. if have not exist then create new-->
            <entity-condition entity-name="WorkEffortContactMechView" list="existEmailAddresses">
                <condition-list combine="and">
                    <condition-expr field-name="workEffortId" from-field="parameters.workEffortId"/>
                    <condition-expr field-name="contactMechTypeId" value="EMAIL_ADDRESS"/>
                    <condition-expr field-name="infoString" from-field="parameters.emailAddress" ignore-case="true"/>
                </condition-list>
            </entity-condition>
            <filter-list-by-date list="existEmailAddresses"/>
            <if-empty field="existEmailAddresses">
                <!-- expire old work effort's e-mail address -->
                <entity-and list="oldEmailAddresses" entity-name="WorkEffortContactMechView">
                    <field-map field-name="workEffortId" from-field="parameters.workEffortId"/>
                    <field-map field-name="contactMechTypeId" value="EMAIL_ADDRESS"/>
                </entity-and>
                <filter-list-by-date list="oldEmailAddresses"/>
                <iterate list="oldEmailAddresses" entry="oldEmailAddress">
                    <entity-and list="oldWorkEffortContactMechs" entity-name="WorkEffortContactMech">
                        <field-map field-name="workEffortId" from-field="oldEmailAddress.workEffortId"/>
                        <field-map field-name="contactMechId" from-field="oldEmailAddress.contactMechId"/>
                    </entity-and>
                    <first-from-list list="oldWorkEffortContactMechs" entry="oldWorkEffortContactMech"/>
                    <now-timestamp field="oldWorkEffortContactMech.thruDate"/>
                    <store-value value-field="oldWorkEffortContactMech"/>
                </iterate>
                
                <!-- create new work effort's e-mail address -->
                <set field="emailAddressIn.emailAddress" from-field="parameters.emailAddress"/>
                <set field="emailAddressIn.contactMechTypeId" value="EMAIL_ADDRESS"/>
                <call-service service-name="createEmailAddress" in-map-name="emailAddressIn">
                    <result-to-field result-name="contactMechId"/>
                </call-service>
                <set field="workEffortContactMechIn.workEffortId" from-field="parameters.workEffortId"/>
                <set field="workEffortContactMechIn.contactMechId" from-field="contactMechId"/>
                <set field="workEffortContactMechIn.contactMechTypeId" value="EMAIL_ADDRESS"/>
                <set field="workEffortContactMechIn.infoString" from-field="parameters.emailAddress"/>
                <call-service service-name="createWorkEffortContactMech" in-map-name="workEffortContactMechIn"/>
            </if-empty>
        </if-not-empty>
    </simple-method>

    <simple-method method-name="updProjectRole"
        short-description="update/create a specif role and type for a project
                            input map: updProjectRole.newPartyId, updProjectRole.roleTypeId">
        <entity-and entity-name="WorkEffortPartyAssignment" list="workEffortPartyAssignments" filter-by-date="true">
            <field-map field-name="workEffortId" from-field="parameters.workEffortId"/>
            <field-map field-name="roleTypeId" from-field="updProjectRole.roleTypeId"/>
        </entity-and>
        <!-- end current record if required -->
        <if-not-empty field="workEffortPartyAssignments">
            <first-from-list list="workEffortPartyAssignments" entry="workEffortPartyAssignment"/>
            <if-compare-field field="updProjectRole.newPartyId" operator="not-equals" to-field="workEffortPartyAssignment.partyId">
                <now-timestamp field="workEffortPartyAssignment.thruDate"/>
                <store-value value-field="workEffortPartyAssignment"/>
            </if-compare-field>
        </if-not-empty>
        <!-- create new record if required -->
        <if>
            <condition>
                <or>
                    <if-empty field="workEffortPartyAssignments"/>
                    <and>
                        <not><if-empty field="workEffortPartyAssignments"/></not>
                        <if-compare-field field="updProjectRole.newPartyId" operator="not-equals" to-field="workEffortPartyAssignment.partyId"/>
                    </and>
                </or>
            </condition>
            <then>
                <make-value entity-name="WorkEffortPartyAssignment" value-field="workEffortPartyAssignment"/>
                <set field="workEffortPartyAssignment.workEffortId" from-field="parameters.workEffortId"/>
                <set field="workEffortPartyAssignment.partyId" from-field="updProjectRole.newPartyId"/>
                <set field="workEffortPartyAssignment.roleTypeId" from-field="updProjectRole.roleTypeId"/>
                <now-timestamp field="workEffortPartyAssignment.fromDate"/>
                <create-value value-field="workEffortPartyAssignment"/>
            </then>
        </if>
    </simple-method>

    <simple-method method-name="createProjectTask" short-description="Create a project task and optionally assign">
        <!-- create task -->
        <if-empty field="parameters.statusId">
            <set field="parameters.statusId" value="PTS_CREATED"/>
        </if-empty>
        <call-simple-method method-name="createWorkEffort" xml-resource="component://workeffort/minilang/workeffort/WorkEffortSimpleServices.xml"/>
        <set field="parameters.workEffortId" from-field="newEntity.workEffortId"/>
        <!-- optionally assign to party -->
        <if-not-empty field="parameters.partyId">
            <call-simple-method method-name="assignPartyToWorkEffort" xml-resource="component://workeffort/minilang/workeffort/WorkEffortSimpleServices.xml"/>
        </if-not-empty>
        <!-- optionally enter estimated time and required skill -->
        <if-not-empty field="parameters.estimatedHours">
            <set field="parameters.estimatedDuration" from-field="parameters.estimatedHours" type="Double"/>
            <if-empty field="parameters.skillTypeId">
                <set field="parameters.skillTypeId" value="_NA_"/>
            </if-empty>
            <set-service-fields service-name="createWorkEffortSkillStandard" map="parameters" to-map="createWorkEffortSkillStandard"/>
            <call-service service-name="createWorkEffortSkillStandard" in-map-name="createWorkEffortSkillStandard"/>
        </if-not-empty>
    </simple-method>

    <simple-method method-name="updateTaskAndRelatedInfo" short-description="Update the task and when info is provided update the related information too">
        <set-service-fields service-name="updateWorkEffort" map="parameters" to-map="updateWorkeffort"/>
        <call-service service-name="updateWorkEffort" in-map-name="updateWorkeffort"/>
        <if-not-empty field="parameters.estimatedDuration">
            <set-service-fields service-name="updateWorkEffortSkillStandard" map="parameters" to-map="updateWorkEffortSkillStandard"/>
            <if-empty field="parameters.skillTypeId">
                <entity-and entity-name="WorkEffortSkillStandard" list="workEffortSkillStandards">
                    <field-map field-name="workEffortId" from-field="parameters.workEffortId"/>
                </entity-and>
                <if-not-empty field="workEffortSkillStandards">
                    <first-from-list list="workEffortSkillStandards" entry="workEffortSkillStandard"/>
                    <set field="updateWorkEffortSkillStandard.skillTypeId" from-field="workEffortSkillStandard.skillTypeId"/>
                    <else>
                        <set field="updateWorkEffortSkillStandard.skillTypeId" value="_NA_"/>
                    </else>
                </if-not-empty>
            </if-empty>
            <entity-one entity-name="WorkEffortSkillStandard" value-field="workEffortSkillStandard">
                <field-map field-name="workEffortId" from-field="parameters.workEffortId"/>
                <field-map field-name="skillTypeId" from-field="updateWorkEffortSkillStandard.skillTypeId"/>
            </entity-one>
            <if-not-empty field="workEffortSkillStandard">
                <call-service service-name="updateWorkEffortSkillStandard" in-map-name="updateWorkEffortSkillStandard"/>
                <else>
                    <call-service service-name="createWorkEffortSkillStandard" in-map-name="updateWorkEffortSkillStandard"/>
                </else>
            </if-not-empty>
        </if-not-empty>
        <!-- if required can update more task related info here -->
    </simple-method>
    
    <simple-method method-name="updateTaskAssigment"
        short-description="Update task to resource assignment, if required create a new one by re-assigment">
        <field-to-result field="parameters.workEffortId" result-name="workEffortId"/>
        <if>
            <!-- check if a change in partyId Or roletypeId: need to delete and create new -->
            <condition>
                <or>
                    <and>
                        <not><if-empty field="parameters.newPartyId"/></not>
                        <if-compare-field field="parameters.partyId" to-field="parameters.newPartyId" operator="not-equals"/>
                    </and>
                    <and>
                        <not><if-empty field="parameters.newRoleTypeId"/></not>
                        <if-compare-field field="parameters.roleTypeId" to-field="parameters.newRoleTypeId" operator="not-equals"/>
                    </and>
                </or>
            </condition>
            <then>
                <!-- roleType and/or partyId changed: end old and create new assign-->
                <entity-one entity-name="WorkEffortPartyAssignment" value-field="workEffortPartyAssignment"/>
                <set field="workEffortPartyAssignment.delegateReasonEnumId" from-field="parameters.delegateReasonEnumId"/>
                <set field="workEffortPartyAssignment.comments" from-field="parameters.comments"/>
                <set field="workEffortPartyAssignment.assignedByUserLoginId" from-field="userLogin.userLoginId"/>
                <now-timestamp field="workEffortPartyAssignment.thruDate"/>
                <store-value value-field="workEffortPartyAssignment"/>
                <!-- create a new one -->
                <make-value entity-name="WorkEffortPartyAssignment" value-field="newAssign"/>
                <set field="newAssign.workEffortId" from-field="parameters.workEffortId"/>
                <set field="newAssign.partyId" from-field="parameters.newPartyId"/>
                <set field="newAssign.roleTypeId" from-field="parameters.newRoleTypeId"/>
                <set field="newAssign.assignedByUserLoginId" from-field="userLogin.userLoginId"/>
                <now-timestamp field="newAssign.fromDate"/>
                <set field="newAssign.statusId" value="PAS_ASSIGNED"/>
                <create-value value-field="newAssign"/>
            </then>
            <else>
                <set field="fromDate" from-field="parameters.fromDate" type="Timestamp"/>
                <entity-one entity-name="WorkEffortPartyAssignment" value-field="assignment">
                    <field-map field-name="workEffortId" from-field="parameters.workEffortId"/>
                    <field-map field-name="partyId" from-field="parameters.partyId"/>
                    <field-map field-name="roleTypeId" from-field="parameters.roleTypeId"/>
                    <field-map field-name="fromDate" from-field="fromDate"/>
                </entity-one>
                <if-not-empty field="assignment">
                    <!-- status changed or assignment ended -->
                    <if-compare field="parameters.statusId" value="PAS_ENDED" operator="equals">
                        <!-- special case to indicate end of assignment -->
                        <now-timestamp field="assignment.thruDate"/>
                        <clear-field field="parameters.statusId"/>
                    </if-compare>
                    <set-nonpk-fields map="parameters" value-field="assignment"/>
                    <store-value value-field="assignment"/>
                    <if-compare field="assignment.statusId" value="PAS_COMPLETED" operator="equals">
                        <call-simple-method method-name="updateTaskStatusToComplete"/>
                    </if-compare>
                    <else>
                        <!-- new assignment -->
                        <call-simple-method method-name="assignPartyToWorkEffort" xml-resource="component://workeffort/minilang/workeffort/WorkEffortSimpleServices.xml"/>
                    </else>
                </if-not-empty>
            </else>
        </if>
    </simple-method>

    <simple-method method-name="updateTaskStatusToComplete"
        short-description="Check partyassignments on a task, if all completes set task status to completed and set actual completiondate to now">
        <entity-and entity-name="WorkEffortPartyAssignment" list="assignments" filter-by-date="true">
            <field-map field-name="workEffortId" from-field="parameters.workEffortId"/>
        </entity-and>
        <!-- check if all open assignments were completed -->
        <if-not-empty field="assignments">
            <iterate list="assignments" entry="assignment">
                <if-compare field="assignment.statusId" value="PAS_COMPLETED" operator="not-equals">
                    <set field="status" value="notcomplete"/>
                </if-compare>
            </iterate>
        </if-not-empty>
        <if-empty field="status">
            <now-timestamp field="parameters.actualCompletionDate"/>
            <set field="parameters.currentStatusId" value="PTS_COMPLETED"/>
            <call-simple-method method-name="updateWorkEffort" xml-resource="component://workeffort/minilang/workeffort/WorkEffortSimpleServices.xml"/>
            <!-- check for related customer request, set these too to completed -->
            <entity-and entity-name="CustRequestWorkEffort" list="custRequests">
                <field-map field-name="workEffortId" from-field="parameters.workEffortId"/>
            </entity-and>
            <if-not-empty field="custRequests">
                <iterate list="custRequests" entry="custReq">
                    <set field="updStat.custRequestId" from-field="custReq.custRequestId"/>
                    <set field="updStat.statusId" value="CRQ_COMPLETED"/>
                    <call-service service-name="updateCustRequest" in-map-name="updStat"/>
                </iterate>
            </if-not-empty>
        </if-empty>
    </simple-method>

    <simple-method method-name="scheduleProject" short-description="Project Scheduler sets the planningdates according task requirements and available resources">
        <!--
                theory behind the program
                - - - - - - - - - - - - -
                (program under development)
                Assumptions for tasks and resources
                1. a workday has 8 hours.
                2. a workweek has 40 hours and 5 days.
                3. The order of the execution of the tasks is set by the workeffortassociation.
                4. The default start of the project is today
                5. default length of a task is 3 day if not planned hours entered

                The steps of the program are:
                1. read all tasks  and check if there are predesessors, when not set he estimated dates
                    for critical path processing:
                    * ES - Earliest Start time
                    * EF - Earliest Finish time
                    * LS - Latest Start time
                    * LF - Latest Finish time

                    EF = LF task is on the critical path

                2. call a recursive java function to set all the dependant tasks.
        -->
        <field-to-result field="parameters.projectId" result-name="projectId"/>

        <!-- find a starting point being either the estimated start date of a project or the earliest actual start date. -->
        <entity-condition entity-name="ProjectAndPhaseAndTask" list="tasks">
            <condition-expr field-name="actualStartDate" operator="not-equals" from-field="null"/>
            <order-by field-name="-actualStartDate"/>
        </entity-condition>

        <if-not-empty field="tasks">
            <!-- remove all estimated dates -->
            <iterate list="tasks" entry="task">
                <clear-field field="task.estimatedStartDate"/>
                <clear-field field="task.estimatedCompletionDate"/>
            </iterate>

            <first-from-list list="tasks" entry="task"/>
            <set field="startDate" from-field="task.actualStartDate"/>
            <set field="taskId" from-field="task.workEffortId"/>
            <else>
                <now-timestamp field="generalStartDate"/>
            </else>
        </if-not-empty>
        <while>
            <condition>
                <if-empty field="generalStartDate"/>
            </condition>
            <then>
                <entity-and entity-name="WorkEffortAssoc" list="assocs">
                    <field-map field-name="workEffortIdTo" from-field="taskId"/>
                </entity-and>
                <if-not-empty field="assocs">
                    <iterate list="assocs" entry="assoc">
                        <clear-field field="hours"/>
                        <set field="getTask.taskId" from-field="assoc.workEffortIdFrom"/>
                        <call-service service-name="getProjectTask" in-map-name="getTask">
                            <result-to-field result-name="estimatedHours"/>
                            <result-to-field result-name="actualHours"/>
                        </call-service>
                        <if-not-empty field="estimatedHours">
                            <if-not-empty field="actualHours">
                                <if-compare-field field="estimatedHours" operator="greater" to-field="actualHours">
                                    <set field="hours" from-field="estimatedHours" type="Double"/>
                                    <else>
                                        <set field="hours" from-field="actualHours" type="Double"/>
                                    </else>
                                </if-compare-field>
                                <else>
                                    <set field="hours" from-field="estimatedHours" type="Double"/>
                                </else>
                            </if-not-empty>
                        </if-not-empty>
                        <if-not-empty field="actualHours">
                            <set field="hours" from-field="actualHours" type="Double"/>
                        </if-not-empty>
                        <if-empty field="hours">
                            <set field="hours" value="16" type="Double"/>
                        </if-empty>
                        <if-empty field="highestHours">
                            <set field="highestHours" from-field="hours" type="Double"/>
                            <set field="preDesessorId" from-field="assoc.workEffortIdFrom"/>
                            <else>
                                <if-compare-field field="highestHours" operator="less" to-field="hours">
                                    <set field="highestHours" from-field="hours" type="Double"/>
                                    <set field="preDesessorId" from-field="assoc.workEffortIdFrom"/>
                                </if-compare-field>
                            </else>
                        </if-empty>
                    </iterate>
                    <set field="taskId" from-field="preDesessorId"/>
                    <calculate field="taskDays">
                        <calcop operator="divide" field="higestHours"/>
                        <number value="8"/>
                    </calculate>
                    <calculate field="taskDays">
                        <calcop operator="multiply" field="taskDays"/>
                        <number value="-1"/>
                    </calculate>
                    <call-class-method class-name="org.apache.ofbiz.base.util.UtilDateTime" method-name="addDaysToTimestamp" ret-field="startDate">
                        <field field="startDate"/>
                        <field field="taskDays"/>
                    </call-class-method>
                    <else>
                        <entity-one entity-name="WorkEffort" value-field="workEffort">
                            <field-map field-name="workEffortId" from-field="taskId"/>
                        </entity-one>
                        <if-not-empty field="workEffortId.parentWorkEffortId">
                            <set field="taskId" from-field="workEffortId.parentWorkEffortId"/>
                            <else>
                                <set field="generalStartDate" from-field="startDate"/>
                            </else>
                        </if-not-empty>
                    </else>
                </if-not-empty>
            </then>
        </while>

        <!-- create the tasklist -->
        <entity-one entity-name="WorkEffort" value-field="project">
            <field-map field-name="workEffortId" from-field="parameters.projectId"/>
        </entity-one>
        <get-related value-field="project" relation-name="ChildWorkEffort" list="phases"/>
        <if-not-empty field="phases">
            <iterate list="phases" entry="phase">
                <get-related value-field="phase" relation-name="ChildWorkEffort" list="tasks"/>
                <if-not-empty field="tasks">
                    <iterate list="tasks" entry="task">
                        <get-related value-field="task" relation-name="ToWorkEffortAssoc" list="t.prevTasks"/>
                        <if-empty field="t.prevTasks">
                            <!-- no predecessors so i can set the dates -->
                            <now-timestamp field="upd.estimatedStartDate"/>
                            <now-timestamp field="currentDate"/>
                            <call-class-method class-name="org.apache.ofbiz.project.Various" method-name="calculateCompletionDate" ret-field="upd.estimatedCompletionDate">
                                <field field="task" type="org.apache.ofbiz.entity.GenericValue"/>
                                <field field="currentDate" type="java.sql.Timestamp"/>
                            </call-class-method>
                            <set field="upd.workEffortId" from-field="task.workEffortId"/>
                            <call-service service-name="updateWorkEffort" in-map-name="upd"/>
                            <entity-one entity-name="WorkEffort" value-field="newTask">
                                <field-map field-name="workEffortId" from-field="task.workEffortId"/>
                            </entity-one>
                            <call-class-method class-name="org.apache.ofbiz.project.Various" method-name="setDatesFollowingTasks">
                                <field field="newTask" type="org.apache.ofbiz.entity.GenericValue"/>
                            </call-class-method>
                        </if-empty>
                    </iterate>
                </if-not-empty>
            </iterate>
        </if-not-empty>
    </simple-method>

    <simple-method method-name="updateTimeEntryByWorkeffort" short-description="Update workeffort by workeffortId and timesheetId ">
        <field-to-result field="parameters.timesheetId" result-name="timesheetId"/>
        <if-empty field="parameters.workEffortId">
            <return/>
        </if-empty>
        <if-compare field="parameters.workEffortId" operator="equals" value="Totals">
            <return/>
        </if-compare>
        <entity-one entity-name="Timesheet" value-field="timesheet"/>

        <!-- check if party assigned to task, when not add with roletype of project, if assigned check status -->
        <entity-and entity-name="WorkEffortPartyAssignment" list="assigns" filter-by-date="true">
            <field-map field-name="workEffortId" from-field="parameters.workEffortId"/>
            <field-map field-name="partyId" from-field="timesheet.partyId"/>
        </entity-and>
        <if-empty field="assigns">
            <set field="getpr.taskId" from-field="parameters.workEffortId"/>
            <call-service service-name="getProjectIdAndNameFromTask" in-map-name="getpr">
                <result-to-field result-name="projectId"/>
            </call-service>
            <entity-and entity-name="WorkEffortPartyAssignment" list="projectAssigns" filter-by-date="true">
                <field-map field-name="workEffortId" from-field="projectId"/>
                <field-map field-name="partyId" from-field="timesheet.partyId"/>
            </entity-and>
            <first-from-list list="projectAssigns" entry="projectAssign"/>
            <set field="parameters.partyId" from-field="timesheet.partyId"/>
            <set field="parameters.roleTypeId" from-field="projectAssign.roleTypeId"/>
            <set field="parameters.statusId" value="PAS_ASSIGNED"/>
            <call-simple-method method-name="assignPartyToWorkEffort" xml-resource="component://workeffort/minilang/workeffort/WorkEffortSimpleServices.xml"/>
        </if-empty>
        <check-errors/>

        <!-- check if the actual start date is set, when not set it to todays date -->
        <if-empty field="project.actualStartDate">
            <entity-one entity-name="WorkEffort" value-field="workEffort"/>
            <now-timestamp field="workEffort.actualStartDate"/>
            <store-value value-field="workEffort"/>
        </if-empty>

        <get-related value-field="timesheet" relation-name="TimeEntry" list="timeEntries"/>

        <!-- update existing entries -->
        <set field="hours" value="0" type="Double"/>
        <if-not-empty field="timeEntries">
            <iterate list="timeEntries" entry="timeEntry">
                <if-compare-field field="timeEntry.workEffortId" to-field="parameters.workEffortId" operator="equals">
                    <if-compare-field field="timeEntry.rateTypeId" to-field="parameters.rateTypeId" operator="equals">
                        <if-not-empty field="timeEntry.hours">
                            <remove-value value-field="timeEntry"/>
                            <else>
                                <!-- translate the date into the daynumber -->
                                <call-class-method class-name="org.apache.ofbiz.base.util.UtilDateTime" method-name="getIntervalInDays" ret-field="dayNumber">
                                    <field field="timesheet.fromDate" type="java.sql.Timestamp"/>
                                    <field field="timeEntry.fromDate" type="java.sql.Timestamp"/>
                                </call-class-method>
                                <!-- get the related field -->
                                <if-not-empty field="parameters.hoursDay${dayNumber}">
                                    <set field="hours" from-field="parameters.hoursDay${dayNumber}" type="Double"/>
                                    <else>
                                        <set field="hours" value="0" type="Double"/>
                                    </else>
                                </if-not-empty>
                                <call-simple-method method-name="updateTimeEntry"/>
                                <set field="parameters.hoursDay${dayNumber}" value="-999999" type="Double"/>
                            </else>
                        </if-not-empty>
                    </if-compare-field>
                </if-compare-field>
            </iterate>
        </if-not-empty>

        <!-- process not yet done fields -->
        <loop count="7" field="dayNr">
            <if-not-empty field="parameters.hoursDay${dayNr}">
                <if-compare field="parameters.hoursDay${dayNr}" value="-999999" operator="not-equals">
                    <set field="hours" from-field="parameters.hoursDay${dayNr}" type="Double"/>
                    <call-class-method class-name="org.apache.ofbiz.base.util.UtilDateTime" method-name="addDaysToTimestamp" ret-field="fromDate">
                        <field field="timesheet.fromDate" type="java.sql.Timestamp"/>
                        <field field="dayNr" type="int"/>
                    </call-class-method>
                    <call-simple-method method-name="updateTimeEntry"/>
                </if-compare>
            </if-not-empty>
        </loop>

        <!-- update the assignment status if required -->
        <if-compare field="parameters.checkComplete" value="Y" operator="equals">
            <entity-and entity-name="WorkEffortPartyAssignment" list="assigns" filter-by-date="true">
                <field-map field-name="workEffortId" from-field="parameters.workEffortId"/>
                <field-map field-name="partyId" from-field="timesheet.partyId"/>
            </entity-and>
            <first-from-list list="assigns" entry="alreadyAssign"/>
            <if-compare field="alreadyAssign.statusId" value="PAS_COMPLETED" operator="not-equals">
                <set field="upStat.partyId" from-field="timesheet.partyId"/>
                <set field="upStat.statusId" value="PAS_COMPLETED"/>
                <set field="upStat.roleTypeId" from-field="alreadyAssign.roleTypeId"/>
                <set field="upStat.workEffortId" from-field="parameters.workEffortId"/>
                <set field="upStat.fromDate" from-field="alreadyAssign.fromDate"/>
                <call-service service-name="updateTaskAssigment" in-map-name="upStat"/>
            </if-compare>
        </if-compare>
    </simple-method>

    <simple-method method-name="getProjectIdAndNameFromTask" short-description="Get the projectId when a phase or task is provided." login-required="true">
        <if-empty field="parameters.taskId">
            <if-empty field="parameters.phaseId">
                <return/>
            </if-empty>
        </if-empty>
        <if-not-empty field="parameters.taskId"><!-- taskId is provided -->
            <entity-one entity-name="WorkEffort" value-field="task">
                <field-map field-name="workEffortId" from-field="parameters.taskId"/>
            </entity-one>
            <if-not-empty field="task">
                <get-related-one value-field="task" relation-name="ParentWorkEffort" to-value-field="phase"/>
                <else>
                    <return/>
                </else>
            </if-not-empty>
            <else><!-- phaseId is provided -->
                <entity-one entity-name="WorkEffort" value-field="phase">
                    <field-map field-name="workEffortId" from-field="parameters.phaseId"/>
                </entity-one>
            </else>
        </if-not-empty>
        <!-- get project info -->
        <if-not-empty field="phase">
            <get-related-one value-field="phase" relation-name="ParentWorkEffort" to-value-field="project"/>
            <field-to-result field="project.workEffortId" result-name="projectId"/>
            <field-to-result field="project.workEffortName" result-name="projectName"/>
            <field-to-result field="phase.workEffortId" result-name="phaseId"/>
            <field-to-result field="phase.workEffortName" result-name="phaseName"/>
            <field-to-result field="task.workEffortId" result-name="taskId"/>
            <field-to-result field="task.workEffortName" result-name="taskName"/>
            <set field="taskWbsId" value="${project.workEffortId}.${phase.sequenceNum}.${task.sequenceNum}"/>
            <field-to-result field="taskWbsId"/>
        </if-not-empty>
    </simple-method>

    <simple-method method-name="copyProjectToTemplate" short-description="copy a project to a workeffortType starting with 'template'">
        <set field="toTemplate" value="dummy"/>
        <call-simple-method method-name="copyProject"/>
    </simple-method>

    <simple-method method-name="copyProject" short-description="copy a project with related phases and tasks however no actual data">
        <entity-one entity-name="WorkEffort" value-field="project">
            <field-map field-name="workEffortId" from-field="parameters.projectId"/>
        </entity-one>

        <if-empty field="project">
            <field-to-result field="parameters.projectId" result-name="projectId"/>
            <add-error error-list-name="error_list">
                <fail-property resource="ProjectMgrUiLabels" property="ProjectMgrErrorProjectNotFound"/>
            </add-error>
        </if-empty>
        <if-empty field="parameters.workEffortName">
            <set field="parameters.workEffortName" from-field="project.workEffortName"/>
        </if-empty>
        <if-empty field="parameters.description">
            <set field="parameters.description" from-field="project.description"/>
        </if-empty>
        <if-not-empty field="toTemplate">
            <set field="parameters.workEffortTypeId" value="PROJECT_TEMPLATE"/>
            <else>
                <set field="parameters.workEffortTypeId" value="PROJECT"/>
            </else>
        </if-not-empty>
        <set field="parameters.currentStatusId" value="PRJ_ACTIVE"/>
        <clear-field field="parameters.workEffortId"/>
        <call-simple-method method-name="createWorkEffort" xml-resource="component://workeffort/minilang/workeffort/WorkEffortSimpleServices.xml"/>
        <set field="newProjectId" from-field="newEntity.workEffortId"/>

        <!-- copy assigned parties -->
        <get-related value-field="project" relation-name="WorkEffortPartyAssignment" list="partiesAll"/>
        <filter-list-by-date list="partiesAll" to-list="parties"/>
        <if-not-empty field="parties">
            <iterate list="parties" entry="party">
                <set field="parameters.workEffortId" from-field="newProjectId"/>
                <set field="parameters.partyId" from-field="party.partyId"/>
                <set field="parameters.roleTypeId" from-field="party.roleTypeId"/>
                <set field="parameters.statusId" value="PAS_ASSIGNED"/>
                <call-simple-method method-name="assignPartyToWorkEffort" xml-resource="component://workeffort/minilang/workeffort/WorkEffortSimpleServices.xml"/>
            </iterate>
        </if-not-empty>

        <get-related value-field="project" relation-name="ChildWorkEffort" list="phases"/>
        <if-not-empty field="phases">
            <iterate list="phases" entry="phase">
                <clear-field field="newPhase"/>
                <if-not-empty field="toTemplate">
                    <set field="parameters.workEffortTypeId" value="PHASE_TEMPLATE"/>
                    <else>
                        <set field="parameters.workEffortTypeId" value="PHASE"/>
                    </else>
                </if-not-empty>
                <set field="parameters.workEffortName" from-field="phase.workEffortName"/>
                <set field="parameters.workEffortParentId" from-field="newProjectId"/>
                <set field="parameters.currentStatusId" value="_NA_"/>
                <clear-field field="parameters.workEffortId"/>
                <call-simple-method method-name="createWorkEffort" xml-resource="component://workeffort/minilang/workeffort/WorkEffortSimpleServices.xml"/>
                <set field="newPhaseId" from-field="newEntity.workEffortId"/>

                <get-related value-field="phase" relation-name="ChildWorkEffort" list="tasks"/>
                <if-not-empty field="tasks">
                    <iterate list="tasks" entry="task">
                        <clear-field field="newTask"/>
                        <if-not-empty field="toTemplate">
                            <set field="newTask.workEffortTypeId" value="TASK_TEMPLATE"/>
                            <else>
                                <set field="newTask.workEffortTypeId" value="TASK"/>
                            </else>
                        </if-not-empty>
                        <set field="parameters.workEffortName" from-field="task.workEffortName"/>
                        <set field="parameters.priority" from-field="task.priority"/>
                        <set field="parameters.workEffortParentId" from-field="newPhaseId"/>
                        <set field="parameters.currentStatusId" value="PTS_CREATED"/>
                        <clear-field field="parameters.workEffortId"/>
                        <call-simple-method method-name="createWorkEffort" xml-resource="component://workeffort/minilang/workeffort/WorkEffortSimpleServices.xml"/>
                    </iterate>
                </if-not-empty>
            </iterate>
        </if-not-empty>
        <field-to-result field="newProjectId" result-name="projectId"/>
    </simple-method>

    <simple-method method-name="getProject" short-description="get Project information" login-required="true">
        <if-empty field="parameters.projectId">
            <return/>
        </if-empty>
        <if-not-empty field="parameters.partyId">
            <set field="parameters.hoursPartyId" from-field="parameters.partyId"/>
        </if-not-empty>
        <entity-one entity-name="WorkEffort" value-field="project">
            <field-map field-name="workEffortId" from-field="parameters.projectId"/>
        </entity-one>
        <set field="highInfo.projectId" from-field="project.workEffortId"/>
        <set field="highInfo.projectName" from-field="project.workEffortName"/>
        <set field="highInfo.projectDescription" from-field="project.description"/>
        <set field="highInfo.estimatedStartDate" from-field="project.estimatedStartDate"/>
        <set field="highInfo.estimatedCompletionDate" from-field="project.estimatedCompletionDate"/>
        <set field="highInfo.actualStartDate" from-field="project.actualStartDate"/>
        <set field="highInfo.actualCompletionDate" from-field="project.actualCompletionDate"/>
        <set field="highInfo.scopeEnumId" from-field="project.scopeEnumId"/>
        <set field="highInfo.createdStamp" from-field="project.createdStamp"/>
        <entity-one entity-name="StatusItem" value-field="highSeq">
            <field-map field-name="statusId" from-field="project.currentStatusId"/>
        </entity-one>
        <set field="highInfo.createdDate" from-field="project.createdDate"/>
        <set field="highInfo.parentProjectId" from-field="project.workEffortParentId"/>
        <!-- loop through the related phases and tasks -->
        <call-simple-method method-name="combineInfo"/>

        <!-- get e-mail address -->
        <entity-and entity-name="WorkEffortContactMechView" list="emailAddresses">
            <field-map field-name="workEffortId" from-field="highInfo.projectId"/>
            <field-map field-name="contactMechTypeId" value="EMAIL_ADDRESS"/>
        </entity-and>
        <filter-list-by-date list="emailAddresses"/>
        <if-not-empty field="emailAddresses">
            <first-from-list list="emailAddresses" entry="emailAddress"/>
            <set field="highInfo.emailAddress" from-field="emailAddress.infoString"/>
        </if-not-empty>

        <!-- closed overrules everything -->
        <if-compare field="project.currentStatusId" value="PRJ_CLOSED" operator="equals">
            <set field="highInfo.currentStatusId" value="PRJ_CLOSED"/>
        </if-compare>

        <call-simple-method method-name="createDates"/>

        <!-- results -->
        <field-to-result field="highInfo" result-name="projectInfo"/>
        <field-to-result field="parameters.projectId" result-name="projectId"/>
    </simple-method>

    <simple-method method-name="getProjectPhaseList" short-description="get Project Phase information" login-required="true">
        <if-empty field="parameters.projectId">
            <return/>
        </if-empty>
        <entity-and entity-name="WorkEffort" list="phases">
            <field-map field-name="workEffortTypeId" value="PHASE"/>
            <field-map field-name="workEffortParentId" from-field="parameters.projectId"/>
            <order-by field-name="sequenceNum"/>
            <order-by field-name="workEffortName"/>
        </entity-and>
        <if-not-empty field="phases">
        <iterate list="phases" entry="phase">
            <!-- get the phase seq id -->
            <entity-one entity-name="StatusItem" value-field="highSeq">
                <field-map field-name="statusId" from-field="phase.currentStatusId"/>
            </entity-one>
            <clear-field field="highInfo"/>
            <set field="highInfo.sequenceId" from-field="highSeq.sequenceId"/>
            <set field="highInfo.phaseId" from-field="phase.workEffortId"/>
            <set field="highInfo.phaseSeqNum" from-field="phase.sequenceNum"/>
            <set field="highInfo.phaseName" from-field="phase.workEffortName"/>
            <set field="highInfo.phaseDescription" from-field="phase.description"/>
            <set field="highInfo.scopeEnumId" from-field="phase.scopeEnumId"/>

            <!-- loop through the related tasks and combine information -->
            <call-simple-method method-name="combineInfo"/>

            <!-- merge estimated and actual dates -->
            <call-simple-method method-name="createDates"/>

            <field-to-list field="highInfo" list="phaseList"/>
        </iterate>
        </if-not-empty>

        <!-- results -->
        <field-to-result field="phaseList"/>
        <field-to-result field="parameters.projectId" result-name="projectId"/>
    </simple-method>

    <simple-method method-name="getProjectTaskList" short-description="get Project Phase/task information" login-required="true">
        <if-empty field="parameters.projectId">
            <return/>
        </if-empty>
        <entity-and entity-name="ProjectAndPhaseAndTask" list="tasks">
            <field-map field-name="projectId" from-field="parameters.projectId"/>
            <order-by field-name="phaseSeqNum"/>
            <order-by field-name="phaseName"/>
            <order-by field-name="sequenceNum"/>
            <order-by field-name="workEffortName"/>
        </entity-and>
        <if-not-empty field="tasks">
            <iterate list="tasks" entry="lowInfo">
                <set field="highInfo.phaseName" from-field="lowInfo.phaseName"/>
                <set field="highInfo.phaseSeqNum" from-field="lowInfo.phaseSeqNum"/>
                <set field="highInfo.taskId" from-field="lowInfo.workEffortId"/>
                <call-simple-method method-name="combineInfo"/>
                <clear-field field="highInfo.sequenceId"/>
                <call-simple-method method-name="createDates"/>
                <set field="highInfo.workEffortId" from-field="lowInfo.workEffortId"/>
                <set field="highInfo.workEffortName" from-field="lowInfo.workEffortName"/>
                <set field="highInfo.sequenceNum" from-field="lowInfo.sequenceNum"/>
                <field-to-list field="highInfo" list="taskList"/>
                <clear-field field="highInfo"/>
            </iterate>
        </if-not-empty>
        <!-- results -->
        <field-to-result field="taskList"/>
        <field-to-result field="parameters.projectId" result-name="projectId"/>
    </simple-method>

    <simple-method method-name="getProjectTask" short-description="get Project task information" login-required="true">
        <entity-one entity-name="WorkEffort" value-field="lowInfo">
            <field-map field-name="workEffortId" from-field="parameters.taskId"/>
        </entity-one>
        <set field="highInfo.taskId" from-field="lowInfo.workEffortId"/>
        <set field="highInfo.taskSeqNum" from-field="lowInfo.sequenceNum"/>
        <set field="highInfo.taskName" from-field="lowInfo.workEffortName"/>
        <set field="highInfo.taskDescription" from-field="lowInfo.description"/>
        <set field="highInfo.scopeEnumId" from-field="lowInfo.scopeEnumId"/>
        <set field="highInfo.workEffortParentId" from-field="lowInfo.workEffortParentId"/>
        <call-simple-method method-name="combineInfo"/>
        <field-to-result field="highInfo" result-name="taskInfo"/>
    </simple-method>

    <simple-method method-name="getProjectsByParties" short-description="get Project information by party member" login-required="true">
        <entity-condition entity-name="ProjectAndPhaseAndTaskParty" list="tasks">
            <condition-list combine="and">
                <condition-expr field-name="projectId" operator="equals" from-field="parameters.projectId" ignore-if-empty="true"/>
                <condition-expr field-name="partyId" operator="equals" from-field="parameters.partyId" ignore-if-empty="true"/>
                <condition-expr field-name="partyId" operator="not-equals" from-field="null"/>
            </condition-list>
            <order-by field-name="projectId"/>
            <order-by field-name="partyId"/>
        </entity-condition>
        <if-not-empty field="tasks">
            <iterate list="tasks" entry="task">
                <if>
                    <condition>
                        <and>
                            <not><if-empty field="projectParty"/></not>
                            <if-compare-field field="task.partyId" to-field="projectParty.partyId" operator="not-equals"/>
                        </and>
                    </condition>
                    <then>
                        <field-to-list field="projectParty" list="projectParties"/>
                        <clear-field field="projectParty"/>
                        <clear-field field="highInfo"/>
                    </then>
                </if>

                <if-empty field="projectParty">
                    <set field="projectParty.partyId" from-field="task.partyId"/>
                    <entity-one entity-name="PartyNameView" value-field="partyNameView">
                        <field-map field-name="partyId" from-field="task.partyId"/>
                    </entity-one>
                    <if-not-empty field="partyNameView">
                        <set field="projectParty.partyName" value="${partyNameView.lastName},${partyNameView.firstName}${partyNameView.groupName}"/>
                    </if-not-empty>
                    <set field="projectParty.roleTypeId" from-field="task.roleTypeId"/>
                    <set field="projectParty.fromDate" from-field="task.fromDate"/>
                    <set field="projectParty.thruDate" from-field="task.thruDate"/>
                </if-empty>

                <!-- get the planned/actual hours -->
                <set field="lowInfo" from-field="task"/>
                <set field="parameters.hoursPartyId" from-field="task.partyId"/>
                <call-simple-method method-name="getHours" xml-resource="component://workeffort/minilang/workeffort/WorkEffortSimpleServices.xml"/>
                <set field="projectParty.plannedHours" from-field="highInfo.plannedHours" type="Double"/>
                <set field="projectParty.actualHours" from-field="highInfo.actualHours" type="Double"/>
            </iterate>
            <if-not-empty field="projectParty">
                <field-to-list field="projectParty" list="projectParties"/>
            </if-not-empty>
            <if-not-empty field="projectParties">
                <field-to-result field="projectParties"/>
            </if-not-empty>
        </if-not-empty>
    </simple-method>

    <simple-method method-name="getTasksByParties" short-description="get task information by party member" login-required="true">
        <!-- get the list of tasks optionaly selected for a party -->
        <entity-condition entity-name="WorkEffortPartyAssignment" list="tasks" filter-by-date="true">
            <condition-list combine="and">
                <condition-expr field-name="partyId" operator="equals" from-field="parameters.partyId" ignore-if-empty="true"/>
                <condition-expr field-name="workEffortId" operator="equals" from-field="parameters.workEffortId" ignore-if-empty="true"/>
            </condition-list>
            <order-by field-name="workEffortId"/>
            <order-by field-name="partyId"/>
        </entity-condition>
        <if-not-empty field="tasks">
            <iterate list="tasks" entry="task">
                <if>
                    <condition >
                        <and>
                            <not>
                                <if-empty field="taskParty"/>
                            </not>
                            <if-compare-field field="task.partyId" to-field="taskParty.partyId" operator="not-equals"/>
                        </and>
                    </condition>
                    <then>
                        <field-to-list field="taskParty" list="taskParties"/>
                        <clear-field field="taskParty"/>
                        <clear-field field="highInfo"/>
                    </then>
                </if>

                <if-empty field="taskParty">
                    <set field="taskParty.partyId" from-field="task.partyId"/>
                    <entity-one entity-name="PartyNameView" value-field="partyNameView">
                        <field-map field-name="partyId" from-field="task.partyId"/>
                    </entity-one>
                    <if-not-empty field="partyNameView">
                        <set field="taskParty.partyName" value="${partyNameView.lastName},${partyNameView.firstName}${partyNameView.groupName}"/>
                    </if-not-empty>
                    <set field="taskParty.roleTypeId" from-field="task.roleTypeId"/>
                    <set field="taskParty.statusId" from-field="task.statusId"/>
                    <set field="taskParty.fromDate" from-field="task.fromDate"/>
                    <set field="taskParty.thruDate" from-field="task.thruDate"/>
                </if-empty>

                <!-- get the planned hours -->
                <set field="lowInfo" from-field="task"/>
                <set field="parameters.hoursPartyId" from-field="task.partyId"/>
                <get-related-one value-field="task" relation-name="WorkEffort" to-value-field="lowInfo"/>
                <call-simple-method method-name="getHours" xml-resource="component://workeffort/minilang/workeffort/WorkEffortSimpleServices.xml"/>
                <set field="taskParty.plannedHours" from-field="highInfo.plannedHours" type="Double"/>
                <set field="taskParty.actualHours" from-field="highInfo.actualHours" type="Double"/>
                <set field="taskParty.originalActualHours" from-field="highInfo.originalActualHours" type="Double"/>
            </iterate>
            <if-not-empty field="taskParty">
                <field-to-list field="taskParty" list="taskParties"/>
            </if-not-empty>
            <if-not-empty field="taskParties">
                <field-to-result field="taskParties"/>
            </if-not-empty>
        </if-not-empty>
    </simple-method>

    <!-- Internal functions  -->
    <simple-method method-name="combineStatusInfo" short-description="combine lower level status">
        <!-- the status for a project or phase is
         IN_PROGRESS if at least one task still in progress
         COMPLETED if all task are either completed or cancelled
         CREATED if other conditions does not apply
         For a task the status is
         IN_PROGRESS if it has at least one resource and at least a time entry
         ASSIGNED if it has at least one resource but no time entry associated
         -->
        <!-- if lowlevel type equals TASK then get create the status first -->
        <if-compare field="lowInfo.workEffortTypeId" value="TASK" operator="equals">
            <set field="highInfo.currentStatusId" from-field="lowInfo.currentStatusId"/>
            <if-compare field="lowInfo.currentStatusId" value="PTS_CREATED" operator="equals">
                <get-related value-field="lowInfo" relation-name="WorkEffortPartyAssignment" list="assignsAll"/>
                <filter-list-by-date list="assignsAll" to-list="assigns"/>
                <if-not-empty field="assigns">
                    <set field="highInfo.currentStatusId" value="PTS_CREATED_AS"/><!-- task is ASSIGNED -->
                </if-not-empty>
                <get-related value-field="lowInfo" relation-name="TimeEntry" list="entries"/>
                <if-not-empty field="entries">
                    <set field="highInfo.currentStatusId" value="PTS_CREATED_IP"/><!-- task is IN_PROGRESS -->
                </if-not-empty>
            </if-compare>
            <return/>
        </if-compare>
        <entity-count count-field="tasksCount" entity-name="ProjectPhaseTaskAssignmentView">
            <condition-list>
                <condition-expr field-name="projectId" from-field="highInfo.projectId" ignore-if-empty="true"/>
                <condition-expr field-name="phaseId" from-field="highInfo.phaseId" ignore-if-empty="true"/>
                <condition-expr field-name="taskId" from-field="highInfo.taskId" ignore-if-empty="true"/>
            </condition-list>
        </entity-count>
        <log level="info" message="related tasks count ====> ${tasksCount}"/>
        <entity-count count-field="completedTasks" entity-name="ProjectPhaseTaskAssignmentView">
            <condition-list>
                <condition-expr field-name="projectId" from-field="highInfo.projectId" ignore-if-empty="true"/>
                <condition-expr field-name="phaseId" from-field="highInfo.phaseId" ignore-if-empty="true"/>
                <condition-expr field-name="taskId" from-field="highInfo.taskId" ignore-if-empty="true"/>
            </condition-list>
            <having-condition-list combine="or">
            <condition-expr field-name="taskStatusId" operator="equals" value="PTS_COMPLETED"/>
            <condition-expr field-name="taskStatusId" operator="equals" value="PTS_CANCELLED"/>
        </having-condition-list>
        </entity-count>
        <log level="info" message="related completed tasks count ====> ${completedTasks}"/>
        <entity-count count-field="assignedTasks" entity-name="ProjectPhaseTaskAssignmentView">
            <condition-list>
                <condition-expr field-name="projectId" from-field="highInfo.projectId" ignore-if-empty="true"/>
                <condition-expr field-name="phaseId" from-field="highInfo.phaseId" ignore-if-empty="true"/>
                <condition-expr field-name="taskId" from-field="highInfo.taskId" ignore-if-empty="true"/>
            </condition-list>
            <having-condition-list combine="and">
            <condition-expr field-name="entriesCount" value="0"/>
            <condition-expr field-name="resourceCount" operator="greater-equals" value="1"/>
            <condition-expr field-name="taskStatusId" operator="not-equals" value="PTS_COMPLETED"/>
            <condition-expr field-name="taskStatusId" operator="not-equals" value="PTS_CANCELLED"/>
        </having-condition-list>
        </entity-count>
        <log level="info" message="related assigned tasks count ====> ${assignedTasks}"/>
        <entity-count count-field="inprogressTasks" entity-name="ProjectPhaseTaskAssignmentView">
            <condition-list>
                <condition-expr field-name="projectId" from-field="highInfo.projectId" ignore-if-empty="true"/>
                <condition-expr field-name="phaseId" from-field="highInfo.phaseId" ignore-if-empty="true"/>
                <condition-expr field-name="taskId" from-field="highInfo.taskId" ignore-if-empty="true"/>
            </condition-list>
            <having-condition-list combine="and">
                <condition-expr field-name="entriesCount" operator="greater-equals" value="1"/>
                <condition-expr field-name="resourceCount" operator="greater-equals" value="1"/>
                <condition-expr field-name="taskStatusId" operator="not-equals" value="PTS_COMPLETED"/>
                <condition-expr field-name="taskStatusId" operator="not-equals" value="PTS_CANCELLED"/>
            </having-condition-list>
        </entity-count>
        <log level="info" message="related in progress tasks count ====> ${inprogressTasks}"/>
        <if>
            <condition>
                <or>
                    <if-compare field="inprogressTasks" type="Long" operator="greater" value="0"/>
                    <if-compare field="assignedTasks" type="Long" operator="greater" value="0"/>
                </or>
            </condition>
            <then>
                <set field="highInfo.currentStatusId" value="PTS_CREATED_IP"/>
            </then>
            <else>
                <if>
                    <condition>
                        <if-compare-field operator="equals" field="completedTasks" to-field="tasksCount"/>
                    </condition>
                    <then>
                        <set field="highInfo.currentStatusId" value="PTS_COMPLETED"/>
                    </then>
                    <else>
                        <set field="highInfo.currentStatusId" value="PTS_CREATED"/>
                    </else>
                </if>
            </else>
        </if>
    </simple-method>

    <simple-method method-name="combineDatesAndPlannedHoursInfo" short-description="combine lower level start end dates and planned hours for a project, phase or task">
        <entity-condition  entity-name="ProjectPhaseTaskSklSumView" list="summaryInfos">
            <condition-list>
                <condition-expr field-name="projectId" from-field="highInfo.projectId" ignore-if-empty="true"/>
                <condition-expr field-name="phaseId" from-field="highInfo.phaseId" ignore-if-empty="true"/>
                <condition-expr field-name="taskId" from-field="highInfo.taskId" ignore-if-empty="true"/>
            </condition-list>
            <select-field field-name="projectId"/>
            <select-field field-name="estimatedStartDate"/>
            <select-field field-name="actualStartDate"/>
            <select-field field-name="estimatedCompletionDate"/>
            <select-field field-name="actualCompletionDate"/>
            <select-field field-name="plannedHours"/>
            <select-field field-name="priority"/>
        </entity-condition>

        <!-- Now used TimeEntries to update (or not) actual start and end Date -->
        <first-from-list list="summaryInfos" entry="summaryInfo"/>
        <set field="highInfo.estimatedStartDate" from-field="summaryInfo.estimatedStartDate"/>
        <set field="highInfo.estimatedCompletionDate" from-field="summaryInfo.estimatedCompletionDate"/>
        <set field="highInfo.actualStartDate" from-field="summaryInfo.actualStartDate"/>
        <set field="highInfo.actualCompletionDate" from-field="summaryInfo.actualCompletionDate"/>
        <set field="highInfo.priority" from-field="summaryInfo.priority"/>
        <set field="highInfo.plannedHours" from-field="summaryInfo.plannedHours"/>
        <!-- <log level="info" message="projectId=${highInfo.projectId} phaseId=${highInfo.phaseId} taskId=${highInfo.taskId} highInfo.plannedHours=${highInfo.plannedHours}"/>-->
        <!-- update actual start date by the min date form sub tasks associated TimeEntries 
        (if before actualStartDate field) -->
        <entity-condition  entity-name="ProjectPhaseTaskActualEntrySumView" list="summaryEntriesInfos">
            <condition-list>
                <condition-expr field-name="projectId" from-field="highInfo.projectId" ignore-if-empty="true"/>
                <condition-expr field-name="phaseId" from-field="highInfo.phaseId" ignore-if-empty="true"/>
                <condition-expr field-name="taskId" from-field="highInfo.taskId" ignore-if-empty="true"/>
            </condition-list>
            <select-field field-name="actualEntryStartDate"/>
        </entity-condition>
        <first-from-list list="summaryEntriesInfos" entry="timeEntriesInfo"/>
        <if-not-empty field="timeEntriesInfo">
          <if-not-empty field="timeEntriesInfo.actualEntryStartDate">
            <if>
                <condition>
                    <or>
                        <if-empty field="highInfo.actualStartDate"/>
                        <if-compare-field field="highInfo.actualStartDate" operator="greater" type="Timestamp" to-field="timeEntriesInfo.actualEntryStartDate"/>
                    </or>
                </condition>
                <then>
                    <set field="highInfo.actualStartDate" from-field="timeEntriesInfo.actualEntryStartDate"/>
                </then>
            </if>
          </if-not-empty>
        </if-not-empty>
    </simple-method>

    <simple-method method-name="combineInfo" short-description="combine lower level status, dates of tasks.">
        <call-simple-method method-name="combineStatusInfo"/>
        <call-simple-method method-name="combineDatesAndPlannedHoursInfo"/>
        <call-simple-method method-name="combineActualHours"/>
    </simple-method>

    <simple-method method-name="combineActualHours" short-description="combine lower level Actual hours info.">
        <!-- 
        -to calculate actual hours : the declared number of hours in time entry should be multiplied by the 
         max percentage declared in PartyRate if a valid party rate can be found for the party associated to a
         the timesheet associated to this time entry and has the same rateType as this timeEntry 
        -actualHoursOriginal is the total of hours in time entries without application of percentage declared in partyRate
         -->
        <clear-field field="originalHours"/>
        <clear-field field="actualHours"/>
        <clear-field field="originalActualHours"/>

        <!-- I- get timeEntries for which there is no rate  (originalHours)-->
        <entity-condition entity-name="ProjectPhaseTaskActualNotRatedHoursView" list="notRatedValues">
            <condition-list>
                <condition-expr field-name="projectId" from-field="highInfo.projectId" ignore-if-empty="true"/>
                <condition-expr field-name="phaseId" from-field="highInfo.phaseId" ignore-if-empty="true"/>
                <condition-expr field-name="taskId" from-field="highInfo.taskId" ignore-if-empty="true"/>
                <condition-expr field-name="hoursPartyId" from-field="parameters.hoursPartyId" ignore-if-empty="true"/>
            </condition-list>
            <select-field field-name="totalOriginalHours"/>
        </entity-condition>
        <first-from-list list="notRatedValues" entry="notRatedValue"/>
        <set field="originalHours" from-field="notRatedValue.totalOriginalHours" type="Double"/>

        <!-- II- get total for timeEntries having a partyRate that should be applied
        before applying rate (totalOriginalHours)
        after applying rate (totalRatedHours)-->
        <entity-condition entity-name="ProjectPhaseTaskActualRatedHoursView" list="ratedValues">
            <condition-list>
                <condition-expr field-name="projectId" from-field="highInfo.projectId" ignore-if-empty="true"/>
                <condition-expr field-name="phaseId" from-field="highInfo.phaseId" ignore-if-empty="true"/>
                <condition-expr field-name="taskId" from-field="highInfo.taskId" ignore-if-empty="true"/>
                <condition-expr field-name="hoursPartyId" from-field="parameters.hoursPartyId" ignore-if-empty="true"/>
            </condition-list>
            <select-field field-name="totalOriginalHours"/>
            <select-field field-name="totalRatedHours"/>
        </entity-condition>
        <first-from-list list="ratedValues" entry="ratedValue"/>
        <!-- not used ratedValue.totalRatedHours  because not works, reason seem to be totalRatedHours is a calculated field ??? -->
        <call-object-method method-name="getDouble" obj-field="ratedValue" ret-field="actualHours">
            <string value="totalRatedHours"/>
        </call-object-method>

        <if-empty field="actualHours">
            <set field="actualHours" from-field="originalHours"/>
            <else>
                <calculate field="actualHours" type="Double">
                    <calcop operator="add" field="originalHours">
                        <calcop operator="get" field="actualHours"/>
                    </calcop>
                </calculate>
            </else>
        </if-empty>

        <if-empty field="originalHours">
            <set field="originalActualHours" from-field="ratedValue.totalOriginalHours" type="Double"/>
            <else>
                <calculate field="originalActualHours" type="Double">
                    <calcop operator="add" field="originalHours">
                        <calcop operator="get" field="ratedValue.totalOriginalHours"/>
                    </calcop>
                </calculate>
            </else>
        </if-empty>

        <set field="highInfo.originalActualHours" from-field="originalActualHours"/>
        <set field="highInfo.actualHours" from-field="actualHours"/>
        <!-- do the same but for non-billed hours -->
        <!-- first get not rated hours -->
        <entity-condition entity-name="ProjectPhaseTaskActualNotRatedHoursView" list="notRatedValues">
            <condition-list>
                <condition-expr field-name="projectId" from-field="highInfo.projectId" ignore-if-empty="true"/>
                <condition-expr field-name="phaseId" from-field="highInfo.phaseId" ignore-if-empty="true"/>
                <condition-expr field-name="taskId" from-field="highInfo.taskId" ignore-if-empty="true"/>
                <condition-expr field-name="hoursPartyId" from-field="parameters.hoursPartyId" ignore-if-empty="true"/>
                <condition-expr field-name="invoiceId" from-field="nullField"/>
            </condition-list>
            <select-field field-name="totalOriginalHours"/>
        </entity-condition>
        <first-from-list list="notRatedValues" entry="notRatedValue"/>
        <set field="actualNonBilledHours" from-field="notRatedValue.totalOriginalHours" type="Double"/>
        <!-- second get non billed for entries having an invoiceId -->
        <entity-condition entity-name="ProjectPhaseTaskActualRatedHoursView" list="ratedValues">
            <condition-list>
                <condition-expr field-name="projectId" from-field="highInfo.projectId" ignore-if-empty="true"/>
                <condition-expr field-name="phaseId" from-field="highInfo.phaseId" ignore-if-empty="true"/>
                <condition-expr field-name="taskId" from-field="highInfo.taskId" ignore-if-empty="true"/>
                <condition-expr field-name="hoursPartyId" from-field="parameters.hoursPartyId" ignore-if-empty="true"/>
                <condition-expr field-name="invoiceId" from-field="nullField"/>
            </condition-list>
            <select-field field-name="totalOriginalHours"/>
            <select-field field-name="totalRatedHours"/>
        </entity-condition>
        <first-from-list list="ratedValues" entry="ratedValue"/>
        <call-object-method method-name="getDouble" obj-field="ratedValue" ret-field="actualHours">
            <string value="totalOriginalHours"/>
        </call-object-method>

        <if-not-empty field="actualNonBilledHours">
            <calculate field="actualNonBilledHours" type="Double">
                <calcop operator="get" field="actualNonBilledHours">
                    <calcop operator="add" field="actualHours"/>
                </calcop>
            </calculate>
            <else>
                <set field="actualNonBilledHours" from-field="totalOriginalHours" default-value="0" type="Double"/>
            </else>
        </if-not-empty>
        <set field="highInfo.actualNonBilledHours" from-field="actualNonBilledHours" type="Double"/>
    </simple-method>

    <simple-method method-name="combineInfoOld" short-description="combine lower level status, dates of tasks.">
        <!-- in/output highInfo infoMap -->
        <!-- input lowInfo info map -->
        <!-- set the dates from the lower level tasks -->
        <if-not-empty field="lowInfo.estimatedStartDate">
            <if-empty field="highInfo.estimatedStartDate">
                <set field="highInfo.estimatedStartDate" from-field="lowInfo.estimatedStartDate"/>
                <else>
                    <if-compare-field to-field="lowInfo.estimatedStartDate" field="highInfo.estimatedStartDate" operator="greater" type="Timestamp">
                        <set field="highInfo.estimatedStartDate" from-field="lowInfo.estimatedStartDate"/>
                    </if-compare-field>
                </else>
            </if-empty>
        </if-not-empty>
        <if-not-empty field="lowInfo.estimatedCompletionDate">
            <if-empty field="highInfo.estimatedCompletionDate">
                <set field="highInfo.estimatedCompletionDate" from-field="lowInfo.estimatedCompletionDate"/>
                <else>
                    <if-compare-field to-field="lowInfo.estimatedCompletionDate" field="highInfo.estimatedCompletionDate" operator="less" type="Timestamp">
                        <set field="highInfo.estimatedCompletionDate" from-field="lowInfo.estimatedCompletionDate"/>
                    </if-compare-field>
                </else>
            </if-empty>
        </if-not-empty>
        <if-not-empty field="lowInfo.actualStartDate">
            <if-empty field="highInfo.actualStartDate">
                <set field="highInfo.actualStartDate" from-field="lowInfo.actualStartDate"/>
                <else>
                    <if-compare-field to-field="lowInfo.actualStartDate" field="highInfo.actualStartDate" operator="greater" type="Timestamp">
                        <set field="highInfo.actualStartDate" from-field="lowInfo.actualStartDate"/>
                    </if-compare-field>
                </else>
            </if-empty>
        </if-not-empty>
        <if-not-empty field="lowInfo.actualCompletionDate">
            <if-empty field="highInfo.actualCompletionDate">
                <set field="highInfo.actualCompletionDate" from-field="lowInfo.actualCompletionDate"/>
                <else>
                    <if-compare-field to-field="lowInfo.actualCompletionDate" field="highInfo.actualCompletionDate" operator="less" type="Timestamp">
                        <set field="highInfo.actualCompletionDate" from-field="lowInfo.actualCompletionDate"/>
                    </if-compare-field>
                </else>
            </if-empty>
        </if-not-empty>

        <!-- combine the priorities -->
        <if-not-empty field="lowInfo.priority">
            <if-empty field="highInfo.priority">
                <set field="highInfo.priority" from-field="lowInfo.priority"/>
                <else>
                    <if-compare-field to-field="lowInfo.priority" field="highInfo.priority" operator="greater">
                        <set field="highInfo.priority" from-field="lowInfo.priority"/>
                    </if-compare-field>
                </else>
            </if-empty>
        </if-not-empty>

        <!-- if lowlevel type equals TASK then get create the status first -->
        <if-compare field="lowInfo.workEffortTypeId" value="TASK" operator="equals">
            <if-compare field="lowInfo.currentStatusId" value="PTS_CREATED" operator="equals">
                <get-related value-field="lowInfo" relation-name="WorkEffortPartyAssignment" list="assignsAll"/>
                <filter-list-by-date list="assignsAll" to-list="assigns"/>
                <if-not-empty field="assigns">
                    <set field="lowInfo.currentStatusId" value="PTS_CREATED_AS"/><!-- task is assigned -->
                </if-not-empty>
                <get-related value-field="lowInfo" relation-name="TimeEntry" list="entries"/>
                <if-not-empty field="entries">
                    <set field="lowInfo.currentStatusId" value="PTS_CREATED_IP"/><!-- task is in progress -->
                </if-not-empty>
            </if-compare>
        </if-compare>

        <entity-one entity-name="StatusItem" value-field="status">
            <field-map field-name="statusId" from-field="lowInfo.currentStatusId"/>
        </entity-one>
        <if-empty field="highInfo.sequenceId">
            <set field="highInfo.sequenceId" from-field="status.sequenceId"/>
            <else>
                <if>
                    <condition>
                        <and>
                            <if-compare-field field="highInfo.sequenceId" to-field="status.sequenceId" operator="less"/>
                            <and>
                                <if-compare field="highInfo.sequenceId" value="05" operator="not-equals"/>
                                <if-compare field="status.sequenceId" value="09" operator="not-equals"/>
                            </and>
                        </and>
                    </condition>
                    <then>
                        <set field="highInfo.sequenceId" from-field="status.sequenceId"/>
                    </then>
                    <else>
                        <set field="highInfo.sequenceId" value="05"/>
                    </else>
                </if>
            </else>
        </if-empty>
    </simple-method>

    <simple-method method-name="createDates" short-description="merge the estimated and actual dates">
        <!-- input/output is 'highInfo map -->
        <!-- create dates taking the last known one to save space on the list -->
        <if-not-empty field="highInfo.actualStartDate">
            <set field="highInfo.startDate" from-field="highInfo.actualStartDate"/>
            <else>
                <set field="highInfo.startDate" from-field="highInfo.estimatedStartDate"/>
            </else>
        </if-not-empty>
        <if-not-empty field="highInfo.actualCompletionDate">
            <set field="highInfo.completionDate" from-field="highInfo.actualCompletionDate"/>
            <else>
                <set field="highInfo.completionDate" from-field="highInfo.estimatedCompletionDate"/>
            </else>
        </if-not-empty>
    </simple-method>

    <simple-method method-name="updateTimeEntry" short-description="">
        <if-compare field="hours" value="-1" operator="equals">
            <return/>
        </if-compare>
        <if-not-empty field="timeEntry.timeEntryId">
            <if-compare field="hours" operator="equals" value="0">
                <set  field="teDelMap.timeEntryId" from-field="timeEntry.timeEntryId"/>
                <call-service service-name="deleteTimeEntry" in-map-name="teDelMap"/>
                <else>
                    <clear-field field="teUpdMap"/>
                    <set field="teUpdMap.hours" from-field="hours" type="Double"/>
                    <set field="teUpdMap.timeEntryId" from-field="timeEntry.timeEntryId"/>
                    <set field="teUpdMap.rateTypeId" from-field="parameters.rateTypeId"/>
                    <set field="teUpdMap.partyId" from-field="userLogin.partyId"/>
                    <call-service service-name="updateTimeEntry" in-map-name="teUpdMap"/>
                </else>
            </if-compare>
            <else>
                <if-compare field="hours" operator="not-equals" value="0">
                    <set-service-fields service-name="createTimeEntry" map="parameters" to-map="teCreMap"/>
                    <set field="teCreMap.hours" from-field="hours" type="Double"/>
                    <set field="teCreMap.fromDate" from-field="fromDate"/>
                    <set field="teCreMap.partyId" from-field="userLogin.partyId"/>
                    <call-service service-name="createTimeEntry" in-map-name="teCreMap"/>
                </if-compare>
            </else>
        </if-not-empty>
    </simple-method>

    <simple-method method-name="createTimeEntryInTimesheet" short-description="Creates TimeEntry and searches for a timesheetId if not provided">
        <if-not-empty field="parameters.fromDate">
            <if-empty field="parameters.timesheetId">
                <entity-condition entity-name="Timesheet" list="timesheets">
                    <condition-list combine="and">
                        <condition-expr field-name="fromDate" operator="less-equals" from-field="parameters.fromDate"/>
                        <condition-expr field-name="thruDate" operator="greater-equals" from-field="parameters.fromDate"/>
                        <condition-expr field-name="partyId" operator="equals" from-field="parameters.partyId"/>
                    </condition-list>
                </entity-condition>
                <if-not-empty field="timesheets">
                    <!-- use existing timesheet -->
                    <first-from-list list="timesheets" entry="timesheet"/>
                    <if-compare field="timesheet.statusId" value="TIMESHEET_IN_PROCESS" operator="equals">
                        <set field="parameters.timesheetId" from-field="timesheet.timesheetId"/>
                        <else>
                            <add-error>
                                <fail-property resource="ProjectMgrUiLabels" property="ProjectMgrCannotAddToTimesheet"/>
                            </add-error>
                            <check-errors/>
                        </else>
                    </if-compare>
                    <else>
                        <!-- create new timesheet -->
                        <set field="parameters.requiredDate" from-field="parameters.fromDate"/>
                        <call-simple-method method-name="createTimesheetForThisWeek" xml-resource="component://workeffort/minilang/timesheet/TimesheetServices.xml"/>
                        <set field="parameters.timesheetId" from-field="newEntity.timesheetId"/>
                    </else>
                </if-not-empty>
            </if-empty>
        </if-not-empty>
        <!-- get role for this party in this project -->
        <if-empty field="parameters.roleTypeId">
          <entity-and entity-name="ProjectPartyAndPhaseAndTask" list="taskRoles" filter-by-date="true">
              <field-map field-name="partyId" from-field="parameters.partyId"/>
              <field-map field-name="workEffortId" from-field="parameters.workEffortId"/>
          </entity-and>
          <first-from-list list="taskRoles" entry="taskRole"/>
          <set field="parameters.roleTypeId" from-field="taskRole.roleTypeId"/>
          <set field="parameters.statusId" value="PAS_ASSIGNED"/>
          <call-simple-method method-name="assignPartyToWorkEffort" xml-resource="component://workeffort/minilang/workeffort/WorkEffortSimpleServices.xml"/>
        </if-empty>
        <call-simple-method method-name="createTimeEntry" xml-resource="component://workeffort/minilang/timesheet/TimesheetServices.xml"/>
    </simple-method>

    <simple-method method-name="addProjectTimeToNewInvoice" short-description="add all reported time on all completed timesheets from all workefforts for a project">
        <!-- recreate the invoice if still in preparation in order to correct errors. -->
        <if-compare operator="equals" value="Y" field="parameters.reCreate">
            <entity-one entity-name="Invoice" value-field="invoice"/>
            <if-empty field="invoice">
                <add-error>
                    <fail-property resource="WorkEffortUiLabels" property="WorkEffortTimesheetCannotFindInvoice"/>
                </add-error>
                <check-errors/>
            </if-empty>

            <call-simple-method method-name="InvoiceStatusInProgress" xml-resource="component://accounting/minilang/invoice/InvoiceServices.xml"/>

            <entity-and entity-name="TimeEntry" list="entries">
                <field-map field-name="invoiceId" from-field="parameters.invoiceId"/>
            </entity-and>
            <iterate list="entries" entry="timeEntry">
                <clear-field field="timeEntry.invoiceId"/>
                <clear-field field="timeEntry.invoiceItemSeqId"/>
                <store-value value-field="timeEntry"/>
            </iterate>
            <set field="removeItems.invoiceId" from-field="parameters.invoiceId"/>
            <remove-by-and entity-name="InvoiceItem" map="removeItems"/>
            <set field="notFirst" value="Y"/><!-- do not create, only add -->
        </if-compare>
        <entity-condition entity-name="ProjectPhaseTaskAndTimeEntryTimeSheet" list="tasks">
            <condition-list combine="and">
                <condition-expr field-name="projectId" operator="equals" from-field="parameters.projectId"/>
                <condition-expr field-name="invoiceId" operator="equals" from-field="nullField"/>
                <condition-expr field-name="timesheetStatusId" operator="equals" value="TIMESHEET_COMPLETED"/>
                <condition-expr field-name="fromDate" operator="less" from-field="parameters.thruDate" ignore-if-empty="true"/>
            </condition-list>
            <order-by field-name="workEffortId"/>
        </entity-condition>
        <if-empty field="tasks">
            <add-error>
                <fail-property resource="ProjectMgrUiLabels" property="ProjectMgrNoTimeentryItemsFound"/>
            </add-error>
            <check-errors/>
        </if-empty>
        <iterate list="tasks" entry="task">
            <if-empty field="notFirst">
                <!-- first time so create invoice -->
                <set-service-fields service-name="addWorkEffortTimeToNewInvoice" map="parameters" to-map="addTaskToNewInvoice"/>
                <set field="addTaskToNewInvoice.workEffortId" from-field="task.workEffortId"/>
                <set field="addTaskToNewInvoice.combineInvoiceItem" value="Y"/>
                <set field="addTaskToNewInvoice.thruDate" from-field="parameters.thruDate"/>
                <call-service service-name="addWorkEffortTimeToNewInvoice" in-map-name="addTaskToNewInvoice">
                    <result-to-field result-name="invoiceId" field="parameters.invoiceId"/>
                </call-service>
                <set field="addTaskToInvoice.combineInvoiceItem" value="Y"/>
                <field-to-result field="parameters.invoiceId" result-name="invoiceId"/>
                <set field="notFirst" value="Y"/>
                <else>
                    <if>
                        <condition>
                            <or>
                                <if-empty field="oldWorkeffortId"/>
                                <if-compare-field operator="not-equals" field="oldWorkeffortId" to-field="task.workEffortId"/>
                            </or>
                        </condition>
                        <then>
                            <!-- add to created invoice -->
                            <set field="addTaskToInvoice.combineInvoiceItem" value="Y"/>
                            <set field="addTaskToInvoice.invoiceId" from-field="parameters.invoiceId"/>
                            <set field="addTaskToInvoice.workEffortId" from-field="task.workEffortId"/>
                            <set field="addTaskToInvoice.thruDate" from-field="parameters.thruDate"/>
                            <call-service service-name="addWorkEffortTimeToInvoice" in-map-name="addTaskToInvoice"/>
                        </then>
                    </if>
                    <set field="oldWorkeffortId" from-field="task.workEffortId"/>
                </else>
            </if-empty>
        </iterate>
    </simple-method>

    <simple-method method-name="addProjectTimeToInvoice" short-description="add all reported time on all completed timesheets
        from all workefforts for a project to an existing invoice">
        <entity-one entity-name="Invoice" value-field="invoice"/>
        <if-empty field="invoice">
            <add-error>
                <fail-property resource="WorkEffortUiLabels" property="WorkEffortTimesheetCannotFindInvoice"/>
            </add-error>
            <check-errors/>
        </if-empty>

        <call-simple-method method-name="InvoiceStatusInProgress" xml-resource="component://accounting/minilang/invoice/InvoiceServices.xml"/>

        <entity-condition entity-name="ProjectPhaseTaskAndTimeEntryTimeSheet" list="tasks">
            <condition-list combine="and">
                <condition-expr field-name="projectId" operator="equals" from-field="parameters.projectId"/>
                <condition-expr field-name="invoiceId" operator="equals" from-field="nullField"/>
                <condition-expr field-name="timesheetStatusId" operator="equals" value="TIMESHEET_COMPLETED"/>
                <condition-expr field-name="fromDate" operator="less" from-field="parameters.thruDate" ignore-if-empty="true"/>
            </condition-list>
            <order-by field-name="workEffortId"/>
        </entity-condition>

        <if-empty field="tasks">
            <add-error>
                <fail-property resource="ProjectMgrUiLabels" property="ProjectMgrNoTimeentryItemsFound"/>
            </add-error>
            <check-errors/>
        </if-empty>

        <iterate list="tasks" entry="task">
            <if>
                <condition>
                    <or>
                        <if-empty field="oldWorkeffortId"/>
                        <if-compare-field operator="not-equals" field="oldWorkeffortId" to-field="task.workEffortId"/>
                    </or>
                </condition>
                <then>
                    <!-- add to created invoice -->
                    <set field="addTaskToInvoice.combineInvoiceItem" value="Y"/>
                    <set field="addTaskToInvoice.invoiceId" from-field="parameters.invoiceId"/>
                    <set field="addTaskToInvoice.workEffortId" from-field="task.workEffortId"/>
                    <set field="addTaskToInvoice.thruDate" from-field="parameters.thruDate"/>
                    <call-service service-name="addWorkEffortTimeToInvoice" in-map-name="addTaskToInvoice"/>
                </then>
            </if>
            <set field="oldWorkeffortId" from-field="task.workEffortId"/>
        </iterate>
    </simple-method>

    <simple-method method-name="addValidationPartiesToTask" short-description="SECA to add either project-testing or -approval parties to a task when a task is set to complete">
        <!-- check if this is the last party which completed his task -->
        <entity-condition entity-name="WorkEffortPartyAssignment" list="openTasks" filter-by-date="true">
            <condition-list combine="and">
                <condition-expr field-name="workEffortId" operator="equals" from-field="parameters.workEffortId"/>
                <condition-expr field-name="statusId" operator="not-equals" value="PAS_COMPLETED"/>
                <condition-expr field-name="partyId" operator="not-equals" from-field="parameters.partyId"/>
            </condition-list>
        </entity-condition>
        <if-empty field="openTasks">
            <set field="getProject.taskId" from-field="parameters.workEffortId"/>
            <call-service service-name="getProjectIdAndNameFromTask" in-map-name="getProject">
            <result-to-field result-name="projectId"/>
            </call-service>
            <!-- see who is reponsible for testing/validation in this project -->
            <entity-condition entity-name="WorkEffortPartyAssignment" list="assigns" filter-by-date="true">
                <condition-list combine="and">
                    <condition-expr field-name="workEffortId" operator="equals" from-field="projectId"/>
                    <condition-expr field-name="partyId" operator="not-equals" from-field="parameters.partyId"/><!-- should not test/val own work -->
                    <condition-list combine="or">
                        <condition-expr field-name="roleTypeId" operator="equals" value="PROVIDER_VALIDATOR"/>
                        <condition-expr field-name="roleTypeId" operator="equals" value="PROVIDER_TESTER"/>
                    </condition-list>
                </condition-list>
            </entity-condition>
            <if-not-empty field="assigns">
                <set field="addAssign.workEffortId" from-field="parameters.workEffortId"/>
                <set field="addAssign.statusId" value="PAS_ASSIGNED"/>
                <iterate list="assigns" entry="assign">
                    <make-value entity-name="WorkEffortPartyAssignment" value-field="newAssign"/>
                    <set field="newAssign.workEffortId" from-field="parameters.workEffortId"/>
                    <set field="newAssign.partyId" from-field="assign.partyId"/>
                    <set field="newAssign.roleTypeId" from-field="assign.roleTypeId"/>
                    <set field="newAssign.assignedByUserLoginId" value="system"/>
                    <now-timestamp field="newAssign.fromDate"/>
                    <set field="newAssign.statusId" value="PAS_ASSIGNED"/>
                    <create-value value-field="newAssign"/>
                </iterate>
                <else>
                    <log level="info" message="No validation parties defined in this project: no validation parties added...."/>
                </else>
            </if-not-empty>
            <else>
                <log level="info" message="Not the last party who completes his task: validation parties not added...."/>
            </else>
        </if-empty>
    </simple-method>

</simple-methods>
