diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a901d12fcb45897f87ed1fd4158b051c913efe29..2cb75d911af0d35dab1bcd0e151dfb3b6d66e82e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -15,9 +15,6 @@ variables:
   DOCKER_DRIVER: overlay2
   DOCKER_TLS_CERTDIR: "/certs"
 
-  SAST_DISABLE_DIND: "false"
-  SAST_DEFAULT_ANALYZERS: "spotbugs"
-
   # Configure mysql environment variables
   MYSQL_DATABASE: "$DB_NAME"
   MYSQL_USER: "$DB_NAME"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 389d0529602c73d12aefc4cc452e0b44489e1166..8ab34b8e162766436643accdfbc70ae8b870e1d0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,8 +8,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ## [Unreleased]
 
 ### Added
+
 ### Changed
+
+### Fixed
+
+## [2.1.1]
+
+### Added
+
+### Changed
+* Job offers page now has a programme select before the user sees any job offers @rwbackx
+
 ### Fixed
+* Offer positions now works again @rwbackx
+* FlexDelft export is now in the correct format @rwbackx
 
 ## [2.1.0]
 
@@ -79,6 +92,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 * Job offer import now allows for creating editions @rbackx
 * Renamed declarations to contract requests @toberhuber
 * Hiring message visible when accepted and offered @toberhuber
+* TA Training and Raise Requests only show programme specific requests @toberhuber
+* All applications and all contract requests pages only show programme specific applications/declarations (including exports) @toberhuber
+* Renames "Manage Defaults" to "Manage Programme" @toberhuber
 
 ### Fixed
 * Header icons now stack and align nicely as per wireframes @toberhuber
@@ -106,6 +122,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 * Offering positions to people with open applications @toberhuber
 * EditionID being used as CohortID in FlexDelft exports @toberhuber
 * Notification of unhandled declarations didn't include rejected declarations @toberhuber
+* Creating new editions when looking at the "all courses" page @toberhuber
 
 ### Deprecated
 * Removed person note model @toberhuber
diff --git a/build.gradle.kts b/build.gradle.kts
index b172033245934c977382496ca12031af92e8963e..7f1b1af85da08bf1d64388210ae0f150cbdce7fa 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -4,12 +4,12 @@ import nl.javadude.gradle.plugins.license.DownloadLicensesExtension
 import nl.javadude.gradle.plugins.license.LicenseExtension
 
 group = "nl.tudelft.tam"
-version = "2.1.0"
+version = "2.1.1"
 
 val javaVersion = JavaVersion.VERSION_17
 
-val labradoorVersion = "1.3.4"
-val libradorVersion = "1.0.3-SNAPSHOT6"
+val labradoorVersion = "1.3.5"
+val libradorVersion = "1.0.3-SNAPSHOT7"
 val guavaVersion = "31.1-jre"
 val modelMapperVersion = "3.1.0"
 val jQueryVersion = "3.6.2"
