global class ProjectISRAssociation_Batch implements Database.Batchable<Sobject>, Database.Stateful {
String query = '';
Set<Id> projIds = new Set<Id>();
List<OpportunityTeamMember> newOptyMembers_for_opt_upd = new List<OpportunityTeamMember>();
global ProjectISRAssociation_Batch(List<OpportunityTeamMember> newOptyMembers) {
this.newOptyMembers_for_opt_upd = newOptyMembers;
for(OpportunityTeamMember otmTemp : newOptyMembers_for_opt_upd) {
projIds.add(otmTemp.OpportunityId);
}
query = 'SELECT Id, Name, Sales_Rep__c, Sales_Rep__r.isActive, EPM__c, EPM__r.isActive, ' +
'Inside_Sales_Rep__c, Zone_Manager__c, Regional_Sales_Manager__c, OwnerId, Owner.isActive, ' +
'Owner.Account_Team_Role__c, Owner.Ag__c, ' +
'(SELECT Id, UserId, User.Account_Team_Role__c, User.isActive, TeamMemberRole FROM OpportunityTeamMembers ORDER BY CreatedDate DESC), ' +
'(SELECT Id FROM Engineering_Requests__r) FROM Opportunity WHERE Id IN: projIds';
}
global Database.QueryLocator start(Database.BatchableContext BC) {
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<Opportunity> opt_tm_ls) {
List<Opportunity> opptyList_upd = new List<Opportunity>();
Map<Id, Case> casesUpdate = new Map<Id, Case>();
try {
// Loop through Opportunities
for(Opportunity opt : opt_tm_ls) {
Boolean isAgRep = opt.Owner.Ag__c;
Map<String, Integer> stusCnt = new Map<String, Integer>();
// Count the number of Team Members per role
for(OpportunityTeamMember otmTemp : opt.OpportunityTeamMembers) {
stusCnt.put(otmTemp.TeamMemberRole, stusCnt.getOrDefault(otmTemp.TeamMemberRole, 0) + 1);
}
// Process each OpportunityTeamMember
for(OpportunityTeamMember otmTemp : opt.OpportunityTeamMembers) {
processTeamMemberRole(opt, otmTemp, stusCnt, isAgRep, casesUpdate);
}
// Add updated Opportunity to the list for bulk update
opptyList_upd.add(opt);
}
// Perform DML operations outside of loops
if (!opptyList_upd.isEmpty()) {
update opptyList_upd;
}
if (!casesUpdate.isEmpty()) {
update casesUpdate.values();
}
} catch (Exception e) {
System.debug(LoggingLevel.ERROR, 'Error in batch execute: ' + e.getMessage());
}
}
global void finish(Database.BatchableContext BC) {
// Any cleanup if needed after batch completion can be added here
}
// Helper method to handle the processing of each team member's role
private void processTeamMemberRole(Opportunity opt, OpportunityTeamMember otmTemp,
Map<String, Integer> stusCnt, Boolean isAgRep,
Map<Id, Case> casesUpdate) {
String role = otmTemp.TeamMemberRole;
switch on role {
when Constants.ISR_STATUS {
opt.Inside_Sales_Rep__c = otmTemp.UserId;
}
when Constants.ZM_STATUS {
opt.Zone_Manager__c = otmTemp.UserId;
}
when Constants.RSM_STATUS {
opt.Regional_Sales_Manager__c = otmTemp.UserId;
}
when Constants.APM_MANAGER_STATUS {
opt.APM_Manager__c = otmTemp.UserId;
}
when Constants.EPM_MANAGER_STATUS {
opt.EPM_Manager__c = otmTemp.UserId;
}
when Constants.AG_REP_STATUS {
if (isAgRep) {
updateSalesRep(opt, otmTemp, stusCnt, Constants.AG_REP_STATUS, casesUpdate);
}
}
when Constants.SR_STATUS {
if (!isAgRep) {
updateSalesRep(opt, otmTemp, stusCnt, Constants.SR_STATUS, casesUpdate);
}
}
when Constants.MA_STATUS {
opt.Market_Analyst__c = otmTemp.UserId;
}
when Constants.EPM_STATUS {
updateEPM(opt, otmTemp, stusCnt, casesUpdate);
}
when Constants.APM_STATUS {
opt.APM__c = otmTemp.UserId;
updateCases(opt, otmTemp, casesUpdate);
}
when Constants.IPM_STATUS {
opt.IPM__c = otmTemp.UserId;
updateCases(opt, otmTemp, casesUpdate);
}
when else {
// Handle other roles if needed
}
}
// Special logic to reassign Opportunity Owner if Account_Team_Role matches and Owner is inactive
if (opt.Owner.Account_Team_Role__c == otmTemp.User.Account_Team_Role__c && !opt.Owner.isActive) {
opt.OwnerId = otmTemp.UserId;
}
}
// Helper method to update Sales Rep and Engineering Cases
private void updateSalesRep(Opportunity opt, OpportunityTeamMember otmTemp,
Map<String, Integer> stusCnt, String role, Map<Id, Case> casesUpdate) {
if (stusCnt.get(role) == 1) {
opt.Sales_Rep__c = otmTemp.UserId;
} else if (stusCnt.get(role) > 1) {
if ((opt.Sales_Rep__c == null || !opt.Sales_Rep__r.isActive) && opt.Sales_Rep__c != otmTemp.UserId) {
opt.Sales_Rep__c = otmTemp.UserId;
}
}
// Update related Cases with new Sales Rep
updateCases(opt, otmTemp, casesUpdate);
}
// Helper method to update Engineering Cases for specific roles
private void updateCases(Opportunity opt, OpportunityTeamMember otmTemp, Map<Id, Case> casesUpdate) {
for (Case currCase : opt.Engineering_Requests__r) {
currCase.SalesRep__c = otmTemp.UserId;
casesUpdate.put(currCase.Id, currCase);
}
}
// Helper method to update EPM Manager
private void updateEPM(Opportunity opt, OpportunityTeamMember otmTemp,
Map<String, Integer> stusCnt, Map<Id, Case> casesUpdate) {
if (stusCnt.get(Constants.EPM_STATUS) == 1) {
opt.EPM__c = otmTemp.UserId;
} else if (stusCnt.get(Constants.EPM_STATUS) > 1) {
if ((opt.EPM__c == null || !opt.EPM__r.isActive) && opt.EPM__c != otmTemp.UserId) {
opt.EPM__c = otmTemp.UserId;
}
}
// Update related Cases with new EPM
updateCases(opt, otmTemp, casesUpdate);
}
}