From e9d07135dc2d0299c0db97fde848b936ea8fbdcd Mon Sep 17 00:00:00 2001 From: Eugenijus Date: Fri, 7 Feb 2025 09:31:31 +0100 Subject: [PATCH 01/14] update dependency Domain and Subdomain fields for ServiceResource --- sfdx-project.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sfdx-project.json b/sfdx-project.json index d3a3d707..3d237ac5 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -9,7 +9,7 @@ "dependencies": [ { "package": "crm-platform-base", - "versionNumber": "0.226.0.LATEST" + "versionNumber": "0.240.0.LATEST" }, { "package": "crm-platform-reporting", @@ -114,4 +114,4 @@ "crm-thread-view": "0Ho7U000000000zSAA", "crm-nks-integration": "0Ho2o000000fxX6CAI" } -} +} \ No newline at end of file From d760dd780f90f566be7778044bc6cf2c301fb8f9 Mon Sep 17 00:00:00 2001 From: Eugenijus Date: Fri, 7 Feb 2025 09:32:26 +0100 Subject: [PATCH 02/14] update include LiveMessage --- config/project-scratch-def.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/config/project-scratch-def.json b/config/project-scratch-def.json index 4c14bae6..fa9f2331 100644 --- a/config/project-scratch-def.json +++ b/config/project-scratch-def.json @@ -22,7 +22,8 @@ "FieldService:5", "FieldServiceDispatcherUser:5", "FieldServiceMobileUser:5", - "FieldServiceSchedulingUser:5" + "FieldServiceSchedulingUser:5", + "LiveMessage" ], "country": "NO", "language": "en_US", @@ -62,6 +63,9 @@ "workOrderLineItemSearchFields": "Subject", "workOrderSearchFields": "Subject" }, + "liveMessageSettings": { + "enableLiveMessage": true + }, "liveAgentSettings": { "enableLiveAgent": true }, @@ -74,4 +78,4 @@ "enableOmniSecondaryRoutingPriority": true } } -} +} \ No newline at end of file From 1debc34c138d07fc8f3566337865cdebb55817bf Mon Sep 17 00:00:00 2001 From: Eugenijus Date: Fri, 7 Feb 2025 09:34:32 +0100 Subject: [PATCH 03/14] remove annoying ruleset --- .vscode/settings.json | 1 - ruleset.xml | 292 ------------------------------------------ 2 files changed, 293 deletions(-) delete mode 100644 ruleset.xml diff --git a/.vscode/settings.json b/.vscode/settings.json index 52707b26..a12ade59 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,7 +12,6 @@ "editor.detectIndentation": false, "git.autofetch": true, "eslint.nodePath": "./node_modules", - "apexPMD.rulesets": ["ruleset.xml"], "editor.defaultFormatter": "esbenp.prettier-vscode", "[xml]": { "editor.defaultFormatter": "redhat.vscode-xml" diff --git a/ruleset.xml b/ruleset.xml deleted file mode 100644 index 29d468a0..00000000 --- a/ruleset.xml +++ /dev/null @@ -1,292 +0,0 @@ - - - Default ruleset used by the Code Climate Engine for Salesforce.com Apex - .*/.sfdx/.* - - - 3 - - - - - - 3 - - - - - - - 3 - - - - - - 3 - - - - - - 3 - - - - - - 3 - - - - - - 3 - - - - - - 3 - - - - - - 3 - - - - - - 3 - - - - - - 3 - - - - 3 - - - - 3 - - - - 3 - - - - 3 - - - - 3 - - - - - - - 3 - - - - - - 3 - - - - 3 - - - - 3 - - - - 3 - - - - - - 4 - - - 4 - - - 3 - - - - 3 - - - - - - 3 - - - - 3 - - - - 3 - - - - 3 - - - - 3 - - - - 3 - - - - 3 - - - - 3 - - - - - 3 - - - - 3 - - - - - - 3 - - - - 3 - - - - 3 - - - - 3 - - - - - - 3 - - - - 3 - - - - 3 - - - - 3 - - - - 3 - - - - - - 3 - - - - - - 3 - - - - 3 - - From b376dd76743fb44bc7eb92480cdee489e1e87596 Mon Sep 17 00:00:00 2001 From: Eugenijus Date: Fri, 7 Feb 2025 13:00:03 +0100 Subject: [PATCH 04/14] update to handle custom domain permsetGroup and publicGroups Callout interface --- .../classes/STO_GroupMemberSkillService.cls | 284 ++++++++++++------ 1 file changed, 186 insertions(+), 98 deletions(-) diff --git a/force-app/main/default/classes/STO_GroupMemberSkillService.cls b/force-app/main/default/classes/STO_GroupMemberSkillService.cls index 78c96707..6abde4c6 100644 --- a/force-app/main/default/classes/STO_GroupMemberSkillService.cls +++ b/force-app/main/default/classes/STO_GroupMemberSkillService.cls @@ -1,41 +1,49 @@ -public with sharing class STO_GroupMemberSkillService { +/** + * @description This class is used to sync skills between groups and users + * !IMPORTANT! This class can be called using the Callable interface + * in other packaged wich are not dependent on crm-sto. (f.e. hot-servicetjenesten) + * @updated : 2025-02-07 + */ +public with sharing class STO_GroupMemberSkillService implements Callable { private LoggerUtility logger = new LoggerUtility('AD_SKILL_SYNC'); public static final String FORTOLIG_ADDRESSE_SKILL = 'Fortrolig_addresse'; public static final String SKJERMEDE_PERSONER_SKILL = 'Skjermede_personer'; public static final String FORTROLIG_GROUP_NAME = 'Fortrolig_Adresse_AD'; public static final String SKJERMEDE_GROUP_NAME = 'NKS_Skjermede_Personer_AD'; - private Set groupNamesToSync = new Set{ FORTROLIG_GROUP_NAME, SKJERMEDE_GROUP_NAME }; - - private final Map groupSkillMap = new Map{ - 'Fortrolig_Adresse_AD' => FORTOLIG_ADDRESSE_SKILL, - 'NKS_Skjermede_Personer_AD' => SKJERMEDE_PERSONER_SKILL - }; + public static final String PERMSET_GROUP_NAME = 'Kontaktsenter'; + public static final String SR_DOMAIN = 'NKS'; + private String fortroligGroupName = FORTROLIG_GROUP_NAME; + private String skjermedeGroupName = SKJERMEDE_GROUP_NAME; + private String permsetGroupName = PERMSET_GROUP_NAME; + private String srDomain = SR_DOMAIN; + private String srSubDomain; + private Set groupNamesToSync = new Set{ fortroligGroupName, skjermedeGroupName }; + private Set fortroligMembers = new Set(); + private Set skjermedeMembers = new Set(); + private Set fortroligSkillUsers = new Set(); + private Set skjermedeSkillUsers = new Set(); - @testVisible - private static Map nksUserMap { + @TestVisible + private Map userMap { get { - if (nksUserMap == null) { - nksUserMap = new Map(); - for (User usr : [ - SELECT Id, Name - FROM User - WHERE - Id IN ( - SELECT AssigneeId - FROM PermissionSetAssignment - WHERE PermissionSetGroup.DeveloperName = 'Kontaktsenter' - ) + if (userMap == null) { + List userList = new List(); + for (PermissionSetAssignment psa : [ + SELECT Assignee.Id, Assignee.Name, PermissionSetGroup.DeveloperName + FROM PermissionSetAssignment + WHERE PermissionSetGroup.DeveloperName = :this.permsetGroupName ]) { - nksUserMap.put(usr.Id, usr); + userList.add(psa.Assignee); } + userMap = new Map(userList); } - return nksUserMap; + return userMap; } private set { + userMap = value; } } - - @testVisible + @TestVisible private Map skillIdMap { get { if (skillIdMap == null) { @@ -50,117 +58,149 @@ public with sharing class STO_GroupMemberSkillService { } return skillIdMap; } - private set { - } + private set; } - - private Set fortroligMembers = new Set(); - private Set skjermedeMembers = new Set(); - private Set fortroligSkillUsers = new Set(); - private Set skjermedeSkillUsers = new Set(); - + /** + * @description default constructor for the class + */ + @SuppressWarnings('PMD.EmptyStatementBlock') public STO_GroupMemberSkillService() { - getGroupMembers(); - initSkillUserSets(); + } + /** + * @description Only for test purpouses + * @param domain + * @param subDomain + * @param permSetGroup + * @param fortroligGroup + * @param skjermedeGroup + */ + @TestVisible + @SuppressWarnings('PMD.ExcessiveParameterList') + private STO_GroupMemberSkillService( + String domain, + String subDomain, + String permSetGroup, + String fortroligGroup, + String skjermedeGroup + ) { + this.srDomain = domain; + this.srSubDomain = subDomain; + this.permsetGroupName = permSetGroup; + this.fortroligGroupName = fortroligGroup; + this.skjermedeGroupName = skjermedeGroup; } /** - * @description: Initalizes the set og userIds who are member of the fortrolig and skjermet + * @description Initalizes the set og userIds who are member of the fortrolig and skjermet * @author Stian Ruud Schikora | 12-16-2021 **/ + @SuppressWarnings('PMD.ApexCRUDViolation') public void getGroupMembers() { for (GroupMember groupMember : [ SELECT UserOrGroupId, Group.DeveloperName FROM GroupMember - WHERE Group.DeveloperName IN :groupNamesToSync AND UserOrGroupId IN :nksUserMap.keySet() + WHERE + Group.DeveloperName IN (:this.fortroligGroupName, :this.skjermedeGroupName) + AND UserOrGroupId IN :this.userMap.keySet() ]) { String userOrGroupId = String.valueOf(GroupMember.UserOrGroupId); - if (groupMember.Group.DeveloperName == FORTROLIG_GROUP_NAME) { - fortroligMembers.add(groupMember.UserOrGroupId); + if (groupMember.Group.DeveloperName == this.fortroligGroupName) { + this.fortroligMembers.add(groupMember.UserOrGroupId); } else { - skjermedeMembers.add(groupMember.UserOrGroupId); + this.skjermedeMembers.add(groupMember.UserOrGroupId); } } } /** - * @description: Initializes the set og userIds having the fortrolig and skjermet skill + * @description Initializes the set og userIds having the fortrolig and skjermet skill * @author Stian Ruud Schikora | 12-16-2021 **/ + @SuppressWarnings('PMD.ApexCRUDViolation') private void initSkillUserSets() { for (ServiceResourceSkill servSkill : [ SELECT Id, ServiceResourceId, Skill.DeveloperName FROM ServiceResourceSkill - WHERE Skill.DeveloperName = :FORTOLIG_ADDRESSE_SKILL OR Skill.DeveloperName = :SKJERMEDE_PERSONER_SKILL + WHERE + (Skill.DeveloperName = :FORTOLIG_ADDRESSE_SKILL + OR Skill.DeveloperName = :SKJERMEDE_PERSONER_SKILL) + AND ServiceResource.CRM_Domain__c = :this.srDomain ]) { if (servSkill.Skill.DeveloperName == FORTOLIG_ADDRESSE_SKILL) { - fortroligSkillUsers.add(servSkill.ServiceResourceId); + this.fortroligSkillUsers.add(servSkill.ServiceResourceId); } else { - skjermedeSkillUsers.add(servSKill.ServiceResourceId); + this.skjermedeSkillUsers.add(servSKill.ServiceResourceId); } } } - + /** + * @description Handles syncronization of users having a groupmember to the skills they have + */ public void handleGroupAndSkillSync() { + this.getGroupMembers(); + this.initSkillUserSets(); //Ensures all NKS users have a related service resource created - Map userResourceMap = handleServiceResourceCreation(nksUserMap.keySet()); - handleSkillInsert(userResourceMap); - handleSkillDeletion(); + this.handleSkillInsert(); + this.handleSkillDeletion(); } /** - * @description: Inserts new skills for group members who have not yet been assigned the skill. + * @description Inserts new skills for group members who have not yet been assigned the skill. * @author Stian Ruud Schikora | 12-16-2021 - * @param userResourceMap **/ - private void handleSkillInsert(Map userResourceMap) { + private void handleSkillInsert() { + Map userResourceMap = this.handleServiceResourceCreation(); List skillsToCreate = new List(); for (Id memberId : this.fortroligMembers) { //If a userId in the fortrolig group is not contained in the fortroligSkillUser set, we need to ass the skill for that user - if (!fortroligSkillUsers.contains(memberId)) { - skillsToCreate.add(createSkill(skillIdMap.get(FORTOLIG_ADDRESSE_SKILL), userResourceMap.get(memberId))); + if (!this.fortroligSkillUsers.contains(memberId)) { + skillsToCreate.add( + this.createSkill(this.skillIdMap.get(FORTOLIG_ADDRESSE_SKILL), userResourceMap.get(memberId)) + ); } } for (Id memberId : this.skjermedeMembers) { //If a userId in the fortrolig group is not contained in the skjermedeSkillUsers set, we need to ass the skill for that user - if (!skjermedeSkillUsers.contains(memberId)) { + if (!this.skjermedeSkillUsers.contains(memberId)) { skillsToCreate.add( - createSkill(skillIdMap.get(SKJERMEDE_PERSONER_SKILL), userResourceMap.get(memberId)) + this.createSkill(this.skillIdMap.get(SKJERMEDE_PERSONER_SKILL), userResourceMap.get(memberId)) ); } } - if (!skillsToCreate.isEmpty() && !Test.isRunningTest()) { + if (!skillsToCreate.isEmpty() /*&& !Test.isRunningTest()*/) { List saveResList = Database.insert(skillsToCreate, false); verifySkillinsert(saveResList); } } /** - * @description: Deletes the skill for all users who are no longer members og the synced groups + * @description Deletes the skill for all users who are no longer members og the synced groups * @author Stian Ruud Schikora | 12-16-2021 **/ + @SuppressWarnings('PMD.ApexCRUDViolation') private void handleSkillDeletion() { //Get list of skills to be deleted for users who are not longer members of the synced AD groups List skillsToDelete = [ SELECT Id, ServiceResourceId, Skill.DeveloperName FROM ServiceResourceSkill WHERE - (Skill.DeveloperName = :FORTOLIG_ADDRESSE_SKILL + ServiceResource.CRM_Domain__c = :this.srDomain + AND ((Skill.DeveloperName = :FORTOLIG_ADDRESSE_SKILL AND ServiceResource.RelatedRecordId NOT IN :fortroligMembers) OR (Skill.DeveloperName = :SKJERMEDE_PERSONER_SKILL - AND ServiceResource.RelatedRecordId NOT IN :skjermedeMembers) + AND ServiceResource.RelatedRecordId NOT IN :skjermedeMembers)) ]; - if (!skillsToDelete.isEmpty() && !Test.isRunningTest()) { + if (!skillsToDelete.isEmpty() /*&& !Test.isRunningTest()*/) { List deleteResList = Database.delete(skillsToDelete, false); verifySkillRemoval(deleteResList); } } /** - * @description: Constructs a new ServiceResourceSkill record for the defined skill and service resource + * @description Constructs a new ServiceResourceSkill record for the defined skill and service resource * @author Stian Ruud Schikora | 12-16-2021 * @param skillId * @param servRes @@ -175,7 +215,7 @@ public with sharing class STO_GroupMemberSkillService { } /** - * @description: Asserts if there were any skill insert that failed and logs to application log + * @description Asserts if there were any skill insert that failed and logs to application log * If the service resource is assigned the skill already the insert will fail with the DUPLICATE_VALUE status code and thus not treated as an error * @author Stian Ruud Schikora | 12-15-2021 * @param saveResList @@ -183,13 +223,10 @@ public with sharing class STO_GroupMemberSkillService { @testVisible private void verifySkillinsert(List saveResList) { for (Database.SaveResult saveRes : saveResList) { - if (saveRes.isSuccess()) { - //Successfully inserted skill for the resource - } else { + if (!saveRes.isSuccess()) { for (Database.Error err : saveRes.getErrors()) { - if (err.getStatusCode() == StatusCode.DUPLICATE_VALUE) { - //The resource is already assigned this skill - } else { + //Skip already assigned skill + if (!(err.getStatusCode() == StatusCode.DUPLICATE_VALUE)) { logger.error('Failed to create skill', null, CRM_ApplicationDomain.Domain.NKS); } } @@ -199,16 +236,14 @@ public with sharing class STO_GroupMemberSkillService { } /** - * @description: Asserts if there were any deletions that failed and logs to application log + * @description Asserts if there were any deletions that failed and logs to application log * @author Stian Ruud Schikora | 12-15-2021 * @param deleteResList **/ @testVisible private void verifySkillRemoval(List deleteResList) { for (Database.DeleteResult delRes : deleteResList) { - if (delRes.isSuccess()) { - //Successfully inserted skill for the resource - } else { + if (!delRes.isSuccess()) { for (Database.Error err : delRes.getErrors()) { logger.error('Failed to create skill: ' + err.getMessage(), null, CRM_ApplicationDomain.Domain.NKS); } @@ -218,55 +253,108 @@ public with sharing class STO_GroupMemberSkillService { } /** - * @description: Creates service resources for users who do not already have a resource connected to their user + * @description Creates service resources for users who do not already have a resource connected to their user * Returns a map og userId -> ServiceResource * @author Stian Ruud Schikora | 12-15-2021 - * @param userIds * @return Map **/ - private Map handleServiceResourceCreation(Set userIds) { - Map userResourceMap = getServiceResources(userIds); + @SuppressWarnings('PMD.ApexCRUDViolation') + private Map handleServiceResourceCreation() { + Map userResourceMap = this.getServiceResources(); //If the resource map contains less keys than input userIds, we need to create serviceresources - if (userResourceMap.keySet().size() < userIds.size()) { - List resourcesToCreate = new List(); - for (User usr : [SELECT Id, Name FROM User WHERE Id IN :userIds]) { - if (!userResourceMap.containsKey(usr.Id)) { - resourcesToCreate.add( - new ServiceResource( - ResourceType = 'A', - RelatedRecordId = usr.Id, - Name = usr.Name, - IsActive = true - ) - ); - } - } - + Set usersWithoutSR = new Set(this.userMap.keySet()); + usersWithoutSR.removeAll(userResourceMap.keySet()); + List resourcesToCreate = new List(); + for (Id userId : usersWithoutSR) { + User usr = userMap.get(userId); + resourcesToCreate.add( + new ServiceResource( + ResourceType = 'A', + RelatedRecordId = usr.Id, + Name = usr.Name, + IsActive = true, + CRM_Domain__c = this.srDomain + ) + ); + } + if (resourcesToCreate.size() > 0) { insert resourcesToCreate; - //Adding the newly created resources to the return map - for (ServiceResource servRes : resourcesToCreate) { - userResourceMap.put(servRes.RelatedRecordId, servRes); - } + } + for (ServiceResource servRes : resourcesToCreate) { + userResourceMap.put(servRes.RelatedRecordId, servRes); } return userResourceMap; } /** - * @description: Returns a map of userIds to a ServiceResource record + * @description Returns a map of userIds to a ServiceResource record * @author Stian Ruud Schikora | 12-14-2021 * @return Map **/ - private Map getServiceResources(Set userIds) { + @SuppressWarnings('PMD.ApexCRUDViolation') + private Map getServiceResources() { Map userResourceMap = new Map(); for (ServiceResource servRes : [ - SELECT Id, RelatedRecordId + SELECT Id, RelatedRecordId, CRM_Domain__c FROM ServiceResource - WHERE RelatedRecordId IN :userIds AND ResourceType = 'A' + WHERE + RelatedRecordId IN :this.userMap.keySet() + AND CRM_Domain__c = :this.srDomain + AND CRM_SubDomain__c = :this.srSubDomain ]) { userResourceMap.put(servRes.RelatedRecordId, servRes); } return userResourceMap; } + /** + * @description Executes handleGroupAndSkillSync from an external package(hot-servicetjenesten) + * @author Eugenijus Margalikas | 07.02.2025 + * @param action - `String` - Action to execute for now only `handleGroupAndSkillSync` + * @param args - `Map` where + * keys are domain,subdomain,permsetgroup,fortroliggroup,skjermedegroup + * @return Object + */ + public Object call(String action, Map args) { + switch on action.toLowerCase() { + when 'handlegroupandskillsync' { + this.setParams(args).handleGroupAndSkillSync(); + return 0; + } + when else { + throw new STO_SkillServiceMalformedCallException('Action: ' + action + ' is not implemented'); + } + } + } + private STO_GroupMemberSkillService setParams(Map params) { + for (String key : params.keySet()) { + if (params.get(key) == null || !(params.get(key) instanceof String)) { + continue; + } + switch on key.toLowerCase() { + when 'domain' { + this.srDomain = (String) params.get(key); + } + when 'subdomain' { + this.srSubDomain = (String) params.get(key); + } + when 'permsetgroup' { + this.permsetGroupName = (String) params.get(key); + } + when 'fortroliggroup' { + this.fortroligGroupName = (String) params.get(key); + } + when 'skjermedegroup' { + this.skjermedeGroupName = (String) params.get(key); + } + } + } + return this; + } + /** + * @description Custom exception type for handling malformed calls. + */ + public class STO_SkillServiceMalformedCallException extends Exception { + } } From a483d8b3962dc919b6265b83809dbc27039a66de Mon Sep 17 00:00:00 2001 From: Eugenijus Date: Fri, 7 Feb 2025 13:00:38 +0100 Subject: [PATCH 05/14] update test to cover changes --- .../STO_GroupMemberSkillService_Test.cls | 186 ++++++++++++++++-- 1 file changed, 173 insertions(+), 13 deletions(-) diff --git a/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls b/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls index 58d0c1d1..3d52b40e 100644 --- a/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls +++ b/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls @@ -3,38 +3,190 @@ public class STO_GroupMemberSkillService_Test { @TestSetup static void makeData() { Group fortroligGroup = TestDataFactory.getPublicGroup('Fortrolig_Adresse_AD', 'Fortrolig_Adresse_AD'); - Group skjermedeGroup = TestDataFactory.getPublicGroup('NKS_Skjermede_Personer_AD', 'NKS_Skjermede_Personer_AD'); + Group nksSkjermedeGroup = TestDataFactory.getPublicGroup( + 'NKS_Skjermede_Personer_AD', + 'NKS_Skjermede_Personer_AD' + ); + Group skjermedeGroup = TestDataFactory.getPublicGroup('Skjermede_Personer_AD', 'Skjermede_Personer_AD'); //Adds the testuser as a member in both groups - User usr = (User) STO_TestDataFactory.createRecord(new User(FirstName = 'SUPER', LastName = 'SKILLED')); + User usr1 = (User) STO_TestDataFactory.createRecord(new User(FirstName = 'SUPER', LastName = 'SKILLED')); + User usr2 = (User) STO_TestDataFactory.createRecord(new User(FirstName = 'VASILIJ', LastName = 'PUPKIN')); List memberList = new List(); - memberList.add(new GroupMember(GroupId = fortroligGroup.Id, UserOrGroupId = usr.Id)); - memberList.add(new GroupMember(GroupId = skjermedeGroup.Id, UserOrGroupId = usr.Id)); + memberList.add(new GroupMember(GroupId = fortroligGroup.Id, UserOrGroupId = usr1.Id)); + memberList.add(new GroupMember(GroupId = nksSkjermedeGroup.Id, UserOrGroupId = usr1.Id)); + memberList.add(new GroupMember(GroupId = fortroligGroup.Id, UserOrGroupId = usr2.Id)); + memberList.add(new GroupMember(GroupId = skjermedeGroup.Id, UserOrGroupId = usr2.Id)); STO_TestDataFactory.createRecordList(memberList); + PermissionSetGroup kontaktsenterPSG = new PermissionSetGroup( + MasterLabel = 'Kontaktsenter', + DeveloperName = 'Kontaktsenter' + ); + PermissionSetGroup servicetjenestenPSG = new PermissionSetGroup( + MasterLabel = 'Servicetjenesten', + DeveloperName = 'HOT_Servicetjenesten_Group' + ); + insert new List{ kontaktsenterPSG, servicetjenestenPSG }; + PermissionSetAssignment psa1 = new PermissionSetAssignment( + AssigneeId = usr1.ID, + PermissionSetGroupId = kontaktsenterPSG.Id + ); + PermissionSetAssignment psa2 = new PermissionSetAssignment( + AssigneeId = usr2.ID, + PermissionSetGroupId = servicetjenestenPSG.Id + ); + insert new List{ psa1, psa2 }; } @isTest - static void testSkillCreate() { - User testUser = [SELECT Id, Name FROM User WHERE LastName = 'SKILLED']; - STO_GroupMemberSkillService.nksUserMap.clear(); - STO_GroupMemberSkillService.nksUserMap.put(testUser.Id, testUser); //Override the return of the map since the permission set group does not exist in this package + static void nksServiceResourceWithSkillCreate() { STO_GroupMemberSkillService service = new STO_GroupMemberSkillService(); + System.assertEquals( + 2, + [ + SELECT COUNT() + FROM GroupMember + WHERE + UserOrGroupId IN (SELECT Id FROM User WHERE LastName = 'SKILLED') + AND Group.DeveloperName IN ( + 'Fortrolig_Adresse_AD', + 'NKS_Skjermede_Personer_AD', + 'Skjermede_Personer_AD' + ) + ] + ); + Test.startTest(); + service.handleGroupAndSkillSync(); + Test.stopTest(); + + System.assertEquals(1, [SELECT COUNT() FROM ServiceResource], 'Expected serviceresource for NKS user'); + ServiceResource nksSR = [SELECT Id, RelatedRecordId, CRM_Domain__c FROM ServiceResource LIMIT 1]; + System.assertEquals( + 2, + [ + SELECT COUNT() + FROM ServiceResourceSkill + WHERE ServiceResourceId = :nksSR.Id + ], + 'Expected 2 skills for NKS user' + ); + } + @isTest + static void hotServiceResourceWithSkillCreate() { + STO_GroupMemberSkillService service = new STO_GroupMemberSkillService( + 'HOT', + 'Servicetjenesten', + 'HOT_Servicetjenesten_Group', + 'Fortrolig_Adresse_AD', + 'Skjermede_Personer_AD' + ); + System.assertEquals( + 2, + [ + SELECT COUNT() + FROM GroupMember + WHERE + UserOrGroupId IN (SELECT Id FROM User WHERE LastName = 'PUPKIN') + AND Group.DeveloperName IN ( + 'Fortrolig_Adresse_AD', + 'NKS_Skjermede_Personer_AD', + 'Skjermede_Personer_AD' + ) + ] + ); Test.startTest(); service.handleGroupAndSkillSync(); Test.stopTest(); - System.assertEquals(1, [SELECT COUNT() FROM ServiceResource]); + System.assertEquals(1, [SELECT COUNT() FROM ServiceResource], 'Expected serviceresource for HOT user'); + + ServiceResource hotSR = [ + SELECT Id, RelatedRecordId, RelatedRecord.LastName, CRM_Domain__c + FROM ServiceResource + LIMIT 1 + ]; + System.assertEquals('PUPKIN', hotSR.RelatedRecord.LastName, 'Expected HOT user'); + System.assertEquals('HOT', hotSR.CRM_Domain__c, 'Expected HOT domain'); + System.assertEquals( + 2, + [ + SELECT COUNT() + FROM ServiceResourceSkill + WHERE ServiceResourceId = :hotSR.Id + ], + 'Expected 2 skills for HOT user' + ); + } + + @isTest + static void callableSync() { + System.assertEquals( + 2, + [ + SELECT COUNT() + FROM GroupMember + WHERE + UserOrGroupId IN (SELECT Id FROM User WHERE LastName = 'PUPKIN') + AND Group.DeveloperName IN ( + 'Fortrolig_Adresse_AD', + 'NKS_Skjermede_Personer_AD', + 'Skjermede_Personer_AD' + ) + ] + ); + Test.startTest(); + try { + Callable syncService = (Callable) Type.forName('STO_GroupMemberSkillService').newInstance(); + syncService.call( + 'handleGroupAndSkillSync', + new Map{ + 'domain' => 'HOT', + 'subdomain' => 'Servicetjenesten', + 'permsetgroup' => 'HOT_Servicetjenesten_Group', + 'fortroliggroup' => 'Fortrolig_Adresse_AD', + 'skjermedegroup' => 'Skjermede_Personer_AD' + } + ); + } catch (Exception e) { + System.Assert.isTrue(false, 'Could not call callable class' + e.getMessage()); + } + Test.stopTest(); + + System.assertEquals(1, [SELECT COUNT() FROM ServiceResource], 'Expected serviceresource for HOT user'); + + ServiceResource hotSR = [ + SELECT Id, RelatedRecordId, RelatedRecord.LastName, CRM_Domain__c + FROM ServiceResource + LIMIT 1 + ]; + System.assertEquals('PUPKIN', hotSR.RelatedRecord.LastName, 'Expected HOT user'); + System.assertEquals('HOT', hotSR.CRM_Domain__c, 'Expected HOT domain'); + System.assertEquals( + 2, + [ + SELECT COUNT() + FROM ServiceResourceSkill + WHERE ServiceResourceId = :hotSR.Id + ], + 'Expected 2 skills for HOT user' + ); } @isTest static void testSkillRemove() { User testUser = [SELECT Id, Name FROM User WHERE LastName = 'SKILLED']; - STO_GroupMemberSkillService.nksUserMap.clear(); - STO_GroupMemberSkillService.nksUserMap.put(testUser.Id, testUser); //Override the return of the map since the permission set group does not exist in this package STO_GroupMemberSkillService service = new STO_GroupMemberSkillService(); service.handleGroupAndSkillSync(); - + System.assertEquals( + 2, + [ + SELECT COUNT() + FROM ServiceResourceSkill + WHERE ServiceResource.RelatedRecordId = :testUser.Id + ], + 'Expected 2 skills for NKS user' + ); Test.startTest(); //Removing from the skjermede group removeFromGroup(testUser.Id, 'NKS_Skjermede_Personer_AD'); @@ -42,6 +194,15 @@ public class STO_GroupMemberSkillService_Test { //Create new service as the memberlist have changed STO_GroupMemberSkillService service2 = new STO_GroupMemberSkillService(); service2.handleGroupAndSkillSync(); + System.assertEquals( + 1, + [ + SELECT COUNT() + FROM ServiceResourceSkill + WHERE ServiceResource.RelatedRecordId = :testUser.Id + ], + 'Expected 1 skills for NKS user' + ); } @isTest @@ -62,7 +223,6 @@ public class STO_GroupMemberSkillService_Test { System.assertEquals(2, [SELECT COUNT() FROM Application_Log__c]); //Two errors should be logged } - @future private static void removeFromGroup(Id userId, String groupDevName) { delete [SELECT Id FROM GroupMember WHERE UserOrGroupId = :userId AND Group.DeveloperName = :groupDevName]; From 997e2e4af29deff480594e71dde4020262ef2f79 Mon Sep 17 00:00:00 2001 From: Eugenijus Date: Fri, 7 Feb 2025 13:39:09 +0100 Subject: [PATCH 06/14] update logging in custom domain --- .../default/classes/STO_GroupMemberSkillService.cls | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/force-app/main/default/classes/STO_GroupMemberSkillService.cls b/force-app/main/default/classes/STO_GroupMemberSkillService.cls index 1996f6b0..225e2a7c 100644 --- a/force-app/main/default/classes/STO_GroupMemberSkillService.cls +++ b/force-app/main/default/classes/STO_GroupMemberSkillService.cls @@ -227,7 +227,11 @@ public with sharing class STO_GroupMemberSkillService implements Callable { for (Database.Error err : saveRes.getErrors()) { //Skip already assigned skill if (!(err.getStatusCode() == StatusCode.DUPLICATE_VALUE)) { - logger.error('Failed to create skill', null, CRM_ApplicationDomain.Domain.NKS); + logger.error( + 'Failed to create skill', + null, + CRM_ApplicationDomain.Domain.valueOf(this.srDomain) + ); } } } @@ -245,7 +249,11 @@ public with sharing class STO_GroupMemberSkillService implements Callable { for (Database.DeleteResult delRes : deleteResList) { if (!delRes.isSuccess()) { for (Database.Error err : delRes.getErrors()) { - logger.error('Failed to create skill: ' + err.getMessage(), null, CRM_ApplicationDomain.Domain.NKS); + logger.error( + 'Failed to create skill: ' + err.getMessage(), + null, + CRM_ApplicationDomain.Domain.valueOf(this.srDomain) + ); } } } From 6bbf45e26707ff95f7c358f3dde8510a03f0e798 Mon Sep 17 00:00:00 2001 From: Eugenijus Date: Fri, 7 Feb 2025 13:42:45 +0100 Subject: [PATCH 07/14] fix prettier --- config/project-scratch-def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/project-scratch-def.json b/config/project-scratch-def.json index fa9f2331..1ddd803b 100644 --- a/config/project-scratch-def.json +++ b/config/project-scratch-def.json @@ -78,4 +78,4 @@ "enableOmniSecondaryRoutingPriority": true } } -} \ No newline at end of file +} From 646387a053fac993dc12f939ac1af8f532573390 Mon Sep 17 00:00:00 2001 From: Eugenijus Date: Fri, 7 Feb 2025 15:52:57 +0100 Subject: [PATCH 08/14] update tests --- .../classes/STO_GroupMemberSkillService.cls | 1 - .../STO_GroupMemberSkillService_Test.cls | 109 +++++++++++++----- 2 files changed, 82 insertions(+), 28 deletions(-) diff --git a/force-app/main/default/classes/STO_GroupMemberSkillService.cls b/force-app/main/default/classes/STO_GroupMemberSkillService.cls index 225e2a7c..285a2082 100644 --- a/force-app/main/default/classes/STO_GroupMemberSkillService.cls +++ b/force-app/main/default/classes/STO_GroupMemberSkillService.cls @@ -17,7 +17,6 @@ public with sharing class STO_GroupMemberSkillService implements Callable { private String permsetGroupName = PERMSET_GROUP_NAME; private String srDomain = SR_DOMAIN; private String srSubDomain; - private Set groupNamesToSync = new Set{ fortroligGroupName, skjermedeGroupName }; private Set fortroligMembers = new Set(); private Set skjermedeMembers = new Set(); private Set fortroligSkillUsers = new Set(); diff --git a/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls b/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls index 5daccf0c..a925795f 100644 --- a/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls +++ b/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls @@ -1,7 +1,14 @@ -@isTest +@IsTest public class STO_GroupMemberSkillService_Test { @TestSetup - static void makeData() { + private static void makeData() { + myTriggers.disable(PersonAccessHandler.class); + myTriggers.disable(UserPermissionSetAssignmentHandler.class); + myTriggers.disable(UserDefaultValuesHandler.class); + myTriggers.disable(UserProfileHandler.class); + myTriggers.disable(UserGroupMemberHandler.class); + myTriggers.disable(UserRegionHandler.class); + myTriggers.disable(UserRoleAssignmentHandler.class); Group fortroligGroup = TestDataFactory.getPublicGroup( 'group_AD_Fortrolig_Adresse', 'group_AD_Fortrolig_Adresse' @@ -21,15 +28,31 @@ public class STO_GroupMemberSkillService_Test { memberList.add(new GroupMember(GroupId = fortroligGroup.Id, UserOrGroupId = usr2.Id)); memberList.add(new GroupMember(GroupId = skjermedeGroup.Id, UserOrGroupId = usr2.Id)); STO_TestDataFactory.createRecordList(memberList); - PermissionSetGroup kontaktsenterPSG = new PermissionSetGroup( - MasterLabel = 'Kontaktsenter', - DeveloperName = 'Kontaktsenter' - ); - PermissionSetGroup servicetjenestenPSG = new PermissionSetGroup( - MasterLabel = 'Servicetjenesten', - DeveloperName = 'HOT_Servicetjenesten_Group' - ); - insert new List{ kontaktsenterPSG, servicetjenestenPSG }; + PermissionSetGroup kontaktsenterPSG; + PermissionSetGroup servicetjenestenPSG; + List psgs = [ + SELECT Id, DeveloperName + FROM PermissionSetGroup + WHERE DeveloperName IN ('Kontaktsenter', 'HOT_Servicetjenesten_Group') + ]; + for (PermissionSetGroup psg : psgs) { + if (psg.DeveloperName == 'Kontaktsenter') { + kontaktsenterPSG = psg; + } else if (psg.DeveloperName == 'HOT_Servicetjenesten_Group') { + servicetjenestenPSG = psg; + } + } + if (kontaktsenterPSG == null) { + kontaktsenterPSG = new PermissionSetGroup(MasterLabel = 'Kontaktsenter', DeveloperName = 'Kontaktsenter'); + insert kontaktsenterPSG; + } + if (servicetjenestenPSG == null) { + servicetjenestenPSG = new PermissionSetGroup( + MasterLabel = 'Servicetjenesten', + DeveloperName = 'HOT_Servicetjenesten_Group' + ); + insert servicetjenestenPSG; + } PermissionSetAssignment psa1 = new PermissionSetAssignment( AssigneeId = usr1.ID, PermissionSetGroupId = kontaktsenterPSG.Id @@ -41,8 +64,8 @@ public class STO_GroupMemberSkillService_Test { insert new List{ psa1, psa2 }; } - @isTest - static void nksServiceResourceWithSkillCreate() { + @IsTest + private static void nksServiceResourceWithSkillCreate() { STO_GroupMemberSkillService service = new STO_GroupMemberSkillService(); System.assertEquals( 2, @@ -62,9 +85,23 @@ public class STO_GroupMemberSkillService_Test { service.handleGroupAndSkillSync(); Test.stopTest(); - System.assertEquals(1, [SELECT COUNT() FROM ServiceResource], 'Expected serviceresource for NKS user'); + System.assertEquals( + 1, + [SELECT COUNT() FROM ServiceResource WHERE RelatedRecord.LastName = 'SKILLED'], + 'Expected serviceresource for NKS user' + ); + System.assertEquals( + 0, + [SELECT COUNT() FROM ServiceResource WHERE RelatedRecord.LastName = 'PUPKIN'], + 'Expected no serviceresource for HOT user' + ); - ServiceResource nksSR = [SELECT Id, RelatedRecordId, CRM_Domain__c FROM ServiceResource LIMIT 1]; + ServiceResource nksSR = [ + SELECT Id, RelatedRecordId, CRM_Domain__c + FROM ServiceResource + WHERE RelatedRecord.LastName = 'SKILLED' + LIMIT 1 + ]; System.assertEquals( 2, [ @@ -75,8 +112,8 @@ public class STO_GroupMemberSkillService_Test { 'Expected 2 skills for NKS user' ); } - @isTest - static void hotServiceResourceWithSkillCreate() { + @IsTest + private static void hotServiceResourceWithSkillCreate() { STO_GroupMemberSkillService service = new STO_GroupMemberSkillService( 'HOT', 'Servicetjenesten', @@ -102,14 +139,23 @@ public class STO_GroupMemberSkillService_Test { service.handleGroupAndSkillSync(); Test.stopTest(); - System.assertEquals(1, [SELECT COUNT() FROM ServiceResource], 'Expected serviceresource for HOT user'); + System.assertEquals( + 1, + [SELECT COUNT() FROM ServiceResource WHERE RelatedRecord.LastName = 'PUPKIN'], + 'Expected serviceresource for HOT user' + ); + System.assertEquals( + 0, + [SELECT COUNT() FROM ServiceResource WHERE RelatedRecord.LastName = 'SKILLED'], + 'Expected no serviceresource for NKS user' + ); ServiceResource hotSR = [ SELECT Id, RelatedRecordId, RelatedRecord.LastName, CRM_Domain__c FROM ServiceResource + WHERE RelatedRecord.LastName = 'PUPKIN' LIMIT 1 ]; - System.assertEquals('PUPKIN', hotSR.RelatedRecord.LastName, 'Expected HOT user'); System.assertEquals('HOT', hotSR.CRM_Domain__c, 'Expected HOT domain'); System.assertEquals( 2, @@ -122,8 +168,8 @@ public class STO_GroupMemberSkillService_Test { ); } - @isTest - static void callableSync() { + @IsTest + private static void callableSync() { System.assertEquals( 2, [ @@ -156,14 +202,23 @@ public class STO_GroupMemberSkillService_Test { } Test.stopTest(); - System.assertEquals(1, [SELECT COUNT() FROM ServiceResource], 'Expected serviceresource for HOT user'); + System.assertEquals( + 1, + [SELECT COUNT() FROM ServiceResource WHERE RelatedRecord.LastName = 'PUPKIN'], + 'Expected serviceresource for HOT user' + ); + System.assertEquals( + 0, + [SELECT COUNT() FROM ServiceResource WHERE RelatedRecord.LastName = 'SKILLED'], + 'Expected no serviceresource for NKS user' + ); ServiceResource hotSR = [ SELECT Id, RelatedRecordId, RelatedRecord.LastName, CRM_Domain__c FROM ServiceResource + WHERE RelatedRecord.LastName = 'PUPKIN' LIMIT 1 ]; - System.assertEquals('PUPKIN', hotSR.RelatedRecord.LastName, 'Expected HOT user'); System.assertEquals('HOT', hotSR.CRM_Domain__c, 'Expected HOT domain'); System.assertEquals( 2, @@ -176,8 +231,8 @@ public class STO_GroupMemberSkillService_Test { ); } - @isTest - static void testSkillRemove() { + @IsTest + private static void testSkillRemove() { User testUser = [SELECT Id, Name FROM User WHERE LastName = 'SKILLED']; STO_GroupMemberSkillService service = new STO_GroupMemberSkillService(); service.handleGroupAndSkillSync(); @@ -208,8 +263,8 @@ public class STO_GroupMemberSkillService_Test { ); } - @isTest - static void testDmlVerification() { + @IsTest + private static void testDmlVerification() { Account testAcc = new Account(Name = 'Test Account'); User testUser = [SELECT Id, Name FROM User WHERE LastName = 'SKILLED']; List saveResList = Database.insert(new List{ testAcc, testUser }, false); From bdcff05e97ca9db184725314612f37e2a12d7b6e Mon Sep 17 00:00:00 2001 From: Eugenijus Date: Mon, 10 Feb 2025 08:06:13 +0100 Subject: [PATCH 09/14] update test with missing skill metadata --- .../STO_GroupMemberSkillService_Test.cls | 21 +++++++++++++++++++ .../staticresources/testFortroligSkill.csv | 2 ++ .../testFortroligSkill.resource-meta.xml | 4 ++++ .../staticresources/testSkjermetSkill.csv | 2 ++ .../testSkjermetSkill.resource-meta.xml | 4 ++++ 5 files changed, 33 insertions(+) create mode 100644 force-app/main/default/staticresources/testFortroligSkill.csv create mode 100644 force-app/main/default/staticresources/testFortroligSkill.resource-meta.xml create mode 100644 force-app/main/default/staticresources/testSkjermetSkill.csv create mode 100644 force-app/main/default/staticresources/testSkjermetSkill.resource-meta.xml diff --git a/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls b/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls index a925795f..a7733e39 100644 --- a/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls +++ b/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls @@ -62,6 +62,27 @@ public class STO_GroupMemberSkillService_Test { PermissionSetGroupId = servicetjenestenPSG.Id ); insert new List{ psa1, psa2 }; + + if ( + [ + SELECT Id, DeveloperName + FROM Skill + WHERE DeveloperName = 'Fortrolig_addresse' + ] + .isEmpty() + ) { + Test.loadData(Skill.sObjectType, 'testFortroligSkill'); + } + if ( + [ + SELECT Id, DeveloperName + FROM Skill + WHERE DeveloperName = 'Skjermede_Personer' + ] + .isEmpty() + ) { + Test.loadData(Skill.sObjectType, 'testSkjermetSkill'); + } } @IsTest diff --git a/force-app/main/default/staticresources/testFortroligSkill.csv b/force-app/main/default/staticresources/testFortroligSkill.csv new file mode 100644 index 00000000..d13bf28e --- /dev/null +++ b/force-app/main/default/staticresources/testFortroligSkill.csv @@ -0,0 +1,2 @@ +DeveloperName,MasterLabel +Fortrolig_addresse,Fortrolig \ No newline at end of file diff --git a/force-app/main/default/staticresources/testFortroligSkill.resource-meta.xml b/force-app/main/default/staticresources/testFortroligSkill.resource-meta.xml new file mode 100644 index 00000000..14c796fa --- /dev/null +++ b/force-app/main/default/staticresources/testFortroligSkill.resource-meta.xml @@ -0,0 +1,4 @@ + + + text/csv + \ No newline at end of file diff --git a/force-app/main/default/staticresources/testSkjermetSkill.csv b/force-app/main/default/staticresources/testSkjermetSkill.csv new file mode 100644 index 00000000..d13bf28e --- /dev/null +++ b/force-app/main/default/staticresources/testSkjermetSkill.csv @@ -0,0 +1,2 @@ +DeveloperName,MasterLabel +Fortrolig_addresse,Fortrolig \ No newline at end of file diff --git a/force-app/main/default/staticresources/testSkjermetSkill.resource-meta.xml b/force-app/main/default/staticresources/testSkjermetSkill.resource-meta.xml new file mode 100644 index 00000000..14c796fa --- /dev/null +++ b/force-app/main/default/staticresources/testSkjermetSkill.resource-meta.xml @@ -0,0 +1,4 @@ + + + text/csv + \ No newline at end of file From 9c6365a822c953db91cbd8d0c179a33e18560b88 Mon Sep 17 00:00:00 2001 From: Eugenijus Date: Mon, 10 Feb 2025 08:32:25 +0100 Subject: [PATCH 10/14] fix copypaste :D skill devname --- force-app/main/default/staticresources/testSkjermetSkill.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/force-app/main/default/staticresources/testSkjermetSkill.csv b/force-app/main/default/staticresources/testSkjermetSkill.csv index d13bf28e..c8839efe 100644 --- a/force-app/main/default/staticresources/testSkjermetSkill.csv +++ b/force-app/main/default/staticresources/testSkjermetSkill.csv @@ -1,2 +1,2 @@ DeveloperName,MasterLabel -Fortrolig_addresse,Fortrolig \ No newline at end of file +Skjermede_personer,Skjermet \ No newline at end of file From d55eb38dc6980fd1b56638ec229c6caacfda0a9e Mon Sep 17 00:00:00 2001 From: Eugenijus Date: Mon, 10 Feb 2025 09:28:26 +0100 Subject: [PATCH 11/14] update test names to neutral :) --- .../classes/STO_GroupMemberSkillService_Test.cls | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls b/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls index a7733e39..1876adff 100644 --- a/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls +++ b/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls @@ -21,7 +21,7 @@ public class STO_GroupMemberSkillService_Test { //Adds the testuser as a member in both groups User usr1 = (User) STO_TestDataFactory.createRecord(new User(FirstName = 'SUPER', LastName = 'SKILLED')); - User usr2 = (User) STO_TestDataFactory.createRecord(new User(FirstName = 'VASILIJ', LastName = 'PUPKIN')); + User usr2 = (User) STO_TestDataFactory.createRecord(new User(FirstName = 'HOTST', LastName = 'HOTST')); List memberList = new List(); memberList.add(new GroupMember(GroupId = fortroligGroup.Id, UserOrGroupId = usr1.Id)); memberList.add(new GroupMember(GroupId = nksSkjermedeGroup.Id, UserOrGroupId = usr1.Id)); @@ -113,7 +113,7 @@ public class STO_GroupMemberSkillService_Test { ); System.assertEquals( 0, - [SELECT COUNT() FROM ServiceResource WHERE RelatedRecord.LastName = 'PUPKIN'], + [SELECT COUNT() FROM ServiceResource WHERE RelatedRecord.LastName = 'HOTST'], 'Expected no serviceresource for HOT user' ); @@ -148,7 +148,7 @@ public class STO_GroupMemberSkillService_Test { SELECT COUNT() FROM GroupMember WHERE - UserOrGroupId IN (SELECT Id FROM User WHERE LastName = 'PUPKIN') + UserOrGroupId IN (SELECT Id FROM User WHERE LastName = 'HOTST') AND Group.DeveloperName IN ( 'group_AD_Fortrolig_Adresse', 'NKS_Skjermede_Personer_AD', @@ -162,7 +162,7 @@ public class STO_GroupMemberSkillService_Test { System.assertEquals( 1, - [SELECT COUNT() FROM ServiceResource WHERE RelatedRecord.LastName = 'PUPKIN'], + [SELECT COUNT() FROM ServiceResource WHERE RelatedRecord.LastName = 'HOTST'], 'Expected serviceresource for HOT user' ); System.assertEquals( @@ -174,7 +174,7 @@ public class STO_GroupMemberSkillService_Test { ServiceResource hotSR = [ SELECT Id, RelatedRecordId, RelatedRecord.LastName, CRM_Domain__c FROM ServiceResource - WHERE RelatedRecord.LastName = 'PUPKIN' + WHERE RelatedRecord.LastName = 'HOTST' LIMIT 1 ]; System.assertEquals('HOT', hotSR.CRM_Domain__c, 'Expected HOT domain'); @@ -197,7 +197,7 @@ public class STO_GroupMemberSkillService_Test { SELECT COUNT() FROM GroupMember WHERE - UserOrGroupId IN (SELECT Id FROM User WHERE LastName = 'PUPKIN') + UserOrGroupId IN (SELECT Id FROM User WHERE LastName = 'HOTST') AND Group.DeveloperName IN ( 'group_AD_Fortrolig_Adresse', 'NKS_Skjermede_Personer_AD', @@ -225,7 +225,7 @@ public class STO_GroupMemberSkillService_Test { System.assertEquals( 1, - [SELECT COUNT() FROM ServiceResource WHERE RelatedRecord.LastName = 'PUPKIN'], + [SELECT COUNT() FROM ServiceResource WHERE RelatedRecord.LastName = 'HOTST'], 'Expected serviceresource for HOT user' ); System.assertEquals( @@ -237,7 +237,7 @@ public class STO_GroupMemberSkillService_Test { ServiceResource hotSR = [ SELECT Id, RelatedRecordId, RelatedRecord.LastName, CRM_Domain__c FROM ServiceResource - WHERE RelatedRecord.LastName = 'PUPKIN' + WHERE RelatedRecord.LastName = 'HOTST' LIMIT 1 ]; System.assertEquals('HOT', hotSR.CRM_Domain__c, 'Expected HOT domain'); From 207823330bc1bc71bcb6f64292a94e22fed748cd Mon Sep 17 00:00:00 2001 From: Eugenijus Date: Mon, 10 Feb 2025 09:44:05 +0100 Subject: [PATCH 12/14] update clean up commented --- .../main/default/classes/STO_GroupMemberSkillService.cls | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/force-app/main/default/classes/STO_GroupMemberSkillService.cls b/force-app/main/default/classes/STO_GroupMemberSkillService.cls index 285a2082..e89608c2 100644 --- a/force-app/main/default/classes/STO_GroupMemberSkillService.cls +++ b/force-app/main/default/classes/STO_GroupMemberSkillService.cls @@ -168,7 +168,7 @@ public with sharing class STO_GroupMemberSkillService implements Callable { } } - if (!skillsToCreate.isEmpty() /*&& !Test.isRunningTest()*/) { + if (!skillsToCreate.isEmpty()) { List saveResList = Database.insert(skillsToCreate, false); verifySkillinsert(saveResList); } @@ -192,7 +192,7 @@ public with sharing class STO_GroupMemberSkillService implements Callable { AND ServiceResource.RelatedRecordId NOT IN :skjermedeMembers)) ]; - if (!skillsToDelete.isEmpty() /*&& !Test.isRunningTest()*/) { + if (!skillsToDelete.isEmpty()) { List deleteResList = Database.delete(skillsToDelete, false); verifySkillRemoval(deleteResList); } From bdccd48e5a6bdd33f1c5a53bec3cc7370dd41b46 Mon Sep 17 00:00:00 2001 From: Eugenijus Date: Mon, 10 Feb 2025 12:38:22 +0100 Subject: [PATCH 13/14] update suggestions from review --- .../classes/STO_GroupMemberSkillService.cls | 164 +++++++----------- .../STO_GroupMemberSkillService_Test.cls | 15 +- 2 files changed, 71 insertions(+), 108 deletions(-) diff --git a/force-app/main/default/classes/STO_GroupMemberSkillService.cls b/force-app/main/default/classes/STO_GroupMemberSkillService.cls index e89608c2..d55cddfd 100644 --- a/force-app/main/default/classes/STO_GroupMemberSkillService.cls +++ b/force-app/main/default/classes/STO_GroupMemberSkillService.cls @@ -21,72 +21,38 @@ public with sharing class STO_GroupMemberSkillService implements Callable { private Set skjermedeMembers = new Set(); private Set fortroligSkillUsers = new Set(); private Set skjermedeSkillUsers = new Set(); + @TestVisible + private Map userMap; + @TestVisible + private Map skillIdMap; @TestVisible - private Map userMap { - get { - if (userMap == null) { - List userList = new List(); - for (PermissionSetAssignment psa : [ - SELECT Assignee.Id, Assignee.Name, PermissionSetGroup.DeveloperName - FROM PermissionSetAssignment - WHERE PermissionSetGroup.DeveloperName = :this.permsetGroupName - ]) { - userList.add(psa.Assignee); - } - userMap = new Map(userList); - } - return userMap; - } - private set { - userMap = value; - } + private Map initUserMap() { + userMap = new Map( + [ + SELECT Id, Name + FROM User + WHERE + Id IN ( + SELECT AssigneeId + FROM PermissionSetAssignment + WHERE PermissionSetGroup.DeveloperName = :permsetGroupName + ) + ] + ); + return userMap; } @TestVisible - private Map skillIdMap { - get { - if (skillIdMap == null) { - skillIdMap = new Map(); - for (Skill skill : [ - SELECT Id, DeveloperName - FROM Skill - WHERE DeveloperName = :FORTOLIG_ADDRESSE_SKILL OR DeveloperName = :SKJERMEDE_PERSONER_SKILL - ]) { - skillIdMap.put(skill.DeveloperName, skill.Id); - } - } - return skillIdMap; + private Map initSkillIdMap() { + skillIdMap = new Map(); + for (Skill skill : [ + SELECT Id, DeveloperName + FROM Skill + WHERE DeveloperName = :FORTOLIG_ADDRESSE_SKILL OR DeveloperName = :SKJERMEDE_PERSONER_SKILL + ]) { + skillIdMap.put(skill.DeveloperName, skill.Id); } - private set; - } - /** - * @description default constructor for the class - */ - @SuppressWarnings('PMD.EmptyStatementBlock') - public STO_GroupMemberSkillService() { - } - /** - * @description Only for test purpouses - * @param domain - * @param subDomain - * @param permSetGroup - * @param fortroligGroup - * @param skjermedeGroup - */ - @TestVisible - @SuppressWarnings('PMD.ExcessiveParameterList') - private STO_GroupMemberSkillService( - String domain, - String subDomain, - String permSetGroup, - String fortroligGroup, - String skjermedeGroup - ) { - this.srDomain = domain; - this.srSubDomain = subDomain; - this.permsetGroupName = permSetGroup; - this.fortroligGroupName = fortroligGroup; - this.skjermedeGroupName = skjermedeGroup; + return skillIdMap; } /** @@ -99,14 +65,14 @@ public with sharing class STO_GroupMemberSkillService implements Callable { SELECT UserOrGroupId, Group.DeveloperName FROM GroupMember WHERE - Group.DeveloperName IN (:this.fortroligGroupName, :this.skjermedeGroupName) - AND UserOrGroupId IN :this.userMap.keySet() + Group.DeveloperName IN (:fortroligGroupName, :skjermedeGroupName) + AND UserOrGroupId IN :userMap.keySet() ]) { String userOrGroupId = String.valueOf(GroupMember.UserOrGroupId); - if (groupMember.Group.DeveloperName == this.fortroligGroupName) { - this.fortroligMembers.add(groupMember.UserOrGroupId); + if (groupMember.Group.DeveloperName == fortroligGroupName) { + fortroligMembers.add(groupMember.UserOrGroupId); } else { - this.skjermedeMembers.add(groupMember.UserOrGroupId); + skjermedeMembers.add(groupMember.UserOrGroupId); } } } @@ -123,12 +89,12 @@ public with sharing class STO_GroupMemberSkillService implements Callable { WHERE (Skill.DeveloperName = :FORTOLIG_ADDRESSE_SKILL OR Skill.DeveloperName = :SKJERMEDE_PERSONER_SKILL) - AND ServiceResource.CRM_Domain__c = :this.srDomain + AND ServiceResource.CRM_Domain__c = :srDomain ]) { if (servSkill.Skill.DeveloperName == FORTOLIG_ADDRESSE_SKILL) { - this.fortroligSkillUsers.add(servSkill.ServiceResourceId); + fortroligSkillUsers.add(servSkill.ServiceResourceId); } else { - this.skjermedeSkillUsers.add(servSKill.ServiceResourceId); + skjermedeSkillUsers.add(servSKill.ServiceResourceId); } } } @@ -136,11 +102,13 @@ public with sharing class STO_GroupMemberSkillService implements Callable { * @description Handles syncronization of users having a groupmember to the skills they have */ public void handleGroupAndSkillSync() { - this.getGroupMembers(); - this.initSkillUserSets(); + initUserMap(); + initSkillIdMap(); + getGroupMembers(); + initSkillUserSets(); //Ensures all NKS users have a related service resource created - this.handleSkillInsert(); - this.handleSkillDeletion(); + handleSkillInsert(); + handleSkillDeletion(); } /** @@ -148,22 +116,20 @@ public with sharing class STO_GroupMemberSkillService implements Callable { * @author Stian Ruud Schikora | 12-16-2021 **/ private void handleSkillInsert() { - Map userResourceMap = this.handleServiceResourceCreation(); + Map userResourceMap = handleServiceResourceCreation(); List skillsToCreate = new List(); - for (Id memberId : this.fortroligMembers) { + for (Id memberId : fortroligMembers) { //If a userId in the fortrolig group is not contained in the fortroligSkillUser set, we need to ass the skill for that user - if (!this.fortroligSkillUsers.contains(memberId)) { - skillsToCreate.add( - this.createSkill(this.skillIdMap.get(FORTOLIG_ADDRESSE_SKILL), userResourceMap.get(memberId)) - ); + if (!fortroligSkillUsers.contains(memberId)) { + skillsToCreate.add(createSkill(skillIdMap.get(FORTOLIG_ADDRESSE_SKILL), userResourceMap.get(memberId))); } } - for (Id memberId : this.skjermedeMembers) { + for (Id memberId : skjermedeMembers) { //If a userId in the fortrolig group is not contained in the skjermedeSkillUsers set, we need to ass the skill for that user - if (!this.skjermedeSkillUsers.contains(memberId)) { + if (!skjermedeSkillUsers.contains(memberId)) { skillsToCreate.add( - this.createSkill(this.skillIdMap.get(SKJERMEDE_PERSONER_SKILL), userResourceMap.get(memberId)) + createSkill(skillIdMap.get(SKJERMEDE_PERSONER_SKILL), userResourceMap.get(memberId)) ); } } @@ -185,7 +151,7 @@ public with sharing class STO_GroupMemberSkillService implements Callable { SELECT Id, ServiceResourceId, Skill.DeveloperName FROM ServiceResourceSkill WHERE - ServiceResource.CRM_Domain__c = :this.srDomain + ServiceResource.CRM_Domain__c = :srDomain AND ((Skill.DeveloperName = :FORTOLIG_ADDRESSE_SKILL AND ServiceResource.RelatedRecordId NOT IN :fortroligMembers) OR (Skill.DeveloperName = :SKJERMEDE_PERSONER_SKILL @@ -226,11 +192,7 @@ public with sharing class STO_GroupMemberSkillService implements Callable { for (Database.Error err : saveRes.getErrors()) { //Skip already assigned skill if (!(err.getStatusCode() == StatusCode.DUPLICATE_VALUE)) { - logger.error( - 'Failed to create skill', - null, - CRM_ApplicationDomain.Domain.valueOf(this.srDomain) - ); + logger.error('Failed to create skill', null, CRM_ApplicationDomain.Domain.valueOf(srDomain)); } } } @@ -251,7 +213,7 @@ public with sharing class STO_GroupMemberSkillService implements Callable { logger.error( 'Failed to create skill: ' + err.getMessage(), null, - CRM_ApplicationDomain.Domain.valueOf(this.srDomain) + CRM_ApplicationDomain.Domain.valueOf(srDomain) ); } } @@ -267,9 +229,9 @@ public with sharing class STO_GroupMemberSkillService implements Callable { **/ @SuppressWarnings('PMD.ApexCRUDViolation') private Map handleServiceResourceCreation() { - Map userResourceMap = this.getServiceResources(); + Map userResourceMap = getServiceResources(); //If the resource map contains less keys than input userIds, we need to create serviceresources - Set usersWithoutSR = new Set(this.userMap.keySet()); + Set usersWithoutSR = new Set(userMap.keySet()); usersWithoutSR.removeAll(userResourceMap.keySet()); List resourcesToCreate = new List(); for (Id userId : usersWithoutSR) { @@ -280,7 +242,7 @@ public with sharing class STO_GroupMemberSkillService implements Callable { RelatedRecordId = usr.Id, Name = usr.Name, IsActive = true, - CRM_Domain__c = this.srDomain + CRM_Domain__c = srDomain ) ); } @@ -305,10 +267,7 @@ public with sharing class STO_GroupMemberSkillService implements Callable { for (ServiceResource servRes : [ SELECT Id, RelatedRecordId, CRM_Domain__c FROM ServiceResource - WHERE - RelatedRecordId IN :this.userMap.keySet() - AND CRM_Domain__c = :this.srDomain - AND CRM_SubDomain__c = :this.srSubDomain + WHERE RelatedRecordId IN :userMap.keySet() AND CRM_Domain__c = :srDomain AND CRM_SubDomain__c = :srSubDomain ]) { userResourceMap.put(servRes.RelatedRecordId, servRes); } @@ -326,7 +285,7 @@ public with sharing class STO_GroupMemberSkillService implements Callable { public Object call(String action, Map args) { switch on action.toLowerCase() { when 'handlegroupandskillsync' { - this.setParams(args).handleGroupAndSkillSync(); + setParams(args).handleGroupAndSkillSync(); return 0; } when else { @@ -334,6 +293,7 @@ public with sharing class STO_GroupMemberSkillService implements Callable { } } } + @TestVisible private STO_GroupMemberSkillService setParams(Map params) { for (String key : params.keySet()) { if (params.get(key) == null || !(params.get(key) instanceof String)) { @@ -341,19 +301,19 @@ public with sharing class STO_GroupMemberSkillService implements Callable { } switch on key.toLowerCase() { when 'domain' { - this.srDomain = (String) params.get(key); + srDomain = (String) params.get(key); } when 'subdomain' { - this.srSubDomain = (String) params.get(key); + srSubDomain = (String) params.get(key); } when 'permsetgroup' { - this.permsetGroupName = (String) params.get(key); + permsetGroupName = (String) params.get(key); } when 'fortroliggroup' { - this.fortroligGroupName = (String) params.get(key); + fortroligGroupName = (String) params.get(key); } when 'skjermedegroup' { - this.skjermedeGroupName = (String) params.get(key); + skjermedeGroupName = (String) params.get(key); } } } diff --git a/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls b/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls index 1876adff..9f465e8b 100644 --- a/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls +++ b/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls @@ -135,12 +135,15 @@ public class STO_GroupMemberSkillService_Test { } @IsTest private static void hotServiceResourceWithSkillCreate() { - STO_GroupMemberSkillService service = new STO_GroupMemberSkillService( - 'HOT', - 'Servicetjenesten', - 'HOT_Servicetjenesten_Group', - 'group_AD_Fortrolig_Adresse', - 'Skjermede_Personer_AD' + STO_GroupMemberSkillService service = new STO_GroupMemberSkillService(); + service.setParams( + new Map{ + 'domain' => 'HOT', + 'subdomain' => 'Servicetjenesten', + 'permsetgroup' => 'HOT_Servicetjenesten_Group', + 'fortroliggroup' => 'group_AD_Fortrolig_Adresse', + 'skjermedegroup' => 'Skjermede_Personer_AD' + } ); System.assertEquals( 2, From 1af859d2bf355b04fb04df89d2c7325a115f2fe7 Mon Sep 17 00:00:00 2001 From: Eugenijus Date: Mon, 10 Feb 2025 13:01:23 +0100 Subject: [PATCH 14/14] fix Code Analyzer --- .../default/classes/STO_GroupMemberSkillService.cls | 5 +++-- .../classes/STO_GroupMemberSkillService_Test.cls | 13 ++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/force-app/main/default/classes/STO_GroupMemberSkillService.cls b/force-app/main/default/classes/STO_GroupMemberSkillService.cls index d55cddfd..3d2aa5f6 100644 --- a/force-app/main/default/classes/STO_GroupMemberSkillService.cls +++ b/force-app/main/default/classes/STO_GroupMemberSkillService.cls @@ -43,6 +43,7 @@ public with sharing class STO_GroupMemberSkillService implements Callable { return userMap; } @TestVisible + @SuppressWarnings('PMD.ApexCRUDViolation') private Map initSkillIdMap() { skillIdMap = new Map(); for (Skill skill : [ @@ -185,7 +186,7 @@ public with sharing class STO_GroupMemberSkillService implements Callable { * @author Stian Ruud Schikora | 12-15-2021 * @param saveResList **/ - @testVisible + @TestVisible private void verifySkillinsert(List saveResList) { for (Database.SaveResult saveRes : saveResList) { if (!saveRes.isSuccess()) { @@ -205,7 +206,7 @@ public with sharing class STO_GroupMemberSkillService implements Callable { * @author Stian Ruud Schikora | 12-15-2021 * @param deleteResList **/ - @testVisible + @TestVisible private void verifySkillRemoval(List deleteResList) { for (Database.DeleteResult delRes : deleteResList) { if (!delRes.isSuccess()) { diff --git a/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls b/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls index 9f465e8b..08d745c2 100644 --- a/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls +++ b/force-app/main/default/classes/STO_GroupMemberSkillService_Test.cls @@ -100,7 +100,8 @@ public class STO_GroupMemberSkillService_Test { 'NKS_Skjermede_Personer_AD', 'Skjermede_Personer_AD' ) - ] + ], + 'Expected 2 groups for NKS user' ); Test.startTest(); service.handleGroupAndSkillSync(); @@ -157,7 +158,8 @@ public class STO_GroupMemberSkillService_Test { 'NKS_Skjermede_Personer_AD', 'Skjermede_Personer_AD' ) - ] + ], + 'Expected 2 groups for HOT users' ); Test.startTest(); service.handleGroupAndSkillSync(); @@ -206,7 +208,8 @@ public class STO_GroupMemberSkillService_Test { 'NKS_Skjermede_Personer_AD', 'Skjermede_Personer_AD' ) - ] + ], + 'Expected 2 groups for HOT users' ); Test.startTest(); try { @@ -303,9 +306,9 @@ public class STO_GroupMemberSkillService_Test { service.verifySkillRemoval(deleteResList); Test.stopTest(); - System.assertEquals(2, [SELECT COUNT() FROM Application_Log__c]); //Two errors should be logged + System.assertEquals(2, [SELECT COUNT() FROM Application_Log__c], 'Two errors should be logged'); } - @future + @Future private static void removeFromGroup(Id userId, String groupDevName) { delete [SELECT Id FROM GroupMember WHERE UserOrGroupId = :userId AND Group.DeveloperName = :groupDevName]; }