Skip to content

Commit

Permalink
Psp 8368 variable payments, gst fixes, unit tests. (#4166)
Browse files Browse the repository at this point in the history
* psp-8368 add ability to track variable payments.

* ensure that rent categories only display for variable payments.

* WIP

* test updates.

* snapshot update.

* lint correction.

* code review comments.

* disable test temporarily.

* disable test.

* disable other test.

* cleanup.

---------

Co-authored-by: Smith <devin.smith@quartech.com>
  • Loading branch information
devinleighsmith and Smith authored Jul 9, 2024
1 parent 55757af commit 7a51426
Show file tree
Hide file tree
Showing 160 changed files with 3,982 additions and 965 deletions.
2 changes: 2 additions & 0 deletions source/backend/api/Controllers/LookupController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ public IActionResult GetAll()
var dispositionChecklistSectionTypes = _mapper.Map<Model.LookupModel[]>(_lookupRepository.GetAllDispositionChecklistSectionTypes());
var historicalNumberTypes = _mapper.Map<Model.LookupModel[]>(_lookupRepository.GetAllHistoricalNumberTypes());
var leaseChecklistSectionTypes = _mapper.Map<Model.LookupModel[]>(_lookupRepository.GetAllLeaseChecklistSectionTypes());
var leasePaymentCategoryTypes = _mapper.Map<Model.LookupModel[]>(_lookupRepository.GetAllLeasePaymentCategoryTypes());

var codes = new List<object>();
codes.AddRange(areaUnitTypes);
Expand Down Expand Up @@ -222,6 +223,7 @@ public IActionResult GetAll()
codes.AddRange(dispositionChecklistSectionTypes);
codes.AddRange(historicalNumberTypes);
codes.AddRange(leaseChecklistSectionTypes);
codes.AddRange(leasePaymentCategoryTypes);

var response = new JsonResult(codes);

Expand Down
32 changes: 26 additions & 6 deletions source/backend/api/Services/LeasePaymentService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using Pims.Api.Models.CodeTypes;
using Pims.Dal.Entities;
using Pims.Dal.Repositories;
using static Pims.Dal.Entities.PimsLeasePaymentStatusType;
Expand Down Expand Up @@ -52,22 +54,40 @@ public PimsLeasePayment AddPayment(long leaseId, PimsLeasePayment payment)
return updatedPayment;
}

private static string GetPaymentStatus(PimsLeasePayment payment, PimsLeasePeriod parent)
public static string GetPaymentStatus(PimsLeasePayment payment, PimsLeasePeriod parent)
{
decimal? expectedTotal = (parent.PaymentAmount ?? 0) + (parent.GstAmount ?? 0);
if (payment.PaymentAmountTotal == 0)
if (!Enum.TryParse(payment.LeasePaymentCategoryTypeCode, out LeasePaymentCategoryTypes leasePaymentCategoryType))
{
throw new InvalidOperationException();
}
decimal? expectedTotal;
switch (leasePaymentCategoryType)
{
case LeasePaymentCategoryTypes.VBL:
expectedTotal = (parent?.VblRentAgreedPmt ?? 0) + (parent?.VblRentGstAmount ?? 0);
break;
case LeasePaymentCategoryTypes.ADDL:
expectedTotal = (parent?.AddlRentAgreedPmt ?? 0) + (parent?.AddlRentGstAmount ?? 0);
break;
case LeasePaymentCategoryTypes.BASE:
expectedTotal = (parent?.PaymentAmount ?? 0) + (parent?.GstAmount ?? 0);
break;
default:
throw new InvalidOperationException();
}
if (payment?.PaymentAmountTotal == 0)
{
return PimsLeasePaymentStatusTypes.UNPAID;
}
else if (payment.PaymentAmountTotal < expectedTotal)
else if (payment?.PaymentAmountTotal < expectedTotal)
{
return PimsLeasePaymentStatusTypes.PARTIAL;
}
else if (payment.PaymentAmountTotal == expectedTotal)
else if (payment?.PaymentAmountTotal == expectedTotal)
{
return PimsLeasePaymentStatusTypes.PAID;
}
else if (payment.PaymentAmountTotal > expectedTotal)
else if (payment?.PaymentAmountTotal > expectedTotal)
{
return PimsLeasePaymentStatusTypes.OVERPAID;
}
Expand Down
4 changes: 4 additions & 0 deletions source/backend/api/Services/LeasePeriodService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ private void ValidateUpdateRules(PimsLeasePeriod period, long periodId)
{
throw new InvalidOperationException("Period must be 'exercised' if payments have been made.");
}
if(leasePeriodToUpdate.IsVariablePayment != period.IsVariablePayment)
{
throw new InvalidOperationException("Period payment variability may not be changed after period creation.");
}
}

