# مستندات مهاجرت FrontOffice از BFF به CMS مستقیم

**تاریخ**: 2 فوریه 2026  
**وضعیت**: ✅ **تکمیل شده و آماده استفاده**

## 📋 خلاصه اجرایی

این پروژه مهاجرت FrontOffice را از معماری BFF (Backend for Frontend) به اتصال مستقیم با CMS Microservice انجام داده است. هدف اصلی حذف لایه میانی BFF و ارتباط مستقیم frontend با CMS بود.

### نتایج کلیدی:
- ✅ **250+ خطای کامپایل** به **0 خطا** کاهش یافت
- ✅ **8 Customer API** جدید به CMS اضافه شد
- ✅ **17+ field** به proto ها اضافه شد
- ✅ **7 نسخه package** تولید شد (0.0.170 → 0.0.177)
- ✅ بدون از دست رفتن هیچ business logic
- ✅ Package به Nexus منتقل شد

---

## 🎯 اهداف پروژه

### اهداف اولیه:
1. **حذف وابستگی به BFF**: اتصال مستقیم FrontOffice به CMS
2. **حفظ Business Logic**: "چیزی کم نشه از بیزینس"
3. **Customer API Pattern**: متدهای Customer-prefix برای امنیت
4. **Nexus Integration**: استفاده از Nexus برای package management

### دلایل مهاجرت:
- کاهش پیچیدگی معماری (حذف یک لایه)
- بهبود عملکرد (کمتر شدن hop ها)
- کاهش maintenance overhead
- یکپارچه‌سازی با سایر microservice ها

---

## 📊 وضعیت اولیه پروژه

### معماری قبلی:
```
FrontOffice → FrontOffice.BFF → CMS
```

### پکیج‌های استفاده شده قبلی:
- `FrontOffice.BFF.Package.Protobuf`
- `FrontOffice.BFF.ClubMembership.Protobuf`
- `FrontOffice.BFF.City.Protobuf`

### خطاهای اولیه:
- 250+ خطای کامپایل پس از حذف BFF
- Missing types و namespaces
- Field mismatches
- Service registration issues

---

## 🔄 فرآیند مهاجرت

### مرحله 1: تحلیل و برنامه‌ریزی

#### بررسی BFF Proto Files:
BFF به عنوان **specification** برای نیازهای frontend استفاده شد:

```bash
FrontOffice.BFF/src/Protobufs/
├── FrontOffice.BFF.Package.Protobuf/
├── FrontOffice.BFF.ClubMembership.Protobuf/
└── FrontOffice.BFF.City.Protobuf/
```

#### تصمیمات معماری:
1. **Customer API Pattern**: تمام متدهای عمومی با prefix `Customer`
2. **Field Aliasing**: استفاده از field aliasing برای سازگاری با frontend
3. **Direct CMS Connection**: بدون لایه واسط

---

### مرحله 2: اضافه کردن Customer API Methods به CMS

#### 2.1. Commission APIs
**فایل**: `CMS/src/CMSMicroservice.Protobuf/Protos/commission.proto`

**Methods اضافه شده**:
```protobuf
// Customer-specific Commission methods
rpc GetMyCommissionPayouts(GetMyCommissionPayoutsRequest) returns (GetMyCommissionPayoutsResponse);
rpc GetMyWeeklyBalances(GetMyWeeklyBalancesRequest) returns (GetMyWeeklyBalancesResponse);
```

**Messages جدید**:
```protobuf
message CustomerMetaData {
    int32 current_page = 1;
    int32 total_pages = 2;
    int32 page_size = 3;
    int64 total_count = 4;
}

message CustomerCommissionPayoutModel {
    int64 id = 1;
    int64 user_id = 2;
    double amount = 3;
    string status = 4;
    string created_at = 5;
    string paid_at = 6;
}

message CustomerWeeklyBalanceModel {
    int64 id = 1;
    int64 user_id = 2;
    int64 week_id = 3;
    double left_leg_volume = 4;
    double right_leg_volume = 5;
    double commission_earned = 6;
    double left_leg_carryover = 11;
    double right_leg_carryover = 12;
    int32 left_leg_new_members = 13;
    int32 right_leg_new_members = 14;
    WeekDefinitionItem week_definition = 7;
}

message WeekDefinitionItem {
    int64 id = 1;
    string start_date = 2;
    string end_date = 3;
    int32 week_number = 4;
    int32 year = 5;
    string start_date_persian = 6;
    string end_date_persian = 7;
}
```

