Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deactivate customer #557

Merged
merged 11 commits into from
Jan 6, 2025
2 changes: 1 addition & 1 deletion backend/Api/Agreements/AgreementController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public async Task<ActionResult<List<AgreementReadModel>>> GetAgreementsByCustome

var agreements = await agreementsRepository.GetAgreementsByCustomerId(customerId, ct);

if (agreements is null || !agreements.Any()) return NotFound();
if (agreements is null) return NotFound();

var responseModels = agreements.Select(agreement => new AgreementReadModel(
AgreementId: agreement.Id,
Expand Down
22 changes: 18 additions & 4 deletions backend/Api/Common/StorageService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,20 @@ private List<Consultant> LoadConsultantsFromDb(string orgUrlKey)
return consultant;
}

public Customer UpdateOrCreateCustomer(Organization org, string customerName, 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();
ClearConsultantCache(orgUrlKey);

return customer;
}

public Customer FindOrCreateCustomer(Organization org, string customerName, string orgUrlKey)
{
var customer = _dbContext.Customer.Where(c => c.OrganizationId == org.Id)
.SingleOrDefault(c => c.Name == customerName);
MariaBonde marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -206,14 +219,15 @@ public Customer UpdateOrCreateCustomer(Organization org, string customerName, st
{
Name = customerName,
Organization = org,
Projects = []
Projects = [],
IsActive = true
};

_dbContext.Customer.Add(customer);
_dbContext.SaveChanges();
ClearConsultantCache(orgUrlKey);
}

_dbContext.SaveChanges();
ClearConsultantCache(orgUrlKey);

return customer;
}
Expand Down
23 changes: 20 additions & 3 deletions backend/Api/Projects/ProjectController.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
using Api.Common;
using Api.StaffingController;
using Core.Consultants;
using Core.Customers;
using Core.DomainModels;
using Core.Engagements;
using Core.Organizations;
using Core.Staffings;
using Infrastructure.DatabaseContext;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
Expand Down Expand Up @@ -47,7 +49,7 @@ public async Task<ActionResult<List<EngagementPerCustomerReadModel>>> Get(
var selectedOrgId = await organisationRepository.GetOrganizationByUrlKey(orgUrlKey, ct);
if (selectedOrgId is null) return BadRequest();

var absenceReadModels = new EngagementPerCustomerReadModel(-1, AbsenceCustomerName,
var absenceReadModels = new EngagementPerCustomerReadModel(-1, AbsenceCustomerName, true,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var absenceReadModels = new EngagementPerCustomerReadModel(-1, AbsenceCustomerName, true,
var absenceReadModels = new EngagementPerCustomerReadModel(-1, AbsenceCustomerName, IsActive: true,

Consider defining what is true

context.Absence.Where(a => a.Organization.UrlKey == orgUrlKey).Select(absence =>
new EngagementReadModel(absence.Id, absence.Name, EngagementState.Absence, false)).ToList());

Expand All @@ -58,6 +60,7 @@ public async Task<ActionResult<List<EngagementPerCustomerReadModel>>> Get(
new EngagementPerCustomerReadModel(
a.Key.Id,
a.Key.Name,
a.Key.IsActive,
a.Select(e =>
new EngagementReadModel(e.Id, e.Name, e.State, e.IsBillable)).ToList()))
.ToList();
Expand Down Expand Up @@ -94,6 +97,7 @@ CancellationToken ct
return new CustomersWithProjectsReadModel(
customer.Id,
customer.Name,
customer.IsActive,
customer.Projects.Where(p =>
p.Staffings.Any(s => s.Week.CompareTo(thisWeek) >= 0) && p.State != EngagementState.Closed).Select(e =>
new EngagementReadModel(e.Id, e.Name, e.State, e.IsBillable)).ToList(),
Expand Down Expand Up @@ -244,6 +248,19 @@ private Engagement MergeProjects(int id)
.Single(p => p.Id == engagementToKeep.Id);
}

[HttpPut]
[Route("customer/{customerId}/activate")]
public async Task<Results<Ok, NotFound<string>>> 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<ActionResult<ProjectWithCustomerModel>> Put([FromRoute] string orgUrlKey,
Expand All @@ -257,7 +274,7 @@ public async Task<ActionResult<ProjectWithCustomerModel>> Put([FromRoute] string
if (body.CustomerName == AbsenceCustomerName)
return Ok(HandleAbsenceChange(body, orgUrlKey));

var customer = service.UpdateOrCreateCustomer(selectedOrg, body.CustomerName, orgUrlKey);
var customer = service.FindOrCreateCustomer(selectedOrg, body.CustomerName, orgUrlKey);

var project = context.Project
.Include(p => p.Customer)
Expand Down Expand Up @@ -301,7 +318,7 @@ private CustomersWithProjectsReadModel HandleGetAbsenceWithAbsences(string orgUr
{
var vacation = new EngagementReadModel(-1, "Ferie", EngagementState.Absence, false);

var readModel = new CustomersWithProjectsReadModel(-1, AbsenceCustomerName + " og Ferie",
var readModel = new CustomersWithProjectsReadModel(-1, AbsenceCustomerName + " og Ferie", true,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var readModel = new CustomersWithProjectsReadModel(-1, AbsenceCustomerName + " og Ferie", true,
var readModel = new CustomersWithProjectsReadModel(-1, AbsenceCustomerName + " og Ferie", IsActive: true,

Consider defining what is true

context.Absence.Where(a => a.Organization.UrlKey == orgUrlKey).Select(absence =>
new EngagementReadModel(absence.Id, absence.Name, EngagementState.Absence, false)).ToList(),
new List<EngagementReadModel>());
Expand Down
28 changes: 17 additions & 11 deletions backend/Api/Projects/ProjectModels.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
using System.ComponentModel.DataAnnotations;
using System.Runtime.InteropServices;
using Core.Customers;
using Core.Engagements;

namespace Api.Projects;

public record EngagementPerCustomerReadModel(
[property: Required] int CustomerId,
[property: Required] string CustomerName,
[property: Required] List<EngagementReadModel> Engagements);
int CustomerId,
string CustomerName,
bool IsActive,
List<EngagementReadModel> Engagements);



public record EngagementReadModel(
[property: Required] int EngagementId,
[property: Required] string EngagementName,
[property: Required] EngagementState BookingType,
[property: Required] bool IsBillable);
int EngagementId,
string EngagementName,
EngagementState BookingType,
bool IsBillable);

public record EngagementWriteModel(
EngagementState BookingType,
Expand Down Expand Up @@ -43,7 +48,8 @@ public record UpdateProjectWriteModel(
public record UpdateEngagementNameWriteModel(int EngagementId, string EngagementName);

public record CustomersWithProjectsReadModel(
[property: Required] int CustomerId,
[property: Required] string CustomerName,
[property: Required] List<EngagementReadModel> ActiveEngagements,
[property: Required] List<EngagementReadModel> InactiveEngagements);
int CustomerId,
string CustomerName,
bool IsActive,
List<EngagementReadModel> ActiveEngagements,
List<EngagementReadModel> InactiveEngagements);
4 changes: 4 additions & 0 deletions backend/Core/Customers/Customer.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;
using Core.Agreements;
using Core.Engagements;
Expand All @@ -15,4 +16,7 @@ public class Customer
public required string Name { get; set; }
public required Organization Organization { get; set; }
public required List<Engagement> Projects { get; set; }

public bool IsActive { get; set; } = true;

}
4 changes: 2 additions & 2 deletions backend/Infrastructure/DatabaseContext/ApplicationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
{
}

public DbSet<Consultant?> Consultant { get; set; } = null!;

Check warning on line 22 in backend/Infrastructure/DatabaseContext/ApplicationContext.cs

View workflow job for this annotation

GitHub Actions / dotnet_core_project_tests (8.x.x)

The type 'Core.Consultants.Consultant?' cannot be used as type parameter 'TEntity' in the generic type or method 'DbSet<TEntity>'. Nullability of type argument 'Core.Consultants.Consultant?' doesn't match 'class' constraint.
public DbSet<Competence> Competence { get; set; } = null!;
public DbSet<CompetenceConsultant> CompetenceConsultant { get; set; } = null!;
public DbSet<Department> Department { get; set; } = null!;
Expand Down Expand Up @@ -61,7 +61,7 @@
.HasForeignKey(customer => customer.OrganizationId);

modelBuilder.Entity<Customer>()
.HasIndex(customer => new { customer.OrganizationId, customer.Name })
.HasIndex(customer => new { customer.OrganizationId, customer.Name, customer.IsActive })
.IsUnique();

modelBuilder.Entity<Customer>()
Expand Down Expand Up @@ -211,7 +211,7 @@
GraduationYear = 2019
});



base.OnModelCreating(modelBuilder);
}
Expand Down
Loading
Loading