# BackOffice.BFF - CMS Integration Documentation

**Date**: 2025-11-30  
**Status**: ✅ Integrated  
**CMS Package Version**: 0.0.140  

---

## 📋 Overview

BackOffice.BFF به CMS Microservice متصل شد و حالا می‌تواند به سرویس‌های Network-Club-Commission دسترسی داشته باشد.

این Integration به BackOffice امکان می‌دهد:
- مدیریت کامیسیون‌های کاربران
- مشاهده ساختار شبکه Binary Tree
- فعال/غیرفعال کردن عضویت باشگاه
- مشاهده گزارشات هفتگی کمیسیون

---

## 🏗️ Architecture

```
┌─────────────────────────────────────────────────────────┐
│              BackOffice.BFF (API Gateway)                │
│                                                           │
│  ┌──────────────────────────────────────────────────┐   │
│  │      IApplicationContractContext                 │   │
│  │  - Users (existing)                              │   │
│  │  - Products (existing)                           │   │
│  │  - Orders (existing)                             │   │
│  │  ✨ Commissions (NEW)                            │   │
│  │  ✨ NetworkMemberships (NEW)                     │   │
│  │  ✨ ClubMemberships (NEW)                        │   │
│  └──────────────────────────────────────────────────┘   │
│                          ↓ gRPC                          │
└─────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────┐
│                  CMS Microservice                        │
│             https://cms.kbs1.ir                          │
│                                                           │
│  ┌─────────────────────┐  ┌─────────────────────────┐  │
│  │ CommissionContract  │  │ NetworkMembershipContract│  │
│  │ - GetWeeklyPool     │  │ - GetUserNetworkInfo    │  │
│  │ - GetUserPayouts    │  │ - GetNetworkTree        │  │
│  │ - ProcessWithdrawal │  │ - CalculateLegBalances  │  │
│  └─────────────────────┘  └─────────────────────────┘  │
│                                                           │
│  ┌─────────────────────┐                                 │
│  │ ClubMembershipContract│                               │
│  │ - ActivateClub      │                                 │
│  │ - DeactivateClub    │                                 │
│  │ - GetClubStatus     │                                 │
│  └─────────────────────┘                                 │
└─────────────────────────────────────────────────────────┘
```

---

## 📦 Integration Details

### 1️⃣ NuGet Package

**Package**: `Foursat.CMSMicroservice.Protobuf`  
**Version**: `0.0.140` (Updated from 0.0.137)

**File**: `/BackOffice.BFF/src/BackOffice.BFF.Domain/BackOffice.BFF.Domain.csproj`

```xml
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.140" />
```

**What's New in 0.0.140**:
- ✨ `commission.proto` - Commission system contracts
- ✨ `networkmembership.proto` - Binary tree network contracts
- ✨ `clubmembership.proto` - Club membership contracts
- ✨ `configuration.proto` - System configuration contracts

---

### 2️⃣ Interface Definition

**File**: `/BackOffice.BFF/src/BackOffice.BFF.Application/Common/Interfaces/IApplicationContractContext.cs`

```csharp
public interface IApplicationContractContext
{
    // ... existing services ...
    
    // Network & Commission System (NEW)
    CommissionContract.CommissionContractClient Commissions { get; }
    NetworkMembershipContract.NetworkMembershipContractClient NetworkMemberships { get; }
    ClubMembershipContract.ClubMembershipContractClient ClubMemberships { get; }
}
```

---

### 3️⃣ Implementation

**File**: `/BackOffice.BFF/src/BackOffice.BFF.Infrastructure/Services/ApplicationContractContext.cs`

```csharp
public class ApplicationContractContext : IApplicationContractContext
{
    // ... existing implementations ...
    
    // Network & Commission System
    public CommissionContract.CommissionContractClient Commissions 
        => GetService<CommissionContract.CommissionContractClient>();
    
    public NetworkMembershipContract.NetworkMembershipContractClient NetworkMemberships 
        => GetService<NetworkMembershipContract.NetworkMembershipContractClient>();
    
    public ClubMembershipContract.ClubMembershipContractClient ClubMemberships 
        => GetService<ClubMembershipContract.ClubMembershipContractClient>();
}
```

---

### 4️⃣ gRPC Configuration

**File**: `/BackOffice.BFF/src/BackOffice.BFF.WebApi/appsettings.json`

```json
{
  "GrpcChannelOptions": {
    "FMSMSAddress": "https://dl.afrino.co",
    "CMSMSAddress": "https://cms.kbs1.ir"
  }
}
```

