Untitled
unknown
java
a year ago
9.9 kB
5
Indexable
// halo_CustomRollup public interface halo_CustomRollup { void initialize(SObject sObj, TriggerContext triggerContext); void recalculate(Map<Id, SObject> ancestors, List<SObject> descendants); Boolean shouldRecalculate(); Set<SObjectField> getDescendantQueryFields(); Set<SObjectField> getAncestorQueryFields(); Set<Id> getAncestorRecordIds(); Set<Id> getUpdatedRecordIds(); } // halo_SObjectTypeCustomRollups public abstract with sharing class halo_SObjectTypeCustomRollups { private final DescendantsSelector selector; private Map<Id, SObject> updatedRecords = new Map<Id, SObject>(); protected SObjectTypeCustomRollups() { this.selector = new DescendantsSelector(getRelationshipField(), getSObjectType()); } public void initialize(SObject sObj, TriggerContext triggerContext) { for (halo_CustomRollup rollup : this.getRollups()) { rollup.initialize(sObj, triggerContext); } } public void recalculate(Map<Id, SObject> ancestors) { List<halo_CustomRollup> rollupsToRecalculate = this.getRollupsToRecalculate(); if (!rollupsToRecalculate.isEmpty()) { this.selector.addCustomRollups(rollupsToRecalculate); List<SObject> descendants = this.selector.getDescendants(); for (halo_CustomRollup rollup : rollupsToRecalculate) { rollup.recalculate(ancestors, descendants); this.summarizeUpdatedRecords(rollup); } } } private void summarizeUpdatedRecords(halo_CustomRollup rollup) { for (Id recordId : rollup.getUpdatedRecordIds()) { updatedRecords.put(recordId, ancestors.get(recordId)); } } public Set<SObject> getUpdatedRecords() { return updatedRecords.values(); } public Set<SObjectField> getAncestorFields() { Set<SObjectField> ancestorFields = new Set<SObjectField>(); for (halo_CustomRollup rollup : this.getRollups()) { ancestorFields.addAll(rollup.getAncestorQueryFields()); } return ancestorFields; } public Set<Id> getAncestorRecordIds() { Set<Id> ancestorRecordIds = new Set<Id>(); for (halo_CustomRollup rollup : this.getRollups()) { ancestorRecordIds.addAll(rollup.getAncestorRecordIds()); } return ancestorRecordIds; } protected abstract List<halo_CustomRollup> getRollups(); protected abstract SObjectType getSObjectType(); protected abstract String getRelationshipField(); private List<halo_CustomRollup> getRollupsToRecalculate() { List<halo_CustomRollup> customRollups = new List<halo_CustomRollup>(); for (halo_CustomRollup rollup : this.getRollups()) { if (rollup.shouldRecalculate()) { customRollups.add(rollup); } } return customRollups; } private with sharing class DescendantsSelector() { private final String relationshipField; private final SObjectType sObjType; private Set<SObjectField> fields = new Set<SObjectField>(); private Set<Id> ancestorRecordIds = new Set<Id>(); public DescendantsSelector(String relationshipField, SObjectType sObjType) { this.relationshipField = relationshipField; this.sObjType = sObjType; } public void addCustomRollups(List<halo_CustomRollup> customRollups) { for (halo_CustomRollup rollup : customRollups) { this.fields.addAll(rollup.getDescendantQueryFields()); this.ancestorRecordIds.addAll(rollup.getAncestorRecordIds()); } } public List<SObject> getRecords() { return Database.query(String.format('SELECT {0} FROM {1} WHERE {2}', new List<Object> { this.fields, this.sObjType + '', this.relationshipField + ' IN :this.ancestorRecordIds' }))); } } } // halo_SObjectRollupsCalculator public abstract with sharing class halo_SObjectRollupsCalculator { public void recalculate(List<SObject> sObjects, TriggerContext triggerContext) { this.initializeRollups(sObjects, triggerContext); Map<Id, SObject> ancestors = this.fetchAncestorRecords(); List<SObject> updatedAncestors = this.processRecalculations(ancestors); update updatedAncestors; } private void initializeRollups(List<SObject> sObjects, TriggerContext triggerContext) { for (SObject sObj : sObjects) { SObjectType sObjType = sObj.getSObjectType(); for (halo_SObjectTypeCustomRollups rollup : this.getCustomRollups().get(sObjType)) { rollup.initialize(sObj, triggerContext); } } } private Map<Id, SObject> fetchAncestorRecords() { AncestorSelector selector = new AncestorSelector(this.getAncestorSObjectType()); for (halo_SObjectTypeCustomRollups customRollup : this.getCustomRollups().values()) { selector.addFields(customRollup.getAncestorFields()); selector.addRecordIds(customRollup.getAncestorRecordIds()); } return selector.getRecords(); } private List<SObject> processRecalculations(Map<Id, SObject> ancestors) { List<SObject> ancestorsToUpdate = new List<SObject>(); for (halo_SObjectTypeCustomRollups customRollup : this.getCustomRollups().values()) { customRollup.recalculate(ancestors); ancestorsToUpdate.addAll(customRollup.getUpdatedRecords()); } return ancestorsToUpdate; } protected abstract Map<SObjectType, halo_SObjectTypeCustomRollups> getCustomRollups(); protected abstract SObjectType getAncestorSObjectType(); private with sharing class AncestorSelector() { private final SObjectType ancestorSObjectType; private Set<SObjectField> fields = new Set<SObjectField>(); private Set<Id> recordIds = new Set<Id>(); public AncestorSelector(SObjectType ancestorSObjectType) { this.ancestorSObjectType = ancestorSObjectType; } public void addFields(Set<SObjectField> fields) { this.fields.addAll(fields); } public void addRecordIds(Set<Id> recordIds) { this.recordIds.addAll(recordIds); } public Map<Id, SObject> getRecords() { return Database.query(String.format('SELECT {0} FROM {1} WHERE {2}', new List<Object> { this.fields, this.ancestorSObjectType + '', 'Id IN :this.recordIds' })); } } } // halo_TourRollupsCalculator public with sharing class halo_TourRollupsCalculator extends halo_SObjectRollupsCalculator { private static final Map<SObjectType, halo_SObjectTypeCustomRollups> CUSTOM_ROLLUPS = new Map<SObjectType, halo_SObjectTypeCustomRollups> { Ticket_Hold__c.SObjectType => new () }; protected override Map<SObjectType, halo_SObjectTypeCustomRollups> getCustomRollups() { return halo_TourRollupsCalculator.CUSTOM_ROLLUPS; } protected override SObjectType getAncestorSObjectType() { return Tour__c.SObjectType; } private with sharing class TicketHoldCustomRollups extends halo_SObjectTypeCustomRollups { private final List<halo_CustomRollup> rollups = new List<halo_CustomRollup> { new TicketHoldComplimentaryRollup() }; protected override List<halo_CustomRollup> getRollups() { return this.rollups; } protected override SObjectType getSObjectType() { return Ticket_Hold__c.SObjectType; } protected abstract String getRelationshipField() { return 'Ticket_Band__r.Show__r.Tour__c'; } } private with sharing class TicketHoldComplimentaryRollup implements halo_CustomRollup { private Set<Id> ancestorRecordIds = new Set<Id>(); private Set<Id> updatedRecordIds = new Set<Id>(); public void initialize(SObject sObj, TriggerContext triggerContext) { Ticket_Hold__c ticketHold = (Ticket_Hold__c) sObj; if ((triggerContext.isNew() || triggerContext.isChanged(sObj, Ticket_Hold__c.Complimentary__c)) && ticketHold.Ticket_Band__r.Show__r.Show_Status__c != 'Cancelled' && ticketHold.Ticket_Band__r.Show__r.Onsales_Date__c != null) { this.ancestorRecordIds.add(ticketHold.Ticket_Band__r.Show__r.Tour__c); } } public void recalculate(Map<Id, SObject> ancestors, Map<Id, List<SObject>> descendants) { for (Id ancestorRecordId : this.ancestorRecordIds) { Tour__c tour = (Tour__c) ancestors.get(ancestorRecordId); Integer complimentarySum = 0; for (Ticket_Hold__c descendant : (List<Ticket_Hold__c>) descendants.get(tour.Id)) { if (descendant.Complimentary__c != null) { complimentarySum += descendant.Complimentary__c; } } if (tour.Comp_Holds__c != complimentarySum) { tour.Comp_Holds__c = complimentarySum; updatedRecordIds.add(tour.Id); } } } public Boolean shouldRecalculate() { return !this.ancestorRecordIds.isEmpty(); } public Set<SObjectField> getDescendantQueryFields() { return new Set<SObjectField> { Ticket_Hold__c.Complimentary__c }; } public Set<SObjectField> getAncestorQueryFields() { return new Set<SObjectField> { Ticket_Hold__c.Comp_Holds__c }; } public Set<Id> getAncestorRecordIds() { return this.ancestorRecordIds; } public Set<Id> getUpdatedRecordIds() { return this.updatedRecordIds; } } }
Editor is loading...
Leave a Comment