You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by nm...@apache.org on 2020/03/10 13:38:17 UTC

[ofbiz-framework] branch trunk updated: Improved: Convert PartyServices.xml from mini lang to groovy (OFBIZ-11361)

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

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


The following commit(s) were added to refs/heads/trunk by this push:
     new c8a838e  Improved: Convert PartyServices.xml from mini lang to groovy (OFBIZ-11361)
c8a838e is described below

commit c8a838ef03aca43cddd827cf7139c94261898c80
Author: Nicolas Malin <ni...@nereide.fr>
AuthorDate: Tue Mar 10 14:37:57 2020 +0100

    Improved: Convert PartyServices.xml from mini lang to groovy
    (OFBIZ-11361)
    
    Thanks to Leila Mekika for providing the patch
---
 .../party/groovyScripts/party/PartyServices.groovy |  927 +++++++++++++++++
 .../party/minilang/party/PartyServices.xml         | 1074 --------------------
 applications/party/servicedef/services.xml         |   76 +-
 applications/party/servicedef/services_view.xml    |   20 +-
 4 files changed, 975 insertions(+), 1122 deletions(-)

diff --git a/applications/party/groovyScripts/party/PartyServices.groovy b/applications/party/groovyScripts/party/PartyServices.groovy
new file mode 100644
index 0000000..d1d9360
--- /dev/null
+++ b/applications/party/groovyScripts/party/PartyServices.groovy
@@ -0,0 +1,927 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.ofbiz.entity.condition.EntityCondition
+import org.apache.ofbiz.entity.condition.EntityJoinOperator
+import org.apache.ofbiz.entity.condition.EntityOperator
+import org.apache.ofbiz.entity.util.EntityUtil
+import org.apache.ofbiz.minilang.SimpleMapProcessor
+
+import java.sql.Timestamp
+import org.apache.ofbiz.base.util.StringUtil
+import org.apache.ofbiz.base.util.UtilDateTime
+import org.apache.ofbiz.entity.GenericValue
+import org.apache.ofbiz.service.ServiceUtil
+import org.apache.ofbiz.party.party.PartyHelper
+
+/**
+  * Save Party Name Change
+  */
+def savePartyNameChange() {
+    // for special case in ecommerce, if no partyId is passed in use userLogin.partyId
+    if (!parameters.partyId) parameters.partyId = userLogin.partyId
+
+    GenericValue partyNameHistory = makeValue('PartyNameHistory', parameters)
+    partyNameHistory.changeDate = UtilDateTime.nowTimestamp()
+
+    if (parameters.groupName) {
+        GenericValue partyGroup = from('PartyGroup').where(parameters).queryOne()
+        if (partyGroup.groupName != parameters.groupName) {
+            partyNameHistory.setNonPKFields(partyGroup)
+            partyNameHistory.create()
+        }
+    } else if (parameters.firstName ||
+               parameters.middleName || 
+               parameters.lastName ||
+               parameters.personalTitle ||
+               parameters.suffix) {
+        GenericValue person = from('Person').where(parameters).queryOne()
+        if (person.firstName != parameters.firstName ||
+                person.middleName != parameters.middleName ||
+                person.lastName != parameters.lastName ||
+                person.personalTitle != parameters.personalTitle ||
+                person.suffix != parameters.suffix) {
+            partyNameHistory.setNonPKFields(person)
+            partyNameHistory.create()
+        }
+    }
+    return success()
+}
+
+/**
+ * Get Party Name For Date
+ */
+def getPartyNameForDate() {
+    Map resultMap = success()
+
+    List<GenericValue> partyNameHistoryList = from("PartyNameHistory")
+        .where("partyId", parameters.partyId)
+        .orderBy("-changeDate")
+        .queryList()
+
+    GenericValue person = from('Person').where(parameters).queryOne()
+    GenericValue partyGroup = from('PartyGroup').where(parameters).queryOne()
+
+    if (!parameters.compareDate) parameters.compareDate = UtilDateTime.nowTimestamp()
+
+    // go through the list which is sorted by most recent first and find the oldest (last) one with the changeDate greater than the compareDate
+    GenericValue partyNameHistoryCurrent = null
+    for (GenericValue partyNameHistory : partyNameHistoryList) {
+        Timestamp changeDate = partyNameHistory.changeDate
+        if (changeDate.after(parameters.compareDate)) {
+            partyNameHistoryCurrent = partyNameHistory
+        }
+    }
+
+    if (partyNameHistoryCurrent) {
+        // partyNameHistoryCurrent has a value
+        if (person) {
+            person = partyNameHistoryCurrent
+        } else if (partyGroup) {
+            partyGroup = partyNameHistoryCurrent
+        }
+    }
+
+    if (person) {
+        resultMap.firstName = person.firstName
+        resultMap.lastName = person.lastName
+        if (person.middleName) resultMap.middleName = person.middleName
+        if (person.personalTitle) resultMap.personalTitle = person.personalTitle
+        if (person.suffix) resultMap.suffix = person.suffix
+        if (person.gender) resultMap.gender = person.gender
+
+        resultMap.fullName = PartyHelper.getPartyName(person, parameters.lastNameFirst == "Y")
+    } else if (partyGroup) {
+        resultMap.groupName = partyGroup.groupName
+        resultMap.fullName = partyGroup.groupName
+    }
+
+    return resultMap
+}
+
+/**
+ * Get Postal Address Boundary
+ */
+def getPostalAddressBoundary() {
+    Map resultMap = success()
+
+    List<String> geoIds = from('PostalAddressBoundary')
+        .where(makeValue('PostalAddressBoundary', parameters))
+        .getFieldList('geoId')
+
+    List<GenericValue> geos = from('Geo')
+            .where(EntityCondition.makeCondition('geoId', EntityOperator.IN, geoIds))
+            .queryList()
+
+    resultMap.geos = geos
+    return resultMap
+}
+
+/**
+ * Create mass party identification with association between value and type
+ */
+def createPartyIdentifications() {
+    Map resultMap = success()
+
+    for (Map.Entry<String, String> entry : parameters.identifications.entrySet()) {
+        GenericValue identificationType = from('PartyIdentificationType')
+            .where("partyIdentificationTypeId", entry.getValue())
+            .queryOne()
+        if (identificationType) {
+            String idValue = parameters.identifications[identificationType.partyIdentificationTypeId]
+            if (idValue) {
+                run service: 'createPartyIdentification', with: [partyId: parameters.partyId,
+                                                                 idValue: idValue,
+                                                                 partyIdentificationTypeId: identificationType.partyIdentificationTypeId]
+            }
+        }
+    }
+ 
+    return resultMap
+}
+
+/**
+ * Sets Party Profile Defaults
+ */
+def setPartyProfileDefaults() {
+    if (!parameters.partyId) parameters.partyId = userLogin.partyId
+
+    // lookup existing value
+    GenericValue partyProfileDefault = from('PartyProfileDefault')
+        .where(parameters)
+        .queryOne()
+    if (!partyProfileDefault) {
+
+        // create the profile defaut because is missing
+        partyProfileDefault = makeValue('PartyProfileDefault', parameters)
+        partyProfileDefault.create()
+    } else {
+
+        // update the fields
+        partyProfileDefault.setNonPKFields(parameters)
+        partyProfileDefault.store()
+    }
+
+    return success()
+}
+
+/**
+ * Gets all parties related to partyIdFrom using the PartyRelationship entity
+ */
+def getPartiesByRelationship() {
+    Map resultMap = success()
+
+    GenericValue lookupMap = makeValue('PartyRelationship')
+    lookupMap.setAllFields(parameters, false, null, null)
+    List<String> partyIdTos = from('PartyRelationship')
+        .where(lookupMap)
+        .getFieldList('partyIdTo')
+
+    List<GenericValue> parties = from('Party')
+            .where(EntityCondition.makeCondition('partyId', EntityOperator.IN, partyIdTos))
+            .queryList()
+    if (parties) resultMap.parties = parties
+    return resultMap
+}
+
+/**
+ * Gets Parent Organizations for an Organization Party
+ */
+def getParentOrganizations() {
+    Map resultMap = success()
+
+    List relatedPartyIdList = [parameters.organizationPartyId]
+    String recurse = "Y"
+    if (parameters.getParentsOfParents) recurse = parameters.getParentsOfParents
+
+    Map res = followPartyRelationshipsInline(relatedPartyIdList,'GROUP_ROLLUP',
+            'ORGANIZATION_UNIT', 'Y', 'PARENT_ORGANIZATION',
+            null, 'Y', recurse, 'Y')
+    resultMap.parentOrganizationPartyIdList = res.relatedPartyIdList
+    return resultMap
+}
+
+/**
+ * Get Parties Related to a Party
+ */
+def getRelatedParties() {
+    Map resultMap = success()
+
+    List relatedPartyIdList = [parameters.partyIdFrom]
+    resultMap.relatedPartyIdList = followPartyRelationshipsInline(relatedPartyIdList, parameters.partyRelationshipTypeId,
+            parameters.roleTypeIdFrom, parameters.roleTypeIdFromInclueAllChildTypes,
+            parameters.roleTypeIdTo, parameters.roleTypeIdToIncludeAllChildTypes,
+            parameters.includeFromToSwitched, parameters.recurse, parameters.useCache)
+    return resultMap
+}
+
+/**
+ * Get Child RoleTypes
+ */
+def getChildRoleTypes () {
+    Map resultMap = success()
+
+    Map res = getChildRoleTypesInline([parameters.roleTypeId])
+
+    resultMap.childRoleTypeIdList = res.childRoleTypeIdList
+    return resultMap
+}
+
+/**
+ * Get the email of the party
+ */
+def getPartyEmail () {
+    Map resultMap = success()
+
+    // First try to find primary email Address when not found get other email
+    Timestamp searchTimestamp = UtilDateTime.nowTimestamp()
+    GenericValue emailAddress = from("PartyContactWithPurpose")
+        .where(partyId: parameters.partyId, contactMechPurposeTypeId: parameters.contactMechPurposeTypeId)
+        .filterByDate(searchTimestamp, 'purposeFromDate', 'purposeThruDate', 'contactFromDate', 'contactThruDate')
+        .queryFirst()
+    // Any other email
+    if (!emailAddress) {
+        emailAddress = from("PartyAndContactMech")
+        .where(partyId: parameters.partyId, contactMechTypeId: "EMAIL_ADDRESS")
+        .filterByDate(searchTimestamp)
+        .queryFirst()
+    }
+    // Any other electronic address
+    if (!emailAddress) {
+        emailAddress = from("PartyAndContactMech")
+        .where(partyId: parameters.partyId, contactMechTypeId: "ELECTRONIC_ADDRESS")
+        .filterByDate(searchTimestamp)
+        .queryFirst()
+    }
+    if (emailAddress) {
+        resultMap.emailAddress = emailAddress.infoString
+        resultMap.contactMechId = emailAddress.contactMechId
+    }
+    return resultMap
+}
+
+/**
+ * Get the telephone number of the party
+ */
+def getPartyTelephone () {
+    Map resultMap = success()
+    Timestamp searchTimestamp = UtilDateTime.nowTimestamp()
+    GenericValue telephone = null
+
+    List<GenericValue> telephoneList = from("PartyContactDetailByPurpose")
+        .where(partyId: parameters.partyId, contactMechTypeId: 'TELECOM_NUMBER')
+        .filterByDate(searchTimestamp, 'purposeFromDate', 'purposeThruDate', 'fromDate', 'thruDate')
+        .queryList()
+    if (telephoneList) {
+        List<String> types = []
+        if (!parameters.contactMechPurposeTypeId) {
+            // search in this order if not provided
+            types = ['PRIMARY_PHONE', 'PHONE_MOBILE', 'PHONE_WORK',
+                     'PHONE_QUICK', 'PHONE_HOME', 'PHONE_BILLING',
+                     'PHONE_SHIPPING', 'PHONE_SHIP_ORIG']
+        } else {
+            types << parameters.contactMechPurposeTypeId
+        }
+
+        telephone = EntityUtil.getFirst(EntityUtil.filterByCondition(telephoneList,
+                EntityCondition.makeCondition("contactMechPurposeTypeId", EntityJoinOperator.IN, types)))
+        if (telephone) {
+            resultMap.contactMechPurposeTypeId = telephone.contactMechPurposeTypeId
+        }
+    } else {
+        telephone = from("PartyAndContactMech")
+            .where(partyId: parameters.partyId, contactMechTypeId: 'TELECOM_NUMBER')
+            .filterByDate(searchTimestamp)
+            .queryFirst()
+    }
+
+    if (telephone) {
+        resultMap.contactMechId = telephone.contactMechId
+        if (telephone.containsKey('countryCode')) {
+            resultMap.countryCode = telephone.countryCode
+        } else if (telephone.containsKey('tnCountryCode')) {
+            resultMap.countryCode = telephone.tnCountryCode
+        }
+        if (telephone.containsKey('areaCode')) {
+            resultMap.areaCode = telephone.areaCode 
+        } else if (telephone.containsKey('tnAreaCode')) {
+            resultMap.areaCode = telephone.tnAreaCode
+        }
+        if (telephone.containsKey('contactNumber')) {
+            resultMap.contactNumber = telephone.contactNumber
+        } else if (telephone.containsKey('tnContactNumber')) {
+            resultMap.contactNumber = telephone.tnContactNumber
+        }
+        if (telephone.containsKey('extension')) resultMap.extension = telephone.extension
+    }
+
+    return resultMap
+}
+
+/**
+ * Get the postal address of the party
+ */
+def getPartyPostalAddress () {
+    Map resultMap = success()
+    GenericValue address = null
+    Timestamp searchTimestamp = UtilDateTime.nowTimestamp()
+
+    List<GenericValue> addressList = from("PartyContactDetailByPurpose")
+        .where(partyId: parameters.partyId, contactMechTypeId: 'POSTAL_ADDRESS')
+        .filterByDate(searchTimestamp, 'purposeFromDate', 'purposeThruDate', 'fromDate', 'thruDate')
+        .queryList()
+    if (addressList) {
+        List<String> types = []
+        if (!parameters.contactMechPurposeTypeId) {
+            // search in this order if not provided
+            types = ['GENERAL_LOCATION', 'BILLING_LOCATION', 'PAYMENT_LOCATION', 'SHIPPING_LOCATION']
+        } else {
+            types << parameters.contactMechPurposeTypeId
+        }
+        addressList = EntityUtil.filterByCondition(addressList,
+                EntityCondition.makeCondition("contactMechPurposeTypeId", EntityJoinOperator.IN, types))
+        if (addressList) {
+            address = addressList[0]
+            resultMap.contactMechPurposeTypeId = address.contactMechPurposeTypeId
+        }
+    } else {
+        address = from("PartyAndContactMech")
+            .where(partyId: parameters.partyId, contactMechTypeId: 'POSTAL_ADDRESS')
+            .filterByDate(searchTimestamp)
+            .queryFirst()
+    }
+
+    if (address) {
+        resultMap.contactMechId = address.contactMechId
+        if (address.containsKey("address1")) {
+            if (address.address1)           resultMap.address1 = address.address1
+            if (address.address2)           resultMap.address2 = address.address2
+            if (address.directions)         resultMap.directions = address.directions
+            if (address.city)               resultMap.city = address.city
+            if (address.postalCode)         resultMap.postalCode = address.postalCode
+            if (address.stateProvinceGeoId) resultMap.stateProvinceGeoId = address.stateProvinceGeoId
+            if (address.countyGeoId)        resultMap.countyGeoId = address.countyGeoId
+            if (address.countryGeoId)       resultMap.countryGeoId = address.countryGeoId
+        } else if (address.containsKey("paAddress1")) {
+            if (address.paAddress1)           resultMap.address1 = address.paAddress1
+            if (address.paAddress2)           resultMap.address2 = address.paAddress2
+            if (address.paDirections)         resultMap.directions = address.paDirections
+            if (address.paCity)               resultMap.city = address.paCity
+            if (address.paPostalCode)         resultMap.postalCode = address.paPostalCode
+            if (address.paStateProvinceGeoId) resultMap.stateProvinceGeoId = address.paStateProvinceGeoId
+            if (address.paCountyGeoId)        resultMap.countyGeoId = address.paCountyGeoId
+            if (address.paCountryGeoId)       resultMap.countryGeoId = address.paCountryGeoId
+        }
+    }
+
+    return resultMap
+}
+
+/**
+  * Create an AddressMatchMap
+  */
+def createAddressMatchMap() {
+    GenericValue newAddressMatchMap = makeValue('AddressMatchMap', parameters)
+    if (parameters.mapKey)   newAddressMatchMap.mapKey = ((String) parameters.mapKey).toUpperCase(context.locale)
+    if (parameters.mapValue) newAddressMatchMap.mapValue = ((String) parameters.mapValue).toUpperCase(context.locale)
+    newAddressMatchMap.create()
+    return success()
+}
+
+/**
+ * Remove all AddressMatchMap
+ */
+def clearAddressMatchMap() {
+    delegator.removeAll('AddressMatchMap')
+    return success()
+}
+
+/**
+ * Create a PartyRelationship
+ */
+def createPartyRelationship() {
+    if (!parameters.fromDate)       parameters.fromDate = UtilDateTime.nowTimestamp()
+    if (!parameters.roleTypeIdFrom) parameters.roleTypeIdFrom = '_NA_'
+    if (!parameters.roleTypeIdTo)   parameters.roleTypeIdTo = '_NA_'
+    if (!parameters.partyIdFrom)    parameters.partyIdFrom = userLogin.partyId
+
+    // check if not already exist
+    List<GenericValue> partyRels = from("PartyRelationship")
+        .where(partyIdFrom: parameters.partyIdFrom,
+               partyIdTo: parameters.partyIdTo,
+               roleTypeIdFrom: parameters.roleTypeIdFrom,
+               roleTypeIdTo: parameters.roleTypeIdTo)
+        .filterByDate()
+        .queryList()
+    if (!partyRels) {
+        GenericValue partyRelationship = makeValue('PartyRelationship', parameters)
+        partyRelationship.create()
+    }
+    return success()
+}
+
+/**
+ * Update a PartyRelationship
+ */
+def updatePartyRelationship() {
+    if (!parameters.roleTypeIdFrom) parameters.roleTypeIdFrom = '_NA_'
+    if (!parameters.roleTypeIdTo)   parameters.roleTypeIdTo = '_NA_'
+
+    // lookup existing value
+    GenericValue partyRelationship = from('PartyRelationship')
+        .where(parameters)
+        .queryOne()
+    partyRelationship.setNonPKFields(parameters)
+    partyRelationship.store()
+
+    return success()
+}
+
+/**
+ * Delete a PartyRelationship
+ */
+def deletePartyRelationship() {
+    if (!parameters.roleTypeIdFrom) parameters.roleTypeIdFrom = '_NA_'
+    if (!parameters.roleTypeIdTo)   parameters.roleTypeIdTo = '_NA_'
+
+    // lookup existing value
+    GenericValue partyRelationship = from('PartyRelationship')
+        .where(parameters)
+        .queryOne()
+    partyRelationship.remove()
+
+    return success()
+}
+
+/**
+ * Create a company/contact relationship and add the related roles
+ */
+def createPartyRelationshipContactAccount() {
+    Map resultMap = success()
+
+    Map roleMap = [partyId: parameters.accountPartyId, roleTypeId: 'ACCOUNT']
+    GenericValue partyRole = from('PartyRole')
+        .where(roleMap)
+        .queryOne()
+    if (!partyRole) {
+        run service: 'createPartyRole', with: roleMap
+    }
+
+    roleMap = [partyId: parameters.contactPartyId, roleTypeId: 'CONTACT']
+    partyRole = from('PartyRole')
+        .where(roleMap)
+        .queryOne()
+    if (!partyRole) {
+        run service: 'createPartyRole', with: roleMap
+    }
+
+    run service: 'createPartyRelationship',
+        with: [partyIdFrom: parameters.accountPartyId,
+               roleTypeIdFrom: 'ACCOUNT',
+               partyIdTo: parameters.contactPartyId,
+               roleTypeIdTo: 'CONTACT',
+               partyRelationshipTypeId: 'EMPLOYMENT',
+               comments: parameters.comments
+              ]
+ 
+    return resultMap
+}
+
+/**
+ * Notification email on party creation
+ */
+def sendCreatePartyEmailNotification() {
+    Map resultMap = success()
+
+    Map lookupMap = [emailType: 'PARTY_REGIS_CONFIRM']
+    String productStoreId = parameters.productStoreId
+    if (!productStoreId) {
+        logWarning('No productStoreId specified.')
+    } else {
+        lookupMap.productStoreId = productStoreId
+    }
+
+    GenericValue storeEmail = from('ProductStoreEmailSetting')
+        .where(lookupMap)
+        .queryOne()
+    if (storeEmail && storeEmail.bodyScreenLocation) {
+        GenericValue webSite = from('WebSite')
+            .where(productStoreId: storeEmail.productStoreId)
+            .queryFirst()
+
+        Map bodyParameters = parameters
+        GenericValue person = from('Person')
+            .where(parameters)
+            .queryOne()
+        bodyParameters.person = person
+
+        run service: 'sendMailFromScreen',
+            with: [bodyParameters: bodyParameters,
+                   sendTo: parameters.emailAddress,
+                   subject: storeEmail.subject,
+                   sendFrom: storeEmail.fromAddress,
+                   sendCc: storeEmail.ccAddress,
+                   sendBcc: storeEmail.bccAddress,
+                   contentType: storeEmail.contentType,
+                   bodyScreenUri: storeEmail.bodyScreenLocation,
+                   webSiteId: webSite.webSiteId,
+                   emailType: lookupMap.emailType]
+    }
+    return resultMap
+}
+
+/**
+ * Send the Notification email on personal information update
+ */
+def sendUpdatePersonalInfoEmailNotification() {
+    Map resultMap = success()
+
+    Map lookupMap = [emailType: 'UPD_PRSNL_INF_CNFRM']
+    String productStoreId = parameters.productStoreId
+    if (!productStoreId) {
+        logWarning('No productStoreId specified.')
+    } else {
+        lookupMap.productStoreId = productStoreId
+    }
+
+    GenericValue storeEmail = from('ProductStoreEmailSetting')
+        .where(lookupMap)
+        .queryOne()
+    if (storeEmail && storeEmail.bodyScreenLocation) {
+        String partyId = parameters.partyId
+        if (parameters.updatedUserLogin) partyId = parameters.updatedUserLogin.partyId
+
+        GenericValue webSite = from('WebSite')
+            .where(productStoreId: storeEmail.productStoreId)
+            .queryFirst()
+
+        Map bodyParameters = parameters
+        GenericValue partyAndPerson = from('PartyAndPerson')
+            .where(parameters)
+            .queryOne()
+        bodyParameters.partyAndPerson = partyAndPerson
+
+        GenericValue partyContactDetailByPurpose = from('PartyContactDetailByPurpose')
+            .where(partyId: partyId, contactMechPurposeTypeId: 'PRIMARY_EMAIL')
+            .filterByDate()
+           .queryFirst()
+        if (!partyContactDetailByPurpose) logWarning('No email found.')
+        else {
+            GenericValue contactMech = from('ContactMech')
+                .where(contactMechId: partyContactDetailByPurpose.contactMechId)
+                .queryOne()
+            run service: 'sendMailFromScreen',
+                with: [bodyParameters: bodyParameters,
+                       sendTo: contactMech.infoString,
+                       subject: storeEmail.subject,
+                       sendFrom: storeEmail.fromAddress,
+                       sendCc: storeEmail.ccAddress,
+                       sendBcc: storeEmail.bccAddress,
+                       contentType: storeEmail.contentType,
+                       bodyScreenUri: storeEmail.bodyScreenLocation,
+                       webSiteId: webSite.webSiteId,
+                       emailType: lookupMap.emailType]
+        }
+    }
+    return resultMap
+}
+
+/**
+ * Send the Notification email on account activated
+ */
+def sendAccountActivatedEmailNotification() {
+    Map resultMap = success()
+
+    Map lookupMap = [emailType: 'PRDS_CUST_ACTIVATED']
+    String productStoreId = parameters.productStoreId
+    if (!productStoreId) {
+        logWarning('No productStoreId specified.')
+    } else {
+        lookupMap.productStoreId = productStoreId
+    }
+
+    GenericValue storeEmail = from('ProductStoreEmailSetting')
+            .where(lookupMap)
+            .queryOne()
+    if (storeEmail && storeEmail.bodyScreenLocation) {
+        String partyId = parameters.partyId
+        if (!partyId) partyId = userLogin.partyId
+
+        GenericValue webSite = from('WebSite')
+                .where(productStoreId: storeEmail.productStoreId)
+                .queryFirst()
+
+        Map bodyParameters = parameters
+        GenericValue person = from('Person')
+                .where(partyId: partyId)
+                .queryOne()
+        bodyParameters.person = person
+
+        GenericValue partyContactDetailByPurpose = from('PartyContactDetailByPurpose')
+                .where(partyId: partyId, contactMechPurposeTypeId: 'PRIMARY_EMAIL')
+                .filterByDate()
+                .queryFirst()
+        if (!partyContactDetailByPurpose) logWarning('No email found.')
+        else {
+            GenericValue contactMech = from('ContactMech')
+                .where('contactMechId': partyContactDetailByPurpose.contactMechId)
+                .queryOne()
+            run service: 'sendMailFromScreen',
+                with: [bodyParameters: bodyParameters,
+                       sendTo: contactMech.infoString,
+                       subject: storeEmail.subject,
+                       sendFrom: storeEmail.fromAddress,
+                       sendCc: storeEmail.ccAddress,
+                       sendBcc: storeEmail.bccAddress,
+                       contentType: storeEmail.contentType,
+                       bodyScreenUri: storeEmail.bodyScreenLocation,
+                       webSiteId: webSite.webSiteId,
+                       emailType: lookupMap.emailType]
+        }
+    }
+    return resultMap
+}
+
+/**
+ * Create and update a person
+ */
+def createUpdatePerson() {
+    Map resultMap = success()
+    String partyId = parameters.partyId
+
+    Map personContext = [partyId: partyId]
+    List<String> messages = []
+    //TODO need to convert from MapProcessor
+    SimpleMapProcessor.runSimpleMapProcessor('component://party/minilang/party/PartyMapProcs.xml',
+            'person', parameters, personContext, messages, context.locale)
+
+    // Check errors
+    if (messages) return error(StringUtil.join(messages, ','))
+
+    GenericValue party = from('Party')
+       .where(partyId: partyId)
+       .queryOne()
+    String serviceName = (party ? 'update' : 'create') + 'Person'
+    run service: serviceName, with: personContext
+    resultMap.partyId = partyId
+    return resultMap
+}
+
+/**
+ * Create customer profile on basis of First Name ,Last Name and Email Address
+ */
+def quickCreateCustomer() {
+    Map resultMap = success()
+
+    Map personContext = [:]
+    Map emailContext = [:]
+    List<String> messages = []
+    //TODO need to convert from MapProcessor
+    SimpleMapProcessor.runSimpleMapProcessor('component://party/minilang/contact/PartyContactMechMapProcs.xml',
+            'person', parameters, personContext, messages, context.locale)
+    SimpleMapProcessor.runSimpleMapProcessor('component://party/minilang/contact/PartyContactMechMapProcs.xml',
+            'emailAddress', parameters, emailContext, messages, context.locale)
+
+    // Check errors
+    if (messages) return error(StringUtil.join(messages, ','))
+
+    // Create person
+    Map serviceResult = run service: 'createPerson', with: personContext
+    if (ServiceUtil.isError(serviceResult)) return serviceResult
+    String partyId = serviceResult.partyId
+
+    GenericValue userLogin = from('UserLogin')
+            .where(userLoginId: 'system')
+            .cache()
+            .queryOne()
+    emailContext.partyId = partyId
+    emailContext.userLogin = userLogin
+    emailContext.contactMechPurposeTypeId = 'PRIMARY_EMAIL'
+    serviceResult = run service: 'createPartyEmailAddress', with: emailContext
+    if (ServiceUtil.isError(serviceResult)) return serviceResult
+
+    // Sign up for Contact List
+    if (parameters.subscribeContactList == 'Y') {
+        serviceResult = run service: 'signUpForContactList', with: [partyId: partyId,
+                                                                    contactListId: parameters.contactListId,
+                                                                    email: parameters.emailAddress]
+        if (ServiceUtil.isError(serviceResult)) return serviceResult
+    }
+
+    // Create the PartyRole
+    serviceResult = run service: 'createPartyRole', with: [partyId: partyId,
+                                                           roleTypeId: 'CUSTOMER']
+    if (ServiceUtil.isError(serviceResult)) return serviceResult
+
+    resultMap.partyId = partyId
+    return resultMap
+}
+
+/**
+ * Get the main role of this party which is a child of the MAIN_ROLE roletypeId
+ */
+def getPartyMainRole() {
+    Map resultMap = success()
+
+    List<GenericValue> partyRoles = from("PartyRole")
+        .where(partyId: parameters.partyId)
+        .queryList()
+    // find the role in the list
+    String mainRoleTypeId = null
+    for (GenericValue partyRole : partyRoles) {
+        if (!mainRoleTypeId) {
+            List<GenericValue> roleTypeIn3Levels = from("RoleTypeIn3Levels")
+                    .where(topRoleTypeId: 'MAIN_ROLE', lowRoleTypeId: partyRole.roleTypeId)
+                    .queryList()
+            if (roleTypeIn3Levels) {
+                mainRoleTypeId = partyRole.roleTypeId
+            }
+        }
+    }
+    if (mainRoleTypeId) {
+        resultMap.roleTypeId = mainRoleTypeId
+        GenericValue roleType = from('RoleType')
+                .where(roleTypeId: mainRoleTypeId)
+                .cache()
+                .queryOne()
+        resultMap.description = roleType.description
+    }
+
+    return resultMap
+}
+
+// Specific methods
+
+/**
+ * Follow PartyRelationships
+ * Uses the following fields in the env (with * are required):
+ * relatedPartyIdList* (initial partyIdFrom should be in this list; accumulator of new partyIds, ie all partyIdTo found will be added to this, thus can support recursion)
+ * partyRelationshipTypeId
+ * roleTypeIdFrom
+ * roleTypeIdFromIncludeAllChildTypes
+ * roleTypeIdTo
+ * roleTypeIdToInclueAllChildTypes
+ * includeFromToSwitched
+ * recurse
+ * useCache (should be "true" or "false")
+ */
+def followPartyRelationshipsInline(List relatedPartyIdList,String partyRelationshipTypeId, String roleTypeIdFrom, String roleTypeIdFromIncludeAllChildTypes,
+    String roleTypeIdTo, String roleTypeIdToInclueAllChildTypes, String includeFromToSwitched, String recurse, String useCache ) {
+    Map resultMap = success()
+    Timestamp nowTimestamp = UtilDateTime.nowTimestamp()
+
+    List roleTypeIdFromList = null
+    if (roleTypeIdFrom) roleTypeIdFromList = [roleTypeIdFrom]
+    if ("Y" == roleTypeIdFromIncludeAllChildTypes) {
+        List roleTypeIdListName = roleTypeIdFromList
+        Map res = getChildRoleTypesInline(roleTypeIdListName)
+        roleTypeIdFromList = res.childRoleTypeIdList
+    }
+
+    List roleTypeIdToList = null
+    if (roleTypeIdTo) roleTypeIdToList = [roleTypeIdTo]
+    if ("Y" == roleTypeIdToInclueAllChildTypes) {
+        List roleTypeIdListName = roleTypeIdToList
+        Map res = getChildRoleTypesInline(roleTypeIdListName)
+        roleTypeIdToList = res.childRoleTypeIdList
+    }
+
+    Map res = followPartyRelationshipsInlineRecurse(relatedPartyIdList, roleTypeIdFromList, roleTypeIdToList,
+        partyRelationshipTypeId, includeFromToSwitched, recurse, nowTimestamp, useCache)
+    for (String newPartyId : res.NewRelatedPartyIdList) {
+        if (!relatedPartyIdList.contains(newPartyId)) {
+            relatedPartyIdList << newPartyId
+        }
+    }
+    resultMap.relatedPartyIdList = relatedPartyIdList
+    return resultMap
+}
+
+/**
+ * Follow PartyRelationships Recurse
+ */
+def followPartyRelationshipsInlineRecurse (List relatedPartyIdList, List roleTypeIdFromList, List roleTypeIdToList, String partyRelationshipTypeId,
+     String includeFromToSwitched, String recurse, Timestamp searchTimestamp, String useCache) {
+
+    Map resultMap = success()
+    List newRelatedPartyIdList = []
+    List relatedPartyIdAlreadySearchedList = []
+    for (String relatedPartyId : relatedPartyIdList) {
+         if (!relatedPartyIdAlreadySearchedList.contains(relatedPartyId)) {
+             relatedPartyIdAlreadySearchedList.add(relatedPartyId)
+
+             List<EntityCondition> entityConditionList = [EntityCondition.makeCondition("partyIdFrom", relatedPartyId)]
+             if (roleTypeIdFromList) entityConditionList << EntityCondition.makeCondition("roleTypeIdFrom", EntityOperator.IN, roleTypeIdFromList)
+             if (roleTypeIdToList) entityConditionList << EntityCondition.makeCondition("roleTypeIdTo", EntityOperator.IN, roleTypeIdToList)
+             if (partyRelationshipTypeId) entityConditionList << EntityCondition.makeCondition("partyRelationshipTypeId", partyRelationshipTypeId)
+             EntityCondition condition = EntityCondition.makeCondition(entityConditionList)
+
+             // get the newest (highest date) first
+             List PartyRelationshipList = from("PartyRelationship")
+                     .where(condition)
+                     .orderBy('-fromDate')
+                     .filterByDate(searchTimestamp)
+                     .cache('Y' == useCache)
+                     .queryList()
+             for (GenericValue PartyRelationship : PartyRelationshipList) {
+                 if ( !relatedPartyIdList.contains(PartyRelationship.partyIdTo) &&
+                      !newRelatedPartyIdList.contains(PartyRelationship.partyIdTo)) {
+                      newRelatedPartyIdList << PartyRelationship.partyIdTo
+                 }
+             }
+
+             if ('Y' == includeFromToSwitched) {
+                 entityConditionList = [EntityCondition.makeCondition("partyIdTo", relatedPartyId)]
+                 // The roles are reversed
+                 if (roleTypeIdFromList) entityConditionList << EntityCondition.makeCondition("roleTypeIdFrom", EntityOperator.IN, roleTypeIdToList)
+                 if (roleTypeIdToList) entityConditionList << EntityCondition.makeCondition("roleTypeIdTo", EntityOperator.IN, roleTypeIdFromList)
+                 if (partyRelationshipTypeId) entityConditionList << EntityCondition.makeCondition("partyRelationshipTypeId", partyRelationshipTypeId)
+                 condition = EntityCondition.makeCondition(entityConditionList)
+
+                PartyRelationshipList = from("PartyRelationship")
+                        .where(condition)
+                        .orderBy('-fromDate')
+                        .filterByDate(searchTimestamp)
+                        .cache('Y' == useCache)
+                        .queryList()
+                for (GenericValue PartyRelationship : PartyRelationshipList) {
+                    if ( !relatedPartyIdList.contains(PartyRelationship.partyIdFrom) &&
+                         !newRelatedPartyIdList.contains(PartyRelationship.partyIdFrom)) {
+                         newRelatedPartyIdList << PartyRelationship.partyIdFrom
+                    }
+                }
+             }
+         }
+    }
+
+    // if we found new ones, add them to the master list and if recurse=Y then recurse
+    if (newRelatedPartyIdList) {
+        relatedPartyIdList = newRelatedPartyIdList
+        if ('Y' == recurse) {
+            logVerbose("Recursively calling followPartyRelationshipsInlineRecurse NewRelatedPartyIdList=${newRelatedPartyIdList}")
+            Map res = followPartyRelationshipsInlineRecurse(relatedPartyIdList, roleTypeIdFromList, roleTypeIdToList,
+                partyRelationshipTypeId, includeFromToSwitched, recurse, searchTimestamp, useCache)
+            for (String newPartyId : res.NewRelatedPartyIdList) {
+                if ( !newRelatedPartyIdList.contains(newPartyId)) {
+                     newRelatedPartyIdList << newPartyId
+                }
+            }
+        }
+    }
+    resultMap.NewRelatedPartyIdList = newRelatedPartyIdList
+    return resultMap
+}
+
+/**
+ * Get Child RoleTypes Inline
+ */
+def getChildRoleTypesInline (List roleTypeIdListName) {
+    Map resultMap = success()
+    List newRoleTypeIdList = []
+    List roleTypeIdAlreadySearchedList = []
+
+    for (String roleTypeId : roleTypeIdListName) {
+        if (!roleTypeIdAlreadySearchedList.contains(roleTypeId)) {
+            roleTypeIdAlreadySearchedList << roleTypeId
+
+            List RoleTypeList = from("RoleType").where(parentTypeId: roleTypeId).cache().queryList()
+            for (GenericValue newRoleType : RoleTypeList) {
+                if ( !roleTypeIdListName.contains(newRoleType.roleTypeId) &&
+                     !newRoleTypeIdList.contains(newRoleType.roleTypeId)) {
+                     newRoleTypeIdList << newRoleType.roleTypeId
+                }
+            }
+        }
+    }
+
+    // if we found new ones, add them to the master list and if recurse=Y then recurse
+    if (newRoleTypeIdList) {
+        roleTypeIdListName = newRoleTypeIdList
+        logVerbose("Recursively calling getChildRoleTypesInline roleTypeIdListName=${roleTypeIdListName}, newRoleTypeIdList=${newRoleTypeIdList}")
+        Map res = getChildRoleTypesInline(roleTypeIdListName)
+        for (String childRoleTypeId : res.childRoleTypeIdList) {
+            if ( !newRoleTypeIdList.contains(childRoleTypeId)) {
+                 newRoleTypeIdList << childRoleTypeId
+            }
+        }
+    }
+
+    resultMap.childRoleTypeIdList = newRoleTypeIdList
+    return resultMap
+}
diff --git a/applications/party/minilang/party/PartyServices.xml b/applications/party/minilang/party/PartyServices.xml
deleted file mode 100644
index fcdebf7..0000000
--- a/applications/party/minilang/party/PartyServices.xml
+++ /dev/null
@@ -1,1074 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License.  You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied.  See the License for the
-specific language governing permissions and limitations
-under the License.
--->
-
-<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xmlns="http://ofbiz.apache.org/Simple-Method" xsi:schemaLocation="http://ofbiz.apache.org/Simple-Method http://ofbiz.apache.org/dtds/simple-methods.xsd">
-
-    <simple-method method-name="savePartyNameChange" short-description="Save Party Name Change">
-        <!-- for special case in ecommerce, if no partyId is passed in use userLogin.partyId -->
-        <if-empty field="parameters.partyId">
-            <set field="parameters.partyId" from-field="userLogin.partyId"/>
-        </if-empty>
-
-        <make-value entity-name="PartyNameHistory" value-field="partyNameHistory"/>
-        <set-pk-fields value-field="partyNameHistory" map="parameters"/>
-        <now-timestamp field="partyNameHistory.changeDate"/>
-
-        <if>
-            <condition><not><if-empty field="parameters.groupName"/></not></condition>
-            <then>
-                <entity-one entity-name="PartyGroup" value-field="partyGroup"/>
-                <if>
-                    <condition><if-compare-field field="partyGroup.groupName" to-field="parameters.groupName" operator="not-equals"/></condition>
-                    <then>
-                        <set-nonpk-fields map="partyGroup" value-field="partyNameHistory"/>
-                        <create-value value-field="partyNameHistory"/>
-                    </then>
-                </if>
-            </then>
-            <else-if>
-                <condition>
-                    <or>
-                        <not><if-empty field="parameters.firstName"></if-empty></not>
-                        <not><if-empty field="parameters.middleName"></if-empty></not>
-                        <not><if-empty field="parameters.lastName"></if-empty></not>
-                        <not><if-empty field="parameters.personalTitle"></if-empty></not>
-                        <not><if-empty field="parameters.suffix"></if-empty></not>
-                    </or>
-                </condition>
-                <then>
-                    <entity-one entity-name="Person" value-field="person"/>
-                    <if>
-                        <condition>
-                            <or>
-                                <if-compare-field field="person.firstName" to-field="parameters.firstName" operator="not-equals"/>
-                                <if-compare-field field="person.middleName" to-field="parameters.middleName" operator="not-equals"/>
-                                <if-compare-field field="person.lastName" to-field="parameters.lastName" operator="not-equals"/>
-                                <if-compare-field field="person.personalTitle" to-field="parameters.personalTitle" operator="not-equals"/>
-                                <if-compare-field field="person.suffix" to-field="parameters.suffix" operator="not-equals"/>
-                            </or>
-                        </condition>
-                        <then>
-                            <set-nonpk-fields map="person" value-field="partyNameHistory"/>
-                            <create-value value-field="partyNameHistory"/>
-                        </then>
-                    </if>
-                </then>
-            </else-if>
-        </if>
-    </simple-method>
-
-    <simple-method method-name="getPartyNameForDate" short-description="Get Party Name For Date">
-        <entity-and entity-name="PartyNameHistory" list="partyNameHistoryList">
-            <field-map field-name="partyId" from-field="parameters.partyId"/>
-            <order-by field-name="-changeDate"/>
-        </entity-and>
-        <entity-one entity-name="Person" value-field="person"/>
-        <entity-one entity-name="PartyGroup" value-field="partyGroup"/>
-        <if-empty field="parameters.compareDate">
-            <now-timestamp field="nowTimestamp"/>
-            <set field="parameters.compareDate" from-field="nowTimestamp"/>
-        </if-empty>
-        <!-- go through the list which is sorted by most recent first and find the oldest (last) one with the changeDate greater than the compareDate -->
-        <iterate list="partyNameHistoryList" entry="partyNameHistory">
-            <if-compare-field field="partyNameHistory.changeDate" to-field="parameters.compareDate" operator="greater" type="Timestamp">
-                <set field="partyNameHistoryCurrent" from-field="partyNameHistory"/>
-            </if-compare-field>
-        </iterate>
-
-        <if-empty field="partyNameHistoryCurrent">
-            <if-not-empty field="person">
-                <field-to-result field="person.firstName" result-name="firstName"/>
-                <if-not-empty field="person.middleName">
-                    <field-to-result field="person.middleName" result-name="middleName"/>
-                </if-not-empty>
-                <field-to-result field="person.lastName" result-name="lastName"/>
-                <if-not-empty field="person.personalTitle">
-                    <field-to-result field="person.personalTitle" result-name="personalTitle"/>
-                </if-not-empty>
-                <if-not-empty field="person.gender">
-                    <field-to-result field="person.gender" result-name="gender"/>
-                </if-not-empty>
-                <if-not-empty field="person.suffix">
-                    <field-to-result field="person.suffix" result-name="suffix"/>
-                </if-not-empty>
-
-
-                <if-compare field="parameters.lastNameFirst" operator="equals" value="Y">
-                    <set field="fullName" value="${person.personalTitle} ${person.lastName}, ${person.firstName} ${person.middleName} ${person.suffix}"/>
-                <else>
-                    <set field="fullName" value="${person.personalTitle} ${person.firstName} ${person.middleName} ${person.lastName} ${person.suffix}"/>
-                </else>
-                </if-compare>
-                <field-to-result field="fullName"/>
-
-                <else>
-                    <if-not-empty field="partyGroup">
-                        <field-to-result field="partyGroup.groupName" result-name="groupName"/>
-                        <field-to-result field="partyGroup.groupName" result-name="fullName"/>
-                    </if-not-empty>
-                </else>
-            </if-not-empty>
-            <else>
-                <!-- partyNameHistoryCurrent has a value -->
-                <if-not-empty field="person">
-                    <field-to-result field="partyNameHistoryCurrent.firstName" result-name="firstName"/>
-                    <if-not-empty field="partyNameHistoryCurrent.middleName">
-                        <field-to-result field="partyNameHistoryCurrent.middleName" result-name="middleName"/>
-                    </if-not-empty>
-                    <field-to-result field="partyNameHistoryCurrent.lastName" result-name="lastName"/>
-                    <if-not-empty field="partyNameHistoryCurrent.personalTitle">
-                        <field-to-result field="partyNameHistoryCurrent.personalTitle" result-name="personalTitle"/>
-                    </if-not-empty>
-                    <if-not-empty field="partyNameHistoryCurrent.suffix">
-                        <field-to-result field="partyNameHistoryCurrent.suffix" result-name="suffix"/>
-                    </if-not-empty>
-                    <if-not-empty field="person.gender">
-                        <field-to-result field="person.gender" result-name="gender"/>
-                    </if-not-empty>
-
-
-                    <if-compare field="parameters.lastNameFirst" operator="equals" value="Y">
-                        <set field="fullName" value="${partyNameHistoryCurrent.personalTitle} ${partyNameHistoryCurrent.lastName}, ${partyNameHistoryCurrent.firstName} ${partyNameHistoryCurrent.middleName} ${partyNameHistoryCurrent.suffix}"/>
-                    <else>
-                        <set field="fullName" value="${partyNameHistoryCurrent.personalTitle} ${partyNameHistoryCurrent.firstName} ${partyNameHistoryCurrent.middleName} ${partyNameHistoryCurrent.lastName} ${partyNameHistoryCurrent.suffix}"/>
-                    </else>
-                    </if-compare>
-                    <field-to-result field="fullName"/>
-
-                    <else>
-                        <if-not-empty field="partyGroup">
-                            <field-to-result field="partyNameHistoryCurrent.groupName" result-name="groupName"/>
-                            <field-to-result field="partyNameHistoryCurrent.groupName" result-name="fullName"/>
-                        </if-not-empty>
-                    </else>
-                </if-not-empty>
-            </else>
-        </if-empty>
-    </simple-method>
-
-    <!-- PostalAddressBoundary methods -->
-    <simple-method method-name="getPostalAddressBoundary" short-description="Get Postal Address Boundary">
-        <make-value entity-name="PostalAddressBoundary" value-field="postalAddressBoundaryLookupMap"/>
-        <set field="postalAddressBoundaryLookupMap.geoId" from-field="parameters.geoId"/>
-        <find-by-and entity-name="PostalAddressBoundary" map="postalAddressBoundaryLookupMap" list="postalAddressBoundaries"/>
-        <iterate list="postalAddressBoundaries" entry="postalAddressBoundary">
-            <get-related-one value-field="postalAddressBoundary" to-value-field="geo" relation-name="Geo"/>
-            <field-to-list field="geo" list="geos"/>
-        </iterate>
-        <field-to-result field="geos"/>
-    </simple-method>
-    
-    <!-- PartyIdentification methods -->
-    <simple-method method-name="createPartyIdentifications" short-description="create mass party identification with association between value and type">
-        <set field="partyIdentCtx.partyId" from-field="parameters.partyId"/>
-        <iterate-map key="key" value="value" map="parameters.identifications">
-            <entity-one entity-name="PartyIdentificationType" value-field="identificationType" use-cache="true">
-                <field-map field-name="partyIdentificationTypeId" from-field="value"/>
-            </entity-one>
-            <if-not-empty field="identificationType">
-                <set field="idValue" value="${parameters.identifications.${identificationType.partyIdentificationTypeId}}"/>
-                <if-not-empty field="idValue">
-                    <set field="partyIdentCtx.partyIdentificationTypeId" from-field="identificationType.partyIdentificationTypeId"/>
-                    <set field="partyIdentCtx.idValue" from-field="idValue"/>
-                    <call-service service-name="createPartyIdentification" in-map-name="partyIdentCtx"/>
-                </if-not-empty> 
-            </if-not-empty>
-        </iterate-map>
-    </simple-method>
-
-    <!-- party profile default -->
-    <simple-method method-name="setPartyProfileDefaults" short-description="Sets Party Profile Defaults">
-        <if-empty field="parameters.partyId">
-            <set from-field="userLogin.partyId" field="parameters.partyId"/>
-        </if-empty>
-
-        <!-- lookup existing value -->
-        <entity-one entity-name="PartyProfileDefault" value-field="partyProfileDefault"/>
-        <if-empty field="partyProfileDefault">
-            <make-value entity-name="PartyProfileDefault" value-field="partyProfileDefault"/>
-            <set-pk-fields value-field="partyProfileDefault" map="parameters"/>
-            <create-value value-field="partyProfileDefault"/>
-        </if-empty>
-
-        <!-- update the fields -->
-        <set-nonpk-fields map="parameters" value-field="partyProfileDefault"/>
-        <store-value value-field="partyProfileDefault"/>
-    </simple-method>
-
-    <!-- create party content -->
-    <!-- TODO: this method will be deleted in favor of new content methods and the PartyContentServices.xml -->
-    <simple-method method-name="createPartyContent" short-description="Creates Party Associated Content" login-required="false">
-           <!-- make sure we are logged in when passing a partyId -->
-        <if-not-empty field="parameters.partyId">
-            <if-empty field="parameters.userLogin">
-                <add-error><fail-property resource="PartyUiLabels" property="PartyPermissionErrorForThisParty"/></add-error>
-                <check-errors/>
-            </if-empty>
-        </if-not-empty>
-
-        <!-- check permission when creating content on behalf of another party -->
-        <if-empty field="parameters.partyId">
-            <if-not-empty field="parameters.userLogin">
-                <set from-field="userLogin.partyId" field="parameters.partyId"/>
-                <if-compare-field to-field="userLogin.partyId" field="parameters.partyId" operator="not-equals">
-                    <check-permission permission="PARTYMGR" action="_UPDATE">
-                        <fail-property resource="PartyUiLabels" property="PartyPermissionErrorForThisParty"/>
-                    </check-permission>
-                </if-compare-field>
-            </if-not-empty>
-        </if-empty>
-       <if-not-empty field="parameters._uploadedFile_fileName">
-           <set field="absolute" value="true" type="Boolean"/>
-           <call-class-method method-name="getDataResourceContentUploadPath" class-name="org.apache.ofbiz.content.data.DataResourceWorker" ret-field="uploadPath">
-               <field field="delegator" type="org.apache.ofbiz.entity.Delegator"/>
-               <field field="absolute" type="boolean"/>
-           </call-class-method>
-           <log level="info" message="[createPartyContent] - Found Subdir : ${uploadPath}"/>
-           <!-- locate the file extension to use based on mime-type -->
-           <set from-field="parameters._uploadedFile_contentType" field="extenLookup.mimeTypeId"/>
-           <find-by-and entity-name="FileExtension" map="extenLookup" list="extensions"/>
-           <first-from-list list="extensions" entry="extension"/>
-           <set-service-fields service-name="createDataResource" map="parameters" to-map="dataResource"/>
-           <!-- create the data resource object -->
-           <set from-field="parameters._uploadedFile_fileName" field="dataResource.dataResourceName"/>
-           <set from-field="parameters._uploadedFile_contentType" field="dataResource.mimeTypeId"/>
-           <set value="LOCAL_FILE" field="dataResource.dataResourceTypeId"/>
-           <call-service service-name="createDataResource" in-map-name="dataResource" break-on-error="false">
-               <result-to-field result-name="dataResourceId" field="dataResourceId"/>
-           </call-service>
-
-           <set-service-fields service-name="updateDataResource" map="dataResource" to-map="dataResource"/>
-           <set from-field="dataResourceId" field="dataResource.dataResourceId"/>
-           <call-service service-name="updateDataResource" in-map-name="dataResource" break-on-error="false"/>
-           <set from-field="dataResource.dataResourceId" field="lookup.dataResourceId"/>
-           <find-by-primary-key entity-name="DataResource" map="lookup" value-field="dataResourceMap" use-cache="true"/>
-       </if-not-empty>
-
-       <set-service-fields service-name="createContent" map="parameters" to-map="createContentMap"/>
-       <if-not-empty field="parameters._uploadedFile_fileName">
-            <set from-field="dataResourceId" field="createContentMap.dataResourceId"/>
-       </if-not-empty>
-       <call-service service-name="createContent" in-map-name="createContentMap" break-on-error="false">
-            <result-to-field result-name="contentId" field="contentId"/>
-       </call-service>
-       <!-- create the content role -->
-       <if-not-empty field="parameters.partyId">
-            <now-timestamp field="nowTimestamp"/>
-            <set-service-fields service-name="createContentRole" map="parameters" to-map="contentRole"/>
-            <set from-field="contentId" field="contentRole.contentId"/>
-            <set from-field="parameters.partyId" field="contentRole.partyId"/>
-            <set from-field="nowTimestamp" field="contentRole.fromDate"/>
-            <set value="OWNER" field="contentRole.roleTypeId"/>
-            <call-service service-name="createContentRole" in-map-name="contentRole" break-on-error="false"/>
-            <!-- check party role -->
-            <make-value entity-name="PartyRole" value-field="partyRole"/>
-            <set-pk-fields value-field="partyRole" map="contentRole"/>
-            <find-by-and entity-name="PartyRole" map="partyRole" list="pRoles"/>
-            <if-empty field="pRoles">
-                <set-service-fields service-name="createPartyRole" map="contentRole" to-map="partyRole"/>
-                <call-service service-name="createPartyRole" in-map-name="partyRole" break-on-error="false"/>
-            </if-empty>
-       </if-not-empty>
-       <if-not-empty field="parameters._uploadedFile_fileName">
-            <!-- store the file -->
-            <set-service-fields service-name="createAnonFile" map="dataResourceMap" to-map="fileCtx"/>
-            <set from-field="parameters.uploadedFile" field="fileCtx.binData"/>
-            <set from-field="dataResourceMap" field="fileCtx.dataResource"/>
-            <call-service service-name="createAnonFile" in-map-name="fileCtx" include-user-login="true"/>
-        </if-not-empty>
-       <field-to-result field="contentId"/>
-    </simple-method>
-
-    <!-- Update party content -->
-    <!-- TODO: this method will be deleted in favor of new content methods and the PartyContentServices.xml -->
-    <simple-method method-name="updatePartyContent" short-description="Creates Party Associated Content" login-required="false">
-           <!-- make sure we are logged in when passing a partyId -->
-        <if-not-empty field="parameters.partyId">
-            <if-empty field="parameters.userLogin">
-                <add-error><fail-property resource="PartyUiLabels" property="PartyPermissionErrorForThisParty"/></add-error>
-                <check-errors/>
-            </if-empty>
-        </if-not-empty>
-
-        <!-- check permission when creating content on behalf of another party -->
-        <if-empty field="parameters.partyId">
-            <if-not-empty field="parameters.userLogin">
-                <set from-field="userLogin.partyId" field="parameters.partyId"/>
-                <if-compare-field to-field="userLogin.partyId" field="parameters.partyId" operator="not-equals">
-                    <check-permission permission="PARTYMGR" action="_UPDATE">
-                        <fail-property resource="PartyUiLabels" property="PartyPermissionErrorForThisParty"/>
-                    </check-permission>
-                </if-compare-field>
-            </if-not-empty>
-        </if-empty>
-
-        <if-not-empty field="parameters._uploadedFile_fileName">
-           <set from-field="parameters.contentId" field="lookupParam.contentId"/>
-           <find-by-primary-key entity-name="Content" map="lookupParam" value-field="content" use-cache="true"/>
-           <if-not-empty field="content.dataResourceId">
-               <set-service-fields service-name="updateDataResource" map="parameters" to-map="dataResource"/>
-               <set from-field="content.dataResourceId" field="dataResource.dataResourceId"/>
-               <call-service service-name="updateDataResource" in-map-name="dataResource" break-on-error="false"/>
-               <set from-field="content.dataResourceId" field="lookup.dataResourceId"/>
-               <find-by-primary-key entity-name="DataResource" map="lookup" value-field="dataResourceMap" use-cache="true"/>
-            <else>
-               <set field="absolute" value="true" type="Boolean"/>
-               <call-class-method method-name="getDataResourceContentUploadPath" class-name="org.apache.ofbiz.content.data.DataResourceWorker" ret-field="uploadPath">
-                   <field field="delegator" type="org.apache.ofbiz.entity.Delegator"/>
-                   <field field="absolute" type="boolean"/>
-               </call-class-method>
-               <log level="info" message="[createPartyContent] - Found Subdir : ${uploadPath}"/>
-               <!-- locate the file extension to use based on mime-type -->
-               <set from-field="parameters._uploadedFile_contentType" field="extenLookup.mimeTypeId"/>
-               <find-by-and entity-name="FileExtension" map="extenLookup" list="extensions"/>
-               <first-from-list list="extensions" entry="extension"/>
-               <set-service-fields service-name="createDataResource" map="parameters" to-map="dataResource"/>
-               <!-- create the data resource object -->
-                <!-- create the data resource object -->
-                <set from-field="parameters._uploadedFile_fileName" field="dataResource.dataResourceName"/>
-                <set from-field="parameters._uploadedFile_contentType" field="dataResource.mimeTypeId"/>
-                <set value="LOCAL_FILE" field="dataResource.dataResourceTypeId"/>
-                <call-service service-name="createDataResource" in-map-name="dataResource" break-on-error="false">
-                    <result-to-field result-name="dataResourceId" field="dataResourceId"/>
-                </call-service>
-                <set value="${uploadPath}/${dataResourceId}" field="dataResource.objectInfo"/>
-                <if-not-empty field="extension">
-                    <set value="${uploadPath}/${dataResourceId}.${extension.fileExtensionId}" field="dataResource.objectInfo"/>
-                </if-not-empty>
-                <set-service-fields service-name="updateDataResource" map="dataResource" to-map="dataResource"/>
-                <set from-field="dataResourceId" field="dataResource.dataResourceId"/>
-                <call-service service-name="updateDataResource" in-map-name="dataResource" break-on-error="false"/>
-                <set from-field="dataResource.dataResourceId" field="lookup.dataResourceId"/>
-                <find-by-primary-key entity-name="DataResource" map="lookup" value-field="dataResourceMap" use-cache="true"/>
-            </else>
-           </if-not-empty>
-       </if-not-empty>
-       <set-service-fields service-name="updateContent" map="parameters" to-map="updateContentMap"/>
-       <if-not-empty field="dataResourceId">
-           <set from-field="dataResourceId" field="updateContentMap.dataResourceId"/>
-       </if-not-empty>
-       <call-service service-name="updateContent" in-map-name="updateContentMap" break-on-error="false"/>
-       <if-not-empty field="parameters._uploadedFile_fileName">
-          <set-service-fields service-name="createAnonFile" map="dataResourceMap" to-map="fileCtx"/>
-          <set from-field="parameters.uploadedFile" field="fileCtx.binData"/>
-          <set from-field="dataResourceMap" field="fileCtx.dataResource"/>
-          <call-service service-name="createAnonFile" in-map-name="fileCtx" include-user-login="true"/>
-      </if-not-empty>
-        <field-to-result  field="parameters.contentId" result-name="contentId"/>
-    </simple-method>
-
-    <!-- get parties based on PartyRelationship -->
-    <simple-method method-name="getPartiesByRelationship"
-            short-description="Gets all parties related to partyIdFrom using the PartyRelationship entity" login-required="false">
-        <set from-field="parameters.partyIdFrom" field="lookupMap.partyIdFrom"/>
-        <set from-field="parameters.partyIdTo" field="lookupMap.partyIdTo"/>
-        <set from-field="parameters.roleTypeIdFrom" field="lookupMap.roleTypeIdFrom"/>
-        <set from-field="parameters.roleTypeIdTo" field="lookupMap.roleTypeIdTo"/>
-        <set from-field="parameters.statusId" field="lookupMap.statusId"/>
-        <set from-field="parameters.priorityTypeId" field="lookupMap.priorityTypeId"/>
-        <set from-field="parameters.partyRelationshipTypeId" field="lookupMap.partyRelationshipTypeId"/>
-
-        <find-by-and entity-name="PartyRelationship" map="lookupMap" list="partyRelationships"/>
-        <iterate list="partyRelationships" entry="partyRelationship">
-            <get-related-one value-field="partyRelationship" relation-name="ToParty" to-value-field="party"/>
-            <field-to-list field="party" list="parties"/>
-        </iterate>
-        <if-not-empty field="parties">
-            <field-to-result field="parties"/>
-        </if-not-empty>
-    </simple-method>
-
-    <simple-method method-name="getParentOrganizations" short-description="Gets Parent Organizations for an Organization Party">
-        <set from-field="parameters.organizationPartyId" field="relatedPartyIdList[]"/>
-        <set from-field="parameters.getParentsOfParents" field="recurse"/>
-        <if-empty field="recurse"><set value="Y" field="recurse"/></if-empty>
-
-        <set value="GROUP_ROLLUP" field="partyRelationshipTypeId"/>
-        <set value="ORGANIZATION_UNIT" field="roleTypeIdFrom"/>
-        <set value="PARENT_ORGANIZATION" field="roleTypeIdTo"/>
-        <set value="Y" field="roleTypeIdFromInclueAllChildTypes"/>
-
-        <set value="Y" field="includeFromToSwitched"/>
-        <set value="true" field="useCache"/>
-
-        <call-simple-method method-name="followPartyRelationshipsInline"/>
-
-        <field-to-result field="relatedPartyIdList" result-name="parentOrganizationPartyIdList"/>
-    </simple-method>
-
-    <simple-method method-name="getRelatedParties" short-description="Get Parties Related to a Party">
-        <set from-field="parameters.partyIdFrom" field="relatedPartyIdList[]"/>
-        <set from-field="parameters.partyRelationshipTypeId" field="partyRelationshipTypeId"/>
-        <set from-field="parameters.roleTypeIdFrom" field="roleTypeIdFrom"/>
-        <set from-field="parameters.roleTypeIdFromInclueAllChildTypes" field="roleTypeIdFromInclueAllChildTypes"/>
-        <set from-field="parameters.roleTypeIdTo" field="roleTypeIdTo"/>
-        <set from-field="parameters.roleTypeIdToIncludeAllChildTypes" field="roleTypeIdToIncludeAllChildTypes"/>
-        <set from-field="parameters.includeFromToSwitched" field="includeFromToSwitched"/>
-        <set from-field="parameters.recurse" field="recurse"/>
-        <set from-field="parameters.useCache" field="useCache"/>
-
-        <call-simple-method method-name="followPartyRelationshipsInline"/>
-
-        <field-to-result field="relatedPartyIdList"/>
-    </simple-method>
-
-    <simple-method method-name="followPartyRelationshipsInline" short-description="followPartyRelationshipsInline">
-        <!--
-            Uses the following fields in the env (with * are required):
-             - relatedPartyIdList* (initial partyIdFrom should be in this list; accumulator of new partyIds, ie all partyIdTo found will be added to this, thus can support recursion)
-             - partyRelationshipTypeId
-             - roleTypeIdFrom
-             - roleTypeIdFromInclueAllChildTypes
-             - roleTypeIdTo
-             - roleTypeIdToIncludeAllChildTypes
-             - includeFromToSwitched
-             - recurse
-             - useCache (should be "true" or "false")
-        -->
-
-        <if-empty field="nowTimestamp"><now-timestamp field="nowTimestamp"/></if-empty>
-
-        <!-- only create these if they don't already exist, more efficient and avoids potential problems in recursed calls -->
-        <if-empty field="_inline_roleTypeIdFromList">
-            <field-to-list field="roleTypeIdFrom" list="_inline_roleTypeIdFromList"/>
-            <if-compare field="roleTypeIdFromInclueAllChildTypes" operator="equals" value="Y">
-                <set value="_inline_roleTypeIdFromList" field="roleTypeIdListName"/>
-                <call-simple-method method-name="getChildRoleTypesInline"/>
-            </if-compare>
-        </if-empty>
-        <if-empty field="_inline_roleTypeIdToList">
-            <field-to-list field="roleTypeIdTo" list="_inline_roleTypeIdToList"/>
-            <if-compare field="roleTypeIdToInclueAllChildTypes" operator="equals" value="Y">
-                <set value="_inline_roleTypeIdToList" field="roleTypeIdListName"/>
-                <call-simple-method method-name="getChildRoleTypesInline"/>
-            </if-compare>
-        </if-empty>
-
-        <call-simple-method method-name="followPartyRelationshipsInlineRecurse"/>
-    </simple-method>
-    <simple-method method-name="followPartyRelationshipsInlineRecurse" short-description="followPartyRelationshipsInlineRecurse">
-        <clear-field field="_inline_NewRelatedPartyIdList"/>
-
-        <iterate list="relatedPartyIdList" entry="relatedPartyId">
-            <if>
-                <condition><not><if-compare-field field="_inline_relatedPartyIdAlreadySearchedList" to-field="relatedPartyId" operator="contains"/></not></condition>
-                <then>
-                    <field-to-list field="relatedPartyId" list="_inline_relatedPartyIdAlreadySearchedList"/>
-
-                    <clear-field field="_inline_PartyRelationshipList"/>
-                    <entity-condition entity-name="PartyRelationship" list="_inline_PartyRelationshipList" use-cache="${useCache}">
-                        <condition-list combine="and">
-                            <condition-expr field-name="partyIdFrom" from-field="relatedPartyId"/>
-                            <condition-expr field-name="roleTypeIdFrom" operator="in" from-field="_inline_roleTypeIdFromList" ignore-if-empty="true"/>
-                            <condition-expr field-name="roleTypeIdTo" operator="in" from-field="_inline_roleTypeIdToList" ignore-if-empty="true"/>
-                            <condition-expr field-name="partyRelationshipTypeId" from-field="partyRelationshipTypeId" ignore-if-empty="true"/>
-
-                            <condition-expr field-name="fromDate" operator="less-equals" from-field="nowTimestamp"/>
-                            <condition-list combine="or">
-                                <condition-expr field-name="thruDate" operator="equals" from-field="nullField"/>
-                                <condition-expr field-name="thruDate" operator="greater" from-field="nowTimestamp"/>
-                            </condition-list>
-                        </condition-list>
-
-                        <!-- get the newest (highest date) first -->
-                        <order-by field-name="-fromDate"/>
-                    </entity-condition>
-                    <iterate list="_inline_PartyRelationshipList" entry="_inline_PartyRelationship">
-                        <if>
-                            <condition>
-                                <and>
-                                    <not><if-compare-field field="relatedPartyIdList" to-field="_inline_PartyRelationship.partyIdTo" operator="contains"/></not>
-                                    <not><if-compare-field field="_inline_NewRelatedPartyIdList" to-field="_inline_PartyRelationship.partyIdTo" operator="contains"/></not>
-                                </and>
-                            </condition>
-                            <then>
-                                <field-to-list field="_inline_PartyRelationship.partyIdTo" list="_inline_NewRelatedPartyIdList"/>
-                            </then>
-                        </if>
-                    </iterate>
-
-                    <if-compare field="includeFromToSwitched" operator="equals" value="Y">
-                        <clear-field field="_inline_PartyRelationshipList"/>
-                        <entity-condition entity-name="PartyRelationship" list="_inline_PartyRelationshipList" use-cache="${useCache}">
-                            <condition-list combine="and">
-                                <condition-expr field-name="partyIdTo" from-field="relatedPartyId"/>
-                                <condition-expr field-name="roleTypeIdTo" operator="in" from-field="_inline_roleTypeIdFromList" ignore-if-empty="true"/>
-                                <condition-expr field-name="roleTypeIdFrom" operator="in" from-field="_inline_roleTypeIdToList" ignore-if-empty="true"/>
-                                <condition-expr field-name="partyRelationshipTypeId" from-field="partyRelationshipTypeId" ignore-if-empty="true"/>
-
-                                <condition-expr field-name="fromDate" operator="less-equals" from-field="nowTimestamp"/>
-                                <condition-list combine="or">
-                                    <condition-expr field-name="thruDate" operator="equals" from-field="nullField"/>
-                                    <condition-expr field-name="thruDate" operator="greater" from-field="nowTimestamp"/>
-                                </condition-list>
-                            </condition-list>
-
-                            <!-- get the newest (highest date) first -->
-                            <order-by field-name="-fromDate"/>
-                        </entity-condition>
-                        <iterate list="_inline_PartyRelationshipList" entry="_inline_PartyRelationship">
-                            <if>
-                                <condition>
-                                    <and>
-                                        <not><if-compare-field field="relatedPartyIdList" to-field="_inline_PartyRelationship.partyIdFrom" operator="contains"/></not>
-                                        <not><if-compare-field field="_inline_NewRelatedPartyIdList" to-field="_inline_PartyRelationship.partyIdFrom" operator="contains"/></not>
-                                    </and>
-                                </condition>
-                                <then>
-                                    <field-to-list field="_inline_PartyRelationship.partyIdFrom" list="_inline_NewRelatedPartyIdList"/>
-                                </then>
-                            </if>
-                        </iterate>
-                    </if-compare>
-                </then>
-            </if>
-        </iterate>
-
-        <!-- if we found new ones, add them to the master list and if recurse=Y then recurse -->
-        <if-not-empty field="_inline_NewRelatedPartyIdList">
-            <list-to-list list="_inline_NewRelatedPartyIdList" to-list="relatedPartyIdList"/>
-            <if-compare field="recurse" operator="equals" value="Y">
-                <log level="verbose" message="Recursively calling followPartyRelationshipsInlineRecurse _inline_NewRelatedPartyIdList=${_inline_NewRelatedPartyIdList}"/>
-                <call-simple-method method-name="followPartyRelationshipsInlineRecurse"/>
-            </if-compare>
-        </if-not-empty>
-    </simple-method>
-
-    <simple-method method-name="getChildRoleTypes" short-description="Get Child RoleTypes">
-        <field-to-list field="roleTypeId" list="childRoleTypeIdList"/>
-        <set value="childRoleTypeIdList" field="roleTypeIdListName"/>
-        <call-simple-method method-name="getChildRoleTypesInline"/>
-        <field-to-result field="childRoleTypeIdList"/>
-    </simple-method>
-    <simple-method method-name="getChildRoleTypesInline" short-description="getChildRoleTypes">
-        <clear-field field="_inline_NewRoleTypeIdList"/>
-
-        <iterate list="${roleTypeIdListName}" entry="roleTypeId">
-            <if>
-                <condition><not><if-compare-field field="_inline_roleTypeIdAlreadySearchedList" to-field="roleTypeId" operator="contains"/></not></condition>
-                <then>
-                    <field-to-list field="roleTypeId" list="_inline_roleTypeIdAlreadySearchedList"/>
-
-                    <clear-field field="_inline_RoleTypeList"/>
-                    <entity-condition entity-name="RoleType" list="_inline_RoleTypeList" use-cache="true">
-                        <condition-expr field-name="parentTypeId" operator="equals" from-field="roleTypeId"/>
-                    </entity-condition>
-                    <iterate list="_inline_RoleTypeList" entry="newRoleType">
-                        <if>
-                            <condition>
-                                <and>
-                                    <not><if-compare-field field="${roleTypeIdListName}" to-field="newRoleType.roleTypeId" operator="contains"/></not>
-                                    <not><if-compare-field field="_inline_NewRoleTypeIdList" to-field="newRoleType.roleTypeId" operator="contains"/></not>
-                                </and>
-                            </condition>
-                            <then>
-                                <field-to-list field="newRoleType.roleTypeId" list="_inline_NewRoleTypeIdList"/>
-                            </then>
-                        </if>
-                    </iterate>
-                </then>
-            </if>
-        </iterate>
-
-        <!-- if we found some new types, add them to the main list -->
-        <if-not-empty field="_inline_NewRoleTypeIdList">
-            <list-to-list list="_inline_NewRoleTypeIdList" to-list="${roleTypeIdListName}"/>
-            <log level="verbose" message="Recursively calling getChildRoleTypesInline roleTypeIdListName=${roleTypeIdListName}, _inline_NewRoleTypeIdList=${_inline_NewRoleTypeIdList}"/>
-            <call-simple-method method-name="getChildRoleTypesInline"/>
-        </if-not-empty>
-    </simple-method>
-
-    <simple-method method-name="getPartyEmail" short-description="Get the email of the party">
-        <!-- first try to find primary email Address when not found get other email -->
-        <entity-and entity-name="PartyContactWithPurpose" list="emailAddressesPurposes">
-            <field-map field-name="partyId" from-field="parameters.partyId"/>
-            <field-map field-name="contactMechPurposeTypeId" from-field="parameters.contactMechPurposeTypeId"/>
-        </entity-and>
-        <filter-list-by-date list="emailAddressesPurposes" to-list="emailAddressesPurposes1" from-field-name="purposeFromDate" thru-field-name="purposeThruDate"/>
-        <filter-list-by-date list="emailAddressesPurposes1" to-list="emailAddresses" from-field-name="contactFromDate" thru-field-name="contactThruDate"/>
-        <!-- any other email -->
-        <if-empty field="emailAddresses">
-            <entity-and entity-name="PartyAndContactMech" list="emailAddresses" filter-by-date="true">
-                <field-map field-name="partyId" from-field="parameters.partyId"/>
-                <field-map field-name="contactMechTypeId" value="EMAIL_ADDRESS"/>
-            </entity-and>
-        </if-empty> 
-        <!-- any other electronic address -->
-        <if-empty field="emailAddresses">
-            <entity-and entity-name="PartyAndContactMech" list="emailAddresses" filter-by-date="true">
-                <field-map field-name="partyId" from-field="parameters.partyId"/>
-                <field-map field-name="contactMechTypeId" value="ELECTRONIC_ADDRESS"/>
-            </entity-and>
-        </if-empty>
-        <if-not-empty field="emailAddresses">
-            <first-from-list list="emailAddresses" entry="emailAddress"/>
-            <field-to-result field="emailAddress.infoString" result-name="emailAddress"/>
-            <field-to-result field="emailAddress.contactMechId" result-name="contactMechId"/>
-        </if-not-empty>
-    </simple-method>
-
-    <simple-method method-name="getPartyTelephone" short-description="Get the telephone number of the party">
-        <set field="findMap.partyId" from-field="parameters.partyId"/>
-        <if-empty field="parameters.contactMechPurposeTypeId">
-            <!-- search in this order if not provided-->
-            <set field="type" value="PRIMARY_PHONE"/><field-to-list field="type" list="types"/>
-            <set field="type" value="PHONE_MOBILE"/><field-to-list field="type" list="types"/>
-            <set field="type" value="PHONE_WORK"/><field-to-list field="type" list="types"/>
-            <set field="type" value="PHONE_QUICK"/><field-to-list field="type" list="types"/>
-            <set field="type" value="PHONE_HOME"/><field-to-list field="type" list="types"/>
-            <set field="type" value="PHONE_BILLING"/><field-to-list field="type" list="types"/>
-            <set field="type" value="PHONE_SHIPPING"/><field-to-list field="type" list="types"/>
-            <set field="type" value="PHONE_SHIP_ORIG"/><field-to-list field="type" list="types"/>
-            <else>
-                <set field="type" from-field="parameters.contactMechPurposeTypeId"/>
-                <field-to-list field="type" list="types"/>
-            </else>
-        </if-empty>
-        <set field="findMap.contactMechTypeId" value="TELECOM_NUMBER"/>
-        <find-by-and entity-name="PartyContactDetailByPurpose" map="findMap" list="telephoneAll1"/>
-        <filter-list-by-date list="telephoneAll1" to-list="telephoneAll2" from-field-name="purposeFromDate" thru-field-name="purposeThruDate"/>
-        <filter-list-by-date list="telephoneAll2" to-list="telephoneAll3"/>
-        <if-not-empty field="telephoneAll3">
-            <iterate list="types" entry="type">
-                <iterate list="telephoneAll3" entry="telephone">
-                    <if-empty field="found">
-                        <if-compare-field field="telephone.contactMechPurposeTypeId" to-field="type" operator="equals">
-                            <set field="found" value="notImportant"/>
-                            <field-to-result field="telephone.contactMechId" result-name="contactMechId"/>
-                            <if-not-empty field="telephone.countryCode">
-                                <field-to-result field="telephone.countryCode" result-name="countryCode"/>
-                            </if-not-empty>
-                            <if-not-empty field="telephone.areaCode">
-                                <field-to-result field="telephone.areaCode" result-name="areaCode"/>
-                            </if-not-empty>
-                            <if-not-empty field="telephone.contactNumber">
-                                <field-to-result field="telephone.contactNumber" result-name="contactNumber"/>
-                            </if-not-empty>
-                            <if-not-empty field="telephone.extension">
-                                <field-to-result field="telephone.extension" result-name="extension"/>
-                            </if-not-empty>
-                            <field-to-result field="telephone.contactMechPurposeTypeId" result-name="contactMechPurposeTypeId"/>
-                        </if-compare-field>
-                    </if-empty>
-                </iterate>
-            </iterate>
-            <else>
-                <find-by-and entity-name="PartyAndContactMech" map="findMap" list="telephoneAll1"/>
-                <filter-list-by-date list="telephoneAll1" to-list="telephoneAll2"/>
-                <first-from-list list="telephoneAll2" entry="telephone"/>
-                <field-to-result field="telephone.contactMechId" result-name="contactMechId"/>
-                <if-not-empty field="telephone.tnCountryCode">
-                    <field-to-result field="telephone.tnCountryCode" result-name="countryCode"/>
-                </if-not-empty>
-                <if-not-empty field="telephone.tnAreaCode">
-                    <field-to-result field="telephone.tnAreaCode" result-name="areaCode"/>
-                </if-not-empty>
-                <if-not-empty field="telephone.tnContactNumber">
-                    <field-to-result field="telephone.tnContactNumber" result-name="contactNumber"/>
-                </if-not-empty>
-                <if-not-empty field="telephone.extension">
-                    <field-to-result field="telephone.extension" result-name="extension"/>
-                </if-not-empty>
-            </else>
-        </if-not-empty>
-    </simple-method>
-
-    <simple-method method-name="getPartyPostalAddress" short-description="Get the postal address of the party">
-        <set field="findMap.partyId" from-field="parameters.partyId"/>
-        <if-empty field="parameters.contactMechPurposeTypeId">
-                <!-- search in this order if not provided-->
-                <set field="type" value="GENERAL_LOCATION"/><field-to-list field="type" list="types"/>
-                <set field="type" value="BILLING_LOCATION"/><field-to-list field="type" list="types"/>
-                <set field="type" value="PAYMENT_LOCATION"/><field-to-list field="type" list="types"/>
-                <set field="type" value="SHIPPING_LOCATION"/><field-to-list field="type" list="types"/>
-                <else>
-                    <set field="type" from-field="parameters.contactMechPurposeTypeId"/><field-to-list field="type" list="types"/>
-                </else>
-        </if-empty>
-        <set field="findMap.contactMechTypeId" value="POSTAL_ADDRESS"/>
-        <find-by-and entity-name="PartyContactDetailByPurpose" map="findMap" list="addressAll1"></find-by-and>
-        <filter-list-by-date list="addressAll1" to-list="addressAll2" from-field-name="purposeFromDate" thru-field-name="purposeThruDate"/>
-        <filter-list-by-date list="addressAll2" to-list="addressAll3"/>
-        <if-not-empty field="addressAll3">
-            <iterate list="types" entry="type">
-                <iterate list="addressAll3" entry="address">
-                    <if-empty field="found">
-                        <if-compare-field field="address.contactMechPurposeTypeId" to-field="type" operator="equals">
-                            <set field="found" value="notImportant"/>
-                            <field-to-result field="address.contactMechId" result-name="contactMechId"/>
-                            <if-not-empty field="address.address1">
-                                <field-to-result field="address.address1" result-name="address1"/>
-                            </if-not-empty>
-                            <if-not-empty field="address.address2">
-                                <field-to-result field="address.address2" result-name="address2"/>
-                            </if-not-empty>
-                            <if-not-empty field="address.directions">
-                                <field-to-result field="address.directions" result-name="directions"/>
-                            </if-not-empty>
-                            <if-not-empty field="address.city">
-                                <field-to-result field="address.city" result-name="city"/>
-                            </if-not-empty>
-                            <if-not-empty field="address.postalCode">
-                                <field-to-result field="address.postalCode" result-name="postalCode"/>
-                            </if-not-empty>
-                            <if-not-empty field="address.stateProvinceGeoId">
-                                <field-to-result field="address.stateProvinceGeoId" result-name="stateProvinceGeoId"/>
-                            </if-not-empty>
-                            <if-not-empty field="address.countyGeoId">
-                                <field-to-result field="address.countyGeoId" result-name="countyGeoId"/>
-                            </if-not-empty>
-                            <if-not-empty field="address.countryGeoId">
-                                <field-to-result field="address.countryGeoId" result-name="countryGeoId"/>
-                            </if-not-empty>
-                            <field-to-result field="address.contactMechPurposeTypeId" result-name="contactMechPurposeTypeId"/>
-                        </if-compare-field>
-                    </if-empty>
-                </iterate>
-            </iterate>
-            <else>
-                <find-by-and entity-name="PartyAndContactMech" map="findMap" list="addressAll1"/>
-                <filter-list-by-date list="addressAll1" to-list="addressAll2"/>
-                <first-from-list list="addressAll2" entry="address"/>
-                      <field-to-result field="address.contactMechId" result-name="contactMechId"/>
-                      <if-not-empty field="address.paAddress1">
-                          <field-to-result field="address.paAddress1" result-name="address1"/>
-                      </if-not-empty>
-                      <if-not-empty field="address.paAddress2">
-                          <field-to-result field="address.paAddress2" result-name="address2"/>
-                      </if-not-empty>
-                      <if-not-empty field="address.paDirections">
-                          <field-to-result field="address.paDirections" result-name="directions"/>
-                      </if-not-empty>
-                      <if-not-empty field="address.paCity">
-                          <field-to-result field="address.paCity" result-name="city"/>
-                      </if-not-empty>
-                      <if-not-empty field="address.paPostalCode">
-                          <field-to-result field="address.paPostalCode" result-name="postalCode"/>
-                      </if-not-empty>
-                      <if-not-empty field="address.paStateProvinceGeoId">
-                          <field-to-result field="address.paStateProvinceGeoId" result-name="stateProvinceGeoId"/>
-                      </if-not-empty>
-                      <if-not-empty field="address.paCountyGeoId">
-                          <field-to-result field="address.paCountyGeoId" result-name="countyGeoId"/>
-                      </if-not-empty>
-                      <if-not-empty field="address.paCountryGeoId">
-                          <field-to-result field="address.paCountryGeoId" result-name="countryGeoId"/>
-                      </if-not-empty>
-            </else>
-        </if-not-empty>
-    </simple-method>
-
-    <!-- address match map -->
-    <simple-method method-name="createAddressMatchMap" short-description="create a AddressMatchMap">
-        <call-object-method obj-field="parameters.mapValue" method-name="toUpperCase" ret-field="parameters.mapValue"/>
-        <call-object-method obj-field="parameters.mapKey" method-name="toUpperCase" ret-field="parameters.mapKey"/>
-        <make-value entity-name="AddressMatchMap" value-field="newEntity"/>
-        <set-pk-fields map="parameters" value-field="newEntity"/>
-        <set-nonpk-fields map="parameters" value-field="newEntity"/>
-        <create-value value-field="newEntity"/>
-    </simple-method>
-    <simple-method method-name="clearAddressMatchMap" short-description="remove all AddressMatchMap">
-        <entity-condition entity-name="AddressMatchMap" list="addrs">
-            <use-iterator/>
-        </entity-condition>
-        <iterate list="addrs" entry="addr">
-            <remove-value value-field="addr"/>
-        </iterate>
-    </simple-method>
-
-    <!-- PartyRelationship services -->
-    <simple-method method-name="createPartyRelationship" short-description="createPartyRelationship">
-        <if-empty field="parameters.roleTypeIdFrom"><set field="parameters.roleTypeIdFrom" value="_NA_"/></if-empty>
-        <if-empty field="parameters.roleTypeIdTo"><set field="parameters.roleTypeIdTo" value="_NA_"/></if-empty>
-        <if-empty field="parameters.partyIdFrom"><set field="parameters.partyIdFrom" from-field="userLogin.partyId"/></if-empty>
-
-        <if-empty field="parameters.fromDate"><now-timestamp field="parameters.fromDate"/></if-empty>
-
-        <!-- check if not already exist -->
-        <entity-and entity-name="PartyRelationship" list="partyRels" filter-by-date="true">
-            <field-map field-name="partyIdFrom" from-field="parameters.partyIdFrom"/>
-            <field-map field-name="roleTypeIdFrom" from-field="parameters.roleTypeIdFrom"/>
-            <field-map field-name="partyIdTo" from-field="parameters.partyIdTo"/>
-            <field-map field-name="roleTypeIdTo" from-field="parameters.roleTypeIdTo"/>
-        </entity-and>
-
-        <if-empty field="partyRels">
-            <make-value entity-name="PartyRelationship" value-field="newEntity"/>
-            <set-pk-fields map="parameters" value-field="newEntity"/>
-            <set-nonpk-fields map="parameters" value-field="newEntity"/>
-            <create-value value-field="newEntity"/>
-        </if-empty>
-    </simple-method>
-    <simple-method method-name="updatePartyRelationship" short-description="updatePartyRelationship">
-        <if-empty field="parameters.roleTypeIdFrom"><set field="parameters.roleTypeIdFrom" value="_NA_"/></if-empty>
-        <if-empty field="parameters.roleTypeIdTo"><set field="parameters.roleTypeIdTo" value="_NA_"/></if-empty>
-
-        <entity-one entity-name="PartyRelationship" value-field="lookedUpValue"/>
-        <set-nonpk-fields map="parameters" value-field="lookedUpValue"/>
-        <store-value value-field="lookedUpValue"/>
-    </simple-method>
-    <simple-method method-name="deletePartyRelationship" short-description="deletePartyRelationship">
-        <if-empty field="parameters.roleTypeIdFrom"><set field="parameters.roleTypeIdFrom" value="_NA_"/></if-empty>
-        <if-empty field="parameters.roleTypeIdTo"><set field="parameters.roleTypeIdTo" value="_NA_"/></if-empty>
-
-        <entity-one entity-name="PartyRelationship" value-field="lookedUpValue"/>
-        <remove-value value-field="lookedUpValue"/>
-    </simple-method>
-
-    <simple-method method-name="createPartyRelationshipContactAccount" short-description="create a company/contact relationship and add the related roles">
-        <set field="roleMap.partyId" from-field="parameters.accountPartyId"/>
-        <set field="roleMap.roleTypeId" value="ACCOUNT"/>
-        <entity-one entity-name="PartyRole" value-field="partyRole">
-            <field-map field-name="partyId" from-field="roleMap.partyId"/>
-            <field-map field-name="roleTypeId" from-field="roleMap.roleTypeId"/>
-        </entity-one>
-        <if-empty field="partyRole">
-            <call-service service-name="createPartyRole" in-map-name="roleMap"/>
-        </if-empty>
-        <set field="roleMap.partyId" from-field="parameters.contactPartyId"/>
-        <set field="roleMap.roleTypeId" value="CONTACT"/>
-        <entity-one entity-name="PartyRole" value-field="partyRole">
-            <field-map field-name="partyId" from-field="roleMap.partyId"/>
-            <field-map field-name="roleTypeId" from-field="roleMap.roleTypeId"/>
-        </entity-one>
-        <if-empty field="partyRole">
-            <call-service service-name="createPartyRole" in-map-name="roleMap"/>
-        </if-empty>
-        <set field="relMap.partyIdFrom" from-field="parameters.accountPartyId"/>
-        <set field="relMap.roleTypeIdFrom" value="ACCOUNT"/>
-        <set field="relMap.partyIdTo" from-field="parameters.contactPartyId"/>
-        <set field="relMap.roleTypeIdTo" value="CONTACT"/>
-        <set field="relMap.partyRelationshipTypeId" value="EMPLOYMENT"/>
-        <set field="relMap.comments" from-field="parameters.comments"/> 
-        <call-service service-name="createPartyRelationship" in-map-name="relMap"/>
-    </simple-method>
-
-    <!-- send party creation email notification -->
-    <simple-method method-name="sendCreatePartyEmailNotification" short-description="Notification email on party creation" login-required="false">
-        <map-to-map map="parameters" to-map="bodyParameters"/>
-        <set field="emailType" value="PARTY_REGIS_CONFIRM"/>
-        <set field="productStoreId" from-field="parameters.productStoreId" />
-        <if-empty field="productStoreId">
-            <log level="warning" message="No productStoreId specified."/>
-        </if-empty>
-        <entity-one entity-name="ProductStoreEmailSetting" value-field="storeEmail">
-            <field-map field-name="emailType"/>
-            <field-map field-name="productStoreId"/>
-        </entity-one>
-        <entity-and entity-name="WebSite" list="webSites">
-            <field-map field-name="productStoreId" from-field="storeEmail.productStoreId"/>
-        </entity-and>
-        <first-from-list list="webSites" entry="webSite"/>
-        <if-not-empty field="storeEmail.bodyScreenLocation">
-            <entity-one entity-name="Person" value-field="person"/>
-            <set field="bodyParameters.person" from-field="person"/>
-            <set field="emailParams.bodyParameters" from-field="bodyParameters"/>
-
-            <set field="emailParams.sendTo" from-field="parameters.emailAddress"/>
-            <set field="emailParams.subject" from-field="storeEmail.subject"/>
-            <set field="emailParams.sendFrom" from-field="storeEmail.fromAddress"/>
-            <set field="emailParams.sendCc" from-field="storeEmail.ccAddress"/>
-            <set field="emailParams.sendBcc" from-field="storeEmail.bccAddress"/>
-            <set field="emailParams.contentType" from-field="storeEmail.contentType"/>
-            <set field="emailParams.bodyScreenUri" from-field="storeEmail.bodyScreenLocation"/>
-            <set field="emailParams.webSiteId" from-field="webSite.webSiteId"/>
-            <set field="emailParams.emailType" from-field="emailType"/>
-            <call-service service-name="sendMailFromScreen" in-map-name="emailParams"/>
-        </if-not-empty>
-    </simple-method>
-
-    <!-- send personal information update email notification -->
-    <simple-method method-name="sendUpdatePersonalInfoEmailNotification" short-description="Send the Notification email on personal information updation" login-required="false">
-        <map-to-map map="parameters" to-map="bodyParameters"/>
-        <set field="productStoreId" from-field="parameters.productStoreId" />
-        <if-empty field="productStoreId">
-            <log level="warning" message="No productStoreId specified."/>
-        </if-empty>
-        <entity-one entity-name="ProductStoreEmailSetting" value-field="storeEmail">
-            <field-map field-name="emailType" value="UPD_PRSNL_INF_CNFRM"/>
-            <field-map field-name="productStoreId"/>
-        </entity-one>
-        <entity-and entity-name="WebSite" list="webSites">
-            <field-map field-name="productStoreId" from-field="storeEmail.productStoreId"/>
-        </entity-and>
-        <first-from-list list="webSites" entry="webSite"/>
-        <if-not-empty field="storeEmail.bodyScreenLocation">
-            <if-not-empty field="parameters.updatedUserLogin.partyId">
-                <set field="partyId" from-field="parameters.updatedUserLogin.partyId"/>
-            <else>
-                <set field="partyId" from-field="parameters.partyId"/>
-            </else>
-            </if-not-empty>
-            <entity-condition entity-name="PartyContactDetailByPurpose" list="partyContactDetailByPurposes" filter-by-date="true">
-                <condition-list>
-                    <condition-expr field-name="contactMechPurposeTypeId" operator="equals" value="PRIMARY_EMAIL"/>
-                    <condition-expr field-name="partyId" operator="equals"  from-field="partyId"/>
-                </condition-list>
-            </entity-condition>
-            <first-from-list list="partyContactDetailByPurposes" entry="partyContactDetailByPurpose"/>
-            <entity-one entity-name="PartyAndPerson" value-field="partyAndPerson"/>
-            <set field="bodyParameters.partyAndPerson" from-field="partyAndPerson"/>
-            <set field="contactMechId" from-field="partyContactDetailByPurpose.contactMechId"/>
-            <entity-one entity-name="ContactMech" value-field="contactMech"/>
-            <set field="emailParams.sendTo" from-field="contactMech.infoString"/>
-            <set field="emailParams.subject" from-field="storeEmail.subject"/>
-            <set field="emailParams.sendFrom" from-field="storeEmail.fromAddress"/>
-            <set field="emailParams.sendCc" from-field="storeEmail.ccAddress"/>
-            <set field="emailParams.sendBcc" from-field="storeEmail.bccAddress"/>
-            <set field="emailParams.contentType" from-field="storeEmail.contentType"/>
-            <set field="emailParams.bodyParameters" from-field="bodyParameters"/>
-            <set field="emailParams.bodyScreenUri" from-field="storeEmail.bodyScreenLocation"/>
-            <set field="emailParams.webSiteId" from-field="webSite.webSiteId"/>
-
-            <if-not-empty field="emailParams.sendTo">
-                <call-service service-name="sendMailFromScreen" in-map-name="emailParams"/>
-                <else>
-                    <log level="warning" message="Tried to send Update Personal Info Notifcation with no to address; partyId is [${partyId}], subject is: ${emailParams.subject}"/>
-                </else>
-            </if-not-empty>
-        </if-not-empty>
-    </simple-method>
-
-    <simple-method method-name="createUpdatePerson" short-description="Create and update a person" login-required="false">
-        <call-map-processor xml-resource="component://party/minilang/party/PartyMapProcs.xml"
-                processor-name="person" in-map-name="parameters" out-map-name="personMap"/>
-        <check-errors/>
-        <set field="partyId" from-field="parameters.partyId"/>
-        <entity-one entity-name="Party" value-field="party"/>
-        <set field="personContext.partyId" from-field="partyId"/>
-        <set-service-fields service-name="createPerson" map="personMap" to-map="personContext"/>
-        <if-empty field="party">
-            <call-service service-name="createPerson" in-map-name="personContext">
-                <result-to-field result-name="partyId" field="partyId"/>
-            </call-service>
-        <else><!-- If party object already exist, update the person record. -->
-            <set field="personContext.userLogin" from-field="parameters.userLogin"/>
-            <call-service service-name="updatePerson" in-map-name="personContext"/>
-        </else>
-        </if-empty>
-        <field-to-result field="partyId"/>
-    </simple-method>
-
-    <simple-method method-name="quickCreateCustomer" short-description="Create customer profile on basis of First Name ,Last Name and Email Address" login-required="false">
-        <call-map-processor xml-resource="component://party/minilang/contact/PartyContactMechMapProcs.xml"
-                processor-name="person" in-map-name="parameters" out-map-name="personInMap"/>
-        <call-map-processor xml-resource="component://party/minilang/contact/PartyContactMechMapProcs.xml"
-                processor-name="emailAddress" in-map-name="parameters" out-map-name="emailAddressInMap"/>
-        <check-errors/>
-        
-        <!-- create person  -->
-        <call-service service-name="createPerson" in-map-name="personInMap">
-            <result-to-field result-name="partyId"/>
-            <result-to-result result-name="partyId"/>
-        </call-service>
-
-        <!-- Create email address -->
-        <entity-one entity-name="UserLogin" value-field="userLogin">
-            <field-map field-name="userLoginId" value="system"/>
-        </entity-one>
-        <set field="emailAddressInMap.partyId" from-field="partyId"/>
-        <set field="emailAddressInMap.userLogin" from-field="userLogin"/>
-        <set field="emailAddressInMap.contactMechPurposeTypeId" value="PRIMARY_EMAIL"/>
-        <call-service service-name="createPartyEmailAddress" in-map-name="emailAddressInMap"/>
-
-        <!-- Signup for Contact List -->
-        <if-compare field="parameters.subscribeContactList" operator="equals" value="Y">
-            <set field="signUpForContactListMap.partyId" from-field="partyId"/>
-            <set field="signUpForContactListMap.contactListId" from-field="parameters.contactListId"/>
-            <set field="signUpForContactListMap.email" from-field="parameters.emailAddress"/>
-            <call-service service-name="signUpForContactList" in-map-name="signUpForContactListMap"/>
-        </if-compare>
-
-        <!-- Create the PartyRole -->
-        <set field="createPartyRoleInMap.partyId" from-field="partyId"/>
-        <set field="createPartyRoleInMap.roleTypeId" value="CUSTOMER"/>
-        <set field="createPartyRoleInMap.userLogin" from-field="userLogin"/>
-        <call-service service-name="createPartyRole" in-map-name="createPartyRoleInMap"/>
-    </simple-method>
-
-    <simple-method method-name="getPartyMainRole"
-        short-description="Get the main role of this party which is a child of the MAIN_ROLE roletypeId">
-        <entity-and entity-name="PartyRole" list="partyRoles">
-            <field-map field-name="partyId" from-field="parameters.partyId" />
-        </entity-and>
-        <!-- find the role in the list -->
-        <clear-field field="mainRoleTypeId"/>
-        <iterate list="partyRoles" entry="partyRole">
-            <if-empty field="mainRoleTypeId">
-                <entity-and entity-name="RoleTypeIn3Levels" list="roleTypeIn3Levels">
-                    <field-map field-name="topRoleTypeId" value="MAIN_ROLE" />
-                    <field-map field-name="lowRoleTypeId" from-field="partyRole.roleTypeId" />
-                </entity-and>
-                <if-not-empty field="roleTypeIn3Levels">
-                    <set field="mainRoleTypeId" from-field="partyRole.roleTypeId" />
-                </if-not-empty>
-            </if-empty>
-        </iterate>
-        <if-not-empty field="mainRoleTypeId">
-            <field-to-result field="mainRoleTypeId" result-name="roleTypeId" />
-            <entity-one entity-name="RoleType" value-field="roleType">
-                <field-map field-name="roleTypeId" from-field="mainRoleTypeId" />
-            </entity-one>
-            <field-to-result field="roleType.description" result-name="description" />
-        </if-not-empty>
-    </simple-method>
-    
-    <!-- send account activated email notification -->
-    <simple-method method-name="sendAccountActivatedEmailNotification" short-description="Notification email on account activated" login-required="false">
-        <map-to-map map="parameters" to-map="bodyParameters"/>
-        <set field="emailType" value="PRDS_CUST_ACTIVATED"/>
-        <set field="productStoreId" from-field="parameters.productStoreId" />
-        <entity-one entity-name="ProductStoreEmailSetting" value-field="storeEmail">
-            <field-map field-name="emailType"/>
-            <field-map field-name="productStoreId"/>
-        </entity-one>
-        <entity-and entity-name="WebSite" list="webSites">
-            <field-map field-name="productStoreId" from-field="storeEmail.productStoreId"/>
-        </entity-and>
-        <first-from-list list="webSites" entry="webSite"/>
-        <if-not-empty field="storeEmail.bodyScreenLocation">
-            <entity-one entity-name="UserLogin" value-field="userLoginParty"/>
-            <set field="parameters.partyId" from-field="userLoginParty.partyId"/>
-            <entity-condition entity-name="PartyContactDetailByPurpose" list="partyContactDetailByPurposes" filter-by-date="true">
-                <condition-list>
-                    <condition-expr field-name="contactMechPurposeTypeId" operator="equals" value="PRIMARY_EMAIL"/>
-                    <condition-expr field-name="partyId" operator="equals"  from-field="parameters.partyId"/>
-                </condition-list>
-            </entity-condition>
-            <first-from-list list="partyContactDetailByPurposes" entry="partyContactDetailByPurpose"/>
-            <entity-one entity-name="Person" value-field="person"/>
-            <set field="bodyParameters.person" from-field="person"/>
-            <set field="emailParams.bodyParameters" from-field="bodyParameters"/>
-            <set field="contactMechId" from-field="partyContactDetailByPurpose.contactMechId"/>
-            <entity-one entity-name="ContactMech" value-field="contactMech"/>
-            <set field="emailParams.sendTo" from-field="contactMech.infoString"/>
-            <set field="emailParams.subject" from-field="storeEmail.subject"/>
-            <set field="emailParams.sendFrom" from-field="storeEmail.fromAddress"/>
-            <set field="emailParams.sendCc" from-field="storeEmail.ccAddress"/>
-            <set field="emailParams.sendBcc" from-field="storeEmail.bccAddress"/>
-            <set field="emailParams.contentType" from-field="storeEmail.contentType"/>
-            <set field="emailParams.bodyScreenUri" from-field="storeEmail.bodyScreenLocation"/>
-            <set field="emailParams.webSiteId" from-field="webSite.webSiteId"/>
-            <set field="emailParams.emailType" from-field="emailType"/>
-            <call-service service-name="sendMailFromScreen" in-map-name="emailParams"/>
-        </if-not-empty>
-    </simple-method>
-</simple-methods>
diff --git a/applications/party/servicedef/services.xml b/applications/party/servicedef/services.xml
index 22b8e9f..00b7109 100644
--- a/applications/party/servicedef/services.xml
+++ b/applications/party/servicedef/services.xml
@@ -25,8 +25,8 @@ under the License.
     <version>1.0</version>
 
     <!-- AddressMatchMap services -->
