# XOperationController & QOperationController - Architecture & Usage Guide

## Overview

Both **XOperationController** and **QOperationController** follow the same architectural pattern for managing external broker API integrations. They use raw cURL for HTTP requests, database-backed configuration, and token/cookie management.

## Architecture Comparison

| Feature | XOperationController | QOperationController |
|---------|---------------------|---------------------|
| HTTP Method | cURL (raw) | cURL (raw) |
| Token Storage | VsLoginToken (token field) | VsLoginToken (cookie field) |
| Auth Type | Bearer Token | Cookie-based |
| Config Source | VsLogin & VsEndPoint models | VsLogin & VsEndPoint models |
| Token Lifespan | 48 hours (configurable) | 8 hours (hardcoded) |
| Auto-reauth | Yes, on 401 errors | Yes, on token expiry check |
| Status Tracking | N/A | VsLastSyncStatus for syncs |

## Common Methods

Both controllers implement:

### 1. httpRequest()
Generic cURL wrapper for all HTTP operations
```php
private function httpRequest($url, $method = 'GET', $data = [], $headers = [], 
                           $returnJson = true, $returnHeaders = false, 
                           $useFormUrlencoded = false): mixed
```

**Features:**
- Automatic header parsing (Set-Cookie extraction)
- JSON encoding/form-urlencoded support
- SSL verification disabled (configurable)
- Error throwing on 4xx/5xx responses

### 2. [System]CheckTokenAlive()
Validate current token without making a real request
```php
public function xCheckTokenAlive(): bool      // X System
public function qCheckTokenAlive(): bool      // Q System
```

### 3. [System]Login()
Authenticate and store credentials
```php
// Private method returning array
private function xLogin(): array
private function qlogin(): array

// Public endpoint returning JsonResponse
public function login(): JsonResponse
```

### 4. [System]Logout()
Invalidate stored tokens
```php
public function xLogout()
public function qLogout()
```

## Database Schema Requirements

### VsLogin Table
```sql
CREATE TABLE vs_logins (
    id BIGINT PRIMARY KEY,
    key VARCHAR(50) UNIQUE,           -- 'xSystem' or 'quantOMS'
    username VARCHAR(255),
    password VARCHAR(255),
    status ENUM('active', 'inactive'),
    created_at TIMESTAMP,
    updated_at TIMESTAMP
);

-- Required entries:
INSERT INTO vs_logins VALUES 
(1, 'xSystem', 'x_username', 'x_password', 'active', NOW(), NOW()),
(2, 'quantOMS', 'q_username', 'q_password', 'active', NOW(), NOW());
```

### VsEndPoint Table
```sql
CREATE TABLE vs_end_points (
    id BIGINT PRIMARY KEY,
    key VARCHAR(50),
    url VARCHAR(500),
    method VARCHAR(10),
    status ENUM('active', 'inactive'),
    created_at TIMESTAMP,
    updated_at TIMESTAMP
);

-- Required for X System:
INSERT INTO vs_end_points VALUES 
(1, 'x_login', 'http://192.168.6.98:96/api/Auth/login', 'POST', 'active', NOW(), NOW()),
(2, 'x_logout', 'http://192.168.6.98:96/api/Auth/logout', 'GET', 'active', NOW(), NOW()),
(3, 'x_check_token_alive', 'http://192.168.6.98:96/api/Auth/verify', 'GET', 'active', NOW(), NOW()),
(4, 'x_ledger_balance', 'http://192.168.6.98:96/api/InvestorLedgerBalance/{clientCode}', 'GET', 'active', NOW(), NOW()),
(5, 'x_ledger_statement', 'http://192.168.6.98:96/api/LedgerStatementRPT', 'GET', 'active', NOW(), NOW()),
(6, 'x_portfolio', 'http://192.168.6.98:96/api/PortfolioRPT', 'GET', 'active', NOW(), NOW());

-- Required for Q System:
INSERT INTO vs_end_points VALUES 
(10, 'quant_login', 'http://broker.quantum.com/login', 'POST', 'active', NOW(), NOW()),
(11, 'quant_logout', 'http://broker.quantum.com/logout', 'GET', 'active', NOW(), NOW()),
(12, 'quant_check_token_alive', 'http://broker.quantum.com/api/verify', 'GET', 'active', NOW(), NOW()),
(13, 'quant_get_order_log', 'http://broker.quantum.com/api/orders?page=', 'GET', 'active', NOW(), NOW());
```

### VsLoginToken Table
```sql
CREATE TABLE vs_login_tokens (
    id BIGINT PRIMARY KEY,
    key VARCHAR(50),                    -- 'xlogin' or 'qlogin'
    status ENUM('active', 'inactive'),
    token TEXT NULL,                    -- Bearer token (X System)
    cookie TEXT NULL,                   -- Session cookie (Q System)
    created_at TIMESTAMP,
    expire_at TIMESTAMP,
    updated_at TIMESTAMP
);
```

### VsLastSyncStatus Table (Q System only)
```sql
CREATE TABLE vs_last_sync_statuses (
    id BIGINT PRIMARY KEY,
    key VARCHAR(50),                    -- 'qTreadeOrderLog'
    date DATE,
    time TIME,
    count INT,
    last_sync TIMESTAMP,
    created_at TIMESTAMP,
    updated_at TIMESTAMP
);
```

