429 lines
18 KiB
C#
429 lines
18 KiB
C#
using _0_Framework.Application;
|
||
using CompanyManagement.Infrastructure.Excel.CWS;
|
||
using CompanyManagment.App.Contracts.InstitutionContract;
|
||
using OfficeOpenXml;
|
||
using OfficeOpenXml.Style;
|
||
using System.Drawing;
|
||
using System.Text.RegularExpressions;
|
||
|
||
namespace CompanyManagement.Infrastructure.Excel.InstitutionContract;
|
||
|
||
// Enum برای تعریف ستونهای موجود
|
||
public enum ExcelColumnType
|
||
{
|
||
RowNumber, // ردیف
|
||
PhysicalContract, // قرارداد فیزیکی
|
||
ContractNo, // شماره قرارداد
|
||
Representative, // معرف
|
||
ContractingPartyName, // طرف حساب
|
||
ArchiveCode, // شماره کارفرما
|
||
EmployerName, // کارفرما
|
||
WorkshopName, // کارگاهها (چندخطی)
|
||
WorkshopCount, // تعداد کارگاه
|
||
EmployeeCount, // مجموع پرسنل
|
||
ContractStartDate, // شروع قرارداد
|
||
ContractEndDate, // پایان قرارداد
|
||
InstallmentAmount, // مبلغ قسط
|
||
ContractAmount, // مبلغ قرارداد
|
||
FinancialStatus // وضعیت مالی
|
||
}
|
||
|
||
// کلاس کانفیگ برای تنظیم ستونهای نمایشی
|
||
public class ExcelColumnConfig
|
||
{
|
||
public List<ExcelColumnType> VisibleColumns { get; set; }
|
||
|
||
public ExcelColumnConfig()
|
||
{
|
||
// فعلاً تمام ستونها فعال هستند
|
||
VisibleColumns = new List<ExcelColumnType>
|
||
{
|
||
ExcelColumnType.RowNumber,
|
||
ExcelColumnType.PhysicalContract,
|
||
ExcelColumnType.ContractNo,
|
||
ExcelColumnType.Representative,
|
||
ExcelColumnType.ContractingPartyName,
|
||
ExcelColumnType.ArchiveCode,
|
||
ExcelColumnType.EmployerName,
|
||
ExcelColumnType.WorkshopName,
|
||
ExcelColumnType.WorkshopCount,
|
||
ExcelColumnType.EmployeeCount,
|
||
ExcelColumnType.ContractStartDate,
|
||
ExcelColumnType.ContractEndDate,
|
||
ExcelColumnType.InstallmentAmount,
|
||
ExcelColumnType.ContractAmount,
|
||
ExcelColumnType.FinancialStatus
|
||
};
|
||
}
|
||
}
|
||
|
||
public class InstitutionContractExcelGenerator
|
||
{
|
||
private static ExcelColumnConfig _columnConfig = new ExcelColumnConfig();
|
||
|
||
public static byte[] GenerateExcel(List<InstitutionContractExcelViewModel> contractViewModels)
|
||
{
|
||
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
|
||
using var package = new ExcelPackage();
|
||
|
||
// ایجاد شیت برای هر تب با دادههای مربوطه
|
||
foreach (var viewModel in contractViewModels)
|
||
{
|
||
var worksheet = CreateWorksheet(package, viewModel.Tab);
|
||
CreateExcelSheet(viewModel.GetInstitutionContractListItemsViewModels ?? new List<GetInstitutionContractListItemsViewModel>(), worksheet);
|
||
}
|
||
|
||
return package.GetAsByteArray();
|
||
}
|
||
|
||
/// <summary>
|
||
/// ایجاد شیت بر اساس نوع تب
|
||
/// </summary>
|
||
private static ExcelWorksheet CreateWorksheet(ExcelPackage package, InstitutionContractListStatus? status)
|
||
{
|
||
return status switch
|
||
{
|
||
InstitutionContractListStatus.DeactiveWithDebt =>
|
||
CreateColoredWorksheet(package, "غیرفعال دارای بدهی", Color.LightBlue),
|
||
|
||
InstitutionContractListStatus.Deactive =>
|
||
CreateColoredWorksheet(package, "غیرفعال", Color.LightGray),
|
||
|
||
InstitutionContractListStatus.PendingForRenewal =>
|
||
CreateColoredWorksheet(package, "در انتظار تمدید", Color.LightCoral),
|
||
|
||
InstitutionContractListStatus.Free =>
|
||
CreateColoredWorksheet(package, "بنفش", Color.MediumPurple),
|
||
|
||
InstitutionContractListStatus.Block =>
|
||
CreateColoredWorksheet(package, "بلاک", Color.DimGray),
|
||
|
||
InstitutionContractListStatus.WithoutWorkshop =>
|
||
CreateColoredWorksheet(package, "بدون کارگاه", Color.Yellow),
|
||
|
||
InstitutionContractListStatus.Active =>
|
||
CreateColoredWorksheet(package, "فعال", Color.White),
|
||
|
||
InstitutionContractListStatus.PendingForVerify =>
|
||
CreateColoredWorksheet(package, "در انتظار تایید", Color.OrangeRed),
|
||
|
||
null => CreateColoredWorksheet(package, "کل قرارداد ها", Color.White),
|
||
_ => throw new ArgumentOutOfRangeException(nameof(status), status, null)
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// ایجاد شیت با رنگ تب
|
||
/// </summary>
|
||
private static ExcelWorksheet CreateColoredWorksheet(ExcelPackage package, string sheetName, Color tabColor)
|
||
{
|
||
var worksheet = package.Workbook.Worksheets.Add(sheetName);
|
||
worksheet.TabColor = tabColor;
|
||
return worksheet;
|
||
}
|
||
|
||
private static void CreateExcelSheet(List<GetInstitutionContractListItemsViewModel> contractItems, ExcelWorksheet worksheet)
|
||
{
|
||
// دریافت نقشه ستونهای مرئی
|
||
var visibleColumnIndices = GetVisibleColumnIndices();
|
||
int columnCount = visibleColumnIndices.Count;
|
||
|
||
// تنظیم Headers
|
||
SetupHeaders(worksheet, visibleColumnIndices, columnCount);
|
||
|
||
using (var range = worksheet.Cells[1, 1, 1, columnCount])
|
||
{
|
||
range.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
|
||
range.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
|
||
range.Style.Font.Bold = true;
|
||
range.Style.Fill.PatternType = ExcelFillStyle.Solid;
|
||
range.Style.Fill.BackgroundColor.SetColor(Color.LightGray); // رنگ پس زمینه خاکستری
|
||
|
||
// اعمال بوردر به همه خطوط
|
||
range.Style.Border.Top.Style = ExcelBorderStyle.Thin;
|
||
range.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
|
||
range.Style.Border.Left.Style = ExcelBorderStyle.Thin;
|
||
range.Style.Border.Right.Style = ExcelBorderStyle.Thin;
|
||
|
||
// اعمال رنگ مشکی برای بوردرها
|
||
range.Style.Border.Top.Color.SetColor(Color.Black);
|
||
range.Style.Border.Bottom.Color.SetColor(Color.Black);
|
||
range.Style.Border.Left.Color.SetColor(Color.Black);
|
||
range.Style.Border.Right.Color.SetColor(Color.Black);
|
||
}
|
||
|
||
int row = 2;
|
||
|
||
for (int i = 0; i < contractItems.Count; i++)
|
||
{
|
||
var contract = contractItems[i];
|
||
var employers = contract.EmployerNames?.ToList() ?? new();
|
||
var workshops = contract.WorkshopNames?.ToList() ?? new();
|
||
|
||
int maxRows = 1; // هر قرارداد فقط یک ردیف؛ نیازی به مرج عمودی نیست
|
||
|
||
int startRow = row;
|
||
int endRow = row + maxRows - 1;
|
||
|
||
// 🎨 دریافت رنگ پسزمینه بر اساس وضعیت قرارداد
|
||
var fillColor = GetColorByStatus(contract.ListStatus, contract.WorkshopsCount);
|
||
|
||
for (int j = 0; j < maxRows; j++)
|
||
{
|
||
int currentRow = row + j;
|
||
|
||
// پر کردن ستونهای employer و workshop
|
||
var employerColIndex = GetColumnIndexForType(ExcelColumnType.EmployerName, visibleColumnIndices);
|
||
var workshopColIndex = GetColumnIndexForType(ExcelColumnType.WorkshopName, visibleColumnIndices);
|
||
|
||
if (employerColIndex > 0)
|
||
worksheet.Cells[currentRow, employerColIndex].Value = j < employers.Count ? employers[j] : null;
|
||
|
||
if (workshopColIndex > 0)
|
||
worksheet.Cells[currentRow, workshopColIndex].Value = j < workshops.Count ? workshops[j] : null;
|
||
|
||
for (int col = 1; col <= columnCount; col++)
|
||
{
|
||
var cell = worksheet.Cells[currentRow, col];
|
||
|
||
// 📏 بوردرهای داخلی نازک / نقطهچین
|
||
cell.Style.Border.Top.Style = ExcelBorderStyle.Dotted;
|
||
cell.Style.Border.Bottom.Style = ExcelBorderStyle.Dotted;
|
||
cell.Style.Border.Left.Style = ExcelBorderStyle.Thin;
|
||
cell.Style.Border.Right.Style = ExcelBorderStyle.Thin;
|
||
|
||
// 🎯 تراز متن
|
||
cell.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
|
||
cell.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
|
||
|
||
// 🎨 اعمال رنگ پسزمینه
|
||
cell.Style.Fill.PatternType = ExcelFillStyle.Solid;
|
||
cell.Style.Fill.BackgroundColor.SetColor(fillColor);
|
||
}
|
||
}
|
||
|
||
// 🧱 مرج و مقداردهی ستونهای اصلی
|
||
FillColumnData(worksheet, contract, startRow, endRow, visibleColumnIndices);
|
||
|
||
// 📦 بوردر ضخیم خارجی برای هر سطر
|
||
var boldRange = worksheet.Cells[startRow, 1, endRow, columnCount];
|
||
boldRange.Style.Border.BorderAround(ExcelBorderStyle.Medium);
|
||
|
||
row += maxRows;
|
||
}
|
||
|
||
SetupPrintSettings(worksheet, visibleColumnIndices, columnCount);
|
||
}
|
||
|
||
/// <summary>
|
||
/// دریافت فهرست ستونهای مرئی بر اساس کانفیگ
|
||
/// </summary>
|
||
private static List<ExcelColumnType> GetVisibleColumnIndices()
|
||
{
|
||
return _columnConfig.VisibleColumns;
|
||
}
|
||
|
||
/// <summary>
|
||
/// دریافت شماره ستون برای یک نوع ستون خاص
|
||
/// </summary>
|
||
private static int GetColumnIndexForType(ExcelColumnType columnType, List<ExcelColumnType> visibleColumns)
|
||
{
|
||
var index = visibleColumns.IndexOf(columnType);
|
||
return index >= 0 ? index + 1 : 0; // 1-based indexing
|
||
}
|
||
|
||
/// <summary>
|
||
/// دریافت متن header برای یک نوع ستون
|
||
/// </summary>
|
||
private static string GetColumnHeader(ExcelColumnType columnType)
|
||
{
|
||
return columnType switch
|
||
{
|
||
ExcelColumnType.RowNumber => "ردیف",
|
||
ExcelColumnType.PhysicalContract => "قرارداد فیزیکی",
|
||
ExcelColumnType.ContractNo => "شماره قرارداد",
|
||
ExcelColumnType.Representative => "معرف",
|
||
ExcelColumnType.ContractingPartyName => "طرف حساب",
|
||
ExcelColumnType.ArchiveCode => "شماره کارفرما",
|
||
ExcelColumnType.EmployerName => "کارفرما",
|
||
ExcelColumnType.WorkshopName => "کارگاهها",
|
||
ExcelColumnType.WorkshopCount => "تعداد کارگاه",
|
||
ExcelColumnType.EmployeeCount => "مجموع پرسنل",
|
||
ExcelColumnType.ContractStartDate => "شروع قرارداد",
|
||
ExcelColumnType.ContractEndDate => "پایان قرارداد",
|
||
ExcelColumnType.InstallmentAmount => "مبلغ قسط",
|
||
ExcelColumnType.ContractAmount => "مبلغ قرارداد",
|
||
ExcelColumnType.FinancialStatus => "وضعیت مالی",
|
||
_ => ""
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// تنظیم Headerهای ستونها
|
||
/// </summary>
|
||
private static void SetupHeaders(ExcelWorksheet worksheet, List<ExcelColumnType> visibleColumns, int columnCount)
|
||
{
|
||
for (int i = 0; i < visibleColumns.Count; i++)
|
||
{
|
||
worksheet.Cells[1, i + 1].Value = GetColumnHeader(visibleColumns[i]);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// پر کردن دادههای ستونها برای یک قرارداد
|
||
/// </summary>
|
||
private static void FillColumnData(ExcelWorksheet worksheet, GetInstitutionContractListItemsViewModel contract, int startRow, int endRow, List<ExcelColumnType> visibleColumns)
|
||
{
|
||
for (int i = 0; i < visibleColumns.Count; i++)
|
||
{
|
||
int columnIndex = i + 1; // 1-based indexing
|
||
var columnType = visibleColumns[i];
|
||
|
||
// Merge cells for non-repeating columns
|
||
worksheet.Cells[startRow, columnIndex, endRow, columnIndex].Merge = true;
|
||
|
||
var cell = worksheet.Cells[startRow, columnIndex];
|
||
|
||
switch (columnType)
|
||
{
|
||
case ExcelColumnType.RowNumber:
|
||
// TODO: مقدار ردیف رو از user input دریافت کن
|
||
break;
|
||
case ExcelColumnType.PhysicalContract:
|
||
// TODO: مقدار قرارداد فیزیکی رو دریافت کن
|
||
break;
|
||
case ExcelColumnType.ContractNo:
|
||
cell.Value = contract.ContractNo;
|
||
break;
|
||
case ExcelColumnType.Representative:
|
||
cell.Value = contract.RepresentativeName;
|
||
break;
|
||
case ExcelColumnType.ContractingPartyName:
|
||
cell.Value = contract.ContractingPartyName;
|
||
break;
|
||
case ExcelColumnType.ArchiveCode:
|
||
cell.Value = contract.ArchiveNo;
|
||
break;
|
||
case ExcelColumnType.EmployerName:
|
||
// این ستون چندخطی است و داخل loop پر میشود
|
||
break;
|
||
case ExcelColumnType.WorkshopName:
|
||
// این ستون چندخطی است و داخل loop پر میشود
|
||
break;
|
||
case ExcelColumnType.WorkshopCount:
|
||
cell.Value = contract.WorkshopsCount;
|
||
break;
|
||
case ExcelColumnType.EmployeeCount:
|
||
cell.Value = contract.EmployeesCount;
|
||
break;
|
||
case ExcelColumnType.ContractStartDate:
|
||
cell.Value = contract.ContractStartFa;
|
||
break;
|
||
case ExcelColumnType.ContractEndDate:
|
||
cell.Value = contract.ContractEndFa;
|
||
break;
|
||
case ExcelColumnType.InstallmentAmount:
|
||
cell.Value = contract.InstallmentAmount;
|
||
cell.Style.Numberformat.Format = "#,##0";
|
||
break;
|
||
case ExcelColumnType.ContractAmount:
|
||
cell.Value = contract.ContractAmount;
|
||
cell.Style.Numberformat.Format = "#,##0";
|
||
break;
|
||
case ExcelColumnType.FinancialStatus:
|
||
cell.Value = contract.Balance;
|
||
cell.Style.Numberformat.Format = "#,##0";
|
||
|
||
if (contract.Balance > 0)
|
||
cell.Style.Font.Color.SetColor(Color.Red);
|
||
else if (contract.Balance < 0)
|
||
cell.Style.Font.Color.SetColor(Color.Green);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// تنظیم تنظیمات چاپ و عرض ستونها
|
||
/// </summary>
|
||
private static void SetupPrintSettings(ExcelWorksheet worksheet, List<ExcelColumnType> visibleColumns, int columnCount)
|
||
{
|
||
worksheet.PrinterSettings.PaperSize = ePaperSize.A4;
|
||
worksheet.PrinterSettings.Orientation = eOrientation.Landscape;
|
||
worksheet.PrinterSettings.FitToPage = true;
|
||
worksheet.PrinterSettings.FitToWidth = 1;
|
||
worksheet.PrinterSettings.FitToHeight = 0;
|
||
worksheet.PrinterSettings.Scale = 85;
|
||
|
||
// تنظیم عرض ستونها بر اساس نوع ستون
|
||
for (int i = 0; i < visibleColumns.Count; i++)
|
||
{
|
||
int columnIndex = i + 1;
|
||
worksheet.Columns[columnIndex].Width = GetColumnWidth(visibleColumns[i]);
|
||
}
|
||
|
||
worksheet.View.RightToLeft = true; // فارسی
|
||
}
|
||
|
||
/// <summary>
|
||
/// دریافت عرض ستون پیشفرض برای هر نوع ستون
|
||
/// </summary>
|
||
private static double GetColumnWidth(ExcelColumnType columnType)
|
||
{
|
||
return columnType switch
|
||
{
|
||
ExcelColumnType.RowNumber => 8,
|
||
ExcelColumnType.PhysicalContract => 15,
|
||
ExcelColumnType.ContractNo => 17,
|
||
ExcelColumnType.Representative => 15,
|
||
ExcelColumnType.ContractingPartyName => 40,
|
||
ExcelColumnType.ArchiveCode => 10,
|
||
ExcelColumnType.EmployerName => 40,
|
||
ExcelColumnType.WorkshopName => 45,
|
||
ExcelColumnType.WorkshopCount => 12,
|
||
ExcelColumnType.EmployeeCount => 12,
|
||
ExcelColumnType.ContractStartDate => 12,
|
||
ExcelColumnType.ContractEndDate => 12,
|
||
ExcelColumnType.InstallmentAmount => 15,
|
||
ExcelColumnType.ContractAmount => 15,
|
||
ExcelColumnType.FinancialStatus => 12,
|
||
_ => 12
|
||
};
|
||
}
|
||
|
||
private static double MoneyToDouble(string value)
|
||
{
|
||
if (string.IsNullOrEmpty(value))
|
||
return 0;
|
||
|
||
var min = value.Length > 1 ? value.Substring(0, 2) : "";
|
||
var test = min == "\u200e\u2212" ? value.MoneyToDouble() * -1 : value.MoneyToDouble();
|
||
return test;
|
||
}
|
||
|
||
/// <summary>
|
||
/// دریافت رنگ بر اساس وضعیت قرارداد
|
||
/// </summary>
|
||
private static Color GetColorByStatus(InstitutionContractListStatus status, int workshopsCount)
|
||
{
|
||
return status switch
|
||
{
|
||
InstitutionContractListStatus.DeactiveWithDebt => Color.LightBlue,
|
||
InstitutionContractListStatus.Deactive => Color.LightGray,
|
||
InstitutionContractListStatus.PendingForRenewal => Color.LightCoral,
|
||
InstitutionContractListStatus.Free => Color.MediumPurple,
|
||
InstitutionContractListStatus.Block => Color.DimGray,
|
||
InstitutionContractListStatus.WithoutWorkshop => Color.Yellow,
|
||
InstitutionContractListStatus.Active => Color.White,
|
||
_ => Color.White
|
||
};
|
||
}
|
||
|
||
}
|
||
|
||
public class InstitutionContractExcelViewModel
|
||
{
|
||
public InstitutionContractListStatus? Tab { get; set; }
|
||
public List<GetInstitutionContractListItemsViewModel> GetInstitutionContractListItemsViewModels { get; set; }
|
||
}
|