**Auto-Registration**: 
- gRPC clients به صورت خودکار توسط `ConfigureGrpcServices.BatchRegisterGrpcClients()` ثبت می‌شوند
- بر اساس نام Assembly (`CMSMicroservice.Protobuf`)
- با Address مشخص شده در `appsettings.json`

---

## 🔌 Available Services

### 1️⃣ CommissionContract

**Namespace**: `CMSMicroservice.Protobuf.Protos.Commission`

#### Commands:
```csharp
// محاسبه بالانس های هفتگی
await _context.Commissions.CalculateWeeklyBalancesAsync(
    new CalculateWeeklyBalancesRequest { WeekNumber = "2025-W48" });

// محاسبه Pool هفتگی
await _context.Commissions.CalculateWeeklyCommissionPoolAsync(
    new CalculateWeeklyCommissionPoolRequest { WeekNumber = "2025-W48" });

// پردازش Payout های کاربران
await _context.Commissions.ProcessUserPayoutsAsync(
    new ProcessUserPayoutsRequest { WeekNumber = "2025-W48" });

// درخواست برداشت توسط کاربر
await _context.Commissions.RequestWithdrawalAsync(
    new RequestWithdrawalRequest 
    { 
        UserId = 123, 
        Amount = 500000 
    });

// پردازش برداشت (توسط Admin)
await _context.Commissions.ProcessWithdrawalAsync(
    new ProcessWithdrawalRequest 
    { 
        PayoutId = 456, 
        Status = WithdrawalStatus.Approved 
    });
```

#### Queries:
```csharp
// دریافت Pool هفتگی
var pool = await _context.Commissions.GetWeeklyCommissionPoolAsync(
    new GetWeeklyCommissionPoolRequest { WeekNumber = "2025-W48" });

// دریافت Payout های یک کاربر
var payouts = await _context.Commissions.GetUserPayoutsAsync(
    new GetUserPayoutsRequest 
    { 
        UserId = 123,
        PageNumber = 1,
        PageSize = 10 
    });

// دریافت تاریخچه Withdrawal ها
var withdrawals = await _context.Commissions.GetWithdrawalHistoryAsync(
    new GetWithdrawalHistoryRequest 
    { 
        UserId = 123,
        Status = WithdrawalStatus.Pending 
    });
```

---

### 2️⃣ NetworkMembershipContract

**Namespace**: `CMSMicroservice.Protobuf.Protos.NetworkMembership`

#### Queries:
```csharp
// دریافت اطلاعات شبکه یک کاربر
var networkInfo = await _context.NetworkMemberships.GetUserNetworkInfoAsync(
    new GetUserNetworkInfoRequest { UserId = 123 });

// دریافت درخت شبکه (Binary Tree)
var tree = await _context.NetworkMemberships.GetNetworkTreeAsync(
    new GetNetworkTreeRequest 
    { 
        RootUserId = 123,
        MaxDepth = 5 
    });

// دریافت بالانس های هفتگی
var balances = await _context.NetworkMemberships.GetUserWeeklyBalancesAsync(
    new GetUserWeeklyBalancesRequest 
    { 
        UserId = 123,
        WeekNumber = "2025-W48" 
    });

// محاسبه بالانس Leg های یک کاربر
var legBalances = await _context.NetworkMemberships.CalculateLegBalancesAsync(
    new CalculateLegBalancesRequest { UserId = 123 });
```

---

### 3️⃣ ClubMembershipContract

**Namespace**: `CMSMicroservice.Protobuf.Protos.ClubMembership`

#### Commands:
```csharp
// فعال کردن عضویت باشگاه
await _context.ClubMemberships.ActivateClubMembershipAsync(
    new ActivateClubMembershipRequest 
    { 
        UserId = 123,
        ActivationDate = Timestamp.FromDateTime(DateTime.UtcNow) 
    });

// غیرفعال کردن عضویت باشگاه
await _context.ClubMemberships.DeactivateClubMembershipAsync(
    new DeactivateClubMembershipRequest 
    { 
        UserId = 123,
        Reason = "User request" 
    });
```

#### Queries:
```csharp
// دریافت وضعیت عضویت باشگاه
var status = await _context.ClubMemberships.GetClubMembershipStatusAsync(
    new GetClubMembershipStatusRequest { UserId = 123 });

// لیست تمام اعضای باشگاه
var members = await _context.ClubMemberships.GetAllClubMembersAsync(
    new GetAllClubMembersRequest 
    { 
        IsActive = true,
        PageNumber = 1,
        PageSize = 20 
    });
```

---

## 📝 Usage Example in BFF

### Example 1: Create Commission Query Handler

**File**: `/BackOffice.BFF/src/BackOffice.BFF.Application/CommissionCQ/Queries/GetUserPayouts/GetUserPayoutsQuery.cs`