-    <service name="createAddressMatchMap" engine="simple" default-entity-name="AddressMatchMap" auth="true"
-            location="component://party/minilang/party/PartyServices.xml" invoke="createAddressMatchMap">
+    <service name="createAddressMatchMap" engine="groovy" default-entity-name="AddressMatchMap" auth="true"
+            location="component://party/groovyScripts/party/PartyServices.groovy" invoke="createAddressMatchMap">
         <description>Create an AddressMatchMap record</description>
         <permission-service service-name="partyBasePermissionCheck" main-action="CREATE"/>
         <auto-attributes mode="IN" include="pk" optional="false"/>
@@ -45,8 +45,8 @@ under the License.
         <permission-service service-name="partyBasePermissionCheck" main-action="DELETE"/>
         <auto-attributes mode="IN" include="pk" optional="false"/>
     </service>
-    <service name="clearAddressMatchMap" engine="simple" default-entity-name="AddressMatchMap" auth="true"
-            location="component://party/minilang/party/PartyServices.xml" invoke="clearAddressMatchMap">
+    <service name="clearAddressMatchMap" engine="groovy" default-entity-name="AddressMatchMap" auth="true"
+            location="component://party/groovyScripts/party/PartyServices.groovy" invoke="clearAddressMatchMap">
         <description>Delete an AddressMatchMap record</description>
         <permission-service service-name="partyBasePermissionCheck" main-action="DELETE"/>
     </service>
