svn commit: r1838349 - in /ofbiz/ofbiz-framework/trunk/applications: datamodel/entitydef/ party/groovyScripts/test/ party/src/main/java/org/apache/ofbiz/party/contact/ party/testdef/ party/testdef/data/ workeffort/entitydef/

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r1838349 - in /ofbiz/ofbiz-framework/trunk/applications: datamodel/entitydef/ party/groovyScripts/test/ party/src/main/java/org/apache/ofbiz/party/contact/ party/testdef/ party/testdef/data/ workeffort/entitydef/

nmalin
Author: nmalin
Date: Sat Aug 18 21:23:31 2018
New Revision: 1838349

URL: http://svn.apache.org/viewvc?rev=1838349&view=rev
Log:
Improved: Refactoring ContactMechWorker.get[Entity]ContactMechValueMaps function to improve processing speed
(OFBIZ-10514)
ContactMechWorker.get[Entity]ContactMechValueMaps are old historic functions that resolve all contact mech context related to an Entity (Party, Facility, Order, WorkEffort).
The problem that they create too many db call during their execution that decrease OFBiz performance when the contactMech history grow.

A solution use to improve the process speed was replace all db call through *GenericValue.getRelated* function by *Delegator.makeValidValue* to instanciate each GenericValue needed after an unique search call on a viewEntity. For the four entities : Party, Facility, Order and WorkEffort, I use the same view structure with a sub view entity on ContactMechDetail. This offer more genericity and permit to slim code.

This commit introduce a regression on genericValue resolved for ContactMechType and ContactMechPurposeType that currently lost their description, it's actually not awkward because theses genericValue use the function .get("description", locale) to resolve the description so call directly the label system.

For Order and WorkEffort, I merged the resolving process in one function, that can be extend later easily for some other entity like Invoice or Quote.
The new FtpAddress wasn't managed by this worker so I introduce it to keep the coherence.

Last improvement, I use
   getPartyContactMechValueMaps(Delegator delegator, String partyId, Timestamp date, String contactMechTypeId)
instead of
   getPartyContactMechValueMaps(Delegator delegator, String partyId, boolean showOld, String contactMechTypeId)
to offert also more possibility to resolve at date instead just use now or all.

icing on the cake, I added groovy test to control this worker

Added:
    ofbiz/ofbiz-framework/trunk/applications/party/groovyScripts/test/
    ofbiz/ofbiz-framework/trunk/applications/party/groovyScripts/test/ContactMechWorkerTests.groovy   (with props)
Modified:
    ofbiz/ofbiz-framework/trunk/applications/datamodel/entitydef/order-entitymodel.xml
    ofbiz/ofbiz-framework/trunk/applications/datamodel/entitydef/party-entitymodel.xml
    ofbiz/ofbiz-framework/trunk/applications/datamodel/entitydef/product-entitymodel.xml
    ofbiz/ofbiz-framework/trunk/applications/party/src/main/java/org/apache/ofbiz/party/contact/ContactMechWorker.java
    ofbiz/ofbiz-framework/trunk/applications/party/testdef/PartyContactMechTests.xml
    ofbiz/ofbiz-framework/trunk/applications/party/testdef/data/PartyContactMechTestData.xml
    ofbiz/ofbiz-framework/trunk/applications/workeffort/entitydef/entitymodel_view.xml

Modified: ofbiz/ofbiz-framework/trunk/applications/datamodel/entitydef/order-entitymodel.xml
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/datamodel/entitydef/order-entitymodel.xml?rev=1838349&r1=1838348&r2=1838349&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/applications/datamodel/entitydef/order-entitymodel.xml (original)
+++ ofbiz/ofbiz-framework/trunk/applications/datamodel/entitydef/order-entitymodel.xml Sat Aug 18 21:23:31 2018
@@ -298,7 +298,38 @@ under the License.
         <key-map field-name="contactMechPurposeTypeId"/>
       </relation>
     </entity>
-    <entity entity-name="OrderContent" package-name="org.apache.ofbiz.order.order" title="Order Data Object">
+    <view-entity entity-name="OrderAndContactMech"
+                 package-name="org.apache.ofbiz.order.order"
+                 title="Order Contact Detail View">
+        <member-entity entity-alias="OCM" entity-name="OrderContactMech"/>
+        <member-entity entity-alias="CMD" entity-name="ContactMechDetail"/>
+        <alias-all entity-alias="OCM"/>
+        <alias-all entity-alias="CMD"/>
+        <view-link entity-alias="OCM" rel-entity-alias="CMD">
+          <key-map field-name="contactMechId"/>
+        </view-link>
+        <relation type="many" rel-entity-name="OrderContactMech">
+          <key-map field-name="orderId"/>
+          <key-map field-name="contactMechPurposeTypeId"/>
+          <key-map field-name="contactMechId"/>
+        </relation>
+        <relation type="one-nofk" rel-entity-name="ContactMech">
+          <key-map field-name="contactMechId"/>
+        </relation>
+        <relation type="one-nofk" rel-entity-name="ContactMechPurposeType">
+          <key-map field-name="contactMechPurposeTypeId"/>
+        </relation>
+        <relation type="one-nofk" rel-entity-name="PostalAddress">
+          <key-map field-name="contactMechId"/>
+        </relation>
+        <relation type="one-nofk" rel-entity-name="TelecomNumber">
+          <key-map field-name="contactMechId"/>
+        </relation>
+        <relation type="one-nofk" rel-entity-name="FtpAddress">
+          <key-map field-name="contactMechId"/>
+        </relation>
+    </view-entity>
+  <entity entity-name="OrderContent" package-name="org.apache.ofbiz.order.order" title="Order Data Object">
         <field name="orderId" type="id"></field>
         <field name="orderItemSeqId" type="id"></field>
         <field name="contentId" type="id"></field>