/// <summary>
Expand Down
16 changes: 16 additions & 0 deletions source/backend/apimodels/CodeTypes/LeasePaymentCategoryTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Runtime.Serialization;
using System.Text.Json.Serialization;

namespace Pims.Api.Models.CodeTypes
{
[JsonConverter(typeof(JsonStringEnumMemberConverter))]
public enum LeasePaymentCategoryTypes
{
[EnumMember(Value = "ADDL")]
ADDL,
[EnumMember(Value = "BASE")]
BASE,
[EnumMember(Value = "VBL")]
VBL,
}
}
16 changes: 16 additions & 0 deletions source/backend/apimodels/Models/Concepts/Lease/LeasePeriodMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,20 @@ public void Register(TypeAdapterConfig config)
.Map(dest => dest.IsGstEligible, src => src.IsGstEligible)
.Map(dest => dest.IsTermExercised, src => src.LeasePeriodStatusTypeCode == LeasePeriodStatusTypes.EXER)
.Map(dest => dest.GstAmount, src => src.IsGstEligible.HasValue && src.IsGstEligible.Value ? src.GstAmount : null)
.Map(dest => dest.AdditionalRentGstAmount, src => src.IsAddlRentSubjectToGst.HasValue && src.IsAddlRentSubjectToGst.Value ? src.AddlRentGstAmount : null)
.Map(dest => dest.VariableRentGstAmount, src => src.IsVblRentSubjectToGst.HasValue && src.IsVblRentSubjectToGst.Value ? src.VblRentGstAmount : null)
.Map(dest => dest.PaymentAmount, src => src.PaymentAmount)
.Map(dest => dest.PaymentNote, src => src.PaymentNote)
.Map(dest => dest.PaymentDueDateStr, src => src.PaymentDueDate)
.Map(dest => dest.Payments, src => src.PimsLeasePayments)
.Map(dest => dest.IsFlexible, src => src.IsFlexibleDuration)
.Map(dest => dest.IsVariable, src => src.IsVariablePayment)
.Map(dest => dest.AdditionalRentPaymentAmount, src => src.AddlRentAgreedPmt)
.Map(dest => dest.AdditionalRentFreqTypeCode, src => src.AddlRentFreqNavigation)
.Map(dest => dest.IsAdditionalRentGstEligible, src => src.IsAddlRentSubjectToGst)
.Map(dest => dest.VariableRentPaymentAmount, src => src.VblRentAgreedPmt)
.Map(dest => dest.VariableRentFreqTypeCode, src => src.VblRentFreqNavigation)
.Map(dest => dest.IsVariableRentGstEligible, src => src.IsVblRentSubjectToGst)
.Inherits<Entity.IBaseAppEntity, BaseAuditModel>();

config.NewConfig<LeasePeriodModel, Entity.PimsLeasePeriod>()
Expand All @@ -41,12 +49,20 @@ public void Register(TypeAdapterConfig config)
.Map(dest => dest.IsGstEligible, src => src.IsGstEligible)
.Map(dest => dest.IsPeriodExercised, src => src.LeasePmtFreqTypeCode != null && src.StatusTypeCode.Id == LeasePeriodStatusTypes.EXER)
.Map(dest => dest.GstAmount, src => src.IsGstEligible ? src.GstAmount : null)
.Map(dest => dest.AddlRentGstAmount, src => src.IsAdditionalRentGstEligible == true ? src.AdditionalRentGstAmount : null)
.Map(dest => dest.VblRentGstAmount, src => src.IsVariableRentGstEligible == true ? src.VariableRentGstAmount : null)
.Map(dest => dest.PaymentAmount, src => src.PaymentAmount)
.Map(dest => dest.PaymentNote, src => src.PaymentNote)
.Map(dest => dest.PaymentDueDate, src => src.PaymentDueDateStr)
.Map(dest => dest.PimsLeasePayments, src => src.Payments)
.Map(dest => dest.IsFlexibleDuration, src => src.IsFlexible)
.Map(dest => dest.IsVariablePayment, src => src.IsVariable)
.Map(dest => dest.AddlRentAgreedPmt, src => src.AdditionalRentPaymentAmount)
.Map(dest => dest.AddlRentFreq, src => src.AdditionalRentFreqTypeCode != null ? src.AdditionalRentFreqTypeCode.Id : null)
.Map(dest => dest.IsAddlRentSubjectToGst, src => src.IsAdditionalRentGstEligible)
.Map(dest => dest.VblRentAgreedPmt, src => src.VariableRentPaymentAmount)
.Map(dest => dest.VblRentFreq, src => src.VariableRentFreqTypeCode != null ? src.VariableRentFreqTypeCode.Id : null)
.Map(dest => dest.IsVblRentSubjectToGst, src => src.IsVariableRentGstEligible)
.Inherits<BaseAuditModel, Entity.IBaseAppEntity>();
}
}
Expand Down
40 changes: 40 additions & 0 deletions source/backend/apimodels/Models/Concepts/Lease/LeasePeriodModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ public class LeasePeriodModel : BaseAuditModel
/// </summary>
public decimal? GstAmount { get; set; }

