frontend költség beállítások
This commit is contained in:
227
docs/db_consistency_and_zombie_api_report.md
Normal file
227
docs/db_consistency_and_zombie_api_report.md
Normal file
@@ -0,0 +1,227 @@
|
||||
# P0 DEEP AUDIT - Database Consistency & Zombie API Hunt Report
|
||||
|
||||
**Date:** 2026-06-21
|
||||
**Author:** Fast Coder (Core Developer)
|
||||
**Gitea Issue:** #274
|
||||
**Scope:** Database schemas `vehicle`, `finance`, `fleet_finance` + Backend API endpoints
|
||||
|
||||
---
|
||||
|
||||
## 1. Database Cleanliness
|
||||
|
||||
### 1.1 Schema: `vehicle` (20 tables)
|
||||
|
||||
| Table | Purpose | Status |
|
||||
|-------|---------|--------|
|
||||
| `assets` | Core vehicle assets (thick model) | ✅ Clean |
|
||||
| `asset_events` | Service/maintenance events | ✅ Clean |
|
||||
| `asset_inspections` | Inspection records | ✅ Clean |
|
||||
| `asset_reviews` | User reviews | ✅ Clean |
|
||||
| `asset_telemetry` | Telemetry data | ✅ Clean |
|
||||
| `auto_data_crawler_queue` | Crawler queue | ✅ Clean |
|
||||
| `catalog_discovery` | Catalog discovery queue | ✅ Clean |
|
||||
| `dict_body_types` | Body type dictionary | ✅ Clean |
|
||||
| `external_reference_library` | External reference data | ✅ Clean |
|
||||
| `feature_definitions` | Feature definitions | ✅ Clean |
|
||||
| `gb_catalog_discovery` | GB catalog discovery | ✅ Clean |
|
||||
| `model_feature_maps` | Model-feature mappings | ✅ Clean |
|
||||
| `motorcycle_specs` | Motorcycle specs | ✅ Clean |
|
||||
| `odometer_readings` | Odometer readings | ✅ Clean |
|
||||
| `reference_lookup` | Reference lookup | ✅ Clean |
|
||||
| `vehicle_catalog` | Vehicle catalog | ✅ Clean |
|
||||
| `vehicle_logbook` | Trip logbook | ✅ Clean |
|
||||
| `vehicle_model_definitions` | Master model definitions | ✅ Clean |
|
||||
| `vehicle_ownership_history` | Ownership history | ✅ Clean |
|
||||
| `vehicle_transfer_requests` | Transfer requests | ✅ Clean |
|
||||
| `vehicle_types` | Vehicle type dictionary | ✅ Clean |
|
||||
| `vehicle_user_ratings` | User ratings | ✅ Clean |
|
||||
|
||||
### 1.2 Schema: `fleet_finance` (6 tables)
|
||||
|
||||
| Table | Purpose | Status |
|
||||
|-------|---------|--------|
|
||||
| `asset_costs` | Cost ledger (moved from `vehicle`) | ✅ Clean |
|
||||
| `asset_financials` | Purchase/financing data (moved from `vehicle`) | ✅ Clean |
|
||||
| `cost_categories` | Cost category hierarchy (moved from `vehicle`) | ✅ Clean |
|
||||
| `insurance_providers` | Insurance provider catalog | ✅ Clean |
|
||||
| `vehicle_insurance_policies` | Vehicle insurance policies | ✅ Clean |
|
||||
| `vehicle_tax_obligations` | Vehicle tax obligations | ✅ Clean |
|
||||
|
||||
### 1.3 Schema: `finance` (7 tables)
|
||||
|
||||
| Table | Purpose | Status |
|
||||
|-------|---------|--------|
|
||||
| `credit_logs` | Credit transactions | ✅ Clean |
|
||||
| `exchange_rates` | Currency exchange rates | ✅ Clean |
|
||||
| `issuers` | Billing entities | ✅ Clean |
|
||||
| `org_subscriptions` | Organization subscriptions | ✅ Clean |
|
||||
| `payment_intents` | Payment intents | ✅ Clean |
|
||||
| `user_subscriptions` | User subscriptions | ✅ Clean |
|
||||
| `withdrawal_requests` | Withdrawal requests | ✅ Clean |
|
||||
|
||||
### 1.4 Critical Checks
|
||||
|
||||
| Check | Result |
|
||||
|-------|--------|
|
||||
| `vehicle.vehicle_expenses` exists? | ❌ **NOT FOUND** - Correctly removed |
|
||||
| `vehicle.costs` (VehicleCost) exists? | ❌ **NOT FOUND** - Correctly removed |
|
||||
| `data` schema has leftover tables? | ❌ **NOT FOUND** - Schema is empty |
|
||||
| Duplicate table names between `vehicle` and `fleet_finance`? | ❌ **NONE** - No overlap |
|
||||
| Legacy `expense`/`cost` tables anywhere? | ❌ **NONE** - Clean |
|
||||
|
||||
**Verdict: ✅ DATABASE IS CLEAN.** No duplicated tables, no legacy tables left behind. The migration of `AssetCost`, `CostCategory`, `AssetFinancials` from `vehicle` → `fleet_finance` schema is complete.
|
||||
|
||||
---
|
||||
|
||||
## 2. Zombie API Endpoints
|
||||
|
||||
### 2.1 🔴 CRITICAL: [`reports.py`](backend/app/api/v1/endpoints/reports.py) - References `vehicle.vehicle_expenses`
|
||||
|
||||
**File:** [`backend/app/api/v1/endpoints/reports.py`](backend/app/api/v1/endpoints/reports.py:18)
|
||||
|
||||
Two endpoints use raw SQL queries referencing the **non-existent** `vehicle.vehicle_expenses` table:
|
||||
|
||||
1. **`GET /reports/summary/{vehicle_id}`** (line 8-32) - Queries `FROM vehicle.vehicle_expenses`
|
||||
2. **`GET /reports/trends/{vehicle_id}`** (line 34-50) - Queries `FROM vehicle.vehicle_expenses`
|
||||
|
||||
**Impact:** These endpoints will **ALWAYS return 500 errors** because the table `vehicle.vehicle_expenses` does not exist in the database.
|
||||
|
||||
**Router registration:** [`api.py`](backend/app/api/v1/api.py:33) - Registered as `prefix="/reports"`
|
||||
|
||||
### 2.2 🟡 WARNING: [`expenses.py`](backend/app/api/v1/endpoints/expenses.py) - Uses `AssetCost` from `fleet_finance` (correct)
|
||||
|
||||
**File:** [`backend/app/api/v1/endpoints/expenses.py`](backend/app/api/v1/endpoints/expenses.py:10)
|
||||
|
||||
Imports `AssetCost` and `CostCategory` from `app.models` which correctly resolves to `fleet_finance` schema models. **This is NOT a zombie** - it's correctly using the moved models.
|
||||
|
||||
### 2.3 🟡 WARNING: [`assets.py`](backend/app/api/v1/endpoints/assets.py) - Uses `AssetCost` from `fleet_finance` (correct)
|
||||
|
||||
**File:** [`backend/app/api/v1/endpoints/assets.py`](backend/app/api/v1/endpoints/assets.py:14-15)
|
||||
|
||||
Imports `AssetCost`, `CostCategory` from `app.models` and `AssetFinancials`, `VehicleInsurancePolicy`, `VehicleTaxObligation` from `app.models.fleet_finance`. **Correctly references the new schema.**
|
||||
|
||||
### 2.4 🟢 OK: [`dictionaries.py`](backend/app/api/v1/endpoints/dictionaries.py) - Uses `CostCategory` from `fleet_finance`
|
||||
|
||||
**File:** [`backend/app/api/v1/endpoints/dictionaries.py`](backend/app/api/v1/endpoints/dictionaries.py:13)
|
||||
|
||||
Imports `CostCategory` from `app.models.fleet_finance`. **Correct.**
|
||||
|
||||
### 2.5 Zombie API Summary
|
||||
|
||||
| Endpoint File | Route Prefix | Status | Issue |
|
||||
|---------------|-------------|--------|-------|
|
||||
| `reports.py` | `/reports/summary/{id}` | 🔴 **ZOMBIE** | References `vehicle.vehicle_expenses` (DNE) |
|
||||
| `reports.py` | `/reports/trends/{id}` | 🔴 **ZOMBIE** | References `vehicle.vehicle_expenses` (DNE) |
|
||||
| `reports.py` | `/reports/summary/latest` | 🟢 OK | Returns mock data only |
|
||||
| `expenses.py` | `/expenses/{asset_id}` | 🟢 OK | Uses `AssetCost` from `fleet_finance` |
|
||||
| `assets.py` | `/assets/vehicles/{id}/costs` | 🟢 OK | Uses `AssetCost` from `fleet_finance` |
|
||||
| `assets.py` | `/assets/vehicles/{id}/insurance` | 🟢 OK | Uses `VehicleInsurancePolicy` |
|
||||
| `assets.py` | `/assets/vehicles/{id}/tax` | 🟢 OK | Uses `VehicleTaxObligation` |
|
||||
| `dictionaries.py` | `/dictionaries/cost-categories` | 🟢 OK | Uses `CostCategory` from `fleet_finance` |
|
||||
|
||||
---
|
||||
|
||||
## 3. InsuranceProvider & Missing CRUD Analysis
|
||||
|
||||
### 3.1 InsuranceProvider Model
|
||||
|
||||
The [`InsuranceProvider`](backend/app/models/fleet_finance/models.py:180) model exists in `fleet_finance.insurance_providers` with fields:
|
||||
- `id` (Integer, PK)
|
||||
- `name` (String, unique)
|
||||
- `claim_phone` (String, nullable)
|
||||
- `claim_url` (String, nullable)
|
||||
- `services_offered` (JSONB)
|
||||
- `is_active` (Boolean)
|
||||
|
||||
### 3.2 Existing Insurance/Tax Endpoints in [`assets.py`](backend/app/api/v1/endpoints/assets.py)
|
||||
|
||||
| Method | Route | Exists? |
|
||||
|--------|-------|---------|
|
||||
| `GET` | `/assets/vehicles/{asset_id}/insurance` | ✅ Yes (list) |
|
||||
| `POST` | `/assets/vehicles/{asset_id}/insurance` | ✅ Yes (create) |
|
||||
| `PUT` | `/assets/vehicles/{asset_id}/insurance/{policy_id}` | ❌ **MISSING** |
|
||||
| `DELETE` | `/assets/vehicles/{asset_id}/insurance/{policy_id}` | ❌ **MISSING** |
|
||||
| `GET` | `/assets/vehicles/{asset_id}/tax` | ✅ Yes (list) |
|
||||
| `POST` | `/assets/vehicles/{asset_id}/tax` | ✅ Yes (create) |
|
||||
| `PUT` | `/assets/vehicles/{asset_id}/tax/{tax_id}` | ❌ **MISSING** |
|
||||
| `DELETE` | `/assets/vehicles/{asset_id}/tax/{tax_id}` | ❌ **MISSING** |
|
||||
|
||||
### 3.3 InsuranceProvider CRUD (Standalone)
|
||||
|
||||
| Method | Route | Exists? |
|
||||
|--------|-------|---------|
|
||||
| `GET` | `/insurance-providers` | ❌ **MISSING** |
|
||||
| `GET` | `/insurance-providers/{id}` | ❌ **MISSING** |
|
||||
| `POST` | `/insurance-providers` | ❌ **MISSING** |
|
||||
| `PUT` | `/insurance-providers/{id}` | ❌ **MISSING** |
|
||||
| `DELETE` | `/insurance-providers/{id}` | ❌ **MISSING** |
|
||||
|
||||
**No schema exists for InsuranceProvider** - searched `backend/app/schemas/` for `InsuranceProvider` patterns - **0 results**.
|
||||
|
||||
---
|
||||
|
||||
## 4. Action Plan
|
||||
|
||||
### 4.1 🔴 P0 - Fix Zombie Endpoints in `reports.py`
|
||||
|
||||
**Problem:** Two endpoints in [`reports.py`](backend/app/api/v1/endpoints/reports.py) reference the non-existent `vehicle.vehicle_expenses` table.
|
||||
|
||||
**Solution:** Rewrite the raw SQL queries to use the new `fleet_finance.asset_costs` table with proper joins to `cost_categories`:
|
||||
|
||||
```python
|
||||
# Replace raw SQL with SQLAlchemy ORM queries using AssetCost + CostCategory
|
||||
from app.models import AssetCost, CostCategory
|
||||
from sqlalchemy import select, func
|
||||
|
||||
# GET /reports/summary/{vehicle_id}
|
||||
stmt = select(
|
||||
CostCategory.code.label("category"),
|
||||
func.sum(AssetCost.amount_gross).label("total_amount"),
|
||||
func.count(AssetCost.id).label("transaction_count")
|
||||
).outerjoin(CostCategory, AssetCost.category_id == CostCategory.id
|
||||
).where(AssetCost.asset_id == vehicle_id
|
||||
).group_by(CostCategory.code)
|
||||
```
|
||||
|
||||
**Estimated effort:** 30 minutes
|
||||
|
||||
### 4.2 🟡 P1 - Add UPDATE/DELETE for Insurance Policies and Tax Obligations
|
||||
|
||||
**Missing endpoints in [`assets.py`](backend/app/api/v1/endpoints/assets.py):**
|
||||
|
||||
1. `PUT /assets/vehicles/{asset_id}/insurance/{policy_id}` - Update insurance policy
|
||||
2. `DELETE /assets/vehicles/{asset_id}/insurance/{policy_id}` - Delete insurance policy
|
||||
3. `PUT /assets/vehicles/{asset_id}/tax/{tax_id}` - Update tax obligation
|
||||
4. `DELETE /assets/vehicles/{asset_id}/tax/{tax_id}` - Delete tax obligation
|
||||
|
||||
**Estimated effort:** 1 hour
|
||||
|
||||
### 4.3 🟡 P1 - Create InsuranceProvider CRUD Endpoints
|
||||
|
||||
**Missing:** Complete CRUD for standalone `InsuranceProvider` catalog:
|
||||
|
||||
1. Create schema: `InsuranceProviderResponse`, `InsuranceProviderCreate`, `InsuranceProviderUpdate`
|
||||
2. Create new endpoint file or add to existing router
|
||||
3. Endpoints: `GET /insurance-providers`, `GET /insurance-providers/{id}`, `POST /insurance-providers`, `PUT /insurance-providers/{id}`, `DELETE /insurance-providers/{id}`
|
||||
|
||||
**Estimated effort:** 1.5 hours
|
||||
|
||||
### 4.4 🟢 P2 - Add InsuranceProvider to Admin UI
|
||||
|
||||
Once the API endpoints exist, add the InsuranceProvider management to the admin panel.
|
||||
|
||||
**Estimated effort:** 1 hour
|
||||
|
||||
---
|
||||
|
||||
## 5. Summary
|
||||
|
||||
| Category | Status |
|
||||
|----------|--------|
|
||||
| **Database Cleanliness** | ✅ **PASS** - No duplicates, no legacy tables |
|
||||
| **Zombie API Endpoints** | 🔴 **2 CRITICAL** - `reports.py` references `vehicle.vehicle_expenses` |
|
||||
| **InsuranceProvider CRUD** | ❌ **FULLY MISSING** - No standalone endpoints |
|
||||
| **Insurance Policy UPDATE/DELETE** | ❌ **MISSING** - Only GET and POST exist |
|
||||
| **Tax Obligation UPDATE/DELETE** | ❌ **MISSING** - Only GET and POST exist |
|
||||
|
||||
**Total estimated fix effort:** ~4 hours
|
||||
Reference in New Issue
Block a user