Modified: ofbiz/ofbiz-framework/trunk/applications/datamodel/entitydef/party-entitymodel.xml
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/datamodel/entitydef/party-entitymodel.xml?rev=1838349&r1=1838348&r2=1838349&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/applications/datamodel/entitydef/party-entitymodel.xml (original)
+++ ofbiz/ofbiz-framework/trunk/applications/datamodel/entitydef/party-entitymodel.xml Sat Aug 18 21:23:31 2018
@@ -1342,6 +1342,7 @@ under the License.
         <member-entity entity-alias="CM" entity-name="ContactMech"/>
         <member-entity entity-alias="PA" entity-name="PostalAddress"/>
         <member-entity entity-alias="TN" entity-name="TelecomNumber"/>
+        <member-entity entity-alias="FA" entity-name="FtpAddress"/>
         <alias-all entity-alias="CM"/>
         <alias-all entity-alias="PA" prefix="pa">
             <exclude field="contactMechId"/>
@@ -1349,36 +1350,32 @@ under the License.
         <alias-all entity-alias="TN" prefix="tn">
             <exclude field="contactMechId"/>
         </alias-all>
+        <alias-all entity-alias="FA" prefix="fa">
+            <exclude field="contactMechId"/>
+        </alias-all>
         <view-link entity-alias="CM" rel-entity-alias="PA" rel-optional="true">
             <key-map field-name="contactMechId"/>
         </view-link>
         <view-link entity-alias="CM" rel-entity-alias="TN" rel-optional="true">
             <key-map field-name="contactMechId"/>
         </view-link>
+        <view-link entity-alias="CM" rel-entity-alias="FA" rel-optional="true">
+            <key-map field-name="contactMechId"/>
+        </view-link>
     </view-entity>
     <view-entity entity-name="PartyAndContactMech"
         package-name="org.apache.ofbiz.party.contact"
         title="Party and Contact Mech View">
         <member-entity entity-alias="PTY" entity-name="Party"/>
         <member-entity entity-alias="PCM" entity-name="PartyContactMech"/>
-        <member-entity entity-alias="CM" entity-name="ContactMech"/>
-        <member-entity entity-alias="PA" entity-name="PostalAddress"/>
-        <member-entity entity-alias="TN" entity-name="TelecomNumber"/>
+        <member-entity entity-alias="CMD" entity-name="ContactMechDetail"/>
         <alias-all entity-alias="PTY"/>
         <alias-all entity-alias="PCM"/>
-        <alias-all entity-alias="CM"/>
-        <alias-all entity-alias="PA" prefix="pa"/>
-        <alias-all entity-alias="TN" prefix="tn"/>
+        <alias-all entity-alias="CMD"/>
         <view-link entity-alias="PTY" rel-entity-alias="PCM">
             <key-map field-name="partyId"/>
         </view-link>
-        <view-link entity-alias="PCM" rel-entity-alias="CM">
-            <key-map field-name="contactMechId"/>
-        </view-link>
-        <view-link entity-alias="PCM" rel-entity-alias="PA" rel-optional="true">
-            <key-map field-name="contactMechId"/>
-        </view-link>
-        <view-link entity-alias="PCM" rel-entity-alias="TN" rel-optional="true">
+        <view-link entity-alias="PCM" rel-entity-alias="CMD">
             <key-map field-name="contactMechId"/>
         </view-link>
         <relation type="many" rel-entity-name="PartyContactMech">
@@ -1397,6 +1394,9 @@ under the License.
         <relation type="one-nofk" rel-entity-name="TelecomNumber">
             <key-map field-name="contactMechId"/>
         </relation>
+        <relation type="one-nofk" rel-entity-name="FtpAddress">
+            <key-map field-name="contactMechId"/>
+        </relation>
     </view-entity>
     <view-entity entity-name="PartyAndPostalAddress"
         package-name="org.apache.ofbiz.party.contact"

Modified: ofbiz/ofbiz-framework/trunk/applications/datamodel/entitydef/product-entitymodel.xml
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/datamodel/entitydef/product-entitymodel.xml?rev=1838349&r1=1838348&r2=1838349&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/applications/datamodel/entitydef/product-entitymodel.xml (original)
+++ ofbiz/ofbiz-framework/trunk/applications/datamodel/entitydef/product-entitymodel.xml Sat Aug 18 21:23:31 2018
@@ -1048,17 +1048,36 @@ under the License.
     </entity>
     <view-entity entity-name="FacilityAndContactMech" package-name="org.apache.ofbiz.product.facility" title="Facility and Contact Mech View">
         <member-entity entity-alias="FA" entity-name="Facility"/>
-        <member-entity entity-alias="CM" entity-name="FacilityContactMech"/>
-        <member-entity entity-alias="MC" entity-name="ContactMech"/>
+        <member-entity entity-alias="FCM" entity-name="FacilityContactMech"/>
+        <member-entity entity-alias="CMD" entity-name="ContactMechDetail"/>
         <alias-all entity-alias="FA"/>
-        <alias-all entity-alias="CM"/>
-        <alias-all entity-alias="MC"/>
-        <view-link entity-alias="FA" rel-entity-alias="CM">
+        <alias-all entity-alias="FCM"/>
+        <alias-all entity-alias="CMD"/>
+        <view-link entity-alias="FA" rel-entity-alias="FCM">
             <key-map field-name="facilityId"/>
         </view-link>
-        <view-link entity-alias="CM" rel-entity-alias="MC">
+        <view-link entity-alias="FCM" rel-entity-alias="CMD">
             <key-map field-name="contactMechId"/>
         </view-link>
+        <relation type="many" rel-entity-name="FacilityContactMech">
+            <key-map field-name="partyId"/>
+            <key-map field-name="contactMechId"/>
+        </relation>
+        <relation type="one-nofk" rel-entity-name="Facility">
+            <key-map field-name="facilityId"/>
+        </relation>
+        <relation type="one-nofk" rel-entity-name="ContactMech">
+            <key-map field-name="contactMechId"/>
+        </relation>
+        <relation type="one-nofk" rel-entity-name="PostalAddress">
+            <key-map field-name="contactMechId"/>
+        </relation>
+        <relation type="one-nofk" rel-entity-name="TelecomNumber">
+            <key-map field-name="contactMechId"/>
+        </relation>
+        <relation type="one-nofk" rel-entity-name="FtpAddress">
+            <key-map field-name="contactMechId"/>
+        </relation>
     </view-entity>
     <entity entity-name="FacilityAttribute" package-name="org.apache.ofbiz.product.facility" title="Facility Attribute">
         <field name="facilityId" type="id"></field>