/// <summary>
/// get/set - The stored calculated additional gst amount based on the total payment and the system gst constant.
/// </summary>
public decimal? AdditionalRentGstAmount { get; set; }

/// <summary>
/// get/set - The stored calculated variable gst amount based on the total payment and the system gst constant.
/// </summary>
public decimal? VariableRentGstAmount { get; set; }

/// <summary>
/// get/set - The expected payment amount of the period, less GST.
/// </summary>
Expand Down Expand Up @@ -86,6 +96,36 @@ public class LeasePeriodModel : BaseAuditModel
/// </summary>
public bool IsVariable { get; set; }

/// <summary>
/// get/set - Additional rent payment amount
/// </summary>
public decimal? AdditionalRentPaymentAmount { get; set; }

/// <summary>
/// get/set - Is the additional rent subject to GST.
/// </summary>
public bool? IsAdditionalRentGstEligible { get; set; }

/// <summary>
/// get/set - Frequency type code for additional rent.
/// </summary>
public CodeTypeModel<string> AdditionalRentFreqTypeCode { get; set; }

/// <summary>
/// get/set - Variable rent payment amount
/// </summary>
public decimal? VariableRentPaymentAmount { get; set; }

/// <summary>
/// get/set - Is the variable rent subject to GST.
/// </summary>
public bool? IsVariableRentGstEligible { get; set; }

/// <summary>
/// get/set - Frequency type code for variable rent.
/// </summary>
public CodeTypeModel<string> VariableRentFreqTypeCode { get; set; }

/// <summary>
/// get/set - An (optional) list of payments associated to this period. Should only be set if the period is excercised.
/// </summary>
Expand Down
2 changes: 2 additions & 0 deletions source/backend/apimodels/Models/Concepts/Lease/PaymentMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public void Register(TypeAdapterConfig config)
.Map(dest => dest.LeasePeriodId, src => src.LeasePeriodId)
.Map(dest => dest.LeasePaymentMethodType, src => src.LeasePaymentMethodTypeCodeNavigation)
.Map(dest => dest.LeasePaymentStatusTypeCode, src => src.LeasePaymentStatusTypeCodeNavigation)
.Map(dest => dest.LeasePaymentCategoryTypeCode, src => src.LeasePaymentCategoryTypeCodeNavigation)
.Map(dest => dest.AmountGst, src => src.PaymentAmountGst)
.Map(dest => dest.AmountPreTax, src => src.PaymentAmountPreTax)
.Map(dest => dest.AmountPst, src => src.PaymentAmountPst)
Expand All @@ -27,6 +28,7 @@ public void Register(TypeAdapterConfig config)
.Map(dest => dest.LeasePeriodId, src => src.LeasePeriodId)
.Map(dest => dest.LeasePaymentMethodTypeCode, src => src.LeasePaymentMethodType.Id)
.Map(dest => dest.LeasePaymentStatusTypeCode, src => src.LeasePaymentStatusTypeCode.Id)
.Map(dest => dest.LeasePaymentCategoryTypeCode, src => src.LeasePaymentCategoryTypeCode.Id)
.Map(dest => dest.PaymentAmountGst, src => src.AmountGst)
.Map(dest => dest.PaymentAmountPreTax, src => src.AmountPreTax)
.Map(dest => dest.PaymentAmountPst, src => src.AmountPst)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ public class PaymentModel : BaseAuditModel
/// </summary>
public CodeTypeModel<string> LeasePaymentStatusTypeCode { get; set; }