@@ -130,8 +130,8 @@ under the License.
         <override name="comments" allow-html="safe"/>
     </service>
 
-    <service name="savePartyNameChange" engine="simple"
-        location="component://party/minilang/party/PartyServices.xml" invoke="savePartyNameChange" auth="true">
+    <service name="savePartyNameChange" engine="groovy"
+        location="component://party/groovyScripts/party/PartyServices.groovy" invoke="savePartyNameChange" auth="true">
         <description>Save Party Name Change</description>
         <attribute name="partyId" type="String" mode="IN" optional="true"><!-- if empty, will use userLogin.partyId to handle special case for updatePerson, etc --></attribute>
         <attribute name="groupName" type="String" mode="IN" optional="true"/>
@@ -141,8 +141,8 @@ under the License.
         <attribute name="personalTitle" type="String" mode="IN" optional="true"/>
         <attribute name="suffix" type="String" mode="IN" optional="true"/>
     </service>
-    <service name="getPartyNameForDate" engine="simple"
-        location="component://party/minilang/party/PartyServices.xml" invoke="getPartyNameForDate" auth="true">
+    <service name="getPartyNameForDate" engine="groovy"
+        location="component://party/groovyScripts/party/PartyServices.groovy" invoke="getPartyNameForDate" auth="true">
         <description>Get Party Name For Date</description>
         <attribute name="partyId" type="String" mode="IN" optional="false"/>
         <attribute name="compareDate" type="Timestamp" mode="IN" optional="true"><!-- defaults to now --></attribute>
