Skip to content

Commit

Permalink
PSP-6031 ACQ file: Add Owner Representative (#3210)
Browse files Browse the repository at this point in the history
* Initial backend model updates

* Frontend model changes

* Add owner representative to ACQ File forms

* Update frontend tests

* Test corrections

* Backend model and mapping changes

* Include owner representative in ACQ file details query

* Update backend tests
  • Loading branch information
asanchezr authored Jun 1, 2023
1 parent f68fbe1 commit ff4043b
Show file tree
Hide file tree
Showing 26 changed files with 1,082 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public void Register(TypeAdapterConfig config)
.Map(dest => dest.AcquisitionTeam, src => src.PimsAcquisitionFilePeople)
.Map(dest => dest.AcquisitionFileOwners, src => src.PimsAcquisitionOwners)
.Map(dest => dest.AcquisitionFileOwnerSolicitors, src => src.PimsAcquisitionOwnerSolicitors)
.Map(dest => dest.AcquisitionFileOwnerRepresentatives, src => src.PimsAcquisitionOwnerReps)
.Map(dest => dest.AcquisitionFileChecklist, src => src.PimsAcquisitionChecklistItems)
.Inherits<Entity.IBaseAppEntity, BaseAppModel>();

Expand All @@ -54,6 +55,7 @@ public void Register(TypeAdapterConfig config)
.Map(dest => dest.PimsAcquisitionFilePeople, src => src.AcquisitionTeam)
.Map(dest => dest.PimsAcquisitionOwners, src => src.AcquisitionFileOwners)
.Map(dest => dest.PimsAcquisitionOwnerSolicitors, src => src.AcquisitionFileOwnerSolicitors)
.Map(dest => dest.PimsAcquisitionOwnerReps, src => src.AcquisitionFileOwnerRepresentatives)
.Map(dest => dest.PimsAcquisitionChecklistItems, src => src.AcquisitionFileChecklist)
.Inherits<BaseAppModel, Entity.IBaseAppEntity>();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ public class AcquisitionFileModel : FileModel
/// get/set - A list of acquisition file owner solicitors.
/// </summary>
public IList<AcquisitionFileOwnerSolicitorModel> AcquisitionFileOwnerSolicitors { get; set; }

/// <summary>
/// get/set - A list of acquisition file owner representatives.
/// </summary>
public IList<AcquisitionFileOwnerRepresentativeModel> AcquisitionFileOwnerRepresentatives { get; set; }
#endregion
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Mapster;
using Entity = Pims.Dal.Entities;

namespace Pims.Api.Models.Concepts
{
public class AcquisitionFileOwnerRepresentativeMap : IRegister
{
public void Register(TypeAdapterConfig config)
{
config.NewConfig<Entity.PimsAcquisitionOwnerRep, AcquisitionFileOwnerRepresentativeModel>()
.Map(dest => dest.Id, src => src.Internal_Id)
.Map(dest => dest.AcquisitionFileId, src => src.AcquisitionFileId)
.Map(dest => dest.IsDisabled, src => src.IsDisabled)
.Map(dest => dest.Person, src => src.Person)
.Map(dest => dest.PersonId, src => src.PersonId)
.Map(dest => dest.Comment, src => src.Comment)
.Inherits<Entity.IBaseEntity, BaseModel>();

config.NewConfig<AcquisitionFileOwnerRepresentativeModel, Entity.PimsAcquisitionOwnerRep>()
.Map(dest => dest.Internal_Id, src => src.Id)
.Map(dest => dest.IsDisabled, src => src.IsDisabled)
.Map(dest => dest.PersonId, src => src.PersonId)
.Map(dest => dest.AcquisitionFileId, src => src.AcquisitionFileId)
.Map(dest => dest.Comment, src => src.Comment)
.Inherits<BaseModel, Entity.IBaseEntity>();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
namespace Pims.Api.Models.Concepts
{
public class AcquisitionFileOwnerRepresentativeModel : BaseModel
{
#region Properties

/// <summary>
/// get/set - The relationship id.
/// </summary>
public long? Id { get; set; }

/// <summary>
/// get/set - The Id of the person associated with an acquisition file as an owner representative.
/// </summary>
public long? PersonId { get; set; }

/// <summary>
/// get/set - The Id of the acquisition file related to this representative.
/// </summary>
public long? AcquisitionFileId { get; set; }

/// <summary>
/// get/set - The person associated with an acquisition file as an owner representative.
/// </summary>
public PersonModel Person { get; set; }

/// <summary>
/// get/set - Additional comment concerning this owner representative.
/// </summary>
public string Comment { get; set; }

/// <summary>
/// get/set - The relationship's disabled status flag.
/// </summary>
public bool? IsDisabled { get; set; }

#endregion
}
}
13 changes: 8 additions & 5 deletions source/backend/dal/Repositories/AcquisitionFileRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ public PimsAcquisitionFile GetById(long id)
.ThenInclude(x => x.Country)
.Include(r => r.PimsAcquisitionOwnerSolicitors)
.ThenInclude(rp => rp.Person)
.Include(r => r.PimsAcquisitionOwnerReps)
.ThenInclude(rp => rp.Person)
.FirstOrDefault(x => x.AcquisitionFileId == id) ?? throw new KeyNotFoundException();
}

Expand Down Expand Up @@ -137,7 +139,7 @@ public PimsAcquisitionFile Update(PimsAcquisitionFile acquisitionFile)
using var scope = Logger.QueryScope();
acquisitionFile.ThrowIfNull(nameof(acquisitionFile));

var existingAcqFile = this.Context.PimsAcquisitionFiles
var existingAcqFile = Context.PimsAcquisitionFiles
.FirstOrDefault(x => x.AcquisitionFileId == acquisitionFile.Internal_Id) ?? throw new KeyNotFoundException();

// PSP-4413 Changing the MOTI region triggers an update to the ACQ File Number
Expand All @@ -153,10 +155,11 @@ public PimsAcquisitionFile Update(PimsAcquisitionFile acquisitionFile)
acquisitionFile.FileNumber = existingAcqFile.FileNumber;
}

this.Context.Entry(existingAcqFile).CurrentValues.SetValues(acquisitionFile);
this.Context.UpdateChild<PimsAcquisitionFile, long, PimsAcquisitionFilePerson, long>(p => p.PimsAcquisitionFilePeople, acquisitionFile.Internal_Id, acquisitionFile.PimsAcquisitionFilePeople.ToArray());
this.Context.UpdateChild<PimsAcquisitionFile, long, PimsAcquisitionOwnerSolicitor, long>(p => p.PimsAcquisitionOwnerSolicitors, acquisitionFile.Internal_Id, acquisitionFile.PimsAcquisitionOwnerSolicitors.ToArray());
this.Context.UpdateGrandchild<PimsAcquisitionFile, long, PimsAcquisitionOwner>(o => o.PimsAcquisitionOwners, oa => oa.Address, acquisitionFile.Internal_Id, acquisitionFile.PimsAcquisitionOwners.ToArray());
Context.Entry(existingAcqFile).CurrentValues.SetValues(acquisitionFile);
Context.UpdateChild<PimsAcquisitionFile, long, PimsAcquisitionFilePerson, long>(p => p.PimsAcquisitionFilePeople, acquisitionFile.Internal_Id, acquisitionFile.PimsAcquisitionFilePeople.ToArray());
Context.UpdateChild<PimsAcquisitionFile, long, PimsAcquisitionOwnerSolicitor, long>(p => p.PimsAcquisitionOwnerSolicitors, acquisitionFile.Internal_Id, acquisitionFile.PimsAcquisitionOwnerSolicitors.ToArray());
Context.UpdateChild<PimsAcquisitionFile, long, PimsAcquisitionOwnerRep, long>(p => p.PimsAcquisitionOwnerReps, acquisitionFile.Internal_Id, acquisitionFile.PimsAcquisitionOwnerReps.ToArray());
Context.UpdateGrandchild<PimsAcquisitionFile, long, PimsAcquisitionOwner>(o => o.PimsAcquisitionOwners, oa => oa.Address, acquisitionFile.Internal_Id, acquisitionFile.PimsAcquisitionOwners.ToArray());

return acquisitionFile;
}
Expand Down
15 changes: 15 additions & 0 deletions source/backend/entities/Partials/AcquisitionFileOwnerRep.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations.Schema;

namespace Pims.Dal.Entities
{
/// <summary>
/// PimsAcquisitionOwnerRep class, provides an entity for the datamodel to manage the relationship between Person (Owner Representative) and Acquisition Files.
/// </summary>
public partial class PimsAcquisitionOwnerRep : StandardIdentityBaseAppEntity<long>, IDisableBaseAppEntity
{
#region Properties
[NotMapped]
public override long Internal_Id { get => this.OwnerRepresentativeId; set => this.OwnerRepresentativeId = value; }
#endregion
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using FluentAssertions;
using Moq;
using Pims.Core.Test;
Expand Down Expand Up @@ -198,6 +199,104 @@ public void Update_Success()
result.FileName.Should().Be("updated");
}

[Fact]
public void Update_Acquisition_OwnerRep_Add()
{
// Arrange
var helper = new TestHelper();
var user = PrincipalHelper.CreateForPermission(Permissions.AcquisitionFileEdit);

var context = helper.CreatePimsContext(user, true);

var person = EntityHelper.CreatePerson(1, "tester", "chester");
context.AddAndSaveChanges(person);

var acqFile = EntityHelper.CreateAcquisitionFile(region: context.PimsRegions.FirstOrDefault());
context.AddAndSaveChanges(acqFile);

var repository = helper.CreateRepository<AcquisitionFileRepository>(user);

// Act
var acquisitionUpdated = EntityHelper.CreateAcquisitionFile(acqFileId: 1, region: context.PimsRegions.FirstOrDefault());
acquisitionUpdated.PimsAcquisitionOwnerReps.Add(
new PimsAcquisitionOwnerRep() { AcquisitionFileId = acqFile.Internal_Id, PersonId = person.Internal_Id, Comment = "blah blah" }
);

var result = repository.Update(acquisitionUpdated);

// Assert
result.Should().NotBeNull();
result.PimsAcquisitionOwnerReps.Should().HaveCount(1);
result.PimsAcquisitionOwnerReps.First().Person.Should().Be(person);
result.PimsAcquisitionOwnerReps.First().Comment.Should().Be("blah blah");
}

[Fact]
public void Update_Acquisition_OwnerRep_Update()
{
// Arrange
var helper = new TestHelper();
var user = PrincipalHelper.CreateForPermission(Permissions.AcquisitionFileEdit);

var context = helper.CreatePimsContext(user, true);

var person = EntityHelper.CreatePerson(1, "tester", "chester");
var updatePerson = EntityHelper.CreatePerson(2, "tester", "two");
updatePerson.PimsPersonAddresses = person.PimsPersonAddresses;
context.AddAndSaveChanges(person, updatePerson);

var acqFile = EntityHelper.CreateAcquisitionFile(region: context.PimsRegions.FirstOrDefault());
acqFile.PimsAcquisitionOwnerReps.Add(
new PimsAcquisitionOwnerRep() { AcquisitionFileId = acqFile.Internal_Id, PersonId = person.Internal_Id, Comment = "blah blah" }
);
context.AddAndSaveChanges(acqFile);

var repository = helper.CreateRepository<AcquisitionFileRepository>(user);

// Act
var acquisitionUpdated = EntityHelper.CreateAcquisitionFile(acqFileId: 1, region: context.PimsRegions.FirstOrDefault());
acquisitionUpdated.PimsAcquisitionOwnerReps.Add(
new PimsAcquisitionOwnerRep() { AcquisitionFileId = acqFile.Internal_Id, PersonId = updatePerson.Internal_Id, Comment = "updated comment" }
);

var result = repository.Update(acquisitionUpdated);

// Assert
result.Should().NotBeNull();
result.PimsAcquisitionOwnerReps.Should().HaveCount(1);
result.PimsAcquisitionOwnerReps.First().Person.Should().Be(updatePerson);
result.PimsAcquisitionOwnerReps.First().Comment.Should().Be("updated comment");
}

[Fact]
public void Update_Acquisition_OwnerRep_Remove()
{
// Arrange
var helper = new TestHelper();
var user = PrincipalHelper.CreateForPermission(Permissions.AcquisitionFileEdit);

var context = helper.CreatePimsContext(user, true);

var person = EntityHelper.CreatePerson(1, "tester", "chester");
context.AddAndSaveChanges(person);

var acqFile = EntityHelper.CreateAcquisitionFile(region: context.PimsRegions.FirstOrDefault());
acqFile.PimsAcquisitionOwnerReps.Add(
new PimsAcquisitionOwnerRep() { AcquisitionFileId = acqFile.Internal_Id, PersonId = person.Internal_Id, Comment = "blah blah" }
);
context.AddAndSaveChanges(acqFile);

var repository = helper.CreateRepository<AcquisitionFileRepository>(user);

// Act
var acquisitionUpdated = EntityHelper.CreateAcquisitionFile(acqFileId: 1, region: context.PimsRegions.FirstOrDefault());
var result = repository.Update(acquisitionUpdated);

// Assert
result.Should().NotBeNull();
result.PimsAcquisitionOwnerReps.Should().BeEmpty();
}

[Fact]
public void Update_Null()
{
Expand Down
2 changes: 1 addition & 1 deletion source/frontend/src/features/notes/NoteContainer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ describe('NoteContainer component', () => {

beforeEach(() => {
mockAxios.onGet(new RegExp('users/info/*')).reply(200, {});
mockAxios.onGet(new RegExp('notes/activity/*')).reply(200, mockNoteResponse(1));
mockAxios.onGet(new RegExp('notes/*')).reply(200, mockNoteResponse(1));
});

afterEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,9 @@ exports[`NoteContainer component renders as expected 1`] = `
class="col"
>
<span>
<strong />
<strong>
Jul 20, 2022
</strong>
by
<span
Expand All @@ -267,7 +269,7 @@ exports[`NoteContainer component renders as expected 1`] = `
id="userNameTooltip"
>
<strong>
USER
admin
</strong>
</span>
</span>
Expand All @@ -285,7 +287,9 @@ exports[`NoteContainer component renders as expected 1`] = `
class="col"
>
<span>
<strong />
<strong>
Jul 20, 2022
</strong>
by
<span
Expand All @@ -294,7 +298,7 @@ exports[`NoteContainer component renders as expected 1`] = `
id="userNameTooltip"
>
<strong>
USER
admin
</strong>
</span>
</span>
Expand Down Expand Up @@ -338,7 +342,9 @@ exports[`NoteContainer component renders as expected 1`] = `
readonly=""
rows="15"
title="Note"
/>
>
Test Note
</textarea>
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit ff4043b

Please sign in to comment.