diff --git a/sfdx-source/apex-extensions/main/default/classes/domains/fflib_ISObjects2.cls b/sfdx-source/apex-extensions/main/default/classes/domains/fflib_ISObjects2.cls index 35a36ac..6e1778d 100644 --- a/sfdx-source/apex-extensions/main/default/classes/domains/fflib_ISObjects2.cls +++ b/sfdx-source/apex-extensions/main/default/classes/domains/fflib_ISObjects2.cls @@ -29,6 +29,10 @@ */ public interface fflib_ISObjects2 extends fflib_ISObjects { + Map> getChildIdsById(Map domainsByRelationshipField); + Map getParentIdById(Map domainsByRelationshipField); + + // DEPRECATED METHODS Map getGrandParentIdById(List relatedDomains); Map> getChildIdsById(List relatedDomains); } \ No newline at end of file diff --git a/sfdx-source/apex-extensions/main/default/classes/domains/fflib_SObjects2.cls b/sfdx-source/apex-extensions/main/default/classes/domains/fflib_SObjects2.cls index f2f4486..b5f5654 100644 --- a/sfdx-source/apex-extensions/main/default/classes/domains/fflib_SObjects2.cls +++ b/sfdx-source/apex-extensions/main/default/classes/domains/fflib_SObjects2.cls @@ -81,33 +81,57 @@ public virtual class fflib_SObjects2 /** * Creates a map between the record Ids of this domain to the last given grandparent domain. - * This method is using getRelatedFieldByDomainType to determine which SObjectField - * is related to the given parent domain * - * @param relatedDomains A List of domains in hierarchical order from first parent to grandparent + * @param domainsByRelationshipField A Map of domains and the in hierarchical order from first parent to grandparent * * @return Returns a map with KEY: The Ids of the records in this domain, * to the VALUE: The Id of the last grandparent record listed in the relatedDomains, * null if no grandparent exists. * - * @see getRelatedFieldByDomainType - * * @example - * IInvoiceLines invoiceLineDomain = InvoiceLines.newInstance(invoiceLineRecords); - * IInvoices invoicesDomain = Invoices.newInstance(invoiceRecords); + * ICases casesDomain = Cases.newInstance(caseRecords); + * IContacts contactsDomain = Contacts.newInstance(contactRecords); * IAccount accountDomain = Accounts.newInstance(accountRecords); * - * // A map with key - InvoiceLine.Id to value - Account.Id - * Map accountIdByInvoiceLineId = - * invoiceLineDomain.getGrandParentIdById( - * new List + * // A map with key - Case.Id to value - Account.Id + * Map accountIdByCaseId = + * casesDomain.getParentIdById( + * new Map * { - * invoicesDomain, - * accountDomain + * Schema.Case.ContactId => contactDomain, + * Schema.Contact.AccountId => accountDomain * }); */ + public virtual Map getParentIdById(Map domainsByRelationshipField) + { + // Takes the highest related domain from the domainsByRelationshipField + Schema.SObjectField relationshipField = + new List(domainsByRelationshipField.keySet()) + .get(0); + fflib_SObjects2 relatedDomain = domainsByRelationshipField.remove(relationshipField); + + // Extract the Id values of the related SObjectType + Map result = getIdFieldByIdField( + relationshipField, + getSObjectType().getDescribe().fields.getMap().get('Id')); + + // Check if we need to resolve another parent relation, if not return the results + if (domainsByRelationshipField.isEmpty()) return result; + + // Fetch the Ids of the related SObjectType + Map parentIdByChildId = relatedDomain.getParentIdById(domainsByRelationshipField); + + // Replace the maps value (ParentId) with the grand parent Id + return fflib_ArrayUtils.replaceValue(result, parentIdByChildId); + } + + /** DEPRECATED **/ public virtual Map getGrandParentIdById(List relatedDomains) { + System.debug(LoggingLevel.WARN, + 'The \'getGrandParentIdById(List relatedDomains)\' method is deprecated,' + + 'please refactor to \'getParentIdById(Map relatedDomains)\''); + fflib_ISObjects2 relatedDomain = relatedDomains.remove(0); SObjectType relatedDomainType = relatedDomain.getSObjectType(); Map relatedFieldByDomainType = getRelatedFieldByDomainType(); @@ -136,30 +160,55 @@ public virtual class fflib_SObjects2 * This method is using getRelatedFieldByDomainType to determine which SObjectField * is related to the given parent domain * - * @param relatedDomains A List of domains in hierarchical order from first child to grandchild + * @param domainsByRelationshipField A Map of domains in hierarchical order from first child to grandchild * * @return Returns a map with KEY: The Ids of the records in this domain, * to the VALUE: The record Ids of the lowest child related record listed in the relatedDomains, * null if no grandchild exists. * - * @see getRelatedFieldByDomainType - * * @example - * IInvoiceLines invoiceLineDomain = InvoiceLines.newInstance(invoiceLineRecords); - * IInvoices invoicesDomain = Invoices.newInstance(invoiceRecords); + * ICases casesDomain = Cases.newInstance(caseRecords); + * IContacts contactsDomain = Contacts.newInstance(contactRecords); * IAccount accountDomain = Accounts.newInstance(accountRecords); * - * // A map with key - Account.Id to value - InvoiceLine.Id - * Map> invoiceLineIdsByAccountId = - * accountDomain.getChildIdsById( - * new List + * // A map with key - Case.Id to value - Account.Id + * Map> caseIdsByAccountId = + * accountsDomain.getChildIdsById( + * new Map * { - * invoicesDomain, - * invoiceLineDomain + * Schema.Contact.AccountId => contactsDomain + * Schema.Case.ContactId => casesDomain, * }); */ + public virtual Map> getChildIdsById(Map domainsByRelationshipField) + { + // Takes the highest related domain from the domainsByRelationshipField + Schema.SObjectField relationshipField = + new List(domainsByRelationshipField.keySet()) + .get(0); + fflib_SObjects2 relatedDomain = domainsByRelationshipField.remove(relationshipField); + + Map> result = relatedDomain.getIdFieldsByIdField( + relatedDomain.getSObjectType().getDescribe().fields.getMap().get('Id'), + relationshipField); + + // Check if we need to resolve another child relation, if not return the results + if (domainsByRelationshipField.isEmpty()) return result; + + Map> childIdsById = relatedDomain.getChildIdsById(domainsByRelationshipField); + + // Replace the maps value (childIds) with the grand child Id + return fflib_ArrayUtils.replaceValues(result, childIdsById); + } + + /** DEPRECATED **/ public virtual Map> getChildIdsById(List relatedDomains) { + System.debug(LoggingLevel.WARN, + 'The \'getChildIdsById(List relatedDomains)\' method is deprecated,' + + 'please refactor to \'getChildIdsById(Map relatedDomains)\''); + + SObjectType thisDomainType = getSObjectType(); fflib_SObjects2 relatedDomain = relatedDomains.remove(0); Map relatedFieldByDomainType = relatedDomain.getRelatedFieldByDomainType(); diff --git a/sfdx-source/apex-extensions/tests/classes/domains/fflib_SObjects2Test.cls b/sfdx-source/apex-extensions/tests/classes/domains/fflib_SObjects2Test.cls index 5168d6d..5cd5edf 100644 --- a/sfdx-source/apex-extensions/tests/classes/domains/fflib_SObjects2Test.cls +++ b/sfdx-source/apex-extensions/tests/classes/domains/fflib_SObjects2Test.cls @@ -121,7 +121,7 @@ private class fflib_SObjects2Test } @IsTest - static void itShouldReturnTheRelatedChildDomainId() + static void itShouldReturnTheRelatedChildDomainId_deprecated() { // GIVEN a case A & Z related to contact A related to Account, Id caseIdA = fflib_IDGenerator.generate(Schema.Case.SObjectType); @@ -161,6 +161,47 @@ private class fflib_SObjects2Test System.Assert.areEqual(2, result.get(accountId).size(), 'Incorrect amount of related cases to the account'); System.Assert.isTrue(result.get(accountId).containsAll(new Set{ caseIdA, caseIdZ })); } + @IsTest + static void itShouldReturnTheRelatedChildDomainId() + { + // GIVEN a case A & Z related to contact A related to Account, + Id caseIdA = fflib_IDGenerator.generate(Schema.Case.SObjectType); + Id caseIdZ = fflib_IDGenerator.generate(Schema.Case.SObjectType); + Id caseIdB = fflib_IDGenerator.generate(Schema.Case.SObjectType); + Id caseIdC = fflib_IDGenerator.generate(Schema.Case.SObjectType); + Id contactIdA = fflib_IDGenerator.generate(Schema.Contact.SObjectType); + Id contactIdB = fflib_IDGenerator.generate(Schema.Contact.SObjectType); + Id accountId = fflib_IDGenerator.generate(Schema.Account.SObjectType); + Account accountRecord = new Account(Id = accountId); + Contact contactRecordA = new Contact(Id = contactIdA, AccountId = accountId); + Contact contactRecordB = new Contact(Id = contactIdB); + Case caseRecordA = new Case(Id = caseIdA, ContactId = contactIdA); + Case caseRecordZ = new Case(Id = caseIdZ, ContactId = contactIdA); + Case caseRecordB = new Case(Id = caseIdB, ContactId = contactIdB); + Case caseRecordC = new Case(Id = caseIdC); + + DomainAccounts accountDomain = new DomainAccounts(new List {accountRecord}); + DomainContacts contactDomain = new DomainContacts(new List {contactRecordA, contactRecordB}); + DomainCases caseDomain = new DomainCases(new List {caseRecordA, caseRecordB, caseRecordC, caseRecordZ}); + + // WHEN we request the relation between Case and Account + System.Test.startTest(); + Map> result = accountDomain.getChildIdsById( + new Map + { + Contact.AccountId => contactDomain, + Case.ContactId => caseDomain + } + ); + System.Test.stopTest(); + System.debug('result: ' + JSON.serializePretty(result)); + + // THEN it should return the AccountId By CaseId + System.Assert.areEqual(1, result.size(), 'Expected one account'); + System.Assert.isTrue(result.containsKey(accountId), 'Account Id should be the main key'); + System.Assert.areEqual(2, result.get(accountId).size(), 'Incorrect amount of related cases to the account'); + System.Assert.isTrue(result.get(accountId).containsAll(new Set{ caseIdA, caseIdZ })); + } @IsTest static void itShouldReturnTheRelatedParentDomainId() @@ -186,6 +227,52 @@ private class fflib_SObjects2Test DomainContacts contactDomain = new DomainContacts(new List {contactRecordA, contactRecordB}); DomainCases caseDomain = new DomainCases(new List {caseRecordA, caseRecordB, caseRecordC}); + // WHEN we request the relation between Case and Account + System.Test.startTest(); + Map result = caseDomain.getParentIdById( + new Map + { + Schema.Case.ContactId => contactDomain, + Schema.Contact.AccountId => accountDomain + } + ); + System.Test.stopTest(); + + // THEN it should return the AccountId By CaseId + System.Assert.areEqual(3, result.size(), 'Expected one related account to the case'); + System.Assert.isTrue(result.containsKey(caseIdA)); + System.Assert.isTrue(result.containsKey(caseIdB)); + System.Assert.isTrue(result.containsKey(caseIdC)); + System.Assert.areEqual(accountId, result.get(caseIdA), 'Account Id should be related to the Case Id A'); + System.Assert.isNull(result.get(caseIdB), 'Case Id B should have no related Account Id'); + System.Assert.isNull(result.get(caseIdC), 'Case Id B should have no related Account Id'); + } + + /** Unit test for the deprecated method **/ + @IsTest + static void itShouldReturnTheRelatedParentDomainId_deprecated() + { + // GIVEN a case related to contact related to Account , + // a case record related to contact but not to Account, + // and a case record related to nothing. + // All encapsulated in domains. + Id caseIdA = fflib_IDGenerator.generate(Schema.Case.SObjectType); + Id caseIdB = fflib_IDGenerator.generate(Schema.Case.SObjectType); + Id caseIdC = fflib_IDGenerator.generate(Schema.Case.SObjectType); + Id contactIdA = fflib_IDGenerator.generate(Schema.Contact.SObjectType); + Id contactIdB = fflib_IDGenerator.generate(Schema.Contact.SObjectType); + Id accountId = fflib_IDGenerator.generate(Schema.Account.SObjectType); + Account accountRecord = new Account(Id = accountId); + Contact contactRecordA = new Contact(Id = contactIdA, AccountId = accountId); + Contact contactRecordB = new Contact(Id = contactIdB); + Case caseRecordA = new Case(Id = caseIdA, ContactId = contactIdA); + Case caseRecordB = new Case(Id = caseIdB, ContactId = contactIdB); + Case caseRecordC = new Case(Id = caseIdC); + + DomainAccounts accountDomain = new DomainAccounts(new List {accountRecord}); + DomainContacts contactDomain = new DomainContacts(new List {contactRecordA, contactRecordB}); + DomainCases caseDomain = new DomainCases(new List {caseRecordA, caseRecordB, caseRecordC}); + // WHEN we request the relation between Case and Account System.Test.startTest(); Map result = caseDomain.getGrandParentIdById(