Skip to content

Commit 7ccdc3b

Browse files
⛳ Add upsert by external id test
1 parent 075bb9f commit 7ccdc3b

File tree

2 files changed

+51
-20
lines changed

2 files changed

+51
-20
lines changed

sfdx-source/apex-common/main/classes/fflib_SObjectUnitOfWork.cls

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,12 @@ public virtual class fflib_SObjectUnitOfWork
109109
}
110110
public void dmlUpsert(List<SObject> objList, Schema.SObjectField externalId) {
111111
if (!objList.isEmpty()) {
112-
Database.upsert(objList, externalId);
112+
113+
Type objListType = Type.ForName('List<' + objList[0].getSObjectType() + '>');
114+
List<SObject> typpedList = (List<SObject>)objListType.newInstance();
115+
typpedList.addAll(objList);
116+
117+
Database.upsert(typpedList, externalId);
113118
}
114119
}
115120
public void dmlDelete(List<SObject> objList)
@@ -491,7 +496,7 @@ public virtual class fflib_SObjectUnitOfWork
491496
**/
492497
public void registerUpsert(SObject record, Schema.SObjectField externalIdField, Schema.sObjectField relatedToParentField, SObject relatedToParentRecord)
493498
{
494-
499+
495500
SObjectType sObjectType = record.getSObjectType();
496501
String sObjName = sObjectType.getDescribe().getName();
497502

@@ -501,7 +506,18 @@ public virtual class fflib_SObjectUnitOfWork
501506
if (externalIdField == null)
502507
throw new UnitOfWorkException('Invalid argument: externalIdField. If you want to upsert by id, use the registerUpsert method that has only one argument');
503508

504-
assertValidExternalId(sObjectType, externalIdField);
509+
String externalIdFieldName = externalIdField.getDescribe().getName();
510+
Boolean relatedHasExternalIdField = sObjectType.getDescribe().fields.getMap().keySet().contains(externalIdFieldName.toLowerCase());
511+
Boolean externalIdFieldIsValid = externalIdField.getDescribe().isIdLookup();
512+
513+
if (record.Id != null && externalIdFieldName != 'Id')
514+
throw new UnitOfWorkException('When upserting by external id, the record cannot already have the standard id populated');
515+
516+
if (!relatedHasExternalIdField)
517+
throw new UnitOfWorkException('Invalid argument: externalIdField. Field supplied is not a known field on the target sObject.');
518+
519+
if (!externalIdFieldIsValid)
520+
throw new UnitOfWorkException('Invalid argument: externalIdField. Field supplied cannot be used with upsert.');
505521

506522
Schema.SObjectField registeredExternalId = m_externalIdToUpsertPerType.get(sObjName);
507523
if (registeredExternalId != null && registeredExternalId != externalIdField)
@@ -848,22 +864,6 @@ public virtual class fflib_SObjectUnitOfWork
848864
}
849865
}
850866

851-
private static void assertValidExternalId(Schema.SObjectType relatedObject, Schema.SObjectField externalIdField)
852-
{
853-
854-
String externalIdFieldName = externalIdField.getDescribe().getName();
855-
Boolean relatedHasExternalIdField = relatedObject.getDescribe().fields.getMap().keySet().contains(externalIdFieldName.toLowerCase());
856-
Boolean externalIdFieldIsValid = externalIdField.getDescribe().isExternalId();
857-
858-
if (!relatedHasExternalIdField) {
859-
throw new UnitOfWorkException('Invalid argument: externalIdField. Field supplied is not a known field on the target sObject.');
860-
}
861-
862-
if (!externalIdFieldIsValid) {
863-
throw new UnitOfWorkException('Invalid argument: externalIdField. Field supplied is not a marked as an External Identifier.');
864-
}
865-
}
866-
867867
private class Relationships
868868
{
869869
private List<IRelationship> m_relationships = new List<IRelationship>();
@@ -893,7 +893,17 @@ public virtual class fflib_SObjectUnitOfWork
893893
List<Schema.SObjectType> relatedObjects = relatedToField.getDescribe().getReferenceTo();
894894
Schema.SObjectType relatedObject = relatedObjects[0];
895895

896-
assertValidExternalId(relatedObject, externalIdField);
896+
String externalIdFieldName = externalIdField.getDescribe().getName();
897+
Boolean relatedHasExternalIdField = relatedObject.getDescribe().fields.getMap().keySet().contains(externalIdFieldName.toLowerCase());
898+
Boolean externalIdFieldIsValid = externalIdField.getDescribe().isExternalId();
899+
900+
if (!relatedHasExternalIdField) {
901+
throw new UnitOfWorkException('Invalid argument: externalIdField. Field supplied is not a known field on the target sObject.');
902+
}
903+
904+
if (!externalIdFieldIsValid) {
905+
throw new UnitOfWorkException('Invalid argument: externalIdField. Field supplied is not a marked as an External Identifier.');
906+
}
897907

898908
RelationshipByExternalId relationship = new RelationshipByExternalId();
899909
relationship.Record = record;

sfdx-source/apex-common/test/classes/fflib_SObjectUnitOfWorkTest.cls

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,27 @@ private with sharing class fflib_SObjectUnitOfWorkTest
568568
System.assertEquals(2, [SELECT COUNT() FROM Opportunity WHERE StageName = 'Closed']);
569569
}
570570

571+
@isTest
572+
private static void testRegisterUpsertByExternalId() {
573+
574+
Opportunity existingOpp = new Opportunity(Name = 'Existing Opportunity', StageName = 'Open', CloseDate = System.today());
575+
insert existingOpp;
576+
577+
existingOpp.StageName = 'Closed';
578+
579+
System.assertEquals(1, [SELECT COUNT() FROM Opportunity]);
580+
System.assertEquals(0, [SELECT COUNT() FROM Opportunity WHERE StageName = 'Closed']);
581+
582+
Test.startTest();
583+
fflib_SObjectUnitOfWork uow = new fflib_SObjectUnitOfWork(MY_SOBJECTS);
584+
uow.registerUpsert(new List<Opportunity>{existingOpp}, Opportunity.Id);
585+
uow.commitWork();
586+
Test.stopTest();
587+
588+
System.assertEquals(1, [SELECT COUNT() FROM Opportunity]);
589+
System.assertEquals(1, [SELECT COUNT() FROM Opportunity WHERE StageName = 'Closed']);
590+
}
591+
571592
/**
572593
* Assert that actual events exactly match expected events (size, order and name)
573594
* and types match expected types

0 commit comments

Comments
 (0)