diff --git a/force-app/main/default/classes/CourseHandler.cls b/force-app/main/default/classes/CourseHandler.cls index 9fb4ffd1..0af3e99a 100644 --- a/force-app/main/default/classes/CourseHandler.cls +++ b/force-app/main/default/classes/CourseHandler.cls @@ -20,7 +20,7 @@ global with sharing class CourseHandler { Theme__c, AvailableSeats__c, MaxNumberOfParticipants__c, - NumberOfParticipants__c, + RegistrationSignupsCount__c, PublishWithoutRegistrationForm__c FROM Course__c WHERE Active__c = TRUE @@ -45,7 +45,7 @@ global with sharing class CourseHandler { wrapper.ShowInActivityList = course.Active__c ? 1 : 0; wrapper.AvailableSeats = course.AvailableSeats__c; wrapper.MaxNumberOfParticipants = course.MaxNumberOfParticipants__c; - wrapper.NumberOfParticipants = course.NumberOfParticipants__c; + wrapper.NumberOfParticipants = course.RegistrationSignupsCount__c; wrapper.PublishWithoutRegistrationForm = course.PublishWithoutRegistrationForm__c; wrapper.configurable_custom = new CourseApiModel.Configurable_custom(); diff --git a/force-app/main/default/classes/CourseRegistrationController.cls b/force-app/main/default/classes/CourseRegistrationController.cls index a74de079..761dc39b 100644 --- a/force-app/main/default/classes/CourseRegistrationController.cls +++ b/force-app/main/default/classes/CourseRegistrationController.cls @@ -63,7 +63,7 @@ public without sharing class CourseRegistrationController { Course__c = courseId ); - Decimal current = (course.NumberOfParticipants__c != null) ? course.NumberOfParticipants__c : 0; + Decimal current = (course.RegistrationSignupsCount__c != null) ? course.RegistrationSignupsCount__c : 0; Decimal maxCap = (course.MaxNumberOfParticipants__c != null) ? course.MaxNumberOfParticipants__c : 0; Decimal avail = maxCap - current; @@ -126,8 +126,8 @@ public without sharing class CourseRegistrationController { RegistrationPlaceName__c, Type__c, MaxNumberOfParticipants__c, - NumberOfParticipants__c, - Waitinglist__c, + RegistrationSignupsCount__c, + RegistrationWaitlistedCount__c, ShowCompany__c, ShowCounty__c, ShowRole__c, @@ -170,7 +170,7 @@ public without sharing class CourseRegistrationController { } try { Course__c course = [ - SELECT Name, NumberOfParticipants__c, MaxNumberOfParticipants__c, Cancel__c + SELECT Name, RegistrationSignupsCount__c, MaxNumberOfParticipants__c, Cancel__c FROM Course__c WHERE Id = :courseId LIMIT 1 diff --git a/force-app/main/default/classes/CourseRegistrationControllerTest.cls b/force-app/main/default/classes/CourseRegistrationControllerTest.cls index 56ba80e3..16dfa72a 100644 --- a/force-app/main/default/classes/CourseRegistrationControllerTest.cls +++ b/force-app/main/default/classes/CourseRegistrationControllerTest.cls @@ -125,9 +125,19 @@ private with sharing class CourseRegistrationControllerTest { @isTest static void testWaitlistLogic() { - Course__c c = new Course__c(Name = 'Full', MaxNumberOfParticipants__c = 1, NumberOfParticipants__c = 1); + Course__c c = new Course__c(Name = 'Full', MaxNumberOfParticipants__c = 1); insert c; + CourseRegistration__c existing = new CourseRegistration__c( + ContactFirstName__c = 'Existing', + ContactLastName__c = 'Attendee', + ContactEmail__c = 'existing@nav.no', + Course__c = c.Id, + Status__c = 'Påmeldt', + NumberOfParticipants__c = 1 + ); + insert existing; + CourseRegistrationModel mw = new CourseRegistrationModel(); mw.firstName = 'M'; mw.lastName = 'W'; @@ -160,7 +170,6 @@ private with sharing class CourseRegistrationControllerTest { RegistrationToDateTime__c = toDT, Type__c = 'Kurs', MaxNumberOfParticipants__c = 50, - Waitinglist__c = 1, ShowCompany__c = true, ShowCounty__c = true, ShowRole__c = true, @@ -168,6 +177,16 @@ private with sharing class CourseRegistrationControllerTest { ); insert c; + CourseRegistration__c waitlisted = new CourseRegistration__c( + ContactFirstName__c = 'Wait', + ContactLastName__c = 'List', + ContactEmail__c = 'wait@nav.no', + Course__c = c.Id, + Status__c = 'Venteliste', + NumberOfParticipants__c = 1 + ); + insert waitlisted; + Course__c f = CourseRegistrationController.getCourseFields(c.Id); System.assertEquals(c.Name, f.Name); System.assertEquals(c.Type__c, f.Type__c); @@ -175,7 +194,7 @@ private with sharing class CourseRegistrationControllerTest { System.assertEquals(c.RegistrationDeadline__c, f.RegistrationDeadline__c); System.assertEquals(c.RegistrationFromDateTime__c, f.RegistrationFromDateTime__c); System.assertEquals(c.RegistrationToDateTime__c, f.RegistrationToDateTime__c); - System.assertEquals(c.Waitinglist__c, f.Waitinglist__c); + System.assertEquals(1, Integer.valueOf(f.RegistrationWaitlistedCount__c)); } @IsTest @@ -202,4 +221,4 @@ private with sharing class CourseRegistrationControllerTest { System.assertEquals(0, accounts.size(), 'No accounts should be returned when the organization number is not found'); } -} +} \ No newline at end of file diff --git a/force-app/main/default/classes/CourseRegistrationControllerTest.cls-meta.xml b/force-app/main/default/classes/CourseRegistrationControllerTest.cls-meta.xml index b7090439..db9bf8c6 100644 --- a/force-app/main/default/classes/CourseRegistrationControllerTest.cls-meta.xml +++ b/force-app/main/default/classes/CourseRegistrationControllerTest.cls-meta.xml @@ -1,4 +1,4 @@ - + 48.0 Active diff --git a/force-app/main/default/classes/CourseRegistrationHandler.cls b/force-app/main/default/classes/CourseRegistrationHandler.cls index e0136f8a..20acfb65 100644 --- a/force-app/main/default/classes/CourseRegistrationHandler.cls +++ b/force-app/main/default/classes/CourseRegistrationHandler.cls @@ -30,9 +30,6 @@ global class CourseRegistrationHandler extends MyTriggers { global override void onAfterDelete() { List deletedRegistrations = (List) records; - if (deletedRegistrations != null && !deletedRegistrations.isEmpty()) { - CourseRegistrationHelper.getCourseIdToReduce(deletedRegistrations); - } Set courseIdsToCheckForPromotion = new Set(); if (deletedRegistrations != null) { for (CourseRegistration__c reg : deletedRegistrations) { @@ -46,10 +43,8 @@ global class CourseRegistrationHandler extends MyTriggers { } } global override void onAfterUndelete() { - CourseRegistrationHelper.getCourseIdToIncrease((List) records); } global override void onAfterInsert() { - CourseRegistrationHelper.getCourseIdToIncrease((List) records); } global override void onAfterUpdate(Map triggerOldMap) { diff --git a/force-app/main/default/classes/CourseRegistrationHandlerTest.cls b/force-app/main/default/classes/CourseRegistrationHandlerTest.cls index 7158ced8..521aec14 100644 --- a/force-app/main/default/classes/CourseRegistrationHandlerTest.cls +++ b/force-app/main/default/classes/CourseRegistrationHandlerTest.cls @@ -10,8 +10,20 @@ public with sharing class CourseRegistrationHandlerTest { Course__c course1 = getCourse('Testkurs'); Course__c course2 = getCourse('Testkurs2'); - System.assertEquals(null, course1.NumberOfParticipants__c, 'Should be 0 participants'); - System.assertEquals(null, course2.NumberOfParticipants__c, 'Should be 0 participants'); + System.assertEquals( + 0, + course1.RegistrationSignupsCount__c == null + ? 0 + : course1.RegistrationSignupsCount__c.intValue(), + 'Should be 0 participants' + ); + System.assertEquals( + 0, + course2.RegistrationSignupsCount__c == null + ? 0 + : course2.RegistrationSignupsCount__c.intValue(), + 'Should be 0 participants' + ); Test.StartTest(); CourseRegistration__c cr = getCourseRegistration('Påmeldt', course1.Id); @@ -22,9 +34,9 @@ public with sharing class CourseRegistrationHandlerTest { Course__c course1After = fetchCourse('Testkurs'); Course__c course2After = fetchCourse('Testkurs2'); - System.assertEquals(1, Integer.valueOf(course1After.NumberOfParticipants__c), 'Should be 1 participant'); - System.assertEquals(1, Integer.valueOf(course2After.NumberOfParticipants__c), 'Should be 1 participant'); - System.assertEquals(1, Integer.valueOf(course2After.WaitingList__c), 'Should be 1 on waitinglist'); + System.assertEquals(1, Integer.valueOf(course1After.RegistrationSignupsCount__c), 'Should be 1 participant'); + System.assertEquals(1, Integer.valueOf(course2After.RegistrationSignupsCount__c), 'Should be 1 participant'); + System.assertEquals(1, Integer.valueOf(course2After.RegistrationWaitlistedCount__c), 'Should be 1 on waitinglist'); } @isTest private static void testDelete() { @@ -43,7 +55,7 @@ public with sharing class CourseRegistrationHandlerTest { System.assertEquals(0, crListDel.size(), 'Should be 0 registrations'); Course__c courseAfter = fetchCourse('Testkurs'); - System.assertEquals(0, Integer.valueOf(courseAfter.NumberOfParticipants__c), 'Should be 0 participants'); + System.assertEquals(0, Integer.valueOf(courseAfter.RegistrationSignupsCount__c), 'Should be 0 participants'); } @isTest private static void testUnDelete() { @@ -63,7 +75,7 @@ public with sharing class CourseRegistrationHandlerTest { System.assertEquals(2, crListUnDel.size(), 'Should be 2 registrations'); Course__c courseAfter = fetchCourse('Testkurs'); - System.assertEquals(2, Integer.valueOf(courseAfter.NumberOfParticipants__c), 'Should be 2 participants'); + System.assertEquals(2, Integer.valueOf(courseAfter.RegistrationSignupsCount__c), 'Should be 2 participants'); } @isTest @@ -77,7 +89,7 @@ public with sharing class CourseRegistrationHandlerTest { Test.StopTest(); Course__c courseAfter = fetchCourse('Testkurs'); - System.assertEquals(0, Integer.valueOf(courseAfter.NumberOfParticipants__c), 'Should be 0 participants'); + System.assertEquals(0, Integer.valueOf(courseAfter.RegistrationSignupsCount__c), 'Should be 0 participants'); } @isTest @@ -91,7 +103,7 @@ public with sharing class CourseRegistrationHandlerTest { Test.StopTest(); Course__c courseAfter = fetchCourse('Testkurs'); - System.assertEquals(1, Integer.valueOf(courseAfter.NumberOfParticipants__c), 'Should be 1 participant'); + System.assertEquals(1, Integer.valueOf(courseAfter.RegistrationSignupsCount__c), 'Should be 1 participant'); } @isTest @@ -105,8 +117,8 @@ public with sharing class CourseRegistrationHandlerTest { Test.StopTest(); Course__c courseAfter = fetchCourse('Testkurs'); - System.assertEquals(0, Integer.valueOf(courseAfter.NumberOfParticipants__c), 'Should be 0 participants'); - System.assertEquals(1, Integer.valueOf(courseAfter.WaitingList__c), 'Should be 1 on waiting list'); + System.assertEquals(0, Integer.valueOf(courseAfter.RegistrationSignupsCount__c), 'Should be 0 participants'); + System.assertEquals(1, Integer.valueOf(courseAfter.RegistrationWaitlistedCount__c), 'Should be 1 on waiting list'); } @isTest @@ -120,8 +132,8 @@ public with sharing class CourseRegistrationHandlerTest { Test.StopTest(); Course__c courseAfter = fetchCourse('Testkurs'); - System.assertEquals(1, Integer.valueOf(courseAfter.NumberOfParticipants__c), 'Should be 1 participant'); - System.assertEquals(0, Integer.valueOf(courseAfter.WaitingList__c), 'Should be 0 on waiting list'); + System.assertEquals(1, Integer.valueOf(courseAfter.RegistrationSignupsCount__c), 'Should be 1 participant'); + System.assertEquals(0, Integer.valueOf(courseAfter.RegistrationWaitlistedCount__c), 'Should be 0 on waiting list'); } @isTest private static void updateOneWaiting_toOneNotAttending() { @@ -134,8 +146,8 @@ public with sharing class CourseRegistrationHandlerTest { Test.StopTest(); Course__c courseAfter = fetchCourse('Testkurs'); - System.assertEquals(0, Integer.valueOf(courseAfter.NumberOfParticipants__c), 'Should be 0 participants'); - System.assertEquals(0, Integer.valueOf(courseAfter.WaitingList__c), 'Should be 0 on waiting list'); + System.assertEquals(0, Integer.valueOf(courseAfter.RegistrationSignupsCount__c), 'Should be 0 participants'); + System.assertEquals(0, Integer.valueOf(courseAfter.RegistrationWaitlistedCount__c), 'Should be 0 on waiting list'); } @isTest @@ -151,7 +163,7 @@ public with sharing class CourseRegistrationHandlerTest { Test.StopTest(); Course__c courseAfter = fetchCourse('Testkurs'); - System.assertEquals(0, Integer.valueOf(courseAfter.NumberOfParticipants__c), 'Should be 0 participants'); + System.assertEquals(0, Integer.valueOf(courseAfter.RegistrationSignupsCount__c), 'Should be 0 participants'); } @isTest @@ -167,7 +179,7 @@ public with sharing class CourseRegistrationHandlerTest { Test.StopTest(); Course__c courseAfter = fetchCourse('Testkurs'); - System.assertEquals(2, Integer.valueOf(courseAfter.NumberOfParticipants__c), 'Should be 2 participants'); + System.assertEquals(2, Integer.valueOf(courseAfter.RegistrationSignupsCount__c), 'Should be 2 participants'); } @isTest @@ -183,8 +195,8 @@ public with sharing class CourseRegistrationHandlerTest { Test.StopTest(); Course__c courseAfter = fetchCourse('Testkurs'); - System.assertEquals(0, Integer.valueOf(courseAfter.NumberOfParticipants__c), 'Should be 0 participants'); - System.assertEquals(2, Integer.valueOf(courseAfter.WaitingList__c), 'Should be 2 on waiting list'); + System.assertEquals(0, Integer.valueOf(courseAfter.RegistrationSignupsCount__c), 'Should be 0 participants'); + System.assertEquals(2, Integer.valueOf(courseAfter.RegistrationWaitlistedCount__c), 'Should be 2 on waiting list'); } @isTest @@ -200,8 +212,8 @@ public with sharing class CourseRegistrationHandlerTest { Test.StopTest(); Course__c courseAfter = fetchCourse('Testkurs'); - System.assertEquals(2, Integer.valueOf(courseAfter.NumberOfParticipants__c), 'Should be 2 participants'); - System.assertEquals(0, Integer.valueOf(courseAfter.WaitingList__c), 'Should be 0 on waiting list'); + System.assertEquals(2, Integer.valueOf(courseAfter.RegistrationSignupsCount__c), 'Should be 2 participants'); + System.assertEquals(0, Integer.valueOf(courseAfter.RegistrationWaitlistedCount__c), 'Should be 0 on waiting list'); } @isTest @@ -217,8 +229,8 @@ public with sharing class CourseRegistrationHandlerTest { Test.StopTest(); Course__c courseAfter = fetchCourse('Testkurs'); - System.assertEquals(0, Integer.valueOf(courseAfter.NumberOfParticipants__c), 'Should be 0 participants'); - System.assertEquals(0, Integer.valueOf(courseAfter.WaitingList__c), 'Should be 0 on waiting list'); + System.assertEquals(0, Integer.valueOf(courseAfter.RegistrationSignupsCount__c), 'Should be 0 participants'); + System.assertEquals(0, Integer.valueOf(courseAfter.RegistrationWaitlistedCount__c), 'Should be 0 on waiting list'); } @isTest @@ -236,8 +248,8 @@ public with sharing class CourseRegistrationHandlerTest { Course__c course1After = fetchCourse('Testkurs'); Course__c course2After = fetchCourse('Testkurs2'); - System.assertEquals(0, Integer.valueOf(course1After.NumberOfParticipants__c), 'Should be 0 participants'); - System.assertEquals(0, Integer.valueOf(course2After.NumberOfParticipants__c), 'Should be 0 participants'); + System.assertEquals(0, Integer.valueOf(course1After.RegistrationSignupsCount__c), 'Should be 0 participants'); + System.assertEquals(0, Integer.valueOf(course2After.RegistrationSignupsCount__c), 'Should be 0 participants'); } @isTest @@ -255,8 +267,8 @@ public with sharing class CourseRegistrationHandlerTest { Course__c course1After = fetchCourse('Testkurs'); Course__c course2After = fetchCourse('Testkurs2'); - System.assertEquals(1, Integer.valueOf(course1After.NumberOfParticipants__c), 'Should be 1 participant'); - System.assertEquals(1, Integer.valueOf(course2After.NumberOfParticipants__c), 'Should be 1 participant'); + System.assertEquals(1, Integer.valueOf(course1After.RegistrationSignupsCount__c), 'Should be 1 participant'); + System.assertEquals(1, Integer.valueOf(course2After.RegistrationSignupsCount__c), 'Should be 1 participant'); } @isTest @@ -280,15 +292,15 @@ public with sharing class CourseRegistrationHandlerTest { Course__c course2After = fetchCourse('Testkurs2'); String cr2IdStatus = [SELECT Id, Status__c FROM CourseRegistration__c WHERE Id = :cr2.Id LIMIT 1].Status__c; String cr4IdStatus = [SELECT Id, Status__c FROM CourseRegistration__c WHERE Id = :cr4.Id LIMIT 1].Status__c; - System.debug('1 after >>' + course1After.NumberOfParticipants__c); - System.debug('c after >>' + course2After.NumberOfParticipants__c); + System.debug('1 after >>' + course1After.RegistrationSignupsCount__c); + System.debug('c after >>' + course2After.RegistrationSignupsCount__c); System.debug('c after >>' + cr2IdStatus); System.debug('c after >>' + cr4IdStatus); - System.assertEquals(1, Integer.valueOf(course1After.NumberOfParticipants__c), 'Should be 1 participant'); - System.assertEquals(0, Integer.valueOf(course1After.WaitingList__c), 'Should be 0 on waiting list'); - System.assertEquals(1, Integer.valueOf(course2After.NumberOfParticipants__c), 'Should be 1 participant'); - System.assertEquals(1, Integer.valueOf(course2After.WaitingList__c), 'Should be 1 on waiting list'); + System.assertEquals(1, Integer.valueOf(course1After.RegistrationSignupsCount__c), 'Should be 1 participant'); + System.assertEquals(0, Integer.valueOf(course1After.RegistrationWaitlistedCount__c), 'Should be 0 on waiting list'); + System.assertEquals(1, Integer.valueOf(course2After.RegistrationSignupsCount__c), 'Should be 1 participant'); + System.assertEquals(1, Integer.valueOf(course2After.RegistrationWaitlistedCount__c), 'Should be 1 on waiting list'); System.assertEquals('Påmeldt', cr2IdStatus, 'cr2 should have Påmeldt status'); System.assertEquals('Påmeldt', cr4IdStatus, 'cr4 should have Påmeldt status'); } @@ -300,7 +312,8 @@ public with sharing class CourseRegistrationHandlerTest { ContactPhone__c = '99887766', ContactEmail__c = 'per.hansen@test.no', Course__c = courseId, - Status__c = status + Status__c = status, + NumberOfParticipants__c = 1 ); insert cr; return cr; @@ -329,11 +342,11 @@ public with sharing class CourseRegistrationHandlerTest { public static Course__c fetchCourse(String courseName) { Course__c course = [ - SELECT Id, NumberOfParticipants__c, WaitingList__c + SELECT Id, RegistrationSignupsCount__c, RegistrationWaitlistedCount__c FROM Course__c WHERE Name = :courseName LIMIT 1 ]; return course; } -} +} \ No newline at end of file diff --git a/force-app/main/default/classes/CourseRegistrationHelper.cls b/force-app/main/default/classes/CourseRegistrationHelper.cls index 53e994a6..457f278d 100644 --- a/force-app/main/default/classes/CourseRegistrationHelper.cls +++ b/force-app/main/default/classes/CourseRegistrationHelper.cls @@ -1,244 +1,139 @@ public class CourseRegistrationHelper { + private static Integer resolveParticipantCount(CourseRegistration__c registration) { + if (registration == null) { + return 0; + } + if (registration.NumberOfParticipants__c == null || registration.NumberOfParticipants__c < 1) { + return 1; + } + return registration.NumberOfParticipants__c.intValue(); + } + + private static Boolean countsTowardsCapacity(CourseRegistration__c registration) { + return registration != null && registration.Status__c == 'Påmeldt'; + } + public static void validateRegistrationsAgainstCourseCapacity( List registrationsToValidate, Map oldRegistrationsMap ) { - Set courseIds = new Set(); - List regsRequiringValidation = new List(); - - for (CourseRegistration__c cr : registrationsToValidate) { - Boolean needsValidation = (oldRegistrationsMap == null || oldRegistrationsMap.get(cr.Id) == null); - if (!needsValidation && oldRegistrationsMap != null && oldRegistrationsMap.get(cr.Id) != null) { - CourseRegistration__c oldCr = oldRegistrationsMap.get(cr.Id); - if (cr.Course__c != oldCr.Course__c || cr.NumberOfParticipants__c != oldCr.NumberOfParticipants__c) { - needsValidation = true; - } - } - - // Only validate if relevant fields are populated and validation is determined to be needed. - if ( - needsValidation && - cr.Course__c != null && - cr.NumberOfParticipants__c != null && - cr.NumberOfParticipants__c > 0 - ) { - courseIds.add(cr.Course__c); - regsRequiringValidation.add(cr); - } - } - - if (regsRequiringValidation.isEmpty()) { + if (registrationsToValidate == null || registrationsToValidate.isEmpty()) { return; } - // Query for course capacities - Map coursesWithCapacity = new Map(); - if (!courseIds.isEmpty()) { - for (Course__c course : [SELECT Id, MaxNumberOfParticipants__c FROM Course__c WHERE Id IN :courseIds]) { - coursesWithCapacity.put(course.Id, course); - } - } + Map safeOldMap = oldRegistrationsMap == null + ? new Map() + : oldRegistrationsMap; - // Perform the validation - for (CourseRegistration__c cr : regsRequiringValidation) { - Course__c relatedCourse = coursesWithCapacity.get(cr.Course__c); - - if (relatedCourse != null) { - if (relatedCourse.MaxNumberOfParticipants__c != null && relatedCourse.MaxNumberOfParticipants__c > 0) { - if (cr.NumberOfParticipants__c > relatedCourse.MaxNumberOfParticipants__c) { - cr.addError( - 'Antall deltakere (' + - cr.NumberOfParticipants__c.intValue() + - ') for denne påmeldingen overstiger kursets maksimale kapasitet (' + - relatedCourse.MaxNumberOfParticipants__c.intValue() + - '). Vennligst reduser antall deltakere. ' + - 'Hvis gruppen din er større enn kursets kapasitet og du ønsker at noen skal settes på venteliste, ' + - 'kan det hende du må opprette flere, mindre påmeldinger.' - ); - } - } else { - System.debug( - LoggingLevel.WARN, - 'CourseRegistrationHelper: MaxNumberOfParticipants__c is not defined or not positive for Course ID ' + - relatedCourse.Id + - '. Skipping capacity validation for Registration ID ' + - cr.Id - ); - } - } else { - System.debug( - LoggingLevel.WARN, - 'CourseRegistrationHelper: Could not find Course details for Registration ID ' + - cr.Id + - ' with Course__c = ' + - cr.Course__c + - '. Skipping capacity validation.' - ); - } - } - } - - private static void processCourseRegistrations( - List registrations, - Boolean isIncreaseOperation // true for increase, false for reduce - ) { - List regsForAttending = new List(); - List regsForWaiting = new List(); - - for (CourseRegistration__c cr : registrations) { - if (cr.Status__c == 'Påmeldt') { - regsForAttending.add(cr); - } else if (cr.Status__c == 'Venteliste') { - regsForWaiting.add(cr); - } - } + Set courseIds = new Set(); + Map courseDelta = new Map(); + Map> courseToIncreasingRegistrations = new Map>(); - if (!regsForAttending.isEmpty()) { - if (isIncreaseOperation) { - countCourseIdsToIncreaseAttending(regsForAttending); - } else { - countCourseIdsToReduceAttending(regsForAttending); - } - } - if (!regsForWaiting.isEmpty()) { - if (isIncreaseOperation) { - countCourseIdsToIncreaseWaiting(regsForWaiting); - } else { - countCourseIdsToReduceWaiting(regsForWaiting); + for (CourseRegistration__c cr : registrationsToValidate) { + if (cr == null) { + continue; } - } - } - public static void getCourseIdToReduce(List registrations) { - processCourseRegistrations(registrations, false); // false indicates a reduction - } + Id newCourseId = cr.Course__c; + Integer newParticipants = resolveParticipantCount(cr); + Boolean newCounts = countsTowardsCapacity(cr); + Decimal newContribution = (newCourseId != null && newCounts) ? Decimal.valueOf(newParticipants) : 0; - public static void getCourseIdToIncrease(List registrations) { - processCourseRegistrations(registrations, true); // true indicates an increase - } + CourseRegistration__c oldCr = safeOldMap.get(cr.Id); + Id oldCourseId = oldCr != null ? oldCr.Course__c : null; + Integer oldParticipants = resolveParticipantCount(oldCr); + Boolean oldCounts = countsTowardsCapacity(oldCr); + Decimal oldContribution = (oldCourseId != null && oldCounts) ? Decimal.valueOf(oldParticipants) : 0; - // Private consolidated helper for accumulating participant changes into a map. - private static void accumulateParticipantChanges( - List registrations, - Map changeMap, - boolean isPositiveIncrement // true for +N (increase), false for -N (reduce) - ) { - for (CourseRegistration__c cr : registrations) { - Integer numParticipants = (cr.NumberOfParticipants__c == null || - cr.NumberOfParticipants__c < 1) - ? 1 - : cr.NumberOfParticipants__c.intValue(); - - Integer currentChange = changeMap.get(cr.Course__c); - if (currentChange == null) { - currentChange = 0; + if (oldCourseId != null && oldContribution > 0) { + Decimal existingDelta = courseDelta.containsKey(oldCourseId) ? courseDelta.get(oldCourseId) : 0; + courseDelta.put(oldCourseId, existingDelta - oldContribution); + courseIds.add(oldCourseId); } - if (isPositiveIncrement) { - changeMap.put(cr.Course__c, currentChange + numParticipants); - } else { - changeMap.put(cr.Course__c, currentChange - numParticipants); - } - } - } + if (newCourseId != null && newContribution > 0) { + Decimal existingDelta = courseDelta.containsKey(newCourseId) ? courseDelta.get(newCourseId) : 0; + courseDelta.put(newCourseId, existingDelta + newContribution); + courseIds.add(newCourseId); - public static void countCourseIdsToReduceAttending(List registrationsToReduce) { - Map courseParticipantChanges = new Map(); - accumulateParticipantChanges(registrationsToReduce, courseParticipantChanges, false); // false for reduce - if (!courseParticipantChanges.isEmpty()) { - updateCoursesParticipants(courseParticipantChanges); - } - } + Boolean increasesOccupancy = true; + if (oldCourseId != null && oldCourseId == newCourseId) { + increasesOccupancy = newContribution > oldContribution; + } - public static void countCourseIdsToIncreaseAttending(List registrationsToIncrease) { - Map courseParticipantChanges = new Map(); - accumulateParticipantChanges(registrationsToIncrease, courseParticipantChanges, true); // true for increase - if (!courseParticipantChanges.isEmpty()) { - updateCoursesParticipants(courseParticipantChanges); + if (increasesOccupancy) { + List regsForCourse = courseToIncreasingRegistrations.containsKey(newCourseId) + ? courseToIncreasingRegistrations.get(newCourseId) + : new List(); + regsForCourse.add(cr); + courseToIncreasingRegistrations.put(newCourseId, regsForCourse); + } + } else if (newCourseId != null) { + courseIds.add(newCourseId); + } } - } - public static void updateCoursesParticipants(Map coursesCountChanges) { - if (coursesCountChanges == null || coursesCountChanges.isEmpty()) + if (courseIds.isEmpty()) { return; + } - List coursesToUpdate = new List(); + Map coursesWithCapacity = new Map(); for (Course__c course : [ - SELECT Id, NumberOfParticipants__c + SELECT Id, MaxNumberOfParticipants__c, RegistrationSignupsCount__c FROM Course__c - WHERE Id IN :coursesCountChanges.keySet() + WHERE Id IN :courseIds ]) { - Decimal currentParticipants = course.NumberOfParticipants__c == null ? 0 : course.NumberOfParticipants__c; - Integer change = coursesCountChanges.get(course.Id); - - course.NumberOfParticipants__c = currentParticipants + change; - if (course.NumberOfParticipants__c < 0) { - course.NumberOfParticipants__c = 0; - } - coursesToUpdate.add(course); + coursesWithCapacity.put(course.Id, course); } - if (!coursesToUpdate.isEmpty()) { - try { - update coursesToUpdate; - } catch (Exception e) { + for (Id courseId : courseIds) { + Course__c relatedCourse = coursesWithCapacity.get(courseId); + if (relatedCourse == null) { System.debug( - LoggingLevel.ERROR, - 'Error updating course participants: ' + - e.getMessage() + - ' Stacktrace: ' + - e.getStackTraceString() + LoggingLevel.WARN, + 'CourseRegistrationHelper: Could not find Course details for Course ID ' + courseId ); + continue; } - } - } - public static void countCourseIdsToReduceWaiting(List registrationsToReduce) { - Map courseWaitlistChanges = new Map(); - accumulateParticipantChanges(registrationsToReduce, courseWaitlistChanges, false); // false for reduce - if (!courseWaitlistChanges.isEmpty()) { - updateCourseWaiting(courseWaitlistChanges); - } - } + Decimal maxCapacity = relatedCourse.MaxNumberOfParticipants__c == null + ? 0 + : relatedCourse.MaxNumberOfParticipants__c; + if (maxCapacity <= 0) { + continue; + } - public static void countCourseIdsToIncreaseWaiting(List registrationsToIncrease) { - Map courseWaitlistChanges = new Map(); - accumulateParticipantChanges(registrationsToIncrease, courseWaitlistChanges, true); // true for increase - if (!courseWaitlistChanges.isEmpty()) { - updateCourseWaiting(courseWaitlistChanges); - } - } + Decimal currentSignups = relatedCourse.RegistrationSignupsCount__c == null + ? 0 + : relatedCourse.RegistrationSignupsCount__c; + Decimal netDelta = courseDelta.containsKey(courseId) ? courseDelta.get(courseId) : 0; + if (netDelta <= 0) { + continue; + } - public static void updateCourseWaiting(Map coursesWaitlistChanges) { - if (coursesWaitlistChanges == null || coursesWaitlistChanges.isEmpty()) - return; + Decimal projectedSignups = currentSignups + netDelta; + if (projectedSignups <= maxCapacity) { + continue; + } - List coursesToUpdate = new List(); - for (Course__c course : [ - SELECT Id, Waitinglist__c - FROM Course__c - WHERE Id IN :coursesWaitlistChanges.keySet() - ]) { - Decimal currentWaitlist = course.Waitinglist__c == null ? 0 : course.Waitinglist__c; - Integer change = coursesWaitlistChanges.get(course.Id); + Decimal availableSeatsDecimal = maxCapacity - currentSignups; + Integer availableSeats = availableSeatsDecimal > 0 ? availableSeatsDecimal.intValue() : 0; + List impactedRegistrations = courseToIncreasingRegistrations.get(courseId); - course.Waitinglist__c = currentWaitlist + change; - if (course.Waitinglist__c < 0) { - course.Waitinglist__c = 0; + if (impactedRegistrations == null || impactedRegistrations.isEmpty()) { + continue; } - coursesToUpdate.add(course); - } - if (!coursesToUpdate.isEmpty()) { - try { - update coursesToUpdate; - } catch (Exception e) { - System.debug( - LoggingLevel.ERROR, - 'Error updating course waitlist: ' + - e.getMessage() + - ' Stacktrace: ' + - e.getStackTraceString() + for (CourseRegistration__c cr : impactedRegistrations) { + Integer regParticipants = resolveParticipantCount(cr); + cr.addError( + 'Antall deltakere (' + + regParticipants + + ') for denne påmeldingen overstiger tilgjengelige plasser (' + + availableSeats + + ') på kurset (maks ' + + maxCapacity.intValue() + + '). Vennligst reduser antall deltakere eller sett påmeldingen på venteliste.' ); } } @@ -247,7 +142,7 @@ public class CourseRegistrationHelper { public static void countCourseIdsToCheckWaiting(Set courseIds) { if (courseIds == null || courseIds.isEmpty()) return; - updateCourseWaitlistPromotions(courseIds); + System.enqueueJob(new CourseWaitlistPromotionJob(new List(courseIds))); } public static void updateCourseWaitlistPromotions(Set courseIdsToProcess) { @@ -257,7 +152,7 @@ public class CourseRegistrationHelper { List registrationsToPromote = new List(); List courses = [ - SELECT Id, NumberOfParticipants__c, Waitinglist__c, MaxNumberOfParticipants__c + SELECT Id, RegistrationSignupsCount__c, RegistrationWaitlistedCount__c, MaxNumberOfParticipants__c FROM Course__c WHERE Id IN :courseIdsToProcess ]; @@ -273,12 +168,12 @@ public class CourseRegistrationHelper { continue; } - Decimal currentParticipants = currentCourse.NumberOfParticipants__c == null + Decimal currentParticipants = currentCourse.RegistrationSignupsCount__c == null ? 0 - : currentCourse.NumberOfParticipants__c; - Decimal currentWaitlistParticipants = currentCourse.Waitinglist__c == null + : currentCourse.RegistrationSignupsCount__c; + Decimal currentWaitlistParticipants = currentCourse.RegistrationWaitlistedCount__c == null ? 0 - : currentCourse.Waitinglist__c; + : currentCourse.RegistrationWaitlistedCount__c; Decimal maxCapacity = currentCourse.MaxNumberOfParticipants__c; if (currentWaitlistParticipants <= 0) diff --git a/force-app/main/default/classes/CourseRegistrationHelperTest.cls b/force-app/main/default/classes/CourseRegistrationHelperTest.cls index d91b746e..5f6dc1f3 100644 --- a/force-app/main/default/classes/CourseRegistrationHelperTest.cls +++ b/force-app/main/default/classes/CourseRegistrationHelperTest.cls @@ -5,177 +5,112 @@ public with sharing class CourseRegistrationHelperTest { TestDataFactory.insertEncryptionKey(); } - private static CourseRegistration__c newReg(String status, Id courseId, Integer participants) { - CourseRegistration__c cr = CourseRegistrationHandlerTest.getCourseRegistration(status, courseId); - if (participants != null) { - cr.NumberOfParticipants__c = participants; - update cr; - } - return cr; - } - /* ---------- capacity validation ---------- */ - @isTest - static void testValidateRegistrationsAgainstCourseCapacity() { - Course__c c = CourseRegistrationHandlerTest.getCourse('Testkurs'); - c.MaxNumberOfParticipants__c = 2; - update c; - - CourseRegistration__c regOk = new CourseRegistration__c( - Course__c = c.Id, - Status__c = 'Invitert', - NumberOfParticipants__c = 2 - ); - CourseRegistration__c regOver = new CourseRegistration__c( - Course__c = c.Id, - Status__c = 'Invitert', - NumberOfParticipants__c = 3 + private static Course__c createCourse(Integer maxSeats) { + Course__c course = new Course__c( + Name = 'Helper Test ' + String.valueOf(Math.random()), + MaxNumberOfParticipants__c = maxSeats, + DescriptionFormatted__c = 'desc', + Active__c = true ); + insert course; + return course; + } - List regs = new List{ regOk, regOver }; - - Test.startTest(); - CourseRegistrationHelper.validateRegistrationsAgainstCourseCapacity(regs, null); - Test.stopTest(); - - System.assertEquals(0, regOk.getErrors().size(), 'Registration at or below capacity should pass validation'); - System.assertEquals(1, regOver.getErrors().size(), 'Registration exceeding capacity should be blocked'); - System.assert( - regOver.getErrors()[0].getMessage().contains('overstiger'), - 'Error message should mention capacity exceeded' + private static CourseRegistration__c createRegistration(Id courseId, String status, Integer participants) { + CourseRegistration__c registration = new CourseRegistration__c( + ContactFirstName__c = 'Test', + ContactLastName__c = 'User', + ContactEmail__c = String.valueOf(Math.random()) + '@example.com', + Course__c = courseId, + Status__c = status, + NumberOfParticipants__c = participants ); + insert registration; + return registration; } - /* ---------- ATTENDING counters ---------- */ - @isTest - static void testCountCourseIdsToReduceAttending() { - Course__c c = CourseRegistrationHandlerTest.getCourse('Testkurs'); - c.NumberOfParticipants__c = 5; - update c; + static void testCapacityValidationAllowsWithinLimit() { + Course__c course = createCourse(5); - List regs = new List{ - newReg('Invitert', c.Id, 1), - newReg('Invitert', c.Id, 1) - }; + CourseRegistration__c pending = new CourseRegistration__c( + Course__c = course.Id, + Status__c = 'Påmeldt', + NumberOfParticipants__c = 3 + ); - Test.startTest(); - CourseRegistrationHelper.countCourseIdsToReduceAttending(regs); - Test.stopTest(); + CourseRegistrationHelper.validateRegistrationsAgainstCourseCapacity( + new List{ pending }, + null + ); System.assertEquals( - 3, - Integer.valueOf(CourseRegistrationHandlerTest.fetchCourse('Testkurs').NumberOfParticipants__c) + 0, + pending.getErrors().size(), + 'Validation should not block registration when capacity allows' ); } @isTest - static void testCountCourseIdsToIncreaseAttending() { - Course__c c = CourseRegistrationHandlerTest.getCourse('Testkurs'); + static void testCapacityValidationBlocksWhenExceedingLimitWithExistingRegistrations() { + Course__c course = createCourse(3); + createRegistration(course.Id, 'Påmeldt', 2); - List regs = new List{ - newReg('Invitert', c.Id, 1), - newReg('Invitert', c.Id, 1) - }; + CourseRegistration__c pending = new CourseRegistration__c( + Course__c = course.Id, + Status__c = 'Påmeldt', + NumberOfParticipants__c = 2 + ); - Test.startTest(); - CourseRegistrationHelper.countCourseIdsToIncreaseAttending(regs); - Test.stopTest(); + CourseRegistrationHelper.validateRegistrationsAgainstCourseCapacity( + new List{ pending }, + null + ); System.assertEquals( - 2, - Integer.valueOf(CourseRegistrationHandlerTest.fetchCourse('Testkurs').NumberOfParticipants__c) + 1, + pending.getErrors().size(), + 'Validation should block registrations that exceed remaining seats' + ); + System.assert( + pending.getErrors()[0].getMessage().contains('overstiger'), + 'Error message should explain that the capacity is exceeded' ); } - /* ---------- WAITLIST counters ---------- */ - @isTest - static void testCountCourseIdsToReduceWaiting() { - Course__c c = CourseRegistrationHandlerTest.getCourse('Testkurs'); - c.Waitinglist__c = 5; - update c; - - List regs = new List{ - newReg('Invitert', c.Id, 1), - newReg('Invitert', c.Id, 1) - }; - - Test.startTest(); - CourseRegistrationHelper.countCourseIdsToReduceWaiting(regs); - Test.stopTest(); + static void testUpdateCourseWaitlistPromotions() { + Course__c course = createCourse(2); + CourseRegistration__c firstAttendee = createRegistration(course.Id, 'Påmeldt', 1); + createRegistration(course.Id, 'Påmeldt', 1); - System.assertEquals(3, Integer.valueOf(CourseRegistrationHandlerTest.fetchCourse('Testkurs').Waitinglist__c)); - } - - @isTest - static void testCountCourseIdsToIncreaseWaiting() { - Course__c c = CourseRegistrationHandlerTest.getCourse('Testkurs'); + CourseRegistration__c waitlistOldest = createRegistration(course.Id, 'Venteliste', 1); + CourseRegistration__c waitlistNewest = createRegistration(course.Id, 'Venteliste', 1); - List regs = new List{ - newReg('Invitert', c.Id, 1), - newReg('Invitert', c.Id, 1) - }; + firstAttendee.Status__c = 'Avmeldt'; + update firstAttendee; Test.startTest(); - CourseRegistrationHelper.countCourseIdsToIncreaseWaiting(regs); + CourseRegistrationHelper.countCourseIdsToCheckWaiting(new Set{ course.Id }); Test.stopTest(); - System.assertEquals(2, Integer.valueOf(CourseRegistrationHandlerTest.fetchCourse('Testkurs').Waitinglist__c)); - } - - /* ---------- direct update helpers ---------- */ - - @isTest - static void testUpdateCoursesParticipants() { - Course__c c = CourseRegistrationHandlerTest.getCourse('Testkurs'); - - Test.startTest(); - CourseRegistrationHelper.updateCoursesParticipants(new Map{ c.Id => 5 }); - Test.stopTest(); + Map refreshed = new Map( + [ + SELECT Status__c + FROM CourseRegistration__c + WHERE Id IN :new List{ waitlistOldest.Id, waitlistNewest.Id } + ] + ); System.assertEquals( - 5, - Integer.valueOf(CourseRegistrationHandlerTest.fetchCourse('Testkurs').NumberOfParticipants__c) + 'Påmeldt', + refreshed.get(waitlistOldest.Id).Status__c, + 'Oldest waitlisted registration should be promoted' ); - } - - @isTest - static void testUpdateCourseWaiting() { - Course__c c = CourseRegistrationHandlerTest.getCourse('Testkurs'); - c.Waitinglist__c = 5; - update c; - - Test.startTest(); - CourseRegistrationHelper.updateCourseWaiting(new Map{ c.Id => -2 }); - Test.stopTest(); - - System.assertEquals(3, Integer.valueOf(CourseRegistrationHandlerTest.fetchCourse('Testkurs').Waitinglist__c)); - } - - /* ---------- wait-list promotion end-to-end ---------- */ - - @isTest - static void testWaitingListFunction() { - Course__c c = CourseRegistrationHandlerTest.getCourse('Testkurs'); - - // 2 attending, 2 wait-listed - CourseRegistration__c r1 = newReg('Påmeldt', c.Id, 1); - CourseRegistration__c r2 = newReg('Påmeldt', c.Id, 1); - CourseRegistration__c r3 = newReg('Venteliste', c.Id, 1); - CourseRegistration__c r4 = newReg('Venteliste', c.Id, 1); - - Course__c before = CourseRegistrationHandlerTest.fetchCourse('Testkurs'); - System.assertEquals(2, before.NumberOfParticipants__c); - System.assertEquals(2, before.Waitinglist__c); - - Test.startTest(); - CourseRegistrationHelper.countCourseIdsToCheckWaiting(new Set{ c.Id }); - Test.stopTest(); - - Map afterRegs = new Map( - [SELECT Status__c FROM CourseRegistration__c WHERE Id IN :new List{ r3.Id, r4.Id }] + System.assertEquals( + 'Venteliste', + refreshed.get(waitlistNewest.Id).Status__c, + 'Only one waitlisted registration should be promoted' ); - System.assertEquals('Påmeldt', afterRegs.get(r3.Id).Status__c); - System.assertEquals('Påmeldt', afterRegs.get(r4.Id).Status__c); } -} +} \ No newline at end of file diff --git a/force-app/main/default/classes/CourseRegistrationUpdateHelper.cls b/force-app/main/default/classes/CourseRegistrationUpdateHelper.cls index 7982e83a..f5a2e9ab 100644 --- a/force-app/main/default/classes/CourseRegistrationUpdateHelper.cls +++ b/force-app/main/default/classes/CourseRegistrationUpdateHelper.cls @@ -1,62 +1,57 @@ public class CourseRegistrationUpdateHelper { public static void updateHelper(List newRecords, Map triggerOldMap) { + if (newRecords == null || newRecords.isEmpty()) { + return; + } + Map oldMap = triggerOldMap == null ? new Map() : new Map((List) triggerOldMap.values()); - List crsToRemoveOldContribution = new List(); - List crsToAddNewContribution = new List(); - Set coursesToCheckWaitlist = new Set(); for (CourseRegistration__c newCr : newRecords) { - CourseRegistration__c oldCr = oldMap.get(newCr.Id); - - boolean relevantChangeOccurred = false; - if (newCr.Status__c != oldCr.Status__c) { - relevantChangeOccurred = true; + if (newCr == null) { + continue; } - if ( - (newCr.Status__c == 'Påmeldt' || - newCr.Status__c == 'Venteliste' || - oldCr.Status__c == 'Påmeldt' || - oldCr.Status__c == 'Venteliste') && (newCr.NumberOfParticipants__c != oldCr.NumberOfParticipants__c) - ) { - relevantChangeOccurred = true; + + CourseRegistration__c oldCr = oldMap.get(newCr.Id); + if (oldCr == null) { + continue; } - if (!relevantChangeOccurred) { - continue; // Skip if no relevant fields changed + Boolean oldWasAttending = oldCr.Status__c == 'Påmeldt'; + Boolean newIsAttending = newCr.Status__c == 'Påmeldt'; + + if (oldWasAttending && !newIsAttending && oldCr.Course__c != null) { + coursesToCheckWaitlist.add(oldCr.Course__c); + continue; } - if (oldCr.Status__c == 'Påmeldt' || oldCr.Status__c == 'Venteliste') { - crsToRemoveOldContribution.add(oldCr); + if (!oldWasAttending || !newIsAttending) { + continue; } - if (newCr.Status__c == 'Påmeldt' || newCr.Status__c == 'Venteliste') { - crsToAddNewContribution.add(newCr); + Id oldCourseId = oldCr.Course__c; + if (oldCourseId == null) { + continue; } - if (oldCr.Status__c == 'Påmeldt' && newCr.Status__c != 'Påmeldt') { - coursesToCheckWaitlist.add(oldCr.Course__c); // Course ID from old record (should be same as new) - } else if ( - oldCr.Status__c == 'Påmeldt' && - newCr.Status__c == 'Påmeldt' && - newCr.NumberOfParticipants__c != null && - oldCr.NumberOfParticipants__c != null && - newCr.NumberOfParticipants__c < oldCr.NumberOfParticipants__c - ) { - // Participants decreased while still attending - coursesToCheckWaitlist.add(oldCr.Course__c); + if (newCr.Course__c != null && newCr.Course__c != oldCourseId) { + coursesToCheckWaitlist.add(oldCourseId); + continue; } - } - if (!crsToRemoveOldContribution.isEmpty()) { - CourseRegistrationHelper.getCourseIdToReduce(crsToRemoveOldContribution); - } + Integer oldParticipants = oldCr.NumberOfParticipants__c == null || oldCr.NumberOfParticipants__c < 1 + ? 1 + : oldCr.NumberOfParticipants__c.intValue(); + Integer newParticipants = newCr.NumberOfParticipants__c == null || newCr.NumberOfParticipants__c < 1 + ? 1 + : newCr.NumberOfParticipants__c.intValue(); - if (!crsToAddNewContribution.isEmpty()) { - CourseRegistrationHelper.getCourseIdToIncrease(crsToAddNewContribution); + if (newParticipants < oldParticipants) { + coursesToCheckWaitlist.add(oldCourseId); + } } if (!coursesToCheckWaitlist.isEmpty()) { diff --git a/force-app/main/default/classes/CourseWaitlistPromotionJob.cls b/force-app/main/default/classes/CourseWaitlistPromotionJob.cls new file mode 100644 index 00000000..27752a29 --- /dev/null +++ b/force-app/main/default/classes/CourseWaitlistPromotionJob.cls @@ -0,0 +1,14 @@ +public class CourseWaitlistPromotionJob implements Queueable { + private final List courseIds; + + public CourseWaitlistPromotionJob(List courseIds) { + this.courseIds = courseIds == null ? new List() : new List(courseIds); + } + + public void execute(QueueableContext context) { + if (courseIds.isEmpty()) { + return; + } + CourseRegistrationHelper.updateCourseWaitlistPromotions(new Set(courseIds)); + } +} diff --git a/force-app/main/default/classes/CourseWaitlistPromotionJob.cls-meta.xml b/force-app/main/default/classes/CourseWaitlistPromotionJob.cls-meta.xml new file mode 100644 index 00000000..5f399c3c --- /dev/null +++ b/force-app/main/default/classes/CourseWaitlistPromotionJob.cls-meta.xml @@ -0,0 +1,5 @@ + + + 63.0 + Active + diff --git a/force-app/main/default/flexipages/Course_Record_Page.flexipage-meta.xml b/force-app/main/default/flexipages/Course_Record_Page.flexipage-meta.xml index 4dd2ba55..05dbbfdc 100644 --- a/force-app/main/default/flexipages/Course_Record_Page.flexipage-meta.xml +++ b/force-app/main/default/flexipages/Course_Record_Page.flexipage-meta.xml @@ -148,15 +148,8 @@ uiBehavior none - Record.NumberOfParticipants__c - RecordNumberOfParticipants__cField - - - {!Record.IsNew__c} - EQUAL - false - - + Record.RegistrationSignupsCount__c + RecordRegistration_Signups_Count_cField @@ -165,15 +158,8 @@ uiBehavior none - Record.Waitinglist__c - RecordWaitinglist__cField - - - {!Record.IsNew__c} - EQUAL - false - - + Record.RegistrationWaitlistedCount__c + RecordRegistration_Waitlisted_Count_cField Facet-25ae3f01-3e42-4c5f-855f-b2ae433d7248 @@ -1200,12 +1186,11 @@ 1440 - reportFilter - FK_CUSTENT_ID + label reportName - Kursdeltakere_ts2 + Kursdeltakere_42y showRefreshButton diff --git a/force-app/main/default/flows/HOT_AutoAssignWaitingParticipantsToCourse.flow-meta.xml b/force-app/main/default/flows/HOT_AutoAssignWaitingParticipantsToCourse.flow-meta.xml index e8632ab7..a712146d 100644 --- a/force-app/main/default/flows/HOT_AutoAssignWaitingParticipantsToCourse.flow-meta.xml +++ b/force-app/main/default/flows/HOT_AutoAssignWaitingParticipantsToCourse.flow-meta.xml @@ -108,7 +108,7 @@ availableseatsleftCheck Number - {!$Record.MaxNumberOfParticipants__c} - {!$Record.NumberOfParticipants__c} + {!$Record.MaxNumberOfParticipants__c} - {!$Record.RegistrationSignupsCount__c} 0 Auto assign waiting participants to Course {!$Flow.CurrentDateTime} diff --git a/force-app/main/default/layouts/Course__c-Course Layout.layout-meta.xml b/force-app/main/default/layouts/Course__c-Course Layout.layout-meta.xml index 0732582f..c927f358 100644 --- a/force-app/main/default/layouts/Course__c-Course Layout.layout-meta.xml +++ b/force-app/main/default/layouts/Course__c-Course Layout.layout-meta.xml @@ -44,6 +44,22 @@ Edit ShowAddMultipleParticipants__c + + Readonly + RegistrationSignupsCount__c + + + Readonly + RegistrationWaitlistedCount__c + + + Readonly + RegistrationCancelledCount__c + + + Readonly + RegistrationInvitedCount__c + @@ -141,6 +157,7 @@ RegistrationPlaceName__c + @@ -190,9 +207,9 @@ false true - - - + + + @@ -253,4 +270,4 @@ 0 Default - \ No newline at end of file + diff --git a/force-app/main/default/lwc/courseRegistrationForm/courseRegistrationForm.js b/force-app/main/default/lwc/courseRegistrationForm/courseRegistrationForm.js index e3ec1169..c8310c33 100644 --- a/force-app/main/default/lwc/courseRegistrationForm/courseRegistrationForm.js +++ b/force-app/main/default/lwc/courseRegistrationForm/courseRegistrationForm.js @@ -133,8 +133,9 @@ export default class CourseRegistrationForm extends NavigationMixin(LightningEle } this.maxNumberOfParticipants = result.MaxNumberOfParticipants__c; - this.numberOfParticipants = result.NumberOfParticipants__c; - this.numberOnWaitinglist = result.Waitinglist__c + 1; + this.numberOfParticipants = result.RegistrationSignupsCount__c || 0; + const waitlistedCount = result.RegistrationWaitlistedCount__c || 0; + this.numberOnWaitinglist = waitlistedCount + 1; if (this.numberOfParticipants >= this.maxNumberOfParticipants) { this.courseIsFullWarning = true; diff --git a/force-app/main/default/lwc/courseRegistrationInformation/courseRegistrationInformation.js b/force-app/main/default/lwc/courseRegistrationInformation/courseRegistrationInformation.js index 2dd3034f..6da8a912 100644 --- a/force-app/main/default/lwc/courseRegistrationInformation/courseRegistrationInformation.js +++ b/force-app/main/default/lwc/courseRegistrationInformation/courseRegistrationInformation.js @@ -39,7 +39,8 @@ export default class courseRegistrationInformation extends LightningElement { moment(result.RegistrationDeadline__c).format('LT'); this.place = result.RegistrationPlaceName__c; this.type = result.Type__c; - this.seats = result.MaxNumberOfParticipants__c - result.NumberOfParticipants__c; + const currentSignups = result.RegistrationSignupsCount__c || 0; + this.seats = result.MaxNumberOfParticipants__c - currentSignups; } else { } }); diff --git a/force-app/main/default/objectTranslations/Course__c-no/RegistrationCancelledCount__c.fieldTranslation-meta.xml b/force-app/main/default/objectTranslations/Course__c-no/RegistrationCancelledCount__c.fieldTranslation-meta.xml new file mode 100644 index 00000000..b5cf7328 --- /dev/null +++ b/force-app/main/default/objectTranslations/Course__c-no/RegistrationCancelledCount__c.fieldTranslation-meta.xml @@ -0,0 +1,5 @@ + + + + RegistrationCancelledCount__c + diff --git a/force-app/main/default/objectTranslations/Course__c-no/RegistrationInvitedCount__c.fieldTranslation-meta.xml b/force-app/main/default/objectTranslations/Course__c-no/RegistrationInvitedCount__c.fieldTranslation-meta.xml new file mode 100644 index 00000000..b3338ab0 --- /dev/null +++ b/force-app/main/default/objectTranslations/Course__c-no/RegistrationInvitedCount__c.fieldTranslation-meta.xml @@ -0,0 +1,5 @@ + + + + RegistrationInvitedCount__c + diff --git a/force-app/main/default/objectTranslations/Course__c-no/RegistrationSignupsCount__c.fieldTranslation-meta.xml b/force-app/main/default/objectTranslations/Course__c-no/RegistrationSignupsCount__c.fieldTranslation-meta.xml new file mode 100644 index 00000000..e1647091 --- /dev/null +++ b/force-app/main/default/objectTranslations/Course__c-no/RegistrationSignupsCount__c.fieldTranslation-meta.xml @@ -0,0 +1,5 @@ + + + + RegistrationSignupsCount__c + diff --git a/force-app/main/default/objectTranslations/Course__c-no/RegistrationWaitlistedCount__c.fieldTranslation-meta.xml b/force-app/main/default/objectTranslations/Course__c-no/RegistrationWaitlistedCount__c.fieldTranslation-meta.xml new file mode 100644 index 00000000..88dd1779 --- /dev/null +++ b/force-app/main/default/objectTranslations/Course__c-no/RegistrationWaitlistedCount__c.fieldTranslation-meta.xml @@ -0,0 +1,5 @@ + + + + RegistrationWaitlistedCount__c + diff --git a/force-app/main/default/objects/CourseRegistration__c/CourseRegistration__c.object-meta.xml b/force-app/main/default/objects/CourseRegistration__c/CourseRegistration__c.object-meta.xml index d9a92ad3..6ee6afa6 100644 --- a/force-app/main/default/objects/CourseRegistration__c/CourseRegistration__c.object-meta.xml +++ b/force-app/main/default/objects/CourseRegistration__c/CourseRegistration__c.object-meta.xml @@ -1,4 +1,4 @@ - + Accept @@ -152,7 +152,7 @@ true true true - ReadWrite + ControlledByParent KP-{000000} @@ -160,7 +160,7 @@ AutoNumber Course Registrations - - ReadWrite + + ControlledByParent Public diff --git a/force-app/main/default/objects/CourseRegistration__c/fields/Course__c.field-meta.xml b/force-app/main/default/objects/CourseRegistration__c/fields/Course__c.field-meta.xml index ac5ae713..a23e7d47 100644 --- a/force-app/main/default/objects/CourseRegistration__c/fields/Course__c.field-meta.xml +++ b/force-app/main/default/objects/CourseRegistration__c/fields/Course__c.field-meta.xml @@ -1,13 +1,14 @@ - + Course__c - Restrict false Course__c Course Registrations CourseRegistrations - true + 0 + false false - Lookup + MasterDetail + false diff --git a/force-app/main/default/objects/CourseRegistration__c/validationRules/Do_not_exceed_max_number_of_participants.validationRule-meta.xml b/force-app/main/default/objects/CourseRegistration__c/validationRules/Do_not_exceed_max_number_of_participants.validationRule-meta.xml index 3e6f6dff..7437cac7 100644 --- a/force-app/main/default/objects/CourseRegistration__c/validationRules/Do_not_exceed_max_number_of_participants.validationRule-meta.xml +++ b/force-app/main/default/objects/CourseRegistration__c/validationRules/Do_not_exceed_max_number_of_participants.validationRule-meta.xml @@ -1,26 +1,36 @@ - + Do_not_exceed_max_number_of_participants true AND( -$Permission.Arbeidsgiver = TRUE, -OR( -AND(ISNEW(),ISPICKVAL(Status__c, "Påmeldt"), Course__r.NumberOfParticipants__c >= Course__r.MaxNumberOfParticipants__c), -AND( -ISCHANGED(Status__c), -OR(ISPICKVAL(PRIORVALUE(Status__c), "Avmeldt"), -ISPICKVAL(PRIORVALUE(Status__c), "Venteliste"), -ISPICKVAL(PRIORVALUE(Status__c), "Invitert")), -ISPICKVAL(Status__c, "Påmeldt"), -Course__r.NumberOfParticipants__c >= Course__r.MaxNumberOfParticipants__c), -AND( -ISCHANGED(Status__c), -ISPICKVAL(PRIORVALUE(Status__c), "Påmeldt"), -OR(ISPICKVAL(Status__c, "Venteliste"), -ISPICKVAL(Status__c, "Avmeldt"), -ISPICKVAL(Status__c, "Invitert")), -Course__r.NumberOfParticipants__c > Course__r.MaxNumberOfParticipants__c)) + $Permission.Arbeidsgiver = TRUE, + OR( + AND( + ISNEW(), + ISPICKVAL(Status__c, "Påmeldt"), + Course__r.RegistrationSignupsCount__c >= Course__r.MaxNumberOfParticipants__c + ), + AND( + ISCHANGED(Status__c), + OR( + ISPICKVAL(PRIORVALUE(Status__c), "Avmeldt"), + ISPICKVAL(PRIORVALUE(Status__c), "Venteliste"), + ISPICKVAL(PRIORVALUE(Status__c), "Invitert") + ), + ISPICKVAL(Status__c, "Påmeldt"), + Course__r.RegistrationSignupsCount__c >= Course__r.MaxNumberOfParticipants__c + ), + AND( + ISCHANGED(Status__c), + ISPICKVAL(PRIORVALUE(Status__c), "Påmeldt"), + OR( + ISPICKVAL(Status__c, "Venteliste"), + ISPICKVAL(Status__c, "Avmeldt"), + ISPICKVAL(Status__c, "Invitert") + ), + Course__r.RegistrationSignupsCount__c > Course__r.MaxNumberOfParticipants__c + ) + ) ) - Maks antall deltagere er registrert på dette kurset. Deltakeren må settes på venteliste. + Maks antall deltagere er registrert på dette kurset. Deltakeren må settes på venteliste. diff --git a/force-app/main/default/objects/Course__c/fields/AvailableSeats__c.field-meta.xml b/force-app/main/default/objects/Course__c/fields/AvailableSeats__c.field-meta.xml index e82fe264..2be9c905 100644 --- a/force-app/main/default/objects/Course__c/fields/AvailableSeats__c.field-meta.xml +++ b/force-app/main/default/objects/Course__c/fields/AvailableSeats__c.field-meta.xml @@ -2,7 +2,7 @@ AvailableSeats__c false - MaxNumberOfParticipants__c - NumberOfParticipants__c + MaxNumberOfParticipants__c - RegistrationSignupsCount__c BlankAsZero 18 diff --git a/force-app/main/default/objects/Course__c/fields/RegistrationCancelledCount__c.field-meta.xml b/force-app/main/default/objects/Course__c/fields/RegistrationCancelledCount__c.field-meta.xml new file mode 100644 index 00000000..01006ea8 --- /dev/null +++ b/force-app/main/default/objects/Course__c/fields/RegistrationCancelledCount__c.field-meta.xml @@ -0,0 +1,16 @@ + + + RegistrationCancelledCount__c + false + + CourseRegistration__c.NumberOfParticipants__c + + CourseRegistration__c.Status__c + equals + Avmeldt + + CourseRegistration__c.Course__c + sum + false + Summary + diff --git a/force-app/main/default/objects/Course__c/fields/RegistrationInvitedCount__c.field-meta.xml b/force-app/main/default/objects/Course__c/fields/RegistrationInvitedCount__c.field-meta.xml new file mode 100644 index 00000000..2a95d1df --- /dev/null +++ b/force-app/main/default/objects/Course__c/fields/RegistrationInvitedCount__c.field-meta.xml @@ -0,0 +1,16 @@ + + + RegistrationInvitedCount__c + false + + CourseRegistration__c.NumberOfParticipants__c + + CourseRegistration__c.Status__c + equals + Invitert + + CourseRegistration__c.Course__c + sum + false + Summary + diff --git a/force-app/main/default/objects/Course__c/fields/RegistrationSignupsCount__c.field-meta.xml b/force-app/main/default/objects/Course__c/fields/RegistrationSignupsCount__c.field-meta.xml new file mode 100644 index 00000000..2577dc91 --- /dev/null +++ b/force-app/main/default/objects/Course__c/fields/RegistrationSignupsCount__c.field-meta.xml @@ -0,0 +1,16 @@ + + + RegistrationSignupsCount__c + false + + CourseRegistration__c.NumberOfParticipants__c + + CourseRegistration__c.Status__c + equals + Påmeldt + + CourseRegistration__c.Course__c + sum + false + Summary + diff --git a/force-app/main/default/objects/Course__c/fields/RegistrationWaitlistedCount__c.field-meta.xml b/force-app/main/default/objects/Course__c/fields/RegistrationWaitlistedCount__c.field-meta.xml new file mode 100644 index 00000000..d1216e76 --- /dev/null +++ b/force-app/main/default/objects/Course__c/fields/RegistrationWaitlistedCount__c.field-meta.xml @@ -0,0 +1,16 @@ + + + RegistrationWaitlistedCount__c + false + + CourseRegistration__c.NumberOfParticipants__c + + CourseRegistration__c.Status__c + equals + Venteliste + + CourseRegistration__c.Course__c + sum + false + Summary + diff --git a/force-app/main/default/permissionsets/Course_Admin.permissionset-meta.xml b/force-app/main/default/permissionsets/Course_Admin.permissionset-meta.xml index dd078569..599bf3a3 100644 --- a/force-app/main/default/permissionsets/Course_Admin.permissionset-meta.xml +++ b/force-app/main/default/permissionsets/Course_Admin.permissionset-meta.xml @@ -551,6 +551,26 @@ Course__c.RegistrationUrl2__c true + + false + Course__c.RegistrationCancelledCount__c + true + + + false + Course__c.RegistrationInvitedCount__c + true + + + false + Course__c.RegistrationSignupsCount__c + true + + + false + Course__c.RegistrationWaitlistedCount__c + true + true Course__c.ShowAddMultipleParticipants__c diff --git a/force-app/main/default/reports/POArbeidsgiverRapporter/Kursdeltakere_ts2.report-meta.xml b/force-app/main/default/reports/POArbeidsgiverRapporter/Kursdeltakere_42y.report-meta.xml similarity index 92% rename from force-app/main/default/reports/POArbeidsgiverRapporter/Kursdeltakere_ts2.report-meta.xml rename to force-app/main/default/reports/POArbeidsgiverRapporter/Kursdeltakere_42y.report-meta.xml index 67a7e786..31efa27c 100644 --- a/force-app/main/default/reports/POArbeidsgiverRapporter/Kursdeltakere_ts2.report-meta.xml +++ b/force-app/main/default/reports/POArbeidsgiverRapporter/Kursdeltakere_42y.report-meta.xml @@ -14,7 +14,7 @@ true CourseRegistration__c.Status__c CHART_BOTTOM - true + false false false false @@ -22,16 +22,13 @@ Auto #000000 12 + Antall påmeldte #000000 18 CourseRegistration__c.CourseParticipant__c - - Sum - CourseRegistration__c.NumberOfParticipants__c - CourseRegistration__c.firstName__c @@ -80,6 +77,10 @@ CourseRegistration__c.OrganizationNumber__c + + Sum + CourseRegistration__c.NumberOfParticipants__c + Summary Day @@ -91,13 +92,13 @@ co 1 - CustomEntity$CourseRegistration__c@CourseRegistration__c.Course__c - organization + CustomEntityCustomEntity$Course__c$CourseRegistration__c + user true true true - CUST_CREATED_DATE + Course__c.RegistrationToDateTime__c INTERVAL_CUSTOM - + \ No newline at end of file