Files
docs/migration/MIGRATION-PROGRESS.md
T

14 KiB

Migration Progress: FrontOffice.BFF → CMS Direct Integration

Date: 2026-02-01

Overview

Migration of FrontOffice from BFF layer to direct CMS microservice integration to eliminate unnecessary abstraction layer and improve architecture.


Migration Strategy

Discovery Phase

  • Key Finding: BFF was acting as a DTO transformation layer
  • Insight: BFF proto files serve as specification for frontend requirements
  • Approach: Systematically compare BFF proto structures with CMS and add missing fields

Field Aliasing Strategy

Proto3 doesn't support field number reuse, so we use unique field numbers for alias fields:

  • Original fields keep their numbers (e.g., name = 2, image_url = 8)
  • Alias fields get new numbers (e.g., title = 12, image_path = 13)
  • Both fields must be populated in service implementations

Completed Work

Phase 1: Infrastructure Setup

  • Changed URL from localhost:32845 (BFF) to localhost:32846 (CMS)
  • Consolidated multiple BFF proto packages into single Foursat.CMSMicroservice.Protobuf
  • Implemented Customer-prefixed API methods for frontend access

Phase 2: Proto Package Updates

Version 0.0.171 (Successful)

  • Added models field aliases in response types:
    • GetAllCategoriesForCustomerResponse: categoriesmodels (field 2)
    • GetCustomerPackagesResponse: packagesmodels (field 1)
    • GetAllUserCartsResponse: itemsmodels (field 1)
  • Added missing fields:
    • GetUserForCustomerResponse.token (field 16)
    • GetClubMembershipResponse.status (field 11)
    • GetClubMembershipResponse.days_remaining (field 12)
  • Removed duplicate validators in CMSMicroservice.Protobuf/Validator/UserCarts/

Version 0.0.172 (Current)

Proto Changes:

  • package.proto: Added title (field 12) and image_path (field 13) to CustomerPackageModel
  • usercarts.proto:
    • Added user_cart_id (field 11) alias to UpdateUserCartRequest
    • Added product_short_infomation (field 14) typo alias to UserCartItem
    • Added created timestamp (field 10) to UserCartItem
  • networkmembership.proto: Added to NetworkTreeNodeModel:
    • full_name (field 20) - alias for user_name
    • level (field 21) - alias for network_level
    • mobile (field 14)
    • avatar (field 15)
    • position (field 16)
    • left_child (field 17)
    • right_child (field 18)

Service Implementation Changes:

  • Updated PackageService.GetCustomerPackageDetails to populate:
    • Title = "پکیج طلایی" (duplicate of Name)
    • ImagePath = "/images/packages/golden-detail.jpg" (duplicate of ImageUrl)

Build Status:

✅ Proto build: Success
✅ Pack version 0.0.172: Success
✅ Package location: /home/masoud/Apps/project/FourSat/nupkg/Foursat.CMSMicroservice.Protobuf.0.0.172.nupkg
✅ FrontOffice.Main.csproj updated to version 0.0.172

Phase 3: Error Reduction

  • Initial: 250+ compilation errors
  • After 0.0.171: 217 errors
  • After 0.0.172: 170 errors ⬇️ (32% reduction)

Remaining Work

⚠️ Critical Issues (170 Errors)

1. Missing Service Methods (8 methods)

Need to be added to CMS proto services:

ConfigurationContract:

  • GetClubConfigurationAsync
  • GetClubFeaturesAsync

CommissionContract:

  • GetMyCommissionPayoutsAsync
  • GetMyWeeklyBalancesAsync

NetworkMembershipContract:

  • GetMyNetworkTreeAsync
  • GetSubordinateTreeAsync
  • GetMyNetworkStatisticsAsync

UserOrderContract:

  • GetVATRateAsync

2. Missing Proto Fields

GetWeekDefinitionsRequest (5 fields):

int32 page_number = ?;
int32 page_size = ?;
string search_text = ?;
google.protobuf.Int32Value persian_year = ?;
google.protobuf.Int32Value gregorian_year = ?;
google.protobuf.BoolValue is_active = ?;

WeekDefinitionItem (2 fields):

string start_date_persian = ?;
string end_date_persian = ?;

3. Type Conversion Issues

PaginationState conflict:

Cannot implicitly convert type 'CMSMicroservice.Protobuf.Protos.PaginationState' 
to 'CMSMicroservice.Protobuf.Protos.City.PaginationState'

Location: Pages/Profile/Components/EditAddressDialog.razor.cs(45,35)

4. Incomplete Alias Population