## API Routes

### X System Routes

#### Public Endpoints
```
POST   /api/x-operation/login
POST   /api/x-operation/logout
GET    /api/x-operation/check-token
```

#### Protected Endpoints (require api.key + role.access)
```
GET    /api/x-operation/ledger-balance/{clientCode}
GET    /api/x-operation/ledger?inv_code=X&from_date=YYYY-MM-DD&to_date=YYYY-MM-DD
GET    /api/x-operation/portfolio?inv_code=X&eod_date=YYYY-MM-DD
```

### Q System Routes

#### Public Endpoints
```
GET    /api/q-operation/login
GET    /api/q-operation/logout
GET    /api/q-operation/check-token
GET    /api/q-operation/order-log
```

## Request/Response Examples

### X System Login
**Request:**
```bash
POST /api/x-operation/login
Content-Type: application/json
```

**Response (201):**
```json
{
  "success": true,
  "message": "Login successful",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs..."
  }
}
```

**Response (401):**
```json
{
  "success": false,
  "message": "Failed to authenticate with X System"
}
```

### Get Ledger Balance
**Request:**
```bash
GET /api/x-operation/ledger-balance/0525
X-API-Key: client-api-key-here
```

**Response (200):**
```json
{
  "success": true,
  "data": {
    "balance": 150000,
    "currency": "BDT",
    "lastUpdated": "2024-02-09T10:30:00Z"
  }
}
```

**Response (401 - Token Expired):**
```json
{
  "success": false,
  "message": "Token expired and login failed"
}
```

**Response (422 - Validation Error):**
```json
{
  "success": false,
  "message": "Client code is required"
}
```

### Get Ledger Statement
**Request:**
```bash
GET /api/x-operation/ledger?inv_code=0525&from_date=2024-01-01&to_date=2024-01-31
X-API-Key: client-api-key-here
```

**Response (200):**
```json
{
  "success": true,
  "data": [
    {
      "date": "2024-01-05",
      "description": "Buy AAPL 100",
      "debit": 15000,
      "credit": 0,
      "balance": 135000
    },
    {
      "date": "2024-01-06",
      "description": "Dividend AAPL",
      "debit": 0,
      "credit": 250,
      "balance": 135250
    }
  ]
}
```

### Q System Login
**Request:**
```bash
GET /api/q-operation/login
```

**Response (200):**
```json
{
  "response": { /* login response */ },
  "cookie": "SESSIONID=abc123def456...",
  "status": true,
  "message": "Login successful and cookie stored"
}
```

## Error Handling

All errors are wrapped in consistent JSON format:

```json
{
  "success": false,
  "message": "Error description"
}
```

### HTTP Status Codes
- `200`: Success
- `201`: Created (login successful)
- `401`: Unauthorized (invalid credentials, token expired)
- `422`: Validation error (missing/invalid parameters)
- `500`: Server error (configuration missing, external API error)

## Implementation Notes

### Token Auto-Refresh
When a protected endpoint receives a 401 error:
1. It calls the internal login method
2. Gets a new token
3. Retries the original request once

### Database-Driven Configuration
All endpoints and credentials are fetched from the database:
- **VsLogin** - Stores credentials for each broker system
- **VsEndPoint** - Stores API endpoint URLs
- **VsLoginToken** - Stores current valid tokens/cookies
- **VsLastSyncStatus** - Tracks synchronization status (Q System)

This allows updating credentials and endpoints without code changes.

### Cookie vs Token
- **X System** (XOperationController): Uses Bearer tokens in Authorization header
- **Q System** (QOperationController): Uses session cookies in Cookie header

Both use the same VsLoginToken table with different fields (token vs cookie).

## Testing

### Test with cURL

**Test X System Login:**
```bash
curl -X POST http://localhost:8000/api/x-operation/login \
  -H "Content-Type: application/json"
```

**Test Protected Endpoint:**
```bash
curl -X GET "http://localhost:8000/api/x-operation/ledger-balance/0525" \
  -H "X-API-Key: your-api-key-here"
```

**Test Q System Login:**
```bash
curl -X GET http://localhost:8000/api/q-operation/login
```

## Security Considerations

1. **API Key Middleware**: Protected endpoints require valid X-API-Key header
2. **Role-Based Access**: Additional role.access middleware checks user permissions
3. **SSL Verification Disabled**: Currently disabled in cURL (CURLOPT_SSL_VERIFYPEER = false)
   - Enable in production: Set CURLOPT_SSL_VERIFYPEER = true
4. **Token Expiration**: Tokens automatically expire and are refreshed on demand
5. **Database Credentials**: Never hardcode; always use VsLogin table

## Troubleshooting

### Issue: Token not being stored
- Check if VsLoginToken table exists and is accessible
- Verify xlogin/qlogin key exists in VsLoginToken

### Issue: 401 Unauthorized on protected endpoints
- Verify API client has valid api.key in database
- Check token hasn't expired (via check-token endpoint)
- Manually call login endpoint to refresh token

### Issue: Endpoint configuration not found
- Verify VsEndPoint entries exist with correct keys (x_login, x_logout, etc.)
- Check endpoint URLs are accessible from server

### Issue: cURL SSL errors
- CURLOPT_SSL_VERIFYPEER is disabled by default (not recommended for production)
- To enable: Modify httpRequest() method and provide valid certificates

