From 5c0994b6a23b0f7719bf3dc77e886bb2b45d449f Mon Sep 17 00:00:00 2001 From: Tarren Anderson Date: Thu, 12 Jan 2023 10:26:30 -0600 Subject: [PATCH 01/15] Arbitrary change for 244 placeholder --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 6b8f2de8d..69ba36bfb 100644 --- a/README.md +++ b/README.md @@ -27,4 +27,3 @@ 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. - From 579f255934d36dedb168256f46ba6d182dda5a8f Mon Sep 17 00:00:00 2001 From: Tarren Anderson Date: Thu, 12 Jan 2023 15:46:06 -0600 Subject: [PATCH 02/15] Sort order for BSDT Combobox --- force-app/main/default/classes/ProgramEngagementSelector.cls | 1 + force-app/main/default/classes/ProgramSelector.cls | 2 +- force-app/main/default/classes/ServiceSelector.cls | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/force-app/main/default/classes/ProgramEngagementSelector.cls b/force-app/main/default/classes/ProgramEngagementSelector.cls index 2e5894d7f..b9fa3f7c0 100755 --- a/force-app/main/default/classes/ProgramEngagementSelector.cls +++ b/force-app/main/default/classes/ProgramEngagementSelector.cls @@ -25,6 +25,7 @@ public with sharing class ProgramEngagementSelector { SELECT Id, Name, Program__c, Program__r.Name FROM ProgramEngagement__c WHERE Contact__c = :contactId + ORDER BY Name ]; return Security.stripInaccessible(AccessType.READABLE, queriedEngagements) diff --git a/force-app/main/default/classes/ProgramSelector.cls b/force-app/main/default/classes/ProgramSelector.cls index d9391c411..14547903f 100644 --- a/force-app/main/default/classes/ProgramSelector.cls +++ b/force-app/main/default/classes/ProgramSelector.cls @@ -41,7 +41,7 @@ public with sharing class ProgramSelector { ' IN :allowedProgramCohortStatuses' ); } - + queryBuilder.withOrderBy(String.valueOf(ProgramCohort__c.Name)); programCohorts = Database.query(queryBuilder.buildSoqlQuery()); return Security.stripInaccessible(AccessType.READABLE, programCohorts) diff --git a/force-app/main/default/classes/ServiceSelector.cls b/force-app/main/default/classes/ServiceSelector.cls index 09e15c255..9d868d62b 100755 --- a/force-app/main/default/classes/ServiceSelector.cls +++ b/force-app/main/default/classes/ServiceSelector.cls @@ -19,6 +19,7 @@ public with sharing class ServiceSelector { SELECT Id, Name, Program__c FROM Service__c WHERE Program__c IN :programIds + ORDER BY Name ]; return Security.stripInaccessible(AccessType.READABLE, queriedServices) @@ -39,6 +40,7 @@ public with sharing class ServiceSelector { FROM ProgramEngagement__c WHERE Id = :programEngagementId ) + ORDER BY Name ]; return Security.stripInaccessible(AccessType.READABLE, services).getRecords(); From d38579458399eb69f8378a6cae7716d36465e025 Mon Sep 17 00:00:00 2001 From: Tarren Anderson Date: Fri, 13 Jan 2023 16:24:22 -0600 Subject: [PATCH 03/15] Using sort vs order by for Shield --- .../main/default/classes/ProgramEngagementSelector.cls | 3 +-- force-app/main/default/classes/ProgramSelector.cls | 3 +-- force-app/main/default/classes/ServiceSelector.cls | 6 ++---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/force-app/main/default/classes/ProgramEngagementSelector.cls b/force-app/main/default/classes/ProgramEngagementSelector.cls index b9fa3f7c0..9a979dca8 100755 --- a/force-app/main/default/classes/ProgramEngagementSelector.cls +++ b/force-app/main/default/classes/ProgramEngagementSelector.cls @@ -25,9 +25,8 @@ public with sharing class ProgramEngagementSelector { SELECT Id, Name, Program__c, Program__r.Name FROM ProgramEngagement__c WHERE Contact__c = :contactId - ORDER BY Name ]; - + queriedEngagements.sort(); return Security.stripInaccessible(AccessType.READABLE, queriedEngagements) .getRecords(); } diff --git a/force-app/main/default/classes/ProgramSelector.cls b/force-app/main/default/classes/ProgramSelector.cls index 14547903f..b0e48e172 100644 --- a/force-app/main/default/classes/ProgramSelector.cls +++ b/force-app/main/default/classes/ProgramSelector.cls @@ -41,9 +41,8 @@ public with sharing class ProgramSelector { ' IN :allowedProgramCohortStatuses' ); } - queryBuilder.withOrderBy(String.valueOf(ProgramCohort__c.Name)); programCohorts = Database.query(queryBuilder.buildSoqlQuery()); - + programCohorts.sort(); return Security.stripInaccessible(AccessType.READABLE, programCohorts) .getRecords(); } diff --git a/force-app/main/default/classes/ServiceSelector.cls b/force-app/main/default/classes/ServiceSelector.cls index 9d868d62b..a44a802c7 100755 --- a/force-app/main/default/classes/ServiceSelector.cls +++ b/force-app/main/default/classes/ServiceSelector.cls @@ -19,9 +19,8 @@ public with sharing class ServiceSelector { SELECT Id, Name, Program__c FROM Service__c WHERE Program__c IN :programIds - ORDER BY Name ]; - + queriedServices.sort(); return Security.stripInaccessible(AccessType.READABLE, queriedServices) .getRecords(); } @@ -40,9 +39,8 @@ public with sharing class ServiceSelector { FROM ProgramEngagement__c WHERE Id = :programEngagementId ) - ORDER BY Name ]; - + services.sort(); return Security.stripInaccessible(AccessType.READABLE, services).getRecords(); } From 3bc2a4b7b0434cdda6381bcbb0925e593dfa1976 Mon Sep 17 00:00:00 2001 From: Tarren Anderson Date: Mon, 20 Feb 2023 19:07:10 -0600 Subject: [PATCH 04/15] BSDT Active Services Filter --- .../main/default/classes/ServiceSelector.cls | 2 +- .../main/default/classes/ServiceService.cls | 41 +++++++++++- .../default/classes/ServiceService_TEST.cls | 64 ++++++++++++++++++- .../Bucket.ServiceStatusActive.md-meta.xml | 9 +++ .../BucketedField.ServiceStatuses.md-meta.xml | 13 ++++ ...ketedValue.ServiceStatusActive.md-meta.xml | 13 ++++ 6 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 force-app/main/default/customMetadata/Bucket.ServiceStatusActive.md-meta.xml create mode 100644 force-app/main/default/customMetadata/BucketedField.ServiceStatuses.md-meta.xml create mode 100644 force-app/main/default/customMetadata/BucketedValue.ServiceStatusActive.md-meta.xml diff --git a/force-app/main/default/classes/ServiceSelector.cls b/force-app/main/default/classes/ServiceSelector.cls index a44a802c7..b1fa15381 100755 --- a/force-app/main/default/classes/ServiceSelector.cls +++ b/force-app/main/default/classes/ServiceSelector.cls @@ -16,7 +16,7 @@ public with sharing class ServiceSelector { return new List(); } List queriedServices = [ - SELECT Id, Name, Program__c + SELECT Id, Name, Program__c, Status__c FROM Service__c WHERE Program__c IN :programIds ]; diff --git a/force-app/main/default/classes/ServiceService.cls b/force-app/main/default/classes/ServiceService.cls index 0f6d4c778..ee2962354 100644 --- a/force-app/main/default/classes/ServiceService.cls +++ b/force-app/main/default/classes/ServiceService.cls @@ -10,6 +10,8 @@ public with sharing class ServiceService { public ServiceService() { } + @TestVisible + private FieldBucketSelector bucketSelector = new FieldBucketSelector(); @TestVisible private FieldSetService fieldSetService = new FieldSetService(); @@ -20,10 +22,44 @@ public with sharing class ServiceService { @TestVisible private ProgramEngagementSelector engagementSelector = new ProgramEngagementSelector(); + @TestVisible + private Set activeStatuses { + get { + if (activeStatuses == null) { + activeStatuses = getactiveStatuses(); + } + return activeStatuses; + } + set; + } + + private Set getActiveStatuses() { + List bucketNames = new List{ 'ServiceStatusActive' }; + Set activeStatuses = new Set(); + + Schema.SObjectType serviceSObjType = Service__c.SObjectType; + Schema.SObjectField statusField = Service__c.Status__c; + + for ( + Bucket__mdt bucket : bucketSelector.getBuckets( + bucketNames, + serviceSObjType, + statusField + ) + ) { + for (BucketedValue__mdt value : bucket.BucketedValues__r) { + activeStatuses.add(value.Value__c); + } + } + + return activeStatuses; + } + public Map> getServicesEngagementsByContactId(Id contactId) { Set programIds = new Set(); String serviceProgram = Schema.SObjectType.Service__c.Fields.Program__c.getName(); String engageProgram = Schema.SObjectType.ProgramEngagement__c.Fields.Program__c.getName(); + Set activeServiceStatuses = activeStatuses; Map> result = new Map>(); result.put('engagements', new List()); @@ -40,7 +76,10 @@ public with sharing class ServiceService { } for (Service__c service : serviceSelector.getServicesByProgramIds(programIds)) { - result.get('services').add(convertObjectToOption(service, serviceProgram)); + if (activeServiceStatuses.contains(service.Status__c)) { + result.get('services') + .add(convertObjectToOption(service, serviceProgram)); + } } return result; diff --git a/force-app/main/default/classes/ServiceService_TEST.cls b/force-app/main/default/classes/ServiceService_TEST.cls index 51aad9973..ed199ef77 100644 --- a/force-app/main/default/classes/ServiceService_TEST.cls +++ b/force-app/main/default/classes/ServiceService_TEST.cls @@ -37,10 +37,23 @@ public with sharing class ServiceService_TEST { UnitOfMeasurement__c = 'Hours' ); + Service__c service2 = new Service__c( + Id = TestUtil.mockId(Service__c.SObjectType), + Name = 'Service 2', + Program__c = program1.Id, + Status__c = 'Planned', + UnitOfMeasurement__c = 'Hours' + ); + List engagements = new List{ engagement1 }; - List services = new List{ service1 }; + List services = new List{ service1, service2 }; + List bucketNames = new List{ 'ServiceStatusActive' }; + Schema.SObjectType serviceSObjType = Service__c.SObjectType; + Schema.SObjectField statusField = Service__c.Status__c; + List statusBuckets = createBuckets(); + TestStub engagementSelectorStub = new StubBuilder(ProgramEngagementSelector.class) .when('getProgramEngagementsByContactId', Id.class) .calledWith(contactId) @@ -51,10 +64,21 @@ public with sharing class ServiceService_TEST { .calledWith(new Set{ program1.Id }) .thenReturn(services) .build(); + TestStub bucketSelectorStub = new StubBuilder(FieldBucketSelector.class) + .when( + 'getBuckets', + List.class, + Schema.SObjectType.class, + Schema.SObjectField.class + ) + .calledWith(bucketNames, serviceSObjType, statusField) + .thenReturn(statusBuckets) + .build(); ServiceService service = new ServiceService(); service.serviceSelector = (ServiceSelector) serviceSelectorStub.create(); service.engagementSelector = (ProgramEngagementSelector) engagementSelectorStub.create(); + service.bucketSelector = (FieldBucketSelector) bucketSelectorStub.create(); Test.startTest(); Map> actual = service.getServicesEngagementsByContactId( @@ -73,8 +97,15 @@ public with sharing class ServiceService_TEST { System.assert(!objList.isEmpty()); } + System.assertEquals( + 1, + actual.get('services').size(), + 'Only active services should be returned' + ); + engagementSelectorStub.assertCalledAsExpected(); serviceSelectorStub.assertCalledAsExpected(); + bucketSelectorStub.assertCalledAsExpected(); } @IsTest @@ -701,4 +732,35 @@ public with sharing class ServiceService_TEST { fieldSetServiceStub.assertCalledAsExpected(); } + + private static List createBuckets() { + BucketedField__mdt bucketedField = (BucketedField__mdt) new TestUtil.BucketedFieldBuilder() + .withDeveloperName('ServiceStatuses') + .withQualifiedApiName(Util.prefixNamespace('ServiceStatuses')) + .withField('Status__c') + .withObject('Service__c') + .withMockId() + .build(); + + List activeValues = new List(); + activeValues.add( + (BucketedValue__mdt) new TestUtil.BucketedValueBuilder() + .withDeveloperName('ServiceStatusActive') + .withQualifiedApiName(Util.prefixNamespace('ServiceStatusActive')) + .withBucket('ServiceStatusActive') + .withValue('Active') + .withMockId() + .build() + ); + + Bucket__mdt activeBucket = (Bucket__mdt) new TestUtil.BucketBuilder() + .withBucketedField(bucketedField) + .withBucketedValues(activeValues) + .withDeveloperName('ServiceStatusActive') + .withQualifiedApiName(Util.prefixNamespace('ServiceStatusActive')) + .withMockId() + .build(); + + return new List{ activeBucket }; + } } diff --git a/force-app/main/default/customMetadata/Bucket.ServiceStatusActive.md-meta.xml b/force-app/main/default/customMetadata/Bucket.ServiceStatusActive.md-meta.xml new file mode 100644 index 000000000..361af2506 --- /dev/null +++ b/force-app/main/default/customMetadata/Bucket.ServiceStatusActive.md-meta.xml @@ -0,0 +1,9 @@ + + + + false + + BucketedField__c + ServiceStatuses + + diff --git a/force-app/main/default/customMetadata/BucketedField.ServiceStatuses.md-meta.xml b/force-app/main/default/customMetadata/BucketedField.ServiceStatuses.md-meta.xml new file mode 100644 index 000000000..030117da0 --- /dev/null +++ b/force-app/main/default/customMetadata/BucketedField.ServiceStatuses.md-meta.xml @@ -0,0 +1,13 @@ + + + + false + + Field__c + Status__c + + + Object__c + Service__c + + diff --git a/force-app/main/default/customMetadata/BucketedValue.ServiceStatusActive.md-meta.xml b/force-app/main/default/customMetadata/BucketedValue.ServiceStatusActive.md-meta.xml new file mode 100644 index 000000000..9b409ac87 --- /dev/null +++ b/force-app/main/default/customMetadata/BucketedValue.ServiceStatusActive.md-meta.xml @@ -0,0 +1,13 @@ + + + + false + + Bucket__c + ServiceStatusActive + + + Value__c + Active + + From cb435bb0769cee4b787ef3c322a84a7f87ae32f6 Mon Sep 17 00:00:00 2001 From: Tarren Anderson Date: Tue, 21 Feb 2023 17:46:56 -0600 Subject: [PATCH 05/15] Program Engagement Stage filter --- .../classes/ProgramEngagementSelector.cls | 2 +- .../main/default/classes/ServiceService.cls | 13 +++++++--- .../default/classes/ServiceService_TEST.cls | 26 +++++++++++++++++-- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/force-app/main/default/classes/ProgramEngagementSelector.cls b/force-app/main/default/classes/ProgramEngagementSelector.cls index 9a979dca8..5ac052935 100755 --- a/force-app/main/default/classes/ProgramEngagementSelector.cls +++ b/force-app/main/default/classes/ProgramEngagementSelector.cls @@ -22,7 +22,7 @@ public with sharing class ProgramEngagementSelector { } List queriedEngagements = [ - SELECT Id, Name, Program__c, Program__r.Name + SELECT Id, Name, Program__c, Program__r.Name, Stage__c FROM ProgramEngagement__c WHERE Contact__c = :contactId ]; diff --git a/force-app/main/default/classes/ServiceService.cls b/force-app/main/default/classes/ServiceService.cls index ee2962354..019c8fe4f 100644 --- a/force-app/main/default/classes/ServiceService.cls +++ b/force-app/main/default/classes/ServiceService.cls @@ -10,6 +10,7 @@ public with sharing class ServiceService { public ServiceService() { } + @TestVisible private FieldBucketSelector bucketSelector = new FieldBucketSelector(); @@ -19,6 +20,9 @@ public with sharing class ServiceService { @TestVisible private ServiceSelector serviceSelector = new ServiceSelector(); + @TestVisible + private ProgramEngagementService engagementService = new ProgramEngagementService(); + @TestVisible private ProgramEngagementSelector engagementSelector = new ProgramEngagementSelector(); @@ -60,6 +64,7 @@ public with sharing class ServiceService { String serviceProgram = Schema.SObjectType.Service__c.Fields.Program__c.getName(); String engageProgram = Schema.SObjectType.ProgramEngagement__c.Fields.Program__c.getName(); Set activeServiceStatuses = activeStatuses; + Set activeProgramEngagementStages = engagementService.getActiveStages(); Map> result = new Map>(); result.put('engagements', new List()); @@ -70,9 +75,11 @@ public with sharing class ServiceService { contactId ) ) { - programIds.add(engagement.Program__c); - result.get('engagements') - .add(convertObjectToOption(engagement, engageProgram)); + if (activeProgramEngagementStages.contains(engagement.Stage__c)) { + programIds.add(engagement.Program__c); + result.get('engagements') + .add(convertObjectToOption(engagement, engageProgram)); + } } for (Service__c service : serviceSelector.getServicesByProgramIds(programIds)) { diff --git a/force-app/main/default/classes/ServiceService_TEST.cls b/force-app/main/default/classes/ServiceService_TEST.cls index ed199ef77..4837c64de 100644 --- a/force-app/main/default/classes/ServiceService_TEST.cls +++ b/force-app/main/default/classes/ServiceService_TEST.cls @@ -23,6 +23,14 @@ public with sharing class ServiceService_TEST { ProgramEngagement__c engagement1 = new ProgramEngagement__c( Name = 'Engagement 1', + Stage__c = 'Active', + Contact__c = contactId, + Program__c = program1.Id, + Role__c = 'Client' + ); + + ProgramEngagement__c engagement2 = new ProgramEngagement__c( + Name = 'Engagement 2', Stage__c = 'Enrolled', Contact__c = contactId, Program__c = program1.Id, @@ -46,14 +54,21 @@ public with sharing class ServiceService_TEST { ); List engagements = new List{ - engagement1 + engagement1, + engagement2 }; List services = new List{ service1, service2 }; List bucketNames = new List{ 'ServiceStatusActive' }; Schema.SObjectType serviceSObjType = Service__c.SObjectType; Schema.SObjectField statusField = Service__c.Status__c; List statusBuckets = createBuckets(); + Set activeStages = new Set{ 'Active' }; + TestStub engagementServiceStub = new StubBuilder(ProgramEngagementService.class) + .when('getActiveStages') + .called() + .thenReturn(activeStages) + .build(); TestStub engagementSelectorStub = new StubBuilder(ProgramEngagementSelector.class) .when('getProgramEngagementsByContactId', Id.class) .calledWith(contactId) @@ -79,6 +94,7 @@ public with sharing class ServiceService_TEST { service.serviceSelector = (ServiceSelector) serviceSelectorStub.create(); service.engagementSelector = (ProgramEngagementSelector) engagementSelectorStub.create(); service.bucketSelector = (FieldBucketSelector) bucketSelectorStub.create(); + service.engagementService = (ProgramEngagementService) engagementServiceStub.create(); Test.startTest(); Map> actual = service.getServicesEngagementsByContactId( @@ -97,10 +113,16 @@ public with sharing class ServiceService_TEST { System.assert(!objList.isEmpty()); } + System.assertEquals( + 1, + actual.get('engagements').size(), + 'Only active Program Engagements should be returned' + ); + System.assertEquals( 1, actual.get('services').size(), - 'Only active services should be returned' + 'Only active Services should be returned' ); engagementSelectorStub.assertCalledAsExpected(); From 9e224e48824a348c299b9d6d36179d7606aeb8bc Mon Sep 17 00:00:00 2001 From: Tarren Anderson Date: Thu, 23 Feb 2023 11:37:20 -0600 Subject: [PATCH 06/15] Review Feedback --- .../main/default/classes/ServiceService.cls | 38 +++++++++++++------ ...ketedValue.ServiceStatusActive.md-meta.xml | 13 ------- 2 files changed, 26 insertions(+), 25 deletions(-) delete mode 100644 force-app/main/default/customMetadata/BucketedValue.ServiceStatusActive.md-meta.xml diff --git a/force-app/main/default/classes/ServiceService.cls b/force-app/main/default/classes/ServiceService.cls index 019c8fe4f..494cf72ca 100644 --- a/force-app/main/default/classes/ServiceService.cls +++ b/force-app/main/default/classes/ServiceService.cls @@ -11,6 +11,15 @@ public with sharing class ServiceService { public ServiceService() { } + private static final String SERVICE_STATUS_ACTIVE = 'ServiceStatusActive'; + private static final String ENGAGEMENTS = 'engagements'; + private static final String SERVICES = 'services'; + private static final String LABEL = 'label'; + private static final String VALUE = 'value'; + private static final String NAME = 'Name'; + private static final String Id = 'Id'; + private static final String PROGRAM = 'program'; + @TestVisible private FieldBucketSelector bucketSelector = new FieldBucketSelector(); @@ -30,7 +39,7 @@ public with sharing class ServiceService { private Set activeStatuses { get { if (activeStatuses == null) { - activeStatuses = getactiveStatuses(); + activeStatuses = getActiveStatuses(); } return activeStatuses; } @@ -38,7 +47,7 @@ public with sharing class ServiceService { } private Set getActiveStatuses() { - List bucketNames = new List{ 'ServiceStatusActive' }; + List bucketNames = new List{ SERVICE_STATUS_ACTIVE }; Set activeStatuses = new Set(); Schema.SObjectType serviceSObjType = Service__c.SObjectType; @@ -67,25 +76,30 @@ public with sharing class ServiceService { Set activeProgramEngagementStages = engagementService.getActiveStages(); Map> result = new Map>(); - result.put('engagements', new List()); - result.put('services', new List()); + result.put(ENGAGEMENTS, new List()); + result.put(SERVICES, new List()); for ( ProgramEngagement__c engagement : engagementSelector.getProgramEngagementsByContactId( contactId ) ) { - if (activeProgramEngagementStages.contains(engagement.Stage__c)) { + if ( + activeProgramEngagementStages.isEmpty() || + activeProgramEngagementStages.contains(engagement.Stage__c) + ) { programIds.add(engagement.Program__c); - result.get('engagements') + result.get(ENGAGEMENTS) .add(convertObjectToOption(engagement, engageProgram)); } } for (Service__c service : serviceSelector.getServicesByProgramIds(programIds)) { - if (activeServiceStatuses.contains(service.Status__c)) { - result.get('services') - .add(convertObjectToOption(service, serviceProgram)); + if ( + activeServiceStatuses.isEmpty() || + activeServiceStatuses.contains(service.Status__c) + ) { + result.get(SERVICES).add(convertObjectToOption(service, serviceProgram)); } } @@ -94,9 +108,9 @@ public with sharing class ServiceService { private Map convertObjectToOption(sObject obj, String programField) { Map result = new Map(); - result.put('label', (String) obj.get('Name')); - result.put('value', (String) obj.get('Id')); - result.put('program', (String) obj.get(programField)); + result.put(LABEL, (String) obj.get(NAME)); + result.put(VALUE, (String) obj.get(ID)); + result.put(PROGRAM, (String) obj.get(programField)); return result; } diff --git a/force-app/main/default/customMetadata/BucketedValue.ServiceStatusActive.md-meta.xml b/force-app/main/default/customMetadata/BucketedValue.ServiceStatusActive.md-meta.xml deleted file mode 100644 index 9b409ac87..000000000 --- a/force-app/main/default/customMetadata/BucketedValue.ServiceStatusActive.md-meta.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - false - - Bucket__c - ServiceStatusActive - - - Value__c - Active - - From 85f9227e7a86428691ab10f87efdb1733e579296 Mon Sep 17 00:00:00 2001 From: Tarren Anderson Date: Fri, 24 Feb 2023 13:31:13 -0600 Subject: [PATCH 07/15] Adding feature gate for Active filter --- .../main/default/classes/ServiceService.cls | 27 +++- .../default/classes/ServiceService_TEST.cls | 126 +++++++++++++++++- force-app/main/default/classes/TestUtil.cls | 1 + ...ketedValue.ServiceStatusActive.md-meta.xml | 13 ++ .../FeatureGate.BSDTActiveFilter.md-meta.xml | 9 ++ 5 files changed, 171 insertions(+), 5 deletions(-) create mode 100644 force-app/main/default/customMetadata/BucketedValue.ServiceStatusActive.md-meta.xml create mode 100644 force-app/main/default/customMetadata/FeatureGate.BSDTActiveFilter.md-meta.xml diff --git a/force-app/main/default/classes/ServiceService.cls b/force-app/main/default/classes/ServiceService.cls index 494cf72ca..880b0b2a1 100644 --- a/force-app/main/default/classes/ServiceService.cls +++ b/force-app/main/default/classes/ServiceService.cls @@ -19,6 +19,7 @@ public with sharing class ServiceService { private static final String NAME = 'Name'; private static final String Id = 'Id'; private static final String PROGRAM = 'program'; + private static final String BSDT_ACTIVE_FILTER = 'BSDTActiveFilter'; @TestVisible private FieldBucketSelector bucketSelector = new FieldBucketSelector(); @@ -68,12 +69,28 @@ public with sharing class ServiceService { return activeStatuses; } + private Boolean getActiveFilterFeatureGateStatus() { + List features = CustomMetadataSelector.getInstance() + .getAllFeatureGates(); + + for (FeatureGate__mdt feature : features) { + if ( + feature.IsActive__c && BSDT_ACTIVE_FILTER.contains(feature.DeveloperName) + ) { + return feature.IsActive__c; + } + } + + return false; + } + public Map> getServicesEngagementsByContactId(Id contactId) { Set programIds = new Set(); String serviceProgram = Schema.SObjectType.Service__c.Fields.Program__c.getName(); String engageProgram = Schema.SObjectType.ProgramEngagement__c.Fields.Program__c.getName(); Set activeServiceStatuses = activeStatuses; Set activeProgramEngagementStages = engagementService.getActiveStages(); + Boolean bsdtFilterIsActive = getActiveFilterFeatureGateStatus(); Map> result = new Map>(); result.put(ENGAGEMENTS, new List()); @@ -85,8 +102,9 @@ public with sharing class ServiceService { ) ) { if ( - activeProgramEngagementStages.isEmpty() || - activeProgramEngagementStages.contains(engagement.Stage__c) + !bsdtFilterIsActive || + (activeProgramEngagementStages.isEmpty() || + activeProgramEngagementStages.contains(engagement.Stage__c)) ) { programIds.add(engagement.Program__c); result.get(ENGAGEMENTS) @@ -96,8 +114,9 @@ public with sharing class ServiceService { for (Service__c service : serviceSelector.getServicesByProgramIds(programIds)) { if ( - activeServiceStatuses.isEmpty() || - activeServiceStatuses.contains(service.Status__c) + !bsdtFilterIsActive || + (activeServiceStatuses.isEmpty() || + activeServiceStatuses.contains(service.Status__c)) ) { result.get(SERVICES).add(convertObjectToOption(service, serviceProgram)); } diff --git a/force-app/main/default/classes/ServiceService_TEST.cls b/force-app/main/default/classes/ServiceService_TEST.cls index 4837c64de..8cf55b962 100644 --- a/force-app/main/default/classes/ServiceService_TEST.cls +++ b/force-app/main/default/classes/ServiceService_TEST.cls @@ -10,7 +10,7 @@ @isTest public with sharing class ServiceService_TEST { @IsTest - private static void testGetServicesEngagementsByContactId() { + private static void testGetServicesEngagementsByContactIdFeatureOn() { Id contactId = TestUtil.mockId(Contact.SObjectType); Program__c program1 = new Program__c( @@ -96,6 +96,9 @@ public with sharing class ServiceService_TEST { service.bucketSelector = (FieldBucketSelector) bucketSelectorStub.create(); service.engagementService = (ProgramEngagementService) engagementServiceStub.create(); + // By turning off none, we turn on all + TestUtil.turnOffFeatureGates(new Set{}); + Test.startTest(); Map> actual = service.getServicesEngagementsByContactId( contactId @@ -130,6 +133,127 @@ public with sharing class ServiceService_TEST { bucketSelectorStub.assertCalledAsExpected(); } + @IsTest + private static void testGetServicesEngagementsByContactIdFeatureOff() { + Id contactId = TestUtil.mockId(Contact.SObjectType); + + Program__c program1 = new Program__c( + Id = TestUtil.mockId(Program__c.SObjectType), + Name = 'Program 1', + Status__c = 'Active', + StartDate__c = Date.today(), + EndDate__c = Date.today().addDays(30) + ); + + ProgramEngagement__c engagement1 = new ProgramEngagement__c( + Name = 'Engagement 1', + Stage__c = 'Active', + Contact__c = contactId, + Program__c = program1.Id, + Role__c = 'Client' + ); + + ProgramEngagement__c engagement2 = new ProgramEngagement__c( + Name = 'Engagement 2', + Stage__c = 'Enrolled', + Contact__c = contactId, + Program__c = program1.Id, + Role__c = 'Client' + ); + + Service__c service1 = new Service__c( + Id = TestUtil.mockId(Service__c.SObjectType), + Name = 'Service 1', + Program__c = program1.Id, + Status__c = 'Active', + UnitOfMeasurement__c = 'Hours' + ); + + Service__c service2 = new Service__c( + Id = TestUtil.mockId(Service__c.SObjectType), + Name = 'Service 2', + Program__c = program1.Id, + Status__c = 'Planned', + UnitOfMeasurement__c = 'Hours' + ); + + List engagements = new List{ + engagement1, + engagement2 + }; + List services = new List{ service1, service2 }; + List bucketNames = new List{ 'ServiceStatusActive' }; + Schema.SObjectType serviceSObjType = Service__c.SObjectType; + Schema.SObjectField statusField = Service__c.Status__c; + List statusBuckets = createBuckets(); + Set activeStages = new Set{ 'Active' }; + + TestStub engagementServiceStub = new StubBuilder(ProgramEngagementService.class) + .when('getActiveStages') + .called() + .thenReturn(activeStages) + .build(); + TestStub engagementSelectorStub = new StubBuilder(ProgramEngagementSelector.class) + .when('getProgramEngagementsByContactId', Id.class) + .calledWith(contactId) + .thenReturn(engagements) + .build(); + TestStub serviceSelectorStub = new StubBuilder(ServiceSelector.class) + .when('getServicesByProgramIds', Set.class) + .calledWith(new Set{ program1.Id }) + .thenReturn(services) + .build(); + TestStub bucketSelectorStub = new StubBuilder(FieldBucketSelector.class) + .when( + 'getBuckets', + List.class, + Schema.SObjectType.class, + Schema.SObjectField.class + ) + .calledWith(bucketNames, serviceSObjType, statusField) + .thenReturn(statusBuckets) + .build(); + + ServiceService service = new ServiceService(); + service.serviceSelector = (ServiceSelector) serviceSelectorStub.create(); + service.engagementSelector = (ProgramEngagementSelector) engagementSelectorStub.create(); + service.bucketSelector = (FieldBucketSelector) bucketSelectorStub.create(); + service.engagementService = (ProgramEngagementService) engagementServiceStub.create(); + + Test.startTest(); + Map> actual = service.getServicesEngagementsByContactId( + contactId + ); + Test.stopTest(); + + Set expectedKeySet = new Set{ 'engagements', 'services' }; + System.assertEquals( + expectedKeySet, + actual.keySet(), + 'Expected both keys to be returned.' + ); + + for (List objList : actual.values()) { + System.assert(!objList.isEmpty()); + } + + System.assertEquals( + 2, + actual.get('engagements').size(), + 'All Program Engagements should be returned' + ); + + System.assertEquals( + 2, + actual.get('services').size(), + 'All Services should be returned' + ); + + engagementSelectorStub.assertCalledAsExpected(); + serviceSelectorStub.assertCalledAsExpected(); + bucketSelectorStub.assertCalledAsExpected(); + } + @IsTest private static void testGetServicesByProgramEngagementId() { Id programEngagementId = TestUtil.mockId(ProgramEngagement__c.SObjectType); diff --git a/force-app/main/default/classes/TestUtil.cls b/force-app/main/default/classes/TestUtil.cls index ad1ab1073..aff65f9aa 100755 --- a/force-app/main/default/classes/TestUtil.cls +++ b/force-app/main/default/classes/TestUtil.cls @@ -13,6 +13,7 @@ */ public with sharing class TestUtil { private static final Set featureGateNames = new Set{ + 'BSDTActiveFilter', 'ServiceDeliveriesToContact', 'ServiceDeliveriesToService', 'ServiceDeliveriesToServiceSession', diff --git a/force-app/main/default/customMetadata/BucketedValue.ServiceStatusActive.md-meta.xml b/force-app/main/default/customMetadata/BucketedValue.ServiceStatusActive.md-meta.xml new file mode 100644 index 000000000..9b409ac87 --- /dev/null +++ b/force-app/main/default/customMetadata/BucketedValue.ServiceStatusActive.md-meta.xml @@ -0,0 +1,13 @@ + + + + false + + Bucket__c + ServiceStatusActive + + + Value__c + Active + + diff --git a/force-app/main/default/customMetadata/FeatureGate.BSDTActiveFilter.md-meta.xml b/force-app/main/default/customMetadata/FeatureGate.BSDTActiveFilter.md-meta.xml new file mode 100644 index 000000000..79917bd92 --- /dev/null +++ b/force-app/main/default/customMetadata/FeatureGate.BSDTActiveFilter.md-meta.xml @@ -0,0 +1,9 @@ + + + + false + + IsActive__c + false + + From 49bd2555815350048b4f56fd38aed7483267b0e9 Mon Sep 17 00:00:00 2001 From: Tarren Anderson Date: Fri, 24 Feb 2023 15:25:53 -0600 Subject: [PATCH 08/15] Review Feedback 2 --- force-app/main/default/classes/ServiceService.cls | 8 +++----- force-app/main/default/classes/ServiceService_TEST.cls | 3 +++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/force-app/main/default/classes/ServiceService.cls b/force-app/main/default/classes/ServiceService.cls index 880b0b2a1..6653e1a12 100644 --- a/force-app/main/default/classes/ServiceService.cls +++ b/force-app/main/default/classes/ServiceService.cls @@ -69,14 +69,12 @@ public with sharing class ServiceService { return activeStatuses; } - private Boolean getActiveFilterFeatureGateStatus() { + private Boolean isBsdtActiveFilterActive() { List features = CustomMetadataSelector.getInstance() .getAllFeatureGates(); for (FeatureGate__mdt feature : features) { - if ( - feature.IsActive__c && BSDT_ACTIVE_FILTER.contains(feature.DeveloperName) - ) { + if (feature.IsActive__c && BSDT_ACTIVE_FILTER == feature.DeveloperName) { return feature.IsActive__c; } } @@ -90,7 +88,7 @@ public with sharing class ServiceService { String engageProgram = Schema.SObjectType.ProgramEngagement__c.Fields.Program__c.getName(); Set activeServiceStatuses = activeStatuses; Set activeProgramEngagementStages = engagementService.getActiveStages(); - Boolean bsdtFilterIsActive = getActiveFilterFeatureGateStatus(); + Boolean bsdtFilterIsActive = isBsdtActiveFilterActive(); Map> result = new Map>(); result.put(ENGAGEMENTS, new List()); diff --git a/force-app/main/default/classes/ServiceService_TEST.cls b/force-app/main/default/classes/ServiceService_TEST.cls index 8cf55b962..99f579a95 100644 --- a/force-app/main/default/classes/ServiceService_TEST.cls +++ b/force-app/main/default/classes/ServiceService_TEST.cls @@ -135,6 +135,7 @@ public with sharing class ServiceService_TEST { @IsTest private static void testGetServicesEngagementsByContactIdFeatureOff() { + final String BSDT_ACTIVE_FILTER = 'BSDTActiveFilter'; Id contactId = TestUtil.mockId(Contact.SObjectType); Program__c program1 = new Program__c( @@ -220,6 +221,8 @@ public with sharing class ServiceService_TEST { service.bucketSelector = (FieldBucketSelector) bucketSelectorStub.create(); service.engagementService = (ProgramEngagementService) engagementServiceStub.create(); + TestUtil.turnOffFeatureGates(new Set{ BSDT_ACTIVE_FILTER }); + Test.startTest(); Map> actual = service.getServicesEngagementsByContactId( contactId From d0e16ea8c6e89a99d17815208621938d27d7049e Mon Sep 17 00:00:00 2001 From: Tarren Anderson Date: Fri, 24 Feb 2023 15:58:57 -0600 Subject: [PATCH 09/15] Streamline feature checks and bucket values --- .../main/default/classes/ServiceService.cls | 23 +++++++++++-------- .../default/classes/ServiceService_TEST.cls | 1 - 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/force-app/main/default/classes/ServiceService.cls b/force-app/main/default/classes/ServiceService.cls index 6653e1a12..10c8a62d9 100644 --- a/force-app/main/default/classes/ServiceService.cls +++ b/force-app/main/default/classes/ServiceService.cls @@ -74,7 +74,9 @@ public with sharing class ServiceService { .getAllFeatureGates(); for (FeatureGate__mdt feature : features) { - if (feature.IsActive__c && BSDT_ACTIVE_FILTER == feature.DeveloperName) { + if ( + feature.IsActive__c && BSDT_ACTIVE_FILTER.contains(feature.DeveloperName) + ) { return feature.IsActive__c; } } @@ -86,10 +88,15 @@ public with sharing class ServiceService { Set programIds = new Set(); String serviceProgram = Schema.SObjectType.Service__c.Fields.Program__c.getName(); String engageProgram = Schema.SObjectType.ProgramEngagement__c.Fields.Program__c.getName(); - Set activeServiceStatuses = activeStatuses; - Set activeProgramEngagementStages = engagementService.getActiveStages(); + Set activeServiceStatuses = new Set(); + Set activeProgramEngagementStages = new Set(); Boolean bsdtFilterIsActive = isBsdtActiveFilterActive(); + if (bsdtFilterIsActive) { + activeServiceStatuses = getActiveStatuses(); + activeProgramEngagementStages = engagementService.getActiveStages(); + } + Map> result = new Map>(); result.put(ENGAGEMENTS, new List()); result.put(SERVICES, new List()); @@ -100,9 +107,8 @@ public with sharing class ServiceService { ) ) { if ( - !bsdtFilterIsActive || - (activeProgramEngagementStages.isEmpty() || - activeProgramEngagementStages.contains(engagement.Stage__c)) + activeProgramEngagementStages.isEmpty() || + activeProgramEngagementStages.contains(engagement.Stage__c) ) { programIds.add(engagement.Program__c); result.get(ENGAGEMENTS) @@ -112,9 +118,8 @@ public with sharing class ServiceService { for (Service__c service : serviceSelector.getServicesByProgramIds(programIds)) { if ( - !bsdtFilterIsActive || - (activeServiceStatuses.isEmpty() || - activeServiceStatuses.contains(service.Status__c)) + activeServiceStatuses.isEmpty() || + activeServiceStatuses.contains(service.Status__c) ) { result.get(SERVICES).add(convertObjectToOption(service, serviceProgram)); } diff --git a/force-app/main/default/classes/ServiceService_TEST.cls b/force-app/main/default/classes/ServiceService_TEST.cls index 99f579a95..05ceb8e23 100644 --- a/force-app/main/default/classes/ServiceService_TEST.cls +++ b/force-app/main/default/classes/ServiceService_TEST.cls @@ -254,7 +254,6 @@ public with sharing class ServiceService_TEST { engagementSelectorStub.assertCalledAsExpected(); serviceSelectorStub.assertCalledAsExpected(); - bucketSelectorStub.assertCalledAsExpected(); } @IsTest From cb93348650bbcfbab5eb99e78694ebe765ac9719 Mon Sep 17 00:00:00 2001 From: Tarren Anderson Date: Fri, 24 Feb 2023 16:32:09 -0600 Subject: [PATCH 10/15] Using activeStatuses getter --- force-app/main/default/classes/ServiceService.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/force-app/main/default/classes/ServiceService.cls b/force-app/main/default/classes/ServiceService.cls index 10c8a62d9..2baf2ea1c 100644 --- a/force-app/main/default/classes/ServiceService.cls +++ b/force-app/main/default/classes/ServiceService.cls @@ -93,7 +93,7 @@ public with sharing class ServiceService { Boolean bsdtFilterIsActive = isBsdtActiveFilterActive(); if (bsdtFilterIsActive) { - activeServiceStatuses = getActiveStatuses(); + activeServiceStatuses = activeStatuses; activeProgramEngagementStages = engagementService.getActiveStages(); } From d7ec4ef21644cafe4c45c631a9db6013636e4413 Mon Sep 17 00:00:00 2001 From: Monica Ramachandran Date: Tue, 14 Mar 2023 10:57:41 -0400 Subject: [PATCH 11/15] updated q3 bsdt tests --- robot/pmm/resources/pmm.py | 2 + .../Attendance/update_attendance.robot | 6 +- .../group_service_delivery.robot | 59 +++++++++---------- .../individual_service_delivery.robot | 22 ++++++- .../service_schedule_filter.robot | 2 +- .../service_schedule_screen3.robot | 6 +- 6 files changed, 57 insertions(+), 40 deletions(-) diff --git a/robot/pmm/resources/pmm.py b/robot/pmm/resources/pmm.py index df26bcf53..b00f991a5 100644 --- a/robot/pmm/resources/pmm.py +++ b/robot/pmm/resources/pmm.py @@ -348,6 +348,7 @@ def click_dialog_button(self, label): self.selenium.wait_until_element_is_enabled( locator, error="Button is not enabled" ) + self.scroll_element_into_view(locator) self.selenium.set_focus_to_element(locator) element = self.selenium.driver.find_element_by_xpath(locator) self.selenium.driver.execute_script("arguments[0].click()", element) @@ -527,6 +528,7 @@ def manage_records_bucketed_value(self): def click_custom_metadata_button(self, button): """Clicks on a button within the custom metadata iFrame""" + time.sleep(3) if button == "New": locator = pmm_lex_locators["custom_metadata_button"].format(button) self.select_frame_with_value( diff --git a/robot/pmm/tests/browser/Attendance/update_attendance.robot b/robot/pmm/tests/browser/Attendance/update_attendance.robot index 75fe0a6ce..626798cd7 100644 --- a/robot/pmm/tests/browser/Attendance/update_attendance.robot +++ b/robot/pmm/tests/browser/Attendance/update_attendance.robot @@ -48,7 +48,7 @@ Setup Test Data UA1: Update attendance when service session status is Pending [Documentation] This test updates attendance for a service session record with Pending Status [tags] W-8607484 perm:admin perm:manage feature:Attendance - Go To Page Details ServiceSession__c object_id=${service_session1}[Id] + Go To Page Details ServiceSession__c quadrant:Q2 object_id=${service_session1}[Id] Populate Attendance Field ${contact1}[Name] Hours 10 Populate Attendance Dropdown ${contact1}[Name] Attendance Status Present Populate Attendance Field ${contact2}[Name] Hours 10 @@ -66,7 +66,7 @@ UA1: Update attendance when service session status is Pending UA2: Update attendance when service session status is Complete [Documentation] This test updates attendance for a service session record with Complete Status - [tags] W-8611541 perm:admin perm:manage feature:Attendance + [tags] W-8611541 perm:admin perm:manage quadrant:Q2 feature:Attendance Go To Page Details ServiceSession__c object_id=${service_session2}[Id] Click Dialog Button Update Page Should Contain Track Attendance @@ -84,7 +84,7 @@ UA2: Update attendance when service session status is Complete UA3: Validate fields added to AttendanceServiceDeliveries Fieldset [Documentation] This test updates attendance for a service session record with Complete Status - [tags] W-9505038 quadrant:Q2 perm:admin feature:Attendance + [tags] W-9505038 quadrant:Q2 perm:admin quadrant:Q3 feature:Attendance Run task add_fields_to_field_set ... field_set=${ns}ServiceDelivery__c.${ns}Attendance_Service_Deliveries ... fields=${{ ["${ns}Service_Provider__c"] }} diff --git a/robot/pmm/tests/browser/Bulk_Service_Delivery/group_service_delivery.robot b/robot/pmm/tests/browser/Bulk_Service_Delivery/group_service_delivery.robot index 2a01f7283..8fa618554 100644 --- a/robot/pmm/tests/browser/Bulk_Service_Delivery/group_service_delivery.robot +++ b/robot/pmm/tests/browser/Bulk_Service_Delivery/group_service_delivery.robot @@ -70,6 +70,33 @@ Setup Test Data API Update Records ${ns}ProgramEngagement__c ${program_engagement4}[Id] ${ns}Stage__c=Applied *** Test Cases *** +Setup custom bucketed values and validate on participant selector component + [Documentation] Create custom bucketed values for Program Cohort Status and Program Engagement Stages and + ... validate the same on the participant selector component on BSDT + [tags] quadrant:Q3 perm:admin + Setup Custom Metadata Bucketed Value Completed Completed ProgramCohortStatusActive Completed + Setup Custom Metadata Bucketed Value Applied Applied Active Applied + Go To Page Custom Bulk_Service_Deliveries + Click Dialog Button Create by Group + Page Should Contain Text Default Service Delivery Values + Populate Lookup Field Service ${service1}[Name] + Page Should Contain ${service1}[${ns}UnitOfMeasurement__c] + Populate Field Quantity ${quantity} + Click Dialog Button Next + Page Should Contain Text Contact Selection + Load Page Object New ServiceSchedule__c + Page Should Contain Applied + Verify dropdown Options Filter by: Program Cohort contains ${program_cohort1}[Name] + sleep 3s + Verify dropdown Options Filter by: Program Cohort does not contain ${program_cohort2}[Name] + sleep 3s + Verify dropdown Options Filter by: Program Cohort does not contain ${program_cohort3}[Name] + sleep 3s + Select Service Participant ${contact1}[Name] + Validate Participant Is Added ${contact1}[Name] + Click Dialog Button Next + Page Should Contain Delivery Date + GSD1: Create service delivery using BSDT Wizard [Documentation] Clicks on Create by Group on BSDT, selects default service delivery values, adds contact ... and creates service delivery using wizard @@ -97,13 +124,11 @@ GSD1: Create service delivery using BSDT Wizard Verify Details Service Delivery Name contains ${contact1}[FirstName] ${contact1}[LastName] ${today}: ${service}[Name] Verify Details Quantity contains ${quantity}.00 Verify Details Unit of Measurement contains ${service}[${ns}UnitOfMeasurement__c] - Save Current Record ID For Deletion ${ns}ServiceDelivery__c Go To Page Listing ${ns}ServiceDelivery__c Click Listview Link ${contact2}[FirstName] ${contact2}[LastName] ${today}: ${service}[Name] Verify Details Service Delivery Name contains ${contact2}[FirstName] ${contact2}[LastName] ${today}: ${service}[Name] Verify Details Quantity contains ${quantity}.00 Verify Details Unit of Measurement contains ${service}[${ns}UnitOfMeasurement__c] - Save Current Record ID For Deletion ${ns}ServiceDelivery__c GSD2: Filter on bsdt wizard based on Program Cohort [Documentation] On BSDT wizard contact selection screen,filter based on program cohort and @@ -119,7 +144,7 @@ GSD2: Filter on bsdt wizard based on Program Cohort Page Should Contain Text Contact Selection Load Page Object New ServiceSchedule__c Page Should Contain No records selected - Select Value From Dropdown Filter by Program Cohort ${program_cohort2}[Name] + Select Value From Dropdown Filter by: Program Cohort ${program_cohort2}[Name] Page Should Not Contain ${contact1}[Name] Page Should Not Contain ${contact2}[Name] Page Should Contain Text ${contact3}[Name] @@ -159,31 +184,3 @@ GSD4: Filter on bsdt wizard based on Stage Page Should Contain No records selected Filter Participants Applied Page Should Contain No records found. - -Setup custom bucketed values and validate on participant selector component - [Documentation] Create custom bucketed values for Program Cohort Status and Program Engagement Stages and - ... validate the same on the participant selector component on BSDT - [tags] quadrant:Q3 perm:admin - Setup Custom Metadata Bucketed Value Completed Completed ProgramCohortStatusActive Completed - Setup Custom Metadata Bucketed Value Applied Applied Active Applied - Go To Page Custom Bulk_Service_Deliveries - Click Dialog Button Create by Group - Page Should Contain Text Default Service Delivery Values - Populate Lookup Field Service ${service1}[Name] - Page Should Contain ${service1}[${ns}UnitOfMeasurement__c] - Populate Field Quantity ${quantity} - Click Dialog Button Next - Page Should Contain Text Contact Selection - Load Page Object New ServiceSchedule__c - Page Should Contain Applied - Verify dropdown Options Filter by Program Cohort contains ${program_cohort1}[Name] - sleep 3s - Verify dropdown Options Filter by Program Cohort does not contain ${program_cohort2}[Name] - sleep 3s - Verify dropdown Options Filter by Program Cohort does not contain ${program_cohort3}[Name] - sleep 3s - Select Service Participant ${contact1}[Name] - Validate Participant Is Added ${contact1}[Name] - Click Dialog Button Next - Page Should Contain Delivery Date - diff --git a/robot/pmm/tests/browser/Bulk_Service_Delivery/individual_service_delivery.robot b/robot/pmm/tests/browser/Bulk_Service_Delivery/individual_service_delivery.robot index 8190550d4..be5898e55 100644 --- a/robot/pmm/tests/browser/Bulk_Service_Delivery/individual_service_delivery.robot +++ b/robot/pmm/tests/browser/Bulk_Service_Delivery/individual_service_delivery.robot @@ -35,6 +35,17 @@ Setup Test Data ${service1} = API Create Service ${Program1}[Id] Set suite variable ${service1} + ${contact4} = API Create Contact + Set suite variable ${contact4} + ${program4} = API Create Program + Set suite variable ${program4} + ${service4} = API Create Service ${Program4}[Id] + Set suite variable ${service4} + API Update Records ${ns}Service__c ${service4}[Id] ${ns}Status__c=Canceled + ${program_engagement4} = API Create Program Engagement ${Program4}[Id] ${contact4}[Id] + Set suite variable ${program_engagement4} + API Update Records ${ns}ProgramEngagement__c ${program_engagement4}[Id] ${ns}Stage__c=Withdrawn + ${contact2} = API Create Contact Set suite variable ${contact2} ${program2} = API Create Program @@ -57,7 +68,9 @@ ISD1: Add service delivery on bulk service delivery [Documentation] This test adds two service deliveries on bulk service delivery and ... navigates to service delivery listview and verifies that the service delivery ... records are displayed - [tags] W-040316 quadrant:Q2 perm:admin perm:manage perm:deliver feature:Service Delivery + [tags] W-040316 quadrant:Q3 perm:admin perm:manage perm:deliver feature:Service Delivery + Setup Custom Metadata Bucketed Value Canceled Service Canceled_Service ServiceStatusActive Canceled + Setup Custom Metadata Bucketed Value PE:Withdrawn PE_Withrawn Active Withdrawn Go To Page Custom Bulk_Service_Deliveries Click Dialog Button Create by Individual Populate Bsdt Lookup 1 Client ${contact1}[FirstName] ${contact1}[LastName] @@ -69,15 +82,20 @@ ISD1: Add service delivery on bulk service delivery Populate Bsdt Dropdown 2 Program Engagement ${program_engagement2}[Name] Populate Bsdt Dropdown 2 Service ${service2}[Name] Populate Bsdt Field 2 Quantity ${quantity2} + Click Bsdt Button Add Entry + Populate Bsdt Lookup 3 Client ${contact4}[FirstName] ${contact4}[LastName] + Populate Bsdt Dropdown 3 Program Engagement ${program_engagement4}[Name] + Populate Bsdt Dropdown 3 Service ${service4}[Name] + Populate Bsdt Field 3 Quantity ${quantity2} Click Bsdt Button Save Verify Persist Save Icon 1 Saved Verify Persist Save Icon 2 Saved + Verify Persist Save Icon 3 Saved Go To Page Listing ${ns}ServiceDelivery__c Page Should Contain ${contact1}[FirstName] ${contact1}[LastName] ${today}: ${service1}[Name] Page Should Contain ${contact2}[FirstName] ${contact2}[LastName] ${today}: ${service2}[Name] Click Listview Link ${contact1}[FirstName] ${contact1}[LastName] ${today}: ${service1}[Name] Verify Details Service Delivery Name contains ${contact1}[FirstName] ${contact1}[LastName] ${today}: ${service1}[Name] - Save Current Record ID For Deletion ${ns}ServiceDelivery__c ISD2: Verify error message when there are no services associated with the program [Documentation] This test verifies that an error message is displayed when there are no diff --git a/robot/pmm/tests/browser/ServiceSchedule/service_schedule_filter.robot b/robot/pmm/tests/browser/ServiceSchedule/service_schedule_filter.robot index 77bace0d0..3382c7605 100644 --- a/robot/pmm/tests/browser/ServiceSchedule/service_schedule_filter.robot +++ b/robot/pmm/tests/browser/ServiceSchedule/service_schedule_filter.robot @@ -59,7 +59,7 @@ SSF1: Filter based on Program Cohort Verify Wizard Screen Title Add Service Participants Page Should Contain ${service_schedule_name} Page Should Contain No records selected - Select Value From Dropdown Filter by Program Cohort ${program_cohort2}[Name] + Select Value From Dropdown Filter by: Program Cohort ${program_cohort2}[Name] Page Should Not Contain ${contact1}[Name] Page Should Not Contain ${contact2}[Name] Page Should Contain Text ${contact3}[Name] diff --git a/robot/pmm/tests/browser/ServiceSchedule/service_schedule_screen3.robot b/robot/pmm/tests/browser/ServiceSchedule/service_schedule_screen3.robot index b8b9f01b9..60ec8a330 100644 --- a/robot/pmm/tests/browser/ServiceSchedule/service_schedule_screen3.robot +++ b/robot/pmm/tests/browser/ServiceSchedule/service_schedule_screen3.robot @@ -150,9 +150,9 @@ Setup custom bucketed values and validate on service schedule wizard Click Dialog Button Next Verify Wizard Screen Title Add Service Participants Page Should Contain Waitlisted - Verify dropdown Options Filter by Program Cohort contains ${program_cohort1}[Name] - Verify dropdown Options Filter by Program Cohort does not contain ${program_cohort2}[Name] - Verify dropdown Options Filter by Program Cohort does not contain ${program_cohort3}[Name] + Verify dropdown Options Filter by: Program Cohort contains ${program_cohort1}[Name] + Verify dropdown Options Filter by: Program Cohort does not contain ${program_cohort2}[Name] + Verify dropdown Options Filter by: Program Cohort does not contain ${program_cohort3}[Name] Select Service Participant ${contact1}[Name] Validate Participant Is Added ${contact1}[Name] Click Dialog Button Next From 6ec9f11eb6bbb0790371470af7088440e44bde14 Mon Sep 17 00:00:00 2001 From: jennifer-bennett Date: Mon, 14 Aug 2023 13:40:41 -0500 Subject: [PATCH 12/15] Add .sf to gitignore and create feature branch. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 75a96fbfc..577fc12bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Salesforce / SFDX / CCI .cci .sfdx +.sf /src.orig /src From e5d0372eaac789e8840ff9431777ceb2127dad9c Mon Sep 17 00:00:00 2001 From: Tarren Anderson Date: Wed, 20 Sep 2023 10:14:15 -0500 Subject: [PATCH 13/15] WIP Debounce --- .../lwc/bulkServiceDeliveryUI/bulkServiceDeliveryUI.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/force-app/main/default/lwc/bulkServiceDeliveryUI/bulkServiceDeliveryUI.js b/force-app/main/default/lwc/bulkServiceDeliveryUI/bulkServiceDeliveryUI.js index c77cd8be4..f87abb54a 100644 --- a/force-app/main/default/lwc/bulkServiceDeliveryUI/bulkServiceDeliveryUI.js +++ b/force-app/main/default/lwc/bulkServiceDeliveryUI/bulkServiceDeliveryUI.js @@ -180,6 +180,10 @@ export default class BulkServiceDeliveryUI extends NavigationMixin(LightningElem return "error"; } + get isSaveDisabled() { + return this.isSaving; + } + addDelivery() { let serviceDelivery = { index: this._nextIndex, @@ -230,6 +234,7 @@ export default class BulkServiceDeliveryUI extends NavigationMixin(LightningElem handleSave() { let rows = this.template.querySelectorAll("c-service-delivery-row"); + this.isSaving = true; this.savedCount = 0; this.errorCount = 0; this.targetSaveCount = 0; @@ -247,6 +252,7 @@ export default class BulkServiceDeliveryUI extends NavigationMixin(LightningElem if (this.targetSaveCount === 0) { this.dispatchEvent(new CustomEvent("done")); + this.isSaving = false; } } @@ -260,6 +266,7 @@ export default class BulkServiceDeliveryUI extends NavigationMixin(LightningElem if (this.savedCount === this.targetSaveCount) { this.dispatchEvent(new CustomEvent("done")); + this.isSaving = false; } } From ab2756ebf379bfca27d4c310a87bd47b6ca2ada2 Mon Sep 17 00:00:00 2001 From: Tarren Anderson Date: Thu, 28 Sep 2023 14:42:21 -0500 Subject: [PATCH 14/15] Adjust Save Checks --- .../lwc/bulkServiceDeliveryUI/bulkServiceDeliveryUI.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/force-app/main/default/lwc/bulkServiceDeliveryUI/bulkServiceDeliveryUI.js b/force-app/main/default/lwc/bulkServiceDeliveryUI/bulkServiceDeliveryUI.js index f87abb54a..191efe86a 100644 --- a/force-app/main/default/lwc/bulkServiceDeliveryUI/bulkServiceDeliveryUI.js +++ b/force-app/main/default/lwc/bulkServiceDeliveryUI/bulkServiceDeliveryUI.js @@ -225,16 +225,15 @@ export default class BulkServiceDeliveryUI extends NavigationMixin(LightningElem // eslint-disable-next-line no-unused-vars handleRowError(event) { this.errorCount++; - if (this.savingComplete()) { this.showSaveSummaryToast(); + this.isSaving = false; } } handleSave() { let rows = this.template.querySelectorAll("c-service-delivery-row"); - this.isSaving = true; this.savedCount = 0; this.errorCount = 0; this.targetSaveCount = 0; @@ -246,13 +245,13 @@ export default class BulkServiceDeliveryUI extends NavigationMixin(LightningElem } if (row.isDirty) { this.currentSaveCount++; + this.isSaving = true; } row.saveRow(); }); if (this.targetSaveCount === 0) { this.dispatchEvent(new CustomEvent("done")); - this.isSaving = false; } } @@ -262,11 +261,11 @@ export default class BulkServiceDeliveryUI extends NavigationMixin(LightningElem if (this.savingComplete()) { this.showSaveSummaryToast(); + this.isSaving = false; } if (this.savedCount === this.targetSaveCount) { this.dispatchEvent(new CustomEvent("done")); - this.isSaving = false; } } From eba61695629c6f5c0f4cdba09e7be59166f16aa7 Mon Sep 17 00:00:00 2001 From: Tarren Anderson Date: Tue, 7 Nov 2023 09:55:59 -0600 Subject: [PATCH 15/15] Limit close event to non-navigation clause --- .../lwc/serviceScheduleCreator/serviceScheduleCreator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/force-app/main/default/lwc/serviceScheduleCreator/serviceScheduleCreator.js b/force-app/main/default/lwc/serviceScheduleCreator/serviceScheduleCreator.js index dd7eba3ac..7297d8a68 100644 --- a/force-app/main/default/lwc/serviceScheduleCreator/serviceScheduleCreator.js +++ b/force-app/main/default/lwc/serviceScheduleCreator/serviceScheduleCreator.js @@ -354,8 +354,8 @@ export default class ServiceScheduleCreator extends NavigationMixin(LightningEle this.navigate(); } else { this.init(); + this.dispatchEvent(new CustomEvent("close", { bubbles: true })); } - this.dispatchEvent(new CustomEvent("close", { bubbles: true })); } reset() {