Files
Backend-Api/CompanyManagement.Infrastructure.Excel/SalaryAid/SalaryAidImportExcel.cs

300 lines
14 KiB
C#

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 calculationMonth, int calculationYear, 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.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
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[3, 1].Text != "نام و نام خانوادگی" ||
worksheet.Cells[3, 2].Text != "کد ملی" ||
worksheet.Cells[3, 3].Text != "شماره حساب" ||
worksheet.Cells[3, 4].Text != "مبلغ قابل پرداخت" ||
worksheet.Cells[1, 3].Text != "تاریخ پرداخت" ||
worksheet.Cells[1, 1].Text != "سال محاسبه" ||
worksheet.Cells[1, 2].Text != "ماه محاسبه")
{
result.Errors.Add(new SalaryAidImportExcelError("ساختار فایل اکسل اشتباه است.", 0, SalaryAidExcelColumns.None.ToString()));
return result;
}
var salaryDateFa = worksheet.Cells[2, 3].Text;
var calculationMonth = Convert.ToInt32(string.IsNullOrWhiteSpace(worksheet.Cells[2, 2].Text) ? "0" : worksheet.Cells[2, 2].Text);
var calculationYear = Convert.ToInt32(string.IsNullOrWhiteSpace(worksheet.Cells[2, 1].Text) ? "0" : worksheet.Cells[2, 1].Text);
if (string.IsNullOrWhiteSpace(salaryDateFa))
{
result.Errors.Add(new SalaryAidImportExcelError("لطفا در سلول زرد رنگ تاریخ پرداخت را وارد کنید", 0, SalaryAidExcelColumns.None.ToString()));
return result;
}
if (calculationMonth == 0)
{
result.Errors.Add(new SalaryAidImportExcelError("لطفا در سلول آبی رنگ ماه محاسبه را وارد کنید", 0, SalaryAidExcelColumns.None.ToString()));
return result;
}
if (calculationYear == 0)
{
result.Errors.Add(new SalaryAidImportExcelError("لطفا در سلول آبی رنگ سال محاسبه را وارد کنید", 0, SalaryAidExcelColumns.None.ToString()));
return result;
}
var calculationDate = $"{calculationYear:0000}/{calculationMonth:00}/01";
if (salaryDateFa.TryToGeorgianDateTime(out var salaryDateTime) == false)
{
result.Errors.Add(new SalaryAidImportExcelError("تاریخ وارد شده نامعتبر است", 0, SalaryAidExcelColumns.None.ToString()));
}
if (calculationDate.TryToGeorgianDateTime(out var calculationDateTime) == 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 = 4;
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, calculationMonth, calculationYear, 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()));
//}
_ = DateTime.Now.Date.AddMonthsFa(-1, out var oneMonthAgoGr);
if (oneMonthAgoGr > calculationDateTime)
{
bool customizeCheckout = false;
bool customizeCheckoutTemp = false;
bool checkout = false;
if (_companyContext.CustomizeCheckouts.Any(x => x.WorkshopId == workshopId && employee.id == x.EmployeeId &&
x.ContractStart <= oneMonthAgoGr && x.ContractEnd >= calculationDateTime))
{
customizeCheckout = true;
}
if (_companyContext.CustomizeCheckoutTemps.Any(x => x.WorkshopId == workshopId && employee.id == x.EmployeeId &&
x.ContractStart <= calculationDateTime && x.ContractEnd >= oneMonthAgoGr))
{
customizeCheckoutTemp = true;
}
if (_companyContext.CheckoutSet.Any(x => x.WorkshopId == workshopId && employee.id == x.EmployeeId &&
x.ContractStart <= calculationDateTime && x.ContractEnd >= oneMonthAgoGr))
{
checkout = true;
}
if (customizeCheckout || customizeCheckoutTemp)
{
result.Errors.Add(new SalaryAidImportExcelError($"شما نمیتوانید به پرسنل {fullName} در تاریخ قبل از یک ماه گذشته که فیش صادر شده باشد مساعده دهید", row, SalaryAidExcelColumns.None.ToString()));
}
}
//if(_companyContext.CheckoutSet.Any(x => x.WorkshopId == workshopId && employee.id == x.EmployeeId &&
// x.ContractStart <= calculationDateTime && x.ContractEnd >= calculationDateTime))
// result.Errors.Add(new SalaryAidImportExcelError($"پرسنل {fullName} در تاریخ {calculationDate} دارای فیش رسمی میباشد", 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, calculationMonth, calculationYear, row, true));
continue;
}
result.ValidData.Add(new SalaryAidImportData(employee.id, workshopId, fullName, amount, accountNumber, nationalCode, salaryDateFa, calculationMonth, calculationYear, row, false));
}
result.RawData = result.RawData.GroupBy(x => x.Row).Select(x => new SalaryAidImportData(x.Last().EmployeeId,
x.First().WorkshopId, x.First().FullName,
x.First().Amount, x.First().AccountNumber, x.First().NationalCode, x.First().SalaryAidDateTime, x.First().calculationMonth, x.First().calculationYear, 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;
}
}