Skip to content

Commit

Permalink
chore: clean up AgreementController (#558)
Browse files Browse the repository at this point in the history
  • Loading branch information
trulshj authored Jan 6, 2025
1 parent e4ff8ef commit 9688b3d
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 110 deletions.
104 changes: 39 additions & 65 deletions backend/Api/Agreements/AgreementController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
using Infrastructure.DatabaseContext;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;

namespace Api.Projects;
namespace Api.Agreements;

[Authorize]
[Route("/v0/{orgUrlKey}/agreements")]
Expand All @@ -18,14 +19,16 @@ public class AgreementController(
IOrganisationRepository organisationRepository,
IAgreementsRepository agreementsRepository) : ControllerBase
{
private const string SelectedOrganizationNotFound = "Selected organization not found";


[HttpGet]
[Route("get/{agreementId}")]
[Route("{agreementId:int}")]
public async Task<ActionResult<AgreementReadModel>> GetAgreement([FromRoute] string orgUrlKey,
[FromRoute] int agreementId, CancellationToken ct)
{
var selectedOrg = await organisationRepository.GetOrganizationByUrlKey(orgUrlKey, ct);
if (selectedOrg is null) return BadRequest("Selected org not found");
if (selectedOrg is null) return NotFound(SelectedOrganizationNotFound);

var agreement = await agreementsRepository.GetAgreementById(agreementId, ct);

Expand All @@ -43,28 +46,21 @@ public async Task<ActionResult<AgreementReadModel>> GetAgreement([FromRoute] str
Notes: agreement.Notes,
Options: agreement.Options,
PriceAdjustmentProcess: agreement.PriceAdjustmentProcess,
Files: agreement.Files.Select(f => new FileReferenceReadModel(
FileName: f.FileName,
BlobName: f.BlobName,
UploadedOn: f.UploadedOn,
UploadedBy: f.UploadedBy ?? "Unknown"
)).ToList()
Files: agreement.Files.Select(f => new FileReferenceReadModel(f)).ToList()
);
return Ok(responseModel);
}

[HttpGet]
[Route("get/engagement/{engagementId}")]
[Route("engagement/{engagementId:int}")]
public async Task<ActionResult<List<AgreementReadModel>>> GetAgreementsByEngagement([FromRoute] string orgUrlKey,
[FromRoute] int engagementId, CancellationToken ct)
{
var selectedOrg = await organisationRepository.GetOrganizationByUrlKey(orgUrlKey, ct);
if (selectedOrg is null) return BadRequest("Selected org not found");
if (selectedOrg is null) return NotFound(SelectedOrganizationNotFound);

var agreements = await agreementsRepository.GetAgreementsByEngagementId(engagementId, ct);

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

var responseModels = agreements.Select(agreement => new AgreementReadModel(
AgreementId: agreement.Id,
Name: agreement.Name,
Expand All @@ -77,29 +73,22 @@ public async Task<ActionResult<List<AgreementReadModel>>> GetAgreementsByEngagem
Notes: agreement.Notes,
Options: agreement.Options,
PriceAdjustmentProcess: agreement.PriceAdjustmentProcess,
Files: agreement.Files.Select(f => new FileReferenceReadModel(
FileName: f.FileName,
BlobName: f.BlobName,
UploadedOn: f.UploadedOn,
UploadedBy: f.UploadedBy ?? "Unknown"
)).ToList()
Files: agreement.Files.Select(f => new FileReferenceReadModel(f)).ToList()
)).ToList();

return Ok(responseModels);
}

[HttpGet]
[Route("get/customer/{customerId}")]
[Route("customer/{customerId:int}")]
public async Task<ActionResult<List<AgreementReadModel>>> GetAgreementsByCustomer([FromRoute] string orgUrlKey,
[FromRoute] int customerId, CancellationToken ct)
{
var selectedOrg = await organisationRepository.GetOrganizationByUrlKey(orgUrlKey, ct);
if (selectedOrg is null) return BadRequest("Selected org not found");
if (selectedOrg is null) return NotFound(SelectedOrganizationNotFound);

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

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

var responseModels = agreements.Select(agreement => new AgreementReadModel(
AgreementId: agreement.Id,
Name: agreement.Name,
Expand All @@ -112,21 +101,15 @@ public async Task<ActionResult<List<AgreementReadModel>>> GetAgreementsByCustome
Notes: agreement.Notes,
Options: agreement.Options,
PriceAdjustmentProcess: agreement.PriceAdjustmentProcess,
Files: agreement.Files.Select(f => new FileReferenceReadModel(
FileName: f.FileName,
BlobName: f.BlobName,
UploadedOn: f.UploadedOn,
UploadedBy: f.UploadedBy ?? "Unknown"
)).ToList()
Files: agreement.Files.Select(f => new FileReferenceReadModel(f)).ToList()
)).ToList();

return Ok(responseModels);
}

[HttpPost]
[Route("create")]
public async Task<ActionResult<AgreementReadModel>> Post([FromRoute] string orgUrlKey,
[FromBody] AgreementWriteModel body, CancellationToken ct)
[FromBody] AgreementWriteModel body, CancellationToken cancellationToken)
{
if (!ModelState.IsValid)
{
Expand All @@ -139,24 +122,26 @@ public async Task<ActionResult<AgreementReadModel>> Post([FromRoute] string orgU
return BadRequest(ModelState);
}

var selectedOrg = await organisationRepository.GetOrganizationByUrlKey(orgUrlKey, ct);
var selectedOrg = await organisationRepository.GetOrganizationByUrlKey(orgUrlKey, cancellationToken);
if (selectedOrg is null)
return BadRequest("Selected organization not found");
return NotFound(SelectedOrganizationNotFound);

Customer? customer = null;
if (body.CustomerId != null)
{
customer = await context.Customer.FindAsync(body.CustomerId.Value);
customer = await context.Customer.FirstOrDefaultAsync(c => c.Id == body.CustomerId.Value,
cancellationToken);
if (customer == null)
return BadRequest("Customer not found");
return NotFound("Customer not found");
}

Engagement? engagement = null;
if (body.EngagementId != null)
{
engagement = await context.Project.FindAsync(body.EngagementId.Value);
engagement =
await context.Project.FirstOrDefaultAsync(e => e.Id == body.EngagementId.Value, cancellationToken);
if (engagement is null)
return BadRequest("Engagement not found");
return NotFound("Engagement not found");
}

var agreement = new Agreement
Expand All @@ -182,7 +167,7 @@ public async Task<ActionResult<AgreementReadModel>> Post([FromRoute] string orgU
}).ToList()
};

await agreementsRepository.AddAgreementAsync(agreement, ct);
await agreementsRepository.AddAgreementAsync(agreement, cancellationToken);

var responseModel = new AgreementReadModel(
Name: agreement.Name,
Expand All @@ -196,22 +181,17 @@ public async Task<ActionResult<AgreementReadModel>> Post([FromRoute] string orgU
Notes: agreement.Notes,
Options: agreement.Options,
PriceAdjustmentProcess: agreement.PriceAdjustmentProcess,
Files: agreement.Files.Select(f => new FileReferenceReadModel(
FileName: f.FileName,
BlobName: f.BlobName,
UploadedOn: f.UploadedOn,
UploadedBy: f.UploadedBy ?? "Unknown"
)).ToList()
Files: agreement.Files.Select(f => new FileReferenceReadModel(f)).ToList()
);
cache.Remove($"consultantCacheKey/{orgUrlKey}");

return Ok(responseModel);
}

[HttpPut]
[Route("update/{agreementId}")]
[Route("{agreementId:int}")]
public async Task<ActionResult<AgreementReadModel>> Put([FromRoute] string orgUrlKey,
[FromRoute] int agreementId, [FromBody] AgreementWriteModel body, CancellationToken ct)
[FromRoute] int agreementId, [FromBody] AgreementWriteModel body, CancellationToken cancellationToken)
{
if (!ModelState.IsValid)
{
Expand All @@ -224,20 +204,19 @@ public async Task<ActionResult<AgreementReadModel>> Put([FromRoute] string orgUr
return BadRequest(ModelState);
}

var selectedOrg = await organisationRepository.GetOrganizationByUrlKey(orgUrlKey, ct);
var selectedOrg = await organisationRepository.GetOrganizationByUrlKey(orgUrlKey, cancellationToken);
if (selectedOrg is null)
return BadRequest("Selected organization not found");
return NotFound("Selected organization not found");

var agreement = await agreementsRepository.GetAgreementById(agreementId, ct);
var agreement = await agreementsRepository.GetAgreementById(agreementId, cancellationToken);
if (agreement is null)
return NotFound("Agreement not found");

Customer? customer = null;
if (body.CustomerId is not null)
{
customer = await context.Customer.FindAsync(body.CustomerId);
var customer = await context.Customer.FirstOrDefaultAsync(c => c.Id == body.CustomerId, cancellationToken);
if (customer is null)
return BadRequest("Customer not found");
return NotFound("Customer not found");

agreement.CustomerId = body.CustomerId;
agreement.Customer = customer;
Expand All @@ -248,12 +227,12 @@ public async Task<ActionResult<AgreementReadModel>> Put([FromRoute] string orgUr
agreement.Customer = null;
}

Engagement? engagement = null;
if (body.EngagementId is not null)
{
engagement = await context.Project.FindAsync(body.EngagementId);
var engagement =
await context.Project.FirstOrDefaultAsync(e => e.Id == body.EngagementId, cancellationToken);
if (engagement is null)
return BadRequest("Engagement not found");
return NotFound("Engagement not found");

agreement.EngagementId = body.EngagementId;
agreement.Engagement = engagement;
Expand All @@ -280,7 +259,7 @@ public async Task<ActionResult<AgreementReadModel>> Put([FromRoute] string orgUr
UploadedBy = f.UploadedBy ?? "Unknown"
}).ToList();

await agreementsRepository.UpdateAgreementAsync(agreement, ct);
await agreementsRepository.UpdateAgreementAsync(agreement, cancellationToken);

var responseModel = new AgreementReadModel(
AgreementId: agreement.Id,
Expand All @@ -294,12 +273,7 @@ public async Task<ActionResult<AgreementReadModel>> Put([FromRoute] string orgUr
Notes: agreement.Notes,
Options: agreement.Options,
PriceAdjustmentProcess: agreement.PriceAdjustmentProcess,
Files: agreement.Files.Select(f => new FileReferenceReadModel(
FileName: f.FileName,
BlobName: f.BlobName,
UploadedOn: f.UploadedOn,
UploadedBy: f.UploadedBy ?? "Unknown"
)).ToList()
agreement.Files.Select(f => new FileReferenceReadModel(f)).ToList()
);

cache.Remove($"consultantCacheKey/{orgUrlKey}");
Expand All @@ -308,11 +282,11 @@ public async Task<ActionResult<AgreementReadModel>> Put([FromRoute] string orgUr
}

[HttpDelete]
[Route("delete/{agreementId}")]
[Route("{agreementId:int}")]
public async Task<ActionResult> Delete([FromRoute] string orgUrlKey, [FromRoute] int agreementId, CancellationToken ct)
{
var selectedOrg = await organisationRepository.GetOrganizationByUrlKey(orgUrlKey, ct);
if (selectedOrg is null) return BadRequest("Selected org not found");
if (selectedOrg is null) return NotFound(SelectedOrganizationNotFound);

var agreement = await agreementsRepository.GetAgreementById(agreementId, ct);
if (agreement is null) return NotFound();
Expand All @@ -328,7 +302,7 @@ public async Task<ActionResult> Delete([FromRoute] string orgUrlKey, [FromRoute]
public async Task<ActionResult<List<string>>> GetPriceAdjustmentIndexes([FromRoute] string orgUrlKey, CancellationToken ct)
{
var selectedOrg = await organisationRepository.GetOrganizationByUrlKey(orgUrlKey, ct);
if (selectedOrg is null) return BadRequest("Selected org not found");
if (selectedOrg is null) return NotFound(SelectedOrganizationNotFound);

var priceAdjustmentIndexes = await agreementsRepository.GetPriceAdjustmentIndexesAsync(ct);

Expand Down
18 changes: 14 additions & 4 deletions backend/Api/Agreements/AgreementModels.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Core.Agreements;
// ReSharper disable NotAccessedPositionalProperty.Global

namespace Api.Agreements;

public record AgreementReadModel(
int AgreementId,
Expand All @@ -16,12 +18,19 @@ public record AgreementReadModel(
string? PriceAdjustmentProcess,
List<FileReferenceReadModel> Files
);

public record FileReferenceReadModel(
string FileName,
string BlobName,
DateTime UploadedOn,
string? UploadedBy
);
)
{
public FileReferenceReadModel(FileReference fileReference) : this(fileReference.FileName, fileReference.BlobName,
fileReference.UploadedOn, fileReference.UploadedBy ?? "Unknown")
{
}
}

public record AgreementWriteModel(
string? Name,
Expand Down Expand Up @@ -49,9 +58,10 @@ public IEnumerable<ValidationResult> Validate(ValidationContext validationContex
}


// ReSharper disable once ClassNeverInstantiated.Global
public record FileReferenceWriteModel(
string FileName,
string BlobName,
DateTime UploadedOn,
string? UploadedBy
);
);
35 changes: 13 additions & 22 deletions backend/Infrastructure/DatabaseContext/ApplicationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,20 @@

namespace Infrastructure.DatabaseContext;

public class ApplicationContext : DbContext
public class ApplicationContext(DbContextOptions options) : DbContext(options)
{
public ApplicationContext(DbContextOptions options) : base(options)
{
}

public DbSet<Consultant?> Consultant { get; set; } = null!;
public DbSet<Competence> Competence { get; set; } = null!;
public DbSet<CompetenceConsultant> CompetenceConsultant { get; set; } = null!;
public DbSet<Department> Department { get; set; } = null!;
public DbSet<Organization> Organization { get; set; } = null!;
public DbSet<Absence> Absence { get; set; } = null!;

public DbSet<PlannedAbsence> PlannedAbsence { get; set; } = null!;
public DbSet<Vacation> Vacation { get; set; } = null!;
public DbSet<Customer> Customer { get; set; } = null!;
public DbSet<Engagement> Project { get; set; } = null!;
public DbSet<Staffing> Staffing { get; set; } = null!;
public DbSet<Agreement> Agreements { get; set; } = null!;
public DbSet<Consultant> Consultant { get; init; } = null!;
public DbSet<Competence> Competence { get; init; } = null!;
public DbSet<CompetenceConsultant> CompetenceConsultant { get; init; } = null!;
public DbSet<Department> Department { get; init; } = null!;
public DbSet<Organization> Organization { get; init; } = null!;
public DbSet<Absence> Absence { get; init; } = null!;
public DbSet<PlannedAbsence> PlannedAbsence { get; init; } = null!;
public DbSet<Vacation> Vacation { get; init; } = null!;
public DbSet<Customer> Customer { get; init; } = null!;
public DbSet<Engagement> Project { get; init; } = null!;
public DbSet<Staffing> Staffing { get; init; } = null!;
public DbSet<Agreement> Agreements { get; init; } = null!;


protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
Expand Down Expand Up @@ -135,10 +130,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
.Property(v => v.EndDate)
.HasConversion<DateOnlyConverter>();

/*modelBuilder.Entity<Consultant>()
.HasMany(v => v.CompetenceConsultant)
.WithMany();*/

modelBuilder.Entity<Consultant>()
.Property(c => c.TransferredVacationDays)
.HasDefaultValue(0);
Expand Down
Loading

0 comments on commit 9688b3d

Please sign in to comment.