Added: ofbiz/ofbiz-framework/trunk/applications/party/groovyScripts/test/ContactMechWorkerTests.groovy
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/party/groovyScripts/test/ContactMechWorkerTests.groovy?rev=1838349&view=auto
==============================================================================
--- ofbiz/ofbiz-framework/trunk/applications/party/groovyScripts/test/ContactMechWorkerTests.groovy (added)
+++ ofbiz/ofbiz-framework/trunk/applications/party/groovyScripts/test/ContactMechWorkerTests.groovy Sat Aug 18 21:23:31 2018
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * 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.base.util.UtilDateTime
+import org.apache.ofbiz.party.contact.ContactMechWorker
+import org.apache.ofbiz.testtools.GroovyScriptTestCase
+
+class ContactMechWorkerTests extends GroovyScriptTestCase {
+
+    void testPartyContactMechResolution() {
+        //control for the DemoCustomer that postal, email, telecom and ftp contact are present and return correct information
+        List partyContactMechValueMaps = ContactMechWorker.getPartyContactMechValueMaps(delegator, "DemoCustomer", true)
+        assert partyContactMechValueMaps
+        assert partyContactMechValueMaps.size() == 7
+        boolean foundPostalAddress, foundTelecom, foundEmailAddress, foundFtpAddress = false
+        partyContactMechValueMaps.forEach {
+            Map partyContactMechValueMap ->
+                switch (partyContactMechValueMap?.contactMech?.contactMechId) {
+                    case '9015':
+                        foundPostalAddress = true
+                        assert partyContactMechValueMap.contactMech.contactMechTypeId == 'POSTAL_ADDRESS'
+                        assert partyContactMechValueMap.partyContactMech
+                        assert partyContactMechValueMap.contactMechType
+                        assert partyContactMechValueMap.partyContactMechPurposes
+                        assert partyContactMechValueMap.partyContactMechPurposes.size() == 3
+                        assert partyContactMechValueMap.postalAddress
+                        assert partyContactMechValueMap.postalAddress.contactMechId == '9015'
+                        assert partyContactMechValueMap.postalAddress.address1 == '2004 Factory Blvd'
+                        break
+                    case '9027':
+                        foundTelecom = true
+                        assert partyContactMechValueMap.contactMech.contactMechTypeId == 'TELECOM_NUMBER'
+                        assert partyContactMechValueMap.partyContactMech
+                        assert partyContactMechValueMap.contactMechType
+                        assert partyContactMechValueMap.partyContactMechPurposes
+                        assert partyContactMechValueMap.partyContactMechPurposes.size() == 1
+                        assert partyContactMechValueMap.telecomNumber
+                        assert partyContactMechValueMap.telecomNumber.contactMechId == '9027'
+                        assert partyContactMechValueMap.telecomNumber.contactNumber == '444-4444'
+                        break
+                    case '9126':
+                        foundEmailAddress = true
+                        assert partyContactMechValueMap.contactMech.contactMechTypeId == 'EMAIL_ADDRESS'
+                        assert partyContactMechValueMap.contactMech.infoString == '[hidden email]'
+                        assert partyContactMechValueMap.partyContactMech
+                        assert partyContactMechValueMap.contactMechType
+                        assert partyContactMechValueMap.partyContactMechPurposes
+                        assert partyContactMechValueMap.partyContactMechPurposes.size() == 2
+                        break
+                    case '9127':
+                        foundFtpAddress = true
+                        assert partyContactMechValueMap.contactMech.contactMechTypeId == 'FTP_ADDRESS'
+                        assert partyContactMechValueMap.partyContactMech
+                        assert partyContactMechValueMap.contactMechType
+                        assert !partyContactMechValueMap.partyContactMechPurposes
+                        assert partyContactMechValueMap.ftpAddress
+                        assert partyContactMechValueMap.ftpAddress.hostname == "ftp://apacheofbiz.foo.com"
+                        break
+                }
+        }
+        assert foundPostalAddress && foundTelecom && foundEmailAddress && foundFtpAddress
+
+        //Restart a search at now, the email 9126 need to have only one purpose
+        partyContactMechValueMaps = ContactMechWorker.getPartyContactMechValueMaps(delegator, "DemoCustomer", false, "EMAIL_ADDRESS")
+        partyContactMechValueMaps.forEach {
+            Map partyContactMechValueMap ->
+                switch (partyContactMechValueMap?.contactMech?.contactMechId) {
+                    case '9126':
+                        assert partyContactMechValueMap.partyContactMechPurposes.size() == 1
+                        break
+                }
+        }
+
+        //Restart a search at 05/13/2001 10:00:00.000, the email 9126 need to have two purposes
+        partyContactMechValueMaps = ContactMechWorker.getPartyContactMechValueMaps(delegator, "DemoCustomer", UtilDateTime.toTimestamp("05/13/2001 10:00:00.000"), "EMAIL_ADDRESS")
+        partyContactMechValueMaps.forEach {
+            Map partyContactMechValueMap ->
+                switch (partyContactMechValueMap?.contactMech?.contactMechId) {
+                    case '9126':
+                        assert partyContactMechValueMap.partyContactMechPurposes.size() == 2
+                        break
+                }
+        }
+    }
+
+    void testOrderContactMechResolution() {
+        List orderContactMechValueMaps = ContactMechWorker.getOrderContactMechValueMaps(delegator, "Demo1002")
+        assert orderContactMechValueMaps
+        assert orderContactMechValueMaps.size() == 3
+
+        boolean foundBillingAddress, foundShippingAddress, foundOrderEmail = false
+        orderContactMechValueMaps.forEach {
+            Map orderContactMechValueMap ->
+                switch (orderContactMechValueMap.contactMech?.contactMechId) {
+                    case '9015':
+                        assert orderContactMechValueMap.contactMech.contactMechTypeId == 'POSTAL_ADDRESS'
+                        assert orderContactMechValueMap.contactMechType
+                        assert orderContactMechValueMap.contactMechPurposeType
+                        assert orderContactMechValueMap.orderContactMech
+                        assert orderContactMechValueMap.postalAddress
+                        assert orderContactMechValueMap.postalAddress.contactMechId == '9015'
+                        assert orderContactMechValueMap.postalAddress.address1 == '2004 Factory Blvd'
+                        foundBillingAddress = foundBillingAddress?: orderContactMechValueMap.contactMechPurposeType.contactMechPurposeTypeId == 'BILLING_LOCATION'
+                        foundShippingAddress = foundShippingAddress?: orderContactMechValueMap.contactMechPurposeType.contactMechPurposeTypeId == 'SHIPPING_LOCATION'
+                        break
+                    case '9026':
+                        assert orderContactMechValueMap.contactMech.contactMechTypeId == 'EMAIL_ADDRESS'
+                        assert orderContactMechValueMap.contactMech.infoString == '[hidden email]'
+                        assert orderContactMechValueMap.orderContactMech
+                        assert orderContactMechValueMap.contactMechType
+                        foundOrderEmail = orderContactMechValueMap.contactMechPurposeType.contactMechPurposeTypeId == 'ORDER_EMAIL'
+                        break
+                    default:
+                        assert false
+                        break
+                }
+        }
+        assert foundBillingAddress && foundShippingAddress && foundOrderEmail
+    }
+}