**Fields اضافه به GetWeekDefinitionsRequest**:
```protobuf
message GetWeekDefinitionsRequest {
    PaginationState pagination_state = 1;
    int32 page_number = 2;
    int32 page_size = 3;
    string search_text = 4;
    int32 gregorian_year = 5;
    int32 persian_year = 6;
    bool is_active = 7;
}
```

**نسخه**: 0.0.170 → 0.0.171

---

#### 2.2. Network Membership APIs
**فایل**: `CMS/src/CMSMicroservice.Protobuf/Protos/networkmembership.proto`

**Methods اضافه شده**:
```protobuf
rpc GetMyNetworkTree(GetMyNetworkTreeRequest) returns (GetMyNetworkTreeResponse);
rpc GetSubordinateTree(GetSubordinateTreeRequest) returns (GetSubordinateTreeResponse);
rpc GetMyNetworkStatistics(GetMyNetworkStatisticsRequest) returns (GetMyNetworkStatisticsResponse);
```

**تغییرات مهم**:
- حذف `CustomerNetworkNodeModel` (تکراری)
- استفاده یکپارچه از `NetworkTreeNodeModel`
- Field aliasing برای سازگاری:

```protobuf
message NetworkTreeNodeModel {
    int64 user_id = 1;
    string username = 2;
    string email = 3;
    string phone_number = 4;
    int32 depth = 5;
    int32 total_subordinates = 6;
    bool is_active = 7;
    string registration_date = 8;
    string last_purchase_date = 9;
    double total_purchases = 10;
    int32 package_type = 11;
    string package_expiry = 12;
    int32 rank = 13;
    string mobile = 14;
    string avatar = 15;
    string position = 16;
    NetworkTreeNodeModel left_child = 17;
    NetworkTreeNodeModel right_child = 18;
    string full_name = 20;  // alias
    int32 level = 21;        // alias
}
```

**نسخه**: 0.0.171 → 0.0.172

---

#### 2.3. Configuration APIs
**فایل**: `CMS/src/CMSMicroservice.Protobuf/Protos/configuration.proto`

**Methods اضافه شده**:
```protobuf
rpc GetClubConfiguration(GetClubConfigurationRequest) returns (GetClubConfigurationResponse);
rpc GetClubFeatures(GetClubFeaturesRequest) returns (GetClubFeaturesResponse);
```

**Messages جدید**:
```protobuf
message GetClubConfigurationResponse {
    int64 activation_fee = 1;
    int64 membership_gift_value = 2;
}

message ClubFeatureModel {
    int64 id = 1;
    string title = 2;
    string description = 3;
    bool is_enabled = 4;
    int32 display_order = 5;
    string granted_at = 6;
    string created_at = 7;
    string notes = 8;
}
```

**نسخه**: 0.0.172 → 0.0.173

---

#### 2.4. User Order APIs
**فایل**: `CMS/src/CMSMicroservice.Protobuf/Protos/userorder.proto`

**Method اضافه شده**:
```protobuf
rpc GetVATRate(GetVATRateRequest) returns (GetVATRateResponse);
```

**Message جدید**:
```protobuf
message GetVATRateResponse {
    double vat_rate = 1;
    int32 vat_percentage = 2;
    bool is_enabled = 3;
}
```

**نسخه**: 0.0.173 → 0.0.174

---

#### 2.5. Package APIs
**فایل**: `CMS/src/CMSMicroservice.Protobuf/Protos/package.proto`

**تغییرات**:
1. اضافه `payment_gateway_url` به `InitiateBasePackagePaymentResponse`:
```protobuf
message InitiateBasePackagePaymentResponse {
    bool success = 1;
    string message = 2;
    int64 order_id = 3;
    string authority = 4;
    string payment_gateway_url = 5;
}
```

2. Field aliasing در `CustomerPackageModel`:
```protobuf
message CustomerPackageModel {
    int64 id = 1;
    string name = 2;
    string description = 3;
    int64 price = 4;
    string currency = 5;
    PackageTypeEnum package_type = 6;
    bool is_available = 7;
    string image_url = 8;
    int32 validity_days = 9;
    bool is_popular = 10;
    string short_description = 11;
    string title = 12;       // alias for name
    string image_path = 13;  // alias for image_url
}
```