@@ -200,8 +200,8 @@ under the License.
         <attribute name="roleType" type="org.apache.ofbiz.entity.GenericValue" mode="OUT"/>
     </service>
 
-    <service name="setPartyProfileDefaults" engine="simple"
-            location="component://party/minilang/party/PartyServices.xml" invoke="setPartyProfileDefaults" auth="true">
+    <service name="setPartyProfileDefaults" engine="groovy"
+            location="component://party/groovyScripts/party/PartyServices.groovy" invoke="setPartyProfileDefaults" auth="true">
         <description>Sets the party (customer) profile defaults</description>
         <permission-service service-name="partyIdPermissionCheck" main-action="UPDATE"/>
         <auto-attributes mode="IN" entity-name="PartyProfileDefault" include="all" optional="true"/>
@@ -294,8 +294,8 @@ under the License.
     </service>
 
     <!-- Party Relationship services -->
-    <service name="createPartyRelationship" default-entity-name="PartyRelationship" engine="simple"
-        location="component://party/minilang/party/PartyServices.xml" invoke="createPartyRelationship" auth="true">
+    <service name="createPartyRelationship" default-entity-name="PartyRelationship" engine="groovy"
+        location="component://party/groovyScripts/party/PartyServices.groovy" invoke="createPartyRelationship" auth="true">
         <description>
             Create a Relationship between two Parties;
             if partyIdFrom is not specified the partyId of the current userLogin will be used;