Propchange: ofbiz/ofbiz-framework/trunk/applications/party/groovyScripts/test/ContactMechWorkerTests.groovy
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/ofbiz-framework/trunk/applications/party/groovyScripts/test/ContactMechWorkerTests.groovy
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/ofbiz-framework/trunk/applications/party/groovyScripts/test/ContactMechWorkerTests.groovy
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: ofbiz/ofbiz-framework/trunk/applications/party/src/main/java/org/apache/ofbiz/party/contact/ContactMechWorker.java
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/party/src/main/java/org/apache/ofbiz/party/contact/ContactMechWorker.java?rev=1838349&r1=1838348&r2=1838349&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/applications/party/src/main/java/org/apache/ofbiz/party/contact/ContactMechWorker.java (original)
+++ ofbiz/ofbiz-framework/trunk/applications/party/src/main/java/org/apache/ofbiz/party/contact/ContactMechWorker.java Sat Aug 18 21:23:31 2018
@@ -21,6 +21,8 @@ package org.apache.ofbiz.party.contact;
 
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
+import java.sql.Timestamp;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -33,12 +35,16 @@ import javax.servlet.ServletRequest;
 
 import org.apache.ofbiz.base.util.Assert;
 import org.apache.ofbiz.base.util.Debug;
+import org.apache.ofbiz.base.util.UtilDateTime;
+import org.apache.ofbiz.base.util.UtilGenerics;
 import org.apache.ofbiz.base.util.UtilMisc;
 import org.apache.ofbiz.base.util.UtilValidate;
 import org.apache.ofbiz.entity.Delegator;
 import org.apache.ofbiz.entity.GenericEntityException;
 import org.apache.ofbiz.entity.GenericValue;
 import org.apache.ofbiz.entity.condition.EntityCondition;
+import org.apache.ofbiz.entity.condition.EntityOperator;
+import org.apache.ofbiz.entity.model.ModelUtil;
 import org.apache.ofbiz.entity.util.EntityQuery;
 import org.apache.ofbiz.entity.util.EntityUtil;
 import org.apache.ofbiz.entity.util.EntityUtilProperties;
