256 lines
11 KiB
C#
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}";
|
|
}
|
|
}
|