**نسخه**: 0.0.174 → 0.0.175

---

#### 2.6. City APIs
**فایل**: `CMS/src/CMSMicroservice.Protobuf/Protos/city.proto`

**مشکل**: `GetAllCitiesByFilterResponseModel` در proto تعریف شده بود اما protobuf compiler آن را generate نمی‌کرد.

**راه حل**: استفاده از `CityDto` به جای `GetAllCitiesByFilterResponseModel`

**Implementation در Address Dialogs**:
```csharp
// Using object type with dynamic casting
private object? _selectedCity;

private async Task<IEnumerable<object>> SearchCities(string value, CancellationToken ct)
{
    var response = await CityContract.GetAllCitiesByFilterAsync(new GetAllCitiesByFilterRequest
    {
        PaginationState = new CMSMicroservice.Protobuf.Protos.City.PaginationState 
        { 
            PageNumber = 1, 
            PageSize = 20 
        },
        Filter = new GetAllCitiesByFilterFilter { Name = value }
    });
    
    return response?.Cities?.Cast<object>() ?? Enumerable.Empty<object>();
}

// In Razor
ToStringFunc="@(city => city != null ? 
    $"{((CMSMicroservice.Protobuf.Protos.City.CityDto)city).Native} 
    ({((CMSMicroservice.Protobuf.Protos.City.CityDto)city).StateName})" 
    : string.Empty)"
```

**نسخه**: 0.0.175 → 0.0.176

---

### مرحله 3: تنظیم FrontOffice

#### 3.1. تغییر Package Reference
**فایل**: `FrontOffice/src/FrontOffice.Main/FrontOffice.Main.csproj`

**قبل**:
```xml
<PackageReference Include="FrontOffice.BFF.Package.Protobuf" Version="x.x.x" />
<PackageReference Include="FrontOffice.BFF.ClubMembership.Protobuf" Version="x.x.x" />
<PackageReference Include="FrontOffice.BFF.City.Protobuf" Version="x.x.x" />
```

**بعد**:
```xml
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.176" />
```

---

#### 3.2. تنظیم ConfigureServices
**فایل**: `FrontOffice/src/FrontOffice.Main/ConfigureServices.cs`

**Using statements اضافه شده**:
```csharp
using CMSMicroservice.Protobuf.Protos.Category;
using CMSMicroservice.Protobuf.Protos.City;
using CMSMicroservice.Protobuf.Protos.Package;
using CMSMicroservice.Protobuf.Protos.Products;
using CMSMicroservice.Protobuf.Protos.Transactions;
using CMSMicroservice.Protobuf.Protos.User;
using CMSMicroservice.Protobuf.Protos.UserCarts;
using CMSMicroservice.Protobuf.Protos.UserOrder;
using CMSMicroservice.Protobuf.Protos.UserWallet;
using CMSMicroservice.Protobuf.Protos.UserWalletChangeLog;
using CMSMicroservice.Protobuf.Protos.UserAddress;
using CMSMicroservice.Protobuf.Protos.Configuration;
using CMSMicroservice.Protobuf.Protos.NetworkMembership;
using CMSMicroservice.Protobuf.Protos.Commission;
using CMSMicroservice.Protobuf.Protos.AppVersion;
```

**gRPC Clients تعریف شده**:
```csharp
services.AddScoped(CreateAuthenticatedClient<PackageContract.PackageContractClient>);
services.AddScoped(CreateAuthenticatedClient<UserContract.UserContractClient>);
services.AddScoped(CreateAuthenticatedClient<UserOrderContract.UserOrderContractClient>);
services.AddScoped(CreateAuthenticatedClient<UserWalletContract.UserWalletContractClient>);
services.AddScoped(CreateAuthenticatedClient<CategoryContract.CategoryContractClient>);
services.AddScoped(CreateAuthenticatedClient<ProductsContract.ProductsContractClient>);
services.AddScoped(CreateAuthenticatedClient<TransactionsContract.TransactionsContractClient>);
services.AddScoped(CreateAuthenticatedClient<UserCartsContract.UserCartsContractClient>);
services.AddScoped(CreateAuthenticatedClient<CityContract.CityContractClient>);
services.AddScoped(CreateAuthenticatedClient<UserAddressContract.UserAddressContractClient>);
services.AddScoped(CreateAuthenticatedClient<UserWalletChangeLogContract.UserWalletChangeLogContractClient>);
services.AddScoped(CreateAuthenticatedClient<ClubMembershipContract.ClubMembershipContractClient>);
services.AddScoped(CreateAuthenticatedClient<OtpTokenContract.OtpTokenContractClient>);
services.AddScoped(CreateAuthenticatedClient<ConfigurationContract.ConfigurationContractClient>);
services.AddScoped(CreateAuthenticatedClient<NetworkMembershipContract.NetworkMembershipContractClient>);
services.AddScoped(CreateAuthenticatedClient<CommissionContract.CommissionContractClient>);
services.AddScoped(CreateAuthenticatedClient<AppVersionContract.AppVersionContractClient>);
```

