# 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*