Files
BackOffice.BFF/docs/cms-integration.md

594 lines
18 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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