import Excel SalaryAid

This commit is contained in:
SamSys
2025-03-04 21:40:02 +03:30
parent 21bdf1e696
commit 2843ab8b47
31 changed files with 2074 additions and 109 deletions

View File

@@ -12,7 +12,8 @@ public interface IRepository<TKey, T> where T:class
T Get(TKey id);
List<T> Get();
void Create(T entity);
Task CreateAsync(T entity);
bool ExistsIgnoreQueryFilter(Expression<Func<T, bool>> expression);
bool Exists(Expression<Func<T, bool>> expression);
void SaveChanges();
Task SaveChangesAsync();

View File

@@ -27,6 +27,17 @@ namespace _0_Framework.InfraStructure
_context.Add(entity);
}
public async Task CreateAsync(T entity)
{
await _context.AddAsync(entity);
}
public bool ExistsIgnoreQueryFilter(Expression<Func<T, bool>> expression)
{
return _context.Set<T>().IgnoreQueryFilters().Any(expression);
}
public bool Exists(Expression<Func<T, bool>> expression)
{
return _context.Set<T>().Any(expression);

View File

@@ -44,6 +44,7 @@ public interface IEmployeeRepository : IRepository<long, Employee>
#endregion
#region Mahan
Employee GetByNationalCode(string nationalCode);
List<EmployeeViewModel> GetBy(List<long> employeeIds);
#endregion

View File

@@ -9,6 +9,7 @@ namespace Company.Domain.ReportAgg
{
public interface IReportRepository
{
AllReport GetAllActiveWorkshopsNew(string year, string month);
AllReport GetAllActiveWorkshops(string year, string month);
WorkshopResult GetWorkshopContractDone(string year, string month, long accountId);
WorkshopResult GetWorkshopContractSignDone(string year, string month, long accountId);

View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="EPPlus" Version="7.5.2" />
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="5.0.17" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AccountMangement.Infrastructure.EFCore\AccountMangement.Infrastructure.EFCore.csproj" />
<ProjectReference Include="..\CompanyManagment.EFCore\CompanyManagment.EFCore.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,240 @@
using _0_Framework.Application;
using CompanyManagment.EFCore;
using Microsoft.AspNetCore.Http;
using OfficeOpenXml;
using LicenseContext = OfficeOpenXml.LicenseContext;
namespace CompanyManagement.Infrastructure.Excel.SalaryAid;
public record SalaryAidImportData(long EmployeeId, long WorkshopId, string FullName, double Amount, string AccountNumber, string NationalCode, string SalaryAidDateTime, int Row, bool Duplicated);
public class ExcelValidation<T>
{
public List<T> ValidData { get; set; } = [];
public List<T> RawData { get; set; } = [];
public List<SalaryAidImportExcelError> Errors { get; set; } = [];
};
public record SalaryAidImportExcelError(string Message, int Row, string Columns);
public enum SalaryAidExcelColumns
{
None = 0,
FullName = 1,
NationalCode = 2,
AccountNumber = 3,
Amount = 4
}
public class SalaryAidImportExcel
{
private readonly CompanyContext _companyContext;
private const string META_DATA_PASS = "{0B0A49C2-4CA6-456A-BA7B-9FA4D56171C1}";
public SalaryAidImportExcel(CompanyContext companyContext)
{
_companyContext = companyContext;
}
public ExcelValidation<SalaryAidImportData> ReadAndValidateExcel(IFormFile file, long workshopId)
{
var result = new ExcelValidation<SalaryAidImportData>
{
ValidData = []
};
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
if (file == null || file.Length == 0)
{
result.Errors.Add(new SalaryAidImportExcelError("فایل اکسل ارسال نشده یا خالی است.", 0, SalaryAidExcelColumns.None.ToString()));
return result;
}
using var stream = new MemoryStream();
file.CopyTo(stream);
using var package = new ExcelPackage(stream);
var worksheet = package.Workbook.Worksheets[0];
if (worksheet == null)
{
result.Errors.Add(new SalaryAidImportExcelError("فایل اکسل معتبر نیست.", 0, SalaryAidExcelColumns.None.ToString()));
return result;
}
var customPropsXml = package.Workbook.Properties.CustomPropertiesXml;
// بررسی اینکه آیا ویژگی قبلاً وجود دارد یا نه
var existingProp = customPropsXml.InnerText;
if (existingProp != META_DATA_PASS)
{
result.Errors.Add(new SalaryAidImportExcelError("قالب ارسال شده معتبر نمیباشد", 0, SalaryAidExcelColumns.None.ToString()));
return result;
}
// بررسی اینکه هدرها همان چیزی هستند که ما انتظار داریم
if (worksheet.Cells[2, 1].Text != "نام و نام خانوادگی" ||
worksheet.Cells[2, 2].Text != "کد ملی" ||
worksheet.Cells[2, 3].Text != "شماره حساب" ||
worksheet.Cells[2, 4].Text != "مبلغ قابل پرداخت" ||
worksheet.Cells[1, 1].Text != "تاریخ پرداخت")
{
result.Errors.Add(new SalaryAidImportExcelError("ساختار فایل اکسل اشتباه است.", 0, SalaryAidExcelColumns.None.ToString()));
return result;
}
var salaryDateFa = worksheet.Cells[1, 4].Text;
if (string.IsNullOrWhiteSpace(salaryDateFa))
{
result.Errors.Add(new SalaryAidImportExcelError("لطفا در سلول زرد رنگ تاریخ پرداخت را وارد کنید", 0, SalaryAidExcelColumns.None.ToString()));
return result;
}
if (salaryDateFa.TryToGeorgianDateTime(out var salaryDateTime) == false)
{
result.Errors.Add(new SalaryAidImportExcelError("تاریخ وارد شده نامعتبر است", 0, SalaryAidExcelColumns.None.ToString()));
}
if (salaryDateTime > DateTime.Now)
{
result.Errors.Add(new SalaryAidImportExcelError("تاریخ پرداخت مساعده می بایست تاریخ امروز یا قبل تر باشد", 0, SalaryAidExcelColumns.None.ToString()));
}
int rowCount = worksheet.Dimension.Rows;
int rowStart = 3;
if (rowCount < rowStart)
{
result.Errors.Add(new SalaryAidImportExcelError("دیتا خالی میباشد", 0, SalaryAidExcelColumns.None.ToString()));
return result;
}
for (var row = rowStart; row <= rowCount; row++)
{
var fullName = worksheet.Cells[row, 1]?.Text?.Trim();
var nationalCode = worksheet.Cells[row, 2]?.Text?.Trim();
var accountNumber = worksheet.Cells[row, 3]?.Value?.ToString()?.Trim();
var amountText = worksheet.Cells[row, 4]?.Value?.ToString()?.Trim();
if (!double.TryParse(amountText, out double amount) || amount <= 0)
{
result.Errors.Add(new SalaryAidImportExcelError("مبلغ خالی یا نامعتبر است", row, SalaryAidExcelColumns.Amount.ToString()));
}
result.RawData.Add(new SalaryAidImportData(0, workshopId, fullName, amount, accountNumber, nationalCode, salaryDateFa, row, false));
if (string.IsNullOrWhiteSpace(fullName))
{
result.Errors.Add(new SalaryAidImportExcelError(" نام و نام خانوادگی خالی است", row, SalaryAidExcelColumns.FullName.ToString()));
}
if (string.IsNullOrWhiteSpace(accountNumber))
{
result.Errors.Add(new SalaryAidImportExcelError(" شماره حساب خالی است", row, SalaryAidExcelColumns.AccountNumber.ToString()));
}
if (string.IsNullOrWhiteSpace(nationalCode))
{
result.Errors.Add(new SalaryAidImportExcelError("کدملی خالی است", row, SalaryAidExcelColumns.NationalCode.ToString()));
}
//if (accountNumber is { Length: < 10 or > 16 })
//{
// result.Errors.Add(new SalaryAidImportExcelError("شماره حساب نامعتبر است", row, SalaryAidExcelColumns.AccountNumber.ToString()));
//}
if (nationalCode.NationalCodeValid() != "valid")
{
result.Errors.Add(new SalaryAidImportExcelError("کد ملی نامعتبر است", row, SalaryAidExcelColumns.NationalCode.ToString()));
}
var employee = _companyContext.Employees.FirstOrDefault(x => x.NationalCode == nationalCode);
if (employee == null)
{
result.Errors.Add(new SalaryAidImportExcelError($" پرسنلی با کد ملی {nationalCode} یافت نشد", row, SalaryAidExcelColumns.NationalCode.ToString()));
continue;
}
const double threshold = 0.4;
var inputWords = fullName.Split(' ').ToArray();
var dbWords = string.Join(" ", employee.FullName.Split(' '));
var inputMatchCount = inputWords.Count(dbWords.Contains);
var accuracyDbToInput = (double)inputMatchCount / inputWords.Length;
var dbArray = dbWords.Split(' ').ToArray();
var dataBaseMatchCount = dbArray.Count(fullName.Contains);
var accuracyInputToDb = (double)dataBaseMatchCount / dbArray.Length;
if (accuracyDbToInput < threshold || accuracyInputToDb < threshold)
{
result.Errors.Add(new SalaryAidImportExcelError($" نام و نام خانوادگی {fullName} با کد ملی وارد شده مطابقت ندارد", row, SalaryAidExcelColumns.FullName.ToString()));
}
if ((_companyContext.LeftWorkList.Any(x => x.EmployeeId == employee.id && x.WorkshopId == workshopId) ||
_companyContext.LeftWorkInsuranceList.Any(x => x.EmployeeId == employee.id && x.WorkshopId == workshopId)) == false)
{
result.Errors.Add(new SalaryAidImportExcelError($" پرسنل {fullName} در کارگاه مورد نظر یافت نشد", row, SalaryAidExcelColumns.None.ToString()));
continue;
}
if (_companyContext.EmployeeBankInformationSet.Any(x => x.EmployeeId == employee.id && x.BankAccountNumber == accountNumber) == false)
{
result.Errors.Add(new SalaryAidImportExcelError($"شماره حساب {accountNumber} برای پرسنل {fullName} یافت نشد", row, SalaryAidExcelColumns.AccountNumber.ToString()));
}
var month = Convert.ToInt32(salaryDateFa.Substring(5, 2));
var year = Convert.ToInt32(salaryDateFa.Substring(0, 4));
if (_companyContext.CustomizeCheckouts.Any(x => x.WorkshopId == workshopId && x.EmployeeId == employee.id && x.YearInt == year && x.MonthInt == month))
{
result.Errors.Add(new SalaryAidImportExcelError($" پرسنل {fullName} در تاریخ {salaryDateFa} دارای فیش حقوقی غیررسمی است.", row, SalaryAidExcelColumns.None.ToString()));
}
if (_companyContext.SalaryAids.Any(x => x.Amount == amount && x.EmployeeId == employee.id && x.WorkshopId == workshopId && x.SalaryAidDateTime == salaryDateTime))
{
// TODO MAHAN: Vafa Add this Code! Please Check it!
result.RawData.Add(new SalaryAidImportData(employee.id, workshopId, fullName, amount, accountNumber, nationalCode, salaryDateFa, row, true));
continue;
}
result.ValidData.Add(new SalaryAidImportData(employee.id, workshopId, fullName, amount, accountNumber, nationalCode, salaryDateFa, row, false));
}
result.RawData = result.RawData.GroupBy(x => x.Row).Select(x => new SalaryAidImportData(x.First().EmployeeId,
x.First().WorkshopId, x.First().FullName,
x.First().Amount, x.First().AccountNumber, x.First().NationalCode, x.First().SalaryAidDateTime, x.Key,
x.Any(s => s.Duplicated))).ToList();
//result.Errors.GroupBy(x => x.Row).Select(x => new
//{
// Row = x.Key,
// Data =x.Select(s=>new
// {
// s.Columns,
// s.Message
// })
//}).ToList();
return result;
}
}

View File

@@ -8,4 +8,5 @@ public class CreateSalaryAidViewModel
public long WorkshopId { get; set; }
public string Amount { get; set; }
public string SalaryDateTime { get; set; }
public string NationalCode { get; set; }
}

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using _0_Framework.Application;
namespace CompanyManagment.App.Contracts.SalaryAid;
@@ -12,4 +13,6 @@ public interface ISalaryAidApplication
OperationResult Edit(EditSalaryAidViewModel command);
OperationResult Remove(long id);
OperationResult RemoveRange(IEnumerable<long> ids);
Task<OperationResult> CreateRange(List<CreateSalaryAidViewModel> commands);
}

View File

@@ -6,7 +6,9 @@ using _0_Framework.Application;
using Company.Domain.CheckoutAgg;
using CompanyManagment.App.Contracts.Checkout;
using System;
using System.Threading.Tasks;
using Company.Domain.CustomizeCheckoutAgg;
using Company.Domain.EmployeeAgg;
namespace CompanyManagment.Application;
@@ -14,11 +16,13 @@ public class SalaryAidApplication : ISalaryAidApplication
{
private readonly ISalaryAidRepository _salaryAidRepository;
private readonly ICustomizeCheckoutRepository _customizeCheckoutRepository;
private readonly IEmployeeRepository _employeeRepository;
public SalaryAidApplication(ISalaryAidRepository salaryAidRepository, ICustomizeCheckoutRepository customizeCheckoutRepository)
public SalaryAidApplication(ISalaryAidRepository salaryAidRepository, ICustomizeCheckoutRepository customizeCheckoutRepository, IEmployeeRepository employeeRepository)
{
_salaryAidRepository = salaryAidRepository;
_customizeCheckoutRepository = customizeCheckoutRepository;
_employeeRepository = employeeRepository;
}
public List<SalaryAidViewModel> GetSearchList(SalaryAidSearchViewModel searchViewModel)
@@ -130,4 +134,51 @@ public class SalaryAidApplication : ISalaryAidApplication
_salaryAidRepository.SaveChanges();
return op.Succcedded();
}
public async Task<OperationResult> CreateRange(List<CreateSalaryAidViewModel> commands)
{
var op = new OperationResult();
foreach (var command in commands)
{
if (!command.SalaryDateTime.TryToGeorgianDateTime(out var startDate))
{
return op.Failed("تاریخ وارد شده نامعتبر است");
}
if (startDate > DateTime.Now)
{
return op.Failed("تاریخ پرداخت مساعده می بایست تاریخ امروز یا قبل تر باشد");
}
if (command.Amount.Length > 15)
{
return op.Failed("مبلغ وارد شده معتبر نیست");
}
var month = Convert.ToInt32(command.SalaryDateTime.Substring(5, 2));
var year = Convert.ToInt32(command.SalaryDateTime.Substring(0, 4));
if (_customizeCheckoutRepository.Exists(x => x.WorkshopId == command.WorkshopId && command.EmployeeIds.Contains(x.EmployeeId) && x.YearInt == year && x.MonthInt == month))
{
return op.Failed("شما نمیتوانید برای پرسنلی در تاریخی که برای فیش حقوقی صادر شده است مساعده ای دهید");
}
foreach (var employeeId in command.EmployeeIds)
{
var id = employeeId;
if (employeeId == 0)
{
var employee = _employeeRepository.GetByNationalCode(command.NationalCode);
id = employee.id;
}
var entity = new SalaryAid(id, command.WorkshopId, command.Amount.MoneyToDouble(), startDate);
await _salaryAidRepository.CreateAsync(entity);
}
}
await _salaryAidRepository.SaveChangesAsync();
return op.Succcedded();
}
}

