From 07116cf107dec97989e510826b797c58727d6b80 Mon Sep 17 00:00:00 2001 From: Piotr Gajek Date: Wed, 28 Jun 2023 18:03:43 +0200 Subject: [PATCH] includes and excludes (#49) * includes and excludes * refactoring * enable acr in scratch * added scratch org support for ACR and person accounts --------- Co-authored-by: Maciej Ptak <0ptaq0@gmail.com> --- config/project-scratch-def.json | 9 ++- force-app/main/default/classes/SOQL.cls | 28 +++++++++ force-app/main/default/classes/SOQL_Test.cls | 60 +++++++++++++++++++ website/docs/api/soql-filter.md | 62 ++++++++++++++++++++ 4 files changed, 158 insertions(+), 1 deletion(-) diff --git a/config/project-scratch-def.json b/config/project-scratch-def.json index 7df17d34..b809d5e8 100644 --- a/config/project-scratch-def.json +++ b/config/project-scratch-def.json @@ -1,13 +1,20 @@ { "orgName": "Beyond The Cloud Dev", "edition": "Developer", - "features": ["EnableSetPasswordInApi"], + "features": [ + "EnableSetPasswordInApi", + "ContactsToMultipleAccounts", + "PersonAccounts" + ], "settings": { "lightningExperienceSettings": { "enableS1DesktopEnabled": true }, "mobileSettings": { "enableS1EncryptedStoragePref2": false + }, + "accountSettings": { + "enableRelateContactToMultipleAccounts": true } } } diff --git a/force-app/main/default/classes/SOQL.cls b/force-app/main/default/classes/SOQL.cls index ede4dffa..e61dcc34 100644 --- a/force-app/main/default/classes/SOQL.cls +++ b/force-app/main/default/classes/SOQL.cls @@ -190,6 +190,10 @@ public inherited sharing class SOQL implements Queryable { Filter notIn(Iterable iterable); // NOT IN :inList or inSet Filter notIn(List inList); // NOT IN :inList Filter notIn(InnerJoin joinQuery); // SOQL.InnerJoin + Filter includesAll(Iterable values); // join with ; + Filter includesSome(Iterable values); // join with , + Filter excludesAll(Iterable values); // join with , + Filter excludesSome(Iterable values); // join with ; Filter removeWhenNull(); // Condition will be removed for value = null @@ -1114,6 +1118,30 @@ public inherited sharing class SOQL implements Queryable { return set('NOT IN', joinQuery); } + public Filter includesAll(Iterable iterable) { + //Bind expressions can't be used with other clauses, such as INCLUDES. + skipBinding = true; + return set('INCLUDES', '(\'' + String.join(iterable, ';') + '\')'); + } + + public Filter includesSome(Iterable iterable) { + //Bind expressions can't be used with other clauses, such as INCLUDES. + skipBinding = true; + return set('INCLUDES', '(\'' + String.join(iterable, '\', \'') + '\')'); + } + + public Filter excludesAll(Iterable iterable) { + //Bind expressions can't be used with other clauses, such as EXCLUDES. + skipBinding = true; + return set('EXCLUDES', '(\'' + String.join(iterable, '\', \'') + '\')'); + } + + public Filter excludesSome(Iterable iterable) { + //Bind expressions can't be used with other clauses, such as EXCLUDES. + skipBinding = true; + return set('EXCLUDES', '(\'' + String.join(iterable, ';') + '\')'); + } + private Filter set(String comperator, Object value) { this.value = value; this.comperator = comperator; diff --git a/force-app/main/default/classes/SOQL_Test.cls b/force-app/main/default/classes/SOQL_Test.cls index 0e4f5f16..9b58ec69 100644 --- a/force-app/main/default/classes/SOQL_Test.cls +++ b/force-app/main/default/classes/SOQL_Test.cls @@ -783,6 +783,66 @@ private class SOQL_Test { Assert.areEqual(names, binding.get('v1')); } + @IsTest + static void inlcudesAll() { + // Setup + List roles = new List{ 'Business User', 'Decision Maker' }; + + // Test + SOQL builder = SOQL.of(AccountContactRelation.SObjectType) + .with(AccountContactRelation.Id) + .whereAre(SOQL.Filter.with(AccountContactRelation.Roles).includesAll(roles)); + + // Verify + String soql = builder.toString(); + Assert.areEqual('SELECT Id FROM AccountContactRelation WHERE Roles INCLUDES (\'Business User;Decision Maker\')', soql); + } + + @IsTest + static void inlcudesSome() { + // Setup + List roles = new List{ 'Executive Sponsor', 'Economic Decision Maker' }; + + // Test + SOQL builder = SOQL.of(AccountContactRelation.SObjectType) + .with(AccountContactRelation.Id) + .whereAre(SOQL.Filter.with(AccountContactRelation.Roles).includesSome(roles)); + + // Verify + String soql = builder.toString(); + Assert.areEqual('SELECT Id FROM AccountContactRelation WHERE Roles INCLUDES (\'Executive Sponsor\', \'Economic Decision Maker\')', soql); + } + + @IsTest + static void excludesAll() { + // Setup + List roles = new List{ 'Technical Buyer', 'Economic Buyer' }; + + // Test + SOQL builder = SOQL.of(AccountContactRelation.SObjectType) + .with(AccountContactRelation.Id) + .whereAre(SOQL.Filter.with(AccountContactRelation.Roles).excludesAll(roles)); + + // Verify + String soql = builder.toString(); + Assert.areEqual('SELECT Id FROM AccountContactRelation WHERE Roles EXCLUDES (\'Technical Buyer\', \'Economic Buyer\')', soql); + } + + @IsTest + static void excludesSome() { + // Setup + List roles = new List{ 'Evaluator', 'Influencer' }; + + // Test + SOQL builder = SOQL.of(AccountContactRelation.SObjectType) + .with(AccountContactRelation.Id) + .whereAre(SOQL.Filter.with(AccountContactRelation.Roles).excludesSome(roles)); + + // Verify + String soql = builder.toString(); + Assert.areEqual('SELECT Id FROM AccountContactRelation WHERE Roles EXCLUDES (\'Evaluator;Influencer\')', soql); + } + @IsTest static void isNull() { // Test diff --git a/website/docs/api/soql-filter.md b/website/docs/api/soql-filter.md index 00047f38..4f32c5fd 100644 --- a/website/docs/api/soql-filter.md +++ b/website/docs/api/soql-filter.md @@ -587,6 +587,68 @@ SOQL.of(Contact.SObjectType) )).toList(); ``` +## multi-select picklist + +### includesAll + +```sql +SELECT Id +FROM AccountContactRelation +WHERE Roles INCLUDES ('Business User;Decision Maker') +``` +```apex +List roles = new List{ 'Business User', 'Decision Maker' }; + +SOQL builder = SOQL.of(AccountContactRelation.SObjectType) + .with(AccountContactRelation.Id) + .whereAre(SOQL.Filter.with(AccountContactRelation.Roles).includesAll(roles)); + ``` + +### includesSome + +```sql +SELECT Id +FROM AccountContactRelation +WHERE Roles INCLUDES ('Business User', 'Decision Maker') +``` +```apex +List roles = new List{ 'Business User', 'Decision Maker' }; + +SOQL builder = SOQL.of(AccountContactRelation.SObjectType) + .with(AccountContactRelation.Id) + .whereAre(SOQL.Filter.with(AccountContactRelation.Roles).includesSome(roles)); + ``` + +### excludesAll + +```sql +SELECT Id +FROM AccountContactRelation +WHERE Roles EXCLUDES ('Business User', 'Decision Maker') +``` +```apex +List roles = new List{ 'Business User', 'Decision Maker' }; + +SOQL builder = SOQL.of(AccountContactRelation.SObjectType) + .with(AccountContactRelation.Id) + .whereAre(SOQL.Filter.with(AccountContactRelation.Roles).excludesAll(roles)); + ``` + +### excludesSome + +```sql +SELECT Id +FROM AccountContactRelation +WHERE Roles EXCLUDES ('Business User;Decision Maker') +``` +```apex +List roles = new List{ 'Business User', 'Decision Maker' }; + +SOQL builder = SOQL.of(AccountContactRelation.SObjectType) + .with(AccountContactRelation.Id) + .whereAre(SOQL.Filter.with(AccountContactRelation.Roles).excludesSome(roles)); + ``` + ## additional ### removeWhenNull