From 511932fa584cb965a19f4669e8e4cea5ae5b3e42 Mon Sep 17 00:00:00 2001 From: mahan Date: Sat, 29 Nov 2025 09:44:30 +0330 Subject: [PATCH] Add discount support for institution contract extensions - Introduce DiscountPercentage and DiscountAmount fields to contract creation and payment models - Implement discount calculation logic in repository - Add SetDiscountForExtension API endpoint and related request/response models - Update contract creation and extension flows to handle discounts --- .../IInstitutionContractRepository.cs | 5 +- .../InstitutionContract.cs | 2 +- .../InstitutionContractExtensionTemp.cs | 1 + .../CreateInstitutionContractRequest.cs | 4 + .../IInstitutionContractApplication.cs | 20 ++++ ...titutionContractPaymentOneTimeViewModel.cs | 3 + .../InstitutionContractApplication.cs | 12 ++- .../InstitutionContractRepository.cs | 99 ++++++++++++++++++- .../institutionContractController.cs | 7 ++ 9 files changed, 147 insertions(+), 6 deletions(-) diff --git a/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs b/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs index 33ced579..dd665510 100644 --- a/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs +++ b/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs @@ -56,6 +56,8 @@ public interface IInstitutionContractRepository : IRepository GetVerificationDetails(Guid id); Task GetByPublicIdAsync(Guid id); + InstitutionContractExtensionPaymentResponse CalculateDiscount(InstitutionContractSetDiscountRequest request); + #region Extension @@ -63,9 +65,10 @@ public interface IInstitutionContractRepository : IRepository GetExtensionWorkshops(InstitutionContractExtensionWorkshopsRequest request); Task GetExtensionInstitutionPlan(InstitutionContractExtensionPlanRequest request); Task GetExtensionPaymentMethod(InstitutionContractExtensionPaymentRequest request); + Task SetDiscountForExtension(InstitutionContractSetDiscountForExtensionRequest request); Task ExtensionComplete(InstitutionContractExtensionCompleteRequest request); - #endregion + #endregion #region Upgrade(Amendment) diff --git a/Company.Domain/InstitutionContractAgg/InstitutionContract.cs b/Company.Domain/InstitutionContractAgg/InstitutionContract.cs index 0484a1c7..9a235715 100644 --- a/Company.Domain/InstitutionContractAgg/InstitutionContract.cs +++ b/Company.Domain/InstitutionContractAgg/InstitutionContract.cs @@ -19,7 +19,7 @@ public class InstitutionContract : EntityBase string contractEndFa, double contractAmount, double dailyCompenseation, double obligation, double totalAmount, int extensionNo, string workshopManualCount, string employeeManualCount, string description, string officialCompany, string typeOfcontract, string hasValueAddedTax, double valueAddedTax, - List workshopDetails, long lawId) + List workshopDetails, long lawId,int discountPercentage, double discountAmount) { ContractNo = contractNo; RepresentativeId = representativeId; diff --git a/Company.Domain/InstitutionContractExtensionTempAgg/InstitutionContractExtensionTemp.cs b/Company.Domain/InstitutionContractExtensionTempAgg/InstitutionContractExtensionTemp.cs index 568ae4a5..9075e183 100644 --- a/Company.Domain/InstitutionContractExtensionTempAgg/InstitutionContractExtensionTemp.cs +++ b/Company.Domain/InstitutionContractExtensionTempAgg/InstitutionContractExtensionTemp.cs @@ -65,6 +65,7 @@ public class InstitutionContractExtensionTemp MonthlyPayment = monthly; OneTimePayment = oneTime; } + } diff --git a/CompanyManagment.App.Contracts/InstitutionContract/CreateInstitutionContractRequest.cs b/CompanyManagment.App.Contracts/InstitutionContract/CreateInstitutionContractRequest.cs index 3cebc401..fb4c9f08 100644 --- a/CompanyManagment.App.Contracts/InstitutionContract/CreateInstitutionContractRequest.cs +++ b/CompanyManagment.App.Contracts/InstitutionContract/CreateInstitutionContractRequest.cs @@ -102,6 +102,10 @@ public class CreateInstitutionContractRequest public double OneMonthAmount { get; set; } public long LawId { get; set; } + + public int DiscountPercentage { get; set; } + + public double DiscountAmount { get; set; } } /// /// مدت زمان قرارداد نهاد diff --git a/CompanyManagment.App.Contracts/InstitutionContract/IInstitutionContractApplication.cs b/CompanyManagment.App.Contracts/InstitutionContract/IInstitutionContractApplication.cs index 710530f2..f1374ff3 100644 --- a/CompanyManagment.App.Contracts/InstitutionContract/IInstitutionContractApplication.cs +++ b/CompanyManagment.App.Contracts/InstitutionContract/IInstitutionContractApplication.cs @@ -228,6 +228,10 @@ public interface IInstitutionContractApplication Task GetExtensionPaymentMethod( InstitutionContractExtensionPaymentRequest request); + + Task SetDiscountForExtension( + InstitutionContractSetDiscountForExtensionRequest request); + Task ExtensionComplete(InstitutionContractExtensionCompleteRequest request); Task> GetInstitutionContractSelectList(string search,string selected); @@ -257,6 +261,22 @@ public interface IInstitutionContractApplication } +public class InstitutionContractSetDiscountForExtensionRequest +{ + public Guid TempId { get; set; } + public int DiscountPercentage { get; set; } + public double PaymentAmount { get; set; } + public bool IsInstallment { get; set; } +} + +public class InstitutionContractSetDiscountRequest +{ + public int DiscountPercentage { get; set; } + public double PaymentAmount { get; set; } + public InstitutionContractDuration Duration { get; set; } + public bool IsInstallment { get; set; } +} + public class InstitutionContractPrintViewModel { public InstitutionContratVerificationParty FirstParty { get; set; } diff --git a/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractPaymentOneTimeViewModel.cs b/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractPaymentOneTimeViewModel.cs index fcc28d47..2cee866e 100644 --- a/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractPaymentOneTimeViewModel.cs +++ b/CompanyManagment.App.Contracts/InstitutionContract/InstitutionContractPaymentOneTimeViewModel.cs @@ -17,6 +17,9 @@ public class InstitutionContractPaymentOneTimeViewModel /// مبلغ قابل پرداخت /// public string PaymentAmount { get; set; } + + public string DiscountedAmount { get; set; } + public int DiscountPercetage { get; set; } } public class InstitutionContractPaymentMonthlyViewModel:InstitutionContractPaymentOneTimeViewModel { diff --git a/CompanyManagment.Application/InstitutionContractApplication.cs b/CompanyManagment.Application/InstitutionContractApplication.cs index e693865e..dec26cd1 100644 --- a/CompanyManagment.Application/InstitutionContractApplication.cs +++ b/CompanyManagment.Application/InstitutionContractApplication.cs @@ -223,7 +223,7 @@ public class InstitutionContractApplication : IInstitutionContractApplication command.ContractStartFa, contractEndGr, command.ContractEndFa, command.ContractAmount, command.DailyCompenseation, command.Obligation, command.TotalAmount, 0, command.WorkshopManualCount, command.EmployeeManualCount, command.Description, - command.OfficialCompany, command.TypeOfContract, command.HasValueAddedTax, command.ValueAddedTax, [], command.LawId); + command.OfficialCompany, command.TypeOfContract, command.HasValueAddedTax, command.ValueAddedTax, [], command.LawId,0,0); _institutionContractRepository.Create(createContract); _institutionContractRepository.SaveChanges(); @@ -332,7 +332,7 @@ public class InstitutionContractApplication : IInstitutionContractApplication command.DailyCompenseation, command.Obligation, command.TotalAmount, command.ExtensionNo, command.WorkshopManualCount, command.EmployeeManualCount, command.Description, command.OfficialCompany, command.TypeOfContract, command.HasValueAddedTax, - command.ValueAddedTax, [], command.LawId); + command.ValueAddedTax, [], command.LawId,0,0); _institutionContractRepository.Create(createContract); _institutionContractRepository.SaveChanges(); @@ -1085,7 +1085,7 @@ public class InstitutionContractApplication : IInstitutionContractApplication command.Workshops.Count.ToString(), command.Workshops.Sum(x => x.PersonnelCount).ToString(), command.Description, "NotOfficial", "JobRelation", hasValueAddedTax, - command.TaxAmount, workshopDetails, command.LawId); + command.TaxAmount, workshopDetails, command.LawId,command.DiscountPercentage,command.DiscountAmount ); FinancialStatment financialStatement; @@ -1446,6 +1446,12 @@ public class InstitutionContractApplication : IInstitutionContractApplication return await _institutionContractRepository.GetExtensionPaymentMethod(request); } + public async Task SetDiscountForExtension( + InstitutionContractSetDiscountForExtensionRequest request) + { + return await _institutionContractRepository.SetDiscountForExtension(request); + } + public async Task ExtensionComplete(InstitutionContractExtensionCompleteRequest request) { return await _institutionContractRepository.ExtensionComplete(request); diff --git a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs index 8bf55d43..031cef14 100644 --- a/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs +++ b/CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs @@ -1870,6 +1870,51 @@ public class InstitutionContractRepository : RepositoryBase x.PublicId == id); } + public InstitutionContractExtensionPaymentResponse CalculateDiscount(InstitutionContractSetDiscountRequest request) + { + var baseAmount = request.PaymentAmount; + var discountAmount = (baseAmount * request.DiscountPercentage) / 100; + var paymentAmount = baseAmount - discountAmount; + var taxAmount = paymentAmount * 0.10; + var totalAmount = paymentAmount + taxAmount; + InstitutionContractPaymentMonthlyViewModel monthlyPayment = null; + InstitutionContractPaymentOneTimeViewModel oneTimePayment = null; + + if (request.IsInstallment) + { + monthlyPayment = new InstitutionContractPaymentMonthlyViewModel() + { + TotalAmount = totalAmount.ToMoney(), + PaymentAmount = paymentAmount.ToMoney(), + Tax = taxAmount.ToMoney(), + DiscountedAmount = discountAmount.ToMoney(), + DiscountPercetage = request.DiscountPercentage, + Installments = InstitutionMonthlyInstallmentCaculation((int)request.Duration, + totalAmount, DateTime.Now.ToFarsi()) + }; + } + else + { + oneTimePayment = new InstitutionContractPaymentOneTimeViewModel() + { + TotalAmount = totalAmount.ToMoney(), + PaymentAmount = paymentAmount.ToMoney(), + Tax = taxAmount.ToMoney(), + DiscountedAmount = discountAmount.ToMoney(), + DiscountPercetage = request.DiscountPercentage + }; + } + + if (discountAmount > baseAmount) + throw new BadRequestException("مقدار تخفیف نمی‌تواند بیشتر از مبلغ کل باشد"); + + return new InstitutionContractExtensionPaymentResponse() + { + Monthly = monthlyPayment, + OneTime = oneTimePayment + }; + } + #region Extension public async Task GetExtensionInquiry(long previousContractId) @@ -2177,6 +2222,58 @@ public class InstitutionContractRepository : RepositoryBase SetDiscountForExtension(InstitutionContractSetDiscountForExtensionRequest request) + { + + if (request.DiscountPercentage <= 0) + throw new BadRequestException("مقدار تخفیف نمی‌تواند برابر یا کمتر از صفر باشد"); + var institutionTemp = await _institutionExtensionTemp.Find(x => x.Id == request.TempId) + .FirstOrDefaultAsync(); + if (institutionTemp == null) + { + throw new BadRequestException("اطلاعات وارد شده نامعتبر است"); + } + + if (request.IsInstallment) + { + if(institutionTemp.MonthlyPayment.DiscountPercetage>0) + throw new BadRequestException("تخفیف قبلا برای این قرارداد اعمال شده است"); + } + else + { + if(institutionTemp.OneTimePayment.DiscountPercetage>0) + throw new BadRequestException("تخفیف قبلا برای این قرارداد اعمال شده است"); + } + + var calculateRequest = new InstitutionContractSetDiscountRequest() + { + Duration = institutionTemp.Duration.Value, + PaymentAmount = request.PaymentAmount, + DiscountPercentage = request.DiscountPercentage, + IsInstallment = request.IsInstallment + }; + var res = CalculateDiscount(calculateRequest); + + //این به این دلیل هست که متد caclulate discount یکی از مقادیر رو پر میکنه و ما نیاز داریم هر دو مقدار رو داشته باشیم + if (request.IsInstallment) + { + res.OneTime = institutionTemp.OneTimePayment; + } + else + { + res.Monthly = institutionTemp.MonthlyPayment; + } + institutionTemp.SetAmountAndDuration(institutionTemp.Duration.Value, res.Monthly, res.OneTime); + await _institutionExtensionTemp.ReplaceOneAsync(x => x.Id == institutionTemp.Id, + institutionTemp); + + return new() + { + OneTime = institutionTemp.OneTimePayment, + Monthly = institutionTemp.MonthlyPayment + }; + } + public async Task ExtensionComplete(InstitutionContractExtensionCompleteRequest request) { var institutionContractTemp = await _institutionExtensionTemp.Find(x => x.Id == request.TemporaryId) @@ -2321,7 +2418,7 @@ public class InstitutionContractRepository : RepositoryBase> SetDiscountForExtension([FromBody]InstitutionContractSetDiscountForExtensionRequest request) + { + var res =await _institutionContractApplication.SetDiscountForExtension(request); + return res; + } [HttpPost("extenstion/complete")] public async Task> ExtensionComplete([FromBody]InstitutionContractExtensionCompleteRequest request)