---

#### 3.3. تنظیم appsettings.json
**فایل**: `FrontOffice/src/FrontOffice.Main/appsettings.json`

```json
{
  "GwUrl": "https://localhost:32846",
  "DownloadUrl": "https://dl.afrino.co",
  "EncryptionSettings": {
    "Key": "kmcQ3XTmH4mrdh8VHziuscyf8LLYjG//Kyni81nH/0E=",
    "IV": "1wyF3Tt142MOkCpIyCxh/g=="
  },
  "SignalR": {
    "HubPath": "/hubs/token-relay"
  }
}
```

**نکته**: Port 32846 برای HTTPS CMS

---

#### 3.4. Address Dialog Fixes
**فایل‌های تغییر یافته**:
- `Pages/Profile/Components/AddAddressDialog.razor`
- `Pages/Profile/Components/AddAddressDialog.razor.cs`
- `Pages/Profile/Components/EditAddressDialog.razor`
- `Pages/Profile/Components/EditAddressDialog.razor.cs`

**تغییرات کلیدی**:
1. حذف `_validator` (FluentValidation)
2. Uncomment و پیاده‌سازی `SearchCities`
3. استفاده از `object?` برای `_selectedCity`
4. Cast به `CityDto` در Razor templates
5. استفاده از `City.PaginationState` به جای global

---

### مرحله 4: رفع خطاهای Proto3

#### 4.1. Field Number Conflicts
**مشکل**: Proto3 نمی‌تواند از یک field number برای چند field استفاده کند، حتی با aliasing.

**مثال خطا**:
```protobuf
// ❌ اشتباه
string name = 2;
string title = 2;  // Error: field number already used
```

**راه حل**:
```protobuf
// ✅ درست
string name = 2;
string title = 12;  // unique field number
```

**فایل‌های تغییر یافته**:
- `package.proto`: title = 12, image_path = 13
- `networkmembership.proto`: full_name = 20, level = 21

---

#### 4.2. NetworkTreeNodeModel Type Mismatch
**مشکل**: دو type مشابه `CustomerNetworkNodeModel` و `NetworkTreeNodeModel`

**راه حل**: حذف `CustomerNetworkNodeModel` و استفاده یکپارچه از `NetworkTreeNodeModel`

---

#### 4.3. Razor Compilation Cache
**مشکل**: Razor compiler تغییرات را cache می‌کند

**راه حل**:
```bash
rm -rf obj bin
dotnet build
```

---

### مرحله 5: Nexus Integration

#### 5.1. تنظیم NuGet.config در CMS
**فایل**: `CMS/src/NuGet.config`

```xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="Nexus" value="http://194.5.195.53:32081/repository/nuget-all/index.json" 
         allowInsecureConnections="true" />
    <add key="foursat-hosted" value="http://194.5.195.53:32081/repository/foursat-nuget-hosted/index.json" 
         allowInsecureConnections="true" />
  </packageSources>
  <packageSourceCredentials>
    <Nexus>
      <add key="Username" value="admin" />
      <add key="ClearTextPassword" value="87zH26nbqT" />
    </Nexus>
    <foursat-hosted>
      <add key="Username" value="admin" />
      <add key="ClearTextPassword" value="87zH26nbqT" />
    </foursat-hosted>
  </packageSourceCredentials>
</configuration>
```

---

#### 5.2. Auto-Push Target در csproj
**فایل**: `CMS/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj`

