Untitled
unknown
plain_text
9 months ago
35 kB
5
Indexable
/** * @author Ionut Boghean * @date 2016 * * @group Opportunity Object * @group-content * * @description Helper class for OpportunityHandler * * ----------------------------------------------------------------------------------------------------------------------------- * Ver. Date Who Description * 2023-02-01 david.sanchez@empaua.com Refactored code and replaced the use of a "fake" email to render the template with * the a call to Messaging.renderStoredEmailTemplate. * EMP-65 2023-02-02 david.sanchez@empaua.com Modified the way in which attachments are selected for Confirmation emails. * Now for Sent and Change confirmations an exclusion list is use (instead of an inclusion list). */ public without sharing class OpportunityHelper { public static Boolean isRecurringExecution = false; public static void checkActivePeriods(Map<Id, Opportunity> newMap, Map<Id, Opportunity> oldMap) { Opportunity oldRecord; Integer activeBookingPeriods = Database.CountQuery('SELECT COUNT() FROM BookingPeriod__c WHERE Active__c = true'); for(Opportunity newRecord :newMap.values()) { oldRecord = oldMap.get(newRecord.Id); if(newRecord.StageName != oldRecord.StageName && (newRecord.StageName == System.Label.OpportunityTransactionStageSent || newRecord.StageName == System.Label.OpportunityTransactionStageBookingCancelledWithFee || newRecord.StageName == System.Label.OpportunityTransactionStageBookingCancelledWithFeeErgoRRV || newRecord.StageName == System.Label.OpportunityTransactionStageBookingChanged ) && newRecord.Type == System.Label.OpportunityTransactionTypeBUC ) { newRecord.HasActiveBookingPeriod__c = (activeBookingPeriods == 1)? true : false; } } } /******************************************************************************************************* * @description Update opportunity related data when its cancelled without fee * @param newMap Updated Opportunity records * @param oldMap Old Opportunity records */ public static void doCancellationUpdates(Map<Id, Opportunity> newMap, Map<Id, Opportunity> oldMap) { Opportunity oldRecord; for(Opportunity newRecord :newMap.values()) { oldRecord = oldMap.get(newRecord.Id); if (newRecord.StageName != oldRecord.StageName && newRecord.Type == System.Label.OpportunityTransactionTypeBUC) { if (newRecord.StageName == System.Label.OpportunityTransactionStageBookingCancelledWithoutFee) { newRecord.AccountsReceivableEuro__c = 0; newRecord.AccountsReceivableLocalCurrency__c = 0; } else if (newRecord.StageName == System.Label.OpportunityTransactionStageBookingCancelledWithoutFeeErgoRRV) { newRecord.AccountsReceivableEuro__c = 0; newRecord.AccountsReceivableLocalCurrency__c = 0; } } } } /******************************************************************************************************* * @description Update opportunity's trustpilot invitation link * @param newMap Updated Opportunity records */ public static void updateTrustpilotInvitationLink(List<Opportunity> newOpportunities) { List<Opportunity> validOpportunities = new List<Opportunity>(); for (Opportunity oppty : newOpportunities) { if (!isRecurringExecution && String.isBlank(oppty.Trustpilot_Invitation_Link__c) ) { validOpportunities.add(oppty); } } if (!validOpportunities.isEmpty()) { System.enqueueJob(new CreateTrustpilotInvitationLink(validOpportunities)); } } /******************************************************************************************************* * @description Update opportunity email from the ac * @param newMap Updated Opportunity records */ public static void doEmailUpdates(Map<Id, Opportunity> newMap) { for(Opportunity opp : [select Id, Customer__c, Customer__r.PersonContactId, Customer__r.PersonEmail from Opportunity where id in :newMap.keySet()]) { if(opp.Customer__r.PersonEmail != null) { newMap.get(opp.Id).CustomerEmail__c = opp.Customer__r.PersonEmail; } } } /******************************************************************************************************* * @description Create booking history records * @param newMap New Opportunity records */ public static void createBookingHistory(Map<Id, Opportunity> newMap) { createBookingHistory(newMap,null); } /*----*/ public static void createBookingHistory(Map<Id, Opportunity> newMap, Map<Id,Date> prevRentingStartDtByOpptId) { List<BookingHistory__c> newHistoryRecords = new List<BookingHistory__c>(); for(Opportunity newRecord :newMap.values()) { newHistoryRecords.add(new BookingHistory__c( OpportunityRef__c = newRecord.Id, IsActive__c = true, AccountRef__c = newRecord.AccountId, BookingID__c = newRecord.BookingID__c, CostsBasisBackageEuro__c = newRecord.CostsBasisBackageEuro__c, CostsAdditionalServices__c = newRecord.CostsAdditionalServices__c, CostsProviderOnSiteEuro__c = newRecord.CostsProviderOnSiteEuro__c, CostsProviderOnSite__c = newRecord.CostsProviderOnSite__c, BookingCountry__c = newRecord.BookingCountry__c, CustomerRef__c = newRecord.Customer__c, Model__c = newRecord.Model__c, NumberOfPassengers__c = newRecord.NumberOfPassengers__c, CostsCamperDays__c = newRecord.CostsCamperDays__c, PaymentMethod__c = newRecord.PaymentMethod__c, RentingBeginDate__c = newRecord.RentingBeginDate__c, RentingReturnDate__c = newRecord.RentingReturnDate__c, RentingReturnLocationRef__c = newRecord.RentingReturnLocation__c, RentingStartLocationRef__c = newRecord.RentingStartLocation__c, TaxCountry__c = newRecord.TaxCountry__c, TotalAmount__c = newRecord.TotalAmount__c, WireTransferBy__c = newRecord.WireTransferBy__c, AmountCO2OffsetAuto__c = newRecord.AmountCO2OffsetAuto__c, Insurance__c = newRecord.Insurance__c, // CDW Insurance CostsInsuranceNew__c = newRecord.CostsInsuranceNew__c, CommissionInsuranceEUR__c = newRecord.CommissionInsuranceAuto__c, HasCOVInsurance__c = newRecord.HasCOVInsurance__c, // COV Insurance InsuranceCostsEuroCOV__c = newRecord.InsuranceCostsEuroCOV__c, CommissionInsuranceCOV__c = newRecord.CommissionInsuranceCOVAuto__c, HasRRVInsurance__c = newRecord.HasRRVInsurance__c, // RRV Insurance InsuranceCostsEuroRRV__c = newRecord.InsuranceCostsEuroRRV__c, CommissionInsuranceRRV__c = newRecord.CommissionInsuranceRRVAuto__c, AccountsPayableEUR__c = newRecord.AccountsReceivableEuro__c, AccountsPayableLocalCurrency__c = newRecord.AccountsReceivableLocalCurrency__c, CommissionableAmountEUR__c = newRecord.CommissionableAmount__c, PreliminaryMarginEUR__c = newRecord.PreliminaryMarginAuto__c, PreviousRentingBeginDate__c = (prevRentingStartDtByOpptId != null ? prevRentingStartDtByOpptId.get(newRecord.Id) : null), CustomerSaldo__c = newRecord.CustomerSaldoAuto__c, Payable_Amount_to_CamperDays_CFX__c = newRecord.Payable_Amount_to_CamperDays_CFX__c )); } try { if(!newHistoryRecords.isEmpty()) { insert newHistoryRecords; } } catch(Exception ex) { } } /******************************************************************************************************* * @description Update history when a booking is changed * @param opportunitiesById Changed bookings */ public static void updateBookingHistory(Map<Id, Opportunity> newMap, Map<Id, Opportunity> oldMap) { Opportunity oldRecord; Set<Id> filteredOppIds = new Set<Id>(); for(Opportunity newRecord :newMap.values()) { oldRecord = oldMap.get(newRecord.Id); if(newRecord.StageName != oldRecord.StageName && newRecord.StageName == System.Label.OpportunityTransactionStageSent) { filteredOppIds.add(newRecord.Id); } } updateBookingHistory(filteredOppIds); } /******************************************************************************************************* * @description Update history when a booking is changed * @param opportunitiesById Changed bookings */ public static void updateBookingHistory(Set<Id> opportunityIds) { Map<Id, Opportunity> opportunitiesById = new Map<Id, Opportunity>(); Map<Id, BookingAdditionalService__c> servicesById; for(Opportunity newRecord :[SELECT Id, AccountId, BookingID__c, CostsBasisBackageEuro__c, CostsAdditionalServices__c, CostsProviderOnSiteEuro__c, CostsProviderOnSite__c, BookingCountry__c, Customer__c, Model__c, NumberOfPassengers__c, CostsCamperDays__c, PaymentMethod__c, RentingBeginDate__c, RentingReturnDate__c, RentingReturnLocation__c, RentingStartLocation__c, TaxCountry__c, TotalAmount__c, WireTransferBy__c, AccountsReceivableEuro__c, AccountsReceivableLocalCurrency__c, Insurance__c, InsuranceID__c, CostsInsuranceNew__c, CommissionInsuranceAuto__c, CustomerSaldoAuto__c, HasCOVInsurance__c, COVInsuranceID__c, CommissionInsuranceCOVAuto__c, InsuranceCostsEuroCOV__c, HasRRVInsurance__c, RRVInsuranceID__c, CommissionInsuranceRRVAuto__c, InsuranceCostsEuroRRV__c, AmountCO2OffsetAuto__c, CommissionableAmount__c, PreliminaryMarginAuto__c,Payable_Amount_to_CamperDays_CFX__c, Original_Customer_Lastname__c,Customer_Exchange_Rate__c,Customer_Currency__c FROM Opportunity WHERE Id IN :opportunityIds]) { opportunitiesById.put(newRecord.Id, newRecord); } List<BookingHistory__c> historyRecordsToUpdate = new List<BookingHistory__c>(); Map<Id,Date> prevRentingStartDtByOpptId = new Map<Id,Date>(); for(BookingHistory__c record :[SELECT Id, OpportunityRef__c, IsActive__c, RentingBeginDate__c FROM BookingHistory__c WHERE OpportunityRef__c IN :opportunitiesById.keySet() AND IsActive__c = true]) { record.IsActive__c = false; historyRecordsToUpdate.add(record); prevRentingStartDtByOpptId.put(record.OpportunityRef__c,record.RentingBeginDate__c); } createBookingHistory(opportunitiesById,prevRentingStartDtByOpptId); try { if(!historyRecordsToUpdate.isEmpty()) { update historyRecordsToUpdate; } } catch(Exception ex) { } servicesById = new Map<Id, BookingAdditionalService__c>([SELECT Id, BookingHistoryRef__c, IsPaidOnSite__c, LocalCurrency__c, NameEnglish__c, NameGerman__c, OpportunityRef__c, Price__c, Quantity__c, Type__c, VATNote__c FROM BookingAdditionalService__c WHERE OpportunityRef__c IN :opportunitiesById.keySet()]); BookingServiceHelper.createBookingHistoryCopy(servicesById); } /******************************************************************************************************* * @description Prepares data to send email in Sent and Booking Changed Stages * @param newMap * @param oldMap */ public static void prepareEmailForBooking(Map<Id, Opportunity> newMap, Map<Id, Opportunity> oldMap) { Boolean isUpdate = (oldMap != null); Map<Id,Id> sendBookings = new Map<Id, Id>(); Map<Id,Id> changeBookings = new Map<Id, Id>(); Map<Id,Id> canceledBookings = new Map<Id, Id>(); for(Opportunity newRecord :newMap.values()) { Opportunity oldRecord = (isUpdate == true) ? oldMap.get(newRecord.Id) : null; if(newRecord.StageName != oldRecord.StageName && newRecord.StageName == System.Label.OpportunityTransactionStageSent) { sendBookings.put(newRecord.Id, null); } if(newRecord.StageName != oldRecord.StageName && newRecord.StageName.contains(System.Label.OpportunityTransactionStageBookingCancelled)) { canceledBookings.put(newRecord.Id, null); } if(newRecord.WasBookingChangedClicked__c != oldRecord.WasBookingChangedClicked__c && newRecord.WasBookingChangedClicked__c == true) { changeBookings.put(newRecord.Id, null); } } if(!isRecurringExecution && (sendBookings.size() > 0 || changeBookings.size() > 0 || canceledBookings.size() > 0)) { sendEmailsForUpdatedRecords(sendBookings, changeBookings, canceledBookings); isRecurringExecution = true; } } @future (callout=true) public static void sendEmailsForUpdatedRecords(Map<Id,Id> sendBookings, Map<Id,Id> changeBookings, Map<Id,Id> canceledBookings){ Map<Id,String> orgWideEmailAddressMap = new Map<Id,String>(); Map<Id,String> bookingToLanguageMap = new Map<Id,String>(); List<Id> oppIds = new List<Id>(); oppIds.addAll(sendBookings.keySet()); oppIds.addAll(changeBookings.keySet()); oppIds.addAll(canceledBookings.keySet()); if(oppIds.size() > 0) { for(Opportunity opp : [select Id, Customer__c, Customer__r.PersonContactId, Customer__r.PersonEmail, LanguageCodeAuto__c, WireTransferBy__c, WireTransferHelper__c from Opportunity where id in :oppIds]) { bookingToLanguageMap.put(opp.Id,opp.LanguageCodeAuto__c); orgWideEmailAddressMap.put(opp.Id,System.Label.get('','BookingEmailWideAddressId_ALL',opp.LanguageCodeAuto__c)); if(sendBookings.containsKey(opp.Id)) { sendBookings.put(opp.Id, opp.Customer__r.PersonContactId); generateDocuments(opp.Id, false); } if(changeBookings.containsKey(opp.Id)) { changeBookings.put(opp.Id, opp.Customer__r.PersonContactId); generateDocuments(opp.Id, true); } if(canceledBookings.containsKey(opp.Id)) { canceledBookings.put(opp.Id, opp.Customer__r.PersonContactId); generateDocument(opp.Id, System.Label.get('','CancelConfirm',opp.LanguageCodeAuto__c), 'canceled'); } } } if(!isRecurringExecution || Test.isRunningTest()) { String bookingConfInclFiles = System.label.BookingConfirmationAttachments + '\n' + System.label.BookingConfirmationAttachments_2; sendEmails(bookingToLanguageMap,orgWideEmailAddressMap,sendBookings, System.label.BookingTemplateId, null, System.label.BookingConfirmationExcludeFiles); sendEmails(bookingToLanguageMap,orgWideEmailAddressMap,changeBookings, System.label.BookingChangeTemplateId, bookingConfInclFiles, null); sendEmails(bookingToLanguageMap,orgWideEmailAddressMap,canceledBookings, System.label.BookingCanceledTemplateId, System.label.BookingCanceledAttachments, null); //update booking history data updateBookingHistory(changeBookings.keySet()); updateBookingHistory(sendBookings.keySet()); isRecurringExecution = true; } } /******************************************************************************************************* * @description Sends emails * @param bookings */ public static void sendEmails(Map<Id,String> bookingToLanguageMap,Map<Id,String> orgWideEmailAddressMap, Map<Id, Id> bookings, String templateId, String attachmentsList, String attachmentExcludeList) { List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>(); for(Id oppId: bookings.keySet()) { Messaging.SingleEmailMessage email = prepareEmail(orgWideEmailAddressMap.get(oppId),oppId, bookings.get(oppId), templateId); email.setFileAttachments(prepareFileAttachments(bookingToLanguageMap.get(oppId), oppId, attachmentsList, attachmentExcludeList)); emails.add(email); } if(!Test.isRunningTest()) { Messaging.sendEmail(emails); } } /******************************************************************************************************* * @description Prepares email for each booking * @param relatedId booking id * @param recipientId contact id * @param templateId template id */ public static Messaging.SingleEmailMessage prepareEmail(String orgWideEmailAddress, Id relatedId, Id recipientId, String templateId) { Messaging.SingleEmailMessage emailToSend = Messaging.renderStoredEmailTemplate(templateId,recipientId,relatedId); emailToSend.setOrgWideEmailAddressId(OrgWideEmailAddress); emailToSend.setTreatTargetObjectAsRecipient(true); emailToSend.setSaveAsActivity(true); return emailToSend; } /** * */ public static List<Messaging.Emailfileattachment> prepareFileAttachments(String languageCode, Id bookingId, String attachmentsList, String attachmentExcludeList) { Set<String> bookingAttachments = new Set<String>(); List<Messaging.Emailfileattachment> fileAttachments = new List<Messaging.Emailfileattachment>(); List<String> cdIds = new List<String>(); Map<id,ContentDocumentLink> CDLMap = New Map<id,ContentDocumentLink>([SELECT ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId =: bookingId]); for(ContentDocumentLink cdl :CDLMap.values()){ cdIds.add(cdl.ContentDocumentId); } List<ContentVersion> Docs = [SELECT Id, Title, FileType, VersionData, isLatest, ContentDocumentId FROM ContentVersion WHERE isLatest = true And ContentDocumentId IN : cdIds order by LastModifiedDate desc]; for (ContentVersion document: Docs) { if (!bookingAttachments.contains(document.Title.replace('.pdf',''))) { Boolean shouldBeAttached = false; if (attachmentsList != null && OpportunityHelper.includeDocument(document.Title, attachmentsList)) { shouldBeAttached = true; } else if (attachmentExcludeList != null && !OpportunityHelper.excludeDocument(document.Title, attachmentExcludeList)) { shouldBeAttached = true; } if (shouldBeAttached) { Messaging.EmailFileAttachment attachment = new Messaging.EmailFileAttachment(); String title = document.Title; if(document.FileType == 'PDF' && !title.contains('.pdf')){ title += '.pdf'; } attachment.setBody(document.VersionData); attachment.setFileName(title); fileAttachments.add(attachment); String fName = document.Title.replace('.pdf',''); if(fName == System.Label.get('','YourInvoice',languageCode)) bookingAttachments.add(System.Label.get('','YourInvoice',languageCode)); if(fName == System.Label.get('','YourVoucher',languageCode)) bookingAttachments.add(System.Label.get('','YourVoucher',languageCode)); bookingAttachments.add(document.Title.replace('.pdf','')); } } } return fileAttachments; } /******************************************************************************************************* * @description checks if the file needs to be added to email * @param fileName * @param attachmentsList - an string containing a list document-names of the documents that should be attached to the email. the names should be separated by a comma, semicolon on new-line. */ public static Boolean includeDocument(String fileName, String attachmentsList) { List<String> neededAttachments = attachmentsList.split('[,;\\n]'); for(String name : neededAttachments) { if (fileName.replace('_',' ').startsWithIgnoreCase(name.trim().replace('_',' '))) { return true; } } return false; } /******************************************************************************************************* * @description checks if the file needs to be excluded and not be attached to the email * @param fileName - name of file to be checked * @param exclucionList - an string containing a list document-names of the documents that should NOT be attached to the email. the names should be separated by a comma, semicolon on new-line. */ public static Boolean excludeDocument(String fileName, String exclucionList) { List<String> excludedDocs = exclucionList.split('[,;\\n]'); for(String name : excludedDocs) { if (fileName.replace('_',' ').startsWithIgnoreCase(name.trim())) { return true; } } return false; } public static void generateDocuments(Id bookingId, Boolean isChange) { Opportunity opp = [Select Id, LanguageCodeAuto__c From Opportunity Where Id =: bookingId]; String fileNameVoucher = System.Label.get('','YourVoucher',opp.LanguageCodeAuto__c); String fileNameInvoice = System.Label.get('','YourInvoice',opp.LanguageCodeAuto__c); generateDocument(bookingId, fileNameVoucher, 'voucher'); generateDocument(bookingId, fileNameInvoice, 'invoice' + (isChange ? 'Changed' : '')); } public static void generateDocument(Id bookingId, String documentName, String componentName) { Pagereference pdf = Page.BookingPDFs; pdf.getParameters().put('id', bookingId); pdf.getParameters().put('document', componentName); pdf.setRedirect(true); ContentVersion contentVersion = new ContentVersion(); if (Test.IsRunningTest()) { contentVersion = createContentVersion(documentName + '.pdf', Blob.valueOf('UNIT.TEST')); } else { contentVersion = createContentVersion(documentName + '.pdf', pdf.getContentAsPDF()); } insert contentVersion; contentVersion = [SELECT Id, ContentDocumentId FROM ContentVersion WHERE Id =:contentVersion.Id]; ContentDocumentLink contentDocumentLink = createContentDocumentLink(contentVersion.ContentDocumentId, bookingId); insert contentDocumentLink; } public static ContentVersion createContentVersion(String name, Blob body){ ContentVersion contentVersion = new ContentVersion(); contentVersion.ContentLocation = 'S'; contentVersion.PathOnClient = name; contentVersion.Title = name; contentVersion.VersionData = body; return contentVersion; } public static ContentDocumentLink createContentDocumentLink(Id contentDocumentId, Id parentId){ ContentDocumentLink contentDocumentLink = new ContentDocumentLink(); contentDocumentLink.ContentDocumentId = contentDocumentId; contentDocumentLink.LinkedEntityId = parentId; contentDocumentLink.ShareType = 'V'; return contentDocumentLink; } /******************************************************************************************************* * @description Sets the exchange rates based on values from KantoxRates__mdt * The rate is only set if it is null or zero. * Some of the Bookings are created from Webpages that provide the exchange rate. * In these cases we don't want to overwrite the provided exchange rate. * * Invoked from the before insert trigger. * * @param newList - a list of Opportunities/Bookings being created */ public static void updateExchangeRates(List<Opportunity> newList){ // Get the Company's Currency List<CurrencyType> currList = [SELECT ISOCode FROM CurrencyType WHERE IsActive = true AND IsCorporate = true]; String companyCurrency = !currList.isEmpty() ? currList[0].ISOCode : 'EUR'; // Get the latest exchange as were uploaded from Kantox Map<String, KantoxRates__mdt> kRatesByKey = new Map<String, KantoxRates__mdt>(); List<KantoxRates__mdt> kRates = [SELECT DeveloperName, BaseCurrency__c, ForeignCurrency__c, Rate__c FROM KantoxRates__mdt]; if(!kRates.isEmpty()){ for(KantoxRates__mdt kr : kRates){ kRatesByKey.put(kr.DeveloperName, kr); } } else { System.debug('No Kantox Rates found.'); } // Set Booking's exchange rates for(Opportunity opp : newList){ // Set exchange rate to Provider's currency // -- LocalCurrency__c - provider's currency // -- BookingExchangeRate__c - exchange to provider's currency if(String.isNotBlank(opp.LocalCurrency__c) && (opp.BookingExchangeRate__c == null || opp.BookingExchangeRate__c == 0)) { String rateKey = companyCurrency + opp.LocalCurrency__c; if (kRatesByKey.containsKey(rateKey)) { opp.BookingExchangeRate__c = kRatesByKey.get(rateKey).Rate__c; } else { System.debug('Provider Exchange rate: The current Key '+rateKey+' was not found.'); } } else { System.debug('The current Booking LocalCurrency__c (Provider Currency) '+opp.LocalCurrency__c+' was not found.'); } // Set exchange rate to Customer's currency System.debug('---OpportunityHelper.updateExchangeRates--1- Customer_Currency: '+opp.Customer_Currency__c+' Customer_Exchange_Rate: '+opp.Customer_Exchange_Rate__c); if (String.isNotBlank(opp.Customer_Currency__c)) { if (opp.Customer_Exchange_Rate__c == null || opp.Customer_Exchange_Rate__c == 0){ String rateKey = companyCurrency + opp.Customer_Currency__c; if (kRatesByKey.containsKey(rateKey)) { opp.Customer_Exchange_Rate__c = kRatesByKey.get(rateKey).Rate__c; } else { System.debug('Customer Exchange rate: The current Key '+rateKey+' was not found.'); } } } else { // If Not Customer_Currency__c is set, assume that it is EUR and set rate to 1. opp.Customer_Exchange_Rate__c = 1; opp.Customer_Currency__c = 'EUR'; } System.debug('---OpportunityHelper.updateExchangeRates--2- Customer_Currency: '+opp.Customer_Currency__c+' Customer_Exchange_Rate: '+opp.Customer_Exchange_Rate__c); if(String.isNotBlank(opp.CurrencyIsoCode)){ String rateKey = companyCurrency + opp.CurrencyIsoCode; if (kRatesByKey.containsKey(rateKey)) { //opp.BookingExchangeRate__c = kRatesByKey.get(rateKey).Rate__c; // FIELD TBD } else { //TODO: Log when no key is found } } else { //TODO: Log when no value on CurrencyIsoCode } } } /** * @description: Calculates and sets the value of AccountsReceivableEuro__c. * Should be called from the before insert & update trigger. * * Note: confusingly the label for this field is: Accounts Payable (Euro), Why? * * @Who: david.sanchez@gmail.com * @When: 2022.07.12 */ public static void setAccountsReceivableEuro(List<Opportunity> newOpportunities, Map<Id,Opportunity> oldOpportunities) { for (Opportunity oppty : newOpportunities) { Decimal oldacctRecvLocal = 0; Decimal oldBookingExchangeRate = 0; if (oldOpportunities != null) { Opportunity oldOppty = oldOpportunities.get(oppty.Id); oldacctRecvLocal = oldOppty.AccountsReceivableLocalCurrency__c; oldBookingExchangeRate = oldOppty.BookingExchangeRate__c; } if (oppty.AccountsReceivableLocalCurrency__c != null && (oppty.AccountsReceivableEuro__c == null || oppty.AccountsReceivableEuro__c == 0 || oppty.AccountsReceivableLocalCurrency__c != oldacctRecvLocal || oppty.BookingExchangeRate__c != oldBookingExchangeRate)) { Decimal xrate = (oppty.BookingExchangeRate__c == null || oppty.BookingExchangeRate__c == 0) ? 1 : oppty.BookingExchangeRate__c; oppty.AccountsReceivableEuro__c = oppty.AccountsReceivableLocalCurrency__c / xrate; } } } /** * When the stage of the Booking is set to "Sent", save the CostCamperDays__c into OriginalCostCamperDays__c. * This value will be needed for the Cancellation Invoice if the Booking is cancelled before any "Booking Change" is performed. */ public static void onSentSaveOriginalCostCamperDays(List<Opportunity> newList, Map<Id, Opportunity> oldMap) { for (Opportunity booking : newList) { if (booking.StageName == 'Sent' && booking.StageName != oldMap.get(booking.Id).StageName) { booking.OriginalCostsCamperDaysAuto__c = booking.CostsCamperDays__c; } } } /** * Sends a confirmation emails to the customer when a booking it is fully paid. * A Booking is fully paid when the TotalAmountpaidbyCustomerEUR__c is greater or equal to CostsCamperDays__c. * The TotalAmountpaidbyCustomerEUR__c is a rollup value from the payments received for the booking. */ public static void sendReceiptPaymntConfirm(List<Opportunity> newList, Map<Id, Opportunity> oldMap) { Set<Id> opptyIds = new Set<Id>(); // IDs of Opportunities to which emails should be sent for (Opportunity oppty : newList) { Decimal oldTotalAmountPaid = oldMap != null ? oldMap.get(oppty.Id).TotalAmountpaidbyCustomerEUR__c : 0; if (oppty.PaymentMethod__c == 'Invoice' && !oppty.IsPaymentConfirmation_Sent__c && oppty.CostsCamperDays__c != 0 && oppty.TotalAmountpaidbyCustomerEUR__c != oldTotalAmountPaid && (oppty.StageName == 'Sent Phone' || oppty.StageName == 'Booking Changed' || oppty.StageName == 'Sent')) { if (oppty.CostsCamperDays__c <= oppty.TotalAmountpaidbyCustomerEUR__c) { opptyIds.add(oppty.Id); } } } if (!opptyIds.isEmpty()) { sendEmailsForPaymentConfirmantion(opptyIds); } } @future(callout=true) private static void sendEmailsForPaymentConfirmantion(Set<Id> opptyIds) { if (!opptyIds.isEmpty()) { EmailTemplate emailTemplate =[SELECT Id FROM EmailTemplate WHERE developername = 'PaymentReceiptConfirmation']; List<Messaging.SingleEmailMessage> emailsList = new List<Messaging.SingleEmailMessage>(); List<Opportunity> opportunities = new List<Opportunity>(); for (Opportunity oppty : [SELECT Id, IsPaymentConfirmation_Sent__c, Customer__r.PersonContactId, Customer__r.PersonEmail, LanguageCodeAuto__c FROM Opportunity WHERE Id IN :opptyIds]) { Messaging.SingleEmailMessage email = preparePaymtRecptEmail(oppty.Customer__r.PersonEmail, oppty.Id, oppty.Customer__r.PersonContactId, emailTemplate.Id, oppty.LanguageCodeAuto__c); emailsList.add(email); oppty.IsPaymentConfirmation_Sent__c = true; opportunities.add(oppty); } update opportunities; if(!Test.isRunningTest()) { Messaging.sendEmail(emailsList); } } } /******************************************************************************************************* * @description Prepares Payment Receipt Confirmation email for each booking * @param relatedId booking id * @param recipientId contact id * @param templateId template id */ public static Messaging.SingleEmailMessage preparePaymtRecptEmail(String customerEmailAddress, Id relatedId, Id recipientId, String templateId, String languageCode) { Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(); email.setTemplateId(templateId); email.setTargetObjectID(recipientId); email.setWhatID(relatedId); email.setOrgWideEmailAddressId(System.Label.get('','BookingEmailWideAddressId_ALL',languageCode)); return email; } }
Editor is loading...
Leave a Comment