diff --git a/src/main/java/nl/tudelft/tam/DevDatabaseLoader.java b/src/main/java/nl/tudelft/tam/DevDatabaseLoader.java
index 9b182377fcf9e50bfd86a3bfb694131b27fc063f..37ef3180ee406683a92d07e2e46a2b040544132f 100644
--- a/src/main/java/nl/tudelft/tam/DevDatabaseLoader.java
+++ b/src/main/java/nl/tudelft/tam/DevDatabaseLoader.java
@@ -91,6 +91,7 @@ public class DevDatabaseLoader {
 	ExtraWork sqt_now_ew_grading;
 
 	nl.tudelft.tam.model.Profile cseteacher1;
+	nl.tudelft.tam.model.Profile cseteacher2;
 	nl.tudelft.tam.model.Profile csestudent1;
 	nl.tudelft.tam.model.Profile csestudent2;
 
@@ -221,13 +222,17 @@ public class DevDatabaseLoader {
 	private void fetchPeople() {
 		cseteacher1 = profileRepository.save(nl.tudelft.tam.model.Profile.builder()
 				.id(3L).emailNotifications(false).build());
+		cseteacher2 = profileRepository.save(nl.tudelft.tam.model.Profile.builder()
+				.id(4L).emailNotifications(false).build());
 		csestudent1 = profileRepository.save(nl.tudelft.tam.model.Profile.builder()
 				.id(9L).emailNotifications(false).build());
 		csestudent2 = profileRepository.save(nl.tudelft.tam.model.Profile.builder()
 				.id(10L).emailNotifications(false).build());
 
+		// Teacher 1 => Coordinator CSE
 		coordinatorRepository.save(Coordinator.builder().personId(cseteacher1.getId()).programId(1L).build());
-		coordinatorRepository.save(Coordinator.builder().personId(cseteacher1.getId()).programId(2L).build());
+		// Teacher 2 => Coordinator EE
+		coordinatorRepository.save(Coordinator.builder().personId(cseteacher2.getId()).programId(2L).build());
 	}
 
 	private void initApplications() {
diff --git a/src/main/java/nl/tudelft/tam/controller/ApplicationController.java b/src/main/java/nl/tudelft/tam/controller/ApplicationController.java
index daeef31d2416aff6ddd159c23e159b80b682ffc2..eeb1d9d2f7ce8ae44e48cbbe0535f8c925d29a59 100644
--- a/src/main/java/nl/tudelft/tam/controller/ApplicationController.java
+++ b/src/main/java/nl/tudelft/tam/controller/ApplicationController.java
@@ -19,7 +19,9 @@ package nl.tudelft.tam.controller;
 
 import java.io.IOException;
 import java.time.LocalDateTime;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 import nl.tudelft.labracore.api.dto.ProgramDetailsDTO;
@@ -125,9 +127,10 @@ public class ApplicationController {
 	 */
 	@PostMapping("submit/{id}")
 	public String submitApplication(@AuthenticatedPerson Person person, @PathVariable Long id,
-			@RequestParam(required = false) String page) {
+			@RequestParam(required = false) String page, @RequestParam(required = false) Long program) {
 		applicationService.submit(person.getId(), id);
-		return "redirect:/" + (page != null ? page : "job-offer/open");
+		return "redirect:/"
+				+ (page != null ? page : "job-offer/open" + (program == null ? "" : "?program=" + program));
 	}
 
 	/**
@@ -142,10 +145,21 @@ public class ApplicationController {
 	public String retractApplication(@AuthenticatedPerson Person person, @PathVariable Long id,
 			@RequestParam(required = false) String page,
 			@RequestParam(required = false) String q,
-			@RequestParam(required = false) String tab) {
+			@RequestParam(required = false) String tab,
+			@RequestParam(required = false) String program) {
 		applicationService.retract(person.getId(), id);
-		return "redirect:/" + (page != null ? page : "job-offer/open") + (q != null ? "?q=" + q : "")
-				+ (tab != null ? "&tab=" + tab : "");
+
+		String url = page == null ? "job-offer/open" : page;
+
+		Map<String, String> params = new HashMap<>();
+		if (q != null)
+			params.put("q", q);
+		if (tab != null)
+			params.put("tab", tab);
+		if (program != null)
+			params.put("program", program);
+
+		return "redirect:/" + url + getURLParamsString(params);
 	}
 
 	/**
@@ -218,9 +232,29 @@ public class ApplicationController {
 	@PreAuthorize("@authorisationService.offerExistsFor(#id)")
 	public String acceptApplication(@AuthenticatedPerson Person person, @PathVariable Long id,
 			@RequestParam(required = false) String q,
-			@RequestParam(required = false) String tab) {
+			@RequestParam(required = false) String tab,
+			@RequestParam(required = false) String program) {
 		applicationService.accept(person.getId(), id);
-		return "redirect:/job-offer/open" + (q != null ? "?q=" + q : "") + (tab != null ? "&tab=" + tab : "");
+
+		Map<String, String> params = new HashMap<>();
+		if (q != null)
+			params.put("q", q);
+		if (tab != null)
+			params.put("tab", tab);
+		if (program != null)
+			params.put("program", program);
+
+		return "redirect:/job-offer/open" + getURLParamsString(params);
+	}
+
+	private static String getURLParamsString(Map<String, String> params) {
+		StringBuilder result = new StringBuilder();
+		char sep = '?';
+		for (String param : params.keySet()) {
+			result.append(sep).append(param).append("=").append(params.get(param));
+			sep = '&';
+		}
+		return result.toString();
 	}
 
 	// endregion
diff --git a/src/main/java/nl/tudelft/tam/controller/JobOfferController.java b/src/main/java/nl/tudelft/tam/controller/JobOfferController.java
index 2096ffca974015cc01aef14e167cfd1cf78fcb9f..cafd9a5b31482aa3d486f03eca880464d66d734d 100644
--- a/src/main/java/nl/tudelft/tam/controller/JobOfferController.java
+++ b/src/main/java/nl/tudelft/tam/controller/JobOfferController.java
@@ -25,9 +25,7 @@ import java.util.stream.Collectors;
 
 import javax.validation.Valid;
 
-import nl.tudelft.labracore.api.dto.EditionDetailsDTO;
-import nl.tudelft.labracore.api.dto.PersonIdDTO;
-import nl.tudelft.labracore.api.dto.RoleEditionDetailsDTO;
+import nl.tudelft.labracore.api.dto.*;
 import nl.tudelft.labracore.lib.security.user.AuthenticatedPerson;
 import nl.tudelft.labracore.lib.security.user.Person;
 import nl.tudelft.tam.dto.create.JobOfferCreateDTO;
@@ -38,7 +36,6 @@ import nl.tudelft.tam.dto.view.details.EditionDetailsOffersWorkDTO;
 import nl.tudelft.tam.dto.view.details.JobOfferDetailsDTO;
 import nl.tudelft.tam.dto.view.summary.ApplicationStatusSummaryDTO;
 import nl.tudelft.tam.dto.view.summary.JobOfferSummaryDTO;
-import nl.tudelft.tam.model.Coordinator;
 import nl.tudelft.tam.security.AuthorisationService;
 import nl.tudelft.tam.service.*;
 
@@ -62,37 +59,40 @@ public class JobOfferController {
 	// region class attributes
 
 	@Autowired
-	JobOfferService jobOfferService;
+	private JobOfferService jobOfferService;
 
 	@Autowired
-	ApplicationService applicationService;
+	private ApplicationService applicationService;
 
 	@Autowired
-	EditionService editionService;
+	private EditionService editionService;
 
 	@Autowired
-	CourseService courseService;
+	private CourseService courseService;
 
 	@Autowired
-	CohortService cohortService;
+	private CohortService cohortService;
 
 	@Autowired
-	CSVService csvService;
+	private CSVService csvService;
 
 	@Autowired
-	PersonService personService;
+	private PersonService personService;
 
 	@Autowired
-	AuthorisationService authorisationService;
+	private AuthorisationService authorisationService;
 
 	@Autowired
-	CoordinatorService coordinatorService;
+	private CoordinatorService coordinatorService;
 
 	@Autowired
-	CoordinatorDefaultService coordinatorDefaultService;
+	private CoordinatorDefaultService coordinatorDefaultService;
 
 	@Autowired
-	ModelMapper mapper;
+	private ProgramService programService;
+
+	@Autowired
+	private ModelMapper mapper;
 
 	// endregion
 
@@ -125,47 +125,35 @@ public class JobOfferController {
 	 */
 	@GetMapping("open")
 	public String getOpenJobOffers(@AuthenticatedPerson Person person,
+			@RequestParam(required = false) Long program,
 			@RequestParam(required = false) String tab,
 			@RequestParam(required = false) String q, Model model) {
 		List<ApplicationDetailsJobOfferDTO> applications = applicationService
 				.getFilteredApplicationsForPerson(person.getId(), q);
 
-		List<JobOfferSummaryDTO> offers = jobOfferService.getFilteredOpen(q).stream()
-				.map(x -> (JobOfferSummaryDTO) x).collect(Collectors.toList());
-
-		// Also include closed jobs, but where the student can accept an offer!
-		//		for (ApplicationDetailsJobOfferDTO app : applications) {
-		//			if (app.getStatus().equals(Status.OFFERED)) {
-		//				JobOfferSummaryDTO appsOffer = mapper.map(app.getJobOffer(), JobOfferSummaryDTO.class);
-		//				if (!offers.contains(appsOffer)) {
-		//					offers.add(appsOffer);
-		//				}
-		//			}
-		//		}
-
-		List<EditionDetailsOffersWorkDTO> editions = editionService
-				.combineOffersAndWorkWithEditions(offers, new ArrayList<>());
-
-		// Sort editions based on Cohort, exclude masters and add them to the end.
-		Comparator<EditionDetailsOffersWorkDTO> editionComparator = Comparator
-				.comparing(o -> o.getCohort().getName());
-		editionComparator = editionComparator.reversed().thenComparing(EditionDetailsDTO::getStartDate)
-				.thenComparing(EditionDetailsDTO::getName);
-
-		List<EditionDetailsOffersWorkDTO> sortedEditions = editions.stream()
-				.sorted(editionComparator)
-				.collect(Collectors.toList());
-
-		// Add all job offers to list for appForOffer to work correctly
-		for (ApplicationDetailsJobOfferDTO app : applications) {
-			JobOfferDetailsDTO jo = app.getJobOffer();
-			offers.add(jo);
+		List<JobOfferDetailsDTO> offerDetails = jobOfferService.getFilteredOpen(q);
+		List<EditionDetailsOffersWorkDTO> editions = Collections.emptyList();
+		if (program != null) {
+			Set<Long> coursesInProgram = courseService.getAllCoursesInProgram(program).stream()
+					.map(CourseSummaryDTO::getId).collect(Collectors.toSet());
+			List<JobOfferSummaryDTO> offers = offerDetails.stream()
+					.filter(o -> coursesInProgram.contains(o.getEdition().getCourse().getId()))
+					.map(x -> (JobOfferSummaryDTO) x).collect(Collectors.toList());
+
+			// Sort editions based on Cohort, exclude masters and add them to the end.
+			Comparator<EditionDetailsOffersWorkDTO> editionComparator = Comparator
+					.<EditionDetailsOffersWorkDTO, String>comparing(o -> o.getCohort().getName())
+					.reversed().thenComparing(EditionDetailsDTO::getStartDate)
+					.thenComparing(EditionDetailsDTO::getName);
+			editions = editionService
+					.combineOffersAndWorkWithEditions(offers, new ArrayList<>())
+					.stream().sorted(editionComparator).toList();
 		}
 
 		Map<Long, ApplicationStatusSummaryDTO> appForOffer = applicationService
 				.getMapWithStatusAppOpenByIdForPerson(
 						person.getId(),
-						offers.stream().map(JobOfferSummaryDTO::getId).collect(Collectors.toList()));
+						offerDetails.stream().map(JobOfferDetailsDTO::getId).collect(Collectors.toList()));
 
 		if (tab == null || !List.of("offers", "applications").contains(tab)) {
 			tab = "offers";
@@ -173,7 +161,9 @@ public class JobOfferController {
 
 		model.addAttribute("tab", tab);
 		model.addAttribute("applications", applications);
-		model.addAttribute("editions", sortedEditions);
+		model.addAttribute("programs", programService.getAllPrograms().stream()
+				.sorted(Comparator.comparing(ProgramSummaryDTO::getName)).toList());
+		model.addAttribute("editions", editions);
 		model.addAttribute("userApplications", appForOffer);
 		return "job_offer/view_many";
 	}
@@ -193,13 +183,21 @@ public class JobOfferController {
 			@RequestParam(required = false) Boolean hidePrev,
 			@RequestParam(required = false) String q,
 			Model model) {
-		List<Long> editionIds = personService.getRolesForPerson(person.getId())
-				.stream().filter(r -> r.getType().equals(RoleEditionDetailsDTO.TypeEnum.TEACHER))
-				.map(r -> Objects.requireNonNull(r.getEdition()).getId()).collect(Collectors.toList());
 
+		List<Long> managedEditionIds = editionService.getAllEditionIdsThatPersonIsAMangerOf(person.getId());
+		List<CourseSummaryDTO> managedCourses = courseService
+				.getManagingCourses(new PersonIdDTO().id(person.getId()));
+		List<Long> programIdsOfManagedCourses = courseService.getCoursesById(managedCourses.stream()
+				.map(CourseSummaryDTO::getId)
+				.collect(Collectors.toList())).stream()
+				.map(x -> x.getProgram().getId())
+				.collect(Collectors.toList());
+
+		// Filter by the search query
 		List<EditionDetailsOffersWorkDTO> editions = editionService
-				.filter(editionService.getEditionsWithJobsAndWork(editionIds), q);
+				.filter(editionService.getEditionsWithJobsAndWork(managedEditionIds), q);
 
+		// Add the coordinator defaults to the edition objects
 		coordinatorDefaultService.addDefaultsToEditionsWithJobsAndWork(editions);
 
 		if (hidePrev == null || hidePrev) {
@@ -212,9 +210,8 @@ public class JobOfferController {
 
 		model.addAttribute("editions", editions);
 		model.addAttribute("showAll", false);
-		model.addAttribute("managed",
-				courseService.getManagingCourses(new PersonIdDTO().id(person.getId())));
-		model.addAttribute("cohorts", cohortService.getAllCohorts());
+		model.addAttribute("managed", managedCourses);
+		model.addAttribute("cohorts", cohortService.getCohortsByProgrammeIds(programIdsOfManagedCourses));
 
 		return "job_offer/manage";
 	}
@@ -234,20 +231,30 @@ public class JobOfferController {
 			@RequestParam(required = false) Boolean hidePrev,
 			@RequestParam(required = false) String q,
 			Model model) {
-		Set<Long> coordinating = coordinatorService.findAllByPersonId(person.getId()).stream()
-				.map(Coordinator::getProgramId).collect(Collectors.toSet());
-		List<EditionDetailsOffersWorkDTO> editions = editionService.filter(
-				editionService.getEditionsWithJobsAndWork(
-						editionService.getAllEditionIds())
-						.stream()
-						.filter(e -> coordinating
-								.contains(
-										Objects.requireNonNull(
-												courseService.getOrThrow(e.getCourse().getId()).getProgram())
-												.getId()))
-						.collect(Collectors.toList()),
-				q);
 
+		Set<Long> coordinatingProgramIds = coordinatorService.getProgramIdsByPersonId(person.getId());
+		List<CourseSummaryDTO> coordinatingCourses = new ArrayList<>();
+		List<Long> coordinatingEditions = new ArrayList<>();
+
+		for (Long id : coordinatingProgramIds) {
+			List<CourseSummaryDTO> coursesInProgram = courseService.getAllCoursesInProgram(id);
+			coordinatingCourses.addAll(coursesInProgram);
+		}
+
+		for (CourseSummaryDTO course : coordinatingCourses) {
+			coordinatingEditions.addAll(editionService.getEditionsForCourse(course.getId()));
+		}
+
+		List<CohortSummaryDTO> coordinatingCohorts = cohortService
+				.getCohortsByProgrammeIds(coordinatingProgramIds.stream().toList());
+
+		List<EditionDetailsOffersWorkDTO> editions = editionService
+				.getEditionsWithJobsAndWork(coordinatingEditions);
+
+		// Filter by the search query
+		editions = editionService.filter(editions, q);
+
+		// Add the coordinator defaults to the edition objects
 		coordinatorDefaultService.addDefaultsToEditionsWithJobsAndWork(editions);
 
 		if (hidePrev == null || hidePrev) {
@@ -260,6 +267,8 @@ public class JobOfferController {
 
 		model.addAttribute("editions", editions);
 		model.addAttribute("showAll", true);
+		model.addAttribute("managed", coordinatingCourses);
+		model.addAttribute("cohorts", coordinatingCohorts);
 
 		return "job_offer/manage";
 	}
diff --git a/src/main/java/nl/tudelft/tam/controller/RaiseRequestController.java b/src/main/java/nl/tudelft/tam/controller/RaiseRequestController.java
index ccd0639333e78269546a6a53ef814aa081e0f52a..92c842ec60c8629cbcebe3046c8e081d41df4c29 100644
--- a/src/main/java/nl/tudelft/tam/controller/RaiseRequestController.java
+++ b/src/main/java/nl/tudelft/tam/controller/RaiseRequestController.java
@@ -19,6 +19,7 @@ package nl.tudelft.tam.controller;
 
 import java.io.IOException;
 import java.util.AbstractMap;
+import java.util.ArrayList;
 import java.util.List;
 
 import javax.transaction.Transactional;
@@ -32,6 +33,7 @@ import nl.tudelft.tam.dto.view.details.RaiseRequestDetailsDTO;
 import nl.tudelft.tam.exception.FileHandlingException;
 import nl.tudelft.tam.exception.InvalidDatabaseEntryException;
 import nl.tudelft.tam.model.Profile;
+import nl.tudelft.tam.service.CoordinatorService;
 import nl.tudelft.tam.service.RaiseRequestService;
 
 import org.springframework.beans.factory.annotation.Autowired;
@@ -53,6 +55,9 @@ public class RaiseRequestController {
 	@Autowired
 	private RaiseRequestService raiseRequestService;
 
+	@Autowired
+	private CoordinatorService coordinatorService;
+
 	/**
 	 * Shows a list of open raise requests.
 	 *
@@ -62,9 +67,14 @@ public class RaiseRequestController {
 	 */
 	@GetMapping("all")
 	@PreAuthorize("@authorisationService.canEditPayScale()")
-	public String getSubmittedRaiseRequests(Model model) throws InvalidDatabaseEntryException {
+	public String getSubmittedRaiseRequests(Model model, @AuthenticatedPerson Person person)
+			throws InvalidDatabaseEntryException {
+
+		List<Long> coordinatingProgramIds = new ArrayList<>(
+				coordinatorService.getProgramIdsByPersonId(person.getId()));
 
-		List<RaiseRequestDetailsDTO> raiseRequests = raiseRequestService.getAllSubmitted();
+		List<RaiseRequestDetailsDTO> raiseRequests = raiseRequestService
+				.getAllSubmitted(coordinatingProgramIds);
 		model.addAttribute("raiseRequests", raiseRequests);
 
 		return "raise_request/submitted";
diff --git a/src/main/java/nl/tudelft/tam/controller/TrainingApprovalRequestController.java b/src/main/java/nl/tudelft/tam/controller/TrainingApprovalRequestController.java
index 85d6440edc15cf1f7703e0545737b79eff16e177..9f33986222bef0fb3c8498c1c83a353509777665 100644
--- a/src/main/java/nl/tudelft/tam/controller/TrainingApprovalRequestController.java
+++ b/src/main/java/nl/tudelft/tam/controller/TrainingApprovalRequestController.java
@@ -18,6 +18,7 @@
 package nl.tudelft.tam.controller;
 
 import java.util.AbstractMap;
+import java.util.ArrayList;
 import java.util.List;
 
 import javax.transaction.Transactional;
@@ -30,6 +31,7 @@ import nl.tudelft.tam.dto.id.ProfileIdDTO;
 import nl.tudelft.tam.dto.view.details.TrainingApprovalRequestDetailsDTO;
 import nl.tudelft.tam.exception.InvalidDatabaseEntryException;
 import nl.tudelft.tam.model.Profile;
+import nl.tudelft.tam.service.CoordinatorService;
 import nl.tudelft.tam.service.TrainingApprovalRequestService;
 
 import org.springframework.beans.factory.annotation.Autowired;
@@ -46,6 +48,9 @@ public class TrainingApprovalRequestController {
 	@Autowired
 	private TrainingApprovalRequestService trainingApprovalRequestService;
 
+	@Autowired
+	private CoordinatorService coordinatorService;
+
 	/**
 	 * Shows a list of open training approval requests.
 	 *
@@ -55,10 +60,14 @@ public class TrainingApprovalRequestController {
 	 */
 	@GetMapping("all")
 	@PreAuthorize("@authorisationService.canEditTaTraining()")
-	public String getSubmittedTrainingApprovalRequests(Model model) throws InvalidDatabaseEntryException {
+	public String getSubmittedTrainingApprovalRequests(Model model, @AuthenticatedPerson Person person)
+			throws InvalidDatabaseEntryException {
+
+		List<Long> coordinatingProgramIds = new ArrayList<>(
+				coordinatorService.getProgramIdsByPersonId(person.getId()));
 
 		List<TrainingApprovalRequestDetailsDTO> trainingApprovalRequests = trainingApprovalRequestService
-				.getAllSubmitted();
+				.getAllSubmitted(coordinatingProgramIds);
 		model.addAttribute("trainingApprovalRequests", trainingApprovalRequests);
 
 		return "training_approval_request/submitted";
diff --git a/src/main/java/nl/tudelft/tam/dto/view/details/RaiseRequestDetailsDTO.java b/src/main/java/nl/tudelft/tam/dto/view/details/RaiseRequestDetailsDTO.java
index ce483aa011bdc5935dc0b855c546ec4d504700d4..305fbc5cff1f01e875c33f1289b3324c59d105ca 100644
--- a/src/main/java/nl/tudelft/tam/dto/view/details/RaiseRequestDetailsDTO.java
+++ b/src/main/java/nl/tudelft/tam/dto/view/details/RaiseRequestDetailsDTO.java
@@ -17,6 +17,8 @@
  */
 package nl.tudelft.tam.dto.view.details;
 
+import java.util.List;
+
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
@@ -33,4 +35,6 @@ public class RaiseRequestDetailsDTO extends RaiseRequestSummaryDTO {
 
 	private PayScale currentPayScale;
 
+	private List<Long> relevantProgramIds;
+
 }
diff --git a/src/main/java/nl/tudelft/tam/dto/view/details/TrainingApprovalRequestDetailsDTO.java b/src/main/java/nl/tudelft/tam/dto/view/details/TrainingApprovalRequestDetailsDTO.java
index 3a7bcdf01e33805ff5672d41e58df07a426ca3d4..ed072bac7c4c12d80e340d648c5ae52f9cf6f95f 100644
--- a/src/main/java/nl/tudelft/tam/dto/view/details/TrainingApprovalRequestDetailsDTO.java
+++ b/src/main/java/nl/tudelft/tam/dto/view/details/TrainingApprovalRequestDetailsDTO.java
@@ -17,6 +17,8 @@
  */
 package nl.tudelft.tam.dto.view.details;
 
+import java.util.List;
+
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
@@ -30,4 +32,6 @@ public class TrainingApprovalRequestDetailsDTO extends TrainingApprovalRequestSu
 
 	private PersonSummaryDTO person;
 
+	private List<Long> relevantProgramIds;
+
 }
diff --git a/src/main/java/nl/tudelft/tam/model/records/FlexDelftExport.java b/src/main/java/nl/tudelft/tam/model/records/FlexDelftExport.java
index 36fc1edf9441b3ec64da1890bf1de9ef57371c9a..bf9fae6d8d62cc81553541c5c0782f522409f9b5 100644
--- a/src/main/java/nl/tudelft/tam/model/records/FlexDelftExport.java
+++ b/src/main/java/nl/tudelft/tam/model/records/FlexDelftExport.java
@@ -17,6 +17,8 @@
  */
 package nl.tudelft.tam.model.records;
 
+import java.time.format.DateTimeFormatter;
+
 import nl.tudelft.labracore.api.dto.EditionDetailsDTO;
 import nl.tudelft.labracore.api.dto.PersonSummaryDTO;
 import nl.tudelft.tam.model.*;
@@ -39,6 +41,8 @@ public record FlexDelftExport(PersonSummaryDTO applicant, Profile applicantProfi
 				edition, coordinatorDefault, approver, batch, remarks);
 	}
 
+	private static final DateTimeFormatter exportDateFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
+
 	/**
 	 * Generates the export array
 	 *
@@ -55,8 +59,8 @@ public record FlexDelftExport(PersonSummaryDTO applicant, Profile applicantProfi
 					coordinatorDefault.getCoordinatorContractName(),
 					String.valueOf(jobOffer.getMaxHours()),
 					applicantProfile.getPayScale().toString(),
-					String.valueOf(jobOffer.getContractStartDate()),
-					String.valueOf(jobOffer.getContractEndDate()),
+					jobOffer.getContractStartDate().format(exportDateFormatter),
+					jobOffer.getContractEndDate().format(exportDateFormatter),
 					batch,
 					remarks
 			};
diff --git a/src/main/java/nl/tudelft/tam/repository/CoordinatorRepository.java b/src/main/java/nl/tudelft/tam/repository/CoordinatorRepository.java
index a6c5006500c02b3d5a8d60c6cebd06180552a13c..437d65a5aebc358ca686e03604d8dfd481a5c046 100644
--- a/src/main/java/nl/tudelft/tam/repository/CoordinatorRepository.java
+++ b/src/main/java/nl/tudelft/tam/repository/CoordinatorRepository.java
@@ -63,4 +63,12 @@ public interface CoordinatorRepository extends JpaRepository<Coordinator, Long>
 	 */
 	boolean existsByPersonIdAndProgramId(Long personId, Long programId);
 
+	/**
+	 * Gets all the coordinators for a given programme.
+	 *
+	 * @param  programId The id of the programme
+	 * @return           The programme's coordinators
+	 */
+	List<Coordinator> findAllByProgramId(Long programId);
+
 }
diff --git a/src/main/java/nl/tudelft/tam/security/AuthorisationService.java b/src/main/java/nl/tudelft/tam/security/AuthorisationService.java
index 47a8d772e274246e0e79f88cb271fdcf6604d734..98ff2e8aaa242fe41436e3b300935b315f17a554 100644
--- a/src/main/java/nl/tudelft/tam/security/AuthorisationService.java
+++ b/src/main/java/nl/tudelft/tam/security/AuthorisationService.java
@@ -224,7 +224,16 @@ public class AuthorisationService {
 	 * @return true if the user is authorised
 	 */
 	public boolean canEditTaTraining() {
-		return isCoordinatorOfAny(); // TODO make this programme specific
+		return isCoordinatorOfAny();
+	}
+
+	/**
+	 * Checks whether the user is authorised to approve TA training.
+	 *
+	 * @return true if the user is authorised
+	 */
+	public boolean canEditTaTrainingForProgram(Long programId) {
+		return isCoordinatorForProgram(programId);
 	}
 
 	/**
@@ -233,7 +242,16 @@ public class AuthorisationService {
 	 * @return true if the user is authorised
 	 */
 	public boolean canEditPayScale() {
-		return isCoordinatorOfAny(); // TODO make this programme specific
+		return isCoordinatorOfAny();
+	}
+
+	/**
+	 * Checks whether the user is authorised to edit a RaiseRequest claim.
+	 *
+	 * @return true if the user is authorised
+	 */
+	public boolean canEditPayScaleForProgram(Long programId) {
+		return isCoordinatorForProgram(programId);
 	}
 
 	/**
diff --git a/src/main/java/nl/tudelft/tam/service/ApplicationService.java b/src/main/java/nl/tudelft/tam/service/ApplicationService.java
index 1d3120f4be75ce8f8f63eaac3b92ebda0f189eb6..703b92bc5a15262ae31fcd0947426cee1befca4f 100644
--- a/src/main/java/nl/tudelft/tam/service/ApplicationService.java
+++ b/src/main/java/nl/tudelft/tam/service/ApplicationService.java
@@ -624,13 +624,18 @@ public class ApplicationService {
 				.getEditionsById(
 						applications.stream().map(a -> a.getJobOffer().getEditionId()).distinct().toList())
 				.stream().collect(Collectors.toMap(EditionDetailsDTO::getId, Function.identity()));
-		Map<Long, CourseDetailsDTO> courses = courseService
-				.getCoursesById(
-						editions.values().stream().map(e -> e.getCourse().getId()).distinct().toList())
-				.stream().collect(Collectors.toMap(CourseDetailsDTO::getId, Function.identity()));
-		return applications.stream().filter(a -> programId.equals(courses
-				.get(editions.get(a.getJobOffer().getEditionId()).getCourse().getId()).getProgram().getId()))
-				.toList();
+		if (!applications.isEmpty()) {
+			Map<Long, CourseDetailsDTO> courses = courseService
+					.getCoursesById(
+							editions.values().stream().map(e -> e.getCourse().getId()).distinct().toList())
+					.stream().collect(Collectors.toMap(CourseDetailsDTO::getId, Function.identity()));
+			return applications.stream().filter(a -> programId.equals(courses
+					.get(editions.get(a.getJobOffer().getEditionId()).getCourse().getId()).getProgram()
+					.getId()))
+					.toList();
+		} else {
+			return List.of();
+		}
 	}
 
 	/**
diff --git a/src/main/java/nl/tudelft/tam/service/CohortService.java b/src/main/java/nl/tudelft/tam/service/CohortService.java
index 672347fffebc1d1eea6dc1f86fd73b661ec95b0b..0877bc4d0c05378626fae5645e15ed7a3cfcb8e5 100644
--- a/src/main/java/nl/tudelft/tam/service/CohortService.java
+++ b/src/main/java/nl/tudelft/tam/service/CohortService.java
@@ -17,7 +17,9 @@
  */
 package nl.tudelft.tam.service;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 import nl.tudelft.labracore.api.CohortControllerApi;
@@ -75,4 +77,19 @@ public class CohortService {
 		ids = ids.stream().distinct().collect(Collectors.toList());
 		return cohortCache.get(ids);
 	}
+
+	/**
+	 * Gets all the cohorts for a list of programmes
+	 *
+	 * @param  programmeIds The list of programme ids
+	 * @return              The list of cohorts
+	 */
+	public List<CohortSummaryDTO> getCohortsByProgrammeIds(List<Long> programmeIds) {
+		List<CohortSummaryDTO> result = new ArrayList<>();
+		for (Long id : programmeIds) {
+			result.addAll(Objects
+					.requireNonNull(cohortControllerApi.getAllCohortsInProgram(id).collectList().block()));
+		}
+		return result;
+	}
 }
diff --git a/src/main/java/nl/tudelft/tam/service/CoordinatorService.java b/src/main/java/nl/tudelft/tam/service/CoordinatorService.java
index b0a0bf830b161a0bfed93953feef7811eaf7cd74..41bba00c11d95e84d4692f7cb63097f998337ea8 100644
--- a/src/main/java/nl/tudelft/tam/service/CoordinatorService.java
+++ b/src/main/java/nl/tudelft/tam/service/CoordinatorService.java
@@ -18,6 +18,8 @@
 package nl.tudelft.tam.service;
 
 import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import nl.tudelft.tam.model.Coordinator;
 import nl.tudelft.tam.repository.CoordinatorRepository;
@@ -31,6 +33,12 @@ public class CoordinatorService {
 	@Autowired
 	CoordinatorRepository coordinatorRepository;
 
+	@Autowired
+	EditionService editionService;
+
+	@Autowired
+	CourseService courseService;
+
 	/**
 	 * Finds all coordinator objects by person id
 	 *
@@ -61,4 +69,27 @@ public class CoordinatorService {
 	public boolean existsByPersonIdAndProgramId(Long personId, Long programId) {
 		return coordinatorRepository.existsByPersonIdAndProgramId(personId, programId);
 	}
+
+	/**
+	 * Finds all program ids by person id
+	 *
+	 * @param  personId The person id to search by
+	 * @return          The list of program ids
+	 */
+	public Set<Long> getProgramIdsByPersonId(Long personId) {
+		return coordinatorRepository.findAllByPersonId(personId).stream()
+				.map(Coordinator::getProgramId).collect(Collectors.toSet());
+	}
+
+	/**
+	 * Finds all coordinators by edition id
+	 *
+	 * @param  editionId The edition id to search by
+	 * @return           The list of coordinators
+	 */
+	public List<Coordinator> getCoordinatorsByEditionId(Long editionId) {
+		Long courseId = editionService.getEditionById(editionId).getCourse().getId();
+		Long programId = courseService.getOrThrow(courseId).getProgram().getId();
+		return coordinatorRepository.findAllByProgramId(programId);
+	}
 }
diff --git a/src/main/java/nl/tudelft/tam/service/CourseService.java b/src/main/java/nl/tudelft/tam/service/CourseService.java
index 22ae0dfade5938b7320a2b7ab8f09ac7d6229246..68413987b608ad70f94d0183be2a2cd59ad7d46d 100644
--- a/src/main/java/nl/tudelft/tam/service/CourseService.java
+++ b/src/main/java/nl/tudelft/tam/service/CourseService.java
@@ -78,4 +78,14 @@ public class CourseService {
 	public List<CourseSummaryDTO> getAllCourses() {
 		return courseApi.getAllCourses().collectList().block();
 	}
+
+	/**
+	 * Gets all courses in a program.
+	 *
+	 * @param  programId The id of the program
+	 * @return           The list of course summaries
+	 */
+	public List<CourseSummaryDTO> getAllCoursesInProgram(Long programId) {
+		return courseApi.getAllCoursesByProgram(programId).collectList().block();
+	}
 }
diff --git a/src/main/java/nl/tudelft/tam/service/EditionService.java b/src/main/java/nl/tudelft/tam/service/EditionService.java
index d64ee8960a80054ab0e1031332c679d969309025..fe90aa7d9bee4d748b0510b877ab7131b561a303 100644
--- a/src/main/java/nl/tudelft/tam/service/EditionService.java
+++ b/src/main/java/nl/tudelft/tam/service/EditionService.java
@@ -27,6 +27,7 @@ import nl.tudelft.labracore.api.EditionControllerApi;
 import nl.tudelft.labracore.api.dto.EditionCreateDTO;
 import nl.tudelft.labracore.api.dto.EditionDetailsDTO;
 import nl.tudelft.labracore.api.dto.EditionSummaryDTO;
+import nl.tudelft.labracore.api.dto.RoleEditionDetailsDTO;
 import nl.tudelft.tam.cache.EditionCacheManager;
 import nl.tudelft.tam.dto.view.details.EditionDetailsOffersWorkDTO;
 import nl.tudelft.tam.dto.view.summary.ExtraWorkSummaryDTO;
@@ -50,6 +51,9 @@ public class EditionService {
 	@Autowired
 	ExtraWorkService extraWorkService;
 
+	@Autowired
+	PersonService personService;
+
 	@Autowired
 	EditionControllerApi editionControllerApi;
 
@@ -242,5 +246,28 @@ public class EditionService {
 		return editionControllerApi.getAllEditionsActiveAtDate(time).toStream().toList();
 	}
 
+	/**
+	 * Gets a list of edition ids that a person is the manager of
+	 *
+	 * @param  personId The person to get the ids for
+	 * @return          The list of edition ids
+	 */
+	public List<Long> getAllEditionIdsThatPersonIsAMangerOf(Long personId) {
+		return personService.getRolesForPerson(personId)
+				.stream().filter(r -> r.getType().equals(RoleEditionDetailsDTO.TypeEnum.TEACHER))
+				.map(r -> Objects.requireNonNull(r.getEdition()).getId()).collect(Collectors.toList());
+	}
+
+	/**
+	 * Get all edition ids for a course
+	 *
+	 * @param  courseId The course id
+	 * @return          The list of edition ids
+	 */
+	public List<Long> getEditionsForCourse(Long courseId) {
+		return editionControllerApi.getAllEditionsByCourse(courseId).map(EditionDetailsDTO::getId)
+				.collect(Collectors.toList()).block();
+	}
+
 	// endregion
 }
diff --git a/src/main/java/nl/tudelft/tam/service/EmailService.java b/src/main/java/nl/tudelft/tam/service/EmailService.java
index 021a845d5e6946f2ea0dc5b9b119da65e70110a8..66c4bb0e86f7603cd350085bf2077c25aa74dce9 100644
--- a/src/main/java/nl/tudelft/tam/service/EmailService.java
+++ b/src/main/java/nl/tudelft/tam/service/EmailService.java
@@ -80,7 +80,6 @@ public class EmailService {
 
 		} catch (MessagingException e) {
 			e.printStackTrace();
-			// TODO what to do in this case
 		}
 
 		return CompletableFuture.completedFuture(null);
diff --git a/src/main/java/nl/tudelft/tam/service/ExtraWorkService.java b/src/main/java/nl/tudelft/tam/service/ExtraWorkService.java
index 9ca897f0466c73f8dd606ccfb5f6beb4f67cf52d..dd360049ab32898c1d628113b88c1042b346d8f4 100644
--- a/src/main/java/nl/tudelft/tam/service/ExtraWorkService.java
+++ b/src/main/java/nl/tudelft/tam/service/ExtraWorkService.java
@@ -70,6 +70,9 @@ public class ExtraWorkService {
 	@Autowired
 	CourseService courseService;
 
+	@Autowired
+	CohortService cohortService;
+
 	@Autowired
 	CSVService csvService;
 
@@ -290,8 +293,6 @@ public class ExtraWorkService {
 		List<EditionSummaryDTO> activeEditions = editionService.getAllActiveEditions(LocalDateTime.now());
 		List<EditionDetailsDTO> editions = editionService.getEditionsById(activeEditions.stream()
 				.filter(x -> !x.getIsArchived()).map(EditionSummaryDTO::getId).toList());
-		List<CourseDetailsDTO> courses = courseService
-				.getCoursesById(editions.stream().map(e -> e.getCourse().getId()).distinct().toList());
 
 		List<ExtraWork> result = new ArrayList<>();
 
@@ -301,9 +302,12 @@ public class ExtraWorkService {
 			String editionName = line[0];
 			String courseCode = line[1];
 
-			EditionDetailsDTO edition = editions.stream().filter(
-					e -> e.getCourse().getCode().equals(courseCode) && e.getName().equals(editionName))
-					.findAny().get();
+			EditionDetailsDTO edition = editions
+					.stream()
+					.filter(e -> e.getCourse().getCode().equals(courseCode)
+							&& e.getName().equals(editionName))
+					.findAny()
+					.get();
 
 			work.setEditionId(edition.getId());
 			work.setName(line[2]);
diff --git a/src/main/java/nl/tudelft/tam/service/JobOfferService.java b/src/main/java/nl/tudelft/tam/service/JobOfferService.java
index 3b725c206f21bad5cc696670ace51a283c639535..378309883590f45663f6d4428a27efacc104706a 100644
--- a/src/main/java/nl/tudelft/tam/service/JobOfferService.java
+++ b/src/main/java/nl/tudelft/tam/service/JobOfferService.java
@@ -22,7 +22,9 @@ import java.nio.file.Path;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import javax.transaction.Transactional;
 import javax.validation.constraints.NotNull;
@@ -36,16 +38,12 @@ import nl.tudelft.tam.enums.Status;
 import nl.tudelft.tam.exception.WrongDataCallException;
 import nl.tudelft.tam.model.Application;
 import nl.tudelft.tam.model.JobOffer;
-import nl.tudelft.tam.model.Profile;
 import nl.tudelft.tam.repository.JobOfferRepository;
 
-import org.apache.commons.lang3.tuple.MutablePair;
-import org.apache.commons.lang3.tuple.Pair;
 import org.modelmapper.ModelMapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Lazy;
-import org.springframework.data.rest.webmvc.ResourceNotFoundException;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -96,6 +94,9 @@ public class JobOfferService {
 	@Autowired
 	CohortService cohortService;
 
+	@Autowired
+	CoordinatorService coordinatorService;
+
 	@Autowired
 	CoordinatorDefaultService coordinatorDefaultService;
 
@@ -266,24 +267,34 @@ public class JobOfferService {
 				.map(o -> mapper.map(o, JobOfferSummaryDTO.class)).collect(Collectors.toList());
 	}
 
+	/**
+	 * Gets the most common approve/disapprove action-maker on TAM since that person will also approve in
+	 * FlexDelft
+	 *
+	 * @param  editionId the id of the edition for which to find the approver
+	 * @return           The person who is the most common approver/disapprover on TAM for that edition
+	 */
 	public PersonSummaryDTO getApprover(Long editionId) {
-		List<PersonSummaryDTO> teachers = roleService.getTeachersById(editionId).stream()
-				.map(t -> new MutablePair<PersonSummaryDTO, Integer>(t.getPerson(), 0))
-				.peek(tPair -> {
-					try {
-						Profile profile = profileService.findByIdOrThrow(tPair.getKey().getId());
-						tPair.setValue(profile.getHandledDeclarations().size()
-								+ profile.getHandledApplications().size());
-					} catch (ResourceNotFoundException e) {
-						tPair.setValue(0);
-					}
-				})
-				.sorted(Comparator.comparingInt(Pair::getValue))
-				.map(Pair::getKey)
-				.collect(Collectors.toList());
+		Stream<PersonSummaryDTO> coordinators = coordinatorService.getCoordinatorsByEditionId(editionId)
+				.stream()
+				.map(coord -> personService.getOrThrow(coord.getPersonId()));
+		Stream<PersonSummaryDTO> teachers = roleService.getTeachersById(editionId)
+				.stream()
+				.map(RolePersonDetailsDTO::getPerson);
+		Stream<PersonSummaryDTO> both = Stream.concat(teachers, coordinators);
 
 		// Return the teacher with the most TAM actions
-		return teachers.get(0);
+		return both.collect(Collectors.toMap(
+				Function.identity(),
+				p -> profileService.findById(p.getId())
+						.map(profile -> profile.getHandledDeclarations().size()
+								+ profile.getHandledApplications().size())
+						.orElse(0)))
+				.entrySet()
+				.stream()
+				.max(Map.Entry.comparingByValue())
+				.map(Map.Entry::getKey)
+				.orElse(null);
 	}
 
 	/**
@@ -353,17 +364,24 @@ public class JobOfferService {
 			String editionName = line[0];
 			String courseCode = line[1];
 
-			Optional<EditionDetailsDTO> matchingEdition = editions.stream().filter(
-					e -> e.getCourse().getCode().equals(courseCode) && e.getName().equals(editionName))
+			Optional<EditionDetailsDTO> matchingEdition = editions
+					.stream()
+					.filter(e -> e.getCourse().getCode().equals(courseCode)
+							&& e.getName().equals(editionName))
 					.findAny();
 
 			EditionDetailsDTO edition = matchingEdition.orElseGet(() -> {
-				CourseSummaryDTO course = courses.stream().filter(c -> c.getCode().equals(courseCode))
+				CourseSummaryDTO course = courses
+						.stream()
+						.filter(c -> c.getCode().equals(courseCode))
+						.findAny()
+						.get();
+				CohortDetailsDTO cohort = cohorts
+						.stream()
+						.filter(c -> c.getProgram().getName().equals(line[12])
+								&& c.getName().equals(line[11]))
 						.findAny()
 						.get();
-				CohortDetailsDTO cohort = cohorts.stream().filter(
-						c -> c.getProgram().getName().equals(line[12]) && c.getName().equals(line[11]))
-						.findAny().get();
 				return editionService.getEditionById(editionService.addEdition(new EditionCreateDTO()
 						.name(editionName)
 						.course(new CourseIdDTO().id(course.getId()))
diff --git a/src/main/java/nl/tudelft/tam/service/ProfileService.java b/src/main/java/nl/tudelft/tam/service/ProfileService.java
index b35a722cfd226a8f028b5cff95565bd818b65e7c..2d337cee272b45757dd892950161ac35076afc2e 100644
--- a/src/main/java/nl/tudelft/tam/service/ProfileService.java
+++ b/src/main/java/nl/tudelft/tam/service/ProfileService.java
@@ -17,6 +17,8 @@
  */
 package nl.tudelft.tam.service;
 
+import java.util.Optional;
+
 import javax.validation.constraints.NotNull;
 
 import nl.tudelft.tam.dto.patch.NotificationPatchDTO;
@@ -44,6 +46,16 @@ public class ProfileService {
 		return repository.findByIdOrThrow(id);
 	}
 
+	/**
+	 * Finds the profile object by id
+	 *
+	 * @param  id The id to find
+	 * @return    The object found wrapped in an optional
+	 */
+	public Optional<Profile> findById(Long id) {
+		return repository.findById(id);
+	}
+
 	/**
 	 * Updates the polo information for a person
 	 *
diff --git a/src/main/java/nl/tudelft/tam/service/ProgramService.java b/src/main/java/nl/tudelft/tam/service/ProgramService.java
index a0d1d7c932c65c3cfe89b0aaffeefe92795243ff..eefcfac33b429147e344c4b73b0f5a300159979f 100644
--- a/src/main/java/nl/tudelft/tam/service/ProgramService.java
+++ b/src/main/java/nl/tudelft/tam/service/ProgramService.java
@@ -21,6 +21,7 @@ import java.util.List;
 
 import nl.tudelft.labracore.api.ProgramControllerApi;
 import nl.tudelft.labracore.api.dto.ProgramDetailsDTO;
+import nl.tudelft.labracore.api.dto.ProgramSummaryDTO;
 import nl.tudelft.tam.repository.CoordinatorRepository;
 
 import org.springframework.beans.factory.annotation.Autowired;
@@ -30,10 +31,10 @@ import org.springframework.stereotype.Service;
 public class ProgramService {
 
 	@Autowired
-	ProgramControllerApi programApi;
+	private ProgramControllerApi programApi;
 
 	@Autowired
-	CoordinatorRepository coordinatorRepository;
+	private CoordinatorRepository coordinatorRepository;
 
 	/**
 	 * Get a program by id
@@ -55,16 +56,30 @@ public class ProgramService {
 		return programApi.getAllProgramsById(ids).collectList().block();
 	}
 
-	/*
+	public List<ProgramSummaryDTO> getAllPrograms() {
+		return programApi.getAllPrograms().collectList().block();
+	}
+
+	/**
 	 * Gets all programs coordinated by a coordinator.
 	 *
-	 * @param coordinatorId The id of the coordinator
+	 * @param  coordinatorId The id of the coordinator
 	 *
-	 * @return All program details coordinated
+	 * @return               All program details coordinated
 	 */
 	public List<ProgramDetailsDTO> getCoordinatingPrograms(Long coordinatorId) {
 		return coordinatorRepository.findAllByPersonId(coordinatorId).stream()
 				.map(c -> programApi.getProgramById(c.getProgramId()).block()).toList();
 	}
 
+	/**
+	 * Returns a list of all the programs which are relevant to the person.
+	 *
+	 * @param  personId The person to get the programs for
+	 * @return          The list of programs
+	 */
+	public List<ProgramSummaryDTO> getAllRelevantPrograms(Long personId) {
+		return programApi.getAllRelevantPrograms(personId).collectList().block();
+	}
+
 }
diff --git a/src/main/java/nl/tudelft/tam/service/RaiseRequestService.java b/src/main/java/nl/tudelft/tam/service/RaiseRequestService.java
index b86b0db93c9d387fadd70cf9c8437bd63e8b566c..fd9a01344da9075bb1d6327aed8d782681f6b399 100644
--- a/src/main/java/nl/tudelft/tam/service/RaiseRequestService.java
+++ b/src/main/java/nl/tudelft/tam/service/RaiseRequestService.java
@@ -24,6 +24,7 @@ import java.util.stream.Collectors;
 import javax.validation.constraints.NotNull;
 
 import nl.tudelft.labracore.api.dto.PersonSummaryDTO;
+import nl.tudelft.labracore.api.dto.ProgramSummaryDTO;
 import nl.tudelft.labracore.lib.security.user.Person;
 import nl.tudelft.librador.dto.view.View;
 import nl.tudelft.tam.dto.create.RaiseRequestCreateDTO;
@@ -58,6 +59,9 @@ public class RaiseRequestService {
 	@Autowired
 	private PersonService personService;
 
+	@Autowired
+	private ProgramService programService;
+
 	@Value("${tam.filesys.payscale-proofs-dir}")
 	private String PROOF_DIRECTORY;
 
@@ -169,9 +173,11 @@ public class RaiseRequestService {
 	/**
 	 * Return all raise requests with status submitted.
 	 *
-	 * @return list of found raise requests
+	 * @param  programIds list of program ids for which to get all submitted raise requests
+	 * @return            list of found raise requests
 	 */
-	public List<RaiseRequestDetailsDTO> getAllSubmitted() throws InvalidDatabaseEntryException {
+	public List<RaiseRequestDetailsDTO> getAllSubmitted(List<Long> programIds)
+			throws InvalidDatabaseEntryException {
 
 		List<RaiseRequest> requests = raiseRequestRepository.findAllByStatus(Status.SUBMITTED);
 
@@ -186,19 +192,37 @@ public class RaiseRequestService {
 		List<PersonSummaryDTO> people = personService.getPeopleById(
 				profiles.stream().map(Profile::getId).collect(Collectors.toList()));
 
-		if (list.size() != people.size()) {
+		if (list.size() != people.size() || people.size() != profiles.size()) {
 			throw new InvalidDatabaseEntryException(
 					"The list of raise requests contains an invalid request, " +
 							"a matching person or profile was not found for at least one request.");
 		}
 
+		List<RaiseRequestDetailsDTO> filteredList = new ArrayList<>();
+
 		for (int i = 0; i < list.size(); i++) {
 			RaiseRequestDetailsDTO request = list.get(i);
-			request.setPerson(people.get(i));
-			request.setCurrentPayScale(profiles.get(i).getPayScale());
+
+			List<Long> relevantProgramIds = programService
+					.getAllRelevantPrograms(people.get(i).getId())
+					.stream()
+					.map(ProgramSummaryDTO::getId)
+					.collect(Collectors.toList());
+
+			for (Long programId : relevantProgramIds) {
+				if (programIds.contains(programId)) {
+					request.setPerson(people.get(i));
+					request.setCurrentPayScale(profiles.get(i).getPayScale());
+					request.setRelevantProgramIds(relevantProgramIds);
+
+					filteredList.add(request);
+					break;
+				}
+			}
+
 		}
 
-		return list;
+		return filteredList;
 	}
 
 	/**
diff --git a/src/main/java/nl/tudelft/tam/service/TrainingApprovalRequestService.java b/src/main/java/nl/tudelft/tam/service/TrainingApprovalRequestService.java
index 1615003f06d22273583ebdb7c5ecb6a673fe20f1..e3a21d5682bb4b114faa0957c80c94e10d80f1d6 100644
--- a/src/main/java/nl/tudelft/tam/service/TrainingApprovalRequestService.java
+++ b/src/main/java/nl/tudelft/tam/service/TrainingApprovalRequestService.java
@@ -22,6 +22,7 @@ import java.util.*;
 import java.util.stream.Collectors;
 
 import nl.tudelft.labracore.api.dto.PersonSummaryDTO;
+import nl.tudelft.labracore.api.dto.ProgramSummaryDTO;
 import nl.tudelft.labracore.lib.security.user.Person;
 import nl.tudelft.librador.dto.view.View;
 import nl.tudelft.tam.dto.create.TrainingApprovalRequestCreateDTO;
@@ -49,6 +50,9 @@ public class TrainingApprovalRequestService {
 	@Autowired
 	private PersonService personService;
 
+	@Autowired
+	private ProgramService programService;
+
 	@Autowired
 	private ModelMapper mapper;
 
@@ -122,9 +126,11 @@ public class TrainingApprovalRequestService {
 	/**
 	 * Return all training approval requests with status submitted.
 	 *
-	 * @return list of found training approval requests
+	 * @param  programIds list of program ids for which to get all submitted training approval requests
+	 * @return            list of found training approval requests
 	 */
-	public List<TrainingApprovalRequestDetailsDTO> getAllSubmitted() throws InvalidDatabaseEntryException {
+	public List<TrainingApprovalRequestDetailsDTO> getAllSubmitted(List<Long> programIds)
+			throws InvalidDatabaseEntryException {
 
 		List<TrainingApprovalRequest> requests = trainingApprovalRequestRepository
 				.findAllByStatus(Status.SUBMITTED);
@@ -148,12 +154,30 @@ public class TrainingApprovalRequestService {
 							"a matching person or profile was not found for at least one request.");
 		}
 
+		List<TrainingApprovalRequestDetailsDTO> filteredList = new ArrayList<>();
+
 		for (int i = 0; i < list.size(); i++) {
 			TrainingApprovalRequestDetailsDTO request = list.get(i);
-			request.setPerson(people.get(i));
+
+			List<Long> relevantProgramIds = programService
+					.getAllRelevantPrograms(people.get(i).getId())
+					.stream()
+					.map(ProgramSummaryDTO::getId)
+					.collect(Collectors.toList());
+
+			for (Long programId : relevantProgramIds) {
+				if (programIds.contains(programId)) {
+					request.setPerson(people.get(i));
+					request.setRelevantProgramIds(relevantProgramIds);
+
+					filteredList.add(request);
+					break;
+				}
+			}
+
 		}
 
-		return list;
+		return filteredList;
 	}
 
 	/**
diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties
index c901cf18b8e76c84b0a04da194bebd88ae373edc..00bec3fde6a7ea59ebbcdb01d96485255665ac66 100644
--- a/src/main/resources/messages.properties
+++ b/src/main/resources/messages.properties
@@ -113,7 +113,7 @@ jobOffer.add = New Job Offer
 jobOffer.import = Import Job Offers
 jobOffer.import.info = Import bulk job offers via a CSV file. Each job offer should be a separate row, with the following columns in this order:
 jobOffer.import.info.columnOrder = Edition Name (e.g 2022/2023), Course Code, Job Offer Name, Contract Name, Contract Start Date, Contract End Date, Contract Baan Code, Max Hours, Hiring Message, Rejection Message, Application Deadline
-jobOffer.import.info.editionCreate = If you want to create non-existing editions, add the following columns: Cohort Name, Program Name, Edition Start Date, Edition End Date
+jobOffer.import.info.editionCreate = If you want to create non-existing/new editions, add the following columns: Cohort Name, Program Name, Edition Start Date, Edition End Date
 jobOffer.deadline = Deadline For Applying
 jobOffer.deadline.none = No Deadline
 jobOffer.deadline.closed = Closed
@@ -156,6 +156,7 @@ jobOffer.export.beforeFirstExport = Before first export
 jobOffer.before = TAed Before
 jobOffer.queueFeedback = Queue Feedback
 jobOffer.queueFeedback.view = View feedback
+jobOffer.selectProgram = Select a programme to view job offers.
 
 application.all = All Applications
 application.my = My Applications
@@ -204,6 +205,7 @@ extraWork.add = New Extra Work
 extraWork.import = Import Extra Work
 extraWork.import.info = Import bulk extra work via a CSV file. Each extra work should be a separate row, with the following columns in this order:
 extraWork.import.info.columnOrder = Edition Name (e.g. 2022/2023), Course Code, Extra Work Name, Contract Name, Contract Baan Code, Max Hours, Contract Request Deadline
+extraWork.import.info.editionCreate = If you want to create non-existing/new editions, add the following columns: Cohort Name, Program Name, Edition Start Date, Edition End Date
 extraWork.deadline = Deadline For Contract Requests
 extraWork.deadline.none = No Deadline
 extraWork.deadline.closed = Closed
@@ -342,9 +344,9 @@ training.import.conflict.ignore = Ignore Conflicts & Close
 coordinator = Coordinator
 coordinator.portal = Coordinator Portal
 coordinator.manager.managed = Managed Courses
-coordinator.manager.all = All Courses
-coordinator.defaults = Manage Defaults
-coordinator.defaults.title = Manage Program Defaults
+coordinator.manager.all = Coordinating Courses
+coordinator.defaults = Manage Programmes
+coordinator.defaults.title = Manage Programmes
 coordinator.defaults.contractName = Contract Name
 coordinator.defaults.contractBaan = Baan Code
 coordinator.defaults.contractStartDate = Contract Start Date
diff --git a/src/main/resources/templates/coordinator/defaults.html b/src/main/resources/templates/coordinator/defaults.html
index c7b6d3bb23bb716c19e7c4d1191bde05c509d1b4..76d06a8b5c36dd81f494383f3aece47e60272a76 100644
--- a/src/main/resources/templates/coordinator/defaults.html
+++ b/src/main/resources/templates/coordinator/defaults.html
@@ -39,9 +39,11 @@
                 <h1 class="title" th:text="#{coordinator.defaults.title}"></h1>
             </div>
 
+            <hr />
+
             <div class="info_row_4x4">
                 <div class="card_stats card" th:each="currDefault : ${programNamesAndDefaults}">
-                    <h2 class="card_title" th:text="${currDefault.key}"></h2>
+                    <h2 class="card_title" th:text="|${currDefault.key} - Default Values|"></h2>
 
                     <h3 class="card_subtitle" th:text="#{extraWork}"></h3>
 
diff --git a/src/main/resources/templates/extra_work/import.html b/src/main/resources/templates/extra_work/import.html
index 7a3a805110a0d7054954fc786a764885423b3992..6aa879fd1bad9a5672d681ab912c258601d8fe7d 100644
--- a/src/main/resources/templates/extra_work/import.html
+++ b/src/main/resources/templates/extra_work/import.html
@@ -36,10 +36,11 @@
                 <h1 class="underlined title" th:text="#{extraWork.import}"></h1>
                 <div class="form-group maxw-60">
                     <span>
-                        <span th:text="#{extraWork.import.info}"></span>
+                        <p th:text="#{extraWork.import.info}"></p>
                         <br />
+                        <p th:text="#{extraWork.import.info.columnOrder}"></p>
                         <br />
-                        <span th:text="#{extraWork.import.info.columnOrder}"></span>
+                        <p th:text="#{extraWork.import.info.editionCreate}"></p>
                     </span>
                 </div>
 
diff --git a/src/main/resources/templates/job_offer/add_offer.html b/src/main/resources/templates/job_offer/add_offer.html
index 3df7e93ab52964b7b22649391feca9a6a1a6e713..23261be44319206000113f5c098386c18dcde885 100644
--- a/src/main/resources/templates/job_offer/add_offer.html
+++ b/src/main/resources/templates/job_offer/add_offer.html
@@ -30,7 +30,7 @@
             <form
                 th:id="add-offer-form"
                 th:action="@{/person/find-candidate}"
-                th:method="get"></form>
+                th:method="post"></form>
 
             <div class="boxed-content">
                 <h1 class="underlined title" th:text="#{jobOffer.addOffer}"></h1>
diff --git a/src/main/resources/templates/job_offer/confirm_retract_app.html b/src/main/resources/templates/job_offer/confirm_retract_app.html
index f2f8a514031fa38d74fb3cf64505950e3f39beff..32c8b2dd0a32b4bb9367e86e2be2330a181b8d99 100644
--- a/src/main/resources/templates/job_offer/confirm_retract_app.html
+++ b/src/main/resources/templates/job_offer/confirm_retract_app.html
@@ -34,6 +34,12 @@
                 class="boxed-content">
                 <h1 class="underlined title" th:text="#{jobOffer.retract.confirm}"></h1>
 
+                <input
+                    th:if="${param.program}"
+                    type="hidden"
+                    name="program"
+                    th:value="${param.program}" />
+
                 <div class="form-group">
                     <span class="form-group-desc" th:text="#{jobOffer.retract.confirm.desc}"></span>
                     <br />
diff --git a/src/main/resources/templates/job_offer/import.html b/src/main/resources/templates/job_offer/import.html
index 17981aae791558038b808939be753fed248054e7..5fd6e4621f190a2cad84a4b76434060e0225e492 100644
--- a/src/main/resources/templates/job_offer/import.html
+++ b/src/main/resources/templates/job_offer/import.html
@@ -37,7 +37,9 @@
                 <div class="form-group maxw-60">
                     <div>
                         <p th:text="#{jobOffer.import.info}"></p>
+                        <br />
                         <p th:text="#{jobOffer.import.info.columnOrder}"></p>
+                        <br />
                         <p th:text="#{jobOffer.import.info.editionCreate}"></p>
                     </div>
                 </div>
diff --git a/src/main/resources/templates/job_offer/view_many.html b/src/main/resources/templates/job_offer/view_many.html
index 928f34c27257345a00b977ff7e3981a5bc35bba4..824766698f0e41d75cee43e25a48d8a64fc9f5b4 100644
--- a/src/main/resources/templates/job_offer/view_many.html
+++ b/src/main/resources/templates/job_offer/view_many.html
@@ -29,20 +29,6 @@
         <link rel="stylesheet" type="text/css" th:href="@{/css/applications.css}" />
 
         <title th:text="#{jobOffer.many}"></title>
-
-        <script th:inline="text">
-            let currentTab = "[[${tab}]]";
-            function switchTab(to) {
-                if (to !== currentTab) {
-                    document.getElementById("offers").classList.toggle("hidden");
-                    document.getElementById("applications").classList.toggle("hidden");
-                    document.getElementById("offers-tab").classList.toggle("active");
-                    document.getElementById("applications-tab").classList.toggle("active");
-                    window.history.replaceState(null, document.title, "/job-offer/open?tab=" + to);
-                }
-                currentTab = to;
-            }
-        </script>
     </head>
 
     <body>
@@ -70,11 +56,12 @@
                 <div class="title-and-search">
                     <h1 class="title" th:text="#{jobOffer.many}"></h1>
 
-                    <form class="search">
+                    <form class="search" id="search-form">
                         <input
                             name="q"
+                            id="job-offer-search"
                             class="search_field"
-                            aria-label="Global search"
+                            aria-label="Search job offers"
                             type="search"
                             th:value="${param.q}"
                             th:placeholder="#{jobOffer.search}" />
@@ -84,6 +71,20 @@
                     </form>
                 </div>
 
+                <div>
+                    <label for="program-select" style="margin-right: 0.25rem">
+                        View job offers for:
+                    </label>
+                    <select id="program-select" class="selectbox">
+                        <option disabled selected>Select study program</option>
+                        <option
+                            th:each="program : ${programs}"
+                            th:value="${program.id}"
+                            th:selected="${param.program?.toString() == program.id.toString()}"
+                            th:text="${program.name}"></option>
+                    </select>
+                </div>
+
                 <div class="non_empty" th:unless="${editions.isEmpty()}">
                     <div class="accordion">
                         <table
@@ -138,6 +139,11 @@
                                         th:action="@{|/application/submit/${offer.id}|}"
                                         method="post"
                                         data-scroll-to="true">
+                                        <input
+                                            th:if="${param.program}"
+                                            type="hidden"
+                                            name="program"
+                                            th:value="${param.program}" />
                                         <input
                                             type="submit"
                                             class="accordion__action"
@@ -163,6 +169,11 @@
                                         th:action="@{|/application/accept/${offer.id}|}"
                                         method="post"
                                         data-scroll-to="true">
+                                        <input
+                                            th:if="${param.program}"
+                                            type="hidden"
+                                            name="program"
+                                            th:value="${param.program}" />
                                         <input
                                             type="submit"
                                             class="accordion__action"
@@ -194,7 +205,14 @@
                 </div>
 
                 <div data-empty="true" th:if="${editions.isEmpty()}">
-                    <span class="empty_description" th:text="#{jobOffer.empty.description}"></span>
+                    <span
+                        th:if="${param.program}"
+                        class="empty_description"
+                        th:text="#{jobOffer.empty.description}"></span>
+                    <span
+                        th:unless="${param.program}"
+                        class="empty_description"
+                        th:text="#{jobOffer.selectProgram}"></span>
                 </div>
             </div>
 
@@ -293,6 +311,39 @@
                     </tr>
                 </table>
             </div>
+
+            <script th:inline="text">
+                let currentTab = "[[${tab}]]";
+                function switchTab(to) {
+                    if (to !== currentTab) {
+                        document.getElementById("offers").classList.toggle("hidden");
+                        document.getElementById("applications").classList.toggle("hidden");
+                        document.getElementById("offers-tab").classList.toggle("active");
+                        document.getElementById("applications-tab").classList.toggle("active");
+                        window.history.replaceState(
+                            null,
+                            document.title,
+                            "/job-offer/open?tab=" + to
+                        );
+                    }
+                    currentTab = to;
+                }
+
+                $(() => {
+                    $("#program-select").change(function () {
+                        let url = new URL(window.location);
+                        url.searchParams.set("program", $(this).val());
+                        window.location = url.toString();
+                    });
+
+                    $("#search-form").submit(function (event) {
+                        event.preventDefault();
+                        let url = new URL(window.location);
+                        url.searchParams.set("q", $(this).find("input[name='q']").val());
+                        window.location = url.toString();
+                    });
+                });
+            </script>
         </div>
     </body>
 </html>
diff --git a/src/test/java/nl/tudelft/tam/controller/JobOfferControllerTest.java b/src/test/java/nl/tudelft/tam/controller/JobOfferControllerTest.java
index 9c85ae1b7b6b5047e5eadd527887f07eef6bb5bd..86f38442bd67eddc40fa838bd5dbcfca942d2153 100644
--- a/src/test/java/nl/tudelft/tam/controller/JobOfferControllerTest.java
+++ b/src/test/java/nl/tudelft/tam/controller/JobOfferControllerTest.java
@@ -38,7 +38,6 @@ import nl.tudelft.tam.dto.view.summary.ApplicationSummaryDTO;
 import nl.tudelft.tam.dto.view.summary.ExtraWorkSummaryDTO;
 import nl.tudelft.tam.dto.view.summary.JobOfferSummaryDTO;
 import nl.tudelft.tam.enums.Status;
-import nl.tudelft.tam.model.Coordinator;
 import nl.tudelft.tam.model.CoordinatorDefault;
 import nl.tudelft.tam.model.JobOffer;
 import nl.tudelft.tam.model.embeddables.ExtraWorkDefault;
@@ -101,6 +100,9 @@ class JobOfferControllerTest {
 	@MockBean
 	CoordinatorService coordinatorService;
 
+	@MockBean
+	ProgramService programService;
+
 	@MockBean
 	CoordinatorDefaultService coordinatorDefaultService;
 
@@ -126,7 +128,7 @@ class JobOfferControllerTest {
 	@BeforeEach
 	void setUp() {
 		edition = new EditionDetailsDTO().id(EDITION_ID)
-				.course(new CourseSummaryDTO().name("course-name").code("course-code"))
+				.course(new CourseSummaryDTO().id(1L).name("course-name").code("course-code"))
 				.cohort(new CohortSummaryDTO().name("cohort-name")).name("edition-name")
 				.endDate(LocalDateTime.now().plusMonths(2));
 
@@ -186,6 +188,10 @@ class JobOfferControllerTest {
 	@Test
 	@WithUserDetails("username")
 	void getOpenTest() throws Exception {
+		when(programService.getAllPrograms()).thenReturn(List.of(new ProgramSummaryDTO().id(1L)));
+		when(courseService.getAllCoursesInProgram(anyLong()))
+				.thenReturn(List.of(new CourseSummaryDTO().id(1L)));
+
 		ApplicationDetailsJobOfferDTO ap1 = mapper.map(app1a, ApplicationDetailsJobOfferDTO.class);
 		ap1.setJobOffer(offer1);
 
@@ -216,7 +222,7 @@ class JobOfferControllerTest {
 
 		when(applicationService.getMapWithStatusAppOpenByIdForPerson(anyLong(), anyList())).thenReturn(apps);
 
-		mvc.perform(get("/job-offer/open").with(csrf()))
+		mvc.perform(get("/job-offer/open").param("program", "1").with(csrf()))
 				.andExpect(status().isOk())
 				.andExpect(view().name("job_offer/view_many"))
 				.andExpect(model().attribute("editions", editions))
@@ -233,6 +239,10 @@ class JobOfferControllerTest {
 	@Test
 	@WithUserDetails("username")
 	void getOpenWithQueryTest() throws Exception {
+		when(programService.getAllPrograms()).thenReturn(List.of(new ProgramSummaryDTO().id(1L)));
+		when(courseService.getAllCoursesInProgram(anyLong()))
+				.thenReturn(List.of(new CourseSummaryDTO().id(1L)));
+
 		String query = "test-query";
 
 		ApplicationDetailsJobOfferDTO ap1 = mapper.map(app1a, ApplicationDetailsJobOfferDTO.class);
@@ -264,7 +274,7 @@ class JobOfferControllerTest {
 
 		when(applicationService.getMapWithStatusAppOpenByIdForPerson(anyLong(), anyList())).thenReturn(apps);
 
-		mvc.perform(get("/job-offer/open").param("q", query).with(csrf()))
+		mvc.perform(get("/job-offer/open").param("q", query).param("program", "1").with(csrf()))
 				.andExpect(status().isOk())
 				.andExpect(view().name("job_offer/view_many"))
 				.andExpect(model().attribute("editions", editions))
@@ -284,7 +294,7 @@ class JobOfferControllerTest {
 		String q = "edi";
 		RoleEditionDetailsDTO role = new RoleEditionDetailsDTO().type(RoleEditionDetailsDTO.TypeEnum.TEACHER)
 				.edition(new EditionSummaryDTO().id(EDITION_ID));
-		List<Long> editionIds = List.of(EDITION_ID);
+		List<Long> editionIds = List.of();
 		List<EditionDetailsOffersWorkDTO> editions = List
 				.of(mapper.map(edition, EditionDetailsOffersWorkDTO.class));
 		editions.get(0).setOffers(List.of(offer1, offer2));
@@ -312,33 +322,36 @@ class JobOfferControllerTest {
 				.andExpect(model().attribute("managed", List.of()))
 				.andExpect(model().attribute("cohorts", List.of()));
 
-		verify(personService).getRolesForPerson(anyLong());
+		verify(editionService).getAllEditionIdsThatPersonIsAMangerOf(anyLong());
+		verify(courseService).getManagingCourses(any());
+		verify(courseService).getCoursesById(anyList());
 		verify(editionService).getEditionsWithJobsAndWork(editionIds);
 		verify(editionService).filter(editions, q);
+		verify(coordinatorDefaultService).addDefaultsToEditionsWithJobsAndWork(anyList());
 	}
 
 	@Test
 	@WithUserDetails("admin")
 	void getManagerPortalTestWithHidePrev() throws Exception {
+		when(authService.isManagerOfAny()).thenReturn(true);
+
 		String q = "edi";
-		RoleEditionDetailsDTO role = new RoleEditionDetailsDTO().type(RoleEditionDetailsDTO.TypeEnum.TEACHER)
-				.edition(new EditionSummaryDTO().id(EDITION_ID));
-		List<Long> editionIds = List.of(EDITION_ID);
+		List<Long> editionIds = List.of();
+
 		List<EditionDetailsOffersWorkDTO> editions = List
 				.of(mapper.map(edition, EditionDetailsOffersWorkDTO.class));
 		editions.get(0).setOffers(List.of(offer1, offer2));
 		editions.get(0).setWork(List.of(work1, work2));
 		editions.get(0).setDefaults(cseDefault);
+
 		List<EditionDetailsOffersWorkDTO> filtered = List
 				.of(mapper.map(edition, EditionDetailsOffersWorkDTO.class));
 		filtered.get(0).setOffers(List.of(offer1));
 		filtered.get(0).setWork(List.of(work1));
 		filtered.get(0).setDefaults(cseDefault);
 
-		when(personService.getRolesForPerson(anyLong())).thenReturn(List.of(role));
 		when(editionService.getEditionsWithJobsAndWork(anyList())).thenReturn(editions);
 		when(editionService.filter(anyList(), anyString())).thenReturn(filtered);
-		when(authService.isManagerOfAny()).thenReturn(true);
 
 		doNothing().when(coordinatorDefaultService).addDefaultsToEditionsWithJobsAndWork(anyList());
 
@@ -352,9 +365,12 @@ class JobOfferControllerTest {
 				.andExpect(model().attribute("managed", List.of()))
 				.andExpect(model().attribute("cohorts", List.of()));
 
-		verify(personService).getRolesForPerson(anyLong());
+		verify(editionService).getAllEditionIdsThatPersonIsAMangerOf(anyLong());
+		verify(courseService).getManagingCourses(any());
+		verify(courseService).getCoursesById(anyList());
 		verify(editionService).getEditionsWithJobsAndWork(editionIds);
 		verify(editionService).filter(editions, q);
+		verify(coordinatorDefaultService).addDefaultsToEditionsWithJobsAndWork(anyList());
 	}
 
 	@Test
@@ -362,11 +378,10 @@ class JobOfferControllerTest {
 	void getManagerPortalAllTest() throws Exception {
 		when(authService.isCoordinatorOfAny()).thenReturn(true);
 
-		Coordinator coordinator = Coordinator.builder().programId(EDITION_ID).build();
-		List<Coordinator> coordinatingList = List.of(coordinator);
-		when(coordinatorService.findAllByPersonId(anyLong())).thenReturn(coordinatingList);
-
-		when(editionService.getAllEditionIds()).thenReturn(List.of(EDITION_ID));
+		when(coordinatorService.getProgramIdsByPersonId(anyLong())).thenReturn(Set.of(1L));
+		when(courseService.getAllCoursesInProgram(anyLong()))
+				.thenReturn(List.of(new CourseSummaryDTO().id(1L)));
+		when(editionService.getEditionsForCourse(anyLong())).thenReturn(List.of(EDITION_ID));
 
 		List<EditionDetailsOffersWorkDTO> editions = List
 				.of(mapper.map(edition, EditionDetailsOffersWorkDTO.class));
@@ -391,10 +406,13 @@ class JobOfferControllerTest {
 				.andExpect(model().attribute("showAll", true))
 				.andExpect(model().attribute("hidePrev", true));
 
-		verify(coordinatorService).findAllByPersonId(anyLong());
-		verify(editionService).getAllEditionIds();
+		verify(coordinatorService).getProgramIdsByPersonId(anyLong());
+		verify(courseService).getAllCoursesInProgram(anyLong());
+		verify(editionService).getEditionsForCourse(anyLong());
+		verify(cohortService).getCohortsByProgrammeIds(anyList());
 		verify(editionService).getEditionsWithJobsAndWork(List.of(EDITION_ID));
 		verify(editionService).filter(editions, null);
+		verify(coordinatorDefaultService).addDefaultsToEditionsWithJobsAndWork(anyList());
 	}
 
 	@Test
@@ -404,11 +422,10 @@ class JobOfferControllerTest {
 
 		when(authService.isCoordinatorOfAny()).thenReturn(true);
 
-		Coordinator coordinator = Coordinator.builder().programId(EDITION_ID).build();
-		List<Coordinator> coordinatingList = List.of(coordinator);
-		when(coordinatorService.findAllByPersonId(anyLong())).thenReturn(coordinatingList);
-
-		when(editionService.getAllEditionIds()).thenReturn(List.of(EDITION_ID));
+		when(coordinatorService.getProgramIdsByPersonId(anyLong())).thenReturn(Set.of(1L));
+		when(courseService.getAllCoursesInProgram(anyLong()))
+				.thenReturn(List.of(new CourseSummaryDTO().id(1L)));
+		when(editionService.getEditionsForCourse(anyLong())).thenReturn(List.of(EDITION_ID));
 
 		List<EditionDetailsOffersWorkDTO> editions = List
 				.of(mapper.map(edition, EditionDetailsOffersWorkDTO.class));
@@ -417,9 +434,6 @@ class JobOfferControllerTest {
 		editions.get(0).setDefaults(cseDefault);
 		when(editionService.getEditionsWithJobsAndWork(any())).thenReturn(editions);
 
-		when(courseService.getOrThrow(any()))
-				.thenReturn(new CourseDetailsDTO().program(new ProgramSummaryDTO().id(EDITION_ID)));
-
 		when(editionService.filter(anyList(), eq(q))).thenReturn(editions);
 
 		doNothing().when(coordinatorDefaultService).addDefaultsToEditionsWithJobsAndWork(anyList());
@@ -433,10 +447,13 @@ class JobOfferControllerTest {
 				.andExpect(model().attribute("showAll", true))
 				.andExpect(model().attribute("hidePrev", true));
 
-		verify(coordinatorService).findAllByPersonId(anyLong());
-		verify(editionService).getAllEditionIds();
+		verify(coordinatorService).getProgramIdsByPersonId(anyLong());
+		verify(courseService).getAllCoursesInProgram(anyLong());
+		verify(editionService).getEditionsForCourse(anyLong());
+		verify(cohortService).getCohortsByProgrammeIds(anyList());
 		verify(editionService).getEditionsWithJobsAndWork(List.of(EDITION_ID));
 		verify(editionService).filter(editions, q);
+		verify(coordinatorDefaultService).addDefaultsToEditionsWithJobsAndWork(anyList());
 	}
 
 	@Test
diff --git a/src/test/java/nl/tudelft/tam/service/ApplicationServiceMockTest.java b/src/test/java/nl/tudelft/tam/service/ApplicationServiceMockTest.java
index 73d1fc6da786af35460f2cabed122e6fe0e931a3..d4453f61cfa93ea9ffa1376ed480e18c94ab91fd 100644
--- a/src/test/java/nl/tudelft/tam/service/ApplicationServiceMockTest.java
+++ b/src/test/java/nl/tudelft/tam/service/ApplicationServiceMockTest.java
@@ -18,6 +18,7 @@
 package nl.tudelft.tam.service;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.Mockito.*;
 
 import java.io.IOException;
@@ -140,8 +141,12 @@ class ApplicationServiceMockTest {
 	@BeforeEach
 	void setUp() {
 		offer1 = JobOffer.builder().name("offer-1").id(JOFFER_ID_1).editionId(EDITION_ID)
+				.contractStartDate(LocalDate.of(2023, 2, 1))
+				.contractEndDate(LocalDate.of(2023, 2, 2))
 				.deadline(LocalDate.now().plusDays(1)).build();
 		offer2 = JobOffer.builder().name("offer-2").id(JOFFER_ID_2).editionId(EDITION_ID)
+				.contractStartDate(LocalDate.of(2023, 2, 1))
+				.contractEndDate(LocalDate.of(2023, 2, 2))
 				.deadline(LocalDate.now().plusDays(2)).build();
 
 		app1a = Application.builder().id(new Application.AppId(PERSON_ID_1, JOFFER_ID_1)).jobOffer(offer1)
@@ -675,8 +680,8 @@ class ApplicationServiceMockTest {
 								"Contract Name Default",
 								"null",
 								"SA2",
-								"null",
-								"null",
+								"01-02-2023",
+								"02-02-2023",
 								"1",
 								"" },
 
@@ -688,9 +693,17 @@ class ApplicationServiceMockTest {
 								"Contract Name Default",
 								"null",
 								"SA2",
-								"null",
-								"null",
+								"01-02-2023",
+								"02-02-2023",
 								"1",
 								"" });
 	}
+
+	@Test
+	void getNumberOfUnhandledApplicationsTest() {
+		when(service.getApplicationsForJobOffer(anyLong())).thenReturn(List.of());
+		when(service.getStatsForApps(anyList())).thenReturn(new int[] { 10, 1, 2, 3 });
+
+		assertEquals(4, service.getNumberOfUnhandledApplications(1L));
+	}
 }
diff --git a/src/test/java/nl/tudelft/tam/service/RaiseRequestServiceMockTest.java b/src/test/java/nl/tudelft/tam/service/RaiseRequestServiceMockTest.java
index 2ca32b910dd9f7e21e1f4ad71f16860b2cbb8c3f..c59a50286de961bfdeaeeb154e66973c2dadb1dc 100644
--- a/src/test/java/nl/tudelft/tam/service/RaiseRequestServiceMockTest.java
+++ b/src/test/java/nl/tudelft/tam/service/RaiseRequestServiceMockTest.java
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Optional;
 
 import nl.tudelft.labracore.api.dto.PersonSummaryDTO;
+import nl.tudelft.labracore.api.dto.ProgramSummaryDTO;
 import nl.tudelft.labracore.lib.security.user.Person;
 import nl.tudelft.tam.dto.create.RaiseRequestCreateDTO;
 import nl.tudelft.tam.dto.view.details.RaiseRequestDetailsDTO;
@@ -65,6 +66,9 @@ class RaiseRequestServiceMockTest {
 	@MockBean
 	PersonService personService;
 
+	@MockBean
+	ProgramService programService;
+
 	@MockBean
 	ProfileService profileService;
 
@@ -142,7 +146,8 @@ class RaiseRequestServiceMockTest {
 
 		when(personService.getPeopleById(anyList())).thenReturn(List.of());
 
-		assertThrows(InvalidDatabaseEntryException.class, () -> raiseRequestService.getAllSubmitted());
+		assertThrows(InvalidDatabaseEntryException.class,
+				() -> raiseRequestService.getAllSubmitted(List.of(1L)));
 
 		verify(personService).getPeopleById(List.of(STUDENT_ID));
 	}
@@ -153,8 +158,10 @@ class RaiseRequestServiceMockTest {
 		String studentName = "abc-student-4984654";
 		when(personService.getPeopleById(anyList()))
 				.thenReturn(List.of(new PersonSummaryDTO().id(STUDENT_ID).externalId(studentName)));
+		when(programService.getAllRelevantPrograms(anyLong()))
+				.thenReturn(List.of(new ProgramSummaryDTO().id(1L).name("Test")));
 
-		List<RaiseRequestDetailsDTO> result = raiseRequestService.getAllSubmitted();
+		List<RaiseRequestDetailsDTO> result = raiseRequestService.getAllSubmitted(List.of(1L));
 
 		assertThat(result.size()).isEqualTo(1);
 		assertThat(result.get(0).getId()).isEqualTo(REQUEST_ID);
diff --git a/src/test/java/nl/tudelft/tam/service/RaiseRequestServiceTest.java b/src/test/java/nl/tudelft/tam/service/RaiseRequestServiceTest.java
index ad72801964438ba7e63c0f5ac2342182da3de406..497ecf43b36ab4939d2a31fdceccf73814544e86 100644
--- a/src/test/java/nl/tudelft/tam/service/RaiseRequestServiceTest.java
+++ b/src/test/java/nl/tudelft/tam/service/RaiseRequestServiceTest.java
@@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.*;
 
 import java.io.IOException;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import javax.transaction.Transactional;
@@ -142,8 +143,6 @@ class RaiseRequestServiceTest {
 		boolean res = raiseRequestService.newRaiseRequest(createDTO, fileb);
 
 		assertThat(res).isFalse();
-
-		//TODO proof didn't get replaced
 	}
 
 	@Test
@@ -156,8 +155,6 @@ class RaiseRequestServiceTest {
 
 		assertThat(res).isTrue();
 		assertThat(raiseRequestRepository.findByRequesterAndSubmitted(profile.getId())).isPresent();
-
-		// TODO check proof is stored
 	}
 
 	@Test
@@ -170,8 +167,6 @@ class RaiseRequestServiceTest {
 
 		assertThat(res).isTrue();
 		assertThat(raiseRequestRepository.findByRequesterAndSubmitted(profile.getId())).isPresent();
-
-		// TODO check request is retracted
 	}
 
 	@Test
@@ -196,7 +191,7 @@ class RaiseRequestServiceTest {
 	void getAllSubmittedEmpty() throws InvalidDatabaseEntryException {
 		raiseRequestRepository.deleteAll();
 
-		assertThat(raiseRequestService.getAllSubmitted().size()).isEqualTo(0);
+		assertThat(raiseRequestService.getAllSubmitted(List.of()).size()).isEqualTo(0);
 	}
 
 	@Test
diff --git a/src/test/java/nl/tudelft/tam/service/TrainingApprovalRequestServiceMockTest.java b/src/test/java/nl/tudelft/tam/service/TrainingApprovalRequestServiceMockTest.java
index 44e97358ea63e650869c6a82c48adc4c1664cc70..7b0a94fadae8848de36728d30203eb56a520cac7 100644
--- a/src/test/java/nl/tudelft/tam/service/TrainingApprovalRequestServiceMockTest.java
+++ b/src/test/java/nl/tudelft/tam/service/TrainingApprovalRequestServiceMockTest.java
@@ -25,6 +25,7 @@ import java.time.LocalDate;
 import java.util.List;
 
 import nl.tudelft.labracore.api.dto.PersonSummaryDTO;
+import nl.tudelft.labracore.api.dto.ProgramSummaryDTO;
 import nl.tudelft.labracore.lib.security.user.Person;
 import nl.tudelft.tam.dto.view.details.TrainingApprovalRequestDetailsDTO;
 import nl.tudelft.tam.enums.Status;
@@ -57,6 +58,9 @@ class TrainingApprovalRequestServiceMockTest {
 	@MockBean
 	PersonService personService;
 
+	@MockBean
+	ProgramService programService;
+
 	@MockBean
 	ProfileService profileService;
 
@@ -134,7 +138,7 @@ class TrainingApprovalRequestServiceMockTest {
 		when(personService.getPeopleById(anyList())).thenReturn(List.of());
 
 		assertThrows(InvalidDatabaseEntryException.class,
-				() -> trainingApprovalRequestService.getAllSubmitted());
+				() -> trainingApprovalRequestService.getAllSubmitted(List.of(1L)));
 
 		verify(personService).getPeopleById(List.of(STUDENT_ID));
 	}
@@ -146,8 +150,11 @@ class TrainingApprovalRequestServiceMockTest {
 		String studentName = "abc-student-4984654";
 		when(personService.getPeopleById(anyList()))
 				.thenReturn(List.of(new PersonSummaryDTO().id(STUDENT_ID).externalId(studentName)));
+		when(programService.getAllRelevantPrograms(anyLong()))
+				.thenReturn(List.of(new ProgramSummaryDTO().id(1L).name("Test")));
 
-		List<TrainingApprovalRequestDetailsDTO> result = trainingApprovalRequestService.getAllSubmitted();
+		List<TrainingApprovalRequestDetailsDTO> result = trainingApprovalRequestService
+				.getAllSubmitted(List.of(1L));
 
 		assertThat(result.size()).isEqualTo(1);
 		assertThat(result.get(0).getId()).isEqualTo(REQUEST_ID);
diff --git a/src/test/java/nl/tudelft/tam/service/TrainingApprovalRequestServiceTest.java b/src/test/java/nl/tudelft/tam/service/TrainingApprovalRequestServiceTest.java
index f7982aafdfebc363ef34fa42451a26197757b5c5..24798812b9472fe24fbf74a95c81b64620406db9 100644
--- a/src/test/java/nl/tudelft/tam/service/TrainingApprovalRequestServiceTest.java
+++ b/src/test/java/nl/tudelft/tam/service/TrainingApprovalRequestServiceTest.java
@@ -20,6 +20,7 @@ package nl.tudelft.tam.service;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.time.LocalDate;
+import java.util.List;
 
 import javax.transaction.Transactional;
 
@@ -128,7 +129,7 @@ class TrainingApprovalRequestServiceTest {
 	void getAllSubmittedEmpty() throws InvalidDatabaseEntryException {
 		trainingApprovalRequestRepository.deleteAll();
 
-		assertThat(trainingApprovalRequestService.getAllSubmitted().size()).isEqualTo(0);
+		assertThat(trainingApprovalRequestService.getAllSubmitted(List.of(1L)).size()).isEqualTo(0);
 	}
 
 	@Test