@@ -307,8 +307,8 @@ under the License.
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
         <override name="partyIdTo" optional="false"/>
     </service>
-    <service name="updatePartyRelationship" default-entity-name="PartyRelationship" engine="simple"
-        location="component://party/minilang/party/PartyServices.xml" invoke="updatePartyRelationship" auth="true">
+    <service name="updatePartyRelationship" default-entity-name="PartyRelationship" engine="groovy"
+        location="component://party/groovyScripts/party/PartyServices.groovy" invoke="updatePartyRelationship" auth="true">
         <description>
             Update a Relationship between two Parties;
             if partyIdFrom is not specified the partyId of the current userLogin will be used;
@@ -322,8 +322,8 @@ under the License.
         <override name="roleTypeIdFrom" optional="true"/>
         <override name="roleTypeIdTo" optional="true"/>
     </service>
-    <service name="deletePartyRelationship" default-entity-name="PartyRelationship" engine="simple"
-        location="component://party/minilang/party/PartyServices.xml" invoke="deletePartyRelationship" auth="true">
+    <service name="deletePartyRelationship" default-entity-name="PartyRelationship" engine="groovy"
+        location="component://party/groovyScripts/party/PartyServices.groovy" invoke="deletePartyRelationship" auth="true">
         <description>
             Delete a Relationship between two Parties;
             if partyIdFrom is not specified the partyId of the current userLogin will be used;
