KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > opensourcestrategies > crmsfa > activities > ActivitiesServices


1 /*
2  * Copyright (c) 2006 - 2007 Open Source Strategies, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the Honest Public License.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * Honest Public License for more details.
11  *
12  * You should have received a copy of the Honest Public License
13  * along with this program; if not, write to Funambol,
14  * 643 Bair Island Road, Suite 305 - Redwood City, CA 94063, USA
15  */

16 /* Copyright (c) 2005-2006 Open Source Strategies, Inc. */
17
18 /*
19  * $Id:$
20  *
21  * Copyright (c) 2001-2005 The Open For Business Project - www.ofbiz.org
22  *
23  * Permission is hereby granted, free of charge, to any person obtaining a
24  * copy of this software and associated documentation files (the "Software"),
25  * to deal in the Software without restriction, including without limitation
26  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
27  * and/or sell copies of the Software, and to permit persons to whom the
28  * Software is furnished to do so, subject to the following conditions:
29  *
30  * The above copyright notice and this permission notice shall be included
31  * in all copies or substantial portions of the Software.
32  *
33  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
34  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
35  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
36  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
37  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
38  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
39  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40  */

41 package com.opensourcestrategies.crmsfa.activities;
42
43 import java.util.HashMap JavaDoc;
44 import java.util.Map JavaDoc;
45 import java.util.List JavaDoc;
46 import java.util.ArrayList JavaDoc;
47 import java.util.Locale JavaDoc;
48 import java.util.Iterator JavaDoc;
49 import java.io.ObjectInputStream.GetField;
50 import java.sql.Timestamp JavaDoc;
51
52 import org.ofbiz.base.util.Debug;
53 import org.ofbiz.base.util.UtilMisc;
54 import org.ofbiz.base.util.UtilDateTime;
55 import org.ofbiz.entity.GenericDelegator;
56 import org.ofbiz.entity.GenericEntityException;
57 import org.ofbiz.entity.GenericValue;
58 import org.ofbiz.entity.condition.EntityConditionList;
59 import org.ofbiz.entity.condition.EntityExpr;
60 import org.ofbiz.entity.condition.EntityOperator;
61 import org.ofbiz.entity.util.EntityUtil;
62 import org.ofbiz.service.DispatchContext;
63 import org.ofbiz.service.GenericServiceException;
64 import org.ofbiz.service.LocalDispatcher;
65 import org.ofbiz.service.ServiceUtil;
66 import org.ofbiz.service.ModelService;
67 import org.ofbiz.service.mail.MimeMessageWrapper;
68 import org.ofbiz.security.Security;
69
70 import com.opensourcestrategies.crmsfa.party.PartyHelper;
71 import com.opensourcestrategies.crmsfa.security.CrmsfaSecurity;
72 import com.opensourcestrategies.crmsfa.util.UtilCommon;
73 import com.opensourcestrategies.crmsfa.opportunities.UtilOpportunity;
74 import com.opensourcestrategies.crmsfa.cases.UtilCase;
75 import com.opensourcestrategies.crmsfa.activities.UtilActivity;
76
77 /**
78  * Activities services. The service documentation is in services_activities.xml.
79  *
80  * @author <a HREF="mailto:leon@opensourcestrategies.com">Leon Torres</a>
81  * @version $Rev: 312 $
82  */

