diff --git a/backend/Api/Common/StorageService.cs b/backend/Api/Common/StorageService.cs index b689bfe2..6c8e4306 100644 --- a/backend/Api/Common/StorageService.cs +++ b/backend/Api/Common/StorageService.cs @@ -199,39 +199,40 @@ public async Task CreateConsultant(Organization org, ConsultantWrite return consultant; } - public Customer DeactivateOrActivateCustomer(int customerId, Organization org, bool active, string orgUrlKey) + public Customer? DeactivateOrActivateCustomer(int customerId, Organization org, bool active, string orgUrlKey) { var customer = GetCustomerFromId(orgUrlKey, customerId); if (customer is null) return null; customer.IsActive = active; - _dbContext.Customer.Update(customer); - _dbContext.SaveChanges(); + context.Customer.Update(customer); + context.SaveChanges(); ClearConsultantCache(orgUrlKey); return customer; } - public Customer FindOrCreateCustomer(Organization org, string customerName, string orgUrlKey) + public async Task FindOrCreateCustomer(Organization org, string customerName, string orgUrlKey, + CancellationToken cancellationToken) { - var customer = context.Customer.Where(c => c.OrganizationId == org.Id) - .SingleOrDefault(c => c.Name == customerName); + var customer = await context.Customer.Where(c => c.OrganizationId == org.Id) + .FirstOrDefaultAsync(c => c.Name == customerName, cancellationToken); - if (customer is null) + if (customer is not null) return customer; + + customer = new Customer { - customer = new Customer - { - Name = customerName, - Organization = org, - OrganizationId = org.Id, - Projects = [], - IsActive = true - }; - - _dbContext.Customer.Add(customer); - _dbContext.SaveChanges(); - ClearConsultantCache(orgUrlKey); - } + Name = customerName, + Organization = org, + OrganizationId = org.Id, + Projects = [], + Agreements = [], + IsActive = true + }; + + context.Customer.Add(customer); + await context.SaveChangesAsync(cancellationToken); + ClearConsultantCache(orgUrlKey); return customer; diff --git a/backend/Api/Projects/ProjectController.cs b/backend/Api/Projects/ProjectController.cs index 6e7a930d..ddcf2bca 100644 --- a/backend/Api/Projects/ProjectController.cs +++ b/backend/Api/Projects/ProjectController.cs @@ -1,8 +1,5 @@ using Api.Common; using Api.StaffingController; -using Core.Consultants; -using Core.Customers; -using Core.DomainModels; using Core.Engagements; using Core.Organizations; using Core.Weeks; @@ -50,12 +47,13 @@ public async Task>> Get( if (selectedOrgId is null) return BadRequest(); var absenceReadModels = new EngagementPerCustomerReadModel(-1, AbsenceCustomerName, true, - context.Absence.Where(a => a.Organization.UrlKey == orgUrlKey).Select(absence => - new EngagementReadModel(absence.Id, absence.Name, EngagementState.Absence, false)).ToList()); + await context.Absence.Where(a => a.Organization.UrlKey == orgUrlKey).Select(absence => + new EngagementReadModel(absence.Id, absence.Name, EngagementState.Absence, false)) + .ToListAsync(cancellationToken)); var projectReadModels = await context.Project.Include(project => project.Customer) .Where(project => - project.Customer.Organization != null && project.Customer.Organization.UrlKey == orgUrlKey) + project.Customer.Organization.UrlKey == orgUrlKey) .GroupBy(project => project.Customer) .Select(a => new EngagementPerCustomerReadModel( @@ -207,6 +205,20 @@ public ActionResult> Put([FromRoute] string orgUrlKey, } } + + [HttpPut] + [Route("customer/{customerId}/activate")] + public async Task>> Put([FromRoute] int customerId, [FromQuery] bool activate, + string orgUrlKey, CancellationToken ct) + { + var service = new StorageService(cache, context); + var selectedOrg = await organisationRepository.GetOrganizationByUrlKey(orgUrlKey, ct); + if (selectedOrg is null) return TypedResults.NotFound("Selected org not found"); + var customer = service.DeactivateOrActivateCustomer(customerId, selectedOrg, activate, orgUrlKey); + if (customer is null) return TypedResults.NotFound("Selected customer not found"); + return TypedResults.Ok(); + } + [HttpPut] public async Task> Put([FromRoute] string orgUrlKey, [FromBody] EngagementWriteModel body, CancellationToken cancellationToken) @@ -219,11 +231,13 @@ public async Task> Put([FromRoute] string if (body.CustomerName == AbsenceCustomerName) return Ok(HandleAbsenceChange(body, orgUrlKey)); - var customer = service.UpdateOrCreateCustomer(selectedOrg, body.CustomerName, orgUrlKey); + var customer = await service.FindOrCreateCustomer(selectedOrg, body.CustomerName, orgUrlKey, cancellationToken); var project = await context.Project .Include(p => p.Customer) - .FirstOrDefaultAsync(p => p.Customer.Id == customer.Id && p.Name == body.ProjectName, cancellationToken); + .FirstOrDefaultAsync(p => p.Customer.Id == customer.Id + && p.Name == body.ProjectName, cancellationToken + ); if (project is null) { @@ -291,64 +305,6 @@ private Engagement MergeProjects(int id) .Single(p => p.Id == engagementToKeep.Id); } - [HttpPut] - [Route("customer/{customerId}/activate")] - public async Task>> Put([FromRoute] int customerId, [FromQuery] bool activate, string orgUrlKey, CancellationToken ct) - { - - var service = new StorageService(cache, context); - var selectedOrg = await organisationRepository.GetOrganizationByUrlKey(orgUrlKey, ct); - if (selectedOrg is null) return TypedResults.NotFound("Selected org not found"); - var customer = service.DeactivateOrActivateCustomer(customerId, selectedOrg, activate, orgUrlKey); - if (customer is null) return TypedResults.NotFound("Selected customer not found"); - return TypedResults.Ok(); - } - - - [HttpPut] - public async Task> Put([FromRoute] string orgUrlKey, - [FromBody] EngagementWriteModel body, CancellationToken ct) - { - var service = new StorageService(cache, context); - - var selectedOrg = await organisationRepository.GetOrganizationByUrlKey(orgUrlKey, ct); - if (selectedOrg is null) return BadRequest("Selected org not found"); - - if (body.CustomerName == AbsenceCustomerName) - return Ok(HandleAbsenceChange(body, orgUrlKey)); - - var customer = service.FindOrCreateCustomer(selectedOrg, body.CustomerName, orgUrlKey); - - var project = context.Project - .Include(p => p.Customer) - .SingleOrDefault(p => p.Customer.Id == customer.Id - && p.Name == body.ProjectName - ); - - if (project is null) - { - project = new Engagement - { - Customer = customer, - State = body.BookingType, - Staffings = new List(), - Consultants = new List(), - Name = body.ProjectName, - IsBillable = body.IsBillable - }; - - context.Project.Add(project); - } - - await context.SaveChangesAsync(ct); - service.ClearConsultantCache(orgUrlKey); - - var responseModel = - new ProjectWithCustomerModel(project.Name, customer.Name, project.State, project.IsBillable, project.Id); - - return Ok(responseModel); - } - private ProjectWithCustomerModel HandleAbsenceChange(EngagementWriteModel body, string orgUrlKey) { diff --git a/backend/Core/Customers/Customer.cs b/backend/Core/Customers/Customer.cs index 08d5bc62..e7bdb411 100644 --- a/backend/Core/Customers/Customer.cs +++ b/backend/Core/Customers/Customer.cs @@ -1,4 +1,3 @@ -using System.ComponentModel; using System.ComponentModel.DataAnnotations.Schema; using Core.Agreements; using Core.Engagements; @@ -14,8 +13,10 @@ public class Customer [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; init; } public required string Name { get; set; } + public required string OrganizationId { get; set; } public required Organization Organization { get; set; } - public required List Projects { get; set; } + public required List Agreements { get; init; } = []; + public required List Projects { get; set; } = []; public bool IsActive { get; set; } = true;