# QR Provider Architecture Refactoring Plan V2

## 🎯 **Executive Summary**

This document outlines the complete refactoring plan to transform the current QR provider architecture into a standardized, maintainable, and extensible system. The refactoring will be done in parallel to existing code to ensure zero disruption to current operations.

## 📊 **Current Architecture Analysis**

### **Existing Components**
- **Controller**: `QRMiddleLayerController` - Handles routing and provider-specific logic
- **Providers**: `Alipay`, `Aani`, `UPI` - Each with different interfaces and response formats
- **Factory**: Basic provider lookup via configuration
- **Database**: Transaction, Provider, PosTerminal, ShukriaTerminal schemas

### **Current Issues**
1. **Inconsistent Module Naming**: Mixed namespaces (`QRProviders` vs `QrProvider`)
2. **Provider-Specific Logic in Controller**: Response handling scattered across controller
3. **Tight Coupling**: Direct configuration access in controller
4. **No Standard Interface**: Each provider has different method signatures
5. **Difficult Extension**: Adding new providers requires core code changes

### **Current Endpoints**
- `POST /api/processTransaction` - QR generation
- `POST /api/cancel_payment` - Payment cancellation  
- `POST /api/refund_payment` - Payment refunds

---

## 🏗️ **New Architecture Design**

### **Design Principles**
1. **Zero Disruption**: Existing code remains untouched
2. **Standard Interface**: All providers implement same contract
3. **Self-Contained Providers**: Each provider handles its own format conversion
4. **Configuration-Driven**: New providers require only config changes
5. **Progressive Migration**: Gradual transition with rollback capability

### **File Structure**
```
lib/da_product_app/
├── qr_providers_v2/                    # NEW - Parallel architecture
│   ├── behaviour.ex                    # Standard interfaces & contracts
│   ├── types.ex                        # Common data structures & types
│   ├── factory.ex                      # Enhanced factory pattern
│   ├── response_normalizer.ex          # Response standardization utilities
│   ├── error_handler.ex               # Standardized error handling
│   └── providers/                      # Provider implementations
│       ├── alipay_v2.ex               # Standardized Alipay implementation
│       ├── aani_v2.ex                 # Standardized Aani implementation  
│       └── upi_v2.ex                  # Standardized UPI implementation
│
├── qr_provider/                        # EXISTING - Untouched
│   ├── alipay.ex                      # Current implementation
│   ├── aani.ex                        # Current implementation
│   └── upi.ex                         # Current implementation
│
└── qr_providers_web/
    ├── controllers/
    │   ├── qr_middle_layer_controller.ex     # EXISTING - Untouched
    │   └── qr_payment_controller_v2.ex       # NEW - Standardized controller
    └── router.ex                       # UPDATED - Add v2 routes
```

---

## 📋 **Phase-by-Phase Implementation Plan**

### **Phase 1: Foundation & Contracts** ⏱️ 2-3 days

#### 1.1 Standard Behavior Contract (`behaviour.ex`)
```elixir
@type standard_request :: %{
  transaction_refid: String.t(),
  amount: number(),
  merchant_id: String.t(),
  device_id: String.t(),
  provider_id: String.t(),
  additional_data: map(),
  # ... other standard fields
}

@type standard_response :: %{
  status: :success | :error | :pending,
  qr_code_url: String.t() | nil,
  qr_code_id: String.t() | nil,
  payment_reference_id: String.t() | nil,
  error_code: atom() | nil,
  error_message: String.t() | nil,
  provider_data: map()
}

@callback generate(standard_request()) :: {:ok, standard_response()} | {:error, standard_response()}
@callback cancel_payment(String.t()) :: {:ok, standard_response()} | {:error, standard_response()}
@callback refund_payment(String.t(), map()) :: {:ok, standard_response()} | {:error, standard_response()}
```

#### 1.2 Data Types (`types.ex`)
- Common data structures
- Validation schemas
- Error codes enumeration

#### 1.3 Enhanced Factory (`factory.ex`)
- Provider registration and lookup
- Method routing
- Error handling

#### 1.4 Configuration Updates
```elixir
config :da_product_app, :qr_providers_v2, %{
  "alipay" => DaProductApp.QRProvidersV2.Providers.AlipayV2,
  "aani" => DaProductApp.QRProvidersV2.Providers.AaniV2,
  "upi" => DaProductApp.QRProvidersV2.Providers.UpiV2
}
```

### **Phase 2: Provider Implementations** ⏱️ 4-5 days

#### 2.1 Provider Architecture Pattern
Each provider will:
1. **Receive standard input** - Convert to provider-specific format
2. **Make provider API calls** - Using existing or enhanced logic
3. **Return standard output** - Convert provider response to standard format
4. **Handle errors consistently** - Standardized error responses