83
84 public class ActivitiesServices {
85
86     public static final String JavaDoc module = ActivitiesServices.class.getName();
87
88     public static Map JavaDoc sendEmail(DispatchContext dctx, Map JavaDoc context) {
89         return sendOrSaveEmailHelper(dctx, context, true, "CrmErrorSendEmailFail");
90     }
91
92     public static Map JavaDoc saveEmail(DispatchContext dctx, Map JavaDoc context) {
93         return sendOrSaveEmailHelper(dctx, context, false, "CrmErrorSaveEmailFail");
94     }
95
96     /**
97      * Saving and sending are very complex services that are nearly identical in most ways.
98      * There are four things that break the identity in minor ways that can be handled with
99      * booleans. The four things are: Send new email, send existing email, save new email,
100      * and send existing email. Instead of creating four separate methods several hundred
101      * lines each, we do everything here.
102      */

103     private static Map JavaDoc sendOrSaveEmailHelper(DispatchContext dctx, Map JavaDoc context, boolean sending, String JavaDoc errorLabel) {
104         GenericDelegator delegator = dctx.getDelegator();
105         LocalDispatcher dispatcher = dctx.getDispatcher();
106         Security security = dctx.getSecurity();
107         GenericValue userLogin = (GenericValue) context.get("userLogin");
108         Locale JavaDoc locale = (Locale JavaDoc) context.get("locale");
109
110         // use the toEmail and internalPartyId to find the contactMechIdTo
111
String JavaDoc toEmail = (String JavaDoc) context.get("toEmail");
112         String JavaDoc internalPartyId = (String JavaDoc) context.get("internalPartyId");
113
114         // if the email exists already, these will be set
115
String JavaDoc communicationEventId = (String JavaDoc) context.get("communicationEventId");
116         String JavaDoc workEffortId = (String JavaDoc) context.get("workEffortId");
117         boolean existing = ((communicationEventId == null) || communicationEventId.equals("") ? false : true);
118
119         try {
120             // validate the associations
121
Map JavaDoc serviceResults = validateWorkEffortAssociations(dctx, context);
122             if (ServiceUtil.isError(serviceResults)) {
123                 return UtilCommon.createAndLogServiceError(serviceResults, errorLabel, locale, module);
124             }
125
126             // search for contactMechIdTo using the passed in email and party
127
List JavaDoc candidates = EntityUtil.filterByDate(delegator.findByAnd("PartyAndContactMech", UtilMisc.toMap("infoString", toEmail, "partyId", internalPartyId)));
128             if (candidates.size() == 0) {
129                 return UtilCommon.createAndLogServiceError("Could not find email [" + toEmail + "] for party with ID [" + internalPartyId + "].", errorLabel, locale, module);
130             }
131             // use the first one in the list
132
String JavaDoc contactMechIdTo = ((GenericValue) candidates.get(0)).getString("contactMechId");
133
134             // also get the partyIdTo and roleTypeIdTo of this contact mech
135
List JavaDoc toContactMechs = EntityUtil.filterByDate(delegator.findByAnd("PartyContactMech",
136                         UtilMisc.toMap("contactMechId", contactMechIdTo), UtilMisc.toList("fromDate DESC")));
137             String JavaDoc partyIdTo = ((GenericValue) toContactMechs.get(0)).getString("partyId");
138             String JavaDoc roleTypeIdTo = PartyHelper.getFirstValidRoleTypeId(partyIdTo, PartyHelper.CLIENT_PARTY_ROLES, delegator);
139
140             /*
141              * We're done with validation, now we begin the complex task of creating comm events, workefforts, and updating them
142              * so that the email is sent or saved properly. The most verbose way of doing this requires four different methods with
143              * a lot of redundant code. But here we use two booleans "existing" and "sending" to decide what to do. This is much
144              * more compact but can be prone to subtle state errors. On the other hand, changes to the form input require only one
145              * change here instead of four changes.
146              */

147
148             // create a PENDING comm event or update the existing one; set the comm event data with the form input
149
String JavaDoc serviceName = (existing ? "updateCommunicationEvent" : "createCommunicationEvent");
150             ModelService service = dctx.getModelService(serviceName);
151             Map JavaDoc input = service.makeValid(context, "IN");
152             if (existing) input.put("communicationEventId", communicationEventId);
153             if (!existing) input.put("entryDate", UtilDateTime.nowTimestamp());
154             input.put("contactMechIdTo", contactMechIdTo);
155             input.put("contactMechTypeId", "EMAIL_ADDRESS");
156             input.put("communicationEventTypeId", "EMAIL_COMMUNICATION");
157             input.put("statusId", "COM_PENDING");
158             input.put("partyIdTo", partyIdTo);
159             input.put("roleTypeIdTo", roleTypeIdTo);
160             input.put("partyIdFrom", userLogin.getString("partyId"));
161             input.put("roleTypeIdFrom", PartyHelper.getFirstValidRoleTypeId(userLogin.getString("partyId"), PartyHelper.TEAM_MEMBER_ROLES, delegator));
162             serviceResults = dispatcher.runSync(serviceName, input);
163             if (ServiceUtil.isError(serviceResults)) {
164                 return UtilCommon.createAndLogServiceError(serviceResults, errorLabel, locale, module);
165             }
166
167             // get the communication event id if the comm event was created
168
if (!existing) communicationEventId = (String JavaDoc) serviceResults.get("communicationEventId");
169
170             if (sending) {
171                 // Update communication event to status IN_PROGRESS: this causes it to be sent by OFBiz synchronously
172
input = UtilMisc.toMap("communicationEventId", communicationEventId, "statusId", "COM_IN_PROGRESS", "userLogin", userLogin);
173                 input.put("communicationEventTypeId", "EMAIL_COMMUNICATION"); // this also needs to be specified to force the ECA that sends email to pass its conditions
174
input.put("datetimeEnded", UtilDateTime.nowTimestamp());
175                 serviceResults = dispatcher.runSync("updateCommunicationEvent", input);
176                 if (ServiceUtil.isError(serviceResults)) {
177                     return UtilCommon.createAndLogServiceError(serviceResults, errorLabel, locale, module);
178                 }
179
180                 // now update or create a work effort to record this email as a completed task
181
input = UtilMisc.toMap("workEffortTypeId", "TASK", "currentStatusId", "TASK_COMPLETED", "userLogin", userLogin);
182                 if (existing) input.put("workEffortId", workEffortId);
183                 input.put("actualStartDate", context.get("datetimeStarted"));
184                 input.put("actualCompletionDate", UtilDateTime.nowTimestamp());
185                 input.put("workEffortName", context.get("subject"));
186                 input.put("workEffortPurposeTypeId", "WEPT_TASK_EMAIL");
187                 serviceName = (existing ? "updateWorkEffort" : "createWorkEffort");
188                 serviceResults = dispatcher.runSync(serviceName, input);
189                 if (ServiceUtil.isError(serviceResults)) {
190                     return UtilCommon.createAndLogServiceError(serviceResults, errorLabel, locale, module);
191                 }
192             } else {
193                 // Create or update a scheduled (TASK_STARTED) TASK WorkEffort to save this email
194
input = UtilMisc.toMap("workEffortTypeId", "TASK", "currentStatusId", "TASK_STARTED", "userLogin", userLogin);
195                 if (existing) input.put("workEffortId", workEffortId);
196                 input.put("actualStartDate", context.get("datetimeStarted"));
197                 input.put("workEffortName", context.get("subject"));
198                 input.put("workEffortPurposeTypeId", "WEPT_TASK_EMAIL");
199                 serviceResults = dispatcher.runSync(existing ? "updateWorkEffort" : "createWorkEffort", input);
200                 if (ServiceUtil.isError(serviceResults)) {
201                     return UtilCommon.createAndLogServiceError(serviceResults, errorLabel, locale, module);
202                 }
203             }
204
205             // get the work effort ID from the serviceResults if a workEffort was created (note that the last service run in this case is always createWorkEffort)
206
if (!existing) workEffortId = (String JavaDoc) serviceResults.get("workEffortId");
207
208             // create an association between the task and comm event (safe even if existing)
209
input = UtilMisc.toMap("userLogin", userLogin, "communicationEventId", communicationEventId, "workEffortId", workEffortId);
210             serviceResults = dispatcher.runSync("createCommunicationEventWorkEff", input);
211             if (ServiceUtil.isError(serviceResults)) {
212                 return UtilCommon.createAndLogServiceError(serviceResults, errorLabel, locale, module);
213             }
214
215             // we need to zap all associations now if there are any previously saved ones
216
if (existing) {
217                 UtilActivity.removeAllAssociationsForWorkEffort(workEffortId, delegator);
218             }
219
220             // create the associations and finish
221
return createWorkEffortPartyAssociations(dctx, context, workEffortId, errorLabel, !existing);
222
223         } catch (GenericEntityException e) {
224             return UtilCommon.createAndLogServiceError(e, errorLabel, locale, module);
225         } catch (GenericServiceException e) {
226             return UtilCommon.createAndLogServiceError(e, errorLabel, locale, module);
227         }
228     }
229     
230     /**
231      * If the party is a member of the team, then Creates a Work Effort, associates it with the Communication Event,
232      * and assigns it to the Party with Work Effort
233      */

234     private static void associateCommunicationEventWorkEffortAndParty(String JavaDoc partyIdTo, GenericValue communicationEvent, GenericDelegator delegator, LocalDispatcher dispatcher, GenericValue userLogin, Locale JavaDoc locale, DispatchContext dctx, Map JavaDoc context)
235                    throws GenericEntityException, GenericServiceException {
236         // create an association between the WorkEffort and the CommunicationEvent using the partyIdTo field provided
237
// partyIdTo is not null and the party has a CRM/SFA team member role (ie, is a CRM/SFA user)
238
if(partyIdTo != null) {
239             String JavaDoc roleTypeId = PartyHelper.getFirstValidTeamMemberRoleTypeId(partyIdTo, delegator);
240
241             if (roleTypeId != null) {
242                 Map JavaDoc serviceResults = null;
243                 Map JavaDoc input = null;
244                 String JavaDoc communicationEventId = communicationEvent.getString("communicationEventId");
245                 
246                 //Create Workeffort from CommunicationEvent with task status as scheduled (TASK_SCHEDULED) instead of complete (TASK_COMPLETED)
247
//so that it shows up in Pending Activities rather than Activities History
248
input = UtilMisc.toMap("workEffortTypeId", "TASK", "currentStatusId", "TASK_SCHEDULED", "userLogin", userLogin);
249                 input.put("actualStartDate", communicationEvent.getTimestamp("datetimeStarted"));
250                 input.put("actualCompletionDate", communicationEvent.getTimestamp("datetimeEnded"));
251                 input.put("workEffortName", communicationEvent.getString("subject"));
252                 input.put("workEffortPurposeTypeId", "WEPT_TASK_EMAIL");
253                 serviceResults = dispatcher.runSync("createWorkEffort", input);
254                 if (ServiceUtil.isError(serviceResults)) {
255                     Debug.logError(ServiceUtil.getErrorMessage(serviceResults), module);
256                     throw new GenericServiceException(ServiceUtil.getErrorMessage(serviceResults));
257                 }
258                 
259                 //get the work effort ID from the serviceResults
260
String JavaDoc workEffortId = (String JavaDoc) serviceResults.get("workEffortId");
261                 
262                 //create an association between the task and comm event
263
input = UtilMisc.toMap("userLogin", userLogin, "communicationEventId", communicationEventId, "workEffortId", workEffortId);
264                 serviceResults = dispatcher.runSync("createCommunicationEventWorkEff", input);
265                 if (ServiceUtil.isError(serviceResults)) {
266                     Debug.logError(ServiceUtil.getErrorMessage(serviceResults), module);
267                     throw new GenericServiceException(ServiceUtil.getErrorMessage(serviceResults));
268                 }
269                 
270                 //create an association between the WorkEffort and the CommunicationEvent using the partyIdFrom field
271
context.put("internalPartyId", communicationEvent.getString("partyIdFrom"));
272                 createWorkEffortPartyAssociations(dctx, context, workEffortId, "CrmErrorProcessIncomingEmailFail", false);
273                 input = UtilMisc.toMap("partyId", partyIdTo, "workEffortId", workEffortId, "roleTypeId", roleTypeId, "statusId", "PRTYASGN_ASSIGNED", "userLogin", userLogin);
274                 serviceResults = dispatcher.runSync("assignPartyToWorkEffort", input);
275                 if (ServiceUtil.isError(serviceResults)) {
276                     Debug.logError(ServiceUtil.getErrorMessage(serviceResults), module);
277                     throw new GenericServiceException(ServiceUtil.getErrorMessage(serviceResults));
278                 }
279             } else {
280                 Debug.logWarning("No valid team member roles found for partyId [" + partyIdTo + "], so no activities will be created for it", module);
281             }
282         }
283     }
284     
285     /**
286      * Calls the storeIncomingEmail service to process incoming emails
287      */

288     public static Map JavaDoc processIncomingEmail(DispatchContext dctx, Map JavaDoc context) {
289         GenericDelegator delegator = dctx.getDelegator();
290         LocalDispatcher dispatcher = dctx.getDispatcher();
291         GenericValue userLogin = (GenericValue) context.get("userLogin");
292         Locale JavaDoc locale = (Locale JavaDoc) context.get("locale");
293         MimeMessageWrapper wrapper = (MimeMessageWrapper) context.get("messageWrapper");
294         Map JavaDoc serviceResults = null;
295         Map JavaDoc input = null;
296         
297         try {
298             if (wrapper == null) {
299                 Debug.logError("Null message wrapper when trying to store email: " + wrapper.getMessage(), module);
300                 return ServiceUtil.returnError("Null message wrapper");
301             }
302             if (userLogin == null) {
303                 Debug.logWarning("Null userLogin in when trying to process incoming email, using system", module);
304                 userLogin = delegator.findByPrimaryKeyCache("UserLogin", UtilMisc.toMap("userLoginId", "system"));
305             }
306             
307             //Call storeIncomingEmail service
308
input = UtilMisc.toMap("messageWrapper", wrapper, "userLogin", userLogin);
309             serviceResults = dispatcher.runSync("storeIncomingEmail", input);
310             if (ServiceUtil.isError(serviceResults)) {
311                 return UtilCommon.createAndLogServiceError(serviceResults, "CrmErrorProcessIncomingEmailFail", locale, module);
312             }
313             
314             //Get communicationEventId
315
String JavaDoc communicationEventId = (String JavaDoc) serviceResults.get("communicationEventId");
316             
317             //Find CommunicationEvent from its Id
318
GenericValue communicationEvent = delegator.findByPrimaryKey("CommunicationEvent", UtilMisc.toMap("communicationEventId", communicationEventId));
319             
320             String JavaDoc partyIdTo = communicationEvent.getString("partyIdTo");
321             
322             //Associate partyIdTo of CommunicationEvent
323
associateCommunicationEventWorkEffortAndParty(partyIdTo, communicationEvent, delegator, dispatcher, userLogin, locale, dctx, context);
324             
325             //Associate partyIds of CommunicationEventRoles associated with the CommunicationEvent
326
List JavaDoc commEventRoles = delegator.findByAnd("CommunicationEventRole", UtilMisc.toMap("communicationEventId", communicationEventId));
327             Iterator JavaDoc itr = commEventRoles.iterator();
328             
329             while (itr.hasNext()) {
330                 GenericValue commEventRole = (GenericValue) itr.next();
331                 
332                 associateCommunicationEventWorkEffortAndParty(commEventRole.getString("partyId"), communicationEvent, delegator, dispatcher, userLogin, locale, dctx, context);
333             }
334         } catch (GenericEntityException e) {
335             return UtilCommon.createAndLogServiceError(e, "CrmErrorProcessIncomingEmailFail", locale, module);
336         } catch (GenericServiceException e) {
337             return UtilCommon.createAndLogServiceError(e, "CrmErrorProcessIncomingEmailFail", locale, module);
338         }
339         
340         return ServiceUtil.returnSuccess();
341     }
342
343     /*************************************************************************/
344     /* Create/Update Activities */
345     /*************************************************************************/
346     
347     public static Map JavaDoc createActivity(DispatchContext dctx, Map JavaDoc context) {
348         GenericDelegator delegator = dctx.getDelegator();
349         LocalDispatcher dispatcher = dctx.getDispatcher();
350         Security security = dctx.getSecurity();
351         GenericValue userLogin = (GenericValue) context.get("userLogin");
352         Locale JavaDoc locale = (Locale JavaDoc) context.get("locale");
353
354         try {
355             // get the estimated completion date from the duration
356
Timestamp JavaDoc estimatedStartDate = (Timestamp JavaDoc) context.get("estimatedStartDate");
357             Timestamp JavaDoc estimatedCompletionDate = UtilCommon.getEndTimestamp(estimatedStartDate, (String JavaDoc) context.get("duration"), locale);
358
359             // check for conflicts
360
String JavaDoc forceIfConflicts = (String JavaDoc) context.get("forceIfConflicts");
361             if (forceIfConflicts == null || forceIfConflicts.equals("N")) {
362                 List JavaDoc events = UtilActivity.getActivityConflicts(userLogin, estimatedStartDate, estimatedCompletionDate);
363                 if (events.size() > 0) {
364                     StringBuffer JavaDoc msg = new StringBuffer JavaDoc("You have one or more conflicting events during the specified time. ");
365                     msg.append("<a class=\"messageLink\" HREF=\"/crmsfa/control/myHome?calendarView=day&start=");
366                     msg.append(UtilDateTime.getDayStart(estimatedStartDate).getTime());
367                     msg.append("\">Click here to view them.</a>");
368                     return UtilCommon.createAndLogServiceError(msg.toString(), "CrmErrorCreateActivityFail", locale, module);
369                 }
370             }
371
372             // validate the associations
373
Map JavaDoc serviceResults = validateWorkEffortAssociations(dctx, context);
374             if (ServiceUtil.isError(serviceResults)) {
375                 return UtilCommon.createAndLogServiceError(serviceResults, "CrmErrorCreateActivityFail", locale, module);
376             }
377
378             // create the workeffort from the context data, which results in a workEffortId
379
ModelService service = dctx.getModelService("createWorkEffort");
380             Map JavaDoc input = service.makeValid(context, "IN");
381             input.put("estimatedCompletionDate", estimatedCompletionDate);
382             serviceResults = dispatcher.runSync("createWorkEffort", input);
383             if (ServiceUtil.isError(serviceResults)) {
384                 return UtilCommon.createAndLogServiceError(serviceResults, "CrmErrorCreateActivityFail", locale, module);
385             }
386             String JavaDoc workEffortId = (String JavaDoc) serviceResults.get("workEffortId");
387
388             // create the associations and finish
389
serviceResults = createWorkEffortPartyAssociations(dctx, context, workEffortId, "CrmErrorCreateActivityFail", true);
390             if (ServiceUtil.isError(serviceResults)) {
391                 return UtilCommon.createAndLogServiceError(serviceResults, "CrmErrorCreateActivityFail", locale, module);
392             }
393
394             Map JavaDoc results = ServiceUtil.returnSuccess();
395             results.put("workEffortId", workEffortId);
396             return results;
397         } catch (IllegalArgumentException JavaDoc e) {
398             return UtilCommon.createAndLogServiceError(e, "CrmErrorCreateActivityFail", locale, module);
399         } catch (GenericEntityException e) {
400             return UtilCommon.createAndLogServiceError(e, "CrmErrorCreateActivityFail", locale, module);
401         } catch (GenericServiceException e) {
402             return UtilCommon.createAndLogServiceError(e, "CrmErrorCreateActivityFail", locale, module);
403         }
404     }
405
406     public static Map JavaDoc updateActivity(DispatchContext dctx, Map JavaDoc context) {
407         GenericDelegator delegator = dctx.getDelegator();
408         LocalDispatcher dispatcher = dctx.getDispatcher();
409         Security security = dctx.getSecurity();
410         GenericValue userLogin = (GenericValue) context.get("userLogin");
411         Locale JavaDoc locale = (Locale JavaDoc) context.get("locale");
412
413         String JavaDoc workEffortId = (String JavaDoc) context.get("workEffortId");
414         try {
415             // check if userlogin can update this work effort
416
if (!CrmsfaSecurity.hasActivityPermission(security, "_UPDATE", userLogin, workEffortId)) {
417                 return UtilCommon.createAndLogServiceError("CrmErrorPermissionDenied", locale, module);
418             }
419
420             // get the estimated completion date from the duration
421
Timestamp JavaDoc estimatedStartDate = (Timestamp JavaDoc) context.get("estimatedStartDate");
422             Timestamp JavaDoc estimatedCompletionDate = UtilCommon.getEndTimestamp(estimatedStartDate, (String JavaDoc) context.get("duration"), locale);
423
424             // check for conflicts
425
String JavaDoc forceIfConflicts = (String JavaDoc) context.get("forceIfConflicts");
426             if (forceIfConflicts == null || forceIfConflicts.equals("N")) {
427                 List JavaDoc events = UtilActivity.getActivityConflicts(userLogin, estimatedStartDate, estimatedCompletionDate, workEffortId);
428                 if (events.size() > 0) {
429                     StringBuffer JavaDoc msg = new StringBuffer JavaDoc("You have one or more conflicting events during the specified time. ");
430                     msg.append("<a class=\"messageLink\" HREF=\"/crmsfa/control/myHome?calendarView=day&start=");
431                     msg.append(UtilDateTime.getDayStart(estimatedStartDate).getTime());
432                     msg.append("\">Click here to view them.</a>");
433                     return UtilCommon.createAndLogServiceError(msg.toString(), "CrmErrorCreateActivityFail", locale, module);
434                 }
435             }
436
437             // validate the associations
438
Map JavaDoc serviceResults = validateWorkEffortAssociations(dctx, context);
439             if (ServiceUtil.isError(serviceResults)) {
440                 return UtilCommon.createAndLogServiceError(serviceResults, "CrmErrorUpdateActivityFail", locale, module);
441             }
442
443             // update the workeffort from the context data
444
ModelService service = dctx.getModelService("updateWorkEffort");
445             Map JavaDoc input = service.makeValid(context, "IN");
446             input.put("estimatedCompletionDate", estimatedCompletionDate);
447             serviceResults = dispatcher.runSync("updateWorkEffort", input);
448             if (ServiceUtil.isError(serviceResults)) {
449                 return UtilCommon.createAndLogServiceError(serviceResults, "CrmErrorUpdateActivityFail", locale, module);
450             }
451
452             // delete existing associations
453
UtilActivity.removeAllAssociationsForWorkEffort(workEffortId, delegator);
454
455             // create the associations and finish
456
return createWorkEffortPartyAssociations(dctx, context, workEffortId, "CrmErrorUpdateActivityFail", false);
457
458         } catch (IllegalArgumentException JavaDoc e) {
459             return UtilCommon.createAndLogServiceError(e, "CrmErrorCreateActivityFail", locale, module);
460         } catch (GenericEntityException e) {
461             return UtilCommon.createAndLogServiceError(e, "CrmErrorUpdateActivityFail", locale, module);
462         } catch (GenericServiceException e) {
463             return UtilCommon.createAndLogServiceError(e, "CrmErrorUpdateActivityFail", locale, module);
464         }
465     }
466
467     public static Map JavaDoc updateActivityWithoutAssoc(DispatchContext dctx, Map JavaDoc context) {
468         GenericDelegator delegator = dctx.getDelegator();
469         LocalDispatcher dispatcher = dctx.getDispatcher();
470         Security security = dctx.getSecurity();
471         GenericValue userLogin = (GenericValue) context.get("userLogin");
472         Locale JavaDoc locale = (Locale JavaDoc) context.get("locale");
473
474         String JavaDoc workEffortId = (String JavaDoc) context.get("workEffortId");
475         try {
476             // check if userlogin can update this work effort
477
if (!CrmsfaSecurity.hasActivityPermission(security, "_UPDATE", userLogin, workEffortId)) {
478                 return UtilCommon.createAndLogServiceError("CrmErrorPermissionDenied", locale, module);
479             }
480             
481             // update the workeffort from the context data
482
ModelService service = dctx.getModelService("updateWorkEffort");
483             Map JavaDoc input = service.makeValid(context, "IN");
484             Map JavaDoc serviceResults = dispatcher.runSync("updateWorkEffort", input);
485             if (ServiceUtil.isError(serviceResults)) {
486                 return UtilCommon.createAndLogServiceError(serviceResults, "CrmErrorUpdateActivityFail", locale, module);
487             }
488             
489             return ServiceUtil.returnSuccess();
490         } catch (GenericServiceException e) {
491             return UtilCommon.createAndLogServiceError(e, "CrmErrorUpdateActivityFail", locale, module);
492         }
493     }
494     
495     /*
496      * Updates the status of the CommunicationEvents associated with a WorkEffort
497      * If WorkEffort status is started then change the status of related CommunicationEvents from entered to pending.
498      * If WorkEffort status is completed then change the status of related CommunicationEvents from pending to completed.
499      */

500     public static Map JavaDoc updateActivityCommEvent(DispatchContext dctx, Map JavaDoc context) {
501         GenericDelegator delegator = dctx.getDelegator();
502         LocalDispatcher dispatcher = dctx.getDispatcher();
503         Security security = dctx.getSecurity();
504         GenericValue userLogin = (GenericValue) context.get("userLogin");
505         Locale JavaDoc locale = (Locale JavaDoc) context.get("locale");
506
507         String JavaDoc workEffortId = (String JavaDoc) context.get("workEffortId");
508         Map JavaDoc input = null;
509         Map JavaDoc serviceResults = null;
510         try {
511             //Find WorkEffort from its Id
512
GenericValue workEffort = delegator.findByPrimaryKey("WorkEffort", UtilMisc.toMap("workEffortId", workEffortId));
513             
514             String JavaDoc workEffortStatus = workEffort.getString("currentStatusId");
515             
516             List JavaDoc commEvents = null;
517             /*
518              * If WorkEffort status is started then change the status of related CommunicationEvents from entered to pending.
519              * If WorkEffort status is completed then change the status of related CommunicationEvents from pending to completed.
520              */

521             if("TASK_STARTED".equals(workEffortStatus)) {
522                 commEvents = delegator.findByAnd("WorkEffortCommunicationEventView", UtilMisc.toMap("workEffortId", workEffortId, "statusId", "COM_ENTERED"));
523                 
524                 if (commEvents.size() == 0) {
525                     return ServiceUtil.returnSuccess();
526                 }
527                 for (Iterator JavaDoc iter = commEvents.iterator(); iter.hasNext(); ) {
528                     GenericValue commEvent = (GenericValue) iter.next();
529                     
530                     input = UtilMisc.toMap("communicationEventId", commEvent.getString("communicationEventId"), "statusId", "COM_PENDING", "userLogin", userLogin);
531                     serviceResults = dispatcher.runSync("updateCommunicationEvent", input);
532                     if (ServiceUtil.isError(serviceResults)) {
533                         return UtilCommon.createAndLogServiceError(serviceResults, "CrmErrorUpdateActivityCommEventFail", locale, module);
534                     }
535                 }
536             } else if("TASK_COMPLETED".equals(workEffortStatus)) {
537                 commEvents = delegator.findByAnd("WorkEffortCommunicationEventView", UtilMisc.toMap("workEffortId", workEffortId, "statusId", "COM_PENDING"));
538                 
539                 if (commEvents.size() == 0) {
540                     return ServiceUtil.returnSuccess();
541                 }
542                 for (Iterator JavaDoc iter = commEvents.iterator(); iter.hasNext(); ) {
543                     GenericValue commEvent = (GenericValue) iter.next();
544                     
545                     input = UtilMisc.toMap("communicationEventId", commEvent.getString("communicationEventId"), "statusId", "COM_COMPLETE", "userLogin", userLogin);
546                     serviceResults = dispatcher.runSync("updateCommunicationEvent", input);
547                     if (ServiceUtil.isError(serviceResults)) {
548                         return UtilCommon.createAndLogServiceError(serviceResults, "CrmErrorUpdateActivityCommEventFail", locale, module);
549                     }
550                 }
551             }
552             
553             return ServiceUtil.returnSuccess();
554         } catch (GenericEntityException e) {
555             return UtilCommon.createAndLogServiceError(e, "CrmErrorUpdateActivityCommEventFail", locale, module);
556         } catch (GenericServiceException e) {
557             return UtilCommon.createAndLogServiceError(e, "CrmErrorUpdateActivityCommEventFail", locale, module);
558         }
559     }
560     
561     public static Map JavaDoc logTask(DispatchContext dctx, Map JavaDoc context) {
562         GenericDelegator delegator = dctx.getDelegator();
563         LocalDispatcher dispatcher = dctx.getDispatcher();
564         Security security = dctx.getSecurity();
565         GenericValue userLogin = (GenericValue) context.get("userLogin");
566         Locale JavaDoc locale = (Locale JavaDoc) context.get("locale");
567         String JavaDoc workEffortPurposeTypeId = (String JavaDoc) context.get("workEffortPurposeTypeId");
568         
569         try {
570             // get the actual completion date from the duration (default to now and 1 hour)
571
Timestamp JavaDoc actualStartDate = (Timestamp JavaDoc) context.get("actualStartDate");
572             if (actualStartDate == null) actualStartDate = UtilDateTime.nowTimestamp();
573             Timestamp JavaDoc actualCompletionDate = UtilCommon.getEndTimestamp(actualStartDate, (String JavaDoc) context.get("duration"), locale);
574
575             // validate the associations
576
Map JavaDoc serviceResults = validateWorkEffortAssociations(dctx, context);
577             if (ServiceUtil.isError(serviceResults)) {
578                 return UtilCommon.createAndLogServiceError(serviceResults, "CrmErrorLogTaskFail", locale, module);
579             }
580
581             //input.put("partyIdFrom", context.get("fromPartyId"));
582
//input.put("roleTypeIdFrom", PartyHelper.getFirstValidRoleTypeId((String) context.get("partyId"), PartyHelper.TEAM_MEMBER_ROLES, delegator));
583

584             // create the workeffort from the context data, which results in a workEffortId
585
ModelService service = dctx.getModelService("createWorkEffort");
586             Map JavaDoc input = service.makeValid(context, "IN");
587             input.put("actualCompletionDate", actualCompletionDate);
588             input.put("workEffortTypeId", "TASK");
589             input.put("currentStatusId", "TASK_COMPLETED");
590             serviceResults = dispatcher.runSync("createWorkEffort", input);
591             if (ServiceUtil.isError(serviceResults)) {
592                 return UtilCommon.createAndLogServiceError(serviceResults, "CrmErrorLogTaskFail", locale, module);
593             }
594             String JavaDoc workEffortId = (String JavaDoc) serviceResults.get("workEffortId");
595
596             // create the associations
597
serviceResults = createWorkEffortPartyAssociations(dctx, context, workEffortId, "CrmErrorLogTaskFail", true);
598             if (ServiceUtil.isError(serviceResults)) {
599                 return UtilCommon.createAndLogServiceError(serviceResults, "CrmErrorLogTaskFail", locale, module);
600             }
601
602             // assumne inbound
603
boolean outbound = false;
604             String JavaDoc partyIdTo = userLogin.getString("partyId");
605             String JavaDoc partyIdFrom = (String JavaDoc) context.get("internalPartyId");
606
607             // then change if it's actually outbound
608
if (context.get("outbound").equals("Y")) {
609                 outbound = true;
610                 partyIdTo = (String JavaDoc) context.get("internalPartyId");
611                 partyIdFrom = userLogin.getString("partyId");
612             }
613
614             // create a completed comm event with as much information as we have
615
service = dctx.getModelService("createCommunicationEvent");
616             input = service.makeValid(context, "IN");
617             input.put("subject", context.get("workEffortName"));
618             input.put("entryDate", UtilDateTime.nowTimestamp());
619             input.put("datetimeStarted", actualStartDate);
620             input.put("datetimeEnded", actualCompletionDate);
621             if ("WEPT_TASK_EMAIL".equals(workEffortPurposeTypeId)) {
622                 input.put("contactMechTypeId", "EMAIL_ADDRESS");
623                 input.put("communicationEventTypeId", "EMAIL_COMMUNICATION");
624             } else if ("WEPT_TASK_PHONE_CALL".equals(workEffortPurposeTypeId)) {
625                 input.put("contactMechTypeId", "TELECOM_NUMBER");
626                 input.put("communicationEventTypeId", "PHONE_COMMUNICATION");
627             } else {
628                 Debug.logWarning("Work effort purpose type [" + workEffortPurposeTypeId + "] not known, not able to set communication event and contact mech types", module);
629             }
630             input.put("statusId", "COM_COMPLETE");
631             input.put("partyIdTo", partyIdTo);
632             input.put("partyIdFrom", partyIdFrom);
633             if (outbound) {
634                 if (partyIdTo != null) input.put("roleTypeIdTo", PartyHelper.getFirstValidInternalPartyRoleTypeId(partyIdTo, delegator));
635                 input.put("roleTypeIdFrom", PartyHelper.getFirstValidTeamMemberRoleTypeId(partyIdFrom, delegator));
636             } else {
637                 if (partyIdFrom != null) input.put("roleTypeIdFrom", PartyHelper.getFirstValidInternalPartyRoleTypeId(partyIdFrom, delegator));
638                 input.put("roleTypeIdTo", PartyHelper.getFirstValidTeamMemberRoleTypeId(partyIdTo, delegator));
639             }
640             serviceResults = dispatcher.runSync("createCommunicationEvent", input);
641             if (ServiceUtil.isError(serviceResults)) {
642                 return UtilCommon.createAndLogServiceError(serviceResults, "CrmErrorLogTaskFail", locale, module);
643             }
644             String JavaDoc communicationEventId = (String JavaDoc) serviceResults.get("communicationEventId");
645
646             // create an association between the task and comm event (safe even if existing)
647
input = UtilMisc.toMap("userLogin", userLogin, "communicationEventId", communicationEventId, "workEffortId", workEffortId);
648             serviceResults = dispatcher.runSync("createCommunicationEventWorkEff", input);
649             if (ServiceUtil.isError(serviceResults)) {
650                 return UtilCommon.createAndLogServiceError(serviceResults, "CrmErrorLogTaskFail", locale, module);
651             }
652
653             Map JavaDoc results = ServiceUtil.returnSuccess();
654             results.put("workEffortId", workEffortId);
655             return results;
656         } catch (IllegalArgumentException JavaDoc e) {
657             return UtilCommon.createAndLogServiceError(e, "CrmErrorLogTaskFail", locale, module);
658         } catch (GenericEntityException e) {
659             return UtilCommon.createAndLogServiceError(e, "CrmErrorLogTaskFail", locale, module);
660         } catch (GenericServiceException e) {
661             return UtilCommon.createAndLogServiceError(e, "CrmErrorLogTaskFail", locale, module);
662         }
663     }
664
665     /*************************************************************************/
666     /* WorkEffortPartyAssignment Services */
667     /*************************************************************************/
668
669     public static Map JavaDoc addWorkEffortPartyAssignment(DispatchContext dctx, Map JavaDoc context) {
670         GenericDelegator delegator = dctx.getDelegator();
671         LocalDispatcher dispatcher = dctx.getDispatcher();
672         Security security = dctx.getSecurity();
673         GenericValue userLogin = (GenericValue) context.get("userLogin");
674         Locale JavaDoc locale = (Locale JavaDoc) context.get("locale");
675
676         String JavaDoc workEffortId = (String JavaDoc) context.get("workEffortId");
677         String JavaDoc partyId = (String JavaDoc) context.get("partyId");
678         try {
679             // check if userlogin can update this work effort
680
if (!CrmsfaSecurity.hasActivityPermission(security, "_UPDATE", userLogin, workEffortId)) {
681                 return UtilCommon.createAndLogServiceError("CrmErrorPermissionDenied", locale, module);
682             }
683
684             // if an unexpired existing relationship exists, then skip (this is to avoid duplicates)
685
List JavaDoc oldAssocs = EntityUtil.filterByDate(delegator.findByAnd("WorkEffortPartyAssignment",
686                         UtilMisc.toMap("workEffortId", workEffortId, "partyId", partyId)));
687             if (oldAssocs.size() == 0) {
688
689                 // assign party as a CAL_ATTENDEE with status assigned to the work effort
690
Map JavaDoc input = UtilMisc.toMap("workEffortId", workEffortId, "partyId", partyId, "roleTypeId", "CAL_ATTENDEE", "statusId", "PRTYASGN_ASSIGNED",
691                         "availabilityStatusId", "WEPA_AV_AVAILABLE");
692                 input.put("userLogin", userLogin);
693                 Map JavaDoc serviceResults = dispatcher.runSync("assignPartyToWorkEffort", input);
694                 if (ServiceUtil.isError(serviceResults)) {
695                     return UtilCommon.createAndLogServiceError(serviceResults, "CrmErrorUpdateActivityFail", locale, module);
696                 }
697             }
698         } catch (GenericEntityException e) {
699             return UtilCommon.createAndLogServiceError(e, "CrmErrorUpdateActivityFail", locale, module);
700         } catch (GenericServiceException e) {
701             return UtilCommon.createAndLogServiceError(e, "CrmErrorUpdateActivityFail", locale, module);
702         }
703         return ServiceUtil.returnSuccess();
704     }
705
706     public static Map JavaDoc removeWorkEffortPartyAssignment(DispatchContext dctx, Map JavaDoc context) {
707         GenericDelegator delegator = dctx.getDelegator();
708         LocalDispatcher dispatcher = dctx.getDispatcher();
709         Security security = dctx.getSecurity();
710         GenericValue userLogin = (GenericValue) context.get("userLogin");
711         Locale JavaDoc locale = (Locale JavaDoc) context.get("locale");
712
713         String JavaDoc workEffortId = (String JavaDoc) context.get("workEffortId");
714         String JavaDoc partyId = (String JavaDoc) context.get("partyId");
715         try {
716             // check if userlogin can update this work effort
717
if (!CrmsfaSecurity.hasActivityPermission(security, "_UPDATE", userLogin, workEffortId)) {
718                 return UtilCommon.createAndLogServiceError("CrmErrorPermissionDenied", locale, module);
719             }
720
721             // remove by hand because service in work effort uses fromDate as a required field
722
List JavaDoc associations = EntityUtil.filterByDate(delegator.findByAnd("WorkEffortPartyAssignment",
723                         UtilMisc.toMap("workEffortId", workEffortId, "partyId", partyId, "roleTypeId", "CAL_ATTENDEE")));
724             if (associations.size() == 0) {
725                 return UtilCommon.createAndLogServiceError("Cannot remove party with ID [" + partyId + "]", "CrmErrorUpdateActivityFail", locale, module);
726             }
727             for (Iterator JavaDoc iter = associations.iterator(); iter.hasNext(); ) {
728                 GenericValue assoc = (GenericValue) iter.next();
729                 assoc.set("thruDate", UtilDateTime.nowTimestamp());
730                 assoc.store();
731             }
732         } catch (GenericEntityException e) {
733             return UtilCommon.createAndLogServiceError(e, "CrmErrorUpdateActivityFail", locale, module);
734         }
735         return ServiceUtil.returnSuccess();
736     }
737
738     public static Map JavaDoc updateWorkEffortPartyAssignment(DispatchContext dctx, Map JavaDoc context) {
739         GenericDelegator delegator = dctx.getDelegator();
740         LocalDispatcher dispatcher = dctx.getDispatcher();
741         Security security = dctx.getSecurity();
742         GenericValue userLogin = (GenericValue) context.get("userLogin");
743         Locale JavaDoc locale = (Locale JavaDoc) context.get("locale");
744
745         String JavaDoc workEffortId = (String JavaDoc) context.get("workEffortId");
746         String JavaDoc partyId = (String JavaDoc) context.get("partyId");
747         try {
748             // check if userlogin can update this work effort
749
if (!CrmsfaSecurity.hasActivityPermission(security, "_UPDATE", userLogin, workEffortId)) {
750                 return UtilCommon.createAndLogServiceError("CrmErrorPermissionDenied", locale, module);
751             }
752
753             // TODO: done by hand because work effort service requires a permission that's not been added to crmsfa
754
List JavaDoc associations = EntityUtil.filterByDate(delegator.findByAnd("WorkEffortPartyAssignment",
755                         UtilMisc.toMap("workEffortId", workEffortId, "partyId", partyId)));
756             if (associations.size() > 0) {
757                 GenericValue assoc = (GenericValue) associations.get(0);
758                 // input context, don't overwrite if context has null or empty, no name prefixes, set both pks and non-pks
759
assoc.setAllFields(context, false, null, null);
760                 assoc.store();
761             }
762         } catch (GenericEntityException e) {
763             return UtilCommon.createAndLogServiceError(e, "CrmErrorUpdateActivityFail", locale, module);
764         }
765         return ServiceUtil.returnSuccess();
766     }
767
768     /*************************************************************************/
769     /* Find Activities */
770     /*************************************************************************/
771
772     public static Map JavaDoc findActivities(DispatchContext dctx, Map JavaDoc context) {
773         GenericDelegator delegator = dctx.getDelegator();
774         LocalDispatcher dispatcher = dctx.getDispatcher();
775         Locale JavaDoc locale = (Locale JavaDoc) context.get("locale");
776         String JavaDoc partyId = (String JavaDoc) context.get("partyId");
777         String JavaDoc salesOpportunityId = (String JavaDoc) context.get("salesOpportunityId");
778         String JavaDoc custRequestId = (String JavaDoc) context.get("custRequestId");
779         List JavaDoc pendingOrderByFields = (List JavaDoc) context.get("pendingOrderByFields");
780         List JavaDoc completedOrderByFields = (List JavaDoc) context.get("completedOrderByFields");
781         
782         Map JavaDoc results = ServiceUtil.returnSuccess();
783         
784         // determine which entity to search and the key relationship for searching it
785
String JavaDoc entityName = null;
786         EntityExpr keyCondition = null;
787         
788         if ((partyId != null) && !(partyId.equals(""))) {
789             entityName = "WorkEffortAndPartyAssign";
790             keyCondition = new EntityExpr("partyId", EntityOperator.EQUALS, partyId);
791         } else if ((salesOpportunityId != null) && !(salesOpportunityId.equals(""))) {
792             entityName = "WorkEffortAndSalesOpportunity";
793             keyCondition = new EntityExpr("salesOpportunityId", EntityOperator.EQUALS, salesOpportunityId);
794         } else if ((custRequestId != null) && !(custRequestId.equals(""))) {
795             entityName = "WorkEffortCustRequestView";
796             keyCondition = new EntityExpr("custRequestId", EntityOperator.EQUALS, custRequestId);
797         }
798         
799         if ((entityName == null) || (keyCondition == null)) {
800             return UtilCommon.createAndLogServiceError("No parameters specified for crmsfa.findActivities", "CrmErrorFindActivitiesFail", locale, module);
801         }
802         
803         try {
804             List JavaDoc fieldsToSelect = UtilMisc.toList("workEffortId", "workEffortTypeId", "workEffortName", "currentStatusId", "estimatedStartDate", "estimatedCompletionDate");
805             fieldsToSelect.add("workEffortPurposeTypeId");
806             fieldsToSelect.add("actualStartDate");
807             fieldsToSelect.add("actualCompletionDate");
808             
809             List JavaDoc pendingActivitiesCondList = UtilMisc.toList(keyCondition);
810             for (Iterator JavaDoc iter = UtilActivity.ACT_STATUSES_COMPLETED.iterator(); iter.hasNext(); ) {
811                 pendingActivitiesCondList.add(new EntityExpr("currentStatusId", EntityOperator.NOT_EQUAL, (String JavaDoc) iter.next()));
812             }
813             if (entityName.equals("WorkEffortAndPartyAssign")) {
814                 pendingActivitiesCondList.add(EntityUtil.getFilterByDateExpr());
815             }
816             EntityConditionList pendingActivitiesCond = new EntityConditionList(pendingActivitiesCondList, EntityOperator.AND);
817             List JavaDoc pendingActivities = delegator.findByCondition(entityName, pendingActivitiesCond, fieldsToSelect, pendingOrderByFields);
818             
819             List JavaDoc completedActivitiesCondList = UtilMisc.toList(keyCondition);
820             for (Iterator JavaDoc iter = UtilActivity.ACT_STATUSES_PENDING.iterator(); iter.hasNext(); ) {
821                 completedActivitiesCondList.add(new EntityExpr("currentStatusId", EntityOperator.NOT_EQUAL, (String JavaDoc) iter.next()));
822             }
823             if (entityName.equals("WorkEffortAndPartyAssign")) {
824                 completedActivitiesCondList.add(EntityUtil.getFilterByDateExpr());
825             }
826             EntityConditionList completedActivitiesCond = new EntityConditionList(completedActivitiesCondList, EntityOperator.AND);
827             List JavaDoc completedActivities = delegator.findByCondition(entityName, completedActivitiesCond, fieldsToSelect, completedOrderByFields);
828             
829             results.put("pendingActivities", pendingActivities);
830             results.put("completedActivities", completedActivities);
831         } catch (GenericEntityException e) {
832             return UtilCommon.createAndLogServiceError(e, "CrmErrorFindActivitiesFail", locale, module);
833         }
834         return results;
835     }
836
837     /*************************************************************************/
838     /* Helper Methods */
839     /*************************************************************************/
840
841     /**
842      * Helper method to create WorkEffort associations for an internal party (account, contact or lead), a case and an opportunity.
843      * If you need to remove existing ones, use the method removeAllAssociationsForWorkEffort() first.
844      *
845      * @param reassign Whether the CAL_OWNER should be overwritten by the userLogin or not
846      * @return If an error occurs, returns service error which can be tested with ServiceUtil.isError(), otherwise a service success
847      */

848     private static Map JavaDoc createWorkEffortPartyAssociations(DispatchContext dctx, Map JavaDoc context, String JavaDoc workEffortId, String JavaDoc errorLabel, boolean reassign)
849         throws GenericEntityException, GenericServiceException {
850         GenericDelegator delegator = dctx.getDelegator();
851         LocalDispatcher dispatcher = dctx.getDispatcher();
852         GenericValue userLogin = (GenericValue) context.get("userLogin");
853         Locale JavaDoc locale = (Locale JavaDoc) context.get("locale");
854         Map JavaDoc input = null;
855         Map JavaDoc serviceResults = null;
856
857         // association IDs
858
String JavaDoc internalPartyId = (String JavaDoc) context.get("internalPartyId");
859         String JavaDoc salesOpportunityId = (String JavaDoc) context.get("salesOpportunityId");
860         String JavaDoc custRequestId = (String JavaDoc) context.get("custRequestId");
861
862         /*
863          * The first step is to collect all the ACCOUNT, CONTACT or PROSPECT parties that we should associate with the workEffort.
864          * This includes those ACCOUNTS and CONTACTS that are associated with the case or opportunity that was specified in the input.
865          * Then we find the first valid role type for each, which is required for the work effort association. If any of these parties
866          * has no valid role types, then a bad ID was passed in. This serves to validate the association input.
867          */

868         List JavaDoc partyAssociationIds = new ArrayList JavaDoc();
869         if (internalPartyId != null) partyAssociationIds.add(internalPartyId);
870         if (salesOpportunityId != null) {
871             partyAssociationIds.addAll(UtilOpportunity.getOpportunityAccountPartyIds(delegator, salesOpportunityId));
872             partyAssociationIds.addAll(UtilOpportunity.getOpportunityContactPartyIds(delegator, salesOpportunityId));
873         }
874         if (custRequestId != null) {
875             List JavaDoc parties = UtilCase.getCaseAccountsAndContacts(delegator, custRequestId);
876             for (Iterator JavaDoc iter = parties.iterator(); iter.hasNext(); ) {
877                 partyAssociationIds.add(((GenericValue) iter.next()).getString("partyId"));
878             }
879         }
880         // now get the roles
881
List JavaDoc partyAssocRoleTypeIds = new ArrayList JavaDoc();
882         for (Iterator JavaDoc iter = partyAssociationIds.iterator(); iter.hasNext(); ) {
883             String JavaDoc partyId = (String JavaDoc) iter.next();
884             String JavaDoc roleTypeId = PartyHelper.getFirstValidRoleTypeId(partyId, PartyHelper.CLIENT_PARTY_ROLES, delegator);
885             if (roleTypeId == null) {
886                 return UtilCommon.createAndLogServiceError("Unknown recepient, opportunity or case with ID [" + partyId + "].", errorLabel, locale, module);
887             }
888             partyAssocRoleTypeIds.add(roleTypeId);
889         }
890
891         /*
892          * The remaining task is to create the associations to work effort.
893          */

894
895         if (reassign) {
896             // expire all associations of type CAL_OWNER for this work effort
897
List JavaDoc oldOwners = EntityUtil.filterByDate(delegator.findByAnd("WorkEffortPartyAssignment", UtilMisc.toMap("workEffortId", workEffortId, "roleTypeId", "CAL_OWNER")));
898             for (Iterator JavaDoc iter = oldOwners.iterator(); iter.hasNext(); ) {
899                 GenericValue old = (GenericValue) iter.next();
900                 old.set("thruDate", UtilDateTime.nowTimestamp());
901                 old.store();
902             }
903
904             // first make sure the userlogin has a role CAL_OWNER
905
input = UtilMisc.toMap("partyId", userLogin.getString("partyId"), "roleTypeId", "CAL_OWNER");
906             List JavaDoc partyRoles = delegator.findByAnd("PartyRole", input);
907             if (partyRoles.size() == 0) {
908                 input.put("userLogin", userLogin);
909                 serviceResults = dispatcher.runSync("createPartyRole", input);
910                 if (ServiceUtil.isError(serviceResults)) {
911                     return UtilCommon.createAndLogServiceError(serviceResults, errorLabel, locale, module);
912                 }
913             }
914
915             // then create the assignment
916
input.put("workEffortId", workEffortId);
917             input.put("userLogin", userLogin);
918             input.put("roleTypeId", "CAL_OWNER");
919             input.put("statusId", "PRTYASGN_ASSIGNED");
920             input.put("availabilityStatusId", context.get("availabilityStatusId")); // add our availability status
921
serviceResults = dispatcher.runSync("assignPartyToWorkEffort", input);
922             if (ServiceUtil.isError(serviceResults)) {
923                 return UtilCommon.createAndLogServiceError(serviceResults, errorLabel, locale, module);
924             }
925         }
926
927         // associate the opportunity with the work effort
928
if (salesOpportunityId != null) {
929             input = UtilMisc.toMap("salesOpportunityId", salesOpportunityId, "workEffortId", workEffortId);
930             GenericValue map = delegator.findByPrimaryKey("SalesOpportunityWorkEffort", input);
931             if (map == null) {
932                 map = delegator.makeValue("SalesOpportunityWorkEffort", input);
933                 // TODO: created by hand because we don't have a service for this yet
934
map.create();
935             }
936         }
937
938         // associate the case with the work effort
939
if (custRequestId != null) {
940             serviceResults = dispatcher.runSync("createWorkEffortRequest",
941                     UtilMisc.toMap("workEffortId", workEffortId, "custRequestId", custRequestId, "userLogin", userLogin));
942             if (ServiceUtil.isError(serviceResults)) {
943                 return UtilCommon.createAndLogServiceError(serviceResults, errorLabel, locale, module);
944             }
945         }
946  
947         // now for each party association, assign the party and its role to the work effort
948
if (partyAssociationIds != null) {
949             Iterator JavaDoc roleIter = partyAssocRoleTypeIds.iterator();
950             Iterator JavaDoc partyIter = partyAssociationIds.iterator();
951             while (partyIter.hasNext()) {
952                 String JavaDoc partyId = (String JavaDoc) partyIter.next();
953                 String JavaDoc roleTypeId = (String JavaDoc) roleIter.next();
954
955                 // if an unexpired existing relationship exists, then skip (this is to avoid duplicates)
956
List JavaDoc oldAssocs = EntityUtil.filterByDate(delegator.findByAnd("WorkEffortPartyAssignment",
957                             UtilMisc.toMap("workEffortId", workEffortId, "roleTypeId", roleTypeId, "partyId", partyId)));
958                 if (oldAssocs.size() > 0) continue;
959
960                 // now create the new one
961
input = UtilMisc.toMap("workEffortId", workEffortId, "partyId", partyId, "roleTypeId", roleTypeId, "statusId", "PRTYASGN_ASSIGNED");
962                 input.put("userLogin", userLogin);
963                 serviceResults = dispatcher.runSync("assignPartyToWorkEffort", input);
964                 if (ServiceUtil.isError(serviceResults)) {
965                     return UtilCommon.createAndLogServiceError(serviceResults, errorLabel, locale, module);
966                 }
967             }
968         }
969         return ServiceUtil.returnSuccess();
970     }
971
972     /**
973      * Helper method to validate the work effort associations that will be created.
974      */

975     private static Map JavaDoc validateWorkEffortAssociations(DispatchContext dctx, Map JavaDoc context)
976         throws GenericEntityException, GenericServiceException {
977         GenericDelegator delegator = dctx.getDelegator();
978         GenericValue userLogin = (GenericValue) context.get("userLogin");
979         Security security = dctx.getSecurity();
980
981         // association IDs
982
String JavaDoc internalPartyId = (String JavaDoc) context.get("internalPartyId");
983         String JavaDoc salesOpportunityId = (String JavaDoc) context.get("salesOpportunityId");
984         String JavaDoc custRequestId = (String JavaDoc) context.get("custRequestId");
985
986         // if there's an internal party, check if we have update on that party
987
if (internalPartyId != null) {
988             String JavaDoc module = CrmsfaSecurity.getSecurityModuleOfInternalParty(internalPartyId, delegator);
989             if (!CrmsfaSecurity.hasPartyRelationSecurity(security, module, "_UPDATE", userLogin, internalPartyId)) {
990                 return ServiceUtil.returnError("Cannot perform this operation because you do not have permission to update the account, contact or lead with ID [" + internalPartyId + "]");
991             }
992         }
993
994         // if there's an opportunity, check if we can update it
995
if (salesOpportunityId != null) {
996             if (!CrmsfaSecurity.hasOpportunityPermission(security, "_UPDATE", userLogin, salesOpportunityId)) {
997                 return ServiceUtil.returnError("Cannot perform this operation because you do not have permission to update the opportunity with ID [" + salesOpportunityId + "]");
998             }
999         }
1000
1001        // if there's an opportunity, check if we can update it
1002
if (custRequestId != null) {
1003            if (!CrmsfaSecurity.hasCasePermission(security, "_UPDATE", userLogin, custRequestId)) {
1004                return ServiceUtil.returnError("Cannot perform this operation because you do not have permission to update the case with ID [" + custRequestId + "]");
1005            }
1006        }
1007
1008        // if we get here, all checks passed
1009
return ServiceUtil.returnSuccess();
1010    }
1011}
1012
Popular Tags