# 📝 Changelog - ۲۹ آذر ۱۴۰۴ (19 December 2025)

> **Session**: مایگریشن از WeekNumber به WeekDefinitionId در سیستم کمیسیون

---

## 🎯 هدف اصلی

تغییر از `string WeekNumber` به `long WeekDefinitionId` به عنوان **Foreign Key** به جدول `WeekDefinitions` در تمام جداول و سرویس‌های مرتبط با کمیسیون.

### دلایل تغییر:
1. **یکپارچگی داده**: استفاده از FK واقعی به جای string
2. **بهبود Query Performance**: Join بر اساس long id سریع‌تر از string
3. **جلوگیری از Orphan Records**: FK constraint
4. **سادگی نام‌گذاری**: `WeekDisplayName` به جای ترکیب `GregorianWeekNumber` + `PersianWeekNumber`

---

## 📦 CMS Microservice

### Entities (5 entity)

#### 1. NetworkWeeklyBalance
```csharp
// قبل
public string WeekNumber { get; set; }

// بعد
public long WeekDefinitionId { get; set; }
public virtual WeekDefinition WeekDefinition { get; set; }
```

#### 2. WeeklyCommissionPool
```csharp
// قبل
public string WeekNumber { get; set; }

// بعد
public long WeekDefinitionId { get; set; }
public virtual WeekDefinition WeekDefinition { get; set; }
```

#### 3. UserCommissionPayout
```csharp
// قبل
public string WeekNumber { get; set; }

// بعد
public long WeekDefinitionId { get; set; }
public virtual WeekDefinition WeekDefinition { get; set; }
```

#### 4. WorkerExecutionLog
```csharp
// قبل
public string WeekNumber { get; set; }

// بعد
public long? WeekDefinitionId { get; set; } // nullable برای backward compatibility
public virtual WeekDefinition? WeekDefinition { get; set; }
```

#### 5. CommissionPayoutHistory
```csharp
// قبل
public string WeekNumber { get; set; }

// بعد
public long WeekDefinitionId { get; set; }
public virtual WeekDefinition WeekDefinition { get; set; }
```

### EF Configurations

**فایل‌های آپدیت شده**:
- `NetworkWeeklyBalanceConfiguration.cs` - Index و FK
- `WeeklyCommissionPoolConfiguration.cs` - Index و FK
- `UserCommissionPayoutConfiguration.cs` - Index و FK
- `WorkerExecutionLogConfiguration.cs` - Index و FK
- `CommissionPayoutHistoryConfiguration.cs` - Index و FK

**نمونه تغییرات**:
```csharp
// حذف Index قدیمی
builder.HasIndex(e => e.WeekNumber);

// اضافه کردن FK جدید
builder.HasIndex(e => e.WeekDefinitionId);
builder.HasOne(e => e.WeekDefinition)
    .WithMany()
    .HasForeignKey(e => e.WeekDefinitionId)
    .OnDelete(DeleteBehavior.Restrict);
```

### Proto Files (commission.proto)

#### UserCommissionPayoutModel
```protobuf
// قبل
string week_number = 4;

// بعد
int64 week_definition_id = 4;
string week_display_name = 11; // فیلد جدید
```

#### UserWeeklyBalanceModel
```protobuf
// قبل
string week_number = 2;

// بعد
int64 week_definition_id = 2;
string week_display_name = 10; // فیلد جدید
```

### Handlers & Mapping Profiles

**فایل‌های آپدیت شده**:
- `GetAllUserCommissionPayoutsQueryHandler.cs`
- `GetUserWeeklyBalancesQueryHandler.cs`
- `CommissionProfile.cs`

**تغییرات Mapping**:
```csharp
// استفاده از WeekDefinition برای ساخت WeekDisplayName
.Map(dest => dest.WeekDisplayName, 
     src => $"هفته {src.WeekDefinition.WeekOrder} - {src.WeekDefinition.StartDatePersian}")
```

---