#### 2.2 Implementation Strategy
- **Alipay V2**: Wrap existing logic with standard interface
- **Aani V2**: Standardize the multi-step token + register flow
- **UPI V2**: Enhance current implementation with standard interface

#### 2.3 Key Features
- Internal format conversion
- Consistent logging patterns
- Error standardization
- Provider-specific configuration

### **Phase 3: Parallel Controller** ⏱️ 3-4 days

#### 3.1 New Controller (`qr_payment_controller_v2.ex`)
- **Endpoint**: `/api/v2/qr/process` - QR generation
- **Endpoint**: `/api/v2/qr/cancel` - Payment cancellation
- **Endpoint**: `/api/v2/qr/refund` - Payment refunds

#### 3.2 Controller Features
- Provider-agnostic logic
- Standard request/response handling  
- Enhanced error responses
- Same database interactions as V1

#### 3.3 Route Configuration
```elixir
# lib/da_product_app_web/router.ex
scope "/api/v2", DaProductAppWeb do
  pipe_through :api
  
  post "/qr/process", QRPaymentControllerV2, :process_transaction
  post "/qr/cancel", QRPaymentControllerV2, :cancel_payment
  post "/qr/refund", QRPaymentControllerV2, :refund_payment
end
```

### **Phase 4: Testing & Validation** ⏱️ 2-3 days

#### 4.1 Test Coverage
- Unit tests for each provider
- Integration tests for controller endpoints
- Database interaction validation
- Error handling verification

#### 4.2 Validation Strategy  
- Compare V1 vs V2 responses
- Performance benchmarking
- Database consistency checks
- Provider API compatibility

### **Phase 5: Migration Strategy** ⏱️ 1-2 days

#### 5.1 Feature Flags
- Runtime switching between V1/V2
- Gradual traffic migration
- A/B testing capability

#### 5.2 Documentation
- API migration guide
- Provider addition guide
- Troubleshooting documentation

---

## 🔧 **Database Integration Strategy**

### **Reused Schemas**
- `transactions` - No changes, same business logic
- `providers` - May add V2-specific configuration fields
- `pos_terminals` - No changes
- `shukria_terminals` - No changes
- `transaction_operations` - Same refund/cancel operations

### **Business Logic Preservation**
- **YSP Notification Service** - Same integration points
- **Event Logging** - Enhanced but compatible format
- **Transaction Management** - Identical database operations
- **Batch Processing** - Same logic, different interface

---

## 💡 **Implementation Samples**

### **Standard Provider Implementation**
```elixir
defmodule DaProductApp.QRProvidersV2.Providers.AlipayV2 do
  @behaviour DaProductApp.QRProvidersV2.Behaviour
  
  @impl true
  def generate(standard_request) do
    # 1. Convert standard format to Alipay format
    alipay_request = convert_to_alipay_format(standard_request)
    
    # 2. Call Alipay API (reuse existing logic)
    case call_alipay_api(alipay_request) do
      {:ok, alipay_response} ->
        # 3. Convert Alipay response to standard format
        standard_response = normalize_alipay_response(alipay_response)
        {:ok, standard_response}
        
      {:error, alipay_error} ->
        # 4. Convert error to standard format
        standard_error = normalize_alipay_error(alipay_error)
        {:error, standard_error}
    end
  end
  
  # Private conversion methods
  defp convert_to_alipay_format(standard_request) do
    %{
      # Map standard fields to Alipay format
      merchantTransactionId: standard_request.transaction_refid,
      paymentAmount: %{
        currency: standard_request.currency || "AED",
        value: to_smallest_unit(standard_request.amount)
      },
      # ... other mappings
    }
  end
  
  defp normalize_alipay_response(alipay_response) do
    %{
      status: determine_status(alipay_response),
      qr_code_url: get_qr_url(alipay_response),
      qr_code_id: alipay_response["paymentId"],
      payment_reference_id: alipay_response["paymentId"],
      provider_data: alipay_response
    }
  end
end
```

### **Standardized Controller**
```elixir
defmodule DaProductAppWeb.QRPaymentControllerV2 do
  use DaProductAppWeb, :controller
  
  def process_transaction(conn, params) do
    # 1. Validate and normalize incoming request
    case validate_and_normalize_request(params) do
      {:ok, standard_request} ->
        # 2. Call provider via factory - same interface for ALL providers
        case DaProductApp.QRProvidersV2.Factory.call_provider(
          params["provider"], :generate, [standard_request]
        ) do
          {:ok, standard_response} ->
            # 3. Return standardized success response
            json(conn, format_success_response(standard_response))
            
          {:error, standard_error} ->
            # 4. Return standardized error response
            json(conn, format_error_response(standard_error))
        end
        
      {:error, validation_error} ->
        json(conn, format_validation_error(validation_error))
    end
  end
  
  # Single response formatter for ALL providers
  defp format_success_response(%{status: :success} = response) do
    %{
      status: "success",
      qrCodeUrl: response.qr_code_url,
      qrCodeId: response.qr_code_id,
      paymentReferenceId: response.payment_reference_id,
      message: "QR code generated successfully"
    }
  end
end
```

