Untitled

 avatar
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