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

chore: clean up AgreementController #558

Merged
merged 4 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading