Untitled
unknown
plain_text
a year ago
35 kB
9
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