Files
CMS/src/CMSMicroservice.Infrastructure/Data/Seeding/WeekDefinitionSeeder.cs
T
masoodafar-web 25476ba120
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 1m43s
feat: implement commission calculation strategy with ORM and SP options
2025-12-20 03:15:28 +03:30

256 lines
11 KiB
C#

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using CMSMicroservice.Domain.Entities;
using CMSMicroservice.Infrastructure.Persistence;
using System.Globalization;
using System.Collections.Generic;
namespace CMSMicroservice.Infrastructure.Data.Seeding;
/// <summary>
/// Seeder برای پر کردن جدول WeekDefinitions
/// هفته اول سیستم: 2025-W46 میلادی = 1404-W35 شمسی
/// شروع هفته شمسی: شنبه | شروع هفته میلادی ISO: دوشنبه
/// </summary>
public class WeekDefinitionSeeder
{
private readonly ApplicationDbContext _context;
private readonly ILogger<WeekDefinitionSeeder> _logger;
private readonly PersianCalendar _persianCalendar;
/// <summary>
/// تاریخ شروع هفته اول سیستم (شنبه 17 آبان 1404 = 8 نوامبر 2025)
/// این شنبه در هفته 46 میلادی (ISO) و هفته 35 شمسی قرار دارد
/// </summary>
private static readonly DateTime BaseWeekStartDate = new DateTime(2025, 11, 8); // شنبه 8 نوامبر 2025
public WeekDefinitionSeeder(
ApplicationDbContext context,
ILogger<WeekDefinitionSeeder> logger)
{
_context = context;
_logger = logger;
_persianCalendar = new PersianCalendar();
}
/// <summary>
/// Seed هفته‌ها از هفته مبدأ تا یک سال بعد
/// </summary>
public async Task SeedAsync(CancellationToken cancellationToken = default)
{
_logger.LogInformation("=== WeekDefinitionSeeder: Starting ===");
_logger.LogInformation("Base week starts at: {BaseDate:yyyy-MM-dd} (Saturday)", BaseWeekStartDate);
try
{
var existingCount = await _context.WeekDefinitions.CountAsync(cancellationToken);
if (existingCount > 0)
{
_logger.LogInformation("WeekDefinitions already has {Count} records. Checking for missing weeks...", existingCount);
}
// شروع از هفته مبدأ
var startDate = BaseWeekStartDate;
// پایان تا یک سال بعد از الان
var endDate = GetEndOfWeek(DateTime.Today.AddYears(1));
var currentDate = startDate;
var addedCount = 0;
while (currentDate <= endDate)
{
var weekStart = currentDate; // شنبه
var weekEnd = currentDate.AddDays(6).Date.AddHours(23).AddMinutes(59).AddSeconds(59); // جمعه 23:59:59
// محاسبه شماره ترتیبی هفته (از 1 شروع می‌شود)
var weekOrder = CalculateWeekOrder(weekStart);
// نام نمایشی: هفته یکم، هفته دوم، ...
var displayName = GetPersianOrdinalWeekName(weekOrder);
// شماره هفته میلادی ISO (بر اساس دوشنبه)
var gregorianWeekNumber = GetISOWeekNumber(weekStart);
// شماره هفته شمسی (بر اساس شنبه)
var persianWeekNumber = GetPersianWeekNumber(weekStart);
// چک کنیم که این هفته قبلاً ثبت نشده باشه
var exists = await _context.WeekDefinitions
.AnyAsync(w => w.StartDate == weekStart, cancellationToken);
if (!exists)
{
var weekDefinition = new WeekDefinition
{
WeekOrder = weekOrder,
DisplayName = displayName,
GregorianWeekNumber = gregorianWeekNumber,
PersianWeekNumber = persianWeekNumber,
StartDate = weekStart,
EndDate = weekEnd,
GregorianYear = weekStart.Year,
PersianYear = _persianCalendar.GetYear(weekStart),
IsActive = true
};
_context.WeekDefinitions.Add(weekDefinition);
addedCount++;
_logger.LogDebug("Added: {DisplayName} | {GregorianWeek} | {PersianWeek} | {Start:yyyy-MM-dd} - {End:yyyy-MM-dd}",
displayName, gregorianWeekNumber, persianWeekNumber, weekStart, weekEnd);
}
// رفتن به هفته بعد (7 روز)
currentDate = currentDate.AddDays(7);
}
if (addedCount > 0)
{
await _context.SaveChangesAsync(cancellationToken);
_logger.LogInformation("Successfully added {Count} week definitions", addedCount);
}
else
{
_logger.LogInformation("No new week definitions needed");
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error seeding WeekDefinitions");
throw;
}
_logger.LogInformation("=== WeekDefinitionSeeder: Completed ===");
}
/// <summary>
/// محاسبه شماره ترتیبی هفته بر اساس فاصله از هفته مبدأ
/// هفته مبدأ = 1، هفته بعد = 2، ...
/// </summary>
private static int CalculateWeekOrder(DateTime weekStartDate)
{
var daysDiff = (weekStartDate - BaseWeekStartDate).Days;
var weeksDiff = daysDiff / 7;
return weeksDiff + 1;
}
/// <summary>
/// تبدیل عدد به نام ترتیبی فارسی
/// 1 -> هفته یکم، 2 -> هفته دوم، ...
/// </summary>
private static string GetPersianOrdinalWeekName(int weekOrder)
{
var ordinals = new Dictionary<int, string>
{
{ 1, "یکم" }, { 2, "دوم" }, { 3, "سوم" }, { 4, "چهارم" }, { 5, "پنجم" },
{ 6, "ششم" }, { 7, "هفتم" }, { 8, "هشتم" }, { 9, "نهم" }, { 10, "دهم" },
{ 11, "یازدهم" }, { 12, "دوازدهم" }, { 13, "سیزدهم" }, { 14, "چهاردهم" }, { 15, "پانزدهم" },
{ 16, "شانزدهم" }, { 17, "هفدهم" }, { 18, "هجدهم" }, { 19, "نوزدهم" }, { 20, "بیستم" },
{ 21, "بیست و یکم" }, { 22, "بیست و دوم" }, { 23, "بیست و سوم" }, { 24, "بیست و چهارم" }, { 25, "بیست و پنجم" },
{ 26, "بیست و ششم" }, { 27, "بیست و هفتم" }, { 28, "بیست و هشتم" }, { 29, "بیست و نهم" }, { 30, "سی‌ام" },
{ 31, "سی و یکم" }, { 32, "سی و دوم" }, { 33, "سی و سوم" }, { 34, "سی و چهارم" }, { 35, "سی و پنجم" },
{ 36, "سی و ششم" }, { 37, "سی و هفتم" }, { 38, "سی و هشتم" }, { 39, "سی و نهم" }, { 40, "چهلم" },
{ 41, "چهل و یکم" }, { 42, "چهل و دوم" }, { 43, "چهل و سوم" }, { 44, "چهل و چهارم" }, { 45, "چهل و پنجم" },
{ 46, "چهل و ششم" }, { 47, "چهل و هفتم" }, { 48, "چهل و هشتم" }, { 49, "چهل و نهم" }, { 50, "پنجاهم" },
{ 51, "پنجاه و یکم" }, { 52, "پنجاه و دوم" }, { 53, "پنجاه و سوم" }, { 54, "پنجاه و چهارم" }, { 55, "پنجاه و پنجم" },
{ 56, "پنجاه و ششم" }, { 57, "پنجاه و هفتم" }, { 58, "پنجاه و هشتم" }, { 59, "پنجاه و نهم" }, { 60, "شصتم" }
};
if (ordinals.TryGetValue(weekOrder, out var ordinal))
{
return $"هفته {ordinal}";
}
// برای اعداد بزرگتر از 60
return $"هفته {weekOrder}";
}
/// <summary>
/// پیدا کردن شنبه این هفته (شروع هفته شمسی)
/// </summary>
private static DateTime GetStartOfWeek(DateTime date)
{
var diff = (7 + (date.DayOfWeek - DayOfWeek.Saturday)) % 7;
return date.AddDays(-diff).Date;
}
/// <summary>
/// پیدا کردن جمعه این هفته (پایان هفته شمسی)
/// </summary>
private static DateTime GetEndOfWeek(DateTime date)
{
return GetStartOfWeek(date).AddDays(6);
}
/// <summary>
/// شماره هفته میلادی ISO 8601
/// هفته ISO از دوشنبه شروع می‌شود
/// برای تاریخ شنبه، باید دوشنبه همان هفته را پیدا کنیم (2 روز بعد)
/// </summary>
private static string GetISOWeekNumber(DateTime saturdayDate)
{
// شنبه + 2 روز = دوشنبه همان هفته ISO
var mondayOfWeek = saturdayDate.AddDays(2);
// محاسبه شماره هفته ISO
var cal = CultureInfo.InvariantCulture.Calendar;
var weekNumber = cal.GetWeekOfYear(mondayOfWeek, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
var year = mondayOfWeek.Year;
// تصحیح سال برای هفته‌های لبه‌ای
if (weekNumber == 1 && mondayOfWeek.Month == 12)
{
year++;
}
else if (weekNumber >= 52 && mondayOfWeek.Month == 1)
{
year--;
}
return $"{year}-W{weekNumber:D2}";
}
/// <summary>
/// شماره هفته شمسی
/// هفته شمسی از شنبه شروع می‌شود
/// </summary>
private string GetPersianWeekNumber(DateTime saturdayDate)
{
var persianYear = _persianCalendar.GetYear(saturdayDate);
var dayOfYear = _persianCalendar.GetDayOfYear(saturdayDate);
// اول فروردین این سال
var firstDayOfYear = _persianCalendar.ToDateTime(persianYear, 1, 1, 0, 0, 0, 0);
// پیدا کردن اولین شنبه سال
var daysUntilFirstSaturday = ((int)DayOfWeek.Saturday - (int)firstDayOfYear.DayOfWeek + 7) % 7;
// اگر اول فروردین شنبه باشه، daysUntilFirstSaturday = 0
// در غیر این صورت روزهای قبل از اولین شنبه، هفته 0 یا هفته آخر سال قبل هستند
int weekNumber;
if (daysUntilFirstSaturday == 0)
{
// اول فروردین شنبه است
weekNumber = ((dayOfYear - 1) / 7) + 1;
}
else
{
// روزهای قبل از اولین شنبه
if (dayOfYear <= daysUntilFirstSaturday)
{
// این روزها متعلق به آخرین هفته سال قبل هستند
// اما برای سادگی، هفته 1 در نظر می‌گیریم
weekNumber = 1;
}
else
{
weekNumber = ((dayOfYear - daysUntilFirstSaturday - 1) / 7) + 1;
}
}
return $"{persianYear}-W{weekNumber:D2}";
}
}