@@ -367,8 +367,8 @@ under the License.
         <override name="fromDate" optional="true"/>
     </service>
 
-    <service name="createPartyRelationshipContactAccount" engine="simple"
-        location="component://party/minilang/party/PartyServices.xml" invoke="createPartyRelationshipContactAccount" auth="true">
+    <service name="createPartyRelationshipContactAccount" engine="groovy"
+        location="component://party/groovyScripts/party/PartyServices.groovy" invoke="createPartyRelationshipContactAccount" auth="true">
         <description>create a company/contact relationship and add the related roles</description>
         <attribute name="accountPartyId" type="String" mode="IN"/>
         <attribute name="contactPartyId" type="String" mode="IN"/>
@@ -636,8 +636,8 @@ under the License.
         <permission-service service-name="partyBasePermissionCheck" main-action="DELETE"/>
         <auto-attributes mode="IN" include="pk"/>
     </service>
-    <service name="createPartyIdentifications" engine="simple" default-entity-name="PartyIdentification"
-            location="component://party/minilang/party/PartyServices.xml" invoke="createPartyIdentifications">
+    <service name="createPartyIdentifications" engine="groovy" default-entity-name="PartyIdentification"
+            location="component://party/groovyScripts/party/PartyServices.groovy" invoke="createPartyIdentifications">
         <description>create many identifications with format in map identifications : [partyType : TYPE, TYPE : value]</description>
         <permission-service service-name="partyBasePermissionCheck" main-action="CREATE"/>
         <attribute name="partyId" mode="IN" type="String"/>