```csharp
public record GetUserPayoutsQuery : IRequest<GetUserPayoutsResponseDto>
{
    public long UserId { get; init; }
    public int PageNumber { get; init; } = 1;
    public int PageSize { get; init; } = 10;
}

public class GetUserPayoutsQueryHandler 
    : IRequestHandler<GetUserPayoutsQuery, GetUserPayoutsResponseDto>
{
    private readonly IApplicationContractContext _context;

    public GetUserPayoutsQueryHandler(IApplicationContractContext context)
    {
        _context = context;
    }

    public async Task<GetUserPayoutsResponseDto> Handle(
        GetUserPayoutsQuery request, 
        CancellationToken cancellationToken)
    {
        var response = await _context.Commissions.GetUserPayoutsAsync(
            request.Adapt<GetUserPayoutsRequest>(), 
            cancellationToken: cancellationToken);

        return response.Adapt<GetUserPayoutsResponseDto>();
    }
}
```

---

### Example 2: Create Network Tree Query Handler

**File**: `/BackOffice.BFF/src/BackOffice.BFF.Application/NetworkCQ/Queries/GetNetworkTree/GetNetworkTreeQuery.cs`

```csharp
public record GetNetworkTreeQuery : IRequest<GetNetworkTreeResponseDto>
{
    public long RootUserId { get; init; }
    public int MaxDepth { get; init; } = 5;
}

public class GetNetworkTreeQueryHandler 
    : IRequestHandler<GetNetworkTreeQuery, GetNetworkTreeResponseDto>
{
    private readonly IApplicationContractContext _context;

    public GetNetworkTreeQueryHandler(IApplicationContractContext context)
    {
        _context = context;
    }

    public async Task<GetNetworkTreeResponseDto> Handle(
        GetNetworkTreeQuery request, 
        CancellationToken cancellationToken)
    {
        var response = await _context.NetworkMemberships.GetNetworkTreeAsync(
            request.Adapt<GetNetworkTreeRequest>(), 
            cancellationToken: cancellationToken);

        return response.Adapt<GetNetworkTreeResponseDto>();
    }
}
```

---

### Example 3: Create Club Activation Command Handler

**File**: `/BackOffice.BFF/src/BackOffice.BFF.Application/ClubCQ/Commands/ActivateClub/ActivateClubCommand.cs`

```csharp
public record ActivateClubCommand : IRequest<Unit>
{
    public long UserId { get; init; }
    public DateTimeOffset? ActivationDate { get; init; }
}

public class ActivateClubCommandHandler 
    : IRequestHandler<ActivateClubCommand, Unit>
{
    private readonly IApplicationContractContext _context;

    public ActivateClubCommandHandler(IApplicationContractContext context)
    {
        _context = context;
    }

    public async Task<Unit> Handle(
        ActivateClubCommand request, 
        CancellationToken cancellationToken)
    {
        await _context.ClubMemberships.ActivateClubMembershipAsync(
            request.Adapt<ActivateClubMembershipRequest>(), 
            cancellationToken: cancellationToken);

        return Unit.Value;
    }
}
```

---

## 🔐 Authentication & Authorization

**JWT Token**:
- BackOffice.BFF به CMS با JWT Token متصل می‌شود
- Token از `ITokenProvider` گرفته می‌شود
- در Header با کلید `Authorization: Bearer {token}` ارسال می‌شود

**Implementation در `ConfigureGrpcServices.cs`**:
```csharp
private static async Task CallCredentials(
    AuthInterceptorContext context, 
    Metadata metadata,
    IServiceProvider serviceProvider)
{
    var provider = serviceProvider.GetRequiredService<ITokenProvider>();
    var token = await provider.GetTokenAsync();
    metadata.Add("Authorization", $"Bearer {token}");
}
```

---

## 🧪 Testing

### Test Connection:

```csharp
// در یک Controller یا Handler:
var pool = await _context.Commissions.GetWeeklyCommissionPoolAsync(
    new GetWeeklyCommissionPoolRequest { WeekNumber = "2025-W48" });

Console.WriteLine($"Total Pool Value: {pool.TotalPoolValue}");
Console.WriteLine($"Active Members: {pool.ActiveMembersCount}");
```

**Expected Output**:
```
Total Pool Value: 50000000
Active Members: 120
```

---

### Test with Postman/Swagger:

1. Start BackOffice.BFF:
   ```bash
   cd /home/masoud/Apps/project/FourSat/BackOffice.BFF/src
   dotnet run --project BackOffice.BFF.WebApi
   ```

2. Call API endpoint (example):
   ```http
   GET /api/commission/weekly-pool?weekNumber=2025-W48
   Authorization: Bearer {your-token}
   ```