Fields with aliases need population in ALL service methods:

  • CustomerPackageModel.Title / ImagePath (partially done)
  • NetworkTreeNodeModel.FullName / Level
  • Other alias fields across services

Technical Decisions

Proto Field Number Strategy

Problem: Proto3 doesn't allow field number reuse for aliases

// ❌ This doesn't work:
string name = 2;
string title = 2; // ERROR: Field number 2 already used

// ✅ Solution:
string name = 2;
string title = 12;  // New unique number

Why Not Update Frontend?

Preserving Business Logic: User requirement is "چیزی کم نشه از بیزینس" (don't lose any business logic). Changing frontend field names risks:

  • Breaking existing functionality
  • Missing edge cases in BFF transformation logic
  • Extensive testing burden

Field Aliasing Benefits:

  • Zero frontend changes required
  • Gradual migration path
  • Easy rollback if needed
  • Maintains backward compatibility

Next Steps

Priority 1: Add Missing Methods

  1. Define proto service methods in CMS .proto files
  2. Implement method stubs in CMS service classes
  3. Return mock/default data initially

Priority 2: Add Missing Fields

  1. Add fields to GetWeekDefinitionsRequest
  2. Add fields to WeekDefinitionItem
  3. Rebuild proto package as version 0.0.173

Priority 3: Fix Type Issues

  1. Resolve PaginationState namespace conflict
  2. Add missing PaymentGatewayUrl field
  3. Fix PaymentMethod enum reference

Priority 4: Complete Alias Population

  1. Populate all alias fields in service responses
  2. Ensure data consistency between original and alias fields

Package Version History

Version Status Changes Errors
0.0.170 Baseline Initial BFF → CMS migration 250+
0.0.171 Success Models aliases, Token field 217
0.0.172 Success Title/ImagePath aliases, Network fields 170
0.0.173 Planned Missing methods and fields TBD

Commands Reference

Build Proto Package

cd /home/masoud/Apps/project/FourSat/CMS/src/CMSMicroservice.Protobuf
dotnet build
dotnet pack -c Release -p:PackageVersion=0.0.172 -o ../../../nupkg -p:RunPushTarget=false

Update FrontOffice

cd /home/masoud/Apps/project/FourSat/FrontOffice/src/FrontOffice.Main
# Edit .csproj to update version number
dotnet build

Check Errors

cd /home/masoud/Apps/project/FourSat/FrontOffice/src/FrontOffice.Main
dotnet build 2>&1 | grep "error CS" | wc -l
dotnet build 2>&1 | grep "error CS" | head -20

Lessons Learned

  1. BFF Transformation Discovery: BFF wasn't just routing - it was transforming DTOs. This is critical business logic.

  2. Proto Field Aliasing: Proto3 requires unique field numbers. Can't reuse numbers for aliases.

  3. Systematic Approach: Comparing BFF proto files as specification prevented missing fields.

  4. Incremental Progress: Breaking work into small packages (0.0.171 → 0.0.172) made debugging easier.

  5. Package Naming: Real package name is Foursat.CMSMicroservice.Protobuf, not CMSMicroservice.Protobuf.


Notes

  • Post-build push to Nexus disabled with -p:RunPushTarget=false due to --allow-insecure-connections flag incompatibility
  • All changes preserve existing business logic per user requirement
  • Field aliases provide backward compatibility during migration
  • Final cleanup phase will update frontend to use CMS field names directly (optional future work)

سابقه مهاجرت اولیه (سرویس‌های اولیه)

FrontOffice.BFF to CMS Migration Progress

Migration Overview

مهاجرت سرویس‌های FrontOffice.BFF به CMS Microservice با معماری Clean Architecture و gRPC.

Completed Services

1. Categories Service

  • Status: Complete
  • Proto Definition: categories.proto
  • Service Implementation: CategoryService.cs
  • Methods Migrated:
    • Admin Methods:
      • AddNewCategory - افزودن دسته‌بندی جدید
      • UpdateCategory - بروزرسانی دسته‌بندی
      • DeleteCategory - حذف دسته‌بندی
      • GetCategory - دریافت یک دسته‌بندی
      • GetAllCategoriesByFilter - دریافت لیست دسته‌بندی‌ها
    • Customer Methods:
      • GetActiveCategoriesForCustomer - دریافت دسته‌بندی‌های فعال برای مشتری

2. City Service

  • Status: Complete
  • Proto Definition: city.proto
  • Service Implementation: CityService.cs
  • Methods Migrated:
    • Admin Methods:
      • AddNewCity - افزودن شهر جدید
      • UpdateCity - بروزرسانی شهر
      • DeleteCity - حذف شهر
      • GetCity - دریافت یک شهر
      • GetAllCitiesByFilter - دریافت لیست شهرها
    • Customer Methods:
      • GetActiveCitiesForCustomer - دریافت شهرهای فعال برای مشتری

3. UserCarts Service

  • Status: Complete
  • Proto Definition: usercarts.proto
  • Service Implementation: UserCartsService.cs
  • Methods Migrated:
    • Admin Methods:
      • AddNewUserCart - افزودن سبد خرید جدید
      • UpdateUserCart - بروزرسانی سبد خرید
      • DeleteUserCart - حذف سبد خرید
      • GetUserCart - دریافت سبد خرید (Admin)
      • GetAllUserCartsByFilter - دریافت لیست سبدهای خرید
    • Customer Methods:
      • AddNewUserCartForCustomer - افزودن محصول به سبد (Customer)
      • UpdateUserCartForCustomer - بروزرسانی تعداد محصول در سبد
      • RemoveUserCartForCustomer - حذف محصول از سبد
      • GetCustomerCart - دریافت سبد خرید مشتری

🛠️ Technical Implementation Details

gRPC HTTP Annotations

تمام سرویس‌ها با HTTP annotations تعریف شده‌اند:

  • Admin endpoints: /ServiceName pattern
  • Customer endpoints: /Customer/Action pattern

Clean Architecture Structure

CMSMicroservice.Domain/       # Core business entities
CMSMicroservice.Application/  # Business logic & CQRS
CMSMicroservice.Infrastructure/ # Data access & external services
CMSMicroservice.WebApi/       # gRPC services & controllers
CMSMicroservice.Protobuf/     # Protocol buffer definitions

Swagger Integration

  • Multiple Swagger documents: cms, admin, customer, unified
  • gRPC HTTP transcoding enabled
  • Custom CSS styling applied
  • Conflict resolution implemented

🔧 Issues Resolved

1. Swagger Conflict Resolution

Problem:

Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: 
Conflicting method/path combination "GET GetUserCart"

Root Cause:

  • دو method با operation ID یکسان: GetUserCart و GetUserCartForCustomer
  • Swagger از method name برای operation ID استفاده می‌کند

Solutions Attempted:

  1. CustomOperationIds - ineffective
  2. ResolveConflictingActions - incomplete resolution
  3. Method Renaming - successful

Final Solution:

// Before (conflicting):
rpc GetUserCartForCustomer(GetUserCartForCustomerRequest) returns (GetUserCartForCustomerResponse)

// After (resolved):
rpc GetCustomerCart(GetUserCartForCustomerRequest) returns (GetUserCartForCustomerResponse)

2. Application Layer Dependencies

Problem: Build errors در Application layer Solution: پاکسازی dependencies و rebuild پروژه

📊 Migration Status Summary

Service Proto Implementation Build Swagger
Categories
City
UserCarts

🎯 Next Steps

  1. Service Integration Testing - تست عملکرد سرویس‌های migrate شده
  2. Business Logic Implementation - پیاده‌سازی منطق کسب‌وکار واقعی
  3. Database Integration - اتصال به لایه دیتا
  4. Continue Migration - ادامه migration سایر سرویس‌ها

🏗️ Technical Architecture

gRPC Service Pattern

public class ServiceName : ServiceContract.ServiceContractBase
{
    private readonly IDispatchRequestToCQRS _dispatcher;
    
    // Customer Methods Section
    #region Customer Methods
    public override async Task<Response> CustomerMethod(Request request, ServerCallContext context)
    {
        // Implementation
    }
    #endregion
    
    // Admin Methods Section  
    #region Admin Methods
    public override async Task<Response> AdminMethod(Request request, ServerCallContext context)
    {
        // Implementation
    }
    #endregion
}

Proto File Structure

syntax = "proto3";
import "google/api/annotations.proto";

service ServiceContract {
    // ============= Admin Methods =============
    rpc AdminMethod(Request) returns (Response) {
        option (google.api.http) = {
            post: "/AdminEndpoint"
            body: "*"
        };
    };
    
    // ============= Customer Methods =============
    rpc CustomerMethod(Request) returns (Response) {
        option (google.api.http) = {
            get: "/Customer/Endpoint"
        };
    };
}

📈 Performance & Quality

  • All services compile successfully
  • Swagger documentation accessible
  • gRPC HTTP transcoding working
  • Clean separation of Admin/Customer concerns
  • Consistent naming conventions applied

Last Updated: January 30, 2026
Migration Phase: Foundation Services Complete
Next Milestone: Business Logic Implementation