diff --git a/Company.Domain/LoanAgg/ILoanRepository.cs b/Company.Domain/LoanAgg/ILoanRepository.cs index 2f91b4a6..2a0fa5a7 100644 --- a/Company.Domain/LoanAgg/ILoanRepository.cs +++ b/Company.Domain/LoanAgg/ILoanRepository.cs @@ -2,13 +2,14 @@ using Company.Domain.LoanAgg.Entities; using CompanyManagment.App.Contracts.Loan; using System.Collections.Generic; +using System.Threading.Tasks; namespace Company.Domain.LoanAgg; public interface ILoanRepository:IRepository { List GetSearchList(LoanSearchViewModel searchViewModel); - LoanViewModel GetDetails(long id); + Task GetDetails(long id); void Remove(Loan entity); List GetBy(IEnumerable ids); void RemoveRange(IEnumerable loans); diff --git a/CompanyManagment.App.Contracts/Loan/ILoanApplication.cs b/CompanyManagment.App.Contracts/Loan/ILoanApplication.cs index 1e372d6f..f55f3132 100644 --- a/CompanyManagment.App.Contracts/Loan/ILoanApplication.cs +++ b/CompanyManagment.App.Contracts/Loan/ILoanApplication.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Threading.Tasks; using _0_Framework.Application; using Microsoft.AspNetCore.Mvc.RazorPages; @@ -7,7 +8,7 @@ namespace CompanyManagment.App.Contracts.Loan; public interface ILoanApplication { List GetSearchList(LoanSearchViewModel searchViewModel); - LoanViewModel GetDetails(long id); + Task GetDetails(long id); OperationResult Create(CreateLoanViewModel command); List CalculateLoanInstallment(string amount , int installmentCount,string loanStartDate,bool getRounded); OperationResult Remove(long id); diff --git a/CompanyManagment.App.Contracts/Loan/LoanDetailsViewModel.cs b/CompanyManagment.App.Contracts/Loan/LoanDetailsViewModel.cs new file mode 100644 index 00000000..b73ddf3e --- /dev/null +++ b/CompanyManagment.App.Contracts/Loan/LoanDetailsViewModel.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace CompanyManagment.App.Contracts.Loan; + +public class LoanDetailsViewModel +{ + public long Id { get; set; } + public string EmployeeFullName { get; set; } + public string LoanGrantDate { get; set; } + public string InstallmentCount { get; set; } + public string TotalLoanAmount { get; set; } + public string TotalPaidAmount { get; set; } + public string TotalRemainingAmount { get; set; } + public List Installments { get; set; } +} +public class LoanInstallmentDetailsViewModel +{ + public long Id { get; set; } + public string InstallmentDate { get; set; } + public string InstallmentAmount { get; set; } + public bool IsPaid { get; set; } +} \ No newline at end of file diff --git a/CompanyManagment.Application/LoanApplication.cs b/CompanyManagment.Application/LoanApplication.cs index 9161e8f6..1457faa3 100644 --- a/CompanyManagment.Application/LoanApplication.cs +++ b/CompanyManagment.Application/LoanApplication.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection.Metadata.Ecma335; +using System.Threading.Tasks; using _0_Framework.Application; using Company.Domain.CheckoutAgg; using Company.Domain.CustomizeCheckoutAgg; @@ -36,9 +37,9 @@ public class LoanApplication : ILoanApplication return _loanRepository.GetSearchList(searchModel); } - public LoanViewModel GetDetails(long id) + public async Task GetDetails(long id) { - return _loanRepository.GetDetails(id); + return await _loanRepository.GetDetails(id); } public OperationResult Create(CreateLoanViewModel command) diff --git a/CompanyManagment.EFCore/Repository/LoanRepository.cs b/CompanyManagment.EFCore/Repository/LoanRepository.cs index 7de894b3..6f23763e 100644 --- a/CompanyManagment.EFCore/Repository/LoanRepository.cs +++ b/CompanyManagment.EFCore/Repository/LoanRepository.cs @@ -5,9 +5,11 @@ using Company.Domain.LoanAgg.Entities; using CompanyManagment.App.Contracts.Loan; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using _0_Framework.Application; using Microsoft.EntityFrameworkCore; using System.Globalization; +using System.Collections; namespace CompanyManagment.EFCore.Repository; @@ -20,18 +22,46 @@ public class LoanRepository : RepositoryBase, ILoanRepository _companyContext = companyContext; } - public LoanViewModel GetDetails(long id) + public async Task GetDetails(long id) { - return _companyContext.Loans.Select(x => new LoanViewModel() + var loan = await _companyContext.Loans.FirstOrDefaultAsync(x => x.id == id); + if (loan == null) { - Id = x.id, - WorkshopId = x.WorkshopId, - EmployeeId = x.EmployeeId, - EmployeeFullName = _companyContext.Employees.FirstOrDefault(e => e.id == x.EmployeeId).FullName, - StartDateTime = x.StartDateMonth, - Count = x.Count, - Amount = x.Amount.ToMoney(), - }).FirstOrDefault(x => x.Id == id); + return null; + } + + var employeeName = await _companyContext.Employees.Where(x => x.id == loan.EmployeeId) + .Select(x => x.FName + " " + x.LName).FirstOrDefaultAsync(); + + var startDate = loan.LoanInstallments.MinBy(x => x.InstallmentDate).InstallmentDate; + var endDate = loan.LoanInstallments.MaxBy(x => x.InstallmentDate).InstallmentDate; + + var customizeCheckouts =await _companyContext.CustomizeCheckouts.Where(x => x.WorkshopId == loan.WorkshopId && x.EmployeeId == loan.EmployeeId && + x.ContractStart <= endDate && x.ContractEnd >= startDate).Select(x=> new {x.MonthInt, x.YearInt}).ToListAsync(); + + var result = new LoanDetailsViewModel() + { + TotalLoanAmount = loan.Amount.ToMoney(), + InstallmentCount = loan.LoanInstallments.Count.ToString(), + EmployeeFullName = employeeName, + Id = loan.id, + LoanGrantDate = loan.LoanGrantDate.ToFarsi(), + Installments = loan.LoanInstallments.Select(x => new LoanInstallmentDetailsViewModel() + { + Id = x.Id, + InstallmentAmount = x.AmountForMonth.ToMoney(), + InstallmentDate = x.InstallmentDate.ToFarsi(), + IsPaid = customizeCheckouts.Any(c => c.MonthInt.ToString() == x.Month && c.YearInt.ToString() == x.Year) + }).ToList() + + }; + var totalPaidAmountD = result.Installments.Where(x => x.IsPaid).Sum(x => x.InstallmentAmount.MoneyToDouble()); + var remainingD = result.Installments.Where(x => !x.IsPaid).Sum(x => x.InstallmentAmount.MoneyToDouble()); + result.TotalPaidAmount = totalPaidAmountD.ToMoney(); + result.TotalRemainingAmount= remainingD.ToMoney(); + + return result; + } public List GetBy(IEnumerable ids) diff --git a/ServiceHost/Areas/Client/Pages/Company/Loan/Index.cshtml b/ServiceHost/Areas/Client/Pages/Company/Loan/Index.cshtml index 9d9cec66..e413247f 100644 --- a/ServiceHost/Areas/Client/Pages/Company/Loan/Index.cshtml +++ b/ServiceHost/Areas/Client/Pages/Company/Loan/Index.cshtml @@ -371,8 +371,10 @@ var loanGroupLoadDataAjax = `@Url.Page("./Index", "Search")`; var removeLoanAjax = `@Url.Page("./Index", "Remove")`; var employeeListAjax = `@Url.Page("./Index", "EmployeeList")`; - + var modalDetailLoanAjax = `@Url.Page("./Index", "Detail")`; var deletePermission = @(AuthHelper.GetPermissions().Contains(SubAccountPermissionHelper.DeleteLoanPermissionCode) ? "true" : "false"); + // TODO: Mr.Farokhi, Please set the permission for loan details. + var detailsPermission = true; } diff --git a/ServiceHost/Areas/Client/Pages/Company/Loan/Index.cshtml.cs b/ServiceHost/Areas/Client/Pages/Company/Loan/Index.cshtml.cs index fe72cdf0..98d11786 100644 --- a/ServiceHost/Areas/Client/Pages/Company/Loan/Index.cshtml.cs +++ b/ServiceHost/Areas/Client/Pages/Company/Loan/Index.cshtml.cs @@ -219,6 +219,29 @@ namespace ServiceHost.Areas.Client.Pages.Company.Loan }); } + + #region Details + + public async Task OnGetDetail(long id) + { + var workshopHash = User.FindFirstValue("WorkshopSlug"); + var workshopId = _passwordHasher.SlugDecrypt(workshopHash); + if (workshopId <= 0) + { + var resultError = new ErrorViewModel() + { + Message = "کارگاه شما یافت نشد" + }; + return Partial("../Error/_ErrorModal", resultError); + } + + var command = await _loanApplication.GetDetails(id); + return Partial("ModalDetailLoan", command); + } + + #endregion + + public IActionResult OnGetSearch(LoanSearchViewModel searchModel) { searchModel.WorkshopId = _workshopId; diff --git a/ServiceHost/Areas/Client/Pages/Company/Loan/ModalDetailLoan.cshtml b/ServiceHost/Areas/Client/Pages/Company/Loan/ModalDetailLoan.cshtml new file mode 100644 index 00000000..b3dabea5 --- /dev/null +++ b/ServiceHost/Areas/Client/Pages/Company/Loan/ModalDetailLoan.cshtml @@ -0,0 +1,159 @@ +@model CompanyManagment.App.Contracts.Loan.LoanDetailsViewModel + +@{ + string clientVersion = _0_Framework.Application.Version.StyleVersion; + + var index = 1; +} + +
+ + +
+ + + + + +@* *@ \ No newline at end of file diff --git a/ServiceHost/wwwroot/AssetsClient/pages/Loan/css/Index.css b/ServiceHost/wwwroot/AssetsClient/pages/Loan/css/Index.css index f74b9c02..35774e1a 100644 --- a/ServiceHost/wwwroot/AssetsClient/pages/Loan/css/Index.css +++ b/ServiceHost/wwwroot/AssetsClient/pages/Loan/css/Index.css @@ -288,7 +288,27 @@ } +.btn-detail { + display: flex; + align-items: center; + justify-content: center; + background: rgba(93, 209, 52, 0.3); + /*border: 0.5px solid #FFFFFF;*/ + border-radius: 7px; + color: #ffffff; + font-size: 12px; + padding: 3px 7px; + font-style: normal; + font-weight: 400; + line-height: normal; + white-space: nowrap; + transition: all ease-in .3s; +} + +.btn-detail:hover { + background: rgba(93, 209, 52, 0.4); +} @@ -437,11 +457,11 @@ display: flex; } - button.btn-print, button.btn-edit, button.btn-delete { + button.btn-print, button.btn-edit, button.btn-delete, btn-detail { width: 32%; } - button.btn-print, button.btn-edit span, button.btn-delete span { - display: unset; - } + button.btn-print, button.btn-edit span, button.btn-delete span, btn-detail span { + display: unset; + } } diff --git a/ServiceHost/wwwroot/AssetsClient/pages/Loan/css/ModalDetailLoan.css b/ServiceHost/wwwroot/AssetsClient/pages/Loan/css/ModalDetailLoan.css new file mode 100644 index 00000000..6f0a25a5 --- /dev/null +++ b/ServiceHost/wwwroot/AssetsClient/pages/Loan/css/ModalDetailLoan.css @@ -0,0 +1,242 @@ +.sticky { + position: sticky; + top: 0px; + z-index: 10; +} + +.infoLoan { + background-color: #FCFCFC; + border: 1px solid #DADADA; + border-radius: 7px; + color: #797979; + width: 100%; + font-size: 13px; +} + + +.installmentContainer { + background-color: #F0F0F0; + padding: 9px; + border-radius: 6px; +} + + .installmentContainer .tableLoanDetail { + height: 400px; + overflow-y: auto; + } + + .installmentContainer .totalPaymentLoan { + padding: 7px; + border-radius: 6px; + background-color: #ffffff; + border: 1px solid #DEDEDE; + } + + .installmentContainer .totalPaymentLoan .infoInstallment { + color: #0B5959; + font-weight: 500; + font-size: 13px; + } + + .installmentContainer .totalPaymentLoan .lineSeparete { + background: rgb(255,255,255); + background: linear-gradient(90deg, rgba(255,255,255,1) 0%, rgba(214,214,214,1) 50%, rgba(255,255,255,1) 100%); + height: 1px; + width: 100%; + margin: 1px auto; + } + + .installmentContainer .totalPaymentLoan .infoInstallment.totalPay { + color: #00BE33 !important; + } + + .installmentContainer .totalPaymentLoan .infoInstallment.remainPay { + color: #D41317 !important; + } + + + +.widthTableBadgeSuccess { + background-color: #BBF7D0; + color: #5E9F02; + border-radius: 30px; + padding: 3px 6px; + width: 160px; +} + +.widthTableBadgeNone { + background-color: #E8E0E0; + color: #BF3737; + border-radius: 30px; + /*padding: 3px 6px;*/ + width: 160px; +} + + +.loanDetailTable .width1 { + width: 10% !important; + justify-content: start !important; +} + +.loanDetailTable .width2 { + width: 30% !important; + justify-content: center !important; +} + +.loanDetailTable .width3 { + width: 40% !important; + justify-content: center !important; +} + +.loanDetailTable .width4 { + width: 20% !important; + justify-content: center !important; +} + +.loanDetailTable .width5 { + width: 30% !important; + justify-content: center !important; +} + +.Rtable .Rtable-row .Rtable-cell .Rtable-cell--content > span { +} + +.installmentContainer1 { + background-color: #F0F0F0; + font-size: 12px; + color: #4f4f4f; + white-space: nowrap; + width: 100%; + overflow: hidden; + cursor: grab; + user-select: none; +} + + .installmentContainer1:active { + cursor: grabbing; + } + +.errored { + animation: shake 300ms; + color: #eb3434 !important; + background-color: #fef2f2 !important; + border: 1px solid #eb3434 !important; +} + +.btn-cancel2 { + width: 100% !important; +} + +.calculationBox { + border-radius: 9px; + background-color: #F0F0F0; + width: 100%; + height: 240px; + display: flex; + align-items: center; + justify-content: center; + padding: 0 50px; +} + +.calculationBox1 { + /*border: 1px solid #B4B4B4;*/ + border-radius: 9px; + background-color: #F0F0F0; + width: 100%; + height: 240px; + display: flex; + align-items: start; + justify-content: center; + overflow-y: scroll +} + + +.table { + --bs-table-bg: #F0F0F0; + --bs-table-color: #4f4f4f; + --bs-table-border-color: #B4B4B4; + font-size: 12px; + margin: 0; +} + +tr.sticky { + position: sticky; + top: 0; + z-index: 1; +} + + +@media (max-width:1366px) { + .loanListModal-width { + max-width: 460px; + } +} + +@media (max-width:768px) { + .infoLoan { + font-size: 11px; + } + + .infoLoan .fullname { + white-space: nowrap; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; + } + + + .Rtable .Rtable-row .Rtable-cell { + font-size: 10px; + } + + .Rtable--collapse .Rtable-row { + padding: 0.6em; + margin: 6px 0px 0; + } + + .widthTableBadgeSuccess, + .widthTableBadgeNone { + font-size: 10px; + width: 70px; + } + .Rtable .Rtable-row .Rtable-cell .Rtable-cell--content > span { + font-size: 10px; + width: 22px; + height: 22px; + } + + .loanDetailTable .width1 { + width: 10% !important; + } + + .loanDetailTable .width2 { + width: 20% !important; + } + + .loanDetailTable .width3 { + width: 40% !important; + } + + .loanDetailTable .width4 { + width: 20% !important; + } + + .loanDetailTable .width5 { + width: 30% !important; + } +} + +@media (max-width:576px) { + .btnCreateNew, .btn-cancel2 { + width: 100% !important; + padding: 10px 40px; + display: flex; + justify-content: center; + } +} + +@media (max-height: 667px) { + .installmentContainer .tableLoanDetail { + height: 300px; + } +} diff --git a/ServiceHost/wwwroot/AssetsClient/pages/Loan/js/Index.js b/ServiceHost/wwwroot/AssetsClient/pages/Loan/js/Index.js index 3592b1d0..7bbfec61 100644 --- a/ServiceHost/wwwroot/AssetsClient/pages/Loan/js/Index.js +++ b/ServiceHost/wwwroot/AssetsClient/pages/Loan/js/Index.js @@ -341,10 +341,10 @@ function htmlLoadSimpleListData(loadLoanListData) { var n = pageIndexJs + 1; html += `
-
-
`; + pageIndexJs++; }); @@ -594,7 +645,31 @@ function htmlLoadWithEmployeeDataByDate(loadLoanListData) { - + ${detailsPermission + ? + `` + : + ``} ${deletePermission ? ` - + ${detailsPermission + ? + `` + : + ``} ${deletePermission ? ` @@ -915,15 +1014,57 @@ function htmlLoadWithEmployeeMobileDataByFullname(loadLoanListData) { پرینت - + جزئیات + ` + : + ``} + + ${deletePermission ? + ` + + ` + : + ` + + ` + }
@@ -1054,15 +1195,57 @@ function htmlLoadWithEmployeeMobileDataByDate(loadLoanListData) { ویرایش - + جزئیات + ` + : + ``} + + ${deletePermission ? + ` + + ` + : + ` + + ` + }
@@ -1170,4 +1353,12 @@ function removeAjax(id) { console.log(err); } }); -} \ No newline at end of file +} + + + +function DetailLoan(LoanId) { + var id = Number(LoanId); + var url = `/Client/Company/Loan/Index?id=${id}&handler=Detail`; + AjaxUrlContentModal(url); +}