View File

@@ -726,6 +726,10 @@ public class EmployeeRepository : RepositoryBase<long, Employee>, IEmployeeRepos
}
}
public Employee GetByNationalCode(string nationalCode)
{
return _context.Employees.FirstOrDefault(x => x.NationalCode == nationalCode);
}
#endregion

View File

@@ -4,6 +4,7 @@ using System.Linq;
using _0_Framework.Application;
using AccountMangement.Infrastructure.EFCore;
using Company.Domain.ReportAgg;
using Company.Domain.WorkshopEmployerAgg;
using CompanyManagment.App.Contracts.LeftWork;
using CompanyManagment.App.Contracts.Report;
using Microsoft.EntityFrameworkCore;
@@ -22,6 +23,138 @@ public class ReportRepository : IReportRepository
_accountContext = accountContext;
}
public AllReport GetAllActiveWorkshopsNew(string year, string month)
{
//یافتن آغاز و پایان ماه جاری
//یافتن آغاز و پایان ماه بعد
#region FindMonthStartAndEnd
string nowFa = $"{(DateTime.Now.ToFarsi()).Substring(0, 8)}01";
if (!string.IsNullOrWhiteSpace(year) && !string.IsNullOrWhiteSpace(month))
nowFa = $"{year}/{month}/01";
var currentEndOfMonth = nowFa.FindeEndOfMonth();
//شروع ماه جاری
var currentMonthStart = nowFa.ToGeorgianDateTime();
// پایان کاه جاری
var currentMonthEnd = currentEndOfMonth.ToGeorgianDateTime();
int currentYear = Convert.ToInt32(nowFa.Substring(0, 4));
var currentMonth = Convert.ToInt32(nowFa.Substring(5, 2));
var nextMonthStartFa = new PersianDateTime(currentYear, currentMonth, 1).AddMonths(1);
//شروع ماه بعد
var nextMonthStart = ($"{nextMonthStartFa}").ToGeorgianDateTime();
//پایان ماه بعد
var nextMonthEnd = (($"{nextMonthStartFa}").FindeEndOfMonth()).ToGeorgianDateTime();
#endregion
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("========================== 1403/12/01 - 1403/12/30 ==========================");
//var allLeft = _context.LeftWorkList
// .Include(x => x.Workshop)
// .Count(x =>
// x.StartWorkDate < currentMonthEnd && x.LeftWorkDate > currentMonthStart);
//Console.ForegroundColor = ConsoleColor.Magenta;
//Console.WriteLine("All Persoennel Active : " + allLeft);
//var leftsDeActive = _context.LeftWorkList
// .Include(x => x.Workshop)
// .Where(x => x.Workshop.IsActiveString != "true")
// .Where(x =>
// x.StartWorkDate < currentMonthEnd && x.LeftWorkDate > currentMonthStart);
//Console.ForegroundColor = ConsoleColor.Red;
//Console.WriteLine("DeActive Workshop : " + leftsDeActive.Count());
//var ActiveWorkshop = _context.LeftWorkList
// .Include(x => x.Workshop)
// .Where(x => x.Workshop.IsActiveString == "true")
// .Where(x =>
// x.StartWorkDate < currentMonthEnd && x.LeftWorkDate > currentMonthStart);
//Console.ForegroundColor = ConsoleColor.Green;
//Console.WriteLine("Active Workshop : " + ActiveWorkshop.Count());
//var leftsActiveContractingParties = _context.LeftWorkList
// .Include(x => x.Workshop)
// .Where(x => x.Workshop.IsActiveString == "true")
// .Where(x =>
// x.StartWorkDate < currentMonthEnd && x.LeftWorkDate > currentMonthStart)
// .Join(_context.WorkshopEmployers,
// left => left.WorkshopId,
// workshopEmployer => workshopEmployer.WorkshopId,
// (left, workshopEmployer) => new { left, workshopEmployer})
// .Join(_context.PersonalContractingParties,
// result => result.workshopEmployer.Employer.id,
// contractingParties => contractingParties.Employers.FirstOrDefault()!.id,
// (result, contractingParties) => new
// {
// result.left,
// result.workshopEmployer,
// contractingParties
// }).Where(x=>x.contractingParties.IsBlock == "false" && x.contractingParties.IsActiveString == "true")
// ;
//Console.ForegroundColor = ConsoleColor.Green;
//Console.WriteLine("Active Workshop Join contractingParties : " + leftsActiveContractingParties.Count());
//var leftsAllContractingParties = _context.LeftWorkList
// .Include(x => x.Workshop)
// .Where(x => x.Workshop.IsActiveString == "true")
// .Where(x =>
// x.StartWorkDate < currentMonthEnd && x.LeftWorkDate > currentMonthStart)
// .Join(_context.WorkshopEmployers,
// left => left.WorkshopId,
// workshopEmployer => workshopEmployer.WorkshopId,
// (left, workshopEmployer) => new { left, workshopEmployer })
// .Join(_context.PersonalContractingParties,
// result => result.workshopEmployer.Employer.id,
// contractingParties => contractingParties.Employers.FirstOrDefault()!.id,
// (result, contractingParties) => new
// {
// result.left,
// result.workshopEmployer,
// contractingParties
// }).Where(x => x.contractingParties.IsBlock == "true" || x.contractingParties.IsActiveString == "false");
//var workshopListAc = leftsActiveContractingParties.Select(x => x.workshopEmployer.WorkshopId);
//var workshopListAllDeActive = leftsAllContractingParties.Select(x => x.workshopEmployer.WorkshopId);
//var employeeActive = leftsActiveContractingParties.Select(x => x.left.EmployeeId);
//var employeeDeActive = leftsAllContractingParties.Select(x => x.left.EmployeeId);
//Console.ForegroundColor = ConsoleColor.Green;
//Console.WriteLine("All Workshop Join contractingParties deActive : " + leftsAllContractingParties.Count());
//var workshops = _context.Workshops
// .Where(x => x.IsActiveString == "true")
// .Include(x => x.LeftWorks.Where(l => l.StartWorkDate < currentMonthEnd && l.LeftWorkDate > currentMonthStart))
// .ToList();
//Console.ForegroundColor = ConsoleColor.Green;
//Console.WriteLine("Active Workshop2 : " + workshops.Sum(x=>x.LeftWorks.Count));
var accountLeftWork = _accountContext.AccountLeftWorks
.Where(x => x.RoleId == 5)
.Where(x => x.StartWorkGr < currentMonthEnd && x.LeftWorkGr > currentMonthStart)
.Select(x => x.WorkshopId);
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("AccountLeftWork Count : " + accountLeftWork.Count());
int i = 1;
foreach (var item in accountLeftWork)
{
Console.WriteLine(i + " - " + item);
i++;
}
return new();
}
public AllReport GetAllActiveWorkshops(string year, string month)
{
var watch = System.Diagnostics.Stopwatch.StartNew();

View File

@@ -1,11 +1,68 @@
using System;
using AccountMangement.Infrastructure.EFCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using _0_Framework.Application;
using CompanyManagment.App.Contracts.Report;
using Microsoft.EntityFrameworkCore;
using PersianTools.Core;
namespace CompanyManagment.EFCore.Repository;
class ReportRepositoryNew
public class ReportRepositoryNew
{
private readonly CompanyContext _context;
private readonly AccountContext _accountContext;
public ReportRepositoryNew(CompanyContext context, AccountContext accountContext)
{
_context = context;
_accountContext = accountContext;
}
public AllReport GetAllActiveWorkshopsNew(string year, string month)
{
//یافتن آغاز و پایان ماه جاری
//یافتن آغاز و پایان ماه بعد
#region FindMonthStartAndEnd
string nowFa = $"{(DateTime.Now.ToFarsi()).Substring(0, 8)}01";
if (!string.IsNullOrWhiteSpace(year) && !string.IsNullOrWhiteSpace(month))
nowFa = $"{year}/{month}/01";
var currentEndOfMonth = nowFa.FindeEndOfMonth();
//شروع ماه جاری
var currentMonthStart = nowFa.ToGeorgianDateTime();
// پایان کاه جاری
var currentMonthEnd = currentEndOfMonth.ToGeorgianDateTime();
int currentYear = Convert.ToInt32(nowFa.Substring(0, 4));
var currentMonth = Convert.ToInt32(nowFa.Substring(5, 2));
var nextMonthStartFa = new PersianDateTime(currentYear, currentMonth, 1).AddMonths(1);
//شروع ماه بعد
var nextMonthStart = ($"{nextMonthStartFa}").ToGeorgianDateTime();
//پایان ماه بعد
var nextMonthEnd = (($"{nextMonthStartFa}").FindeEndOfMonth()).ToGeorgianDateTime();
#endregion
var lefts = _context.LeftWorkList
.Include(x=>x.Workshop)
.Where(x=>x.Workshop.IsActiveString == "true")
.Count(x =>
x.StartWorkDate < currentMonthEnd && x.LeftWorkDate > currentMonthStart);
return new();
}
}

View File

@@ -78,6 +78,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Query", "Query\Query.csproj
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Query.Bootstrapper", "Query.Bootstrapper\Query.Bootstrapper.csproj", "{02892882-2A02-484B-BAF9-7E63F6BDCFA0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CompanyManagement.Infrastructure.Excel", "CompanyManagement.Infrastructure.Excel\CompanyManagement.Infrastructure.Excel.csproj", "{BF98173C-42AF-4897-A7CB-4CACEB2B52A2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -172,6 +174,10 @@ Global
{02892882-2A02-484B-BAF9-7E63F6BDCFA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{02892882-2A02-484B-BAF9-7E63F6BDCFA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{02892882-2A02-484B-BAF9-7E63F6BDCFA0}.Release|Any CPU.Build.0 = Release|Any CPU
{BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BF98173C-42AF-4897-A7CB-4CACEB2B52A2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -205,6 +211,7 @@ Global
{0E6A32F1-1BCB-45A1-BB1A-A5B8AFA8F551} = {09517B4E-C699-4D57-8590-0B773228820A}
{339E05B6-E99F-4403-AFDF-CD0540E96C8D} = {708E8D7E-F190-47C5-B78E-F43131FB7D6D}
{02892882-2A02-484B-BAF9-7E63F6BDCFA0} = {708E8D7E-F190-47C5-B78E-F43131FB7D6D}
{BF98173C-42AF-4897-A7CB-4CACEB2B52A2} = {86921E1B-2AFA-4B8A-9403-EE16D58B5B26}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E6CFB3A7-A7C8-4E82-8F06-F750408F0BA9}

View File

@@ -194,6 +194,7 @@ using CompanyManagment.App.Contracts.EmployeeBankInformation;
using Company.Domain.EmployeeDocumentItemAgg;
using Company.Domain.EmployeeDocumentsAdminSelectionAgg;
using Company.Domain.EmployeeDocumentsAgg;
using CompanyManagement.Infrastructure.Excel.SalaryAid;
using CompanyManagment.App.Contracts.EmployeeDocuments;
using CompanyManagment.App.Contracts.EmployeeDocumentsAdminSelection;
@@ -406,6 +407,8 @@ public class PersonalBootstrapper
services.AddTransient<IAndroidApkVersionRepository, AndroidApkVersionRepository>();
services.AddTransient<IAndroidApkVersionApplication, AndroidApkVersionApplication>();
services.AddTransient<SalaryAidImportExcel>();
#endregion
#region Pooya

View File

@@ -9,6 +9,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CompanyManagement.Infrastructure.Excel\CompanyManagement.Infrastructure.Excel.csproj" />
<ProjectReference Include="..\CompanyManagment.App.Contracts\CompanyManagment.App.Contracts.csproj" />
<ProjectReference Include="..\CompanyManagment.Application\CompanyManagment.Application.csproj" />
<ProjectReference Include="..\CompanyManagment.EFCore\CompanyManagment.EFCore.csproj" />

View File

@@ -118,7 +118,7 @@
<div class="card p-2">
<div class="row align-items-center">
<div class="col-6 col-md-4">
<div class="col-12 col-md-6 col-lg-4 d-flex gap-2">
<button class="btn-create mb-1" onclick="openCreateSalaryAidModal()" Permission="@SubAccountPermissionHelper.CreateSalaryAidPermissionCode">
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="11" cy="11" r="8.25" stroke-width="1.5" stroke="white" />
@@ -127,17 +127,25 @@
</svg>
ایجاد مساعده
</button>
<button class="btn-create mb-1" onclick="openImportExcelSalaryAidModal()" Permission="@SubAccountPermissionHelper.CreateSalaryAidPermissionCode">
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="11" cy="11" r="8.25" stroke-width="1.5" stroke="white" />
<path d="M11 13.75L11 8.25" stroke-width="1.5" stroke="white" stroke-linecap="round" />
<path d="M13.75 11L8.25 11" stroke-width="1.5" stroke="white" stroke-linecap="round" />
</svg>
بارگذاری فایل اکسل
</button>
@* <div class="select-all d-flex d-md-none align-items-center">
<input type="checkbox" class="form-check-input checkAll" name="" id="checkAll1">
<label for="checkAll1">انتخاب همه</label>
</div> *@
</div>
<div class="d-none d-md-block col-4 text-center">
<div class="d-none d-md-block col-6 col-md-4 text-center">
<span>
لیست مساعده
</span>
</div>
<div class="col-6 col-md-4 text-end">
<div class="col-12 col-md-6 col-lg-4 text-end">
@* <div class="d-flex align-items-center justify-content-end my-1">
<button class="btn-print-all" type="button" onclick="printAll()">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
@@ -172,10 +180,10 @@
</div> *@
<label for="checkAll2">ردیف</label>
</div>
<div class="Rtable-cell column-heading width6">تاریخ</div>
<div class="Rtable-cell column-heading width2">نام پرسنل</div>
<div class="Rtable-cell column-heading text-center width3">شماره پرسنلی</div>
<div class="Rtable-cell column-heading width4">مبلغ</div>
<div class="Rtable-cell column-heading width6">تاریخ</div>
<div class="Rtable-cell column-heading text-end pe-2 width8">عملیات</div>
</div>
@@ -249,8 +257,7 @@
</div>
<!-- End Modal From Bottom For Advance Search -->
<div id="MainModal" class="modal fade salaryaidListModal" tabindex="-1" data-bs-backdrop="static" aria-labelledby="myModalLabel" aria-hidden="true" style="display: none;">
<div id="MainModal" class="modal fade salaryaidListModal" data-backdrop="static" tabindex="-1" role="dialog" aria-labelledby="staticBackdropLabel" aria-hidden="true" style="display: none;">
<div class="modal-dialog salaryaidListModal-width modal-dialog-centered modal-dialog-scrollable">
<div class="modal-content" id="ModalContent">
</div>
@@ -272,5 +279,5 @@
var editPermission = @(AuthHelper.GetPermissions().Contains(SubAccountPermissionHelper.EditSalaryAidPermissionCode) ? "true" : "false");
var deletePermission = @(AuthHelper.GetPermissions().Contains(SubAccountPermissionHelper.DeleteSalaryAidPermissionCode) ? "true" : "false");
</script>
<script src="~/assetsclient/pages/salaryaid/js/index.js?ver=@clientVersion"></script>
<script src="~/assetsclient/pages/salaryaid/js/index.js?ver=clientVersion"></script>
}

View File

@@ -7,11 +7,9 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Security.Claims;
using _0_Framework.Infrastructure;
using AccountManagement.Application.Contracts.SubAccount;
using CompanyManagement.Infrastructure.Excel.SalaryAid;
using CompanyManagment.App.Contracts.SalaryAid;
using CompanyManagment.App.Contracts.Employee;
using CompanyManagment.App.Contracts.Reward;
using Microsoft.Extensions.Configuration.UserSecrets;
namespace ServiceHost.Areas.Client.Pages.Company.SalaryAid
{
@@ -20,39 +18,33 @@ namespace ServiceHost.Areas.Client.Pages.Company.SalaryAid
public class IndexModel : PageModel
{
private readonly IPasswordHasher _passwordHasher;
private readonly IWorkshopApplication _workshopApplication;
private readonly ISalaryAidApplication _salaryAidApplication;
private readonly IEmployeeApplication _employeeApplication;
private readonly IAuthHelper _authHelper;
private readonly ISubAccountApplication _subAccountApplication;
private readonly SalaryAidImportExcel _salaryAidImportExcel;
private readonly long _workshopId;
public string WorkshopFullName;
public int PageIndex = 0;
private readonly long _workshopId;
public IndexModel(IPasswordHasher passwordHasher, IWorkshopApplication workshopApplication, ISalaryAidApplication salaryAidApplication, IEmployeeApplication employeeApplication, IAuthHelper authHelper, ISubAccountApplication subAccountApplication)
public IndexModel(IPasswordHasher passwordHasher, ISalaryAidApplication salaryAidApplication,
IEmployeeApplication employeeApplication, IHttpContextAccessor contextAccessor, IAuthHelper authHelper, SalaryAidImportExcel salaryAidImportExcel)
{
_passwordHasher = passwordHasher;
_workshopApplication = workshopApplication;
_salaryAidApplication = salaryAidApplication;
_employeeApplication = employeeApplication;
_authHelper = authHelper;
_subAccountApplication = subAccountApplication;
_salaryAidImportExcel = salaryAidImportExcel;
var workshopHash = _authHelper.GetWorkshopSlug();
_workshopId = _passwordHasher.SlugDecrypt(workshopHash);
if (_workshopId < 1)
throw new InvalidDataException("اختلال در کارگاه");
}
public IActionResult OnGet()
{
var workshopHash = User.FindFirstValue("WorkshopSlug");
var workshopId = _passwordHasher.SlugDecrypt(workshopHash);
if (workshopId <= 0)
return BadRequest();
WorkshopFullName = _authHelper.GetWorkshopName();
return Page();
@@ -60,27 +52,20 @@ namespace ServiceHost.Areas.Client.Pages.Company.SalaryAid
public IActionResult OnGetLoadDataAjax(SalaryAidSearchViewModel searchViewModel)
{
var subAccId = _authHelper.CurrentSubAccountId();
if (subAccId > 0)
searchViewModel.WorkshopId = _workshopId;
var result = _salaryAidApplication.GetSearchList(searchViewModel);
return new JsonResult(new
{
var subAccountViewModel = _subAccountApplication.GetDetails(subAccId);
if (subAccountViewModel.SubAccountRoleId == 2)
{
return new JsonResult(new
{
success = true,
data = new List<SalaryAidViewModel>(),
pageIndex = 0,
});
}
}
var workshopHash = User.FindFirstValue("WorkshopSlug");
var workshopId = _passwordHasher.SlugDecrypt(workshopHash);
success = true,
data = result,
pageIndex = result.Count()
});
}
if (workshopId <= 0)
return BadRequest();
searchViewModel.WorkshopId = workshopId;
public IActionResult OnGetLoadDataByEmployeeAjax(SalaryAidSearchViewModel searchViewModel)
{
searchViewModel.WorkshopId = _workshopId;
var result = _salaryAidApplication.GetSearchList(searchViewModel);
return new JsonResult(new
@@ -93,16 +78,7 @@ namespace ServiceHost.Areas.Client.Pages.Company.SalaryAid
public IActionResult OnGetEmployeeList()
{
var workshopHash = User.FindFirstValue("WorkshopSlug");
var workshopId = _passwordHasher.SlugDecrypt(workshopHash);
if (workshopId <= 0)
return new JsonResult(new
{
success = false,
message = "کارگاه ای یافت نشد",
});
var employees = _employeeApplication.GetWorkingEmployeesByWorkshopId(workshopId);
var employees = _employeeApplication.GetWorkingEmployeesByWorkshopId(_workshopId);
return new JsonResult(new
{
@@ -113,33 +89,13 @@ namespace ServiceHost.Areas.Client.Pages.Company.SalaryAid
public IActionResult OnGetCreate()
{
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 = new CreateSalaryAidViewModel();
return Partial("ModalCreateNewSalaryAid", command);
}
public IActionResult OnPostCreate(CreateSalaryAidViewModel command)
{
var workshopHash = User.FindFirstValue("WorkshopSlug");
var workshopId = _passwordHasher.SlugDecrypt(workshopHash);
if (workshopId <= 0)
return new JsonResult(new
{
IsSuccedded = false,
message = "کارگاه ای یافت نشد",
});
command.WorkshopId = workshopId;
command.WorkshopId = _workshopId;
var result = _salaryAidApplication.Create(command);
return new JsonResult(new
@@ -151,34 +107,13 @@ namespace ServiceHost.Areas.Client.Pages.Company.SalaryAid
public IActionResult OnGetEdit(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 = _salaryAidApplication.GetDetails(id);
return Partial("ModalEditSalaryAid", command);
}
public IActionResult OnPostEdit(EditSalaryAidViewModel command)
{
var workshopHash = User.FindFirstValue("WorkshopSlug");
var workshopId = _passwordHasher.SlugDecrypt(workshopHash);
if (workshopId <= 0)
return new JsonResult(new
{
IsSuccedded = false,
message = "کارگاه ای یافت نشد",
});
command.WorkshopId = workshopId;
command.WorkshopId = _workshopId;
var result = _salaryAidApplication.Edit(command);
return new JsonResult(new
@@ -188,7 +123,6 @@ namespace ServiceHost.Areas.Client.Pages.Company.SalaryAid
});
}
public IActionResult OnPostRemove(long id)
{
var result = _salaryAidApplication.Remove(id);
@@ -198,7 +132,49 @@ namespace ServiceHost.Areas.Client.Pages.Company.SalaryAid
message = result.Message,
});
}
public IActionResult OnGetImportExcel()
{
return Partial("ModalImportExcel");
}
public IActionResult OnGetDownloadExcelTemplate()
{
var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "Excel", "Templates", "SalaryAid", "SA-Template.xlsx");
var bytes = System.IO.File.ReadAllBytes(filePath);
return File(bytes,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"قالب مساعده.xlsx");
}
public IActionResult OnPostValidateExcel(IFormFile excel)
{
var validation = _salaryAidImportExcel.ReadAndValidateExcel(excel, _workshopId);
return new JsonResult(new
{
IsSuccess = !validation.Errors.Any(),
data = validation
});
}
public async Task<IActionResult> OnPostCreateFromExcelData(List<SalaryAidImportData> data)
{
var commands = data.Select(x => new CreateSalaryAidViewModel()
{
WorkshopId = x.WorkshopId,
Amount = x.Amount.ToMoney(),
EmployeeIds = [x.EmployeeId],
SalaryDateTime = x.SalaryAidDateTime,
NationalCode = x.NationalCode
}).ToList();
OperationResult result = await _salaryAidApplication.CreateRange(commands);
return new JsonResult(new
{
result.IsSuccedded,
result.Message
});
}
}
}

View File

@@ -0,0 +1,105 @@
@* @model CompanyManagment.App.Contracts.SalaryAid.CreateSalaryAidViewModel *@
@{
string clientVersion = _0_Framework.Application.Version.StyleVersion;
<link href="~/AssetsClient/css/select2.css?ver=@clientVersion" rel="stylesheet" />
<link href="~/assetsclient/pages/SalaryAid/css/ModalImportExcel.css?ver=@clientVersion" rel="stylesheet" />
}
<form role="form" method="post" name="create-form" id="create-form" autocomplete="off">
<div class="modal-content">
<div class="modal-header pb-0 d-flex align-items-center justify-content-center text-center">
<button type="button" class="btn-close position-absolute text-start" data-bs-dismiss="modal" aria-label="Close"></button>
<div>
<p class="m-0 pdHeaderTitle1">بارگذاری فایل اکسل</p>
</div>
</div>
<div class="modal-body">
<div class="container-fluid p-0">
<div class="row">
<div class="col-12 my-2">
<div class="boxInfo d-flex align-items-center justify-content-start gap-1">
<svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="16" r="12" fill="#2FC1C1"/>
<path d="M17.3334 9.33333C17.3334 10.0697 16.7364 10.6667 16 10.6667C15.2636 10.6667 14.6667 10.0697 14.6667 9.33333C14.6667 8.59695 15.2636 8 16 8C16.7364 8 17.3334 8.59695 17.3334 9.33333Z" fill="white"/>
<path d="M16 21.9974V15.3307C16 14.2377 16 13.6911 15.7287 13.3037C15.6283 13.1604 15.5037 13.0357 15.3603 12.9353C14.9729 12.6641 14.4264 12.6641 13.3333 12.6641V12.6641M16 21.9974H18M16 21.9974H14" stroke="white"/>
</svg>
<p class="infoTxt m-0">
برای بارگذاری فایل excel، ابتدا قالب موردنظر را دانلود، و مشخصات پرسنلی را در آن وارد کنید. سپس فایل تکمیل شده را بارگذاری کنید تا خروجی نمایش داده شود. در نهایت بر روی دکمه ثبت نهایی کلیک کنید.
</p>
</div>
</div>
<div class="col-6 col-md-6 my-2">
<div class="btnExportTitle d-flex align-items-center justify-content-start gap-1" id="downloadExcelTemplate" onclick="downloadExcelTemplate('@Url.Page("/Company/SalaryAid/Index", "DownloadExcelTemplate")')">
<img src="~/assetsclient/images/download.png"/>
<div class="titleBtn">
دانلود قالب excel
</div>
</div>
</div>
<div class="col-6 col-md-6 my-2">
<button type="button" class="btnExportTitle d-flex align-items-center justify-content-start gap-1 w-100 position-relative overflow-hidden" id="uploadExcelFile">
<input type="file" class="d-none" src="" id="uploadExcelFileInput"/>
<img src="~/assetsclient/images/clipboard.png"/>
<div class="titleBtn">
بارگذاری و نمایش خروجی اکسل
</div>
<div class="spinner-loading-progress loading" style="display: none">
</div>
</button>
</div>
<div class="col-12 my-2">
<div class="exportOutputContainer d-flex gap-1 position-relative">
<div id="responseDataTheStructureOfExcel" class="w-100">
</div>
<div id="errorsTheStructureOfExcel" class="errorMessageOfExcel"></div>
<div class="spinner-loading loading" style="display: none">
<span class="spinner-border spinner-border-sm loading text-white" role="status" aria-hidden="true"></span>
</div>
@* <button type="button" class="btnExportOutput" id="btnExportOutput">
خروجی اکسل
</button> *@
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer d-block">
<div class="row">
<div class="col-6 text-end">
<button type="button" class="btn-cancel2 justify-content-center" data-bs-dismiss="modal" aria-label="Close">انصراف</button>
</div>
<div class="col-6 text-start">
<button type="button" class="btnCreateNew position-relative disable" id="createData">
<span class="text-nowrap">ثبت نهایی</span>
<div class="spinner-loading loading" style="display: none;">
<span class="spinner-border spinner-border-sm loading text-white" role="status" aria-hidden="true"></span>
</div>
</button>
</div>
</div>
</div>
</div>
</form>
<script src="~/assetsclient/js/site.js?ver=@clientVersion"></script>
<script src="~/assetsclient/libs/jalaali-js/jalaali.js"></script>
<script src="~/admintheme/js/jquery.mask_1.14.16.min.js"></script>
<script src="~/assetsclient/libs/cleave/cleave.min.js"></script>
<script src="~/assetsclient/libs/wordifyfa/wordifyfa.min.js"></script>
<script>
var antiForgeryToken = $(`@Html.AntiForgeryToken()`).val();
var uploadAndValidate = `@Url.Page("./Index", "ValidateExcel")`;
var sendExcelDataAjax = `@Url.Page("./Index", "CreateFromExcelData")`;
</script>
<script src="~/assetsclient/pages/SalaryAid/js/ModalImportExcel.js?ver=@clientVersion"></script>

View File

@@ -11,10 +11,12 @@ using _0_Framework.Application.UID;
using AccountManagement.Application.Contracts.CameraAccount;
using CompanyManagment.EFCore;
using Company.Domain.EmployeeAgg;
using Company.Domain.ReportAgg;
using Company.Domain.RollCallAgg;
using Company.Domain.RollCallAgg.DomainService;
using CompanyManagment.App.Contracts.AndroidApkVersion;
using Microsoft.EntityFrameworkCore;
using IUidService = _0_Framework.Application.UID.IUidService;
namespace ServiceHost.Pages
@@ -45,11 +47,12 @@ namespace ServiceHost.Pages
private readonly IWebHostEnvironment _webHostEnvironment;
private readonly IAndroidApkVersionApplication _androidApkVersionApplication;
private readonly IUidService _uidService;
private readonly IReportRepository _reportRepository;
public IndexModel(ILogger<IndexModel> logger, IAccountApplication accountApplication, IGoogleRecaptcha googleRecaptcha, ISmsService smsService, IWorker worker,
IAuthHelper authHelper, ICameraAccountApplication cameraAccountApplication, IWebHostEnvironment webHostEnvironment,
IAndroidApkVersionApplication androidApkVersionApplication, IUidService uidService)
IAndroidApkVersionApplication androidApkVersionApplication, IUidService uidService, IReportRepository reportRepository)
{
_logger = logger;
_accountApplication = accountApplication;
@@ -61,14 +64,14 @@ namespace ServiceHost.Pages
_webHostEnvironment = webHostEnvironment;
_androidApkVersionApplication = androidApkVersionApplication;
_uidService = uidService;
_reportRepository = reportRepository;
}
public IActionResult OnGet()
{
//_uidService.GetPersonalInfo("2669318622","1363/02/25").GetAwaiter().GetResult();
//_uidService.IsMachPhoneWithNationalCode("2669318622","09114221321").GetAwaiter().GetResult();
// _reportRepository.GetAllActiveWorkshopsNew("1403", "12");
HasApkToDownload = _androidApkVersionApplication.HasAndroidApkToDownload();
if (User.Identity is { IsAuthenticated: true })

View File

@@ -61,6 +61,7 @@
<ItemGroup>
<ProjectReference Include="..\AccountManagement.Configuration\AccountManagement.Configuration.csproj" />
<ProjectReference Include="..\backService\backService.csproj" />
<ProjectReference Include="..\CompanyManagement.Infrastructure.Excel\CompanyManagement.Infrastructure.Excel.csproj" />
<ProjectReference Include="..\PersonalContractingParty.Config\PersonalContractingParty.Config.csproj" />
<ProjectReference Include="..\Query.Bootstrapper\Query.Bootstrapper.csproj" />
<ProjectReference Include="..\Query\Query.csproj" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -277,4 +277,11 @@
button.btn-print, button.btn-edit span, button.btn-delete span {
display: unset;
}
.btn-create {
width: 100%
}
}

View File

@@ -1,4 +1,18 @@
.errored {
.scroll-container-amount {
font-size: 12px;
color: #4f4f4f;
white-space: nowrap;
width: 100%;
overflow: hidden;
cursor: grab;
user-select: none;
}
.scroll-container-amount:active {
cursor: grabbing;
}
.errored {
animation: shake 300ms;
color: #eb3434 !important;
background-color: #fef2f2 !important;

View File

@@ -0,0 +1,450 @@
.salaryaidListModal-width {
max-width: 900px;
}
.scroll-container-amount {
font-size: 12px;
color: #4f4f4f;
white-space: nowrap;
width: 100%;
overflow: hidden;
cursor: grab;
user-select: none;
}
.scroll-container-amount:active {
cursor: grabbing;
}
.errored {
animation: shake 300ms;
color: #eb3434 !important;
background-color: #fef2f2 !important;
border: 1px solid #eb3434 !important;
}
.boxInfo {
background: #FFFFFF;
border: 1px solid #ECECEC;
box-shadow: 0 4px 7px rgba(0, 0, 0, 0.1);
border-radius: 7px;
padding: 5px;
}
.boxInfo svg {
width: 40px;
height: 40px
}
.infoTxt {
text-align: justify;
color: #2D2D2D;
font-size: 13px;
font-weight: 500;
}
.btnExportTitle {
background: #FFFFFF;
border: 1px solid #DADADA;
border-radius: 7px;
padding: 12px;
cursor: pointer;
transition: all ease-in-out .3s;
}
.btnExportTitle:hover {
border: 1px solid #0B9999;
}
.btnExportTitle img {
width: 50px;
}
.btnExportTitle .titleBtn {
color: #575757;
font-size: 15px;
font-weight: 500;
}
.exportOutputContainer {
background: #F0F0F0;
border: 1px solid #DADADA;
color: #575757;
font-size: 15px;
font-weight: 500;
border-radius: 7px;
height: 300px;
overflow-y: scroll;
}
.btnExportOutput {
color: #ffffff;
font-size: 13px;
font-weight: 500;
background-color: #84CC16;
border-radius: 7px;
padding: 6px 18px;
}
.errorMessageOfExcel ul li {
color: red;
}
.btnExportOutput:hover {
background-color: #5f9213;
}
.errorMessageOfExcel {
position: absolute;
top: 12px;
right: 12px;
}
.btnCreateNew {
font-size: 14px;
font-weight: 500;
background-color: #84CC16;
color: #FFFFFF;
border-radius: 7px;
padding: 10px 0;
}
.btnCreateNew:hover {
background-color: #5f9213;
}
.btnCreateNew,
.btn-cancel2 {
width: 180px !important;
border-radius: 7px;
}
.error-header {
background: none !important;
background-color: #F87171 !important;
font-weight: bold !important;
color: white !important;
}
.error-row {
background-color: #FEE2E2 !important;
font-weight: bold !important;
color: #000000 !important;
font-size: 12px;
border: 1px solid #EAEAEA !important;
}
.lineHead {
background-color: #EE0000 !important;
height: 1px;
}
.lineHeadValid {
background-color: #009898 !important;
height: 1px;
}
.error-column {
background-color: #FE9C9C;
height: 100%;
align-items: center;
justify-content: center;
}
.error-row .Rtable-cell .prevent-select span {
border-radius: 5px;
background: #FCA5A5 !important;
width: 32px;
height: 32px;
display: inline-block;
padding: 6px;
}
.excelTable .widthNone1 {
width: 10% !important;
}
.excelTable .widthNone2 {
width: 85% !important;
}
.excelTable .width1 {
width: 5% !important;
}
.excelTable .width2 {
width: 10% !important;
}
.excelTable .width3 {
width: 25% !important;
}
.excelTable .width4 {
width: 20% !important;
}
.excelTable .width5 {
width: 20% !important;
}
.excelTable .width6 {
width: 20% !important;
}
.excelTable .width7 {
width: 10% !important;
}
.excelValidTable .width1 {
width: 5% !important;
}
.excelValidTable .width2 {
width: 30% !important;
}
.excelValidTable .width3 {
width: 15% !important;
}
.excelValidTable .width4 {
width: 15% !important;
}
.excelValidTable .width5 {
width: 15% !important;
}
.excelValidTable .width6 {
width: 20% !important;
}
.excelValidTable .width7 {
width: 10% !important;
}
.radio-group {
display: flex;
gap: 10px;
}
.radio-input {
display: none;
}
.btnRadioAll,
.btnRadio {
display: flex;
align-items: center;
justify-content: space-around;
gap: 1px;
padding: 5px;
font-size: 11px;
font-weight: 800;
width: 78px;
border-radius: 7px;
color: #ffffff;
cursor: pointer;
transition: background-color 0.3s ease-in-out, border 0.2s;
}
.btnAcceptAll {
background-color: #84CC16;
border: 1px solid #ffffff;
}
.btnAccept {
background-color: #84CC16;
}
.btnAcceptAll:hover,
.btnAccept:hover {
background-color: #67971d;
}
.btnRejectAll {
background-color: #FF9595;
border: 1px solid #ffffff;
}
.btnReject {
background-color: #FF9595;
}
.btnRejectAll:hover,
.btnReject:hover {
background-color: #dd8080;
}
.radio-input:checked + .btnAcceptAll,
.radio-input:checked + .btnAccept {
background-color: #8D8D8D;
}
.radio-input:checked + .btnRejectAll,
.radio-input:checked + .btnReject {
background-color: #8D8D8D;
}
.rowDuplicated {
background-color: #F3E38B !important;
}
.rowRejected {
background-color: #B1C3C3 !important;
}
.tooltipfull-container {
cursor: pointer;
position: relative;
}
.sticky {
position: sticky;
top: 0;
z-index: 20;
}
.tooltipfull {
opacity: 0;
z-index: 99;
color: #fff !important;
display: grid;
font-size: 12px;
padding: 5px 10px;
border-radius: 8px;
background: #23a8a8;
border: 1px solid #23a8a8;
-webkit-transition: all .2s ease-in-out;
-moz-transition: all .2s ease-in-out;
-o-transition: all .2s ease-in-out;
transition: all .2s ease-in-out;
-webkit-transform: scale(0);
-moz-transform: scale(0);
-o-transform: scale(0);
-ms-transform: scale(0);
transform: scale(0);
position: absolute;
right: -22px;
bottom: 39px;
/* white-space: nowrap; */
width: 180px;
text-align: justify;
}
.tooltipfull-container:hover .tooltipfull, a:hover .tooltipfull {
opacity: 1;
-webkit-transform: scale(1);
-moz-transform: scale(1);
-o-transform: scale(1);
-ms-transform: scale(1);
transform: scale(1);
}
.tooltipfull:before, .tooltipfull:after {
content: '';
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid #23a8a8;
position: absolute;
bottom: -10px;
right: 20px;
}
.ellipsed {
display: block;
width: 100%;
text-overflow: ellipsis;
overflow-x: clip;
white-space: nowrap;
text-align: start
}
@media (max-width:1366px) {
.infoTxt {
font-size: 12px;
}
.btnExportTitle .titleBtn {
font-size: 13px;
}
}
@media (max-width:768px) {
.Rtable--collapse.ErrorCustom .Rtable-row .Rtable-cell .Rtable-cell--content {
text-align: start !important;
}
.Rtable--collapse.rowCustom .Rtable-row {
padding: 0.5em;
margin: 4px 0px 0;
}
.Rtable .Rtable-row .Rtable-cell.column-heading.rowHeaderCustom {
margin: 0.6em 0 !important;
}
.excelTable .width1 {
width: 15% !important;
}
.excelTable .widthNone1 {
width: 20% !important;
}
.excelTable .widthNone2 {
width: 57% !important;
}
.excelTable .width2 {
width: 20% !important;
}
.excelTable .width3 {
width: 55% !important;
}
.excelValidTable .width2 {
width: 35% !important;
}
.excelValidTable .width6 {
width: 40% !important;
}
.salaryaidListModal-width {
max-width: max-content;
}
.form-control {
margin: 0 !important;
}
.boxInfo svg {
width: 60px;
height: 60px
}
.btnExportTitle img {
width: 43px;
}
.infoTxt {
font-size: 11px;
}
.btnExportTitle .titleBtn {
font-size: 11px;
}
}
@media (max-width:576px) {
.btnRadio {
width: 66px;
}
.btnCreateNew, .btn-cancel2 {
width: 100% !important;
padding: 10px 40px;
display: flex;
justify-content: center;
}
}

View File

@@ -240,6 +240,9 @@ function loadSalaryAidList() {
</span>
</label>
</div>
<div class="Rtable-cell d-md-block d-none width5">
<div class="Rtable-cell--content ">${item.salaryAidDateTimeFa}</div>
</div>
<div class="Rtable-cell justify-content-start width2">
<div class="Rtable-cell--content text-start">${item.employeeFullName}</div>
</div>
@@ -249,9 +252,6 @@ function loadSalaryAidList() {
<div class="Rtable-cell d-md-block d-none width4">
<div class="Rtable-cell--content ">${item.amount}</div>
</div>
<div class="Rtable-cell d-md-block d-none width5">
<div class="Rtable-cell--content ">${item.salaryAidDateTimeFa}</div>
</div>
<div class="Rtable-cell width8">
<div class="Rtable-cell--content align-items-center justify-content-end d-flex text-end">
<button type="button" class="btn-print d-md-none d-none" onclick="printSalaryAid(item.Id)">
@@ -423,6 +423,11 @@ function openCreateSalaryAidModal() {
window.location.href = goTo;
}
function openImportExcelSalaryAidModal() {
var goTo = `#showmodal=/Client/Company/SalaryAid/Index?handler=ImportExcel`;
window.location.href = goTo;
}
$(document).on('click', '.btn-edit', function () {
var id = $(this).data('edit-id');
var goTo = `#showmodal=/Client/Company/SalaryAid/Index?id=${id}&handler=Edit`;

View File

@@ -1,5 +1,36 @@
var urlPathname = location.pathname;
document.querySelectorAll('.scroll-container-amount').forEach(container => {
let isDown = false;
let startX;
let scrollLeft;
container.addEventListener('mousedown', (e) => {
isDown = true;
startX = e.pageX - container.offsetLeft;
scrollLeft = container.scrollLeft;
container.style.cursor = "grabbing";
});
container.addEventListener('mouseleave', () => {
isDown = false;
container.style.cursor = "grab";
});
container.addEventListener('mouseup', () => {
isDown = false;
container.style.cursor = "grab";
});
container.addEventListener('mousemove', (e) => {
if (!isDown) return;
e.preventDefault();
const x = e.pageX - container.offsetLeft;
const walk = (x - startX) * 2;
container.scrollLeft = scrollLeft - walk;
});
});
$(document).ready(function () {
$('.loading').hide();

View File

@@ -1,4 +1,35 @@
$(document).ready(function () {
document.querySelectorAll('.scroll-container-amount').forEach(container => {
let isDown = false;
let startX;
let scrollLeft;
container.addEventListener('mousedown', (e) => {
isDown = true;
startX = e.pageX - container.offsetLeft;
scrollLeft = container.scrollLeft;
container.style.cursor = "grabbing";
});
container.addEventListener('mouseleave', () => {
isDown = false;
container.style.cursor = "grab";
});
container.addEventListener('mouseup', () => {
isDown = false;
container.style.cursor = "grab";
});
container.addEventListener('mousemove', (e) => {
if (!isDown) return;
e.preventDefault();
const x = e.pageX - container.offsetLeft;
const walk = (x - startX) * 2;
container.scrollLeft = scrollLeft - walk;
});
});
$(document).ready(function () {
$('.form-control-number').on('keydown', function (e) {
const allowedKeys = [
'Backspace', 'Tab', 'Escape', 'Enter', 'ArrowLeft', 'ArrowRight',

View File

@@ -0,0 +1,804 @@
var urlPathname = location.pathname;
var rawDataArray = [];
var validDataArray = [];
$(document).on('click', ".openActionModal", function () {
if (window.matchMedia('(max-width: 767px)').matches) {
$(this).next().find(".operations-btns").slideToggle(500);
$(".operations-btns").not($(this).next().find(".operations-btns")).slideUp(500);
}
});
$(document).ready(function () {
document.getElementById('uploadExcelFile').onclick = function () {
$('#uploadExcelFileInput').val('');
document.getElementById('uploadExcelFileInput').click();
};
$('#uploadExcelFileInput').change(function (e) {
e.preventDefault();
var fileInputFile = this.files[0];
if (!fileInputFile) return;
var fileName = fileInputFile.name;
var fileExtension = fileName.split('.').pop().toLowerCase();
if (fileExtension !== 'xlsx') {
showAlertMessage('.alert-msg', 'لطفا فقط فایل با پسوند .xlsx را انتخاب کنید', 3500);
$('#uploadExcelFileInput').val('');
return;
}
if (fileInputFile.size > 20000000) {
showAlertMessage('.alert-msg', 'لطفا فایل حجم کمتر از 20 مگابایت را انتخاب کنید', 3500);
$(`#uploadExcelFileInput`).val('');
return;
}
uploadFile(fileInputFile);
});
});
function uploadFile(file) {
const formData = new FormData();
formData.append('excel', file);
$('#createData').prop('disabled', true).addClass('disable');
var xhr = new XMLHttpRequest();
xhr.open('POST', uploadAndValidate, true);
xhr.setRequestHeader('RequestVerificationToken', antiForgeryToken);
const loading = $("#uploadExcelFile").find('.spinner-loading-progress').css('color', `#ffffff`).show();
let uploadStartTime = Date.now();
xhr.upload.addEventListener('progress', function (e) {
if (e.lengthComputable) {
var percentComplete = Math.round((e.loaded / e.total) * 100);
loading.text(percentComplete + '%').css('width', percentComplete + '%');
}
});
xhr.onload = function () {
let elapsedTime = Date.now() - uploadStartTime;
let remainingTime = Math.max(1000 - elapsedTime, 0);
setTimeout(() => {
if (xhr.status === 200) {
const response = JSON.parse(xhr.responseText);
const loadingResult = $(".exportOutputContainer").find('.spinner-loading').show();
setTimeout(() => {
loadingResult.hide();
if (response.isSuccess) {
loading.css('width', '0').hide();
let responseDataContainer = $('#responseDataTheStructureOfExcel');
responseDataContainer.empty();
let errorsContainer = $('#errorsTheStructureOfExcel');
errorsContainer.empty();
responseDataContainer.html(loadFinalExcelDataAjax(response.data));
checkInputsEnabled();
} else {
validDataArray = [];
$('#createData').prop('disabled', true).addClass('disable');
loading.css('width', '0').hide();
let responseDataContainer = $('#responseDataTheStructureOfExcel');
responseDataContainer.empty();
let errorsContainer = $('#errorsTheStructureOfExcel');
errorsContainer.empty();
responseDataContainer.html(loadErrorExcelDataAjax(response.data));
showAlertMessage('.alert-msg', 'خطا در آپلود فایل', 3500);
$("#uploadExcelFileInput").val('');
}
}, 1500);
}
}, remainingTime);
};
xhr.onerror = function () {
storedExcelData = null;
showAlertMessage('.alert-msg', 'مشکلی در آپلود فایل به وجود آمد.', 3500);
$("#uploadExcelFileInput").val('');
$('#createData').prop('disabled', true).addClass('disable');
};
xhr.send(formData);
}
function showAlertMessage(selector, message, timeout) {
$(selector).show();
$(selector + ' p').text(message);
setTimeout(function () {
$(selector).hide();
$(selector + ' p').text('');
}, timeout);
}
function loadErrorExcelDataAjax(data) {
var htmlTable = '';
if (data.errors.length > 0) {
//let allRows = new Array(Math.max(data.rawData.length, data.errors.length)).fill(null);
//let rowErrorsDataArray = data.rawData.filter(x => data.errors.some(e => e.row === x.row));
htmlTable += `
<div class="wrapper">
<div class="excelTable Rtable Rtable--5cols Rtable--collapse rowCustom px-1">
<div class="Rtable-row Rtable-row--head align-items-center d-flex flex-column w-100 error-header sticky p-0">
<div class="Rtable-cell column-heading rowHeaderCustom text-center justify-content-center w-100 px-1">تاریخ ${data.rawData[0]?.salaryAidDateTime ?? ""}</div>
<div class="lineHead w-100"></div>
<div class="d-flex w-100 px-1 gap-2">
<div class="Rtable-cell column-heading rowHeaderCustom width1">
<span class="d-flex text-white align-items-center">
<label for="checkAllCreate2" class="text-white prevent-select">ردیف</label>
</span>
</div>
<div class="Rtable-cell column-heading rowHeaderCustom width2">جایگاه</div>
<div class="Rtable-cell column-heading rowHeaderCustom width3">نام و نام خانوادگی</div>
<div class="Rtable-cell column-heading rowHeaderCustom width4 text-center d-none d-md-block">کد ملی</div>
<div class="Rtable-cell column-heading rowHeaderCustom width5 text-center d-none d-md-block">شماره حساب</div>
<div class="Rtable-cell column-heading rowHeaderCustom width6 text-center d-none d-md-block">مبلغ قابل پرداخت</div>
</div>
</div>`;
let errorsMap = {};
data.errors.forEach(error => {
if (!errorsMap[error.row]) {
errorsMap[error.row] = [];
}
errorsMap[error.row].push(error);
});
const formattedErrors = Object.keys(errorsMap).map(row => ({
row,
data: errorsMap[row]
}));
//let rowErrorsDataMap = data.errors.reduce((acc, error) => {
// if (!acc[error.row]) {
// acc[error.row] = {
// ...data.rawData.find(x => x.row === error.row) || {},
// formattedErrors: [],
// row: error.row
// };
// }
// acc[error.row].formattedErrors.push(error);
// return acc;
//}, {});
//let rowErrorsDataArray = Object.values(rowErrorsDataMap);
let rowErrorsDataMap = data.errors.reduce((acc, error, index) => {
if (error.row === 0) {
let newKey = Object.keys(acc).length;
acc[newKey] = Object.assign(
{},
data.rawData.find(x => x.row === error.row) || {},
{ formattedErrors: [error], row: error.row }
);
} else {
if (!acc[error.row]) {
acc[error.row] = Object.assign(
{},
data.rawData.find(x => x.row === error.row) || {},
{ formattedErrors: [], row: error.row }
);
}
acc[error.row].formattedErrors.push(error);
}
return acc;
}, {});
let rowErrorsDataArray = Object.values(rowErrorsDataMap);
rowErrorsDataArray.forEach((item, index) => {
const rowErrors = errorsMap[item.row];
const rowData = data.rawData.find(x => x.row === item.row);
htmlTable += `<div class="Rtable-row rowPad align-items-center position-relative employee-row openActionModal error-row gap-2">`;
htmlTable += `<div class="Rtable-cell width1">
<label class="Rtable-cell--content prevent-select">
<span class="d-flex align-items-center justify-content-center gap-1">${index + 1}</span>
</label>
</div>`;
if (rowErrors.some(e => e.columns === "None")) {
//let fullErrorMessage = rowErrors.map(e => e.message).join('<br>');
let fullErrorMessage = item.row === 0 ? rowErrors[index].message : rowErrors.map(e => e.message).join('<br>');
htmlTable += `
<div class="Rtable-cell widthNone1">${item.row === 0 ? `-` : `ردیف ${item.row}`}</div>
<div class="text-start widthNone2 text-danger">${fullErrorMessage}</div>
</div>`;
} else {
let getColumnError = column => rowErrors.find(e => e.columns === column);
htmlTable += `<div class="Rtable-cell width2">ردیف ${item.row}</div>
<div class="Rtable-cell width3 d-flex justify-content-center ${getColumnError('FullName') ? 'error-column tooltipfull-container' : ''}">
<div class="Rtable-cell--content text-start ellipsed">${rowData?.fullName ?
getColumnError('FullName') ?
`<div class="d-flex justify-content-between align-items-center px-2">
<span>${rowData.fullName}</span>
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="11" cy="11" r="8.25" fill="#ED5252"/>
<path d="M11.9166 6.41667C11.9166 6.92293 11.5062 7.33333 10.9999 7.33333C10.4937 7.33333 10.0833 6.92293 10.0833 6.41667C10.0833 5.91041 10.4937 5.5 10.9999 5.5C11.5062 5.5 11.9166 5.91041 11.9166 6.41667Z" fill="white"/>
<path d="M11.0001 15.1276V10.5443C11.0001 10.2346 11.0001 10.0797 10.9773 9.95047C10.8678 9.32945 10.3816 8.84323 9.76055 8.73373C9.63131 8.71094 9.47646 8.71094 9.16675 8.71094V8.71094M11.0001 15.1276H12.3751M11.0001 15.1276H9.62508" stroke="white"/>
</svg>
</div>`
: rowData.fullName
:
`<div class="d-flex justify-content-between align-items-center px-2">
<span>-</span>
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="11" cy="11" r="8.25" fill="#ED5252"/>
<path d="M11.9166 6.41667C11.9166 6.92293 11.5062 7.33333 10.9999 7.33333C10.4937 7.33333 10.0833 6.92293 10.0833 6.41667C10.0833 5.91041 10.4937 5.5 10.9999 5.5C11.5062 5.5 11.9166 5.91041 11.9166 6.41667Z" fill="white"/>
<path d="M11.0001 15.1276V10.5443C11.0001 10.2346 11.0001 10.0797 10.9773 9.95047C10.8678 9.32945 10.3816 8.84323 9.76055 8.73373C9.63131 8.71094 9.47646 8.71094 9.16675 8.71094V8.71094M11.0001 15.1276H12.3751M11.0001 15.1276H9.62508" stroke="white"/>
</svg>
</div>`
}
</div>
${getColumnError('FullName') ? `<span class="tooltipfull">${getColumnError('FullName').message}</span>` : ''}
</div>
<div class="Rtable-cell width4 d-md-flex d-none justify-content-center ${getColumnError('NationalCode') ? 'error-column tooltipfull-container' : ''}">
<div class="Rtable-cell--content text-center w-100">${rowData?.nationalCode ?
getColumnError('NationalCode') ?
`<div class="d-flex justify-content-between align-items-center px-2">
<span>${rowData.nationalCode}</span>
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="11" cy="11" r="8.25" fill="#ED5252"/>
<path d="M11.9166 6.41667C11.9166 6.92293 11.5062 7.33333 10.9999 7.33333C10.4937 7.33333 10.0833 6.92293 10.0833 6.41667C10.0833 5.91041 10.4937 5.5 10.9999 5.5C11.5062 5.5 11.9166 5.91041 11.9166 6.41667Z" fill="white"/>
<path d="M11.0001 15.1276V10.5443C11.0001 10.2346 11.0001 10.0797 10.9773 9.95047C10.8678 9.32945 10.3816 8.84323 9.76055 8.73373C9.63131 8.71094 9.47646 8.71094 9.16675 8.71094V8.71094M11.0001 15.1276H12.3751M11.0001 15.1276H9.62508" stroke="white"/>
</svg>
</div>`
: rowData.nationalCode
:
`<div class="d-flex justify-content-between align-items-center px-2">
<span>-</span>
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="11" cy="11" r="8.25" fill="#ED5252"/>
<path d="M11.9166 6.41667C11.9166 6.92293 11.5062 7.33333 10.9999 7.33333C10.4937 7.33333 10.0833 6.92293 10.0833 6.41667C10.0833 5.91041 10.4937 5.5 10.9999 5.5C11.5062 5.5 11.9166 5.91041 11.9166 6.41667Z" fill="white"/>
<path d="M11.0001 15.1276V10.5443C11.0001 10.2346 11.0001 10.0797 10.9773 9.95047C10.8678 9.32945 10.3816 8.84323 9.76055 8.73373C9.63131 8.71094 9.47646 8.71094 9.16675 8.71094V8.71094M11.0001 15.1276H12.3751M11.0001 15.1276H9.62508" stroke="white"/>
</svg>
</div>`
}
</div>
${getColumnError('NationalCode') ? `<span class="tooltipfull">${getColumnError('NationalCode').message}</span>` : ''}
</div>
<div class="Rtable-cell width5 d-md-flex d-none justify-content-center ${getColumnError('AccountNumber') ? 'error-column tooltipfull-container' : ''}">
<div class="Rtable-cell--content text-center w-100">${rowData?.accountNumber ?
getColumnError('AccountNumber') ?
`<div class="d-flex justify-content-between align-items-center px-2">
<span>${rowData.accountNumber}</span>
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="11" cy="11" r="8.25" fill="#ED5252"/>
<path d="M11.9166 6.41667C11.9166 6.92293 11.5062 7.33333 10.9999 7.33333C10.4937 7.33333 10.0833 6.92293 10.0833 6.41667C10.0833 5.91041 10.4937 5.5 10.9999 5.5C11.5062 5.5 11.9166 5.91041 11.9166 6.41667Z" fill="white"/>
<path d="M11.0001 15.1276V10.5443C11.0001 10.2346 11.0001 10.0797 10.9773 9.95047C10.8678 9.32945 10.3816 8.84323 9.76055 8.73373C9.63131 8.71094 9.47646 8.71094 9.16675 8.71094V8.71094M11.0001 15.1276H12.3751M11.0001 15.1276H9.62508" stroke="white"/>
</svg>
</div>`
: rowData.accountNumber
:
`<div class="d-flex justify-content-between align-items-center px-2">
<span>-</span>
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="11" cy="11" r="8.25" fill="#ED5252"/>
<path d="M11.9166 6.41667C11.9166 6.92293 11.5062 7.33333 10.9999 7.33333C10.4937 7.33333 10.0833 6.92293 10.0833 6.41667C10.0833 5.91041 10.4937 5.5 10.9999 5.5C11.5062 5.5 11.9166 5.91041 11.9166 6.41667Z" fill="white"/>
<path d="M11.0001 15.1276V10.5443C11.0001 10.2346 11.0001 10.0797 10.9773 9.95047C10.8678 9.32945 10.3816 8.84323 9.76055 8.73373C9.63131 8.71094 9.47646 8.71094 9.16675 8.71094V8.71094M11.0001 15.1276H12.3751M11.0001 15.1276H9.62508" stroke="white"/>
</svg>
</div>`
}
</div>
${getColumnError('AccountNumber') ? `<span class="tooltipfull">${getColumnError('AccountNumber').message}</span>` : ''}
</div>
<div class="Rtable-cell width6 d-md-flex d-none justify-content-center ${getColumnError('Amount') ? 'error-column tooltipfull-container' : ''}">
<div class="Rtable-cell--content text-center w-100">${rowData?.amount ?
getColumnError('Amount') ?
`<div class="d-flex justify-content-between align-items-center px-2">
<span>${parseFloat(rowData.amount).toLocaleString()}</span>
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="11" cy="11" r="8.25" fill="#ED5252"/>
<path d="M11.9166 6.41667C11.9166 6.92293 11.5062 7.33333 10.9999 7.33333C10.4937 7.33333 10.0833 6.92293 10.0833 6.41667C10.0833 5.91041 10.4937 5.5 10.9999 5.5C11.5062 5.5 11.9166 5.91041 11.9166 6.41667Z" fill="white"/>
<path d="M11.0001 15.1276V10.5443C11.0001 10.2346 11.0001 10.0797 10.9773 9.95047C10.8678 9.32945 10.3816 8.84323 9.76055 8.73373C9.63131 8.71094 9.47646 8.71094 9.16675 8.71094V8.71094M11.0001 15.1276H12.3751M11.0001 15.1276H9.62508" stroke="white"/>
</svg>
</div>`
: parseFloat(rowData.amount).toLocaleString()
:
`<div class="d-flex justify-content-between align-items-center px-2">
<span>-</span>
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="11" cy="11" r="8.25" fill="#ED5252"/>
<path d="M11.9166 6.41667C11.9166 6.92293 11.5062 7.33333 10.9999 7.33333C10.4937 7.33333 10.0833 6.92293 10.0833 6.41667C10.0833 5.91041 10.4937 5.5 10.9999 5.5C11.5062 5.5 11.9166 5.91041 11.9166 6.41667Z" fill="white"/>
<path d="M11.0001 15.1276V10.5443C11.0001 10.2346 11.0001 10.0797 10.9773 9.95047C10.8678 9.32945 10.3816 8.84323 9.76055 8.73373C9.63131 8.71094 9.47646 8.71094 9.16675 8.71094V8.71094M11.0001 15.1276H12.3751M11.0001 15.1276H9.62508" stroke="white"/>
</svg>
</div>`
}
</div>
${getColumnError('Amount') ? `<span class="tooltipfull">${getColumnError('Amount').message}</span>` : ''}
</div>
</div>`;
htmlTable += `<div class="operation-div w-100">
<div class="operations-btns">
<div class="row p-0">
<div class="py-1 ${getColumnError('NationalCode') ? 'error-column rounded-lg' : ''}">
<div class="d-flex align-items-center justify-content-between">
<span class="span1">کد ملی:</span>
<span class="span1">${rowData?.nationalCode ? rowData.nationalCode : ""}</span>
</div>
<div>${getColumnError('NationalCode') ? getColumnError('NationalCode').message : ''}</div>
</div>
<div class="py-1 ${getColumnError('AccountNumber') ? 'error-column rounded-lg' : ''}">
<div class="d-flex align-items-center justify-content-between">
<span class="span1">شماره حساب:</span>
<span class="span1">${rowData?.accountNumber ? rowData.accountNumber : ""}</span>
</div>
<div>${getColumnError('AccountNumber') ? getColumnError('AccountNumber').message : ''}</div>
</div>
<div class="py-1 ${getColumnError('Amount') ? 'error-column rounded-lg' : ''}">
<div class="d-flex align-items-center justify-content-between">
<span class="span1">مبلغ قابل پرداخت:</span>
<span class="span1">${rowData?.amount ? parseFloat(rowData.amount).toLocaleString() : ""}</span>
</div>
<div>${getColumnError('Amount') ? getColumnError('Amount').message : ''}</div>
</div>
</div>
</div>
</div >`;
}
});
htmlTable += `</div></div>`;
}
return htmlTable;
}
function loadFinalExcelDataAjax(data) {
rawDataArray = [...data.rawData];
validDataArray = [...data.validData];
let htmlTable = '';
if (data.rawData.length > 0) {
const rowValidDataDuplicateExist = data.rawData.filter(x => x.duplicated);
htmlTable += `<div class="wrapper">
<div class="excelValidTable Rtable Rtable--5cols Rtable--collapse rowCustom px-1">
<div class="Rtable-row Rtable-row--head align-items-center d-flex flex-column w-100 sticky p-0">
<div class="Rtable-cell column-heading rowHeaderCustom d-flex align-items-center ${rowValidDataDuplicateExist.length > 0 ? 'justify-content-between' : 'justify-content-center'} w-100 px-2">
<div>تاریخ ${data.rawData[0].salaryAidDateTime}</div>`;
if (rowValidDataDuplicateExist.length > 0) {
htmlTable += `<div class="d-flex align-items-center gap-1">
<div class="radio-group">
<input type="radio" id="acceptAll" name="approvalAll" class="radio-input">
<label for="acceptAll" class="btnRadioAll btnAcceptAll">
<span>تایید همه</span>
<svg width="17" height="16" viewBox="0 0 11 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="5.5" cy="5.5" r="4.125" stroke="white"/>
<path d="M3.66683 5.5L5.04183 6.875L7.3335 4.125" stroke="white" stroke-linecap="round"/>
</svg>
</label>
<input type="radio" id="rejectAll" name="approvalAll" class="radio-input">
<label for="rejectAll" class="btnRadioAll btnRejectAll">
<span>رد همه</span>
<svg width="15" height="16" viewBox="0 0 11 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.5 9.625C4.9583 9.625 4.4219 9.5183 3.92143 9.311C3.42096 9.1037 2.96623 8.79986 2.58318 8.41682C2.20014 8.03377 1.8963 7.57904 1.689 7.07857C1.4817 6.5781 1.375 6.0417 1.375 5.5C1.375 4.9583 1.4817 4.4219 1.689 3.92143C1.8963 3.42096 2.20014 2.96623 2.58318 2.58318C2.96623 2.20014 3.42096 1.8963 3.92143 1.689C4.4219 1.4817 4.9583 1.375 5.5 1.375C6.0417 1.375 6.5781 1.4817 7.07857 1.689C7.57904 1.8963 8.03377 2.20014 8.41682 2.58319C8.79986 2.96623 9.1037 3.42096 9.311 3.92143C9.5183 4.4219 9.625 4.9583 9.625 5.5C9.625 6.0417 9.5183 6.5781 9.311 7.07857C9.1037 7.57904 8.79986 8.03377 8.41681 8.41682C8.03377 8.79986 7.57904 9.1037 7.07857 9.311C6.5781 9.5183 6.0417 9.625 5.5 9.625L5.5 9.625Z" stroke="white"/>
<path d="M4.125 4.125L6.875 6.875" stroke="white" stroke-linecap="round"/>
<path d="M6.875 4.125L4.125 6.875" stroke="white" stroke-linecap="round"/>
</svg>
</label>
</div>
</div>`;
}
htmlTable += `</div>
<div class="lineHeadValid w-100"></div>
<div class="d-flex w-100 px-2">
<div class="Rtable-cell column-heading rowHeaderCustom width1">
<span class="d-flex text-white align-items-center">
<label for="checkAllCreate2" class="text-white prevent-select">ردیف</label>
</span>
</div>
<div class="Rtable-cell column-heading rowHeaderCustom width2">نام و نام خانوادگی</div>
<div class="Rtable-cell column-heading rowHeaderCustom width3 text-center d-none d-md-block">کد ملی</div>
<div class="Rtable-cell column-heading rowHeaderCustom width4 text-center d-none d-md-block">شماره حساب</div>
<div class="Rtable-cell column-heading rowHeaderCustom width5 text-center d-none d-md-block">مبلغ قابل پرداخت</div>`;
if (rowValidDataDuplicateExist.length > 0) {
htmlTable += `<div class="Rtable-cell column-heading rowHeaderCustom width6 text-end">عملیات</div>`;
}
htmlTable += `</div></div>`;
const sortedData = data.rawData.sort((a, b) => {
if (a.duplicated === b.duplicated) {
return a.rejected === b.rejected ? 0 : a.rejected ? 1 : -1;
}
return a.duplicated ? -1 : 1;
});
htmlTable += `<div class="w-100 appendDepand">`;
sortedData.forEach((item, index) => {
htmlTable += `<div></div>
<div data-row-id="${item.row}" class="Rtable-row align-items-center position-relative employee-row openActionModal ${item.duplicated ? 'rowDuplicated' : ''}">`;
htmlTable += `<div class="Rtable-cell width1">
<div class="Rtable-cell--heading d-none">ردیف</div>
<label for="employee_id_${index}" class="Rtable-cell--content prevent-select">
<span class="d-flex align-items-center justify-content-center gap-1 numberIndex">
${index + 1}
</span>
</label>
</div>`;
if (item) {
htmlTable += `
<div class="Rtable-cell width2">${item.fullName}</div>
<div class="Rtable-cell width3 d-md-flex d-none justify-content-center">${item.nationalCode}</div>
<div class="Rtable-cell width4 d-md-flex d-none justify-content-center">${item.accountNumber}</div>
<div class="Rtable-cell width5 d-md-flex d-none justify-content-center">${parseFloat(item.amount).toLocaleString()}</div>`;
if (rowValidDataDuplicateExist.length > 0) {
htmlTable += `<div class="Rtable-cell width6 justify-content-end">`;
if (item.duplicated) {
htmlTable += `
<div class="radio-group" data-handle-change="false">
<input type="radio" id="accept_${index}" name="approval_${index}" class="radio-input radioAccept">
<label for="accept_${index}" class="btnRadio btnAccept">
<span>تایید</span>
<svg width="17" height="16" viewBox="0 0 11 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="5.5" cy="5.5" r="4.125" stroke="white"/>
<path d="M3.66683 5.5L5.04183 6.875L7.3335 4.125" stroke="white" stroke-linecap="round"/>
</svg>
</label>
<input type="radio" id="reject_${index}" name="approval_${index}" class="radio-input radioReject">
<label for="reject_${index}" class="btnRadio btnReject">
<span>رد</span>
<svg width="15" height="16" viewBox="0 0 11 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.5 9.625C4.9583 9.625 4.4219 9.5183 3.92143 9.311C3.42096 9.1037 2.96623 8.79986 2.58318 8.41682C2.20014 8.03377 1.8963 7.57904 1.689 7.07857C1.4817 6.5781 1.375 6.0417 1.375 5.5C1.375 4.9583 1.4817 4.4219 1.689 3.92143C1.8963 3.42096 2.20014 2.96623 2.58318 2.58318C2.96623 2.20014 3.42096 1.8963 3.92143 1.689C4.4219 1.4817 4.9583 1.375 5.5 1.375C6.0417 1.375 6.5781 1.4817 7.07857 1.689C7.57904 1.8963 8.03377 2.20014 8.41682 2.58319C8.79986 2.96623 9.1037 3.42096 9.311 3.92143C9.5183 4.4219 9.625 4.9583 9.625 5.5C9.625 6.0417 9.5183 6.5781 9.311 7.07857C9.1037 7.57904 8.79986 8.03377 8.41681 8.41682C8.03377 8.79986 7.57904 9.1037 7.07857 9.311C6.5781 9.5183 6.0417 9.625 5.5 9.625L5.5 9.625Z" stroke="white"/>
<path d="M4.125 4.125L6.875 6.875" stroke="white" stroke-linecap="round"/>
<path d="M6.875 4.125L4.125 6.875" stroke="white" stroke-linecap="round"/>
</svg>
</label>
</div>`;
}
htmlTable += `</div>`;
}
}
htmlTable += `</div>`;
htmlTable += `<div class="operation-div w-100">
<div class="operations-btns">
<div class="row p-0">
<div class="py-1">
<div class="d-flex align-items-center justify-content-between">
<span class="span1">کد ملی:</span>
<span class="span1">${item.nationalCode}</span>
</div>
</div>
<div class="py-1">
<div class="d-flex align-items-center justify-content-between">
<span class="span1">شماره حساب:</span>
<span class="span1">${item.accountNumber}</span>
</div>
</div>
<div class="py-1">
<div class="d-flex align-items-center justify-content-between">
<span class="span1">مبلغ قابل پرداخت:</span>
<span class="span1">${parseFloat(item.amount).toLocaleString()}</span>
</div>
</div>
</div>
</div>
</div >`;
});
htmlTable += `</div></div>`;
}
return htmlTable;
}
function reorderRows() {
var i = 1;
const table = $('.appendDepand');
const rowsWithOperations = [];
table.find('.Rtable-row').each(function () {
const row = $(this);
const operationDiv = row.next('.operation-div');
rowsWithOperations.push({ row, operationDiv });
});
const duplicatedRows = rowsWithOperations.filter(x => x.row.hasClass('rowDuplicated'));
const acceptedRows = rowsWithOperations.filter(x => x.row.hasClass('rowAccept'));
const rejectedRows = rowsWithOperations.filter(x => x.row.hasClass('rowRejected'));
const otherRows = rowsWithOperations.filter(x =>
!x.row.hasClass('rowDuplicated') &&
!x.row.hasClass('rowAccept') &&
!x.row.hasClass('rowRejected')
);
table.empty();
table.append('<div></div>');
[...duplicatedRows, ...acceptedRows, ...rejectedRows, ...otherRows].forEach(pair => {
table.append(pair.row);
table.append(pair.operationDiv);
});
$(".numberIndex").each(function () {
$(this).text(i++);
});
}
//function reorderRows() {
// var i = 1;
// const table = $('.appendDepand');
// const duplicatedRows = table.find('.Rtable-row.rowDuplicated').detach();
// const acceptedRows = table.find('.Rtable-row.rowAccept').detach();
// const rejectedRows = table.find('.Rtable-row.rowRejected').detach();
// const otherRows = table.find('.Rtable-row:not(.rowDuplicated, .rowAccept, .rowRejected)').detach();
// table.append(duplicatedRows);
// table.append(acceptedRows);
// table.append(rejectedRows);
// table.append(otherRows);
// $(".numberIndex").each(function () {
// $(this).text(i++);
// });
//}
$(document).on("change", ".radioReject", function () {
const row = $(this).closest('.Rtable-row');
row.removeClass('rowDuplicated rowAccept').addClass('rowRejected');
const radioInput = $(this).closest('.radio-group').find('.radio-input');
$(this).closest('.radio-group').attr("data-handle-change", "true");
//radioInput.prop('disabled', true);
//$(this).closest('.radio-group').addClass('disable');
const rowID = row.data("row-id");
validDataArray = validDataArray.filter(item => item.row !== rowID);
//console.log("بعد از رد کردن:", validDataArray);
reorderRows();
checkInputsEnabled();
});
$(document).on("change", ".radioAccept", function () {
const row = $(this).closest('.Rtable-row');
row.removeClass('rowRejected rowDuplicated').addClass('rowAccept');
const radioInput = $(this).closest('.radio-group').find('.radio-input');
$(this).closest('.radio-group').attr("data-handle-change", "true");
//radioInput.prop('disabled', true);
//$(this).closest('.radio-group').addClass('disable');
const rowID = row.data("row-id");
const selectedItem = rawDataArray.find(item => item.row === rowID);
if (selectedItem && !validDataArray.some(item => item.row === rowID)) {
validDataArray.push(selectedItem);
}
//console.log("بعد از تایید کردن:", validDataArray);
reorderRows();
checkInputsEnabled();
});
$(document).on("click", ".btnAcceptAll", function () {
checkInputsEnabled();
swal({
title: "آیا میخواهید همه را انتخاب کنید؟",
text: "",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "بله",
cancelButtonText: "خیر",
closeOnConfirm: true,
closeOnCancel: true
}, function (isConfirm) {
if (isConfirm) {
$(".radioAccept").each(function () {
const radioGroup = $(this).closest('.radio-group');
if (radioGroup.attr("data-handle-change") === "false") {
$(this).prop("checked", true).trigger("change");
radioGroup.addClass('disable');
$(this).prop("disabled", true);
}
});
$('.btnAcceptAll').closest('.radio-group').find('.radio-input').prop('disabled', true);
$('.btnAcceptAll').closest('.radio-group').addClass('disable');
}
});
});
$(document).on("click", ".btnRejectAll", function () {
checkInputsEnabled();
swal({
title: "آیا میخواهید همه را انتخاب کنید؟",
text: "",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "بله",
cancelButtonText: "خیر",
closeOnConfirm: true,
closeOnCancel: true
}, function (isConfirm) {
if (isConfirm) {
$(".radioReject").each(function () {
const radioGroup = $(this).closest('.radio-group');
if (radioGroup.attr("data-handle-change") === "false") {
$(this).prop("checked", true).trigger("change");
radioGroup.addClass('disable');
$(this).prop("disabled", true);
}
});
$('.btnRejectAll').closest('.radio-group').find('.radio-input').prop('disabled', true);
$('.btnRejectAll').closest('.radio-group').addClass('disable');
}
});
});
function checkInputsEnabled() {
const totalRequiredRows = $('.Rtable-row').has('.radioAccept, .radioReject').length;
const selectedRows = $('.Rtable-row').has('.radioAccept:checked, .radioReject:checked').length;
//let checkCount = $(".radio-group[data-handle-change='true']").length;
//console.log(totalRequiredRows);
//console.log(selectedRows);
//console.log(checkCount);
//totalRequiredRows > 0 &&
if (totalRequiredRows === selectedRows ) {
$('#createData').prop('disabled', false).removeClass('disable');
$('.btnAcceptAll').closest('.radio-group').find('.radio-input').prop('disabled', true);
$('.btnAcceptAll').closest('.radio-group').addClass('disable');
$('.btnRejectAll').closest('.radio-group').find('.radio-input').prop('disabled', true);
$('.btnRejectAll').closest('.radio-group').addClass('disable');
} else {
$('#createData').prop('disabled', true).addClass('disable');
$('.btnAcceptAll').closest('.radio-group').find('.radio-input').prop('disabled', false);
$('.btnAcceptAll').closest('.radio-group').removeClass('disable');
$('.btnRejectAll').closest('.radio-group').find('.radio-input').prop('disabled', false);
$('.btnRejectAll').closest('.radio-group').removeClass('disable');
}
}
$('#createData').click(function () {
if (!validDataArray) {
showAlertMessage('.alert-msg', 'داده ای برای ارسال وجود ندارد.', 3500);
return;
}
var loading = $("#createData").find('.spinner-loading').show();
$('#createData').addClass('disable');
$.ajax({
async: false,
type: 'POST',
url: sendExcelDataAjax,
headers: { "RequestVerificationToken": antiForgeryToken },
data: { data: validDataArray },
success: function (response) {
if (response.isSuccedded) {
$('.alert-success-msg').show();
$('.alert-success-msg p').text(response.message);
setTimeout(function () {
$('.alert-success-msg').hide();
$('.alert-success-msg p').text('');
}, 2000);
if (urlPathname.indexOf('/Client/Company/SalaryAid') > -1) {
$('#salaryaidListAjax').html('');
$('#PageIndex').val(0);
pageIndexJs = 0;
loadSalaryAidList();
}
loading.hide();
$('#MainModal').modal('hide');
} else {
$('.alert-msg').show();
$('.alert-msg p').text(response.message);
setTimeout(function () {
$('.alert-msg').hide();
$('.alert-msg p').text('');
}, 3500);
loading.hide();
$('#createData').removeClass('disable');
}
},
error: function (err) {
console.log(err);
loading.hide();
$('#createData').removeClass('disable');
}
});
});
function downloadExcelTemplate(url) {
$.ajax({
url: url,
method: 'GET',
xhrFields: {
responseType: 'blob'
},
success: function (data, status, xhr) {
let filename = "قالب مساعده.xlsx";
let blob = new Blob([data], { type: xhr.getResponseHeader('Content-Type') });
let link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = filename;
link.filename = "قالب مساعده.xlsx";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
},
error: function (xhr, status, error) {
console.error('Error downloading file:', error);
}
});
}
//$(#createData).click(function() {
//});