Skip to content

Commit

Permalink
Merge branch 'main' into changeable-vacation
Browse files Browse the repository at this point in the history
  • Loading branch information
trulshj authored Nov 27, 2024
2 parents 0bb932e + ceb5b6e commit 5bbbc11
Show file tree
Hide file tree
Showing 114 changed files with 6,481 additions and 6,265 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: '7.x.x'
dotnet-version: '8.x.x'

# Run dotnet build and publish
- name: Build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: '7.x.x'
dotnet-version: '8.x.x'

# Run dotnet build and publish
- name: Build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
dotnet-version: [ '7.x.x' ]
dotnet-version: [ '8.x.x' ]

steps:
- uses: actions/checkout@v4
Expand Down
337 changes: 337 additions & 0 deletions backend/Api/Agreements/AgreementController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,337 @@
using Core.Agreements;
using Core.Customers;
using Core.Engagements;
using Core.Organizations;
using Infrastructure.DatabaseContext;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;

namespace Api.Projects;

[Authorize]
[Route("/v0/{orgUrlKey}/agreements")]
[ApiController]
public class AgreementController(
ApplicationContext context,
IMemoryCache cache,
IOrganisationRepository organisationRepository,
IAgreementsRepository agreementsRepository) : ControllerBase
{

[HttpGet]
[Route("get/{agreementId}")]
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");

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

if (agreement is null) return NotFound();

var responseModel = new AgreementReadModel(
Name: agreement.Name,
AgreementId: agreement.Id,
EngagementId: agreement.EngagementId,
CustomerId: agreement.CustomerId,
StartDate: agreement.StartDate,
EndDate: agreement.EndDate,
NextPriceAdjustmentDate: agreement.NextPriceAdjustmentDate,
PriceAdjustmentIndex: agreement.PriceAdjustmentIndex,
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()
);
return Ok(responseModel);
}

[HttpGet]
[Route("get/engagement/{engagementId}")]
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");

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,
EngagementId: agreement.EngagementId,
CustomerId: agreement.CustomerId,
StartDate: agreement.StartDate,
EndDate: agreement.EndDate,
NextPriceAdjustmentDate: agreement.NextPriceAdjustmentDate,
PriceAdjustmentIndex: agreement.PriceAdjustmentIndex,
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()
)).ToList();

return Ok(responseModels);
}

[HttpGet]
[Route("get/customer/{customerId}")]
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");

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,
EngagementId: agreement.EngagementId,
CustomerId: agreement.CustomerId,
StartDate: agreement.StartDate,
EndDate: agreement.EndDate,
NextPriceAdjustmentDate: agreement.NextPriceAdjustmentDate,
PriceAdjustmentIndex: agreement.PriceAdjustmentIndex,
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()
)).ToList();

return Ok(responseModels);
}

[HttpPost]
[Route("create")]
public async Task<ActionResult<AgreementReadModel>> Post([FromRoute] string orgUrlKey,
[FromBody] AgreementWriteModel body, CancellationToken ct)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

if (body.CustomerId is null && body.EngagementId is null)
{
ModelState.AddModelError("", "At least one of CustomerId or EngagementId must be provided.");
return BadRequest(ModelState);
}

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

Customer? customer = null;
if (body.CustomerId != null)
{
customer = await context.Customer.FindAsync(body.CustomerId.Value);
if (customer == null)
return BadRequest("Customer not found");
}

Engagement? engagement = null;
if (body.EngagementId != null)
{
engagement = await context.Project.FindAsync(body.EngagementId.Value);
if (engagement is null)
return BadRequest("Engagement not found");
}

var agreement = new Agreement
{
Name = body.Name,
CustomerId = body.CustomerId,
Customer = customer,
EngagementId = body.EngagementId,
Engagement = engagement,
StartDate = body.StartDate,
EndDate = body.EndDate,
NextPriceAdjustmentDate = body.NextPriceAdjustmentDate,
PriceAdjustmentIndex = body.PriceAdjustmentIndex,
Notes = body.Notes,
Options = body.Options,
PriceAdjustmentProcess = body.PriceAdjustmentProcess,
Files = body.Files.Select(f => new FileReference
{
FileName = f.FileName,
BlobName = f.BlobName,
UploadedOn = f.UploadedOn,
UploadedBy = f.UploadedBy ?? "Unknown"
}).ToList()
};

