Skip to content

Commit

Permalink
Merge pull request #677 from SalesforceFoundation/feature/254
Browse files Browse the repository at this point in the history
Feature 254
  • Loading branch information
AndersonTarren authored Nov 22, 2024
2 parents bb9db07 + 3819b42 commit b67c6f8
Show file tree
Hide file tree
Showing 12 changed files with 407 additions and 116 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ PMM AND SFDO BASE ARE NON-SFDC APPLICATIONS OR THIRD-PARTY APPLICATIONS, AND NOT

SFDC WILL NOT HAVE ANY LIABILITY ARISING OUT OF OR RELATED TO YOUR USE OF PMM OR SFDO BASE FOR ANY DIRECT DAMAGES OR FOR ANY LOST PROFITS, REVENUES, GOODWILL OR INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL, EXEMPLARY, COVER, BUSINESS INTERRUPTION OR PUNITIVE DAMAGES, WHETHER AN ACTION IS IN CONTRACT OR TORT AND REGARDLESS OF THE THEORY OF LIABILITY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES OR IF A REMEDY OTHERWISE FAILS OF ITS ESSENTIAL PURPOSE. THE FOREGOING DISCLAIMER WILL NOT APPLY TO THE EXTENT PROHIBITED BY LAW. SFDC DISCLAIMS ALL LIABILITY AND INDEMNIFICATION OBLIGATIONS FOR ANY HARM OR DAMAGES CAUSED BY ANY THIRD-PARTY HOSTING PROVIDERS.

THIS AGREEMENT SHALL BE GOVERNED EXCLUSIVELY BY, AND CONSTRUED EXCLUSIVELY IN ACCORDANCE WITH, THE LAWS OF THE UNITED STATES AND THE STATE OF CALIFORNIA, WITHOUT REGARD TO ITS CONFLICT OF LAWS PROVISIONS. THE STATE AND FEDERAL COURTS LOCATED IN SAN FRANCISCO, CALIFORNIA SHALL HAVE EXCLUSIVE JURISDICTION TO ADJUDICATE ANY DISPUTE ARISING OUT OF OR RELATING TO THIS AGREEMENT. EACH PARTY HEREBY CONSENTS TO THE JURISDICTION OF SUCH COURTS AND WAIVES ANY RIGHT IT MAY OTHERWISE HAVE TO CHALLENGE THE APPROPRIATENESS OF SUCH FORUMS.
THIS AGREEMENT SHALL BE GOVERNED EXCLUSIVELY BY, AND CONSTRUED EXCLUSIVELY IN ACCORDANCE WITH, THE LAWS OF THE UNITED STATES AND THE STATE OF CALIFORNIA, WITHOUT REGARD TO ITS CONFLICT OF LAWS PROVISIONS. THE STATE AND FEDERAL COURTS LOCATED IN SAN FRANCISCO, CALIFORNIA SHALL HAVE EXCLUSIVE JURISDICTION TO ADJUDICATE ANY DISPUTE ARISING OUT OF OR RELATING TO THIS AGREEMENT. EACH PARTY HEREBY CONSENTS TO THE JURISDICTION OF SUCH COURTS AND WAIVES ANY RIGHT IT MAY OTHERWISE HAVE TO CHALLENGE THE APPROPRIATENESS OF SUCH FORUMS.
3 changes: 1 addition & 2 deletions force-app/main/default/classes/ProgramEngagementSelector.cls
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,7 @@ public with sharing class ProgramEngagementSelector {
List<List<SObject>> contactResult = [
FIND :searchText
IN ALL FIELDS
RETURNING
Contact(FirstName, LastName, Email ORDER BY LastName LIMIT :SEARCH_LIMIT)
RETURNING Contact(FirstName, LastName, Email LIMIT :SEARCH_LIMIT)
];

return getEngagementIdsFromSOSLResult(
Expand Down
17 changes: 3 additions & 14 deletions force-app/main/default/classes/ProgramEngagementSelector_TEST.cls
Original file line number Diff line number Diff line change
Expand Up @@ -171,21 +171,14 @@ public with sharing class ProgramEngagementSelector_TEST {
[
SELECT Id, Contact__r.Name, Contact__r.Email, Stage__c, ProgramCohort__c
FROM ProgramEngagement__c
WHERE
Program__c = :program.Id
AND Contact__r.Name LIKE '%Contact%'
AND Stage__c = 'Enrolled'
WHERE Program__c = :program.Id AND Stage__c = 'Enrolled'
]
);

//Search results must be populated manually for SOSL
List<Id> soslTestIds = new List<Id>{ expected[0].Id };

for (Contact con : [
SELECT Id, Name, Email
FROM Contact
WHERE Name LIKE '%Contact%'
]) {
for (Contact con : [SELECT Id, Name, Email FROM Contact]) {
soslTestIds.add(con.Id);
}
Test.setFixedSearchResults(soslTestIds);
Expand Down Expand Up @@ -240,11 +233,7 @@ public with sharing class ProgramEngagementSelector_TEST {
//Search results must be populated manually for SOSL
List<Id> soslTestIds = new List<Id>{ expected[0].Id };

for (Contact con : [
SELECT Id, Name, Email
FROM Contact
WHERE Name LIKE '%Contact%'
]) {
for (Contact con : [SELECT Id, Name, Email FROM Contact]) {
soslTestIds.add(con.Id);
}
Test.setFixedSearchResults(soslTestIds);
Expand Down
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 b67c6f8

Please sign in to comment.