From 139b1e804028a676fbd4dbcf163b8feec5c3262e Mon Sep 17 00:00:00 2001 From: Elaine Tan Date: Tue, 9 Apr 2013 17:51:30 +0800 Subject: [PATCH] IDEMPIERE-840 Improvement to Request model class --- .../oracle/201304091740_IDEMPIERE-840.sql | 7 + .../postgresql/201304091740_IDEMPIERE-840.sql | 7 + .../base/event/RequestSendEMailEventData.java | 116 +++++ .../src/org/compiere/model/MRequest.java | 347 +------------- .../org/compiere/model/RequestValidator.java | 423 ++++++++++++++++++ 5 files changed, 567 insertions(+), 333 deletions(-) create mode 100644 migration/i1.0a-release/oracle/201304091740_IDEMPIERE-840.sql create mode 100644 migration/i1.0a-release/postgresql/201304091740_IDEMPIERE-840.sql create mode 100644 org.adempiere.base/src/org/adempiere/base/event/RequestSendEMailEventData.java create mode 100644 org.adempiere.base/src/org/compiere/model/RequestValidator.java diff --git a/migration/i1.0a-release/oracle/201304091740_IDEMPIERE-840.sql b/migration/i1.0a-release/oracle/201304091740_IDEMPIERE-840.sql new file mode 100644 index 0000000000..51f1695d26 --- /dev/null +++ b/migration/i1.0a-release/oracle/201304091740_IDEMPIERE-840.sql @@ -0,0 +1,7 @@ +-- Apr 8, 2013 3:19:13 PM SGT +-- IDEMPIERE-840 Improvement to Request model class +INSERT INTO AD_ModelValidator (SeqNo,AD_ModelValidator_ID,ModelValidationClass,EntityType,Name,AD_ModelValidator_UU,AD_Org_ID,Created,CreatedBy,Updated,UpdatedBy,IsActive,AD_Client_ID) VALUES (0,200003,'org.compiere.model.RequestValidator','D','Model Validator to Request','999ba600-0d71-4f82-bf24-1a7876efa389',0,TO_DATE('2013-04-08 15:19:11','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2013-04-08 15:19:11','YYYY-MM-DD HH24:MI:SS'),100,'Y',0) +; + +SELECT register_migration_script('201304091740_IDEMPIERE-840.sql') FROM dual +; \ No newline at end of file diff --git a/migration/i1.0a-release/postgresql/201304091740_IDEMPIERE-840.sql b/migration/i1.0a-release/postgresql/201304091740_IDEMPIERE-840.sql new file mode 100644 index 0000000000..27dedbeb9f --- /dev/null +++ b/migration/i1.0a-release/postgresql/201304091740_IDEMPIERE-840.sql @@ -0,0 +1,7 @@ +-- Apr 8, 2013 3:19:13 PM SGT +-- IDEMPIERE-840 Improvement to Request model class +INSERT INTO AD_ModelValidator (SeqNo,AD_ModelValidator_ID,ModelValidationClass,EntityType,Name,AD_ModelValidator_UU,AD_Org_ID,Created,CreatedBy,Updated,UpdatedBy,IsActive,AD_Client_ID) VALUES (0,200003,'org.compiere.model.RequestValidator','D','Model Validator to Request','999ba600-0d71-4f82-bf24-1a7876efa389',0,TO_TIMESTAMP('2013-04-08 15:19:11','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2013-04-08 15:19:11','YYYY-MM-DD HH24:MI:SS'),100,'Y',0) +; + +SELECT register_migration_script('201304091740_IDEMPIERE-840.sql') FROM dual +; \ No newline at end of file diff --git a/org.adempiere.base/src/org/adempiere/base/event/RequestSendEMailEventData.java b/org.adempiere.base/src/org/adempiere/base/event/RequestSendEMailEventData.java new file mode 100644 index 0000000000..e3e8f0806a --- /dev/null +++ b/org.adempiere.base/src/org/adempiere/base/event/RequestSendEMailEventData.java @@ -0,0 +1,116 @@ +/****************************************************************************** + * Copyright (C) 2013 Elaine Tan * + * Copyright (C) 2013 Trek Global + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ + +package org.adempiere.base.event; + +import java.io.File; + +import org.compiere.model.MClient; +import org.compiere.model.MUser; + +/** + * + * @author Elaine + * + */ +public class RequestSendEMailEventData +{ + private MClient client; + private MUser from; + private MUser to; + private String subject; + private String message; + private File attachment; + private int requestID; + private boolean isHtml; + + public RequestSendEMailEventData(MClient client, MUser from, MUser to, String subject, String message, File attachment, int requestID) { + this(client, from, to, subject, message, attachment, requestID, false); + } + + public RequestSendEMailEventData(MClient client, MUser from, MUser to, String subject, String message, File attachment, int requestID, boolean isHtml) { + setClient(client); + setFrom(from); + setTo(to); + setSubject(subject); + setMessage(message); + setAttachment(attachment); + setRequestID(requestID); + setHtml(isHtml); + } + + public MClient getClient() { + return client; + } + + public void setClient(MClient client) { + this.client = client; + } + + public MUser getFrom() { + return from; + } + + public void setFrom(MUser from) { + this.from = from; + } + + public MUser getTo() { + return to; + } + + public void setTo(MUser to) { + this.to = to; + } + + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public File getAttachment() { + return attachment; + } + + public void setAttachment(File attachment) { + this.attachment = attachment; + } + + public int getRequestID() { + return requestID; + } + + public void setRequestID(int requestID) { + this.requestID = requestID; + } + + public boolean isHtml() { + return isHtml; + } + + public void setHtml(boolean isHtml) { + this.isHtml = isHtml; + } +} diff --git a/org.adempiere.base/src/org/compiere/model/MRequest.java b/org.adempiere.base/src/org/compiere/model/MRequest.java index 433a7867be..1f39b11155 100644 --- a/org.adempiere.base/src/org/compiere/model/MRequest.java +++ b/org.adempiere.base/src/org/compiere/model/MRequest.java @@ -17,22 +17,15 @@ package org.compiere.model; import java.io.File; -import java.sql.PreparedStatement; import java.sql.ResultSet; -import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.List; import java.util.Properties; -import java.util.logging.Level; -import org.adempiere.exceptions.DBException; import org.compiere.util.CLogger; -import org.compiere.util.DB; import org.compiere.util.Env; -import org.compiere.util.Msg; import org.compiere.util.TimeUtil; -import static org.compiere.model.SystemIDs.*; /** * Request Model @@ -46,7 +39,7 @@ public class MRequest extends X_R_Request * */ private static final long serialVersionUID = -6049674214655497548L; - + /** * Get Request ID from mail text * @param mailText mail text @@ -83,6 +76,7 @@ public class MRequest extends X_R_Request private static final String TAG_START = "[Req#"; /** Request Tag End */ private static final String TAG_END = "#ID]"; + /************************************************************************** @@ -160,8 +154,6 @@ public class MRequest extends X_R_Request private MBPartner m_partner = null; /** User/Contact */ private MUser m_user = null; - /** List of EMail Notices */ - private StringBuffer m_emailTo = new StringBuffer(); /** Separator line */ public static final String SEPARATOR = @@ -790,143 +782,10 @@ public class MRequest extends X_R_Request // Importance / Priority setPriority(); - // New - if (newRecord) - return true; - - // Change Log - m_changed = false; - ArrayList sendInfo = new ArrayList(); - MRequestAction ra = new MRequestAction(this, false); - // - if (checkChange(ra, "R_RequestType_ID")) - sendInfo.add("R_RequestType_ID"); - if (checkChange(ra, "R_Group_ID")) - sendInfo.add("R_Group_ID"); - if (checkChange(ra, "R_Category_ID")) - sendInfo.add("R_Category_ID"); - if (checkChange(ra, "R_Status_ID")) - sendInfo.add("R_Status_ID"); - if (checkChange(ra, "R_Resolution_ID")) - sendInfo.add("R_Resolution_ID"); - // - if (checkChange(ra, "SalesRep_ID")) - { - // Sender - int AD_User_ID = Env.getContextAsInt(p_ctx, "#AD_User_ID"); - if (AD_User_ID == 0) - AD_User_ID = getUpdatedBy(); - // Old - Object oo = get_ValueOld("SalesRep_ID"); - int oldSalesRep_ID = 0; - if (oo instanceof Integer) - oldSalesRep_ID = ((Integer)oo).intValue(); - if (oldSalesRep_ID != 0) - { - // RequestActionTransfer - Request {0} was transfered by {1} from {2} to {3} - Object[] args = new Object[] {getDocumentNo(), - MUser.getNameOfUser(AD_User_ID), - MUser.getNameOfUser(oldSalesRep_ID), - MUser.getNameOfUser(getSalesRep_ID()) - }; - String msg = Msg.getMsg(getCtx(), "RequestActionTransfer", args); - addToResult(msg); - sendInfo.add("SalesRep_ID"); - } - } - checkChange(ra, "AD_Role_ID"); - // - checkChange(ra, "Priority"); - if (checkChange(ra, "PriorityUser")) - sendInfo.add("PriorityUser"); - if (checkChange(ra, "IsEscalated")) - sendInfo.add("IsEscalated"); - // - checkChange(ra, "ConfidentialType"); - checkChange(ra, "Summary"); - checkChange(ra, "IsSelfService"); - checkChange(ra, "C_BPartner_ID"); - checkChange(ra, "AD_User_ID"); - checkChange(ra, "C_Project_ID"); - checkChange(ra, "A_Asset_ID"); - checkChange(ra, "C_Order_ID"); - checkChange(ra, "C_Invoice_ID"); - checkChange(ra, "M_Product_ID"); - checkChange(ra, "C_Payment_ID"); - checkChange(ra, "M_InOut_ID"); - checkChange(ra, "M_RMA_ID"); - // checkChange(ra, "C_Campaign_ID"); - // checkChange(ra, "RequestAmt"); - checkChange(ra, "IsInvoiced"); - checkChange(ra, "C_Activity_ID"); - checkChange(ra, "DateNextAction"); - checkChange(ra, "M_ProductSpent_ID"); - checkChange(ra, "QtySpent"); - checkChange(ra, "QtyInvoiced"); - checkChange(ra, "StartDate"); - checkChange(ra, "CloseDate"); - checkChange(ra, "TaskStatus"); - checkChange(ra, "DateStartPlan"); - checkChange(ra, "DateCompletePlan"); - // - if (m_changed) - ra.saveEx(); - - // Current Info - MRequestUpdate update = new MRequestUpdate(this); - if (update.isNewInfo()) - update.saveEx(); - else - update = null; - // - m_emailTo = new StringBuffer(); - if (update != null || sendInfo.size() > 0) - { - // Note that calling the notifications from beforeSave is causing the - // new interested are not notified if the RV_RequestUpdates view changes - // this is, when changed the sales rep (solved in sendNotices) - // or when changed the request category or group or contact (unsolved - the old ones are notified) - sendNotices(sendInfo); - - // Update - setDateLastAction(getUpdated()); - setLastResult(getResult()); - setDueType(); - // Reset - setConfidentialTypeEntry (getConfidentialType()); - // setStartDate(null); //red1 - bug [ 1743159 ] Requests - Start Date is not retained. - setEndTime(null); - setR_StandardResponse_ID(0); - setR_MailText_ID(0); - setResult(null); - // globalqss - these fields must be cleared (waiting to open bug in sf) - // setM_ProductSpent_ID(0); - // setQtySpent(null); - // setQtyInvoiced(null); - } return true; } // beforeSave - /** - * Check for changes - * @param ra request action - * @param columnName column - * @return true if changes - */ - private boolean checkChange (MRequestAction ra, String columnName) - { - if (is_ValueChanged(columnName)) - { - Object value = get_ValueOld(columnName); - if (value == null) - ra.addNullColumn(columnName); - else - ra.set_ValueNoCheck(columnName, value); - m_changed = true; - return true; - } - return false; - } // checkChange + /** * Check the ability to send email. @@ -1000,10 +859,7 @@ public class MRequest extends X_R_Request MRequestUpdate update = new MRequestUpdate(this); update.saveEx(); } - // Initial Mail - if (newRecord) - sendNotices(new ArrayList()); - + // ChangeRequest - created in Request Processor if (getM_ChangeRequest_ID() != 0 && is_ValueChanged(COLUMNNAME_R_Group_ID)) // different ECN assignment? @@ -1032,9 +888,6 @@ public class MRequest extends X_R_Request } } - if (m_emailTo.length() > 0) - log.saveInfo ("RequestActionEMailOK", m_emailTo.toString()); - return success; } // afterSave @@ -1070,188 +923,6 @@ public class MRequest extends X_R_Request } // afterSaveTransfer */ - /** - * Send Update EMail/Notices - * @param list list of changes - */ - public void sendNotices(ArrayList list) - { - // Subject - String subject = Msg.translate(getCtx(), "R_Request_ID") - + " " + Msg.getMsg(getCtx(), "Updated") + ": " + getDocumentNo(); - // Message - StringBuilder message = new StringBuilder(); - // UpdatedBy: Joe - int UpdatedBy = Env.getAD_User_ID(getCtx()); - MUser from = MUser.get(getCtx(), UpdatedBy); - if (from != null) - message.append(Msg.translate(getCtx(), "UpdatedBy")).append(": ") - .append(from.getName()); - // LastAction/Created: ... - if (getDateLastAction() != null) - message.append("\n").append(Msg.translate(getCtx(), "DateLastAction")) - .append(": ").append(getDateLastAction()); - else - message.append("\n").append(Msg.translate(getCtx(), "Created")) - .append(": ").append(getCreated()); - // Changes - for (int i = 0; i < list.size(); i++) - { - String columnName = (String)list.get(i); - message.append("\n").append(Msg.getElement(getCtx(), columnName)) - .append(": ").append(get_DisplayValue(columnName, false)) - .append(" -> ").append(get_DisplayValue(columnName, true)); - } - // NextAction - if (getDateNextAction() != null) - message.append("\n").append(Msg.translate(getCtx(), "DateNextAction")) - .append(": ").append(getDateNextAction()); - message.append(SEPARATOR) - .append(getSummary()); - if (getResult() != null) - message.append("\n----------\n").append(getResult()); - message.append(getMailTrailer(null)); - File pdf = createPDF(); - if (log.isLoggable(Level.FINER)) log.finer(message.toString()); - - // Prepare sending Notice/Mail - MClient client = MClient.get(getCtx()); - // Reset from if external - if (from.getEMailUser() == null || from.getEMailUserPW() == null) - from = null; - int success = 0; - int failure = 0; - int notices = 0; - // - ArrayList userList = new ArrayList(); - final String sql = "SELECT u.AD_User_ID, u.NotificationType, u.EMail, u.Name, MAX(r.AD_Role_ID) " - + "FROM RV_RequestUpdates_Only ru" - + " INNER JOIN AD_User u ON (ru.AD_User_ID=u.AD_User_ID OR u.AD_User_ID=?)" - + " LEFT OUTER JOIN AD_User_Roles r ON (u.AD_User_ID=r.AD_User_ID) " - + "WHERE ru.R_Request_ID=? " - + "GROUP BY u.AD_User_ID, u.NotificationType, u.EMail, u.Name"; - PreparedStatement pstmt = null; - ResultSet rs = null; - try - { - pstmt = DB.prepareStatement (sql, get_TrxName()); - pstmt.setInt (1, getSalesRep_ID()); - pstmt.setInt (2, getR_Request_ID()); - rs = pstmt.executeQuery (); - while (rs.next ()) - { - int AD_User_ID = rs.getInt(1); - String NotificationType = rs.getString(2); - if (NotificationType == null) - NotificationType = X_AD_User.NOTIFICATIONTYPE_EMail; - String email = rs.getString(3); - String Name = rs.getString(4); - // Role - int AD_Role_ID = rs.getInt(5); - if (rs.wasNull()) - AD_Role_ID = -1; - - // Don't send mail to oneself - // if (AD_User_ID == UpdatedBy) - // continue; - - // No confidential to externals - if (AD_Role_ID == -1 - && (getConfidentialTypeEntry().equals(CONFIDENTIALTYPE_Internal) - || getConfidentialTypeEntry().equals(CONFIDENTIALTYPE_PrivateInformation))) - continue; - - if (X_AD_User.NOTIFICATIONTYPE_None.equals(NotificationType)) - { - if (log.isLoggable(Level.CONFIG)) log.config("Opt out: " + Name); - continue; - } - if ((X_AD_User.NOTIFICATIONTYPE_EMail.equals(NotificationType) - || X_AD_User.NOTIFICATIONTYPE_EMailPlusNotice.equals(NotificationType)) - && (email == null || email.length() == 0)) - { - if (AD_Role_ID >= 0) - NotificationType = X_AD_User.NOTIFICATIONTYPE_Notice; - else - { - if (log.isLoggable(Level.CONFIG)) log.config("No EMail: " + Name); - continue; - } - } - if (X_AD_User.NOTIFICATIONTYPE_Notice.equals(NotificationType) - && AD_Role_ID >= 0) - { - if (log.isLoggable(Level.CONFIG)) log.config("No internal User: " + Name); - continue; - } - - // Check duplicate receivers - Integer ii = new Integer (AD_User_ID); - if (userList.contains(ii)) - continue; - userList.add(ii); - // - MUser to = MUser.get (getCtx(), AD_User_ID); - // Send Mail - if (X_AD_User.NOTIFICATIONTYPE_EMail.equals(NotificationType) - || X_AD_User.NOTIFICATIONTYPE_EMailPlusNotice.equals(NotificationType)) - { - if (client.sendEMail(from, to, subject, message.toString(), pdf)) - { - success++; - if (m_emailTo.length() > 0) - m_emailTo.append(", "); - m_emailTo.append(to.getEMail()); - } - else - { - log.warning("Failed: " + Name); - failure++; - NotificationType = X_AD_User.NOTIFICATIONTYPE_Notice; - } - } - // Send Note - if (X_AD_User.NOTIFICATIONTYPE_Notice.equals(NotificationType) - || X_AD_User.NOTIFICATIONTYPE_EMailPlusNotice.equals(NotificationType)) - { - int AD_Message_ID = MESSAGE_REQUESTUPDATE; - MNote note = new MNote(getCtx(), AD_Message_ID, AD_User_ID, - X_R_Request.Table_ID, getR_Request_ID(), - subject, message.toString(), get_TrxName()); - if (note.save()) - notices++; - } - } - } - catch (SQLException e) - { - throw new DBException(e, sql); - } - finally - { - DB.close(rs, pstmt); - rs = null; pstmt = null; - } - if (log.isLoggable(Level.INFO)) log.info("EMail Success=" + success + ", Failure=" + failure - + " - Notices=" + notices); - } // sendNotice - - /************************************************************************** - * Get MailID - * @param serverAddress server address - * @return Mail Trailer - */ - public String getMailTrailer(String serverAddress) - { - StringBuffer sb = new StringBuffer("\n").append(SEPARATOR) - .append(Msg.translate(getCtx(), "R_Request_ID")) - .append(": ").append(getDocumentNo()) - .append(" ").append(getMailTag()) - .append("\nSent by AdempiereMail"); - if (serverAddress != null) - sb.append(" from ").append(serverAddress); - return sb.toString(); - } // getMailTrailer /** * Get Mail Tag @@ -1324,4 +995,14 @@ public class MRequest extends X_R_Request } } // doEscalate + public boolean isChanged() + { + return m_changed; + } + + public void setIsChanged(boolean changed) + { + this.m_changed = changed; + } + } // MRequest diff --git a/org.adempiere.base/src/org/compiere/model/RequestValidator.java b/org.adempiere.base/src/org/compiere/model/RequestValidator.java new file mode 100644 index 0000000000..a6a4ec19dd --- /dev/null +++ b/org.adempiere.base/src/org/compiere/model/RequestValidator.java @@ -0,0 +1,423 @@ +/****************************************************************************** + * Copyright (C) 2013 Elaine Tan * + * Copyright (C) 2013 Trek Global + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ + +package org.compiere.model; + +import static org.compiere.model.SystemIDs.MESSAGE_REQUESTUPDATE; + +import java.io.File; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.logging.Level; + +import org.adempiere.base.event.EventManager; +import org.adempiere.base.event.RequestSendEMailEventData; +import org.adempiere.exceptions.DBException; +import org.compiere.util.CLogger; +import org.compiere.util.DB; +import org.compiere.util.Env; +import org.compiere.util.Msg; +import org.osgi.service.event.Event; +import org.osgi.service.event.EventHandler; + +/** + * + * @author Elaine + * + */ +public class RequestValidator implements ModelValidator, EventHandler +{ + public static final String ON_REQUEST_SEND_EMAIL_TOPIC = "onRequestSendEMail"; + + private static CLogger s_log = CLogger.getCLogger (RequestValidator.class); + + private int m_AD_Client_ID; + + @Override + public void initialize(ModelValidationEngine engine, MClient client) + { + if (client != null) + m_AD_Client_ID = client.getAD_Client_ID(); + engine.addModelChange(I_R_Request.Table_Name, this); + + if (EventManager.getInstance() != null) + EventManager.getInstance().register(ON_REQUEST_SEND_EMAIL_TOPIC, this); + } + + @Override + public int getAD_Client_ID() + { + return m_AD_Client_ID; + } + + @Override + public String login(int AD_Org_ID, int AD_Role_ID, int AD_User_ID) + { + return null; + } + + @Override + public String modelChange(PO po, int type) throws Exception + { + if (po instanceof MRequest ) + { + MRequest r = (MRequest) po; + if (type == TYPE_BEFORE_NEW || type == TYPE_BEFORE_CHANGE) + beforeSaveRequest(r); + else if (type == TYPE_AFTER_NEW || type == TYPE_AFTER_CHANGE) + afterSaveRequest(r); + } + return null; + } + + @Override + public String docValidate(PO po, int timing) + { + return null; + } + + public static String beforeSaveRequest(MRequest r) + { + // New + if (r.is_new()) + return null; + + // Change Log + r.setIsChanged(false); + ArrayList sendInfo = new ArrayList(); + MRequestAction ra = new MRequestAction(r, false); + // + if (checkChange(r, ra, "R_RequestType_ID")) + sendInfo.add("R_RequestType_ID"); + if (checkChange(r, ra, "R_Group_ID")) + sendInfo.add("R_Group_ID"); + if (checkChange(r, ra, "R_Category_ID")) + sendInfo.add("R_Category_ID"); + if (checkChange(r, ra, "R_Status_ID")) + sendInfo.add("R_Status_ID"); + if (checkChange(r, ra, "R_Resolution_ID")) + sendInfo.add("R_Resolution_ID"); + // + if (checkChange(r, ra, "SalesRep_ID")) + { + // Sender + int AD_User_ID = Env.getContextAsInt(r.getCtx(), "#AD_User_ID"); + if (AD_User_ID == 0) + AD_User_ID = r.getUpdatedBy(); + // Old + Object oo = r.get_ValueOld("SalesRep_ID"); + int oldSalesRep_ID = 0; + if (oo instanceof Integer) + oldSalesRep_ID = ((Integer)oo).intValue(); + if (oldSalesRep_ID != 0) + { + // RequestActionTransfer - Request {0} was transfered by {1} from {2} to {3} + Object[] args = new Object[] {r.getDocumentNo(), + MUser.getNameOfUser(AD_User_ID), + MUser.getNameOfUser(oldSalesRep_ID), + MUser.getNameOfUser(r.getSalesRep_ID()) + }; + String msg = Msg.getMsg(r.getCtx(), "RequestActionTransfer", args); + r.addToResult(msg); + sendInfo.add("SalesRep_ID"); + } + } + checkChange(r, ra, "AD_Role_ID"); + // + checkChange(r, ra, "Priority"); + if (checkChange(r, ra, "PriorityUser")) + sendInfo.add("PriorityUser"); + if (checkChange(r, ra, "IsEscalated")) + sendInfo.add("IsEscalated"); + // + checkChange(r, ra, "ConfidentialType"); + checkChange(r, ra, "Summary"); + checkChange(r, ra, "IsSelfService"); + checkChange(r, ra, "C_BPartner_ID"); + checkChange(r, ra, "AD_User_ID"); + checkChange(r, ra, "C_Project_ID"); + checkChange(r, ra, "A_Asset_ID"); + checkChange(r, ra, "C_Order_ID"); + checkChange(r, ra, "C_Invoice_ID"); + checkChange(r, ra, "M_Product_ID"); + checkChange(r, ra, "C_Payment_ID"); + checkChange(r, ra, "M_InOut_ID"); + checkChange(r, ra, "M_RMA_ID"); + // checkChange(ra, "C_Campaign_ID"); + // checkChange(ra, "RequestAmt"); + checkChange(r, ra, "IsInvoiced"); + checkChange(r, ra, "C_Activity_ID"); + checkChange(r, ra, "DateNextAction"); + checkChange(r, ra, "M_ProductSpent_ID"); + checkChange(r, ra, "QtySpent"); + checkChange(r, ra, "QtyInvoiced"); + checkChange(r, ra, "StartDate"); + checkChange(r, ra, "CloseDate"); + checkChange(r, ra, "TaskStatus"); + checkChange(r, ra, "DateStartPlan"); + checkChange(r, ra, "DateCompletePlan"); + // + if (r.is_Changed()) + ra.saveEx(); + + // Current Info + MRequestUpdate update = new MRequestUpdate(r); + if (update.isNewInfo()) + update.saveEx(); + else + update = null; + // + if (update != null || sendInfo.size() > 0) + { + // Note that calling the notifications from beforeSave is causing the + // new interested are not notified if the RV_RequestUpdates view changes + // this is, when changed the sales rep (solved in sendNotices) + // or when changed the request category or group or contact (unsolved - the old ones are notified) + sendNotices(r, sendInfo); + + // Update + r.setDateLastAction(r.getUpdated()); + r.setLastResult(r.getResult()); + r.setDueType(); + // Reset + r.setConfidentialTypeEntry (r.getConfidentialType()); + // r.setStartDate(null); //red1 - bug [ 1743159 ] Requests - Start Date is not retained. + r.setEndTime(null); + r.setR_StandardResponse_ID(0); + r.setR_MailText_ID(0); + r.setResult(null); + // globalqss - these fields must be cleared (waiting to open bug in sf) + // r.setM_ProductSpent_ID(0); + // r.setQtySpent(null); + // r.setQtyInvoiced(null); + } + + return null; + } + + public static String afterSaveRequest(MRequest r) + { + // Initial Mail + if (r.is_new()) + sendNotices(r, new ArrayList()); + + return null; + } + + /** + * Check for changes + * @param ra request action + * @param columnName column + * @return true if changes + */ + public static boolean checkChange (MRequest r, MRequestAction ra, String columnName) + { + if (r.is_ValueChanged(columnName)) + { + Object value = r.get_ValueOld(columnName); + if (value == null) + ra.addNullColumn(columnName); + else + ra.set_ValueNoCheck(columnName, value); + r.setIsChanged(true); + return true; + } + return false; + } // checkChange + + /** + * Send Update EMail/Notices + * @param list list of changes + */ + public static void sendNotices(MRequest r, ArrayList list) + { + // Subject + String subject = Msg.translate(r.getCtx(), "R_Request_ID") + + " " + Msg.getMsg(r.getCtx(), "Updated") + ": " + r.getDocumentNo(); + // Message + StringBuilder message = new StringBuilder(); + // UpdatedBy: Joe + int UpdatedBy = Env.getAD_User_ID(r.getCtx()); + MUser from = MUser.get(r.getCtx(), UpdatedBy); + if (from != null) + message.append(Msg.translate(r.getCtx(), "UpdatedBy")).append(": ") + .append(from.getName()); + // LastAction/Created: ... + if (r.getDateLastAction() != null) + message.append("\n").append(Msg.translate(r.getCtx(), "DateLastAction")) + .append(": ").append(r.getDateLastAction()); + else + message.append("\n").append(Msg.translate(r.getCtx(), "Created")) + .append(": ").append(r.getCreated()); + // Changes + for (int i = 0; i < list.size(); i++) + { + String columnName = (String)list.get(i); + message.append("\n").append(Msg.getElement(r.getCtx(), columnName)) + .append(": ").append(r.get_DisplayValue(columnName, false)) + .append(" -> ").append(r.get_DisplayValue(columnName, true)); + } + // NextAction + if (r.getDateNextAction() != null) + message.append("\n").append(Msg.translate(r.getCtx(), "DateNextAction")) + .append(": ").append(r.getDateNextAction()); + message.append(MRequest.SEPARATOR) + .append(r.getSummary()); + if (r.getResult() != null) + message.append("\n----------\n").append(r.getResult()); + message.append(getMailTrailer(r, null)); + File pdf = r.createPDF(); + if (s_log.isLoggable(Level.FINER)) s_log.finer(message.toString()); + + // Prepare sending Notice/Mail + MClient client = MClient.get(r.getCtx()); + // Reset from if external + if (from.getEMailUser() == null || from.getEMailUserPW() == null) + from = null; + // + ArrayList userList = new ArrayList(); + final String sql = "SELECT u.AD_User_ID, u.NotificationType, u.EMail, u.Name, MAX(r.AD_Role_ID) " + + "FROM RV_RequestUpdates_Only ru" + + " INNER JOIN AD_User u ON (ru.AD_User_ID=u.AD_User_ID OR u.AD_User_ID=?)" + + " LEFT OUTER JOIN AD_User_Roles r ON (u.AD_User_ID=r.AD_User_ID) " + + "WHERE ru.R_Request_ID=? " + + "GROUP BY u.AD_User_ID, u.NotificationType, u.EMail, u.Name"; + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement (sql, r.get_TrxName()); + pstmt.setInt (1, r.getSalesRep_ID()); + pstmt.setInt (2, r.getR_Request_ID()); + rs = pstmt.executeQuery (); + while (rs.next ()) + { + int AD_User_ID = rs.getInt(1); + String NotificationType = rs.getString(2); + if (NotificationType == null) + NotificationType = X_AD_User.NOTIFICATIONTYPE_EMail; + String email = rs.getString(3); + String Name = rs.getString(4); + // Role + int AD_Role_ID = rs.getInt(5); + if (rs.wasNull()) + AD_Role_ID = -1; + + // Don't send mail to oneself + // if (AD_User_ID == UpdatedBy) + // continue; + + // No confidential to externals + if (AD_Role_ID == -1 + && (r.getConfidentialTypeEntry().equals(MRequest.CONFIDENTIALTYPE_Internal) + || r.getConfidentialTypeEntry().equals(MRequest.CONFIDENTIALTYPE_PrivateInformation))) + continue; + + if (X_AD_User.NOTIFICATIONTYPE_None.equals(NotificationType)) + { + if (s_log.isLoggable(Level.CONFIG)) s_log.config("Opt out: " + Name); + continue; + } + if ((X_AD_User.NOTIFICATIONTYPE_EMail.equals(NotificationType) + || X_AD_User.NOTIFICATIONTYPE_EMailPlusNotice.equals(NotificationType)) + && (email == null || email.length() == 0)) + { + if (AD_Role_ID >= 0) + NotificationType = X_AD_User.NOTIFICATIONTYPE_Notice; + else + { + if (s_log.isLoggable(Level.CONFIG)) s_log.config("No EMail: " + Name); + continue; + } + } + if (X_AD_User.NOTIFICATIONTYPE_Notice.equals(NotificationType) + && AD_Role_ID >= 0) + { + if (s_log.isLoggable(Level.CONFIG)) s_log.config("No internal User: " + Name); + continue; + } + + // Check duplicate receivers + Integer ii = new Integer (AD_User_ID); + if (userList.contains(ii)) + continue; + userList.add(ii); + // + MUser to = MUser.get (r.getCtx(), AD_User_ID); + // Send Mail + if (X_AD_User.NOTIFICATIONTYPE_EMail.equals(NotificationType) + || X_AD_User.NOTIFICATIONTYPE_EMailPlusNotice.equals(NotificationType)) + { + RequestSendEMailEventData eventData = new RequestSendEMailEventData(client, from, to, subject, message.toString(), pdf, r.getR_Request_ID()); + Event event = EventManager.newEvent(ON_REQUEST_SEND_EMAIL_TOPIC, eventData); + EventManager.getInstance().postEvent(event); + } + // Send Note + if (X_AD_User.NOTIFICATIONTYPE_Notice.equals(NotificationType) + || X_AD_User.NOTIFICATIONTYPE_EMailPlusNotice.equals(NotificationType)) + { + int AD_Message_ID = MESSAGE_REQUESTUPDATE; + MNote note = new MNote(r.getCtx(), AD_Message_ID, AD_User_ID, + X_R_Request.Table_ID, r.getR_Request_ID(), + subject, message.toString(), r.get_TrxName()); + note.save(); + } + } + } + catch (SQLException e) + { + throw new DBException(e, sql); + } + finally + { + DB.close(rs, pstmt); + rs = null; pstmt = null; + } + } // sendNotice + + /************************************************************************** + * Get MailID + * @param serverAddress server address + * @return Mail Trailer + */ + public static String getMailTrailer(MRequest r, String serverAddress) + { + StringBuffer sb = new StringBuffer("\n").append(MRequest.SEPARATOR) + .append(Msg.translate(r.getCtx(), "R_Request_ID")) + .append(": ").append(r.getDocumentNo()) + .append(" ").append(r.getMailTag()) + .append("\nSent by AdempiereMail"); + if (serverAddress != null) + sb.append(" from ").append(serverAddress); + return sb.toString(); + } // getMailTrailer + + @Override + public void handleEvent(Event event) { + if (event.getTopic() == ON_REQUEST_SEND_EMAIL_TOPIC) + { + RequestSendEMailEventData eventData = (RequestSendEMailEventData) event.getProperty(EventManager.EVENT_DATA); + if (!eventData.getClient().sendEMail(eventData.getFrom(), eventData.getTo(), eventData.getSubject(), eventData.getMessage(), eventData.getAttachment())) + { + int AD_Message_ID = MESSAGE_REQUESTUPDATE; + MNote note = new MNote(Env.getCtx(), AD_Message_ID, eventData.getTo().getAD_User_ID(), + X_R_Request.Table_ID, eventData.getRequestID(), + eventData.getSubject(), eventData.getMessage(), null); + note.save(); + } + } + } +}