---

## ✅ **Benefits & Advantages**

### **Immediate Benefits**
- ✅ **Zero Disruption**: Existing functionality unchanged
- ✅ **Clean Architecture**: Provider-agnostic controller logic
- ✅ **Consistent Interface**: Same methods for all providers
- ✅ **Better Error Handling**: Standardized error responses
- ✅ **Easier Testing**: Uniform test patterns

### **Long-term Benefits**
- 🚀 **Effortless Provider Addition**: New providers need only config changes
- 🔧 **Simplified Maintenance**: Single interface for all operations  
- 📈 **Better Scalability**: Provider-specific optimizations isolated
- 🔍 **Enhanced Monitoring**: Consistent logging and metrics
- 🛡️ **Improved Security**: Centralized validation and error handling

### **Developer Experience**
- 📚 **Better Documentation**: Standard interfaces are self-documenting
- 🧪 **Easier Testing**: Mock any provider with same interface
- 🔄 **Faster Development**: Reusable patterns across providers
- 🐛 **Simpler Debugging**: Consistent error formats and logging

---

## 🎯 **Success Criteria**

### **Phase Completion Criteria**

#### Phase 1 ✅
- [ ] Standard behavior contract defined
- [ ] Common types and structures created
- [ ] Enhanced factory implemented
- [ ] Configuration updated

#### Phase 2 ✅  
- [ ] All 3 providers implement standard interface
- [ ] Format conversion working correctly
- [ ] Error handling standardized
- [ ] Existing functionality preserved

#### Phase 3 ✅
- [ ] New controller endpoints functional
- [ ] Same database interactions as V1
- [ ] Standard request/response formats
- [ ] Proper error handling

#### Phase 4 ✅
- [ ] 100% test coverage for new components
- [ ] V1 vs V2 response validation
- [ ] Performance benchmarks pass
- [ ] Database integrity maintained

#### Phase 5 ✅
- [ ] Feature flags implemented
- [ ] Migration documentation complete
- [ ] Rollback procedures tested
- [ ] Monitoring and alerts configured

---

## 🔄 **Migration Timeline**

| Phase | Duration | Dependencies | Deliverables |
|-------|----------|--------------|--------------|
| **Phase 1** | 2-3 days | - | Contracts, Types, Factory |
| **Phase 2** | 4-5 days | Phase 1 | Provider Implementations |
| **Phase 3** | 3-4 days | Phase 1,2 | Controller & Routes |
| **Phase 4** | 2-3 days | Phase 1,2,3 | Tests & Validation |
| **Phase 5** | 1-2 days | Phase 1,2,3,4 | Migration Strategy |
| **Total** | **12-17 days** | - | **Complete V2 Architecture** |

---

## 📚 **References & Resources**

### **Current System Documentation**
- `QRGen.md` - Current QR generation flow
- `YSP_NOTIFICATION_ENHANCEMENT.md` - YSP integration details
- Database migrations - Schema definitions

### **Related Files**
- `qr_middle_layer_controller.ex` - Current controller implementation
- `config/config.exs` - Provider configurations
- Provider implementations in `qr_provider/` directory

### **Key Database Tables**
- `transactions` - Main transaction records
- `providers` - Provider definitions
- `pos_terminals` - Terminal information  
- `shukria_terminals` - Terminal-provider mappings
- `transaction_operations` - Operation records (refund/cancel)

---

## 🚀 **Getting Started**

### **Implementation Order**
1. **Review & Approve Plan** - Stakeholder sign-off
2. **Start Phase 1** - Foundation & contracts
3. **Parallel Development** - Providers can be built simultaneously
4. **Integration Testing** - Continuous validation
5. **Gradual Rollout** - Feature-flagged deployment

### **Ready to Begin?**
- [ ] Plan reviewed and approved
- [ ] Development environment ready
- [ ] Repository access confirmed
- [ ] Phase 1 implementation ready to start

**Next Step**: Implement Phase 1 - Foundation & Contracts

---

*This document serves as the definitive guide for the QR Provider Architecture V2 refactoring. All implementation decisions and progress should be tracked against this plan.*