Untitled
Fullc folder OpportunityOfferingSaveEditAllController.cls public without sharing class OpportunityOfferingSaveEditAllController { public static Map<String,String> statusMessage = new Map<String,String>(); @AuraEnabled public static List<OpportunityOfferingWrapper> getOfferings(Id recordId){ List<Opportunity_Offering__c> drLinesList = new List<Opportunity_Offering__c>(); List<OpportunityOfferingWrapper> drLinesWrapperList = new List<OpportunityOfferingWrapper>(); drLinesList = [select Id,Virtusa_Offering__c,Deal_Led_By__c,Virtusa_Offering__r.Name,Virtusa_Offering__r.Offering_Deal_Type__c,Virtu_Offering_Split_p__c,Opportunity_Name__c,OwnerId,Owner.Name,Opportunity_Name__r.name from Opportunity_Offering__c where Opportunity_Name__c = :recordId ]; for(Opportunity_Offering__c drRec : drLinesList){ drLinesWrapperList.add(new OpportunityOfferingWrapper(drRec)); } return drLinesWrapperList; } @AuraEnabled public static OppOfferWrapper getOppDetails(Id recordId){ Opportunity opp = [select id,name,stagename from opportunity where id = :recordId]; User userRecord = [select id,Name from User where id = :UserInfo.getUserId()]; return new OppOfferWrapper(userRecord.Id, userRecord.Name, opp.Id, opp.Name, opp.stagename); } @AuraEnabled public static Map<String,String> saveDRList(String oppId, String dealType, List<OpportunityOfferingWrapper> drLinesList){ system.debug(dealType + ' dealType'); Set<Id> oppIds = new Set<Id>(); Savepoint sp = Database.setSavepoint(); statusMessage.put('status','Success'); statusMessage.put('message','Records saved successfully'); statusMessage.put('url',URL.getOrgDomainUrl().toExternalForm()); List<Opportunity_Offering__c> oppOfferingToUpdate = new List<Opportunity_Offering__c>(); List<Opportunity_Offering__c> oppOfferingToInsert = new List<Opportunity_Offering__c>(); Map<Id,String> idVsDealType = new Map<Id,String>(); for(OpportunityOfferingWrapper drLine : drLinesList){ idVsDealType.put(drLine.VirtusaOffering,drLine.VirtusaOfferingDealType); } List<Virtusa_Offering__c> virtusaLis = [select id,Offering_Deal_Type__c from Virtusa_Offering__c where id IN :idVsDealType.keySet()]; for(Virtusa_Offering__c offer : virtusaLis){ idVsDealType.put(offer.id,offer.Offering_Deal_Type__c); } Decimal consultingSum = 0; Decimal nonConsultingSum = 0; for(OpportunityOfferingWrapper drLine : drLinesList){ String virtusaOffDealType = drLine.VirtusaOfferingDealType != null && drLine.VirtusaOfferingDealType != '' ? drLine.VirtusaOfferingDealType : idVsDealType.get(drLine.VirtusaOffering); if(virtusaOffDealType == 'Consulting'){ consultingSum = consultingSum + Decimal.valueOf(drLine.OfferingSplit); } if(virtusaOffDealType == 'Non Consulting'){ nonConsultingSum = nonConsultingSum + Decimal.valueOf(drLine.OfferingSplit); } } if(dealType == 'Consulting'){ if(consultingSum != 100 || nonConsultingSum > 50){ statusMessage.put('status','Fail'); statusMessage.put('message','For Consulting Deals it is mandatory to select one or more consulting offering with split% totaling to 100% and optional to have non consulting Offerings with up to 50% split'); if(!Test.isRunningTest()) return statusMessage; } } if(dealType == 'Non Consulting'){ if(nonConsultingSum < 5 || nonConsultingSum > 100 || consultingSum > 50){ statusMessage.put('status','Fail'); statusMessage.put('message','For Non-Consulting Deals Offering Sum of Split% can vary between 5% to max 100% and optionally Consulting Offerings Split % sum can be up to 50%'); if(!Test.isRunningTest()) return statusMessage; } } system.debug(nonConsultingSum + ' nonConsultingSum'); system.debug(consultingSum + ' consultingSum'); if(dealType == 'No Offerings Required'){ system.debug('inside if block no offering....'); if(nonConsultingSum != 0 || consultingSum != 0){ statusMessage.put('status','Fail'); statusMessage.put('message','For "No Offerings Required" Deals tagging No Offerings is only allowed'); if(!Test.isRunningTest()) return statusMessage; } } try{ Boolean isNoOfferingExist = false; String virId = ''; if(dealType == 'No Offerings Required'){ List<Opportunity_Offering__c> drLinesListNoOff = new List<Opportunity_Offering__c>(); drLinesListNoOff = [select Id,Virtusa_Offering__c,Deal_Led_By__c,Virtusa_Offering__r.Name,Virtusa_Offering__r.Offering_Deal_Type__c,Virtu_Offering_Split_p__c,Opportunity_Name__c,OwnerId,Owner.Name,Opportunity_Name__r.name from Opportunity_Offering__c where Opportunity_Name__c = :oppId and Virtu_Offering_Split_p__c = 0]; if(drLinesListNoOff.size() != 0 ) isNoOfferingExist = true; List<Virtusa_Offering__c> vir = [select id,name from Virtusa_Offering__c where name = 'No Offerings']; virId = vir[0].Id; } for(OpportunityOfferingWrapper drLine : drLinesList){ oppIds.add(drLine.opportunityId); Opportunity_Offering__c drlineRec = new Opportunity_Offering__c(); drlineRec.Virtusa_Offering__c = drLine.VirtusaOffering; if(drLine.OfferingSplit != null && drLine.OfferingSplit != '' ) drlineRec.Virtu_Offering_Split_p__c = Decimal.valueOf(drLine.OfferingSplit); drlineRec.Opportunity_Name__c = drLine.opportunityId; drlineRec.Deal_Led_By__c = dealType; if(virId == drLine.VirtusaOffering) isNoOfferingExist = true; //drLineRecordToInsert.add(drlineRec); if(drLine.Id != null && drLine.Id != ''){ drlineRec.Id = drLine.Id; oppOfferingToUpdate.add(drlineRec);//if(Decimal.valueOf(drLine.OfferingSplit) != 0) removed logic as not able to update offering to zero } else{ oppOfferingToInsert.add(drlineRec); } } if(dealType == 'No Offerings Required' && !isNoOfferingExist){ List<Opportunity_Offering__c> drLinesListNoOff = new List<Opportunity_Offering__c>(); drLinesListNoOff = [select Id,Virtusa_Offering__c,Deal_Led_By__c,Virtusa_Offering__r.Name,Virtusa_Offering__r.Offering_Deal_Type__c,Virtu_Offering_Split_p__c,Opportunity_Name__c,OwnerId,Owner.Name,Opportunity_Name__r.name from Opportunity_Offering__c where Opportunity_Name__c = :oppId and Virtu_Offering_Split_p__c != 0]; Opportunity_Offering__c drlineRec = new Opportunity_Offering__c(); drlineRec.Virtusa_Offering__c = virId; drlineRec.Virtu_Offering_Split_p__c = 0; drlineRec.Opportunity_Name__c = oppId; drlineRec.Deal_Led_By__c = dealType; if(drLinesListNoOff.size() == 0 ) oppOfferingToInsert.add(drlineRec); } Set<Id> newOfferingIds = new Set<Id>(); if(oppOfferingToInsert.size() > 0){ insert oppOfferingToInsert; for(Opportunity_Offering__c offers : oppOfferingToInsert){ newOfferingIds.add(offers.Id); } } if(oppOfferingToUpdate.size() > 0){ update oppOfferingToUpdate; } if(oppIds.size() > 0 && (oppOfferingToUpdate.size() > 0 || oppOfferingToInsert.size() > 0)){ initiateEmailNotification(oppIds,newOfferingIds); } } catch(Exception ex){ statusMessage.put('status','Fail'); String errorMsg = ex.getMessage();//Insert failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, You cannot add or edit the offerings of this opportunity: [] if(errorMsg.contains('FIELD_CUSTOM_VALIDATION_EXCEPTION')) errorMsg = errorMsg.substringAfter('FIELD_CUSTOM_VALIDATION_EXCEPTION,'); if(errorMsg.contains(': []')) errorMsg = errorMsg.substringBefore(': []').trim(); statusMessage.put('message',errorMsg); Database.rollback(sp); } return statusMessage; } @Future public static void initiateEmailNotification(Set<Id> oppIds,Set<Id> newOfferings){ Map<Id,List<Opportunity_Offering__c>> oppIdVsOfferingList = new Map<Id,List<Opportunity_Offering__c>>(); Map<Id,Opportunity> offeringOpp = new Map<Id,Opportunity>([Select id, name, Group_SBU__c, Account.Customer_Name__r.Client__r.Name, Account.Customer_Name__r.name, Account.name, Opportunity_ID__c, Deal_Type__c, StageName, Amount, CurrencyIsoCode, Opportunity_Amount_Converted_New__c, Opportunity_CS_Owner__r.Name, Owner.name, OwnerId, Owner.Email, Account.owner.name, Account.CSM__r.Name from Opportunity where id In :oppIds]); Map<Id,Opportunity_Offering__c> idVsRelOfferingRecord = new Map<Id,Opportunity_Offering__c>([select id,Name, Opportunity_Name__c,Virtusa_Offering__c, Virtusa_Offering__r.Offering_Squad__c, Virtu_Offering_Split_p__c, Old_Offering_Split__c, Deal_Led_By__c, Owner.name, Virtusa_Offering__r.Name from Opportunity_Offering__c where Opportunity_Name__c IN :oppIds]); Set<String> squadTeam = new Set<String>(); Map<Id,String> virtusaIdVsSquad = new Map<Id,String>(); for(Opportunity_Offering__c offer : idVsRelOfferingRecord.values()){ if(offer.Virtusa_Offering__c != null && offer.Virtusa_Offering__r.Offering_Squad__c != null){ if(offer.Virtu_Offering_Split_p__c != 0 || (offer.Virtu_Offering_Split_p__c == 0 && offer.Virtu_Offering_Split_p__c != offer.Old_Offering_Split__c)) squadTeam.add(offer.Virtusa_Offering__r.Offering_Squad__c); virtusaIdVsSquad.put(offer.Virtusa_Offering__c,offer.Virtusa_Offering__r.Offering_Squad__c); } if(oppIdVsOfferingList.containsKey(offer.Opportunity_Name__c)){ oppIdVsOfferingList.get(offer.Opportunity_Name__c).add(offer); }else{ oppIdVsOfferingList.put(offer.Opportunity_Name__c,new List<Opportunity_Offering__c>{offer}); } } Map<String,String> emailVsName = new Map<String,String>(); String slist = ''; for (String s: squadTeam) { slist += '\'' + s + '\','; } system.debug(',slist' + slist); slist = slist.removeEnd(','); String value = '(\'' + String.join(squadTeam, '\',\'') + '\')'; String queryString = 'select id,email,name,Offering_squad_Leader__c,Off_Squad_Team_del__c'+ ' from contact' + ' where email != null and ' + ' Offering_squad_Leader__c = true and ' + ' Off_Squad_Team_del__c includes' + value; List<Contact> contactList = DataBase.query(queryString); system.debug('List of records: '+contactList); /*Map<Id,Contact> contactList = new Map<Id,Contact>([select id,email,name,Offering_squad_Leader__c,Off_Squad_Team_del__c from contact where email != null and Offering_squad_Leader__c = true and Off_Squad_Team_del__c includes (:slist)]);*/ system.debug(',contactList' + contactList); Map<Id,List<String>> virOffIdVsEmail = new Map<Id,List<String>>(); Map<String,Set<Id>> emailVsVirtusaId = new Map<String,Set<Id>>(); for(Id virId : virtusaIdVsSquad.keySet()){ for(Contact con : contactList){ emailVsName.put(con.email,con.name); if(virtusaIdVsSquad.get(virId) != null && con.Off_Squad_Team_del__c.contains(virtusaIdVsSquad.get(virId))){ if(!virOffIdVsEmail.containskey(virId))virOffIdVsEmail.put(virId,new List<String>{con.email}); else{ virOffIdVsEmail.get(virId).add(con.email); } } } } for(Id oppId : oppIdVsOfferingList.keySet()){ Set<String> to = new Set<String>(); Opportunity opp = offeringOpp.get(oppId); if(opp.owner.email != null){ to.add(opp.owner.email); emailVsName.put(opp.owner.email,opp.owner.name); } for(Opportunity_Offering__c oppOffer : oppIdVsOfferingList.get(oppId)){ Id relatedOffId = oppOffer.Id; if(virOffIdVsEmail != null && idVsRelOfferingRecord != null && idVsRelOfferingRecord.get(relatedOffId) != null && virOffIdVsEmail.get(idVsRelOfferingRecord.get(relatedOffId).Virtusa_Offering__c) != null) to.addAll(virOffIdVsEmail.get(idVsRelOfferingRecord.get(relatedOffId).Virtusa_Offering__c)); if(virOffIdVsEmail != null && virOffIdVsEmail.get(oppOffer.Virtusa_Offering__c) != null){ to.addAll(virOffIdVsEmail.get(oppOffer.Virtusa_Offering__c)); } } String subject = 'Virtusa Offering Notification'; String body = ''; body = 'Hi All,<br/><br/> Following offerings have tagged to the opportunity.<br/><br/>'; String dealLeadBy = oppIdVsOfferingList.get(oppId).size() > 1 ? oppIdVsOfferingList.get(oppId)[1].Deal_Led_By__c : oppIdVsOfferingList.get(oppId)[0].Deal_Led_By__c; body = body + '<b><u>Opportunity Details</b></u><br/><br/>'+ '<li>Deal Lead By - '+dealLeadBy + '</li>'+ '<li>Group SBU - '+offeringOpp.get(oppId).Group_SBU__c+'</li>'+ '<li>Account - '+offeringOpp.get(oppId).Account.name+'</li>'+ '<li>Opportunity ID - <a href="'+ URL.getOrgDomainUrl().toExternalForm() +'/'+oppId+'">'+offeringOpp.get(oppId).Opportunity_ID__c+'</a></li>'+ '<li>Opportunity Name - '+offeringOpp.get(oppId).name + '</li>'+ '<li>Stage - '+offeringOpp.get(oppId).StageName+'</li>'+ '<li>Amount (converted) - '+'USD'+' '+offeringOpp.get(oppId).Opportunity_Amount_Converted_New__c+'</li>'+ '<li>Opportunity Owner - '+offeringOpp.get(oppId).Owner.name + '</li>'+ '<br/><br/>'; body = body + '<b><u>Offering Details</b></u><br/><br/>'; String tableHtml = '<table style="border-collapse: collapse;">'; tableHtml += '<thead>'; tableHtml += '<tr>'; tableHtml += '<th style="font-weight: bold; border: 1px solid black; padding: 8px;">SR. No</th>'; tableHtml += '<th style="font-weight: bold; border: 1px solid black; padding: 8px;">Virtusa Offering Name</th>'; tableHtml += '<th style="font-weight: bold; border: 1px solid black; padding: 8px;">Old Split%</th>'; tableHtml += '<th style="font-weight: bold; border: 1px solid black; padding: 8px;">New Split%</th>'; tableHtml += '<th style="font-weight: bold; border: 1px solid black; padding: 8px;">Is Modified</th>'; tableHtml += '</tr>'; tableHtml += '</thead>'; tableHtml += '<tbody>'; Integer count = 1; List<Opportunity_Offering__c> offerList = oppIdVsOfferingList.get(oppId); for(Opportunity_Offering__c oppOffer : offerList){ if(offerList.size() == 1 || (offerList.size() > 1 && oppOffer.Virtusa_Offering__r.Name != 'No Offerings')){ tableHtml += '<tr>'; tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + count + '</td>'; tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + oppOffer.Virtusa_Offering__r.Name + '</td>'; String oldSplit = oppOffer.Old_Offering_Split__c == null ? '-' : oppOffer.Old_Offering_Split__c.setScale(2) + ''; if(newOfferings.contains(oppOffer.Id)) oldSplit = '-'; tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + oldSplit + '</td>'; //else tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + oppOffer.Old_Offering_Split__c + '</td>'; tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + oppOffer.Virtu_Offering_Split_p__c + '</td>'; Boolean isNotChange = oppOffer.Old_Offering_Split__c == null || oppOffer.Virtu_Offering_Split_p__c == oppOffer.Old_Offering_Split__c; String isChanged = !isNotChange == true ? 'Yes' : 'No'; tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + isChanged + '</td>'; tableHtml += '</tr>'; count++; } } tableHtml += '</tbody>'; tableHtml += '</table>'; body = body + tableHtml + '<br/><br/>'; body = body + 'Thanks,<br/> System Administrator'; String repmail = ''; SingleEmailUtility seu = new SingleEmailUtility(); List<String> ccAddress = new List<String>(); seu.sendMail(new List<String>(to), ccAddress, '', subject, body); } } public class OppOfferWrapper{ @auraEnabled public string currentUserId{get;set;} @auraEnabled public string currentName{get;set;} @auraEnabled public string OpportunityName{get;set;} @auraEnabled public string OpportunityId{get;set;} @auraEnabled public string opportunityStageName{get;set;} public OppOfferWrapper(String userId, String userName, String oppId, String oppName, String oppStage){ this.currentUserId = userId; this.currentName = userName; this.OpportunityName = oppName; this.OpportunityId = oppId; this.opportunityStageName = oppStage; } } } ---------------------- OpportunityOfferingTriggerHelper.cls public without sharing class OpportunityOfferingTriggerHelper { @future public static void createShareRecordsFutureContext(Set<Id> offeringIds){ if(offeringIds != null)createShareRecords(offeringIds); } public static void createShareRecords(Set<Id> offeringIds){ Map<Id,Id> oppOfferIdVsOppId = new Map<Id,Id>(); Map<Id,Id> virOfferIdVsOppId = new Map<Id,Id>(); Map<Id,Set<Id>> oppIdVsOfferingIdSet = new Map<Id,Set<Id>>(); List<Opportunity_Offering__c> opOfferingList = new List<Opportunity_Offering__c>(); opOfferingList = [select id,Opportunity_Name__c,Virtusa_Offering__c from Opportunity_Offering__c where id IN :offeringIds]; for(Opportunity_Offering__c opOffering : opOfferingList){ oppOfferIdVsOppId.put(opOffering.Id,opOffering.Opportunity_Name__c); virOfferIdVsOppId.put(opOffering.Id,opOffering.Virtusa_Offering__c); if(!oppIdVsOfferingIdSet.containsKey(opOffering.Opportunity_Name__c)){ oppIdVsOfferingIdSet.put(opOffering.Opportunity_Name__c,new Set<Id>{opOffering.Id}); }else{ oppIdVsOfferingIdSet.get(opOffering.Opportunity_Name__c).add(opOffering.Id); } } Map<Id,Opportunity> offeringOpp = new Map<Id,Opportunity>([Select id, name from Opportunity where id In :oppOfferIdVsOppId.values() ]); Map<Id,Opportunity_Offering__c> idVsRelOfferingRecord = new Map<Id,Opportunity_Offering__c>([select id, Opportunity_Name__c,Virtusa_Offering__c from Opportunity_Offering__c where Opportunity_Name__c IN :offeringOpp.keySet() and ID Not In :oppOfferIdVsOppId.keySet()]); for(Opportunity_Offering__c opOffering : idVsRelOfferingRecord.values()){ oppOfferIdVsOppId.put(opOffering.Id,opOffering.Opportunity_Name__c); virOfferIdVsOppId.put(opOffering.Id,opOffering.Virtusa_Offering__c); if(!oppIdVsOfferingIdSet.containsKey(opOffering.Opportunity_Name__c)){ oppIdVsOfferingIdSet.put(opOffering.Opportunity_Name__c,new Set<Id>{opOffering.Id}); }else{ oppIdVsOfferingIdSet.get(opOffering.Opportunity_Name__c).add(opOffering.Id); } } Map<Id,Virtusa_Offering__c> vOfferingList = new Map<Id,Virtusa_Offering__c>([Select id, Offering_Squad__c, Virtu_Squad_Email_Address__c from Virtusa_Offering__c where id In :virOfferIdVsOppId.values() ]); Set<String> squadTeam = new Set<String>(); for(Virtusa_Offering__c vr : vOfferingList.values()){ if(vr.Offering_Squad__c != null) squadTeam.add(vr.Offering_Squad__c); } Map<Id,List<String>> virOffIdVsEmail = new Map<Id,List<String>>(); Map<String,Set<Id>> emailVsVirtusaId = new Map<String,Set<Id>>(); String slist = ''; for (String s: squadTeam) { slist += '\'' + s + '\','; } String value = '(\'' + String.join(squadTeam, '\',\'') + '\')'; String queryString = 'select id,email,name,Offering_squad_Leader__c,Off_Squad_Team_del__c'+ ' from contact' + ' where email != null and ' + ' Offering_squad_Leader__c = true and ' + ' Off_Squad_Team_del__c includes' + value; List<Contact> contactList = DataBase.query(queryString); for(Virtusa_Offering__c vr : vOfferingList.values()){ if(vr.Offering_Squad__c != null){ for(Contact con : contactList){ if(con.Off_Squad_Team_del__c.contains(vr.Offering_Squad__c)){ //emailVsName.put(con.email,con.name); if(!emailVsVirtusaId.containskey(con.email)){ emailVsVirtusaId.put(con.email,new Set<Id>{vr.Id}); } else{ emailVsVirtusaId.get(con.email).add(vr.Id); } if(!virOffIdVsEmail.containskey(vr.Id)){ virOffIdVsEmail.put(vr.Id,new List<String>{con.email}); } else{ virOffIdVsEmail.get(vr.Id).add(con.email); } } } } } Set<String> toAddresses = new Set<String>(); for(Opportunity_Offering__c opOffering : opOfferingList){ Set<String> to = new Set<String>(); if(offeringOpp.get(opOffering.Opportunity_Name__c) != null){ Set<Id> relatedOfferingIds = oppIdVsOfferingIdSet.get(opOffering.Opportunity_Name__c); if(relatedOfferingIds != null && relatedOfferingIds.size() > 0){ for(Id relatedOffId : relatedOfferingIds){ if(virOffIdVsEmail != null && idVsRelOfferingRecord != null && idVsRelOfferingRecord.get(relatedOffId) != null && idVsRelOfferingRecord.get(relatedOffId).Virtusa_Offering__c != null ) to.addAll(virOffIdVsEmail.get(idVsRelOfferingRecord.get(relatedOffId).Virtusa_Offering__c)); } } } if(virOffIdVsEmail != null && virOffIdVsEmail.get(opOffering.Virtusa_Offering__c) != null){ to.addAll(virOffIdVsEmail.get(opOffering.Virtusa_Offering__c)); } if(to.size() > 0) toAddresses.addAll(to); } List<User> userRecords = [select id,email from User where email IN :toAddresses]; Map<String,Opportunity_Offering__share> oppOffList = new Map<String,Opportunity_Offering__share>(); for(User userRec : userRecords){ if(emailVsVirtusaId != null && emailVsVirtusaId.get(userRec.email) != null){ Set<Id> virtusaIds = emailVsVirtusaId.get(userRec.email); for(Id oppOfferId : virOfferIdVsOppId.keySet()){ Set<Id> offerIds = oppIdVsOfferingIdSet.get(oppOfferIdVsOppId.get(oppOfferId)); if(virtusaIds.contains(virOfferIdVsOppId.get(oppOfferId))){ for(Id offerId : offerIds){ Opportunity_Offering__share oppOfferShare = new Opportunity_Offering__share(); oppOfferShare.ParentId = offerId; oppOfferShare.UserOrGroupId = userRec.Id; oppOfferShare.AccessLevel = 'edit'; oppOfferShare.RowCause = 'Manual'; if(offerId != null && userRec != null) oppOffList.put(offerId+'-'+userRec.Id,oppOfferShare); } } } } } if(oppOffList.size() > 0) Database.upsert(oppOffList.values(),false); } //Author - Viji //Arguments - opOfferingList -> list of opportunity offering record //Purpose - called from after update,after insert //Date - 21/03/2023 @future public static void updateOffOwnerAccessToOppOwnerHelper(Set<Id> offeringIds){ createShareRecordsForOppOwner(offeringIds); } public static void createShareRecordsForOppOwner(Set<Id> offeringIds){ Map<Id,Id> oppOfferIdVsOppId = new Map<Id,Id>(); Map<Id,Set<Id>> oppIdVsOfferingIdSet = new Map<Id,Set<Id>>(); Map<Id,Id> offOwner = new Map<Id,Id>(); List<Opportunity_Offering__c> opOfferingList = new List<Opportunity_Offering__c>(); opOfferingList = [select id,Opportunity_Name__c,Virtusa_Offering__c,OwnerId from Opportunity_Offering__c where id IN :offeringIds]; for(Opportunity_Offering__c oppOffering : opOfferingList){ oppOfferIdVsOppId.put(oppOffering.id,oppOffering.Opportunity_Name__c); if(!oppIdVsOfferingIdSet.containsKey(oppOffering.Opportunity_Name__c)){ oppIdVsOfferingIdSet.put(oppOffering.Opportunity_Name__c,new Set<Id>{oppOffering.Id}); }else{ oppIdVsOfferingIdSet.get(oppOffering.Opportunity_Name__c).add(oppOffering.Id); } } Map<Id,Opportunity> offeringOpp = new Map<Id,Opportunity>([Select id, name,stagename,ownerid from Opportunity where id In :oppOfferIdVsOppId.values() ]); for(Opportunity_Offering__c opOffering : opOfferingList){ Opportunity oppRec = offeringOpp.get(opOffering.Opportunity_Name__c); Id offeringOwner = opOffering.ownerId; if(oppRec != null){ Set<Id> relatedOfferingIds = oppIdVsOfferingIdSet.get(opOffering.Opportunity_Name__c); if(relatedOfferingIds != null && relatedOfferingIds.size() > 0){ for(Id relatedOffId : relatedOfferingIds){ if(oppRec.OwnerId != null && offeringOwner != null && oppRec.OwnerId != offeringOwner){ offOwner.put(oppRec.Id, oppRec.OwnerId); } } } } } List<User> ownerUserRecords = [select id from User where Id =: offOwner.values()]; Map<String,Opportunity_Offering__share> oppOffList = new Map<String,Opportunity_Offering__share>(); List<Opportunity_Offering__c> oppOwnerOffList= [select id,Opportunity_Name__c,ownerId from Opportunity_Offering__c where ownerId NOT IN :ownerUserRecords AND Opportunity_Name__c =: offOwner.keySet()]; for(User userRec : ownerUserRecords){ if(userRec!=null){ for(Opportunity_Offering__c offering : oppOwnerOffList){ Opportunity_Offering__share oppOfferShare = new Opportunity_Offering__share(); oppOfferShare.ParentId = offering.Id; oppOfferShare.UserOrGroupId = userRec.Id; oppOfferShare.AccessLevel = 'edit'; oppOfferShare.RowCause = 'Manual'; if(offering!=null && userRec != null){ oppOffList.put(offering.Id+'-'+userRec.Id,oppOfferShare); } } if(oppOffList.size() > 0) upsert oppOffList.values(); } } } public static void deleteNoOffering(List<Opportunity_Offering__c> opOfferingList,Boolean isUpdate){ Set<Id> oppIds = new Set<Id>(); Set<Id> curroppIds = new Set<Id>(); for(Opportunity_Offering__c oppOffering : opOfferingList){ oppIds.add(oppOffering.Opportunity_Name__c); if(!isUpdate) curroppIds.add(oppOffering.Id); } deletNoOfferingFuture(oppIds,curroppIds); } @future public static void deletNoOfferingFuture(Set<Id> oppIds,Set<Id> curroppIds){ List<Opportunity_Offering__c> oppList = [SELECT Id, OwnerId, Name, Opportunity_Name__c, Opportunity_Id__c, Virtusa_Offering__c,Virtusa_Offering__r.name FROM Opportunity_Offering__c where Opportunity_Name__c IN :oppIds AND Virtusa_Offering__r.name = 'No Offerings' AND id NOT IN :curroppIds]; if(oppList != null && oppList.size() > 0){ delete oppList; } } public static void stampOldPec(Map<Id, Opportunity_Offering__c > mapOldRecord,Map<Id, Opportunity_Offering__c > mapNewRecord){ for(Opportunity_Offering__c opOffering : mapNewRecord.values()){ if(mapOldRecord.get(opOffering.Id).Virtu_Offering_Split_p__c != null){ opOffering.Old_Offering_Split__c = mapOldRecord.get(opOffering.Id).Virtu_Offering_Split_p__c; } } } public static void validateNoOffering(List<Opportunity_Offering__c> opOfferingList){ Set<Id> oppIds = new Set<Id>(); Set<Id> virIds = new Set<Id>(); Map<Id,Boolean> oppIdToRes = new Map<Id,Boolean>(); //Boolean noOffering; for(Opportunity_Offering__c oppOffering : opOfferingList){ oppIds.add(oppOffering.Opportunity_Name__c); virIds.add(oppOffering.Virtusa_Offering__c); } Map<Id,Virtusa_Offering__c> vOfferingList = new Map<Id,Virtusa_Offering__c>([Select id,Name, Offering_Squad__c, Virtu_Squad_Email_Address__c from Virtusa_Offering__c where id In :virIds]); List<Opportunity_Offering__c> oppList = [SELECT Id, OwnerId, Name, Opportunity_Name__c, Opportunity_Id__c, Virtusa_Offering__c,Virtusa_Offering__r.name, Virtu_Offering_Split_p__c FROM Opportunity_Offering__c where Opportunity_Name__c IN :oppIds]; oppList.addAll(opOfferingList); for(Opportunity_Offering__c opp : oppList){ if(oppList.size()>0){ oppIdToRes.put(opp.Opportunity_Name__c,false); if(opp.Virtu_Offering_Split_p__c == 0){ //noOffering = true; }else{ //noOffering = false; oppIdToRes.put(opp.Opportunity_Name__c,true); } } } for(Opportunity_Offering__c opp : opOfferingList){ if(oppList.size()>0){ //if(vOfferingList.get(opp.Virtusa_Offering__c).name == 'No Offerings' && !noOffering && oppIdToRes.contains(opp.Opportunity_Name__c)){ if(vOfferingList.get(opp.Virtusa_Offering__c).name == 'No Offerings' && oppIdToRes.containsKey(opp.Opportunity_Name__c) && oppIdToRes.get(opp.Opportunity_Name__c)){ opp.addError('"No Offerings" Cannot Be Tagged If Opportunity has Offerings'); } } } } } --------------------- OpportunityOfferingSaveEditAllController.cls public without sharing class OpportunityOfferingSaveEditAllController { public static Map<String,String> statusMessage = new Map<String,String>(); @AuraEnabled public static List<OpportunityOfferingWrapper> getOfferings(Id recordId){ List<Opportunity_Offering__c> drLinesList = new List<Opportunity_Offering__c>(); List<OpportunityOfferingWrapper> drLinesWrapperList = new List<OpportunityOfferingWrapper>(); drLinesList = [select Id,Virtusa_Offering__c,Deal_Led_By__c,Virtusa_Offering__r.Name,Virtusa_Offering__r.Offering_Deal_Type__c,Virtu_Offering_Split_p__c,Opportunity_Name__c,OwnerId,Owner.Name,Opportunity_Name__r.name from Opportunity_Offering__c where Opportunity_Name__c = :recordId ]; for(Opportunity_Offering__c drRec : drLinesList){ drLinesWrapperList.add(new OpportunityOfferingWrapper(drRec)); } return drLinesWrapperList; } @AuraEnabled public static OppOfferWrapper getOppDetails(Id recordId){ Opportunity opp = [select id,name,stagename from opportunity where id = :recordId]; User userRecord = [select id,Name from User where id = :UserInfo.getUserId()]; return new OppOfferWrapper(userRecord.Id, userRecord.Name, opp.Id, opp.Name, opp.stagename); } @AuraEnabled public static Map<String,String> saveDRList(String oppId, String dealType, List<OpportunityOfferingWrapper> drLinesList){ system.debug(dealType + ' dealType'); Set<Id> oppIds = new Set<Id>(); Savepoint sp = Database.setSavepoint(); statusMessage.put('status','Success'); statusMessage.put('message','Records saved successfully'); statusMessage.put('url',URL.getOrgDomainUrl().toExternalForm()); List<Opportunity_Offering__c> oppOfferingToUpdate = new List<Opportunity_Offering__c>(); List<Opportunity_Offering__c> oppOfferingToInsert = new List<Opportunity_Offering__c>(); Map<Id,String> idVsDealType = new Map<Id,String>(); for(OpportunityOfferingWrapper drLine : drLinesList){ idVsDealType.put(drLine.VirtusaOffering,drLine.VirtusaOfferingDealType); } List<Virtusa_Offering__c> virtusaLis = [select id,Offering_Deal_Type__c from Virtusa_Offering__c where id IN :idVsDealType.keySet()]; for(Virtusa_Offering__c offer : virtusaLis){ idVsDealType.put(offer.id,offer.Offering_Deal_Type__c); } Decimal consultingSum = 0; Decimal nonConsultingSum = 0; for(OpportunityOfferingWrapper drLine : drLinesList){ String virtusaOffDealType = drLine.VirtusaOfferingDealType != null && drLine.VirtusaOfferingDealType != '' ? drLine.VirtusaOfferingDealType : idVsDealType.get(drLine.VirtusaOffering); if(virtusaOffDealType == 'Consulting'){ consultingSum = consultingSum + Decimal.valueOf(drLine.OfferingSplit); } if(virtusaOffDealType == 'Non Consulting'){ nonConsultingSum = nonConsultingSum + Decimal.valueOf(drLine.OfferingSplit); } } if(dealType == 'Consulting'){ if(consultingSum != 100 || nonConsultingSum > 50){ statusMessage.put('status','Fail'); statusMessage.put('message','For Consulting Deals it is mandatory to select one or more consulting offering with split% totaling to 100% and optional to have non consulting Offerings with up to 50% split'); if(!Test.isRunningTest()) return statusMessage; } } if(dealType == 'Non Consulting'){ if(nonConsultingSum < 5 || nonConsultingSum > 100 || consultingSum > 50){ statusMessage.put('status','Fail'); statusMessage.put('message','For Non-Consulting Deals Offering Sum of Split% can vary between 5% to max 100% and optionally Consulting Offerings Split % sum can be up to 50%'); if(!Test.isRunningTest()) return statusMessage; } } system.debug(nonConsultingSum + ' nonConsultingSum'); system.debug(consultingSum + ' consultingSum'); if(dealType == 'No Offerings Required'){ system.debug('inside if block no offering....'); if(nonConsultingSum != 0 || consultingSum != 0){ statusMessage.put('status','Fail'); statusMessage.put('message','For "No Offerings Required" Deals tagging No Offerings is only allowed'); if(!Test.isRunningTest()) return statusMessage; } } try{ Boolean isNoOfferingExist = false; String virId = ''; if(dealType == 'No Offerings Required'){ List<Opportunity_Offering__c> drLinesListNoOff = new List<Opportunity_Offering__c>(); drLinesListNoOff = [select Id,Virtusa_Offering__c,Deal_Led_By__c,Virtusa_Offering__r.Name,Virtusa_Offering__r.Offering_Deal_Type__c,Virtu_Offering_Split_p__c,Opportunity_Name__c,OwnerId,Owner.Name,Opportunity_Name__r.name from Opportunity_Offering__c where Opportunity_Name__c = :oppId and Virtu_Offering_Split_p__c = 0]; if(drLinesListNoOff.size() != 0 ) isNoOfferingExist = true; List<Virtusa_Offering__c> vir = [select id,name from Virtusa_Offering__c where name = 'No Offerings']; virId = vir[0].Id; } for(OpportunityOfferingWrapper drLine : drLinesList){ oppIds.add(drLine.opportunityId); Opportunity_Offering__c drlineRec = new Opportunity_Offering__c(); drlineRec.Virtusa_Offering__c = drLine.VirtusaOffering; if(drLine.OfferingSplit != null && drLine.OfferingSplit != '' ) drlineRec.Virtu_Offering_Split_p__c = Decimal.valueOf(drLine.OfferingSplit); drlineRec.Opportunity_Name__c = drLine.opportunityId; drlineRec.Deal_Led_By__c = dealType; if(virId == drLine.VirtusaOffering) isNoOfferingExist = true; //drLineRecordToInsert.add(drlineRec); if(drLine.Id != null && drLine.Id != ''){ drlineRec.Id = drLine.Id; oppOfferingToUpdate.add(drlineRec);//if(Decimal.valueOf(drLine.OfferingSplit) != 0) removed logic as not able to update offering to zero } else{ oppOfferingToInsert.add(drlineRec); } } if(dealType == 'No Offerings Required' && !isNoOfferingExist){ List<Opportunity_Offering__c> drLinesListNoOff = new List<Opportunity_Offering__c>(); drLinesListNoOff = [select Id,Virtusa_Offering__c,Deal_Led_By__c,Virtusa_Offering__r.Name,Virtusa_Offering__r.Offering_Deal_Type__c,Virtu_Offering_Split_p__c,Opportunity_Name__c,OwnerId,Owner.Name,Opportunity_Name__r.name from Opportunity_Offering__c where Opportunity_Name__c = :oppId and Virtu_Offering_Split_p__c != 0]; Opportunity_Offering__c drlineRec = new Opportunity_Offering__c(); drlineRec.Virtusa_Offering__c = virId; drlineRec.Virtu_Offering_Split_p__c = 0; drlineRec.Opportunity_Name__c = oppId; drlineRec.Deal_Led_By__c = dealType; if(drLinesListNoOff.size() == 0 ) oppOfferingToInsert.add(drlineRec); } Set<Id> newOfferingIds = new Set<Id>(); if(oppOfferingToInsert.size() > 0){ insert oppOfferingToInsert; for(Opportunity_Offering__c offers : oppOfferingToInsert){ newOfferingIds.add(offers.Id); } } if(oppOfferingToUpdate.size() > 0){ update oppOfferingToUpdate; } if(oppIds.size() > 0 && (oppOfferingToUpdate.size() > 0 || oppOfferingToInsert.size() > 0)){ initiateEmailNotification(oppIds,newOfferingIds); } } catch(Exception ex){ statusMessage.put('status','Fail'); String errorMsg = ex.getMessage();//Insert failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, You cannot add or edit the offerings of this opportunity: [] if(errorMsg.contains('FIELD_CUSTOM_VALIDATION_EXCEPTION')) errorMsg = errorMsg.substringAfter('FIELD_CUSTOM_VALIDATION_EXCEPTION,'); if(errorMsg.contains(': []')) errorMsg = errorMsg.substringBefore(': []').trim(); statusMessage.put('message',errorMsg); Database.rollback(sp); } return statusMessage; } @Future public static void initiateEmailNotification(Set<Id> oppIds,Set<Id> newOfferings){ Map<Id,List<Opportunity_Offering__c>> oppIdVsOfferingList = new Map<Id,List<Opportunity_Offering__c>>(); Map<Id,Opportunity> offeringOpp = new Map<Id,Opportunity>([Select id, name, Group_SBU__c, Account.Customer_Name__r.Client__r.Name, Account.Customer_Name__r.name, Account.name, Opportunity_ID__c, Deal_Type__c, StageName, Amount, CurrencyIsoCode, Opportunity_Amount_Converted_New__c, Opportunity_CS_Owner__r.Name, Owner.name, OwnerId, Owner.Email, Account.owner.name, Account.CSM__r.Name from Opportunity where id In :oppIds]); Map<Id,Opportunity_Offering__c> idVsRelOfferingRecord = new Map<Id,Opportunity_Offering__c>([select id,Name, Opportunity_Name__c,Virtusa_Offering__c, Virtusa_Offering__r.Offering_Squad__c, Virtu_Offering_Split_p__c, Old_Offering_Split__c, Deal_Led_By__c, Owner.name, Virtusa_Offering__r.Name from Opportunity_Offering__c where Opportunity_Name__c IN :oppIds]); Set<String> squadTeam = new Set<String>(); Map<Id,String> virtusaIdVsSquad = new Map<Id,String>(); for(Opportunity_Offering__c offer : idVsRelOfferingRecord.values()){ if(offer.Virtusa_Offering__c != null && offer.Virtusa_Offering__r.Offering_Squad__c != null){ if(offer.Virtu_Offering_Split_p__c != 0 || (offer.Virtu_Offering_Split_p__c == 0 && offer.Virtu_Offering_Split_p__c != offer.Old_Offering_Split__c)) squadTeam.add(offer.Virtusa_Offering__r.Offering_Squad__c); virtusaIdVsSquad.put(offer.Virtusa_Offering__c,offer.Virtusa_Offering__r.Offering_Squad__c); } if(oppIdVsOfferingList.containsKey(offer.Opportunity_Name__c)){ oppIdVsOfferingList.get(offer.Opportunity_Name__c).add(offer); }else{ oppIdVsOfferingList.put(offer.Opportunity_Name__c,new List<Opportunity_Offering__c>{offer}); } } Map<String,String> emailVsName = new Map<String,String>(); String slist = ''; for (String s: squadTeam) { slist += '\'' + s + '\','; } system.debug(',slist' + slist); slist = slist.removeEnd(','); String value = '(\'' + String.join(squadTeam, '\',\'') + '\')'; String queryString = 'select id,email,name,Offering_squad_Leader__c,Off_Squad_Team_del__c'+ ' from contact' + ' where email != null and ' + ' Offering_squad_Leader__c = true and ' + ' Off_Squad_Team_del__c includes' + value; List<Contact> contactList = DataBase.query(queryString); system.debug('List of records: '+contactList); /*Map<Id,Contact> contactList = new Map<Id,Contact>([select id,email,name,Offering_squad_Leader__c,Off_Squad_Team_del__c from contact where email != null and Offering_squad_Leader__c = true and Off_Squad_Team_del__c includes (:slist)]);*/ system.debug(',contactList' + contactList); Map<Id,List<String>> virOffIdVsEmail = new Map<Id,List<String>>(); Map<String,Set<Id>> emailVsVirtusaId = new Map<String,Set<Id>>(); for(Id virId : virtusaIdVsSquad.keySet()){ for(Contact con : contactList){ emailVsName.put(con.email,con.name); if(virtusaIdVsSquad.get(virId) != null && con.Off_Squad_Team_del__c.contains(virtusaIdVsSquad.get(virId))){ if(!virOffIdVsEmail.containskey(virId))virOffIdVsEmail.put(virId,new List<String>{con.email}); else{ virOffIdVsEmail.get(virId).add(con.email); } } } } for(Id oppId : oppIdVsOfferingList.keySet()){ Set<String> to = new Set<String>(); Opportunity opp = offeringOpp.get(oppId); if(opp.owner.email != null){ to.add(opp.owner.email); emailVsName.put(opp.owner.email,opp.owner.name); } for(Opportunity_Offering__c oppOffer : oppIdVsOfferingList.get(oppId)){ Id relatedOffId = oppOffer.Id; if(virOffIdVsEmail != null && idVsRelOfferingRecord != null && idVsRelOfferingRecord.get(relatedOffId) != null && virOffIdVsEmail.get(idVsRelOfferingRecord.get(relatedOffId).Virtusa_Offering__c) != null) to.addAll(virOffIdVsEmail.get(idVsRelOfferingRecord.get(relatedOffId).Virtusa_Offering__c)); if(virOffIdVsEmail != null && virOffIdVsEmail.get(oppOffer.Virtusa_Offering__c) != null){ to.addAll(virOffIdVsEmail.get(oppOffer.Virtusa_Offering__c)); } } String subject = 'Virtusa Offering Notification'; String body = ''; body = 'Hi All,<br/><br/> Following offerings have tagged to the opportunity.<br/><br/>'; String dealLeadBy = oppIdVsOfferingList.get(oppId).size() > 1 ? oppIdVsOfferingList.get(oppId)[1].Deal_Led_By__c : oppIdVsOfferingList.get(oppId)[0].Deal_Led_By__c; body = body + '<b><u>Opportunity Details</b></u><br/><br/>'+ '<li>Deal Lead By - '+dealLeadBy + '</li>'+ '<li>Group SBU - '+offeringOpp.get(oppId).Group_SBU__c+'</li>'+ '<li>Account - '+offeringOpp.get(oppId).Account.name+'</li>'+ '<li>Opportunity ID - <a href="'+ URL.getOrgDomainUrl().toExternalForm() +'/'+oppId+'">'+offeringOpp.get(oppId).Opportunity_ID__c+'</a></li>'+ '<li>Opportunity Name - '+offeringOpp.get(oppId).name + '</li>'+ '<li>Stage - '+offeringOpp.get(oppId).StageName+'</li>'+ '<li>Amount (converted) - '+'USD'+' '+offeringOpp.get(oppId).Opportunity_Amount_Converted_New__c+'</li>'+ '<li>Opportunity Owner - '+offeringOpp.get(oppId).Owner.name + '</li>'+ '<br/><br/>'; body = body + '<b><u>Offering Details</b></u><br/><br/>'; String tableHtml = '<table style="border-collapse: collapse;">'; tableHtml += '<thead>'; tableHtml += '<tr>'; tableHtml += '<th style="font-weight: bold; border: 1px solid black; padding: 8px;">SR. No</th>'; tableHtml += '<th style="font-weight: bold; border: 1px solid black; padding: 8px;">Virtusa Offering Name</th>'; tableHtml += '<th style="font-weight: bold; border: 1px solid black; padding: 8px;">Old Split%</th>'; tableHtml += '<th style="font-weight: bold; border: 1px solid black; padding: 8px;">New Split%</th>'; tableHtml += '<th style="font-weight: bold; border: 1px solid black; padding: 8px;">Is Modified</th>'; tableHtml += '</tr>'; tableHtml += '</thead>'; tableHtml += '<tbody>'; Integer count = 1; List<Opportunity_Offering__c> offerList = oppIdVsOfferingList.get(oppId); for(Opportunity_Offering__c oppOffer : offerList){ if(offerList.size() == 1 || (offerList.size() > 1 && oppOffer.Virtusa_Offering__r.Name != 'No Offerings')){ tableHtml += '<tr>'; tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + count + '</td>'; tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + oppOffer.Virtusa_Offering__r.Name + '</td>'; String oldSplit = oppOffer.Old_Offering_Split__c == null ? '-' : oppOffer.Old_Offering_Split__c.setScale(2) + ''; if(newOfferings.contains(oppOffer.Id)) oldSplit = '-'; tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + oldSplit + '</td>'; //else tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + oppOffer.Old_Offering_Split__c + '</td>'; tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + oppOffer.Virtu_Offering_Split_p__c + '</td>'; Boolean isNotChange = oppOffer.Old_Offering_Split__c == null || oppOffer.Virtu_Offering_Split_p__c == oppOffer.Old_Offering_Split__c; String isChanged = !isNotChange == true ? 'Yes' : 'No'; tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + isChanged + '</td>'; tableHtml += '</tr>'; count++; } } tableHtml += '</tbody>'; tableHtml += '</table>'; body = body + tableHtml + '<br/><br/>'; body = body + 'Thanks,<br/> System Administrator'; String repmail = ''; SingleEmailUtility seu = new SingleEmailUtility(); List<String> ccAddress = new List<String>(); seu.sendMail(new List<String>(to), ccAddress, '', subject, body); } } public class OppOfferWrapper{ @auraEnabled public string currentUserId{get;set;} @auraEnabled public string currentName{get;set;} @auraEnabled public string OpportunityName{get;set;} @auraEnabled public string OpportunityId{get;set;} @auraEnabled public string opportunityStageName{get;set;} public OppOfferWrapper(String userId, String userName, String oppId, String oppName, String oppStage){ this.currentUserId = userId; this.currentName = userName; this.OpportunityName = oppName; this.OpportunityId = oppId; this.opportunityStageName = oppStage; } } } ------------------------ OpportunityOfferingTriggerHelper.cls public without sharing class OpportunityOfferingTriggerHelper { @future public static void createShareRecordsFutureContext(Set<Id> offeringIds){ if(offeringIds != null)createShareRecords(offeringIds); } public static void createShareRecords(Set<Id> offeringIds){ Map<Id,Id> oppOfferIdVsOppId = new Map<Id,Id>(); Map<Id,Id> virOfferIdVsOppId = new Map<Id,Id>(); Map<Id,Set<Id>> oppIdVsOfferingIdSet = new Map<Id,Set<Id>>(); List<Opportunity_Offering__c> opOfferingList = new List<Opportunity_Offering__c>(); opOfferingList = [select id,Opportunity_Name__c,Virtusa_Offering__c from Opportunity_Offering__c where id IN :offeringIds]; for(Opportunity_Offering__c opOffering : opOfferingList){ oppOfferIdVsOppId.put(opOffering.Id,opOffering.Opportunity_Name__c); virOfferIdVsOppId.put(opOffering.Id,opOffering.Virtusa_Offering__c); if(!oppIdVsOfferingIdSet.containsKey(opOffering.Opportunity_Name__c)){ oppIdVsOfferingIdSet.put(opOffering.Opportunity_Name__c,new Set<Id>{opOffering.Id}); }else{ oppIdVsOfferingIdSet.get(opOffering.Opportunity_Name__c).add(opOffering.Id); } } Map<Id,Opportunity> offeringOpp = new Map<Id,Opportunity>([Select id, name from Opportunity where id In :oppOfferIdVsOppId.values() ]); Map<Id,Opportunity_Offering__c> idVsRelOfferingRecord = new Map<Id,Opportunity_Offering__c>([select id, Opportunity_Name__c,Virtusa_Offering__c from Opportunity_Offering__c where Opportunity_Name__c IN :offeringOpp.keySet() and ID Not In :oppOfferIdVsOppId.keySet()]); for(Opportunity_Offering__c opOffering : idVsRelOfferingRecord.values()){ oppOfferIdVsOppId.put(opOffering.Id,opOffering.Opportunity_Name__c); virOfferIdVsOppId.put(opOffering.Id,opOffering.Virtusa_Offering__c); if(!oppIdVsOfferingIdSet.containsKey(opOffering.Opportunity_Name__c)){ oppIdVsOfferingIdSet.put(opOffering.Opportunity_Name__c,new Set<Id>{opOffering.Id}); }else{ oppIdVsOfferingIdSet.get(opOffering.Opportunity_Name__c).add(opOffering.Id); } } Map<Id,Virtusa_Offering__c> vOfferingList = new Map<Id,Virtusa_Offering__c>([Select id, Offering_Squad__c, Virtu_Squad_Email_Address__c from Virtusa_Offering__c where id In :virOfferIdVsOppId.values() ]); Set<String> squadTeam = new Set<String>(); for(Virtusa_Offering__c vr : vOfferingList.values()){ if(vr.Offering_Squad__c != null) squadTeam.add(vr.Offering_Squad__c); } Map<Id,List<String>> virOffIdVsEmail = new Map<Id,List<String>>(); Map<String,Set<Id>> emailVsVirtusaId = new Map<String,Set<Id>>(); String slist = ''; for (String s: squadTeam) { slist += '\'' + s + '\','; } String value = '(\'' + String.join(squadTeam, '\',\'') + '\')'; String queryString = 'select id,email,name,Offering_squad_Leader__c,Off_Squad_Team_del__c'+ ' from contact' + ' where email != null and ' + ' Offering_squad_Leader__c = true and ' + ' Off_Squad_Team_del__c includes' + value; List<Contact> contactList = DataBase.query(queryString); for(Virtusa_Offering__c vr : vOfferingList.values()){ if(vr.Offering_Squad__c != null){ for(Contact con : contactList){ if(con.Off_Squad_Team_del__c.contains(vr.Offering_Squad__c)){ //emailVsName.put(con.email,con.name); if(!emailVsVirtusaId.containskey(con.email)){ emailVsVirtusaId.put(con.email,new Set<Id>{vr.Id}); } else{ emailVsVirtusaId.get(con.email).add(vr.Id); } if(!virOffIdVsEmail.containskey(vr.Id)){ virOffIdVsEmail.put(vr.Id,new List<String>{con.email}); } else{ virOffIdVsEmail.get(vr.Id).add(con.email); } } } } } Set<String> toAddresses = new Set<String>(); for(Opportunity_Offering__c opOffering : opOfferingList){ Set<String> to = new Set<String>(); if(offeringOpp.get(opOffering.Opportunity_Name__c) != null){ Set<Id> relatedOfferingIds = oppIdVsOfferingIdSet.get(opOffering.Opportunity_Name__c); if(relatedOfferingIds != null && relatedOfferingIds.size() > 0){ for(Id relatedOffId : relatedOfferingIds){ if(virOffIdVsEmail != null && idVsRelOfferingRecord != null && idVsRelOfferingRecord.get(relatedOffId) != null && idVsRelOfferingRecord.get(relatedOffId).Virtusa_Offering__c != null ) to.addAll(virOffIdVsEmail.get(idVsRelOfferingRecord.get(relatedOffId).Virtusa_Offering__c)); } } } if(virOffIdVsEmail != null && virOffIdVsEmail.get(opOffering.Virtusa_Offering__c) != null){ to.addAll(virOffIdVsEmail.get(opOffering.Virtusa_Offering__c)); } if(to.size() > 0) toAddresses.addAll(to); } List<User> userRecords = [select id,email from User where email IN :toAddresses]; Map<String,Opportunity_Offering__share> oppOffList = new Map<String,Opportunity_Offering__share>(); for(User userRec : userRecords){ if(emailVsVirtusaId != null && emailVsVirtusaId.get(userRec.email) != null){ Set<Id> virtusaIds = emailVsVirtusaId.get(userRec.email); for(Id oppOfferId : virOfferIdVsOppId.keySet()){ Set<Id> offerIds = oppIdVsOfferingIdSet.get(oppOfferIdVsOppId.get(oppOfferId)); if(virtusaIds.contains(virOfferIdVsOppId.get(oppOfferId))){ for(Id offerId : offerIds){ Opportunity_Offering__share oppOfferShare = new Opportunity_Offering__share(); oppOfferShare.ParentId = offerId; oppOfferShare.UserOrGroupId = userRec.Id; oppOfferShare.AccessLevel = 'edit'; oppOfferShare.RowCause = 'Manual'; if(offerId != null && userRec != null) oppOffList.put(offerId+'-'+userRec.Id,oppOfferShare); } } } } } if(oppOffList.size() > 0) Database.upsert(oppOffList.values(),false); } //Author - Viji //Arguments - opOfferingList -> list of opportunity offering record //Purpose - called from after update,after insert //Date - 21/03/2023 @future public static void updateOffOwnerAccessToOppOwnerHelper(Set<Id> offeringIds){ createShareRecordsForOppOwner(offeringIds); } public static void createShareRecordsForOppOwner(Set<Id> offeringIds){ Map<Id,Id> oppOfferIdVsOppId = new Map<Id,Id>(); Map<Id,Set<Id>> oppIdVsOfferingIdSet = new Map<Id,Set<Id>>(); Map<Id,Id> offOwner = new Map<Id,Id>(); List<Opportunity_Offering__c> opOfferingList = new List<Opportunity_Offering__c>(); opOfferingList = [select id,Opportunity_Name__c,Virtusa_Offering__c,OwnerId from Opportunity_Offering__c where id IN :offeringIds]; for(Opportunity_Offering__c oppOffering : opOfferingList){ oppOfferIdVsOppId.put(oppOffering.id,oppOffering.Opportunity_Name__c); if(!oppIdVsOfferingIdSet.containsKey(oppOffering.Opportunity_Name__c)){ oppIdVsOfferingIdSet.put(oppOffering.Opportunity_Name__c,new Set<Id>{oppOffering.Id}); }else{ oppIdVsOfferingIdSet.get(oppOffering.Opportunity_Name__c).add(oppOffering.Id); } } Map<Id,Opportunity> offeringOpp = new Map<Id,Opportunity>([Select id, name,stagename,ownerid from Opportunity where id In :oppOfferIdVsOppId.values() ]); for(Opportunity_Offering__c opOffering : opOfferingList){ Opportunity oppRec = offeringOpp.get(opOffering.Opportunity_Name__c); Id offeringOwner = opOffering.ownerId; if(oppRec != null){ Set<Id> relatedOfferingIds = oppIdVsOfferingIdSet.get(opOffering.Opportunity_Name__c); if(relatedOfferingIds != null && relatedOfferingIds.size() > 0){ for(Id relatedOffId : relatedOfferingIds){ if(oppRec.OwnerId != null && offeringOwner != null && oppRec.OwnerId != offeringOwner){ offOwner.put(oppRec.Id, oppRec.OwnerId); } } } } } List<User> ownerUserRecords = [select id from User where Id =: offOwner.values()]; Map<String,Opportunity_Offering__share> oppOffList = new Map<String,Opportunity_Offering__share>(); List<Opportunity_Offering__c> oppOwnerOffList= [select id,Opportunity_Name__c,ownerId from Opportunity_Offering__c where ownerId NOT IN :ownerUserRecords AND Opportunity_Name__c =: offOwner.keySet()]; for(User userRec : ownerUserRecords){ if(userRec!=null){ for(Opportunity_Offering__c offering : oppOwnerOffList){ Opportunity_Offering__share oppOfferShare = new Opportunity_Offering__share(); oppOfferShare.ParentId = offering.Id; oppOfferShare.UserOrGroupId = userRec.Id; oppOfferShare.AccessLevel = 'edit'; oppOfferShare.RowCause = 'Manual'; if(offering!=null && userRec != null){ oppOffList.put(offering.Id+'-'+userRec.Id,oppOfferShare); } } if(oppOffList.size() > 0) upsert oppOffList.values(); } } } public static void deleteNoOffering(List<Opportunity_Offering__c> opOfferingList,Boolean isUpdate){ Set<Id> oppIds = new Set<Id>(); Set<Id> curroppIds = new Set<Id>(); for(Opportunity_Offering__c oppOffering : opOfferingList){ oppIds.add(oppOffering.Opportunity_Name__c); if(!isUpdate) curroppIds.add(oppOffering.Id); } deletNoOfferingFuture(oppIds,curroppIds); } @future public static void deletNoOfferingFuture(Set<Id> oppIds,Set<Id> curroppIds){ List<Opportunity_Offering__c> oppList = [SELECT Id, OwnerId, Name, Opportunity_Name__c, Opportunity_Id__c, Virtusa_Offering__c,Virtusa_Offering__r.name FROM Opportunity_Offering__c where Opportunity_Name__c IN :oppIds AND Virtusa_Offering__r.name = 'No Offerings' AND id NOT IN :curroppIds]; if(oppList != null && oppList.size() > 0){ delete oppList; } } public static void stampOldPec(Map<Id, Opportunity_Offering__c > mapOldRecord,Map<Id, Opportunity_Offering__c > mapNewRecord){ for(Opportunity_Offering__c opOffering : mapNewRecord.values()){ if(mapOldRecord.get(opOffering.Id).Virtu_Offering_Split_p__c != null){ opOffering.Old_Offering_Split__c = mapOldRecord.get(opOffering.Id).Virtu_Offering_Split_p__c; } } } public static void validateNoOffering(List<Opportunity_Offering__c> opOfferingList){ Set<Id> oppIds = new Set<Id>(); Set<Id> virIds = new Set<Id>(); Map<Id,Boolean> oppIdToRes = new Map<Id,Boolean>(); //Boolean noOffering; for(Opportunity_Offering__c oppOffering : opOfferingList){ oppIds.add(oppOffering.Opportunity_Name__c); virIds.add(oppOffering.Virtusa_Offering__c); } Map<Id,Virtusa_Offering__c> vOfferingList = new Map<Id,Virtusa_Offering__c>([Select id,Name, Offering_Squad__c, Virtu_Squad_Email_Address__c from Virtusa_Offering__c where id In :virIds]); List<Opportunity_Offering__c> oppList = [SELECT Id, OwnerId, Name, Opportunity_Name__c, Opportunity_Id__c, Virtusa_Offering__c,Virtusa_Offering__r.name, Virtu_Offering_Split_p__c FROM Opportunity_Offering__c where Opportunity_Name__c IN :oppIds]; oppList.addAll(opOfferingList); for(Opportunity_Offering__c opp : oppList){ if(oppList.size()>0){ oppIdToRes.put(opp.Opportunity_Name__c,false); if(opp.Virtu_Offering_Split_p__c == 0){ //noOffering = true; }else{ //noOffering = false; oppIdToRes.put(opp.Opportunity_Name__c,true); } } } for(Opportunity_Offering__c opp : opOfferingList){ if(oppList.size()>0){ //if(vOfferingList.get(opp.Virtusa_Offering__c).name == 'No Offerings' && !noOffering && oppIdToRes.contains(opp.Opportunity_Name__c)){ if(vOfferingList.get(opp.Virtusa_Offering__c).name == 'No Offerings' && oppIdToRes.containsKey(opp.Opportunity_Name__c) && oppIdToRes.get(opp.Opportunity_Name__c)){ opp.addError('"No Offerings" Cannot Be Tagged If Opportunity has Offerings'); } } } } } -------------------FULLC REAL-------------- OpportunityOfferingSaveEditAllController public without sharing class OpportunityOfferingSaveEditAllController { public static Map<String,String> statusMessage = new Map<String,String>(); @AuraEnabled public static List<OpportunityOfferingWrapper> getOfferings(Id recordId){ List<Opportunity_Offering__c> drLinesList = new List<Opportunity_Offering__c>(); List<OpportunityOfferingWrapper> drLinesWrapperList = new List<OpportunityOfferingWrapper>(); drLinesList = [select Id,Virtusa_Offering__c,Deal_Led_By__c,Virtusa_Offering__r.Name,Virtusa_Offering__r.Offering_Deal_Type__c,Virtu_Offering_Split_p__c,Opportunity_Name__c,OwnerId,Owner.Name,Opportunity_Name__r.name from Opportunity_Offering__c where Opportunity_Name__c = :recordId ]; for(Opportunity_Offering__c drRec : drLinesList){ drLinesWrapperList.add(new OpportunityOfferingWrapper(drRec)); } return drLinesWrapperList; } @AuraEnabled public static OppOfferWrapper getOppDetails(Id recordId){ Opportunity opp = [select id,name,stagename from opportunity where id = :recordId]; User userRecord = [select id,Name from User where id = :UserInfo.getUserId()]; return new OppOfferWrapper(userRecord.Id, userRecord.Name, opp.Id, opp.Name, opp.stagename); } @AuraEnabled public static Map<String,String> saveDRList(String oppId, String dealType, List<OpportunityOfferingWrapper> drLinesList){ system.debug(dealType + ' dealType'); Set<Id> oppIds = new Set<Id>(); Savepoint sp = Database.setSavepoint(); statusMessage.put('status','Success'); statusMessage.put('message','Records saved successfully'); statusMessage.put('url',URL.getOrgDomainUrl().toExternalForm()); List<Opportunity_Offering__c> oppOfferingToUpdate = new List<Opportunity_Offering__c>(); List<Opportunity_Offering__c> oppOfferingToInsert = new List<Opportunity_Offering__c>(); Map<Id,String> idVsDealType = new Map<Id,String>(); for(OpportunityOfferingWrapper drLine : drLinesList){ idVsDealType.put(drLine.VirtusaOffering,drLine.VirtusaOfferingDealType); } List<Virtusa_Offering__c> virtusaLis = [select id,Offering_Deal_Type__c from Virtusa_Offering__c where id IN :idVsDealType.keySet()]; for(Virtusa_Offering__c offer : virtusaLis){ idVsDealType.put(offer.id,offer.Offering_Deal_Type__c); } Decimal consultingSum = 0; Decimal nonConsultingSum = 0; for(OpportunityOfferingWrapper drLine : drLinesList){ String virtusaOffDealType = drLine.VirtusaOfferingDealType != null && drLine.VirtusaOfferingDealType != '' ? drLine.VirtusaOfferingDealType : idVsDealType.get(drLine.VirtusaOffering); if(virtusaOffDealType == 'Consulting'){ consultingSum = consultingSum + Decimal.valueOf(drLine.OfferingSplit); } if(virtusaOffDealType == 'Non Consulting'){ nonConsultingSum = nonConsultingSum + Decimal.valueOf(drLine.OfferingSplit); } } if(dealType == 'Consulting'){ if(consultingSum != 100 || nonConsultingSum > 50){ statusMessage.put('status','Fail'); statusMessage.put('message','For Consulting Deals it is mandatory to select one or more consulting offering with split% totaling to 100% and optional to have non consulting Offerings with up to 50% split'); if(!Test.isRunningTest()) return statusMessage; } } if(dealType == 'Non Consulting'){ if(nonConsultingSum < 5 || nonConsultingSum > 100 || consultingSum > 50){ statusMessage.put('status','Fail'); statusMessage.put('message','For Non-Consulting Deals Offering Sum of Split% can vary between 5% to max 100% and optionally Consulting Offerings Split % sum can be up to 50%'); if(!Test.isRunningTest()) return statusMessage; } } system.debug(nonConsultingSum + ' nonConsultingSum'); system.debug(consultingSum + ' consultingSum'); if(dealType == 'No Offerings Required'){ system.debug('inside if block no offering....'); if(nonConsultingSum != 0 || consultingSum != 0){ statusMessage.put('status','Fail'); statusMessage.put('message','For "No Offerings Required" Deals tagging No Offerings is only allowed'); if(!Test.isRunningTest()) return statusMessage; } } try{ Boolean isNoOfferingExist = false; String virId = ''; if(dealType == 'No Offerings Required'){ List<Opportunity_Offering__c> drLinesListNoOff = new List<Opportunity_Offering__c>(); drLinesListNoOff = [select Id,Virtusa_Offering__c,Deal_Led_By__c,Virtusa_Offering__r.Name,Virtusa_Offering__r.Offering_Deal_Type__c,Virtu_Offering_Split_p__c,Opportunity_Name__c,OwnerId,Owner.Name,Opportunity_Name__r.name from Opportunity_Offering__c where Opportunity_Name__c = :oppId and Virtu_Offering_Split_p__c = 0]; if(drLinesListNoOff.size() != 0 ) isNoOfferingExist = true; List<Virtusa_Offering__c> vir = [select id,name from Virtusa_Offering__c where name = 'No Offerings']; virId = vir[0].Id; } for(OpportunityOfferingWrapper drLine : drLinesList){ oppIds.add(drLine.opportunityId); Opportunity_Offering__c drlineRec = new Opportunity_Offering__c(); drlineRec.Virtusa_Offering__c = drLine.VirtusaOffering; if(drLine.OfferingSplit != null && drLine.OfferingSplit != '' ) drlineRec.Virtu_Offering_Split_p__c = Decimal.valueOf(drLine.OfferingSplit); drlineRec.Opportunity_Name__c = drLine.opportunityId; drlineRec.Deal_Led_By__c = dealType; if(virId == drLine.VirtusaOffering) isNoOfferingExist = true; //drLineRecordToInsert.add(drlineRec); if(drLine.Id != null && drLine.Id != ''){ drlineRec.Id = drLine.Id; oppOfferingToUpdate.add(drlineRec);//if(Decimal.valueOf(drLine.OfferingSplit) != 0) removed logic as not able to update offering to zero } else{ oppOfferingToInsert.add(drlineRec); } } if(dealType == 'No Offerings Required' && !isNoOfferingExist){ List<Opportunity_Offering__c> drLinesListNoOff = new List<Opportunity_Offering__c>(); drLinesListNoOff = [select Id,Virtusa_Offering__c,Deal_Led_By__c,Virtusa_Offering__r.Name,Virtusa_Offering__r.Offering_Deal_Type__c,Virtu_Offering_Split_p__c,Opportunity_Name__c,OwnerId,Owner.Name,Opportunity_Name__r.name from Opportunity_Offering__c where Opportunity_Name__c = :oppId and Virtu_Offering_Split_p__c != 0]; Opportunity_Offering__c drlineRec = new Opportunity_Offering__c(); drlineRec.Virtusa_Offering__c = virId; drlineRec.Virtu_Offering_Split_p__c = 0; drlineRec.Opportunity_Name__c = oppId; drlineRec.Deal_Led_By__c = dealType; if(drLinesListNoOff.size() == 0 ) oppOfferingToInsert.add(drlineRec); } Set<Id> newOfferingIds = new Set<Id>(); if(oppOfferingToInsert.size() > 0){ insert oppOfferingToInsert; for(Opportunity_Offering__c offers : oppOfferingToInsert){ newOfferingIds.add(offers.Id); } } if(oppOfferingToUpdate.size() > 0){ update oppOfferingToUpdate; } if(oppIds.size() > 0 && (oppOfferingToUpdate.size() > 0 || oppOfferingToInsert.size() > 0)){ initiateEmailNotification(oppIds,newOfferingIds); } } catch(Exception ex){ statusMessage.put('status','Fail'); String errorMsg = ex.getMessage();//Insert failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, You cannot add or edit the offerings of this opportunity: [] if(errorMsg.contains('FIELD_CUSTOM_VALIDATION_EXCEPTION')) errorMsg = errorMsg.substringAfter('FIELD_CUSTOM_VALIDATION_EXCEPTION,'); if(errorMsg.contains(': []')) errorMsg = errorMsg.substringBefore(': []').trim(); statusMessage.put('message',errorMsg); Database.rollback(sp); } return statusMessage; } @Future public static void initiateEmailNotification(Set<Id> oppIds,Set<Id> newOfferings){ Map<Id,List<Opportunity_Offering__c>> oppIdVsOfferingList = new Map<Id,List<Opportunity_Offering__c>>(); Map<Id,Opportunity> offeringOpp = new Map<Id,Opportunity>([Select id, name, Group_SBU__c, Account.Customer_Name__r.Client__r.Name, Account.Customer_Name__r.name, Account.name, Opportunity_ID__c, Deal_Type__c, StageName, Amount, CurrencyIsoCode, Opportunity_Amount_Converted_New__c, Opportunity_CS_Owner__r.Name, Owner.name, OwnerId, Owner.Email, Account.owner.name, Account.CSM__r.Name from Opportunity where id In :oppIds]); Map<Id,Opportunity_Offering__c> idVsRelOfferingRecord = new Map<Id,Opportunity_Offering__c>([select id,Name, Opportunity_Name__c,Virtusa_Offering__c, Virtusa_Offering__r.Offering_Squad__c, Virtu_Offering_Split_p__c, Old_Offering_Split__c, Deal_Led_By__c, Owner.name, Virtusa_Offering__r.Name from Opportunity_Offering__c where Opportunity_Name__c IN :oppIds]); Set<String> squadTeam = new Set<String>(); Map<Id,String> virtusaIdVsSquad = new Map<Id,String>(); for(Opportunity_Offering__c offer : idVsRelOfferingRecord.values()){ if(offer.Virtusa_Offering__c != null && offer.Virtusa_Offering__r.Offering_Squad__c != null){ if(offer.Virtu_Offering_Split_p__c != 0 || (offer.Virtu_Offering_Split_p__c == 0 && offer.Virtu_Offering_Split_p__c != offer.Old_Offering_Split__c)) squadTeam.add(offer.Virtusa_Offering__r.Offering_Squad__c); virtusaIdVsSquad.put(offer.Virtusa_Offering__c,offer.Virtusa_Offering__r.Offering_Squad__c); } if(oppIdVsOfferingList.containsKey(offer.Opportunity_Name__c)){ oppIdVsOfferingList.get(offer.Opportunity_Name__c).add(offer); }else{ oppIdVsOfferingList.put(offer.Opportunity_Name__c,new List<Opportunity_Offering__c>{offer}); } } Map<String,String> emailVsName = new Map<String,String>(); String slist = ''; for (String s: squadTeam) { slist += '\'' + s + '\','; } system.debug(',slist' + slist); slist = slist.removeEnd(','); String value = '(\'' + String.join(squadTeam, '\',\'') + '\')'; String queryString = 'select id,email,name,Offering_squad_Leader__c,Off_Squad_Team_del__c'+ ' from contact' + ' where email != null and ' + ' Offering_squad_Leader__c = true and ' + ' Off_Squad_Team_del__c includes' + value; List<Contact> contactList = DataBase.query(queryString); system.debug('List of records: '+contactList); /*Map<Id,Contact> contactList = new Map<Id,Contact>([select id,email,name,Offering_squad_Leader__c,Off_Squad_Team_del__c from contact where email != null and Offering_squad_Leader__c = true and Off_Squad_Team_del__c includes (:slist)]);*/ system.debug(',contactList' + contactList); Map<Id,List<String>> virOffIdVsEmail = new Map<Id,List<String>>(); Map<String,Set<Id>> emailVsVirtusaId = new Map<String,Set<Id>>(); for(Id virId : virtusaIdVsSquad.keySet()){ for(Contact con : contactList){ emailVsName.put(con.email,con.name); if(virtusaIdVsSquad.get(virId) != null && con.Off_Squad_Team_del__c.contains(virtusaIdVsSquad.get(virId))){ if(!virOffIdVsEmail.containskey(virId))virOffIdVsEmail.put(virId,new List<String>{con.email}); else{ virOffIdVsEmail.get(virId).add(con.email); } } } } for(Id oppId : oppIdVsOfferingList.keySet()){ Set<String> to = new Set<String>(); Opportunity opp = offeringOpp.get(oppId); if(opp.owner.email != null){ to.add(opp.owner.email); emailVsName.put(opp.owner.email,opp.owner.name); } for(Opportunity_Offering__c oppOffer : oppIdVsOfferingList.get(oppId)){ Id relatedOffId = oppOffer.Id; if(virOffIdVsEmail != null && idVsRelOfferingRecord != null && idVsRelOfferingRecord.get(relatedOffId) != null && virOffIdVsEmail.get(idVsRelOfferingRecord.get(relatedOffId).Virtusa_Offering__c) != null) to.addAll(virOffIdVsEmail.get(idVsRelOfferingRecord.get(relatedOffId).Virtusa_Offering__c)); if(virOffIdVsEmail != null && virOffIdVsEmail.get(oppOffer.Virtusa_Offering__c) != null){ to.addAll(virOffIdVsEmail.get(oppOffer.Virtusa_Offering__c)); } } String subject = 'Virtusa Offering Notification'; String body = ''; body = 'Hi All,<br/><br/> Following offerings have tagged to the opportunity.<br/><br/>'; String dealLeadBy = oppIdVsOfferingList.get(oppId).size() > 1 ? oppIdVsOfferingList.get(oppId)[1].Deal_Led_By__c : oppIdVsOfferingList.get(oppId)[0].Deal_Led_By__c; body = body + '<b><u>Opportunity Details</b></u><br/><br/>'+ '<li>Deal Lead By - '+dealLeadBy + '</li>'+ '<li>Group SBU - '+offeringOpp.get(oppId).Group_SBU__c+'</li>'+ '<li>Account - '+offeringOpp.get(oppId).Account.name+'</li>'+ '<li>Opportunity ID - <a href="'+ URL.getOrgDomainUrl().toExternalForm() +'/'+oppId+'">'+offeringOpp.get(oppId).Opportunity_ID__c+'</a></li>'+ '<li>Opportunity Name - '+offeringOpp.get(oppId).name + '</li>'+ '<li>Stage - '+offeringOpp.get(oppId).StageName+'</li>'+ '<li>Amount (converted) - '+'USD'+' '+offeringOpp.get(oppId).Opportunity_Amount_Converted_New__c+'</li>'+ '<li>Opportunity Owner - '+offeringOpp.get(oppId).Owner.name + '</li>'+ '<br/><br/>'; body = body + '<b><u>Offering Details</b></u><br/><br/>'; String tableHtml = '<table style="border-collapse: collapse;">'; tableHtml += '<thead>'; tableHtml += '<tr>'; tableHtml += '<th style="font-weight: bold; border: 1px solid black; padding: 8px;">SR. No</th>'; tableHtml += '<th style="font-weight: bold; border: 1px solid black; padding: 8px;">Virtusa Offering Name</th>'; tableHtml += '<th style="font-weight: bold; border: 1px solid black; padding: 8px;">Old Split%</th>'; tableHtml += '<th style="font-weight: bold; border: 1px solid black; padding: 8px;">New Split%</th>'; tableHtml += '<th style="font-weight: bold; border: 1px solid black; padding: 8px;">Is Modified</th>'; tableHtml += '</tr>'; tableHtml += '</thead>'; tableHtml += '<tbody>'; Integer count = 1; List<Opportunity_Offering__c> offerList = oppIdVsOfferingList.get(oppId); for(Opportunity_Offering__c oppOffer : offerList){ if(offerList.size() == 1 || (offerList.size() > 1 && oppOffer.Virtusa_Offering__r.Name != 'No Offerings')){ tableHtml += '<tr>'; tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + count + '</td>'; tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + oppOffer.Virtusa_Offering__r.Name + '</td>'; String oldSplit = oppOffer.Old_Offering_Split__c == null ? '-' : oppOffer.Old_Offering_Split__c.setScale(2) + ''; if(newOfferings.contains(oppOffer.Id)) oldSplit = '-'; tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + oldSplit + '</td>'; //else tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + oppOffer.Old_Offering_Split__c + '</td>'; tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + oppOffer.Virtu_Offering_Split_p__c + '</td>'; Boolean isNotChange = oppOffer.Old_Offering_Split__c == null || oppOffer.Virtu_Offering_Split_p__c == oppOffer.Old_Offering_Split__c; String isChanged = !isNotChange == true ? 'Yes' : 'No'; tableHtml += '<td style="border: 1px solid black; padding: 8px;">' + isChanged + '</td>'; tableHtml += '</tr>'; count++; } } tableHtml += '</tbody>'; tableHtml += '</table>'; body = body + tableHtml + '<br/><br/>'; body = body + 'Thanks,<br/> System Administrator'; String repmail = ''; SingleEmailUtility seu = new SingleEmailUtility(); List<String> ccAddress = new List<String>(); seu.sendMail(new List<String>(to), ccAddress, '', subject, body); } } public class OppOfferWrapper{ @auraEnabled public string currentUserId{get;set;} @auraEnabled public string currentName{get;set;} @auraEnabled public string OpportunityName{get;set;} @auraEnabled public string OpportunityId{get;set;} @auraEnabled public string opportunityStageName{get;set;} public OppOfferWrapper(String userId, String userName, String oppId, String oppName, String oppStage){ this.currentUserId = userId; this.currentName = userName; this.OpportunityName = oppName; this.OpportunityId = oppId; this.opportunityStageName = oppStage; } } } ------------------------- OpportunityOfferingTriggerHelper.cls public without sharing class OpportunityOfferingTriggerHelper { @future public static void createShareRecordsFutureContext(Set<Id> offeringIds){ if(offeringIds != null)createShareRecords(offeringIds); } public static void createShareRecords(Set<Id> offeringIds){ Map<Id,Id> oppOfferIdVsOppId = new Map<Id,Id>(); Map<Id,Id> virOfferIdVsOppId = new Map<Id,Id>(); Map<Id,Set<Id>> oppIdVsOfferingIdSet = new Map<Id,Set<Id>>(); List<Opportunity_Offering__c> opOfferingList = new List<Opportunity_Offering__c>(); opOfferingList = [select id,Opportunity_Name__c,Virtusa_Offering__c from Opportunity_Offering__c where id IN :offeringIds]; for(Opportunity_Offering__c opOffering : opOfferingList){ oppOfferIdVsOppId.put(opOffering.Id,opOffering.Opportunity_Name__c); virOfferIdVsOppId.put(opOffering.Id,opOffering.Virtusa_Offering__c); if(!oppIdVsOfferingIdSet.containsKey(opOffering.Opportunity_Name__c)){ oppIdVsOfferingIdSet.put(opOffering.Opportunity_Name__c,new Set<Id>{opOffering.Id}); }else{ oppIdVsOfferingIdSet.get(opOffering.Opportunity_Name__c).add(opOffering.Id); } } Map<Id,Opportunity> offeringOpp = new Map<Id,Opportunity>([Select id, name from Opportunity where id In :oppOfferIdVsOppId.values() ]); Map<Id,Opportunity_Offering__c> idVsRelOfferingRecord = new Map<Id,Opportunity_Offering__c>([select id, Opportunity_Name__c,Virtusa_Offering__c from Opportunity_Offering__c where Opportunity_Name__c IN :offeringOpp.keySet() and ID Not In :oppOfferIdVsOppId.keySet()]); for(Opportunity_Offering__c opOffering : idVsRelOfferingRecord.values()){ oppOfferIdVsOppId.put(opOffering.Id,opOffering.Opportunity_Name__c); virOfferIdVsOppId.put(opOffering.Id,opOffering.Virtusa_Offering__c); if(!oppIdVsOfferingIdSet.containsKey(opOffering.Opportunity_Name__c)){ oppIdVsOfferingIdSet.put(opOffering.Opportunity_Name__c,new Set<Id>{opOffering.Id}); }else{ oppIdVsOfferingIdSet.get(opOffering.Opportunity_Name__c).add(opOffering.Id); } } Map<Id,Virtusa_Offering__c> vOfferingList = new Map<Id,Virtusa_Offering__c>([Select id, Offering_Squad__c, Virtu_Squad_Email_Address__c from Virtusa_Offering__c where id In :virOfferIdVsOppId.values() ]); Set<String> squadTeam = new Set<String>(); for(Virtusa_Offering__c vr : vOfferingList.values()){ if(vr.Offering_Squad__c != null) squadTeam.add(vr.Offering_Squad__c); } Map<Id,List<String>> virOffIdVsEmail = new Map<Id,List<String>>(); Map<String,Set<Id>> emailVsVirtusaId = new Map<String,Set<Id>>(); String slist = ''; for (String s: squadTeam) { slist += '\'' + s + '\','; } String value = '(\'' + String.join(squadTeam, '\',\'') + '\')'; String queryString = 'select id,email,name,Offering_squad_Leader__c,Off_Squad_Team_del__c'+ ' from contact' + ' where email != null and ' + ' Offering_squad_Leader__c = true and ' + ' Off_Squad_Team_del__c includes' + value; List<Contact> contactList = DataBase.query(queryString); for(Virtusa_Offering__c vr : vOfferingList.values()){ if(vr.Offering_Squad__c != null){ for(Contact con : contactList){ if(con.Off_Squad_Team_del__c.contains(vr.Offering_Squad__c)){ //emailVsName.put(con.email,con.name); if(!emailVsVirtusaId.containskey(con.email)){ emailVsVirtusaId.put(con.email,new Set<Id>{vr.Id}); } else{ emailVsVirtusaId.get(con.email).add(vr.Id); } if(!virOffIdVsEmail.containskey(vr.Id)){ virOffIdVsEmail.put(vr.Id,new List<String>{con.email}); } else{ virOffIdVsEmail.get(vr.Id).add(con.email); } } } } } Set<String> toAddresses = new Set<String>(); for(Opportunity_Offering__c opOffering : opOfferingList){ Set<String> to = new Set<String>(); if(offeringOpp.get(opOffering.Opportunity_Name__c) != null){ Set<Id> relatedOfferingIds = oppIdVsOfferingIdSet.get(opOffering.Opportunity_Name__c); if(relatedOfferingIds != null && relatedOfferingIds.size() > 0){ for(Id relatedOffId : relatedOfferingIds){ if(virOffIdVsEmail != null && idVsRelOfferingRecord != null && idVsRelOfferingRecord.get(relatedOffId) != null && idVsRelOfferingRecord.get(relatedOffId).Virtusa_Offering__c != null ) to.addAll(virOffIdVsEmail.get(idVsRelOfferingRecord.get(relatedOffId).Virtusa_Offering__c)); } } } if(virOffIdVsEmail != null && virOffIdVsEmail.get(opOffering.Virtusa_Offering__c) != null){ to.addAll(virOffIdVsEmail.get(opOffering.Virtusa_Offering__c)); } if(to.size() > 0) toAddresses.addAll(to); } List<User> userRecords = [select id,email from User where email IN :toAddresses]; Map<String,Opportunity_Offering__share> oppOffList = new Map<String,Opportunity_Offering__share>(); for(User userRec : userRecords){ if(emailVsVirtusaId != null && emailVsVirtusaId.get(userRec.email) != null){ Set<Id> virtusaIds = emailVsVirtusaId.get(userRec.email); for(Id oppOfferId : virOfferIdVsOppId.keySet()){ Set<Id> offerIds = oppIdVsOfferingIdSet.get(oppOfferIdVsOppId.get(oppOfferId)); if(virtusaIds.contains(virOfferIdVsOppId.get(oppOfferId))){ for(Id offerId : offerIds){ Opportunity_Offering__share oppOfferShare = new Opportunity_Offering__share(); oppOfferShare.ParentId = offerId; oppOfferShare.UserOrGroupId = userRec.Id; oppOfferShare.AccessLevel = 'edit'; oppOfferShare.RowCause = 'Manual'; if(offerId != null && userRec != null) oppOffList.put(offerId+'-'+userRec.Id,oppOfferShare); } } } } } if(oppOffList.size() > 0) Database.upsert(oppOffList.values(),false); } //Author - Viji //Arguments - opOfferingList -> list of opportunity offering record //Purpose - called from after update,after insert //Date - 21/03/2023 @future public static void updateOffOwnerAccessToOppOwnerHelper(Set<Id> offeringIds){ createShareRecordsForOppOwner(offeringIds); } public static void createShareRecordsForOppOwner(Set<Id> offeringIds){ Map<Id,Id> oppOfferIdVsOppId = new Map<Id,Id>(); Map<Id,Set<Id>> oppIdVsOfferingIdSet = new Map<Id,Set<Id>>(); Map<Id,Id> offOwner = new Map<Id,Id>(); List<Opportunity_Offering__c> opOfferingList = new List<Opportunity_Offering__c>(); opOfferingList = [select id,Opportunity_Name__c,Virtusa_Offering__c,OwnerId from Opportunity_Offering__c where id IN :offeringIds]; for(Opportunity_Offering__c oppOffering : opOfferingList){ oppOfferIdVsOppId.put(oppOffering.id,oppOffering.Opportunity_Name__c); if(!oppIdVsOfferingIdSet.containsKey(oppOffering.Opportunity_Name__c)){ oppIdVsOfferingIdSet.put(oppOffering.Opportunity_Name__c,new Set<Id>{oppOffering.Id}); }else{ oppIdVsOfferingIdSet.get(oppOffering.Opportunity_Name__c).add(oppOffering.Id); } } Map<Id,Opportunity> offeringOpp = new Map<Id,Opportunity>([Select id, name,stagename,ownerid from Opportunity where id In :oppOfferIdVsOppId.values() ]); for(Opportunity_Offering__c opOffering : opOfferingList){ Opportunity oppRec = offeringOpp.get(opOffering.Opportunity_Name__c); Id offeringOwner = opOffering.ownerId; if(oppRec != null){ Set<Id> relatedOfferingIds = oppIdVsOfferingIdSet.get(opOffering.Opportunity_Name__c); if(relatedOfferingIds != null && relatedOfferingIds.size() > 0){ for(Id relatedOffId : relatedOfferingIds){ if(oppRec.OwnerId != null && offeringOwner != null && oppRec.OwnerId != offeringOwner){ offOwner.put(oppRec.Id, oppRec.OwnerId); } } } } } List<User> ownerUserRecords = [select id from User where Id =: offOwner.values()]; Map<String,Opportunity_Offering__share> oppOffList = new Map<String,Opportunity_Offering__share>(); List<Opportunity_Offering__c> oppOwnerOffList= [select id,Opportunity_Name__c,ownerId from Opportunity_Offering__c where ownerId NOT IN :ownerUserRecords AND Opportunity_Name__c =: offOwner.keySet()]; for(User userRec : ownerUserRecords){ if(userRec!=null){ for(Opportunity_Offering__c offering : oppOwnerOffList){ Opportunity_Offering__share oppOfferShare = new Opportunity_Offering__share(); oppOfferShare.ParentId = offering.Id; oppOfferShare.UserOrGroupId = userRec.Id; oppOfferShare.AccessLevel = 'edit'; oppOfferShare.RowCause = 'Manual'; if(offering!=null && userRec != null){ oppOffList.put(offering.Id+'-'+userRec.Id,oppOfferShare); } } if(oppOffList.size() > 0) upsert oppOffList.values(); } } } public static void deleteNoOffering(List<Opportunity_Offering__c> opOfferingList,Boolean isUpdate){ Set<Id> oppIds = new Set<Id>(); Set<Id> curroppIds = new Set<Id>(); for(Opportunity_Offering__c oppOffering : opOfferingList){ oppIds.add(oppOffering.Opportunity_Name__c); if(!isUpdate) curroppIds.add(oppOffering.Id); } deletNoOfferingFuture(oppIds,curroppIds); } @future public static void deletNoOfferingFuture(Set<Id> oppIds,Set<Id> curroppIds){ List<Opportunity_Offering__c> oppList = [SELECT Id, OwnerId, Name, Opportunity_Name__c, Opportunity_Id__c, Virtusa_Offering__c,Virtusa_Offering__r.name FROM Opportunity_Offering__c where Opportunity_Name__c IN :oppIds AND Virtusa_Offering__r.name = 'No Offerings' AND id NOT IN :curroppIds]; if(oppList != null && oppList.size() > 0){ delete oppList; } } public static void stampOldPec(Map<Id, Opportunity_Offering__c > mapOldRecord,Map<Id, Opportunity_Offering__c > mapNewRecord){ for(Opportunity_Offering__c opOffering : mapNewRecord.values()){ if(mapOldRecord.get(opOffering.Id).Virtu_Offering_Split_p__c != null){ opOffering.Old_Offering_Split__c = mapOldRecord.get(opOffering.Id).Virtu_Offering_Split_p__c; } } } public static void validateNoOffering(List<Opportunity_Offering__c> opOfferingList){ Set<Id> oppIds = new Set<Id>(); Set<Id> virIds = new Set<Id>(); Map<Id,Boolean> oppIdToRes = new Map<Id,Boolean>(); //Boolean noOffering; for(Opportunity_Offering__c oppOffering : opOfferingList){ oppIds.add(oppOffering.Opportunity_Name__c); virIds.add(oppOffering.Virtusa_Offering__c); } Map<Id,Virtusa_Offering__c> vOfferingList = new Map<Id,Virtusa_Offering__c>([Select id,Name, Offering_Squad__c, Virtu_Squad_Email_Address__c from Virtusa_Offering__c where id In :virIds]); List<Opportunity_Offering__c> oppList = [SELECT Id, OwnerId, Name, Opportunity_Name__c, Opportunity_Id__c, Virtusa_Offering__c,Virtusa_Offering__r.name, Virtu_Offering_Split_p__c FROM Opportunity_Offering__c where Opportunity_Name__c IN :oppIds]; oppList.addAll(opOfferingList); for(Opportunity_Offering__c opp : oppList){ if(oppList.size()>0){ oppIdToRes.put(opp.Opportunity_Name__c,false); if(opp.Virtu_Offering_Split_p__c == 0){ //noOffering = true; }else{ //noOffering = false; oppIdToRes.put(opp.Opportunity_Name__c,true); } } } for(Opportunity_Offering__c opp : opOfferingList){ if(oppList.size()>0){ //if(vOfferingList.get(opp.Virtusa_Offering__c).name == 'No Offerings' && !noOffering && oppIdToRes.contains(opp.Opportunity_Name__c)){ if(vOfferingList.get(opp.Virtusa_Offering__c).name == 'No Offerings' && oppIdToRes.containsKey(opp.Opportunity_Name__c) && oppIdToRes.get(opp.Opportunity_Name__c)){ opp.addError('"No Offerings" Cannot Be Tagged If Opportunity has Offerings'); } } } } }
Leave a Comment