## 🔗 BackOffice.BFF

### Proto Files (commission.proto)

#### WeekInfo
```protobuf
// اضافه شد
int64 week_definition_id = 1;  // جدید - برای انتخاب هفته
string display_name = 2;        // تغییر نام از week_number
```

#### WeeklyCommissionPoolModel
```protobuf
// اضافه شد
string week_display_name = 3;   // جدید
```

#### WorkerExecutionLogModel
```protobuf
// اضافه شد
string week_display_name = 3;   // جدید
```

### Application DTOs

**GetAvailableWeeksResponseDto.cs**:
```csharp
public class WeekInfoDto
{
    public long WeekDefinitionId { get; set; }  // جدید
    public string DisplayName { get; set; }
    ...
}
```

**GetAllWeeklyPoolsResponseDto.cs**:
```csharp
public record WeeklyCommissionPoolDto
{
    public string WeekDisplayName { get; init; }  // جدید
    ...
}
```

**GetWorkerExecutionLogsResponseDto.cs**:
```csharp
public class WorkerExecutionLogModel
{
    public string WeekDisplayName { get; set; }  // جدید
    ...
}
```

### Mapping Profiles (CommissionProfile.cs)

```csharp
// WeekInfo mapping
.Map(dest => dest.WeekDefinitionId, src => src.WeekDefinitionId)

// WeeklyCommissionPoolModel mapping
WeekDisplayName = m.WeekDisplayName ?? string.Empty,

// WeeklyBalanceModel mapping
WeekDisplayName = m.WeekDisplayName ?? string.Empty,
```

---

## 🖥️ BackOffice Admin (Blazor)

### Project Reference

**BackOffice.csproj**:
```xml
<!-- تغییر از PackageReference به ProjectReference برای 23 proto پروژه -->
<ProjectReference Include="..\..\..\..\BackOffice.BFF\src\Protobufs\BackOffice.BFF.Commission.Protobuf\..." />
<!-- و 22 proto پروژه دیگر -->
```

### Components Updated

#### WeekNumberPicker.razor.cs
```csharp
// قبل - فقط string binding
[Parameter] public string? SelectedWeekNumber { get; set; }

// بعد - dual binding support
[Parameter] public string? SelectedWeekNumber { get; set; }      // for DisplayName
[Parameter] public long? SelectedWeekDefinitionId { get; set; }  // for API calls
```

#### Dashboard.razor.cs
```csharp
// قبل
private string _selectedWeek = "";

// بعد
private long? _selectedWeekDefinitionId;
private WeekInfo? _selectedWeek;
private string _currentWeekDisplayName = string.Empty;
```

#### UserPayouts.razor.cs
```csharp
// قبل
private string _filterWeekNumber = "";

// بعد
private long? _filterWeekDefinitionId;
```

#### BalancesReport.razor
```csharp
// قبل
private string _filterWeekNumber = "";
public string WeekNumber { get; set; }

// بعد
private long? _filterWeekDefinitionId;
public string WeekDisplayName { get; set; }
```

#### WeeklyReports.razor
```csharp
// قبل
public string WeekNumber { get; set; }

// بعد
public long WeekDefinitionId { get; set; }
public string WeekDisplayName { get; set; }
```

#### SystemOverview.razor
```csharp
// قبل
private string _currentWeek = "";

// بعد
private long _currentWeekDefinitionId = 0;
private string _currentWeekDisplayName = string.Empty;
```

#### WorkerControl.razor
```csharp
// قبل
public string WeekNumber { get; set; }

// بعد
public long WeekDefinitionId { get; set; }
public string WeekDisplayName { get; set; }
```

#### PayoutDetailsDialog.razor
```razor
<!-- قبل -->
@Payout.WeekNumber

<!-- بعد -->
@Payout.WeekDisplayName
```

---

## 🔗 FrontOffice.BFF

### Proto Files

#### commission.proto
```protobuf
message UserCommissionPayoutModel {
    int64 week_definition_id = 4;  // تغییر از week_number
    string week_display_name = 11; // جدید
}
message UserWeeklyBalanceModel {
    int64 week_definition_id = 2;  // تغییر از week_number
    string week_display_name = 10; // جدید
}
```

#### userwallet.proto
```protobuf
message UserWithdrawalModel {
    int64 week_definition_id = 2;   // تغییر از week_number
    string week_display_name = 3;   // تغییر از week_label
}
```

### Application DTOs

**GetMyCommissionPayoutsResponseDto.cs**:
```csharp
public class CommissionPayoutItem
{
    // حذف
    public int WeekNumber { get; set; }
    public string WeekLabel { get; set; }
    
    // اضافه
    public long WeekDefinitionId { get; set; }
    public string WeekDisplayName { get; set; }
}
```

**GetMyWeeklyBalancesResponseDto.cs**:
```csharp
public class WeeklyBalanceItem
{
    // حذف
    public int WeekNumber { get; set; }
    public string WeekLabel { get; set; }
    
    // اضافه
    public long WeekDefinitionId { get; set; }
    public string WeekDisplayName { get; set; }
}
```

### Handlers

**GetMyCommissionPayoutsQueryHandler.cs**:
- Mapping از `WeekDefinitionId` و `WeekDisplayName`

**GetMyWeeklyBalancesQueryHandler.cs**:
- Mapping از `WeekDefinitionId` و `WeekDisplayName`

---

## 🖥️ FrontOffice (Blazor)

### DTOs (CommissionDtos.cs)

```csharp
// قبل
public record CommissionPayoutDto(
    int WeekNumber,
    string WeekLabel,
    ...
);

// بعد
public record CommissionPayoutDto(
    long WeekDefinitionId,
    string WeekDisplayName,
    ...
);
```

```csharp
// قبل
public record WeeklyBalanceDto(
    int WeekNumber,
    string WeekLabel,
    ...
);

// بعد
public record WeeklyBalanceDto(
    long WeekDefinitionId,
    string WeekDisplayName,
    ...
);
```

```csharp
// قبل
public record WeekDefinitionDto(
    ...
    string GregorianWeekNumber,
    string PersianWeekNumber
);

// بعد
public record WeekDefinitionDto(
    long Id,
    ...
    // حذف GregorianWeekNumber و PersianWeekNumber
);
```

### Services (CommissionService.cs)

```csharp
// قبل
public async Task<...> GetMyCommissionPayoutsAsync(int? weekNumber, ...)

// بعد
public async Task<...> GetMyCommissionPayoutsAsync(long? weekDefinitionId, ...)
```

```csharp
// قبل
public async Task<WeeklyBalanceDto?> GetMyWeeklyBalanceAsync(string? weekNumber)

// بعد
public async Task<WeeklyBalanceDto?> GetMyWeeklyBalanceAsync(long? weekDefinitionId)
```

**حذف متد**: `ExtractWeekNumber(string)`

### Services (WalletService.cs)

```csharp
// قبل
public record WalletWithdrawal(
    long Id, 
    string WeekNumber, 
    ...
);

// بعد
public record WalletWithdrawal(
    long Id,
    long WeekDefinitionId,
    string WeekDisplayName,
    ...
);
```

### Components

#### WeekSelector.razor.cs
```csharp
// حذف
public WeekDefinitionDto? FindByGregorianWeekNumber(string weekNumber)

// اضافه
public WeekDefinitionDto? FindById(long id)
```

#### WeeklyBalancePage.razor.cs
```csharp
// استفاده از Id به جای GregorianWeekNumber
_selectedWeekDefinition = _weekSelector?.FindById(id);
```

### Razor Templates

#### CommissionDashboardPage.razor
```razor
<!-- قبل -->
<MudChip>@context.WeekLabel</MudChip>
Href="?week={context.WeekNumber}"

<!-- بعد -->
<MudChip>@context.WeekDisplayName</MudChip>
Href="?week={context.WeekDefinitionId}"
```

#### CommissionHistoryPage.razor
```razor
<!-- قبل -->
<MudChip>@context.WeekLabel</MudChip>
Href="?week={context.WeekNumber}"

<!-- بعد -->
<MudChip>@context.WeekDisplayName</MudChip>
Href="?week={context.WeekDefinitionId}"
```

#### WeeklyBalancePage.razor
```razor
<!-- قبل -->
<MudText>@_weeklyBalance.WeekLabel</MudText>

<!-- بعد -->
<MudText>@_weeklyBalance.WeekDisplayName</MudText>
```

#### WithdrawalRequests.razor
```razor
<!-- قبل -->
<MudTd>@context.WeekNumber</MudTd>
<MudText>هفته @wd.WeekNumber</MudText>

<!-- بعد -->
<MudTd>@context.WeekDisplayName</MudTd>
<MudText>@wd.WeekDisplayName</MudText>
```

### Project Reference

**FrontOffice.Main.csproj**:
```xml
<!-- کامنت شد (NuGet قدیمی) -->
<!-- <PackageReference Include="Foursat.FrontOffice.BFF.UserWallet.Protobuf" Version="0.0.15" /> -->

<!-- اضافه شد (ProjectReference برای proto جدید) -->
<ProjectReference Include="...FrontOffice.BFF.UserWallet.Protobuf.csproj" />
```

---

## 📊 خلاصه فایل‌های تغییریافته

### CMS (15+ فایل):
| فایل | تغییر |
|------|-------|
| `NetworkWeeklyBalance.cs` | Entity + FK |
| `WeeklyCommissionPool.cs` | Entity + FK |
| `UserCommissionPayout.cs` | Entity + FK |
| `WorkerExecutionLog.cs` | Entity + FK (nullable) |
| `CommissionPayoutHistory.cs` | Entity + FK |
| `NetworkWeeklyBalanceConfiguration.cs` | EF Config |
| `WeeklyCommissionPoolConfiguration.cs` | EF Config |
| `UserCommissionPayoutConfiguration.cs` | EF Config |
| `WorkerExecutionLogConfiguration.cs` | EF Config |
| `CommissionPayoutHistoryConfiguration.cs` | EF Config |
| `commission.proto` | Proto models (WeeklyCommissionPoolModel, WorkerExecutionLogModel) |
| `CommissionProfile.cs` | Mapster mapping |
| `GetAllUserCommissionPayoutsQueryHandler.cs` | Include WeekDefinition |
| `GetUserWeeklyBalancesQueryHandler.cs` | Include WeekDefinition |
| `GetAvailableWeeksQueryHandler.cs` | WeekDefinitionId in WeekInfo |

### BackOffice.BFF (8 فایل):
| فایل | تغییر |
|------|-------|
| `commission.proto` | WeekInfo, WeeklyCommissionPoolModel, WorkerExecutionLogModel |
| `GetAvailableWeeksResponseDto.cs` | WeekDefinitionId in WeekInfoDto |
| `GetAllWeeklyPoolsResponseDto.cs` | WeekDisplayName |
| `GetWorkerExecutionLogsResponseDto.cs` | WeekDisplayName |
| `GetAvailableWeeksQueryHandler.cs` | Mapping WeekDefinitionId |
| `CommissionProfile.cs` | Mapster config for new fields |

### BackOffice Admin (12 فایل):
| فایل | تغییر |
|------|-------|
| `BackOffice.csproj` | 23 ProjectReference به جای PackageReference |
| `WeekNumberPicker.razor.cs` | Dual binding (string + long) |
| `Dashboard.razor` | WeekDefinitionId selector |
| `Dashboard.razor.cs` | _selectedWeekDefinitionId, _currentWeekDisplayName |
| `UserPayouts.razor` | WeekDisplayName column |
| `UserPayouts.razor.cs` | _filterWeekDefinitionId |
| `BalancesReport.razor` | WeekDisplayName column, filter |
| `WeeklyReports.razor` | WeekDefinitionId, WeekDisplayName |
| `SystemOverview.razor` | _currentWeekDisplayName |
| `WorkerControl.razor` | WeekDisplayName in logs |
| `PayoutDetailsDialog.razor` | WeekDisplayName |

### FrontOffice.BFF (8 فایل):
| فایل | تغییر |
|------|-------|
| `commission.proto` | week_definition_id, week_display_name |
| `userwallet.proto` | week_definition_id, week_display_name |
| `GetMyCommissionPayoutsResponseDto.cs` | DTO fields |
| `GetMyWeeklyBalancesResponseDto.cs` | DTO fields |
| `GetUserWithdrawalsResponseDto.cs` | DTO fields |
| `GetMyCommissionPayoutsQueryHandler.cs` | Mapping |
| `GetMyWeeklyBalancesQueryHandler.cs` | Mapping |
| `CommissionProfile.cs` | Mapster config |

### FrontOffice (12 فایل):
| فایل | تغییر |
|------|-------|
| `CommissionDtos.cs` | DTOs |
| `CommissionService.cs` | Service methods |
| `WalletService.cs` | WalletWithdrawal record |
| `WeekSelector.razor` | UI |
| `WeekSelector.razor.cs` | FindById method |
| `WeeklyBalancePage.razor` | WeekDisplayName |
| `WeeklyBalancePage.razor.cs` | WeekDefinitionId |
| `CommissionDashboardPage.razor` | Links & display |
| `CommissionHistoryPage.razor` | Links & display |
| `WithdrawalRequests.razor` | WeekDisplayName |
| `FrontOffice.Main.csproj` | ProjectReference |

---

## ⚠️ نکات مهم

### Migration مورد نیاز
قبل از deploy، باید EF migration اجرا شود:
```bash
cd CMS/src
dotnet ef migrations add MigrateWeekNumberToWeekDefinitionId -p CMSMicroservice.Infrastructure -s CMSMicroservice.WebApi
dotnet ef database update -p CMSMicroservice.Infrastructure -s CMSMicroservice.WebApi
```

### Data Migration
داده‌های موجود باید migrate شوند:
```sql
-- مثال برای NetworkWeeklyBalance
UPDATE NetworkWeeklyBalances 
SET WeekDefinitionId = (
    SELECT Id FROM WeekDefinitions 
    WHERE CONCAT(Year, '-', LPAD(WeekOrder, 2, '0')) = NetworkWeeklyBalances.WeekNumber
)
WHERE WeekDefinitionId IS NULL;
```

### FK Constraint
جدول `WorkerExecutionLogs` ممکن است رکوردهایی با `WeekNumber` نامعتبر داشته باشد که باید قبل از اعمال FK constraint اصلاح شوند.

---

## ✅ وضعیت Build

| پروژه | وضعیت |
|-------|--------|
| CMS | ✅ Build Succeeded |
| BackOffice.BFF | ✅ Build Succeeded |
| BackOffice Admin | ✅ Build Succeeded |
| FrontOffice.BFF | ✅ Build Succeeded |
| FrontOffice | ✅ Build Succeeded |

---

## 🔄 تغییرات Proto NuGet

برای publish نهایی، باید proto packageها آپدیت شوند:
1. `Foursat.CMSMicroservice.Protobuf` → ورژن جدید
2. `Foursat.BackOffice.BFF.Commission.Protobuf` → ورژن جدید
3. `Foursat.FrontOffice.BFF.Commission.Protobuf` → ورژن جدید
4. `Foursat.FrontOffice.BFF.UserWallet.Protobuf` → ورژن جدید

---

## 📝 نکته مهم درباره ProjectReference

در این سشن، برای BackOffice Admin و FrontOffice، تمام `PackageReference` های proto به `ProjectReference` تغییر داده شدند تا تغییرات proto بدون نیاز به publish فوری قابل تست باشند.