@@ -963,8 +963,8 @@ under the License.
         </group>
     </service>
 
-    <service name="getPartyEmail" engine="simple"
-        location="component://party/minilang/party/PartyServices.xml" invoke="getPartyEmail" auth="false">
+    <service name="getPartyEmail" engine="groovy"
+        location="component://party/groovyScripts/party/PartyServices.groovy" invoke="getPartyEmail" auth="false">
         <description>Get the main party Email address</description>
         <attribute name="partyId" type="String" mode="IN" optional="false"/>
         <attribute name="contactMechPurposeTypeId" type="String" mode="IN" optional="false" default-value="PRIMARY_EMAIL"/>
@@ -972,8 +972,8 @@ under the License.
         <attribute name="contactMechId" type="String" mode="OUT" optional="true"/>
     </service>
 
-    <service name="getPartyTelephone" engine="simple"
-        location="component://party/minilang/party/PartyServices.xml" invoke="getPartyTelephone" auth="false">
+    <service name="getPartyTelephone" engine="groovy"
+        location="component://party/groovyScripts/party/PartyServices.groovy" invoke="getPartyTelephone" auth="false">
         <description>Get the party Email Telephone</description>
         <attribute name="contactMechId" type="String" mode="OUT" optional="true"/>
         <attribute name="partyId" type="String" mode="IN" optional="false"/>