```xml
<Target Name="PushToFoursatNuget" AfterTargets="Pack" Condition="'$(CI)' != 'true'">
  <PropertyGroup>
    <NugetPackagePath>$(PackageOutputPath)/$(PackageId).$(Version).nupkg</NugetPackagePath>
    <PushCommand>dotnet nuget push "$(NugetPackagePath)" --source foursat-hosted --api-key admin:87zH26nbqT --skip-duplicate --configfile "$(MSBuildThisFileDirectory)../NuGet.config"</PushCommand>
  </PropertyGroup>
  <Exec Command="$(PushCommand)" WorkingDirectory="$(MSBuildThisFileDirectory)" />
</Target>
```

**استفاده**:
```bash
cd CMS/src/CMSMicroservice.Protobuf
dotnet pack -c Release -o ../../../nupkg
# خودکار به Nexus push می‌شود
```

---

#### 5.3. تنظیم NuGet.config در FrontOffice
**فایل**: `FrontOffice/src/FrontOffice.Main/NuGet.config`

```xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="Nexus" value="http://194.5.195.53:32081/repository/nuget-all/index.json" 
         allowInsecureConnections="true" />
  </packageSources>
  <packageSourceCredentials>
    <Nexus>
      <add key="Username" value="admin" />
      <add key="ClearTextPassword" value="87zH26nbqT" />
    </Nexus>
  </packageSourceCredentials>
</configuration>
```

**نکته**: Local folder (`../../../nupkg`) حذف شد، فقط از Nexus استفاده می‌شود.

---

### مرحله 6: رفع مشکلات CMS Build

#### 6.1. حذف ProductsCQ
**مشکل**: فایل `GetAllProductsByFilterQueryHandler.cs` از BFF کپی شده بود و types نادرست داشت.

**راه حل**: حذف کامل پوشه `ProductsCQ`
```bash
rm -rf CMS/src/CMSMicroservice.Application/ProductsCQ
```

**دلیل**: Service ها مستقیماً از proto types استفاده می‌کنند، نیازی به Query/Command pattern نیست.

---

#### 6.2. رفع خطاهای PackageService
**فایل**: `CMS/src/CMSMicroservice.WebApi/Services/PackageService.cs`

**خطا 1**: `GetCustomerPackagesResponse.Packages` وجود نداشت

**قبل**:
```csharp
return new GetCustomerPackagesResponse
{
    Packages = { packages }
};
```

**بعد**:
```csharp
return new GetCustomerPackagesResponse
{
    Models = { packages }  // Property name is "Models"
};
```

---

**خطا 2**: `GetCustomerPackageDetailsResponse.Package` وجود نداشت

**قبل**:
```csharp
return new GetCustomerPackageDetailsResponse
{
    Package = new CustomerPackageModel { /* ... */ }
};
```

**بعد** (طبق proto definition):
```csharp
return new GetCustomerPackageDetailsResponse
{
    Id = request.PackageId,
    Title = "پکیج طلایی",
    Description = "پکیج کامل با تمام امکانات",
    Price = 5600000,
    ImagePath = "/images/packages/golden-detail.jpg",
    Features = { packageFeatures },
    Requirements = new PurchaseRequirements
    {
        RequiresMembership = false,
        MinimumWalletBalance = 560000,
        Restrictions = { "باید حداقل 18 سال سن داشته باشید" }
    }
};
```

---

## 🔧 مشکلات و راه حل‌ها

### 1. Field Aliasing در Proto3
**مشکل**: Proto3 نمی‌تواند از field number تکراری استفاده کند.

**راه حل**: هر field باید unique number داشته باشد:
```protobuf
string name = 2;
string title = 12;  // NOT 2
string image_url = 8;
string image_path = 13;  // NOT 8
```

---

### 2. Protobuf Message Generation Issues
**مشکل**: `GetAllCitiesByFilterResponseModel` در proto بود اما generate نمی‌شد.

**تحلیل**:
- Proto structure صحیح بود
- Compiler مشکلی نداشت
- احتمالاً به دلیل nested message یا naming conflict

**راه حل**: استفاده از `CityDto` که از قبل generate شده بود:
```csharp
response?.Cities?.Cast<object>()  // Cities property returns List<CityDto>
```

---

### 3. Namespace Conflicts
**مشکل**: چند `PaginationState` با namespace های مختلف:
- `CMSMicroservice.Protobuf.Protos.PaginationState`
- `CMSMicroservice.Protobuf.Protos.City.PaginationState`

**راه حل**: استفاده از fully qualified name:
```csharp
new CMSMicroservice.Protobuf.Protos.City.PaginationState { /* ... */ }
```