await agreementsRepository.AddAgreementAsync(agreement, ct);

var responseModel = new AgreementReadModel(
Name: agreement.Name,
AgreementId: agreement.Id,
CustomerId: agreement.CustomerId,
EngagementId: agreement.EngagementId,
StartDate: agreement.StartDate,
EndDate: agreement.EndDate,
NextPriceAdjustmentDate: agreement.NextPriceAdjustmentDate,
PriceAdjustmentIndex: agreement.PriceAdjustmentIndex,
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()
);
cache.Remove($"consultantCacheKey/{orgUrlKey}");

return Ok(responseModel);
}

[HttpPut]
[Route("update/{agreementId}")]
public async Task<ActionResult<AgreementReadModel>> Put([FromRoute] string orgUrlKey,
[FromRoute] int agreementId, [FromBody] AgreementWriteModel body, CancellationToken ct)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

if (body.CustomerId is null && body.EngagementId is null)
{
ModelState.AddModelError("", "At least one of CustomerId or EngagementId must be provided.");
return BadRequest(ModelState);
}

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

var agreement = await agreementsRepository.GetAgreementById(agreementId, ct);
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);
if (customer is null)
return BadRequest("Customer not found");

agreement.CustomerId = body.CustomerId;
agreement.Customer = customer;
}
else
{
agreement.CustomerId = null;
agreement.Customer = null;
}

Engagement? engagement = null;
if (body.EngagementId is not null)
{
engagement = await context.Project.FindAsync(body.EngagementId);
if (engagement is null)
return BadRequest("Engagement not found");

agreement.EngagementId = body.EngagementId;
agreement.Engagement = engagement;
}
else
{
agreement.EngagementId = null;
agreement.Engagement = null;
}

agreement.Name = body.Name;
agreement.StartDate = body.StartDate;
agreement.EndDate = body.EndDate;
agreement.NextPriceAdjustmentDate = body.NextPriceAdjustmentDate;
agreement.PriceAdjustmentIndex = body.PriceAdjustmentIndex;
agreement.Notes = body.Notes;
agreement.Options = body.Options;
agreement.PriceAdjustmentProcess = body.PriceAdjustmentProcess;
agreement.Files = body.Files.Select(f => new FileReference
{
FileName = f.FileName,
BlobName = f.BlobName,
UploadedOn = f.UploadedOn,
UploadedBy = f.UploadedBy ?? "Unknown"
}).ToList();

await agreementsRepository.UpdateAgreementAsync(agreement, ct);

var responseModel = new AgreementReadModel(
AgreementId: agreement.Id,
Name: agreement.Name,
CustomerId: agreement.CustomerId,
EngagementId: agreement.EngagementId,
StartDate: agreement.StartDate,
EndDate: agreement.EndDate,
NextPriceAdjustmentDate: agreement.NextPriceAdjustmentDate,
PriceAdjustmentIndex: agreement.PriceAdjustmentIndex,
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()
);

cache.Remove($"consultantCacheKey/{orgUrlKey}");

return Ok(responseModel);
}

[HttpDelete]
[Route("delete/{agreementId}")]
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");

var agreement = await agreementsRepository.GetAgreementById(agreementId, ct);
if (agreement is null) return NotFound();

await agreementsRepository.DeleteAgreementAsync(agreementId, ct);
cache.Remove($"consultantCacheKey/{orgUrlKey}");

return Ok("Deleted");
}

[HttpGet]
[Route("priceAdjustmentIndexes")]
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");

var priceAdjustmentIndexes = await agreementsRepository.GetPriceAdjustmentIndexesAsync(ct);

return Ok(priceAdjustmentIndexes);
}
}
Loading

0 comments on commit 5bbbc11

Please sign in to comment.