@@ -984,8 +984,8 @@ under the License.
         <attribute name="extension" type="String" mode="OUT" optional="true"/>
     </service>
 
-    <service name="getPartyPostalAddress" engine="simple"
-        location="component://party/minilang/party/PartyServices.xml" invoke="getPartyPostalAddress" auth="false">
+    <service name="getPartyPostalAddress" engine="groovy"
+        location="component://party/groovyScripts/party/PartyServices.groovy" invoke="getPartyPostalAddress" auth="false">
         <description>Get the party postal address</description>
         <attribute name="partyId" type="String" mode="IN" optional="false"/>
         <attribute name="contactMechPurposeTypeId" type="String" mode="INOUT" optional="true"/>
@@ -1014,14 +1014,14 @@ under the License.
         <auto-attributes mode="IN" include="nonpk" optional="true"/>
     </service>
 
-    <service name="sendUpdatePersonalInfoEmailNotification" engine="simple"
-            location="component://party/minilang/party/PartyServices.xml" invoke="sendUpdatePersonalInfoEmailNotification" auth="false">
+    <service name="sendUpdatePersonalInfoEmailNotification" engine="groovy"
+            location="component://party/groovyScripts/party/PartyServices.groovy" invoke="sendUpdatePersonalInfoEmailNotification" auth="false">
         <attribute name="partyId" type="String" mode="IN" optional="true"/>
         <attribute name="updatedUserLogin" type="org.apache.ofbiz.entity.GenericValue" mode="IN" optional="true"/>
         <attribute name="productStoreId" type="String" mode="IN" optional="true"/>
     </service>
-    <service name="sendCreatePartyEmailNotification" engine="simple"
-            location="component://party/minilang/party/PartyServices.xml" invoke="sendCreatePartyEmailNotification" auth="false">
+    <service name="sendCreatePartyEmailNotification" engine="groovy"
+            location="component://party/groovyScripts/party/PartyServices.groovy" invoke="sendCreatePartyEmailNotification" auth="false">
         <attribute name="partyId" type="String" mode="IN" optional="false"/>
         <attribute name="emailAddress" type="String" mode="IN" optional="false"/>
         <attribute name="productStoreId" type="String" mode="IN" optional="false"/>
@@ -1221,8 +1221,8 @@ under the License.
         <auto-attributes entity-name="TelecomNumber" include="nonpk" mode="IN" optional="true"/>
         <attribute name="phoneContactMechId" type="String" mode="IN" optional="true"/>
     </service>
-    <service name="createUpdatePerson" engine="simple" default-entity-name="Person"
-            location="component://party/minilang/party/PartyServices.xml" invoke="createUpdatePerson" auth="false">
+    <service name="createUpdatePerson" engine="groovy" default-entity-name="Person"
+            location="component://party/groovyScripts/party/PartyServices.groovy" invoke="createUpdatePerson" auth="false">
         <description>Create and Update a person</description>
         <auto-attributes mode="INOUT" include="pk" optional="true"/>
         <auto-attributes mode="IN" include="nonpk" optional="true"/>
@@ -1289,8 +1289,8 @@ under the License.
         <implements service="mailProcessInterface"/>
     </service>
 
-    <service name="quickCreateCustomer" engine="simple"
-            location="component://party/minilang/party/PartyServices.xml" invoke="quickCreateCustomer">
+    <service name="quickCreateCustomer" engine="groovy"
+            location="component://party/groovyScripts/party/PartyServices.groovy" invoke="quickCreateCustomer">
         <description>Create customer profile on basis of First Name ,Last Name and Email Address</description>
         <attribute name="firstName" type="String" mode="IN" optional="false"/>
         <attribute name="lastName" type="String" mode="IN" optional="false"/>
@@ -1300,8 +1300,8 @@ under the License.
         <attribute name="subscribeContactList" type="String" mode="IN" optional="true"/>
     </service>
 
-    <service name="getPartyMainRole" engine="simple"
-            location="component://party/minilang/party/PartyServices.xml" invoke="getPartyMainRole">
+    <service name="getPartyMainRole" engine="groovy"
+            location="component://party/groovyScripts/party/PartyServices.groovy" invoke="getPartyMainRole">
         <description>Get the main role of this party which is a child of the MAIN_ROLE roletypeId</description>
         <attribute name="partyId" type="String" mode="IN" optional="false"/>
         <attribute name="roleTypeId" type="String" mode="OUT" optional="true"/>
@@ -1327,8 +1327,8 @@ under the License.
     </service>
     
     <!-- send account activated email notification -->
-    <service name="sendAccountActivatedEmailNotification" engine="simple"
-            location="component://party/minilang/party/PartyServices.xml" invoke="sendAccountActivatedEmailNotification" auth="false">
+    <service name="sendAccountActivatedEmailNotification" engine="groovy"
+            location="component://party/groovyScripts/party/PartyServices.groovy" invoke="sendAccountActivatedEmailNotification" auth="false">
         <attribute name="userLoginId" type="String" mode="IN" optional="false"/>
         <attribute name="productStoreId" type="String" mode="IN" optional="false"/>
     </service>
diff --git a/applications/party/servicedef/services_view.xml b/applications/party/servicedef/services_view.xml
index d0d2793..8b8c05c 100644
--- a/applications/party/servicedef/services_view.xml
+++ b/applications/party/servicedef/services_view.xml
@@ -169,8 +169,8 @@ under the License.
         <attribute name="parties" type="java.util.List" mode="OUT" optional="true"/>
     </service>
     
-    <service name="getPartiesByRelationship" engine="simple"
-        location="component://party/minilang/party/PartyServices.xml" invoke="getPartiesByRelationship">
+    <service name="getPartiesByRelationship" engine="groovy"
+        location="component://party/groovyScripts/party/PartyServices.groovy" invoke="getPartiesByRelationship">
         <description>Gets all parties related to partyIdFrom through the PartyRelationship entity</description>
         <auto-attributes mode="IN" include="all" optional="true" entity-name="PartyRelationship"/>
         <attribute name="parties" type="java.util.Collection" mode="OUT" optional="true"/>
@@ -196,8 +196,8 @@ under the License.
         <attribute name="relatedPartyIdList" type="List" mode="OUT" optional="false"/>
     </service>
 
-    <service name="getParentOrganizations" engine="simple"
-            location="component://party/minilang/party/PartyServices.xml" invoke="getParentOrganizations">
+    <service name="getParentOrganizations" engine="groovy"
+            location="component://party/groovyScripts/party/PartyServices.groovy" invoke="getParentOrganizations">
         <description>
             Gets Parent Organizations for an Organization Party.
             This uses the PartyRelationship table with partyRelationshipTypeId="GROUP_ROLLUP".
@@ -211,8 +211,8 @@ under the License.
         <attribute name="parentOrganizationPartyIdList" type="List" mode="OUT" optional="false"/>
     </service>
 
-    <service name="getChildRoleTypes" engine="simple"
-            location="component://party/minilang/party/PartyServices.xml" invoke="getChildRoleTypes">
+    <service name="getChildRoleTypes" engine="groovy"
+            location="component://party/groovyScripts/party/PartyServices.groovy" invoke="getChildRoleTypes">
         <description>
             Get Child RoleTypes.
             The childRoleTypeIdList coming out will contain the original roleTypeId.
@@ -222,16 +222,16 @@ under the License.
     </service>
 
     <!-- PostalAddressBoundary -->
-    <service name="getPostalAddressBoundary" engine="simple"
-            location="component://party/minilang/party/PartyServices.xml" invoke="getPostalAddressBoundary">
+    <service name="getPostalAddressBoundary" engine="groovy"
+            location="component://party/groovyScripts/party/PartyServices.groovy" invoke="getPostalAddressBoundary">
         <description>Get all Postal Address Boundaries</description>
         <permission-service service-name="partyBasePermissionCheck" main-action="VIEW"/>
         <attribute name="contactMechId" type="String" mode="IN" optional="false"/>
         <attribute name="geos" type="java.util.List" mode="OUT" optional="true"/>
     </service>
     
-    <service name="getRelatedParties" engine="simple"
-        location="component://party/minilang/party/PartyServices.xml" invoke="getRelatedParties">
+    <service name="getRelatedParties" engine="groovy"
+        location="component://party/groovyScripts/party/PartyServices.groovy" invoke="getRelatedParties">
         <description>
             Get Parties Related to a Party
             - The relatedPartyIdList coming out will include the original partyIdFrom