Skip to content

Commit

Permalink
Merge pull request #681 from SalesforceFoundation/feature/254__fix-bu…
Browse files Browse the repository at this point in the history
…lk-save

Move to bulk save.
  • Loading branch information
mldyang authored Sep 19, 2024
2 parents 6dde17b + 353cb15 commit 3819b42
Show file tree
Hide file tree
Showing 9 changed files with 402 additions and 99 deletions.
14 changes: 14 additions & 0 deletions force-app/main/default/classes/ServiceDeliveryController.cls
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ public with sharing class ServiceDeliveryController {
return true;
}

@AuraEnabled
public static String upsertServiceDeliveries(
List<ServiceDelivery__c> serviceDeliveries,
Boolean allOrNone
) {
try {
List<Database.UpsertResult> results = deliveryDomain
.upsertServiceDeliveries(serviceDeliveries, allOrNone);
return JSON.serialize(results);
} catch (Exception e) {
throw Util.getAuraHandledException(e);
}
}

@AuraEnabled
public static Integer deleteServiceDeliveriesForSession(Id sessionId) {
try {
Expand Down
80 changes: 80 additions & 0 deletions force-app/main/default/classes/ServiceDeliveryController_TEST.cls
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,86 @@ public with sharing class ServiceDeliveryController_TEST {
);
}

@IsTest
private static void testUpsertServiceDeliveries() {
List<ServiceDelivery__c> serviceDeliveries = new List<ServiceDelivery__c>{
new ServiceDelivery__c(
Name = 'Test1',
Id = TestUtil.mockId(ServiceDelivery__c.SObjectType)
),
new ServiceDelivery__c(
Name = 'Test2',
Id = TestUtil.mockId(ServiceDelivery__c.SObjectType)
),
new ServiceDelivery__c(
Name = 'Test3',
Id = TestUtil.mockId(ServiceDelivery__c.SObjectType)
)
};

domainStub.withReturnValue(
'upsertServiceDeliveries',
new List<Type>{ List<Database.UpsertResult>.class, Boolean.class },
null
);

Test.startTest();
ServiceDeliveryController.deliveryDomain = (ServiceDeliveryDomain) domainStub.createMock();
ServiceDeliveryController.upsertServiceDeliveries(serviceDeliveries, false);
Test.stopTest();

domainStub.assertCalledWith(
'upsertServiceDeliveries',
new List<Type>{ List<ServiceDelivery__c>.class, Boolean.class },
new List<Object>{ serviceDeliveries, false }
);
}

@IsTest
private static void testUpsertServiceDeliveriesException() {
List<ServiceDelivery__c> serviceDeliveries = new List<ServiceDelivery__c>{
new ServiceDelivery__c(
Name = 'Test1',
Id = TestUtil.mockId(ServiceDelivery__c.SObjectType)
),
new ServiceDelivery__c(
Name = 'Test2',
Id = TestUtil.mockId(ServiceDelivery__c.SObjectType)
),
new ServiceDelivery__c(
Name = 'Test3',
Id = TestUtil.mockId(ServiceDelivery__c.SObjectType)
)
};

domainStub.withThrowException(
'upsertServiceDeliveries',
new List<Type>{ List<ServiceDelivery__c>.class, Boolean.class }
);

Test.startTest();
ServiceDeliveryController.deliveryDomain = (ServiceDeliveryDomain) domainStub.createMock();

Exception actualException;
try {
ServiceDeliveryController.upsertServiceDeliveries(serviceDeliveries, false);
} catch (Exception e) {
actualException = e;
}
Test.stopTest();

System.assertEquals(
domainStub.testExceptionMessage,
actualException.getMessage(),
'Expected the controller to rethrow the exception from the domain.'
);
domainStub.assertCalledWith(
'upsertServiceDeliveries',
new List<Type>{ List<ServiceDelivery__c>.class, Boolean.class },
new List<Object>{ serviceDeliveries, false }
);
}

@IsTest
private static void testGetNumberOfServiceDeliveriesForSession() {
Integer expectedNumberOfDeliveries = 5;
Expand Down
64 changes: 53 additions & 11 deletions force-app/main/default/classes/ServiceDeliveryDomain.cls
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,7 @@ public with sharing class ServiceDeliveryDomain {
return;
}

if (
!PermissionValidator.getInstance()
.hasObjectAccess(
ServiceDelivery__c.SObjectType,
PermissionValidator.CRUDAccessType.CREATEABLE
)
) {
throw new ServiceDeliveryDomainException(Label.UpsertOperationException);
}
validateInsertAccess();

insert Security.stripInaccessible(AccessType.CREATABLE, serviceDeliveries)
.getRecords();
Expand All @@ -70,6 +62,47 @@ public with sharing class ServiceDeliveryDomain {
return;
}

validateUpdateAccess();

update Security.stripInaccessible(AccessType.UPDATABLE, serviceDeliveries)
.getRecords();
}

public List<Database.UpsertResult> upsertServiceDeliveries(
List<ServiceDelivery__c> serviceDeliveries,
Boolean allOrNone
) {
Boolean hasNewRecords = false;
Boolean hasExistingRecords = false;

for (ServiceDelivery__c delivery : serviceDeliveries) {
if (!hasNewRecords && delivery.Id == null) {
hasNewRecords = true;
} else if (!hasExistingRecords && delivery.Id != null) {
hasExistingRecords = true;
}
if (hasNewRecords && hasExistingRecords) {
break;
}
}

if (hasNewRecords) {
validateInsertAccess();
}

if (hasExistingRecords) {
validateUpdateAccess();
}

List<Database.UpsertResult> saveResults = Database.upsert(
Security.stripInaccessible(AccessType.UPSERTABLE, serviceDeliveries)
.getRecords(),
allOrNone
);
return saveResults;
}

private void validateUpdateAccess() {
if (
!PermissionValidator.getInstance()
.hasObjectAccess(
Expand All @@ -79,8 +112,17 @@ public with sharing class ServiceDeliveryDomain {
) {
throw new ServiceDeliveryDomainException(Label.UpsertOperationException);
}
}

update Security.stripInaccessible(AccessType.UPDATABLE, serviceDeliveries)
.getRecords();
private void validateInsertAccess() {
if (
!PermissionValidator.getInstance()
.hasObjectAccess(
ServiceDelivery__c.SObjectType,
PermissionValidator.CRUDAccessType.CREATEABLE
)
) {
throw new ServiceDeliveryDomainException(Label.UpsertOperationException);
}
}
}
53 changes: 53 additions & 0 deletions force-app/main/default/classes/ServiceDeliveryDomain_TEST.cls
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,59 @@ private with sharing class ServiceDeliveryDomain_TEST {
}
}

@IsTest
private static void shouldReturnUpsertResultsOnUpsertServiceDeliveriesWithAllOrNone() {
TestDataFactory.generateServiceData();
Service__c service = [SELECT Id FROM Service__c LIMIT 1];

List<ServiceDelivery__c> existingServiceDeliveries = [
SELECT Id, Name
FROM ServiceDelivery__c
];
for (ServiceDelivery__c delivery : existingServiceDeliveries) {
System.assertNotEquals('Upserted', delivery.Name);
delivery.Name = 'Upserted';
delivery.AutonameOverride__c = true;
}

ServiceDelivery__c newServiceDelivery = new ServiceDelivery__c(
Name = 'Upserted',
AutonameOverride__c = true,
Service__c = service.Id
);

List<ServiceDelivery__c> serviceDeliveriesToUpsert = new List<ServiceDelivery__c>();
serviceDeliveriesToUpsert.addAll(existingServiceDeliveries);
serviceDeliveriesToUpsert.add(newServiceDelivery);

Test.startTest();
List<Database.UpsertResult> results = new ServiceDeliveryDomain()
.upsertServiceDeliveries(serviceDeliveriesToUpsert, false);
Test.stopTest();

List<ServiceDelivery__c> serviceDeliveriesAfter = [
SELECT Id, Name
FROM ServiceDelivery__c
];
System.assertEquals(
existingServiceDeliveries.size() + 1,
serviceDeliveriesAfter.size(),
'One new record should be inserted.'
);
System.assertEquals(
serviceDeliveriesAfter.size(),
results.size(),
'Results should be returned for each record upserted.'
);
for (ServiceDelivery__c delivery : serviceDeliveriesAfter) {
System.assertEquals(
'Upserted',
delivery.Name,
'All records should be renamed.'
);
}
}

@IsTest
private static void shouldThrowExceptionWhenInsertPermissionCheckFails() {
String methodName = 'hasObjectAccess';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@
default-values={delivery}
service-delivery-field-sets={serviceDeliveryFieldSets}
index={delivery.index}
onsuccess={handleRowSuccess}
ondelete={handleRowDelete}
onerror={handleRowError}
row-count={rowCount}
should-focus={delivery.shouldFocus}
></c-service-delivery-row>
Expand Down
Loading

0 comments on commit 3819b42

Please sign in to comment.