/// <summary>
/// get/set - The category of the payment: base, variable or additional.
/// </summary>
public CodeTypeModel<string> LeasePaymentCategoryTypeCode { get; set; }

/// <summary>
/// get/set - The date the payment was or will be received.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,7 @@ public interface ILookupRepository : IRepository
IEnumerable<PimsHistoricalFileNumberType> GetAllHistoricalNumberTypes();

IEnumerable<PimsLeaseChklstSectionType> GetAllLeaseChecklistSectionTypes();

IEnumerable<PimsLeasePaymentCategoryType> GetAllLeasePaymentCategoryTypes();
}
}
1 change: 1 addition & 0 deletions source/backend/dal/Repositories/LeasePaymentRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public PimsLeasePayment Add(PimsLeasePayment pimsLeasePayment)
public IEnumerable<PimsLeasePayment> GetAll(DateTime startDate, DateTime endDate)
{
return this.Context.PimsLeasePayments
.Include(p => p.LeasePaymentCategoryTypeCodeNavigation)
.Include(p => p.LeasePeriod)
.ThenInclude(t => t.Lease)
.ThenInclude(p => p.PimsPropertyLeases)
Expand Down
4 changes: 4 additions & 0 deletions source/backend/dal/Repositories/LeasePeriodRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,15 @@ public IEnumerable<PimsLeasePeriod> GetAllByLeaseId(long leaseId)
{
var periods = this.Context.PimsLeasePeriods.AsNoTracking()
.Include(t => t.LeasePmtFreqTypeCodeNavigation)
.Include(t => t.VblRentFreqNavigation)
.Include(t => t.AddlRentFreqNavigation)
.Include(t => t.LeasePeriodStatusTypeCodeNavigation)
.Include(t => t.PimsLeasePayments)
.ThenInclude(p => p.LeasePaymentMethodTypeCodeNavigation)
.Include(t => t.PimsLeasePayments)
.ThenInclude(p => p.LeasePaymentStatusTypeCodeNavigation)
.Include(t => t.PimsLeasePayments)
.ThenInclude(p => p.LeasePaymentCategoryTypeCodeNavigation)
.Where(t => t.LeaseId == leaseId).ToArray();

periods = periods.OrderBy(t => t.PeriodStartDate).ThenBy(t => t.LeasePeriodId).Select(t =>
Expand Down
5 changes: 5 additions & 0 deletions source/backend/dal/Repositories/LookupRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,11 @@ public IEnumerable<PimsLeaseChklstSectionType> GetAllLeaseChecklistSectionTypes(
return Context.PimsLeaseChklstSectionTypes.AsNoTracking().OrderBy(a => a.DisplayOrder).ToArray();
}

public IEnumerable<PimsLeasePaymentCategoryType> GetAllLeasePaymentCategoryTypes()
{
return Context.PimsLeasePaymentCategoryTypes.AsNoTracking().OrderBy(a => a.DisplayOrder).ToArray();
}

#endregion
}
}
36 changes: 36 additions & 0 deletions source/backend/entities/Partials/LeasePaymentCategoryType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.ComponentModel.DataAnnotations.Schema;

namespace Pims.Dal.Entities
{
/// <summary>
/// PimsLeasePaymentCategoryType class, provides an entity for the datamodel to manage a list of lease payment category types.
/// </summary>
public partial class PimsLeasePaymentCategoryType : ITypeEntity<string>
{
#region Properties

/// <summary>
/// get/set - Primary key to identify lease payment frequency type.
/// </summary>
[NotMapped]
public string Id { get => LeasePaymentCategoryTypeCode; set => LeasePaymentCategoryTypeCode = value; }
#endregion

#region Constructors

/// <summary>
/// Create a new instance of a LeasePaymentFrequencyType class.
/// </summary>
/// <param name="id"></param>
public PimsLeasePaymentCategoryType(string id)
: this()
{
Id = id;
}

public PimsLeasePaymentCategoryType()
{
}
#endregion
}
}
Loading

0 comments on commit 7a51426

Please sign in to comment.