@@ -52,281 +58,199 @@ public class ContactMechWorker {
 
     private ContactMechWorker() {}
 
+    /**
+     * Check the contactMechTypeId value on toAnalyzeFields map and if is a PostalAddress, a TelecomNumber or FtpAddress
+     * add the GenericValue related to elementMap
+     * @param delegator
+     * @param elementMap
+     */
+    private static void insertRelatedContactElement(Delegator delegator, Map<String, Object> elementMap, Map<String, Object> fields) {
+        String contactMechTypeId = (String) fields.get("contactMechTypeId");
+        String entityName = null;
+        String prefix = null;
+        switch (contactMechTypeId) {
+            case "POSTAL_ADDRESS":
+                entityName = "PostalAddress";
+                prefix = "pa";
+                break;
+            case "TELECOM_NUMBER":
+                entityName = "TelecomNumber";
+                prefix = "tn";
+                break;
+            case "FTP_ADDRESS":
+                entityName = "FtpAddress";
+                prefix = "fa";
+                break;
+        }
+        if (entityName != null) {
+            GenericValue element = delegator.makeValue(entityName);
+            element.setAllFields(fields, false, prefix, null);
+            element.set("contactMechId", fields.get("contactMechId"));
+            elementMap.put(ModelUtil.lowerFirstChar(entityName), element);
+        }
+    }
+
     public static List<Map<String, Object>> getPartyContactMechValueMaps(Delegator delegator, String partyId, boolean showOld) {
        return getPartyContactMechValueMaps(delegator, partyId, showOld, null);
     }
-
     public static List<Map<String, Object>> getPartyContactMechValueMaps(Delegator delegator, String partyId, boolean showOld, String contactMechTypeId) {
-        List<Map<String, Object>> partyContactMechValueMaps = new LinkedList<>();
+        Timestamp date = showOld? null: UtilDateTime.nowTimestamp();
+        return getPartyContactMechValueMaps(delegator, partyId, date, contactMechTypeId);
+    }
+    public static List<Map<String, Object>> getPartyContactMechValueMaps(Delegator delegator, String partyId, Timestamp date, String contactMechTypeId) {
+        List<Map<String, Object>> partyContactMechValueMaps = new ArrayList<>();
 
         List<GenericValue> allPartyContactMechs = null;
+        List<EntityCondition> conditionList = UtilMisc.toList(EntityCondition.makeCondition("partyId", partyId));
+        if (contactMechTypeId != null) conditionList.add(EntityCondition.makeCondition("contactMechTypeId", contactMechTypeId));
 
+        //Resolve all
         try {
-            List<GenericValue> tempCol = EntityQuery.use(delegator).from("PartyContactMech").where("partyId", partyId).queryList();
-            if (contactMechTypeId != null) {
-                List<GenericValue> tempColTemp = new LinkedList<>();
-                for (GenericValue partyContactMech: tempCol) {
-                    GenericValue contactMech = delegator.getRelatedOne("ContactMech", partyContactMech, false);
-                    if (contactMech != null && contactMechTypeId.equals(contactMech.getString("contactMechTypeId"))) {
-                        tempColTemp.add(partyContactMech);
-                    }
-
-                }
-                tempCol = tempColTemp;
-            }
-            if (!showOld) {
-                tempCol = EntityUtil.filterByDate(tempCol, true);
-            }
-            allPartyContactMechs = tempCol;
+            allPartyContactMechs = EntityQuery.use(delegator)
+                    .from("PartyAndContactMech")
+                    .where(conditionList)
+                    .filterByDate(date)
+                    .cache()
+                    .queryList();
         } catch (GenericEntityException e) {
             Debug.logWarning(e, module);
         }
 
-        if (allPartyContactMechs == null) {
+        if (UtilValidate.isEmpty(allPartyContactMechs)) {
             return partyContactMechValueMaps;
         }
+        List<String> contactMechIds = EntityUtil.getFieldListFromEntityList(allPartyContactMechs, "contactMechId", true);
+        conditionList = UtilMisc.toList(
+                EntityCondition.makeCondition("partyId", partyId),
+                EntityCondition.makeCondition("contactMechId", EntityOperator.IN, contactMechIds));
+        List<GenericValue> allPartyContactMechPurposes = null;
+        try {
+            allPartyContactMechPurposes = EntityQuery.use(delegator)
+                    .from("PartyContactMechPurpose")
+                    .where(conditionList)
+                    .filterByDate(date)
+                    .cache()
+                    .queryList();
+        } catch (GenericEntityException e) {
+            Debug.logWarning(e, module);
+        }
 
         for (GenericValue partyContactMech: allPartyContactMechs) {
-            GenericValue contactMech = null;
+            Map<String, Object> fields = partyContactMech.getAllFields();
 
-            try {
-                contactMech = partyContactMech.getRelatedOne("ContactMech", false);
-            } catch (GenericEntityException e) {
-                Debug.logWarning(e, module);
-            }
-            if (contactMech != null) {
-                Map<String, Object> partyContactMechValueMap = new HashMap<>();
-
-                partyContactMechValueMaps.add(partyContactMechValueMap);
-                partyContactMechValueMap.put("contactMech", contactMech);
-                partyContactMechValueMap.put("partyContactMech", partyContactMech);
-
-                try {
-                    partyContactMechValueMap.put("contactMechType", contactMech.getRelatedOne("ContactMechType", true));
-                } catch (GenericEntityException e) {
-                    Debug.logWarning(e, module);
-                }
-
-                try {
-                    List<GenericValue> partyContactMechPurposes = partyContactMech.getRelated("PartyContactMechPurpose", null, null, false);
-
-                    if (!showOld) {
-                        partyContactMechPurposes = EntityUtil.filterByDate(partyContactMechPurposes, true);
-                    }
-                    partyContactMechValueMap.put("partyContactMechPurposes", partyContactMechPurposes);
-                } catch (GenericEntityException e) {
-                    Debug.logWarning(e, module);
-                }
-
-                try {
-                    if ("POSTAL_ADDRESS".equals(contactMech.getString("contactMechTypeId"))) {
-                        partyContactMechValueMap.put("postalAddress", contactMech.getRelatedOne("PostalAddress", false));
-                    } else if ("TELECOM_NUMBER".equals(contactMech.getString("contactMechTypeId"))) {
-                        partyContactMechValueMap.put("telecomNumber", contactMech.getRelatedOne("TelecomNumber", false));
-                    } else if ("FTP_ADDRESS".equals(contactMech.getString("contactMechTypeId"))) {
-                        partyContactMechValueMap.put("ftpAddress", contactMech.getRelatedOne("FtpAddress", false));
-                    }
-                } catch (GenericEntityException e) {
-                    Debug.logWarning(e, module);
-                }
-            }
+            Map<String, Object> partyContactMechValueMap = new HashMap<>();
+            partyContactMechValueMaps.add(partyContactMechValueMap);
+            partyContactMechValueMap.put("contactMech", delegator.makeValidValue("ContactMech", fields));
+            partyContactMechValueMap.put("contactMechType", delegator.makeValidValue("ContactMechType", fields));
+            partyContactMechValueMap.put("partyContactMech", delegator.makeValidValue("PartyContactMech", fields));
+
+            ContactMechWorker.insertRelatedContactElement(delegator, partyContactMechValueMap, fields);
+            List<GenericValue> partyContactMechPurposes = EntityUtil.filterByAnd(allPartyContactMechPurposes, UtilMisc.toMap("contactMechId", partyContactMech.getString("contactMechId")));
+            partyContactMechValueMap.put("partyContactMechPurposes", partyContactMechPurposes);
         }
 
         return partyContactMechValueMaps;
     }
 
+    public static List<Map<String, Object>> getFacilityContactMechValueMaps(Delegator delegator, String facilityId, boolean showOld) {
+       return getFacilityContactMechValueMaps(delegator, facilityId, showOld, null);
+    }
     public static List<Map<String, Object>> getFacilityContactMechValueMaps(Delegator delegator, String facilityId, boolean showOld, String contactMechTypeId) {
-        List<Map<String, Object>> facilityContactMechValueMaps = new LinkedList<>();
+        Timestamp date = showOld? UtilDateTime.nowTimestamp(): null;
+        return getFacilityContactMechValueMaps(delegator, facilityId, date, contactMechTypeId);
+    }
+    public static List<Map<String, Object>> getFacilityContactMechValueMaps(Delegator delegator, String facilityId, Timestamp date, String contactMechTypeId) {
+        List<Map<String, Object>> facilityContactMechValueMaps = new ArrayList<>();
 
         List<GenericValue> allFacilityContactMechs = null;
+        List<EntityCondition> conditionList = UtilMisc.toList(EntityCondition.makeCondition("facilityId", facilityId));
+        if (contactMechTypeId != null) conditionList.add(EntityCondition.makeCondition("contactMechTypeId", contactMechTypeId));
 
+        //Resolve all
         try {
-            List<GenericValue> tempCol = EntityQuery.use(delegator).from("FacilityContactMech").where("facilityId", facilityId).queryList();
-            if (contactMechTypeId != null) {
-                List<GenericValue> tempColTemp = new LinkedList<>();
-                for (GenericValue partyContactMech: tempCol) {
-                    GenericValue contactMech = delegator.getRelatedOne("ContactMech", partyContactMech, false);
-                    if (contactMech != null && contactMechTypeId.equals(contactMech.getString("contactMechTypeId"))) {
-                        tempColTemp.add(partyContactMech);
-                    }
-
-                }
-                tempCol = tempColTemp;
-            }
-            if (!showOld) {
-                tempCol = EntityUtil.filterByDate(tempCol, true);
-            }
-            allFacilityContactMechs = tempCol;
+            allFacilityContactMechs = EntityQuery.use(delegator)
+                    .from("FacilityAndContactMech")
+                    .where(conditionList)
+                    .filterByDate(date)
+                    .cache()
+                    .queryList();
         } catch (GenericEntityException e) {
             Debug.logWarning(e, module);
         }
 
-        if (allFacilityContactMechs == null) {
+        if (UtilValidate.isEmpty(allFacilityContactMechs)) {
             return facilityContactMechValueMaps;
         }
+        List<String> contactMechIds = EntityUtil.getFieldListFromEntityList(allFacilityContactMechs, "contactMechId", true);
+        conditionList = UtilMisc.toList(
+                EntityCondition.makeCondition("facilityId", facilityId),
+                EntityCondition.makeCondition("contactMechId", EntityOperator.IN, contactMechIds));
+        List<GenericValue> allFacilityContactMechPurposes = null;
+        try {
+            allFacilityContactMechPurposes = EntityQuery.use(delegator).from("FacilityContactMechPurpose").where(conditionList).filterByDate(date).cache().queryList();
+        } catch (GenericEntityException e) {
+            Debug.logWarning(e, module);
+        }
 
         for (GenericValue facilityContactMech: allFacilityContactMechs) {
-            GenericValue contactMech = null;
+            Map<String, Object> fields = facilityContactMech.getAllFields();
 
-            try {
-                contactMech = facilityContactMech.getRelatedOne("ContactMech", false);
-            } catch (GenericEntityException e) {
-                Debug.logWarning(e, module);
-            }
-            if (contactMech != null) {
-                Map<String, Object> facilityContactMechValueMap = new HashMap<>();
-
-                facilityContactMechValueMaps.add(facilityContactMechValueMap);
-                facilityContactMechValueMap.put("contactMech", contactMech);
-                facilityContactMechValueMap.put("facilityContactMech", facilityContactMech);
-
-                try {
-                    facilityContactMechValueMap.put("contactMechType", contactMech.getRelatedOne("ContactMechType", true));
-                } catch (GenericEntityException e) {
-                    Debug.logWarning(e, module);
-                }
-
-                try {
-                    List<GenericValue> facilityContactMechPurposes = facilityContactMech.getRelated("FacilityContactMechPurpose", null, null, false);
-
-                    if (!showOld) {
-                        facilityContactMechPurposes = EntityUtil.filterByDate(facilityContactMechPurposes, true);
-                    }
-                    facilityContactMechValueMap.put("facilityContactMechPurposes", facilityContactMechPurposes);
-                } catch (GenericEntityException e) {
-                    Debug.logWarning(e, module);
-                }
-
-                try {
-                    if ("POSTAL_ADDRESS".equals(contactMech.getString("contactMechTypeId"))) {
-                        facilityContactMechValueMap.put("postalAddress", contactMech.getRelatedOne("PostalAddress", false));
-                    } else if ("TELECOM_NUMBER".equals(contactMech.getString("contactMechTypeId"))) {
-                        facilityContactMechValueMap.put("telecomNumber", contactMech.getRelatedOne("TelecomNumber", false));
-                    }
-                } catch (GenericEntityException e) {
-                    Debug.logWarning(e, module);
-                }
-            }
+            Map<String, Object> facilityContactMechValueMap = new HashMap<>();
+            facilityContactMechValueMaps.add(facilityContactMechValueMap);
+            facilityContactMechValueMap.put("contactMech", delegator.makeValidValue("ContactMech", fields));
+            facilityContactMechValueMap.put("contactMechType", delegator.makeValidValue("ContactMechType", fields));
+            facilityContactMechValueMap.put("facilityContactMech", delegator.makeValidValue("FacilityContactMech", fields));
+
+            ContactMechWorker.insertRelatedContactElement(delegator, facilityContactMechValueMap, fields);
+            List<GenericValue> facilityContactMechPurposes = EntityUtil.filterByAnd(allFacilityContactMechPurposes, UtilMisc.toMap("contactMechId", facilityContactMech.getString("contactMechId")));
+            facilityContactMechValueMap.put("facilityContactMechPurposes", facilityContactMechPurposes);
         }
 
         return facilityContactMechValueMaps;
     }
 
-
     public static List<Map<String, GenericValue>> getOrderContactMechValueMaps(Delegator delegator, String orderId) {
-        List<Map<String, GenericValue>> orderContactMechValueMaps = new LinkedList<>();
-
-        List<GenericValue> allOrderContactMechs = null;
-
-        try {
-            allOrderContactMechs = EntityQuery.use(delegator).from("OrderContactMech")
-                    .where("orderId", orderId)
-                    .orderBy("contactMechPurposeTypeId")
-                    .queryList();
-        } catch (GenericEntityException e) {
-            Debug.logWarning(e, module);
-        }
-
-        if (allOrderContactMechs == null) {
-            return orderContactMechValueMaps;
-        }
-
-        for (GenericValue orderContactMech: allOrderContactMechs) {
-            GenericValue contactMech = null;
-
-            try {
-                contactMech = orderContactMech.getRelatedOne("ContactMech", false);
-            } catch (GenericEntityException e) {
-                Debug.logWarning(e, module);
-            }
-            if (contactMech != null) {
-                Map<String, GenericValue> orderContactMechValueMap = new HashMap<>();
-
-                orderContactMechValueMaps.add(orderContactMechValueMap);
-                orderContactMechValueMap.put("contactMech", contactMech);
-                orderContactMechValueMap.put("orderContactMech", orderContactMech);
-
-                try {
-                    orderContactMechValueMap.put("contactMechType", contactMech.getRelatedOne("ContactMechType", true));
-                } catch (GenericEntityException e) {
-                    Debug.logWarning(e, module);
-                }
-
-                try {
-                    GenericValue contactMechPurposeType = orderContactMech.getRelatedOne("ContactMechPurposeType", false);
-
-                    orderContactMechValueMap.put("contactMechPurposeType", contactMechPurposeType);
-                } catch (GenericEntityException e) {
-                    Debug.logWarning(e, module);
-                }
-
-                try {
-                    if ("POSTAL_ADDRESS".equals(contactMech.getString("contactMechTypeId"))) {
-                        orderContactMechValueMap.put("postalAddress", contactMech.getRelatedOne("PostalAddress", false));
-                    } else if ("TELECOM_NUMBER".equals(contactMech.getString("contactMechTypeId"))) {
-                        orderContactMechValueMap.put("telecomNumber", contactMech.getRelatedOne("TelecomNumber", false));
-                    }
-                } catch (GenericEntityException e) {
-                    Debug.logWarning(e, module);
-                }
-            }
-        }
-
-        return orderContactMechValueMaps;
+        return getEntityContactMechValueMaps(delegator, "Order", orderId, null);
     }
 
     public static Collection<Map<String, GenericValue>> getWorkEffortContactMechValueMaps(Delegator delegator, String workEffortId) {
-        Collection<Map<String, GenericValue>> workEffortContactMechValueMaps = new LinkedList<>();
+        Collection<Map<String, GenericValue>> workEffortContactMechValueMaps = getEntityContactMechValueMaps(delegator, "WorkEffort", workEffortId, UtilDateTime.nowTimestamp());
+        return UtilValidate.isNotEmpty(workEffortContactMechValueMaps) ? workEffortContactMechValueMaps : null;
+    }
 
-        List<GenericValue> allWorkEffortContactMechs = null;
+    private static List<Map<String, GenericValue>> getEntityContactMechValueMaps(Delegator delegator, String entityName, String entityId, Timestamp date) {
+        List<Map<String, GenericValue>> entityContactMechValueMaps = new LinkedList<>();
+        String downCaseEntityName = ModelUtil.lowerFirstChar(entityName);
+
+        List<GenericValue> allEntityContactMechs = null;
 
         try {
-            allWorkEffortContactMechs = EntityQuery.use(delegator).from("WorkEffortContactMech")
-                    .where("workEffortId", workEffortId)
-                    .filterByDate()
+            allEntityContactMechs = EntityQuery.use(delegator).from(entityName + "AndContactMech")
+                    .where(downCaseEntityName + "Id", entityId)
+                    .orderBy("contactMechPurposeTypeId")
+                    .filterByDate(date)
                     .queryList();
         } catch (GenericEntityException e) {
             Debug.logWarning(e, module);
         }
 
-        if (allWorkEffortContactMechs == null) {
-            return null;
+        if (allEntityContactMechs == null) {
+            return entityContactMechValueMaps;
         }
 
-        for (GenericValue workEffortContactMech: allWorkEffortContactMechs) {
-            GenericValue contactMech = null;
+        for (GenericValue entityContactMech: allEntityContactMechs) {
+            Map<String, Object> fields = entityContactMech.getAllFields();
+            Map<String, GenericValue> entityContactMechValueMap = new HashMap<>();
 
-            try {
-                contactMech = workEffortContactMech.getRelatedOne("ContactMech", false);
-            } catch (GenericEntityException e) {
-                Debug.logWarning(e, module);
-            }
-            if (contactMech != null) {
-                Map<String, GenericValue> workEffortContactMechValueMap = new HashMap<>();
-
-                workEffortContactMechValueMaps.add(workEffortContactMechValueMap);
-                workEffortContactMechValueMap.put("contactMech", contactMech);
-                workEffortContactMechValueMap.put("workEffortContactMech", workEffortContactMech);
-
-                try {
-                    workEffortContactMechValueMap.put("contactMechType", contactMech.getRelatedOne("ContactMechType", true));
-                } catch (GenericEntityException e) {
-                    Debug.logWarning(e, module);
-                }
-
-                try {
-                    if ("POSTAL_ADDRESS".equals(contactMech.getString("contactMechTypeId"))) {
-                        workEffortContactMechValueMap.put("postalAddress", contactMech.getRelatedOne("PostalAddress", false));
-                    } else if ("TELECOM_NUMBER".equals(contactMech.getString("contactMechTypeId"))) {
-                        workEffortContactMechValueMap.put("telecomNumber", contactMech.getRelatedOne("TelecomNumber", false));
-                    }
-                } catch (GenericEntityException e) {
-                    Debug.logWarning(e, module);
-                }
-            }
+            entityContactMechValueMaps.add(entityContactMechValueMap);
+            entityContactMechValueMap.put("contactMech", delegator.makeValidValue("ContactMech", fields));
+            entityContactMechValueMap.put(downCaseEntityName + "ContactMech", delegator.makeValidValue(entityName + "ContactMech", fields));
+            entityContactMechValueMap.put("contactMechType", delegator.makeValidValue("ContactMechType",fields));
+            entityContactMechValueMap.put("contactMechPurposeType", delegator.makeValidValue("ContactMechPurposeType", fields));
+            insertRelatedContactElement(delegator, UtilGenerics.checkMap(entityContactMechValueMap), fields);
         }
 
-        return workEffortContactMechValueMaps.size() > 0 ? workEffortContactMechValueMaps : null;
+        return entityContactMechValueMaps;
     }
 
     public static void getContactMechAndRelated(ServletRequest request, String partyId, Map<String, Object> target) {

Modified: ofbiz/ofbiz-framework/trunk/applications/party/testdef/PartyContactMechTests.xml
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/party/testdef/PartyContactMechTests.xml?rev=1838349&r1=1838348&r2=1838349&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/applications/party/testdef/PartyContactMechTests.xml (original)
+++ ofbiz/ofbiz-framework/trunk/applications/party/testdef/PartyContactMechTests.xml Sat Aug 18 21:23:31 2018
@@ -24,9 +24,12 @@
     <test-case case-name="loadPartyContactMechTestData">
         <entity-xml action="load" entity-xml-url="component://party/testdef/data/PartyContactMechTestData.xml"/>
     </test-case>
-
+    <test-case case-name="ContactMechWorker-tests">
+        <groovy-test-suite name="contactMechWorker" location="component://party/groovyScripts/test/ContactMechWorkerTests.groovy"/>
+    </test-case>
     <test-case case-name="partyContactMech-tests">
         <simple-method-test location="component://party/minilang/test/PartyContactMechTests.xml"/>
     </test-case>
 
+
 </test-suite>

Modified: ofbiz/ofbiz-framework/trunk/applications/party/testdef/data/PartyContactMechTestData.xml
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/party/testdef/data/PartyContactMechTestData.xml?rev=1838349&r1=1838348&r2=1838349&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/applications/party/testdef/data/PartyContactMechTestData.xml (original)
+++ ofbiz/ofbiz-framework/trunk/applications/party/testdef/data/PartyContactMechTestData.xml Sat Aug 18 21:23:31 2018
@@ -27,4 +27,9 @@ under the License.
     <ContactMech contactMechId="9126" contactMechTypeId="EMAIL_ADDRESS" infoString="[hidden email]"/>
     <PartyContactMech partyId="DemoCustomer" contactMechId="9126" fromDate="2001-05-13 00:00:00.000" allowSolicitation="Y"/>
     <PartyContactMechPurpose partyId="DemoCustomer" contactMechId="9126" contactMechPurposeTypeId="PRIMARY_EMAIL" fromDate="2001-05-13 00:00:00.000"/>
+    <PartyContactMechPurpose partyId="DemoCustomer" contactMechId="9126" contactMechPurposeTypeId="BILLING_EMAIL" fromDate="2001-05-13 00:00:00.000" thruDate="2001-05-14 00:00:00.000"/>
+
+    <ContactMech contactMechId="9127" contactMechTypeId="FTP_ADDRESS"/>
+    <FtpAddress contactMechId="9127" hostname="ftp://apacheofbiz.foo.com" port="" username="ofbiz" password="apache" binaryTransfer="Y" passiveMode="Y" path="public"/>
+    <PartyContactMech partyId="DemoCustomer" contactMechId="9127" fromDate="2001-05-13 00:00:00.000" allowSolicitation="Y"/>
 </entity-engine-xml>

Modified: ofbiz/ofbiz-framework/trunk/applications/workeffort/entitydef/entitymodel_view.xml
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/applications/workeffort/entitydef/entitymodel_view.xml?rev=1838349&r1=1838348&r2=1838349&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/applications/workeffort/entitydef/entitymodel_view.xml (original)
+++ ofbiz/ofbiz-framework/trunk/applications/workeffort/entitydef/entitymodel_view.xml Sat Aug 18 21:23:31 2018
@@ -940,6 +940,37 @@ under the License.
             <key-map field-name="contactMechId"/>
         </view-link>
     </view-entity>
+    <view-entity entity-name="WorkEffortAndContactMech"
+                                   package-name="org.apache.ofbiz.workeffort.workeffort"
+                 title="Order Contact Detail View">
+        <member-entity entity-alias="WCM" entity-name="WorkEffortContactMech"/>
+        <member-entity entity-alias="CMD" entity-name="ContactMechDetail"/>
+        <alias-all entity-alias="WCM"/>
+        <alias-all entity-alias="CMD"/>
+        <view-link entity-alias="WCM" rel-entity-alias="CMD">
+            <key-map field-name="contactMechId"/>
+        </view-link>
+        <relation type="many" rel-entity-name="WorkEffortContactMech">
+            <key-map field-name="workEffortId"/>
+            <key-map field-name="contactMechPurposeTypeId"/>
+            <key-map field-name="contactMechId"/>
+        </relation>
+        <relation type="one-nofk" rel-entity-name="ContactMech">
+            <key-map field-name="contactMechId"/>
+        </relation>
+        <relation type="one-nofk" rel-entity-name="ContactMechPurposeType">
+            <key-map field-name="contactMechPurposeTypeId"/>
+        </relation>
+        <relation type="one-nofk" rel-entity-name="PostalAddress">
+            <key-map field-name="contactMechId"/>
+        </relation>
+        <relation type="one-nofk" rel-entity-name="TelecomNumber">
+            <key-map field-name="contactMechId"/>
+        </relation>
+        <relation type="one-nofk" rel-entity-name="FtpAddress">
+            <key-map field-name="contactMechId"/>
+        </relation>
+    </view-entity>
 
     <view-entity entity-name="WorkEffortAndTimeEntry" package-name="org.apache.ofbiz.workeffort.workeffort"
                  title="WorkEffort and TimeEntry View Entity">