From ead17a2d700c23a36869c0a30e48e9adfcfa45da Mon Sep 17 00:00:00 2001 From: Ida Marie Andreassen Date: Tue, 25 Jun 2024 10:52:19 +0200 Subject: [PATCH 1/5] Feat: added new model to update project name --- backend/Api/Projects/ProjectModels.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/Api/Projects/ProjectModels.cs b/backend/Api/Projects/ProjectModels.cs index b229b938..c95c4192 100644 --- a/backend/Api/Projects/ProjectModels.cs +++ b/backend/Api/Projects/ProjectModels.cs @@ -28,6 +28,8 @@ public record ProjectWithCustomerModel( public record UpdateProjectWriteModel(int EngagementId, EngagementState ProjectState, int StartYear, int StartWeek, int WeekSpan); +public record UpdateProjectNameWriteModel(int EngagementId, string EngagementName); + public record CustomersWithProjectsReadModel( [property: Required] int CustomerId, From a8a008816a8108b0526ce24b36d3dfd1df87430f Mon Sep 17 00:00:00 2001 From: Ida Marie Andreassen Date: Tue, 25 Jun 2024 10:53:19 +0200 Subject: [PATCH 2/5] Feat: added controller, validation and storage service for updating project name --- backend/Api/Common/StorageService.cs | 35 +++++++++++++++++++ backend/Api/Projects/ProjectController.cs | 33 +++++++++++++++++ .../Projects/ProjectControllerValidator.cs | 6 ++++ 3 files changed, 74 insertions(+) diff --git a/backend/Api/Common/StorageService.cs b/backend/Api/Common/StorageService.cs index 1d5c0c69..a35c94b2 100644 --- a/backend/Api/Common/StorageService.cs +++ b/backend/Api/Common/StorageService.cs @@ -458,6 +458,41 @@ public Engagement UpdateProjectState(int engagementId, EngagementState projectSt return engagement; } + public Engagement UpdateProjectName(int engagementId, string engagementName, string orgUrlKey) + { + var engagement = _dbContext.Project + .Include(p => p.Customer) + .Include(p => p.Staffings) + .Include(p => p.Consultants) + .SingleOrDefault(p => p.Id == engagementId); + var similarEngagement = _dbContext.Project + //.Include(p => p.Customer) + .Include(p => p.Staffings) + //.Include(p=> p.Consultants) + .SingleOrDefault( + p => p.Customer == engagement.Customer && p.Name == engagement.Name && p.Id != engagementId); + + if (similarEngagement is not null && similarEngagement.Name == engagementName) + { + similarEngagement.MergeEngagement(engagement); + //_dbContext.SaveChanges(); + //foreach (var staffing in engagement.Staffings) _dbContext.Remove(staffing); + _dbContext.Project.Remove(_dbContext.Project.Find(engagement.Id)); + _dbContext.SaveChanges(); + + //engagement = similarEngagement; + } + else + { + engagement.Name = engagementName; + _dbContext.SaveChanges(); + } + + _cache.Remove($"{ConsultantCacheKey}/{orgUrlKey}"); + + return engagement; + } + public Engagement? GetProjectById(int id) { return _dbContext.Project.Find(id); diff --git a/backend/Api/Projects/ProjectController.cs b/backend/Api/Projects/ProjectController.cs index 8bcc83b5..9bc42a0d 100644 --- a/backend/Api/Projects/ProjectController.cs +++ b/backend/Api/Projects/ProjectController.cs @@ -169,6 +169,39 @@ public ActionResult> Put([FromRoute] string orgUrlKey, } } + [HttpPut] + [Route("updateProjectName")] + public ActionResult> Put([FromRoute] string orgUrlKey, + [FromBody] UpdateProjectNameWriteModel projectWriteModel) + { + // Merk: Service kommer snart via Dependency Injection, da slipper å lage ny hele tiden + var service = new StorageService(_cache, _context); + + if (!ProjectControllerValidator.ValidateUpdateProjectNameWriteModel(projectWriteModel, service, orgUrlKey)) + return BadRequest("Error in data"); + + try + { + Engagement engagement; + engagement = _context.Project + .Include(p => p.Consultants) + .Include(p => p.Staffings) + .Single(p => p.Id == projectWriteModel.EngagementId); + + engagement.Name = projectWriteModel.EngagementName; + _context.SaveChanges(); + + service.ClearConsultantCache(orgUrlKey); + + return Ok(); + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + } + private bool EngagementHasSoftMatch(int id) { var engagementToChange = _context.Project diff --git a/backend/Api/Projects/ProjectControllerValidator.cs b/backend/Api/Projects/ProjectControllerValidator.cs index 0bdd0bdd..a3723bc2 100644 --- a/backend/Api/Projects/ProjectControllerValidator.cs +++ b/backend/Api/Projects/ProjectControllerValidator.cs @@ -12,6 +12,12 @@ public static bool ValidateUpdateProjectWriteModel(UpdateProjectWriteModel updat CheckIfEngagementIsInOrganisation(updateProjectWriteModel.EngagementId, storageService, orgUrlKey); } + public static bool ValidateUpdateProjectNameWriteModel(UpdateProjectNameWriteModel updateProjectNameWriteModel, StorageService storageService, string orgUrlKey) + { + return CheckIfEngagementExists(updateProjectNameWriteModel.EngagementId, storageService) && + CheckIfEngagementIsInOrganisation(updateProjectNameWriteModel.EngagementId, storageService, orgUrlKey); + } + private static bool CheckIfEngagementExists(int engagementId, StorageService storageService) { return storageService.GetProjectById(engagementId) is not null; From 5385a3c84f6afb68959f13a7cb5afd91ccda35be Mon Sep 17 00:00:00 2001 From: Ida Marie Andreassen Date: Tue, 25 Jun 2024 10:53:49 +0200 Subject: [PATCH 3/5] Feat: added api-types and routes for frontend to update project name --- frontend/src/api-types.ts | 7 +++++++ .../api/projects/updateProjectName/route.ts | 20 +++++++++++++++++++ frontend/src/types.ts | 5 +++++ 3 files changed, 32 insertions(+) create mode 100644 frontend/src/app/[organisation]/bemanning/api/projects/updateProjectName/route.ts diff --git a/frontend/src/api-types.ts b/frontend/src/api-types.ts index 81e6131f..8ce8f600 100644 --- a/frontend/src/api-types.ts +++ b/frontend/src/api-types.ts @@ -231,6 +231,13 @@ export interface UpdateProjectWriteModel { weekSpan?: number; } +export interface UpdateProjectNameWriteModel { + /** @format int32 */ + engagementId?: number; + /** @minLength 1 */ + projectName: string; +} + export interface VacationMetaData { /** @format int32 */ daysTotal?: number; diff --git a/frontend/src/app/[organisation]/bemanning/api/projects/updateProjectName/route.ts b/frontend/src/app/[organisation]/bemanning/api/projects/updateProjectName/route.ts new file mode 100644 index 00000000..4e44e5af --- /dev/null +++ b/frontend/src/app/[organisation]/bemanning/api/projects/updateProjectName/route.ts @@ -0,0 +1,20 @@ +import { putWithToken } from "@/data/apiCallsWithToken"; +import { updateProjectNameBody } from "@/types"; +import { NextResponse } from "next/server"; +import { EngagementReadModel } from "@/api-types"; + +export async function PUT( + request: Request, + { params }: { params: { organisation: string } }, +) { + const orgUrlKey = params.organisation; + const requestBody = (await request.json()) as updateProjectNameBody; + + const project = + (await putWithToken( + `${orgUrlKey}/projects/updateProjectName`, + requestBody, + )) ?? []; + + return NextResponse.json(project); +} diff --git a/frontend/src/types.ts b/frontend/src/types.ts index d69addb4..1bbf8e68 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -30,6 +30,11 @@ export interface updateProjectStateBody { weekSpan: number; } +export interface updateProjectNameBody { + engagementId: string; + engagementName: string; +} + export interface WeekWithHours { week: number; hours: number; From 2bb849f3834ceac46f5a4e2764449e869eee0bfa Mon Sep 17 00:00:00 2001 From: Ida Marie Andreassen Date: Wed, 24 Jul 2024 10:28:40 +0200 Subject: [PATCH 4/5] Remove unused code --- backend/Api/Common/StorageService.cs | 35 ---------------------------- 1 file changed, 35 deletions(-) diff --git a/backend/Api/Common/StorageService.cs b/backend/Api/Common/StorageService.cs index a35c94b2..1d5c0c69 100644 --- a/backend/Api/Common/StorageService.cs +++ b/backend/Api/Common/StorageService.cs @@ -458,41 +458,6 @@ public Engagement UpdateProjectState(int engagementId, EngagementState projectSt return engagement; } - public Engagement UpdateProjectName(int engagementId, string engagementName, string orgUrlKey) - { - var engagement = _dbContext.Project - .Include(p => p.Customer) - .Include(p => p.Staffings) - .Include(p => p.Consultants) - .SingleOrDefault(p => p.Id == engagementId); - var similarEngagement = _dbContext.Project - //.Include(p => p.Customer) - .Include(p => p.Staffings) - //.Include(p=> p.Consultants) - .SingleOrDefault( - p => p.Customer == engagement.Customer && p.Name == engagement.Name && p.Id != engagementId); - - if (similarEngagement is not null && similarEngagement.Name == engagementName) - { - similarEngagement.MergeEngagement(engagement); - //_dbContext.SaveChanges(); - //foreach (var staffing in engagement.Staffings) _dbContext.Remove(staffing); - _dbContext.Project.Remove(_dbContext.Project.Find(engagement.Id)); - _dbContext.SaveChanges(); - - //engagement = similarEngagement; - } - else - { - engagement.Name = engagementName; - _dbContext.SaveChanges(); - } - - _cache.Remove($"{ConsultantCacheKey}/{orgUrlKey}"); - - return engagement; - } - public Engagement? GetProjectById(int id) { return _dbContext.Project.Find(id); From b476e807facd85d7d5dbe352bbb37f38286a7264 Mon Sep 17 00:00:00 2001 From: Ida Marie Andreassen Date: Wed, 24 Jul 2024 10:29:22 +0200 Subject: [PATCH 5/5] Validate string and check if proposed name is already in use --- backend/Api/Projects/ProjectController.cs | 4 +++- .../Api/Projects/ProjectControllerValidator.cs | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/backend/Api/Projects/ProjectController.cs b/backend/Api/Projects/ProjectController.cs index 9bc42a0d..c6e9fe41 100644 --- a/backend/Api/Projects/ProjectController.cs +++ b/backend/Api/Projects/ProjectController.cs @@ -179,7 +179,9 @@ public ActionResult> Put([FromRoute] string orgUrlKey, if (!ProjectControllerValidator.ValidateUpdateProjectNameWriteModel(projectWriteModel, service, orgUrlKey)) return BadRequest("Error in data"); - + if (ProjectControllerValidator.ValidateUpdateProjectNameAlreadyExist(projectWriteModel, service, orgUrlKey)) + {return BadRequest("Name already in use");} + try { Engagement engagement; diff --git a/backend/Api/Projects/ProjectControllerValidator.cs b/backend/Api/Projects/ProjectControllerValidator.cs index a3723bc2..0234089f 100644 --- a/backend/Api/Projects/ProjectControllerValidator.cs +++ b/backend/Api/Projects/ProjectControllerValidator.cs @@ -15,7 +15,23 @@ public static bool ValidateUpdateProjectWriteModel(UpdateProjectWriteModel updat public static bool ValidateUpdateProjectNameWriteModel(UpdateProjectNameWriteModel updateProjectNameWriteModel, StorageService storageService, string orgUrlKey) { return CheckIfEngagementExists(updateProjectNameWriteModel.EngagementId, storageService) && - CheckIfEngagementIsInOrganisation(updateProjectNameWriteModel.EngagementId, storageService, orgUrlKey); + CheckIfEngagementIsInOrganisation(updateProjectNameWriteModel.EngagementId, storageService, orgUrlKey) && !string.IsNullOrWhiteSpace(updateProjectNameWriteModel.EngagementName); + } + + public static bool ValidateUpdateProjectNameAlreadyExist(UpdateProjectNameWriteModel updateProjectNameWriteModel, + StorageService storageService, string orgUrlKey) + { + var updatedEngagement = storageService.GetProjectById(updateProjectNameWriteModel.EngagementId); + if (updatedEngagement is not null) + { + var customer = storageService.GetCustomerFromId(orgUrlKey, updatedEngagement.CustomerId); + if (customer is not null) + { + return customer.Projects.Any(engagement => string.Equals(engagement.Name, + updateProjectNameWriteModel.EngagementName, StringComparison.OrdinalIgnoreCase)); + } + } + return false; } private static bool CheckIfEngagementExists(int engagementId, StorageService storageService)