3. Expected Response:
   ```json
   {
     "weekNumber": "2025-W48",
     "totalPoolValue": 50000000,
     "activeMembersCount": 120,
     "isCalculated": true
   }
   ```

---

## 📊 Status & Metrics

| Component | Status | Version | Notes |
|-----------|--------|---------|-------|
| **CMS Protobuf Package** | ✅ Active | 0.0.140 | With Network-Club-Commission |
| **gRPC Connection** | ✅ Configured | - | https://cms.kbs1.ir |
| **Auto-Registration** | ✅ Active | - | Via BatchRegisterGrpcClients |
| **Commission Client** | ✅ Ready | - | All commands & queries available |
| **Network Client** | ✅ Ready | - | Binary tree queries available |
| **Club Client** | ✅ Ready | - | Activation/Deactivation available |
| **Authentication** | ✅ Configured | JWT | Via ITokenProvider |

---

## 🔗 Related Documentation

### CMS Side:
- **Implementation Progress**: `/CMS/docs/implementation-progress.md`
- **Network System Design**: `/CMS/docs/network-club-commission-system.md`
- **Monitoring Setup**: `/CMS/docs/monitoring-alerts-consolidated-report.md`
- **Migration Guide**: `/CMS/docs/migration-network-parent-guide.md`
- **Binary Tree Registration**: `/CMS/docs/binary-tree-registration-guide.md`

### BFF Side:
- **This Document**: `/BackOffice.BFF/docs/cms-integration.md`
- **README**: `/BackOffice.BFF/README.md`

---

## 🚀 Next Steps

### Immediate:
1. ✅ Integration completed
2. ⏳ Create Commission/Network/Club CQRS handlers in BFF
3. ⏳ Add API endpoints in BackOffice.BFF.WebApi
4. ⏳ Test integration with real data

### Short-term:
5. ⏳ Add Swagger documentation for new endpoints
6. ⏳ Implement error handling for gRPC calls
7. ⏳ Add logging for commission operations
8. ⏳ Create admin dashboard for network visualization

### Long-term:
9. ⏳ Add real-time notifications (SignalR) for commission updates
10. ⏳ Implement caching for frequently accessed data
11. ⏳ Add reporting/analytics endpoints
12. ⏳ Performance optimization for large network trees

---

## 📞 Troubleshooting

### Issue 1: gRPC Connection Failed

**Error**: `Status(StatusCode="Unavailable", Detail="...")`

**Solutions**:
1. Check CMS service is running: `https://cms.kbs1.ir`
2. Verify network connectivity
3. Check firewall settings
4. Verify SSL certificate is valid

---

### Issue 2: Authentication Failed

**Error**: `Status(StatusCode="Unauthenticated", Detail="...")`

**Solutions**:
1. Verify `ITokenProvider` is registered in DI
2. Check JWT token is valid and not expired
3. Verify token has correct claims/permissions
4. Check Authorization header is being sent

---

### Issue 3: Package Version Mismatch

**Error**: `The type or namespace 'CommissionContract' could not be found`

**Solutions**:
1. Update package version in `.csproj`:
   ```xml
   <PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.140" />
   ```
2. Run `dotnet restore`
3. Clean and rebuild solution

---

### Issue 4: Method Not Found

**Error**: `Method 'GetWeeklyPool' not found on service 'CommissionContract'`

**Solutions**:
1. Verify CMS service has the latest code deployed
2. Check Protobuf contract matches between CMS and BFF
3. Update both CMS and BFF to latest versions
4. Restart both services

---

## 🎯 Summary

### ✅ Completed:
- CMS Protobuf package updated to 0.0.140
- 3 new gRPC clients added to BFF:
  * CommissionContract (8+ methods)
  * NetworkMembershipContract (6+ methods)
  * ClubMembershipContract (4+ methods)
- Auto-registration configured
- Authentication via JWT configured
- Build successful (0 errors)

### ⏳ Pending:
- Create CQRS handlers for Commission operations
- Create CQRS handlers for Network operations
- Create CQRS handlers for Club operations
- Add API Controllers/Endpoints
- Add Swagger documentation
- Integration testing

### 🔑 Key Points:
- **No manual registration needed**: gRPC clients auto-register via `BatchRegisterGrpcClients()`
- **Authentication handled**: JWT token automatically added to all requests
- **Type-safe**: All Protobuf contracts are strongly typed
- **Easy to use**: Simple interface via `IApplicationContractContext`

---

**Last Updated**: 2025-11-30  
**Build Status**: ✅ Success  
**Ready for**: Handler implementation & API endpoint creation