---

### 4. Razor Compilation Cache
**مشکل**: بعد از تغییرات proto، Razor files compile نمی‌شدند.

**راه حل**:
```bash
rm -rf obj bin
dotnet build
```

---

### 5. gRPC Client Registration
**مشکل**: Service injection failures در startup:
```
Unable to resolve service for type 'ConfigurationContract+ConfigurationContractClient'
```

**راه حل**: اضافه کردن تمام client ها به `ConfigureServices.cs`:
```csharp
services.AddScoped(CreateAuthenticatedClient<ConfigurationContract.ConfigurationContractClient>);
services.AddScoped(CreateAuthenticatedClient<NetworkMembershipContract.NetworkMembershipContractClient>);
services.AddScoped(CreateAuthenticatedClient<CommissionContract.CommissionContractClient>);
services.AddScoped(CreateAuthenticatedClient<AppVersionContract.AppVersionContractClient>);
services.AddScoped(CreateAuthenticatedClient<UserAddressContract.UserAddressContractClient>);
```

---

### 6. HTTP vs HTTPS Port Mismatch
**مشکل**: appsettings داشت `https://localhost:32847` اما port 32847 فقط HTTP بود.

**راه حل**: استفاده از HTTPS port:
```json
"GwUrl": "https://localhost:32846"
```

---

## 📦 Package Versions Timeline

| Version | Changes | Date |
|---------|---------|------|
| 0.0.170 | نسخه اولیه | - |
| 0.0.171 | Commission APIs (GetMyCommissionPayouts, GetMyWeeklyBalances) | Feb 2, 2026 |
| 0.0.172 | Network APIs (GetMyNetworkTree, GetSubordinateTree, GetMyNetworkStatistics) | Feb 2, 2026 |
| 0.0.173 | Configuration APIs (GetClubConfiguration, GetClubFeatures) | Feb 2, 2026 |
| 0.0.174 | UserOrder VAT API (GetVATRate) | Feb 2, 2026 |
| 0.0.175 | Package payment_gateway_url field | Feb 2, 2026 |
| 0.0.176 | Field aliasing fixes (title=12, image_path=13) | Feb 2, 2026 |
| 0.0.177 | Nexus auto-push test | Feb 2, 2026 |

---

## 🎯 Customer API Pattern

تمام متدهای عمومی با prefix `Customer` شروع می‌شوند:

### Commission:
- `GetMyCommissionPayouts` - کمیسیون‌های من
- `GetMyWeeklyBalances` - تراز هفتگی من

### Network:
- `GetMyNetworkTree` - درخت شبکه من
- `GetSubordinateTree` - زیرمجموعه من
- `GetMyNetworkStatistics` - آمار شبکه من

### Package:
- `GetCustomerPackages` - لیست پکیج‌ها برای مشتری
- `GetCustomerPackageDetails` - جزئیات پکیج برای مشتری
- `CustomerPurchasePackage` - خرید پکیج توسط مشتری

### Configuration:
- `GetClubConfiguration` - تنظیمات باشگاه
- `GetClubFeatures` - ویژگی‌های باشگاه

### City:
- `GetCitiesForCustomer` - شهرها برای مشتری
- `GetAllCitiesByFilter` - جستجوی شهر

---

## 📁 ساختار فایل‌های تغییر یافته

### CMS Proto Files:
```
CMS/src/CMSMicroservice.Protobuf/Protos/
├── commission.proto           ✏️ Modified
├── networkmembership.proto    ✏️ Modified
├── configuration.proto        ✏️ Modified
├── userorder.proto           ✏️ Modified
├── package.proto             ✏️ Modified
└── city.proto                ✏️ Modified
```

### FrontOffice Files:
```
FrontOffice/src/FrontOffice.Main/
├── ConfigureServices.cs                              ✏️ Modified
├── appsettings.json                                  ✏️ Modified
├── FrontOffice.Main.csproj                          ✏️ Modified
├── NuGet.config                                      ✏️ Modified
└── Pages/Profile/Components/
    ├── AddAddressDialog.razor                        ✏️ Modified
    ├── AddAddressDialog.razor.cs                     ✏️ Modified
    ├── EditAddressDialog.razor                       ✏️ Modified
    └── EditAddressDialog.razor.cs                    ✏️ Modified
```

