279 lines
15 KiB
Markdown
279 lines
15 KiB
Markdown
# P0 Finance API Gap Analysis Report
|
|
|
|
**Date:** 2026-06-21
|
|
**Author:** Fast Coder (Core Developer)
|
|
**Scope:** `fleet_finance` and `finance` schema models vs FastAPI endpoints
|
|
**Status:** ✅ Part 1 API Tests Passed (6/6)
|
|
|
|
---
|
|
|
|
## 1. Executive Summary
|
|
|
|
This report audits all SQLAlchemy models in the `fleet_finance` and `finance` schemas against their corresponding FastAPI REST endpoints. The goal is to identify which models have full CRUD coverage, which have partial coverage, and which are completely missing API access.
|
|
|
|
**Key Finding:** Out of **13 finance-related models** across both schemas, **7 have dedicated API endpoints**, **2 have indirect coverage** (via other endpoints), and **4 have NO API endpoints at all**.
|
|
|
|
---
|
|
|
|
## 2. Part 1: API Test Results ✅
|
|
|
|
All 6 Phase 1 finance API endpoints were tested and passed:
|
|
|
|
| # | Endpoint | Method | Status | Response |
|
|
|---|----------|--------|--------|----------|
|
|
| 1 | `/api/v1/assets/vehicles/{asset_id}/financials` | GET | ✅ 200 | Full financial data returned |
|
|
| 2 | `/api/v1/assets/vehicles/{asset_id}/financials` | PATCH | ✅ 200 | Partial update applied (monthly_installment: 50000→75000) |
|
|
| 3 | `/api/v1/assets/vehicles/{asset_id}/insurance` | GET | ✅ 200 | Empty list (no policies yet) |
|
|
| 4 | `/api/v1/assets/vehicles/{asset_id}/insurance` | POST | ✅ 201 | KGFB policy created |
|
|
| 5 | `/api/v1/assets/vehicles/{asset_id}/tax` | GET | ✅ 200 | Empty list (no obligations yet) |
|
|
| 6 | `/api/v1/assets/vehicles/{asset_id}/tax` | POST | ✅ 201 | WEIGHT_TAX obligation created |
|
|
|
|
**Test Asset Used:** `7ebedcdf-9316-42a4-a6e0-7ce656668cf9` (TEST-API-999, org 1)
|
|
**Auth:** `admin@profibot.hu` (member of org 1 with ADMIN role)
|
|
|
|
---
|
|
|
|
## 3. Schema: `fleet_finance` — Model vs API Matrix
|
|
|
|
| # | Model | Schema | Table | GET | POST | PATCH/PUT | DELETE | CRUD Status |
|
|
|---|-------|--------|-------|-----|------|-----------|--------|-------------|
|
|
| 1 | **CostCategory** | `fleet_finance` | `cost_categories` | ❌ | ❌ | ❌ | ❌ | **❌ MISSING** |
|
|
| 2 | **AssetCost** | `fleet_finance` | `asset_costs` | ✅ | ✅ | ❌ | ❌ | ⚠️ Partial (R+C) |
|
|
| 3 | **AssetFinancials** | `fleet_finance` | `asset_financials` | ✅ | ❌ | ✅ | ❌ | ⚠️ Partial (R+U) |
|
|
| 4 | **InsuranceProvider** | `fleet_finance` | `insurance_providers` | ❌ | ❌ | ❌ | ❌ | **❌ MISSING** |
|
|
| 5 | **VehicleInsurancePolicy** | `fleet_finance` | `vehicle_insurance_policies` | ✅ | ✅ | ❌ | ❌ | ⚠️ Partial (R+C) |
|
|
| 6 | **VehicleTaxObligation** | `fleet_finance` | `vehicle_tax_obligations` | ✅ | ✅ | ❌ | ❌ | ⚠️ Partial (R+C) |
|
|
|
|
### 3.1 Detailed Findings — `fleet_finance`
|
|
|
|
#### ✅ CostCategory — ❌ NO API Endpoints
|
|
- **File:** [`backend/app/models/fleet_finance/models.py`](../backend/app/models/fleet_finance/models.py:35)
|
|
- **Purpose:** Hierarchical cost categories (FUEL, MAINTENANCE, REPAIR, etc.)
|
|
- **Used indirectly** by `AssetCost` via `category_id` FK
|
|
- **No dedicated router** exists for CRUD operations on categories
|
|
- **Impact:** Categories must be seeded via DB scripts (see `seed_cost_category_tiers.py`, `seed_cost_category_visibility.py`)
|
|
- **Recommendation:** Create a `/api/v1/cost-categories` CRUD endpoint for admin management
|
|
|
|
#### ✅ AssetCost — ⚠️ Partial (Read + Create only)
|
|
- **File:** [`backend/app/models/fleet_finance/models.py`](../backend/app/models/fleet_finance/models.py:96)
|
|
- **Endpoints:**
|
|
- `GET /api/v1/assets/{asset_id}/costs` — list costs for an asset ✅
|
|
- `POST /api/v1/expenses/` — create expense (with Smart Linking to AssetEvent) ✅
|
|
- `GET /api/v1/expenses/{asset_id}` — list expenses with category enrichment ✅
|
|
- **Missing:** PATCH (update) and DELETE endpoints
|
|
- **Recommendation:** Add PATCH/DELETE for expense management
|
|
|
|
#### ✅ AssetFinancials — ⚠️ Partial (Read + Update only)
|
|
- **File:** [`backend/app/models/fleet_finance/models.py`](../backend/app/models/fleet_finance/models.py:141)
|
|
- **Endpoints:**
|
|
- `GET /api/v1/assets/vehicles/{asset_id}/financials` ✅
|
|
- `PATCH /api/v1/assets/vehicles/{asset_id}/financials` ✅
|
|
- **Missing:** POST (create) endpoint — PATCH requires pre-existing record
|
|
- **Workaround:** Must be created via direct DB insert or admin script
|
|
- **Recommendation:** Add a POST endpoint to create AssetFinancials records
|
|
|
|
#### ✅ InsuranceProvider — ❌ NO API Endpoints
|
|
- **File:** [`backend/app/models/fleet_finance/models.py`](../backend/app/models/fleet_finance/models.py:180)
|
|
- **Purpose:** Insurance company catalog (name, claim_phone, services_offered)
|
|
- **No API endpoints** exist for listing, creating, or managing providers
|
|
- **Impact:** Cannot create insurance policies via API without pre-seeding providers
|
|
- **Recommendation:** Create a `/api/v1/insurance-providers` CRUD endpoint
|
|
|
|
#### ✅ VehicleInsurancePolicy — ⚠️ Partial (Read + Create only)
|
|
- **File:** [`backend/app/models/fleet_finance/models.py`](../backend/app/models/fleet_finance/models.py:208)
|
|
- **Endpoints:**
|
|
- `GET /api/v1/assets/vehicles/{asset_id}/insurance` ✅
|
|
- `POST /api/v1/assets/vehicles/{asset_id}/insurance` ✅
|
|
- **Missing:** PATCH (update policy details), DELETE (cancel policy)
|
|
- **Recommendation:** Add PATCH for policy updates (e.g., renewal, premium change)
|
|
|
|
#### ✅ VehicleTaxObligation — ⚠️ Partial (Read + Create only)
|
|
- **File:** [`backend/app/models/fleet_finance/models.py`](../backend/app/models/fleet_finance/models.py:252)
|
|
- **Endpoints:**
|
|
- `GET /api/v1/assets/vehicles/{asset_id}/tax` ✅
|
|
- `POST /api/v1/assets/vehicles/{asset_id}/tax` ✅
|
|
- **Missing:** PATCH (update payment status), DELETE
|
|
- **Recommendation:** Add PATCH for payment status updates
|
|
|
|
---
|
|
|
|
## 4. Schema: `finance` — Model vs API Matrix
|
|
|
|
| # | Model | Schema | Table | GET | POST | PATCH/PUT | DELETE | CRUD Status |
|
|
|---|-------|--------|-------|-----|------|-----------|--------|-------------|
|
|
| 1 | **Issuer** | `finance` | `issuers` | ✅ | ❌ | ✅ | ❌ | ⚠️ Partial (R+U) |
|
|
| 2 | **PaymentIntent** | `finance` | `payment_intents` | ✅ | ✅ | ❌ | ❌ | ⚠️ Partial (R+C) |
|
|
| 3 | **WithdrawalRequest** | `finance` | `withdrawal_requests` | ❌ | ❌ | ❌ | ❌ | **❌ MISSING** |
|
|
| 4 | **OrganizationSubscription** | `finance` | `org_subscriptions` | ❌ | ❌ | ❌ | ❌ | **❌ MISSING** |
|
|
| 5 | **UserSubscription** | `finance` | `user_subscriptions` | ❌ | ❌ | ❌ | ❌ | **❌ MISSING** |
|
|
| 6 | **CreditTransaction** | `finance` | `credit_transactions` | ❌ | ❌ | ❌ | ❌ | **❌ MISSING** |
|
|
| 7 | **FinancialLedger** | `audit` | `financial_ledger` | ✅ | ❌ | ❌ | ❌ | ⚠️ Partial (R) |
|
|
|
|
### 4.1 Detailed Findings — `finance`
|
|
|
|
#### ✅ Issuer — ⚠️ Partial (Read + Update only, Admin-only)
|
|
- **File:** [`backend/app/models/marketplace/finance.py`](../backend/app/models/marketplace/finance.py:27)
|
|
- **Endpoints:**
|
|
- `GET /api/v1/finance-admin/` — list issuers (admin only) ✅
|
|
- `PATCH /api/v1/finance-admin/{issuer_id}` — update issuer (admin only) ✅
|
|
- **Missing:** POST (create issuer), public listing
|
|
- **Note:** Admin-only access via `check_finance_admin_access` dependency
|
|
|
|
#### ✅ PaymentIntent — ⚠️ Partial (Read + Create only)
|
|
- **File:** [`backend/app/models/marketplace/payment.py`](../backend/app/models/marketplace/payment.py:30)
|
|
- **Endpoints:**
|
|
- `POST /api/v1/billing/payment-intent/create` ✅
|
|
- `POST /api/v1/billing/payment-intent/{id}/stripe-checkout` ✅
|
|
- `POST /api/v1/billing/payment-intent/{id}/process-internal` ✅
|
|
- `GET /api/v1/billing/payment-intent/{id}/status` ✅
|
|
- `POST /api/v1/billing/stripe-webhook` ✅
|
|
- **Note:** Well-covered for payment flow; no direct PATCH/DELETE needed
|
|
|
|
#### ❌ WithdrawalRequest — ❌ NO API Endpoints
|
|
- **File:** [`backend/app/models/marketplace/payment.py`](../backend/app/models/marketplace/payment.py:147)
|
|
- **Purpose:** Withdrawal requests from Earned wallet (user_id, amount, payout_method, status, approval)
|
|
- **Has domain methods:** `approve()`, `reject()`, `cancel()`, `is_expired()`
|
|
- **No API endpoints** exist for creating or managing withdrawal requests
|
|
- **Impact:** Users cannot request payouts from their Earned wallet
|
|
- **Recommendation:** Create `/api/v1/billing/withdrawals` CRUD endpoint
|
|
|
|
#### ❌ OrganizationSubscription — ❌ NO API Endpoints
|
|
- **File:** [`backend/app/models/core_logic.py`](../backend/app/models/core_logic.py:25)
|
|
- **Purpose:** Organization subscription plans with extra_allowances JSONB
|
|
- **No dedicated API endpoints** — used indirectly via billing upgrade flow
|
|
- **Note:** The `POST /api/v1/billing/upgrade` endpoint handles subscription changes but doesn't expose the model directly
|
|
|
|
#### ❌ UserSubscription — ❌ NO API Endpoints
|
|
- **File:** [`backend/app/models/core_logic.py`](../backend/app/models/core_logic.py:49)
|
|
- **Purpose:** User-level subscriptions
|
|
- **No API endpoints** at all
|
|
|
|
#### ❌ CreditTransaction — ❌ NO API Endpoints
|
|
- **File:** [`backend/app/models/core_logic.py`](../backend/app/models/core_logic.py:72)
|
|
- **Purpose:** Credit transaction logs (org_id, amount, description)
|
|
- **No API endpoints** at all
|
|
- **Note:** Credits are managed internally by the billing engine
|
|
|
|
#### ✅ FinancialLedger — ⚠️ Partial (Read only)
|
|
- **File:** [`backend/app/models/system/audit.py`](../backend/app/models/system/audit.py:78)
|
|
- **Endpoints:**
|
|
- `GET /api/v1/billing/wallet/transactions` — list transactions with pagination ✅
|
|
- **Missing:** No write endpoints (ledger is append-only by design)
|
|
- **Note:** Read-only access is correct for an audit log
|
|
|
|
---
|
|
|
|
## 5. Gap Summary
|
|
|
|
### 5.1 Critical Gaps (No API Access)
|
|
|
|
| Model | Schema | Impact | Priority |
|
|
|-------|--------|--------|----------|
|
|
| **InsuranceProvider** | `fleet_finance` | Cannot create insurance policies without pre-seeded providers | **HIGH** |
|
|
| **CostCategory** | `fleet_finance` | Categories must be managed via DB scripts | **MEDIUM** |
|
|
| **WithdrawalRequest** | `finance` | Users cannot request Earned wallet payouts | **HIGH** |
|
|
| **OrganizationSubscription** | `finance` | No direct subscription management API | **MEDIUM** |
|
|
| **UserSubscription** | `finance` | No direct user subscription API | **LOW** |
|
|
| **CreditTransaction** | `finance` | Credits managed internally; read-only may suffice | **LOW** |
|
|
|
|
### 5.2 Partial Coverage Gaps
|
|
|
|
| Model | Missing Operations | Impact | Priority |
|
|
|-------|-------------------|--------|----------|
|
|
| **AssetFinancials** | POST (create) | Must pre-seed via DB before PATCH works | **MEDIUM** |
|
|
| **AssetCost** | PATCH, DELETE | Cannot update or remove expenses | **MEDIUM** |
|
|
| **VehicleInsurancePolicy** | PATCH, DELETE | Cannot update or cancel policies | **LOW** |
|
|
| **VehicleTaxObligation** | PATCH, DELETE | Cannot update payment status | **LOW** |
|
|
| **Issuer** | POST (create) | Must be created via DB or admin panel | **LOW** |
|
|
|
|
---
|
|
|
|
## 6. Recommendations
|
|
|
|
### Phase 2 — High Priority
|
|
1. **Create `/api/v1/insurance-providers` CRUD endpoint** — enables dynamic provider management
|
|
2. **Create `/api/v1/billing/withdrawals` CRUD endpoint** — enables Earned wallet payout requests
|
|
3. **Add POST `/api/v1/assets/vehicles/{asset_id}/financials`** — enables creating financial records via API
|
|
|
|
### Phase 3 — Medium Priority
|
|
4. **Create `/api/v1/cost-categories` CRUD endpoint** — enables category management via API
|
|
5. **Add PATCH/DELETE to `/api/v1/expenses/{expense_id}`** — enables expense editing
|
|
6. **Add subscription management endpoints** — enables direct plan changes
|
|
|
|
### Phase 4 — Low Priority
|
|
7. **Add PATCH to insurance/tax endpoints** — enables status updates
|
|
8. **Add Issuer POST endpoint** — enables provider creation via admin panel
|
|
|
|
---
|
|
|
|
## 7. Endpoint Inventory (All Finance-Related)
|
|
|
|
### Router: `assets.py` (prefix: `/api/v1/assets`)
|
|
| Method | Path | Model | Status |
|
|
|--------|------|-------|--------|
|
|
| GET | `/vehicles/{asset_id}/financials` | AssetFinancials | ✅ Tested |
|
|
| PATCH | `/vehicles/{asset_id}/financials` | AssetFinancials | ✅ Tested |
|
|
| GET | `/vehicles/{asset_id}/insurance` | VehicleInsurancePolicy | ✅ Tested |
|
|
| POST | `/vehicles/{asset_id}/insurance` | VehicleInsurancePolicy | ✅ Tested |
|
|
| GET | `/vehicles/{asset_id}/tax` | VehicleTaxObligation | ✅ Tested |
|
|
| POST | `/vehicles/{asset_id}/tax` | VehicleTaxObligation | ✅ Tested |
|
|
| GET | `/{asset_id}/financial-summary` | Asset (aggregated) | Not tested |
|
|
| GET | `/{asset_id}/costs` | AssetCost | Not tested |
|
|
|
|
### Router: `expenses.py` (prefix: `/api/v1/expenses`)
|
|
| Method | Path | Model | Status |
|
|
|--------|------|-------|--------|
|
|
| GET | `/{asset_id}` | AssetCost | Not tested |
|
|
| POST | `/` | AssetCost | Not tested |
|
|
|
|
### Router: `finance_admin.py` (prefix: `/api/v1/finance-admin`)
|
|
| Method | Path | Model | Status |
|
|
|--------|------|-------|--------|
|
|
| GET | `/` | Issuer | Not tested |
|
|
| PATCH | `/{issuer_id}` | Issuer | Not tested |
|
|
|
|
### Router: `billing.py` (prefix: `/api/v1/billing`)
|
|
| Method | Path | Model | Status |
|
|
|--------|------|-------|--------|
|
|
| POST | `/upgrade` | OrganizationSubscription | Not tested |
|
|
| POST | `/payment-intent/create` | PaymentIntent | Not tested |
|
|
| POST | `/payment-intent/{id}/stripe-checkout` | PaymentIntent | Not tested |
|
|
| POST | `/payment-intent/{id}/process-internal` | PaymentIntent | Not tested |
|
|
| POST | `/stripe-webhook` | PaymentIntent | Not tested |
|
|
| GET | `/payment-intent/{id}/status` | PaymentIntent | Not tested |
|
|
| GET | `/wallet/balance` | FinancialLedger (aggregated) | Not tested |
|
|
| GET | `/wallet/transactions` | FinancialLedger | Not tested |
|
|
|
|
---
|
|
|
|
## 8. Appendix: Schema Details
|
|
|
|
### `fleet_finance` Schema Tables
|
|
| Table | Primary Key | Key Columns |
|
|
|-------|-------------|-------------|
|
|
| `cost_categories` | `id` (int) | `parent_id`, `code`, `name`, `is_system`, `visibility`, `min_tier` |
|
|
| `asset_costs` | `id` (int) | `asset_id`, `organization_id`, `category_id`, `amount_net/gross`, `vat_rate`, `status`, `linked_asset_event_id` |
|
|
| `asset_financials` | `id` (int) | `asset_id`, `purchase_price_net/gross`, `financing_type`, `accounting_details` (JSONB), `monthly_installment`, `down_payment` |
|
|
| `insurance_providers` | `id` (int) | `name`, `claim_phone`, `claim_url`, `services_offered` (JSONB), `is_active` |
|
|
| `vehicle_insurance_policies` | `id` (uuid) | `asset_id`, `provider_id`, `insurance_type`, `policy_number`, `start/expiry_date`, `premium_amount` |
|
|
| `vehicle_tax_obligations` | `id` (uuid) | `asset_id`, `tax_type`, `tax_year`, `amount`, `due_date`, `payment_status` |
|
|
|
|
### `finance` Schema Tables
|
|
| Table | Primary Key | Key Columns |
|
|
|-------|-------------|-------------|
|
|
| `issuers` | `id` (int) | `name`, `tax_id`, `type` (KFT/EV/BT/ZRT/OTHER), `revenue_limit`, `current_revenue`, `api_config` (JSONB) |
|
|
| `payment_intents` | `id` (uuid) | `intent_token`, `payer_id`, `beneficiary_id`, `target_wallet_type`, `net/handling/gross` amounts, `status`, `stripe_*` fields |
|
|
| `withdrawal_requests` | `id` (uuid) | `user_id`, `amount`, `payout_method`, `status`, `approved_by`, `approved_at`, `rejection_reason` |
|
|
| `org_subscriptions` | `id` (int) | `organization_id`, `tier_id`, `start/end_date`, `status`, `extra_allowances` (JSONB) |
|
|
| `user_subscriptions` | `id` (int) | `user_id`, `tier_id`, `start/end_date`, `status` |
|
|
| `credit_transactions` | `id` (int) | `organization_id`, `amount`, `description`, `created_at` |
|
|
|
|
### `audit` Schema Tables
|
|
| Table | Primary Key | Key Columns |
|
|
|-------|-------------|-------------|
|
|
| `financial_ledger` | `id` (int) | `user_id`, `amount`, `entry_type` (DEBIT/CREDIT), `wallet_type`, `transaction_id`, `status`, `issuer_id`, `invoice_*` fields |
|
|
|
|
---
|
|
|
|
*Report generated by Fast Coder (Core Developer) — 2026-06-21*
|