Skip to content

Commit

Permalink
Added check status logic when updating acq and related entities | psp…
Browse files Browse the repository at this point in the history
…-7006 (#3602)

* Added status checking to details, take, compensation and other acq file pages

* Updated backend and updated tests

* Fixed lint

* Refactored solver to be simpler

* Added tests

* Pr comments

* Added the sys-admin to edit acquisition fields
  • Loading branch information
FuriousLlama authored Nov 24, 2023
1 parent a43d33c commit 1525026
Show file tree
Hide file tree
Showing 51 changed files with 1,742 additions and 387 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ public IActionResult GetRelationshipDocuments(DocumentRelationType relationshipT
return new JsonResult(mappedResearchFileDocuments);
case DocumentRelationType.AcquisitionFiles:
var acquistionFileDocuments = _documentFileService.GetFileDocuments<PimsAcquisitionFileDocument>(FileType.Acquisition, long.Parse(parentId));
var mappedAquisitionFileDocuments = _mapper.Map<List<DocumentRelationshipModel>>(acquistionFileDocuments);
return new JsonResult(mappedAquisitionFileDocuments);
var mappedAcquisitionFileDocuments = _mapper.Map<List<DocumentRelationshipModel>>(acquistionFileDocuments);
return new JsonResult(mappedAcquisitionFileDocuments);
case DocumentRelationType.Templates:
var templateDocuments = _formDocumentService.GetFormDocumentTypes(parentId);
var mappedTemplateDocuments = _mapper.Map<List<DocumentRelationshipModel>>(templateDocuments);
Expand Down
31 changes: 31 additions & 0 deletions source/backend/api/Constants/AcquisitionStatusTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Runtime.Serialization;
using System.Text.Json.Serialization;

namespace Pims.Api.Constants
{
[JsonConverter(typeof(JsonStringEnumMemberConverter))]
public enum AcquisitionStatusTypes
{

[EnumMember(Value = "ACTIVE")]
ACTIVE,

[EnumMember(Value = "ARCHIV")]
ARCHIV,

[EnumMember(Value = "CANCEL")]
CANCEL,

[EnumMember(Value = "CLOSED")]
CLOSED,

[EnumMember(Value = "COMPLT")]
COMPLT,

[EnumMember(Value = "DRAFT")]
DRAFT,

[EnumMember(Value = "HOLD")]
HOLD,
}
}
19 changes: 19 additions & 0 deletions source/backend/api/Constants/AgreementStatusTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Runtime.Serialization;
using System.Text.Json.Serialization;

namespace Pims.Api.Constants
{
[JsonConverter(typeof(JsonStringEnumMemberConverter))]
public enum AgreementStatusTypes
{
[EnumMember(Value = "CANCELLED")]
CANCELLED,

[EnumMember(Value = "DRAFT")]
DRAFT,

[EnumMember(Value = "FINAL")]
FINAL,

}
}
78 changes: 69 additions & 9 deletions source/backend/api/Services/AcquisitionFileService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Security.Claims;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Pims.Api.Constants;
using Pims.Api.Helpers.Exceptions;
using Pims.Api.Helpers.Extensions;
using Pims.Core.Exceptions;
Expand Down Expand Up @@ -40,6 +41,7 @@ public class AcquisitionFileService : IAcquisitionFileService
private readonly ICompReqFinancialService _compReqFinancialService;
private readonly IExpropriationPaymentRepository _expropriationPaymentRepository;
private readonly ITakeRepository _takeRepository;
private readonly IAcquisitionStatusSolver _statusSolver;

public AcquisitionFileService(
ClaimsPrincipal user,
Expand All @@ -57,7 +59,8 @@ public AcquisitionFileService(
IInterestHolderRepository interestHolderRepository,
ICompReqFinancialService compReqFinancialService,
IExpropriationPaymentRepository expropriationPaymentRepository,
ITakeRepository takeRepository)
ITakeRepository takeRepository,
IAcquisitionStatusSolver statusSolver)
{
_user = user;
_logger = logger;
Expand All @@ -75,6 +78,7 @@ public AcquisitionFileService(
_compReqFinancialService = compReqFinancialService;
_expropriationPaymentRepository = expropriationPaymentRepository;
_takeRepository = takeRepository;
_statusSolver = statusSolver;
}

public Paged<PimsAcquisitionFile> GetPage(AcquisitionFilter filter)
Expand Down Expand Up @@ -240,6 +244,12 @@ public PimsAcquisitionFile Update(PimsAcquisitionFile acquisitionFile, IEnumerab
ValidateVersion(acquisitionFile.Internal_Id, acquisitionFile.ConcurrencyControlNumber);
ValidateDrafts(acquisitionFile.Internal_Id);

AcquisitionStatusTypes? currentAcquisitionStatus = GetCurrentAcquisitionStatus(acquisitionFile.Internal_Id);
if (!_statusSolver.CanEditDetails(currentAcquisitionStatus) && !_user.HasPermission(Permissions.SystemAdmin))
{
throw new BusinessRuleViolationException("The file you are editing is not active or draft, so you cannot save changes. Refresh your browser to see file state.");
}

if (!userOverrides.Contains(UserOverrideCode.UpdateRegion))
{
ValidateMinistryRegion(acquisitionFile.Internal_Id, acquisitionFile.RegionCode);
Expand Down Expand Up @@ -341,6 +351,12 @@ public PimsAcquisitionFile UpdateChecklistItems(PimsAcquisitionFile acquisitionF
_user.ThrowIfNotAuthorized(Permissions.AcquisitionFileEdit);
_user.ThrowInvalidAccessToAcquisitionFile(_userRepository, _acqFileRepository, acquisitionFile.Internal_Id);

var currentAcquisitionStatus = GetCurrentAcquisitionStatus(acquisitionFile.Internal_Id);
if (!_statusSolver.CanEditChecklists(currentAcquisitionStatus) && !_user.HasPermission(Permissions.SystemAdmin))
{
throw new BusinessRuleViolationException("The file you are editing is not active or draft, so you cannot save changes. Refresh your browser to see file state.");
}

// Get the current checklist items for this acquisition file.
var currentItems = _checklistRepository.GetAllChecklistItemsByAcquisitionFileId(acquisitionFile.Internal_Id).ToDictionary(ci => ci.Internal_Id);

Expand Down Expand Up @@ -372,7 +388,7 @@ public IEnumerable<PimsAgreement> GetAgreements(long id)
_user.ThrowIfNotAuthorized(Permissions.AgreementView);
_user.ThrowInvalidAccessToAcquisitionFile(_userRepository, _acqFileRepository, id);

return _agreementRepository.GetAgreementsByAquisitionFile(id);
return _agreementRepository.GetAgreementsByAcquisitionFile(id);
}

public IEnumerable<PimsAgreement> SearchAgreements(AcquisitionReportFilterModel filter)
Expand All @@ -393,6 +409,31 @@ public IEnumerable<PimsAgreement> UpdateAgreements(long acquisitionFileId, List<
{
_user.ThrowInvalidAccessToAcquisitionFile(_userRepository, _acqFileRepository, acquisitionFileId);

var currentAcquisitionStatus = GetCurrentAcquisitionStatus(acquisitionFileId);

var currentAgreements = _agreementRepository.GetAgreementsByAcquisitionFile(acquisitionFileId);

var toBeUpdated = currentAgreements.Where(ca => agreements.Any(na => ca.AgreementId == na.AgreementId && !ca.IsEqual(na)));
var toBeDeleted = currentAgreements.Where(ca => !agreements.Any(na => ca.AgreementId == na.AgreementId));

foreach (var agreement in toBeUpdated)
{
var agreementStatus = Enum.Parse<AgreementStatusTypes>(agreement.AgreementStatusTypeCode);
if (!_statusSolver.CanEditOrDeleteAgreement(currentAcquisitionStatus, agreementStatus) && !_user.HasPermission(Permissions.SystemAdmin))
{
throw new BusinessRuleViolationException("The file you are editing is not active or draft, so you cannot save changes. Refresh your browser to see file state.");
}
}

foreach (var agreement in toBeDeleted)
{
var agreementStatus = Enum.Parse<AgreementStatusTypes>(agreement.AgreementStatusTypeCode);
if (!_statusSolver.CanEditOrDeleteAgreement(currentAcquisitionStatus, agreementStatus) && !_user.HasPermission(Permissions.SystemAdmin))
{
throw new BusinessRuleViolationException("The file you are editing is not active or draft, so you cannot save changes. Refresh your browser to see file state.");
}
}

var updatedAgreements = _agreementRepository.UpdateAllForAcquisition(acquisitionFileId, agreements);
_agreementRepository.CommitTransaction();

Expand All @@ -414,6 +455,12 @@ public IEnumerable<PimsInterestHolder> UpdateInterestHolders(long acquisitionFil
_user.ThrowIfNotAuthorized(Permissions.AcquisitionFileEdit);
_user.ThrowInvalidAccessToAcquisitionFile(_userRepository, _acqFileRepository, acquisitionFileId);

var currentAcquisitionStatus = GetCurrentAcquisitionStatus(acquisitionFileId);
if (!_statusSolver.CanEditStakeholders(currentAcquisitionStatus) && !_user.HasPermission(Permissions.SystemAdmin))
{
throw new BusinessRuleViolationException("The file you are editing is not active or draft, so you cannot save changes. Refresh your browser to see file state.");
}

var currentInterestHolders = _interestHolderRepository.GetInterestHoldersByAcquisitionFile(acquisitionFileId);

// Verify that the interest holder is still the same (person or org)
Expand Down Expand Up @@ -690,7 +737,7 @@ private void ValidateMinistryRegion(long acqFileId, short updatedRegion)

private void ValidateDrafts(long acqFileId)
{
var agreements = _agreementRepository.GetAgreementsByAquisitionFile(acqFileId);
var agreements = _agreementRepository.GetAgreementsByAcquisitionFile(acqFileId);
var compensations = _compensationRequisitionRepository.GetAllByAcquisitionFileId(acqFileId);
if (agreements.Any(a => a?.AgreementStatusTypeCode == "DRAFT" || compensations.Any(c => c.IsDraft.HasValue && c.IsDraft.Value)))
{
Expand Down Expand Up @@ -838,7 +885,7 @@ private void AppendToAcquisitionChecklist(PimsAcquisitionFile acquisitionFile, r

private void ValidatePayeeDependency(PimsAcquisitionFile acquisitionFile)
{
var currentAquisitionFile = _acqFileRepository.GetById(acquisitionFile.Internal_Id);
var currentAcquisitionFile = _acqFileRepository.GetById(acquisitionFile.Internal_Id);
var compensationRequisitions = _compensationRequisitionRepository.GetAllByAcquisitionFileId(acquisitionFile.Internal_Id);

if (compensationRequisitions.Count == 0)
Expand All @@ -851,23 +898,23 @@ private void ValidatePayeeDependency(PimsAcquisitionFile acquisitionFile)
// Check for Acquisition File Owner removed
if (compReq.AcquisitionOwnerId is not null
&& !acquisitionFile.PimsAcquisitionOwners.Any(x => x.Internal_Id.Equals(compReq.AcquisitionOwnerId))
&& currentAquisitionFile.PimsAcquisitionOwners.Any(x => x.Internal_Id.Equals(compReq.AcquisitionOwnerId)))
&& currentAcquisitionFile.PimsAcquisitionOwners.Any(x => x.Internal_Id.Equals(compReq.AcquisitionOwnerId)))
{
throw new ForeignKeyDependencyException("Acquisition File Owner can not be removed since it's assigned as a payee for a compensation requisition");
}

// Check for Acquisition InterestHolders
if (compReq.InterestHolderId is not null
&& !acquisitionFile.PimsInterestHolders.Any(x => x.Internal_Id.Equals(compReq.InterestHolderId))
&& currentAquisitionFile.PimsInterestHolders.Any(x => x.Internal_Id.Equals(compReq.InterestHolderId)))
&& currentAcquisitionFile.PimsInterestHolders.Any(x => x.Internal_Id.Equals(compReq.InterestHolderId)))
{
throw new ForeignKeyDependencyException("Acquisition File Interest Holders can not be removed since it's assigned as a payee for a compensation requisition");
}

// Check for File Person
if (compReq.AcquisitionFileTeamId is not null
&& !acquisitionFile.PimsAcquisitionFileTeams.Any(x => x.Internal_Id.Equals(compReq.AcquisitionFileTeamId))
&& currentAquisitionFile.PimsAcquisitionFileTeams.Any(x => x.Internal_Id.Equals(compReq.AcquisitionFileTeamId)))
&& currentAcquisitionFile.PimsAcquisitionFileTeams.Any(x => x.Internal_Id.Equals(compReq.AcquisitionFileTeamId)))
{
throw new ForeignKeyDependencyException("Acquisition File team member can not be removed since it's assigned as a payee for a compensation requisition");
}
Expand All @@ -876,7 +923,7 @@ private void ValidatePayeeDependency(PimsAcquisitionFile acquisitionFile)

private void ValidateInterestHoldersDependency(long acquisitionFileId, List<PimsInterestHolder> interestHolders)
{
var currentAquisitionFile = _acqFileRepository.GetById(acquisitionFileId);
var currentAcquisitionFile = _acqFileRepository.GetById(acquisitionFileId);
var compensationRequisitions = _compensationRequisitionRepository.GetAllByAcquisitionFileId(acquisitionFileId);

if (compensationRequisitions.Count == 0)
Expand All @@ -889,11 +936,24 @@ private void ValidateInterestHoldersDependency(long acquisitionFileId, List<Pims
// Check for Interest Holder
if (compReq.InterestHolderId is not null
&& !interestHolders.Any(x => x.InterestHolderId.Equals(compReq.InterestHolderId))
&& currentAquisitionFile.PimsInterestHolders.Any(x => x.Internal_Id.Equals(compReq.InterestHolderId)))
&& currentAcquisitionFile.PimsInterestHolders.Any(x => x.Internal_Id.Equals(compReq.InterestHolderId)))
{
throw new ForeignKeyDependencyException("Acquisition File Interest Holder can not be removed since it's assigned as a payee for a compensation requisition");
}
}
}

private AcquisitionStatusTypes? GetCurrentAcquisitionStatus(long acquisitionFileId)
{
var currentAcquisitionFile = _acqFileRepository.GetById(acquisitionFileId);
AcquisitionStatusTypes currentAcquisitionStatus;

if (Enum.TryParse(currentAcquisitionFile.AcquisitionFileStatusTypeCode, out currentAcquisitionStatus))
{
return currentAcquisitionStatus;
}

return currentAcquisitionStatus;
}
}
}
Loading

0 comments on commit 1525026

Please sign in to comment.