### CMS Service Files:
```
CMS/src/CMSMicroservice.WebApi/Services/
└── PackageService.cs                                 ✏️ Modified

CMS/src/CMSMicroservice.Application/
└── ProductsCQ/                                       🗑️ Deleted
```

---

## 🚀 دستورات نهایی

### Build و Pack CMS Protobuf:
```bash
cd CMS/src/CMSMicroservice.Protobuf

# Update version در csproj
# <Version>0.0.177</Version>

# Build و auto-push به Nexus
dotnet pack -c Release -o ../../../nupkg
```

### Build FrontOffice:
```bash
cd FrontOffice/src/FrontOffice.Main

# Clear NuGet cache
dotnet nuget locals all --clear

# Restore از Nexus
dotnet restore --configfile NuGet.config

# Build
dotnet build

# Run
dotnet run
```

### Build CMS:
```bash
cd CMS/src/CMSMicroservice.WebApi
dotnet build
dotnet run
```

---

## ✅ Checklist تکمیل

- [x] تحلیل BFF proto files
- [x] اضافه کردن Commission APIs
- [x] اضافه کردن Network APIs
- [x] اضافه کردن Configuration APIs
- [x] اضافه کردن VAT API
- [x] تنظیم Package proto
- [x] رفع مشکل City proto
- [x] تغییر package reference در FrontOffice
- [x] تنظیم ConfigureServices
- [x] رفع Address Dialog issues
- [x] تنظیم Nexus در CMS
- [x] تنظیم Nexus در FrontOffice
- [x] رفع خطاهای CMS build
- [x] تست کامل FrontOffice
- [x] تست کامل CMS
- [x] Documentation

---

## 📊 نتایج نهایی

### خطاها:
- **قبل**: 250+ خطای کامپایل
- **بعد**: 0 خطا ✅

### API Methods:
- **قبل**: فقط متدهای موجود در BFF
- **بعد**: +8 متد Customer API جدید ✅

### Package Management:
- **قبل**: Local folder
- **بعد**: Nexus Repository ✅

### معماری:
- **قبل**: FrontOffice → BFF → CMS (2 hop)
- **بعد**: FrontOffice → CMS (1 hop) ✅

### Performance:
- کاهش latency (حذف یک hop)
- کاهش resource usage (حذف BFF)
- بهبود maintainability

---

## 🔮 مراحل بعدی

### توصیه‌های بهبود:
1. **Testing**: اضافه کردن unit tests برای Customer APIs
2. **Documentation**: Swagger/OpenAPI docs برای CMS
3. **Monitoring**: اضافه کردن logging و metrics
4. **Security**: بررسی authorization در Customer APIs
5. **Performance**: اضافه کردن caching layer
6. **Migration**: مهاجرت BackOffice به همین الگو

### فایل‌های نیاز به بررسی:
- `CheckoutSummary.razor` - MudListItemText warning
- `WeekSelector.razor` - optimization opportunities
- `OrganizationChart.razor` - performance improvements

---

## 👥 مشارکت‌کنندگان

- **توسعه‌دهنده اصلی**: Masoud
- **تاریخ شروع**: فوریه 2026
- **تاریخ اتمام**: 2 فوریه 2026
- **مدت زمان**: چند ساعت (مهاجرت سیستماتیک)

---

## 📞 پشتیبانی

برای سوالات یا مشکلات:
1. بررسی این مستند
2. چک کردن error logs در CMS
3. بررسی browser console در FrontOffice
4. بررسی Nexus repository برای package issues

---

## 📝 یادداشت‌های مهم

### Proto3 Rules:
- هر field باید unique number داشته باشد
- Field aliasing نیاز به unique numbers دارد
- Message nesting می‌تواند مشکل generation ایجاد کند

### Blazor/Razor:
- Compilation cache نیاز به clean build دارد
- Using directives باید در top of file باشند
- Dynamic casting برای generic object types

### gRPC:
- تمام client ها باید registered باشند
- Port مismatch می‌تواند connection failure ایجاد کند
- Authentication header باید در تمام requests باشد

### Nexus:
- `allowInsecureConnections="true"` برای HTTP
- Credentials در `packageSourceCredentials`
- `--skip-duplicate` برای جلوگیری از خطای push

---

**تاریخ آخرین به‌روزرسانی**: 2 فوریه 2026  
**وضعیت**: ✅ Production Ready  
**نسخه مستند**: 1.0
