Fix Demo enterprise
This commit is contained in:
531
FIXES_SUMMARY.md
Normal file
531
FIXES_SUMMARY.md
Normal file
@@ -0,0 +1,531 @@
|
||||
# Enterprise Demo Fixes Summary
|
||||
|
||||
**Date:** 2025-12-17
|
||||
**Issue:** Child tenants not visible in multi-tenant menu & Distribution data not displaying
|
||||
|
||||
## Problems Identified
|
||||
|
||||
### 1. Child Tenant Visibility Issue ❌
|
||||
|
||||
**Root Cause:** Child tenants were being created with the wrong `owner_id`.
|
||||
|
||||
**Location:** `services/tenant/app/api/internal_demo.py:620`
|
||||
|
||||
**Problem Details:**
|
||||
- Child tenants were hardcoded to use the professional demo owner ID: `c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6`
|
||||
- This is INCORRECT for enterprise demos
|
||||
- The enterprise parent tenant uses owner ID: `d2e3f4a5-b6c7-48d9-e0f1-a2b3c4d5e6f7`
|
||||
- Because of the mismatch, when the enterprise parent owner logged in, they could only see the parent tenant
|
||||
- The child tenants belonged to a different owner and were not visible in the tenant switcher
|
||||
|
||||
**Impact:**
|
||||
- Parent tenant owner could NOT see child tenants in the multi-tenant menu
|
||||
- Child tenants existed in the database but were inaccessible
|
||||
- Enterprise demo was non-functional for testing multi-location features
|
||||
|
||||
### 2. Distribution Data File Not Found for Child Tenants ❌
|
||||
|
||||
**Root Cause:** Distribution service was trying to load non-existent distribution files for child tenants.
|
||||
|
||||
**Location:** `services/distribution/app/api/internal_demo.py:148`
|
||||
|
||||
**Problem Details:**
|
||||
- When cloning data for `enterprise_child` tenants, the code tried to load: `shared/demo/fixtures/enterprise/children/C0000000-0000-4000-a000-000000000001/12-distribution.json`
|
||||
- These files don't exist because **child outlets are delivery destinations, not distribution hubs**
|
||||
- Distribution is managed centrally by the parent tenant
|
||||
- This caused the demo session cloning to fail with FileNotFoundError
|
||||
|
||||
**Error Message:**
|
||||
```
|
||||
FileNotFoundError: Seed data file not found:
|
||||
/app/shared/demo/fixtures/enterprise/children/C0000000-0000-4000-a000-000000000001/12-distribution.json
|
||||
```
|
||||
|
||||
**Impact:**
|
||||
- Demo session cloning failed for enterprise demos
|
||||
- Child tenant creation was incomplete
|
||||
- Distribution page showed no data
|
||||
|
||||
### 3. Shipment Model Field Mismatch ❌
|
||||
|
||||
**Root Cause:** Distribution cloning code tried to create Shipment with fields that don't exist in the model.
|
||||
|
||||
**Location:** `services/distribution/app/api/internal_demo.py:283`
|
||||
|
||||
**Problem Details:**
|
||||
- Fixture contains `items` field (list of products being shipped)
|
||||
- Fixture contains `estimated_delivery_time` field
|
||||
- Shipment model doesn't have these fields
|
||||
- Model only has: `actual_delivery_time`, `delivery_notes`, etc.
|
||||
- This caused TypeError when creating Shipment objects
|
||||
|
||||
**Error Message:**
|
||||
```
|
||||
TypeError: 'items' is an invalid keyword argument for Shipment
|
||||
```
|
||||
|
||||
**Impact:**
|
||||
- Distribution data cloning failed completely
|
||||
- No routes or shipments were created
|
||||
- Distribution page was empty even after successful child tenant creation
|
||||
|
||||
## Fixes Applied
|
||||
|
||||
### Fix 1: Child Tenant Owner ID Correction ✅
|
||||
|
||||
**File Modified:** `services/tenant/app/api/internal_demo.py`
|
||||
|
||||
**Changes Made:**
|
||||
|
||||
1. **Added parent tenant lookup** (Lines 599-614):
|
||||
```python
|
||||
# Get parent tenant to retrieve the correct owner_id
|
||||
parent_result = await db.execute(select(Tenant).where(Tenant.id == parent_uuid))
|
||||
parent_tenant = parent_result.scalars().first()
|
||||
|
||||
if not parent_tenant:
|
||||
logger.error("Parent tenant not found", parent_tenant_id=parent_tenant_id)
|
||||
return {...}
|
||||
|
||||
# Use the parent's owner_id for the child tenant (enterprise demo owner)
|
||||
parent_owner_id = parent_tenant.owner_id
|
||||
```
|
||||
|
||||
2. **Updated child tenant creation** (Line 637):
|
||||
```python
|
||||
# Owner ID - MUST match the parent tenant owner (enterprise demo owner)
|
||||
# This ensures the parent owner can see and access child tenants
|
||||
owner_id=parent_owner_id
|
||||
```
|
||||
|
||||
3. **Updated TenantMember creation** (Line 711):
|
||||
```python
|
||||
# Use the parent's owner_id (already retrieved above)
|
||||
# This ensures consistency between tenant.owner_id and TenantMember records
|
||||
child_owner_member = TenantMember(
|
||||
tenant_id=virtual_uuid,
|
||||
user_id=parent_owner_id, # Changed from hardcoded UUID
|
||||
role="owner",
|
||||
...
|
||||
)
|
||||
```
|
||||
|
||||
4. **Enhanced logging** (Line 764):
|
||||
```python
|
||||
logger.info(
|
||||
"Child outlet created successfully",
|
||||
...
|
||||
owner_id=str(parent_owner_id), # Added for debugging
|
||||
...
|
||||
)
|
||||
```
|
||||
|
||||
### Fix 2: Distribution Data Loading for Child Tenants ✅
|
||||
|
||||
**File Modified:** `services/distribution/app/api/internal_demo.py`
|
||||
|
||||
**Changes Made:**
|
||||
|
||||
1. **Added early return for child tenants** (Lines 147-166):
|
||||
```python
|
||||
elif demo_account_type == "enterprise_child":
|
||||
# Child outlets don't have their own distribution data
|
||||
# Distribution is managed centrally by the parent tenant
|
||||
# Child locations are delivery destinations, not distribution hubs
|
||||
logger.info(
|
||||
"Skipping distribution cloning for child outlet - distribution managed by parent",
|
||||
base_tenant_id=base_tenant_id,
|
||||
virtual_tenant_id=virtual_tenant_id,
|
||||
session_id=session_id
|
||||
)
|
||||
duration_ms = int((datetime.now(timezone.utc) - start_time).total_seconds() * 1000)
|
||||
return {
|
||||
"service": "distribution",
|
||||
"status": "completed",
|
||||
"records_cloned": 0,
|
||||
"duration_ms": duration_ms,
|
||||
"details": {
|
||||
"note": "Child outlets don't manage distribution - handled by parent tenant"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Rationale:**
|
||||
- In an enterprise bakery setup, the **central production facility (parent)** manages all distribution
|
||||
- **Retail outlets (children)** are **receiving locations**, not distribution hubs
|
||||
- The parent's distribution.json already includes routes and shipments that reference child tenant locations
|
||||
- Attempting to load child-specific distribution files was architecturally incorrect
|
||||
|
||||
### Fix 3: Shipment Field Compatibility ✅
|
||||
|
||||
**File Modified:** `services/distribution/app/api/internal_demo.py`
|
||||
|
||||
**Changes Made:**
|
||||
|
||||
1. **Removed estimated_delivery_time field** (Lines 261-267):
|
||||
```python
|
||||
# Note: The Shipment model doesn't have estimated_delivery_time
|
||||
# Only actual_delivery_time is stored
|
||||
actual_delivery_time = parse_date_field(
|
||||
shipment_data.get('actual_delivery_time'),
|
||||
session_time,
|
||||
"actual_delivery_time"
|
||||
)
|
||||
```
|
||||
|
||||
2. **Stored items in delivery_notes** (Lines 273-287):
|
||||
```python
|
||||
# Store items in delivery_notes as JSON for demo purposes
|
||||
# (In production, items would be in the linked purchase order)
|
||||
import json
|
||||
items_json = json.dumps(shipment_data.get('items', [])) if shipment_data.get('items') else None
|
||||
|
||||
new_shipment = Shipment(
|
||||
...
|
||||
total_weight_kg=shipment_data.get('total_weight_kg'),
|
||||
actual_delivery_time=actual_delivery_time,
|
||||
# Store items info in delivery_notes for demo display
|
||||
delivery_notes=f"{shipment_data.get('notes', '')}\nItems: {items_json}" if items_json else shipment_data.get('notes'),
|
||||
...
|
||||
)
|
||||
```
|
||||
|
||||
**Rationale:**
|
||||
- Shipment model represents delivery tracking, not content inventory
|
||||
- In production systems, shipment items are stored in the linked purchase order
|
||||
- For demo purposes, we store items as JSON in the `delivery_notes` field
|
||||
- This allows the demo to show what's being shipped without requiring full PO integration
|
||||
|
||||
## How Data Flows in Enterprise Demo
|
||||
|
||||
### User & Ownership Structure
|
||||
|
||||
```
|
||||
Enterprise Demo Owner
|
||||
├── ID: d2e3f4a5-b6c7-48d9-e0f1-a2b3c4d5e6f7
|
||||
├── Email: director@panaderiaartesana.es
|
||||
├── Role: owner
|
||||
│
|
||||
├── Parent Tenant (Central Production)
|
||||
│ ├── ID: 80000000-0000-4000-a000-000000000001 (template)
|
||||
│ ├── Name: "Panadería Artesana España - Central"
|
||||
│ ├── Type: parent
|
||||
│ └── Owner: d2e3f4a5-b6c7-48d9-e0f1-a2b3c4d5e6f7
|
||||
│
|
||||
└── Child Tenants (Retail Outlets)
|
||||
├── Madrid - Salamanca
|
||||
│ ├── ID: A0000000-0000-4000-a000-000000000001 (template)
|
||||
│ ├── Type: child
|
||||
│ └── Owner: d2e3f4a5-b6c7-48d9-e0f1-a2b3c4d5e6f7 ✅ (NOW CORRECT)
|
||||
│
|
||||
├── Barcelona - Eixample
|
||||
│ ├── ID: B0000000-0000-4000-a000-000000000001
|
||||
│ └── Owner: d2e3f4a5-b6c7-48d9-e0f1-a2b3c4d5e6f7 ✅
|
||||
│
|
||||
├── Valencia - Ruzafa
|
||||
│ ├── ID: C0000000-0000-4000-a000-000000000001
|
||||
│ └── Owner: d2e3f4a5-b6c7-48d9-e0f1-a2b3c4d5e6f7 ✅
|
||||
│
|
||||
├── Seville - Triana
|
||||
│ ├── ID: D0000000-0000-4000-a000-000000000001
|
||||
│ └── Owner: d2e3f4a5-b6c7-48d9-e0f1-a2b3c4d5e6f7 ✅
|
||||
│
|
||||
└── Bilbao - Casco Viejo
|
||||
├── ID: E0000000-0000-4000-a000-000000000001
|
||||
└── Owner: d2e3f4a5-b6c7-48d9-e0f1-a2b3c4d5e6f7 ✅
|
||||
```
|
||||
|
||||
### Tenant Loading Flow
|
||||
|
||||
1. **User logs into enterprise demo**
|
||||
- Demo session created with `demo_account_type: "enterprise"`
|
||||
- Session ID stored in JWT token
|
||||
|
||||
2. **Frontend requests user tenants**
|
||||
- Calls: `GET /tenants/user/{user_id}/owned`
|
||||
- Backend: `services/tenant/app/api/tenant_operations.py:284`
|
||||
|
||||
3. **Backend retrieves virtual tenants**
|
||||
- Extracts `demo_session_id` from JWT
|
||||
- Calls: `tenant_service.get_virtual_tenants_for_session(demo_session_id, "enterprise")`
|
||||
- Query: `SELECT * FROM tenants WHERE demo_session_id = ? AND owner_id = ?`
|
||||
- Returns: Parent + All child tenants with matching owner_id ✅
|
||||
|
||||
4. **Frontend displays in TenantSwitcher**
|
||||
- Component: `frontend/src/components/ui/TenantSwitcher.tsx`
|
||||
- Shows all tenants where user is owner
|
||||
- Now includes all 6 tenants (1 parent + 5 children) ✅
|
||||
|
||||
### Distribution Data Flow
|
||||
|
||||
1. **Demo session cloning**
|
||||
- Orchestrator calls distribution service: `POST /internal/demo/clone`
|
||||
- Loads fixture: `shared/demo/fixtures/enterprise/parent/12-distribution.json`
|
||||
|
||||
2. **Distribution data includes**
|
||||
- Delivery routes with route_sequence (stops at multiple locations)
|
||||
- Shipments linked to child tenants
|
||||
- All dates use BASE_TS markers for session-relative times
|
||||
|
||||
3. **Frontend queries distribution**
|
||||
- Calls: `GET /tenants/{tenant_id}/distribution/routes?date={date}`
|
||||
- Calls: `GET /tenants/{tenant_id}/distribution/shipments?date={date}`
|
||||
- Service: `frontend/src/api/hooks/useEnterpriseDashboard.ts:307`
|
||||
|
||||
## Testing Instructions
|
||||
|
||||
### 1. Restart Services
|
||||
|
||||
After applying the fixes, you need to restart the affected services:
|
||||
|
||||
```bash
|
||||
# Restart tenant service (Fix 1: child tenant owner_id)
|
||||
kubectl rollout restart deployment tenant-service -n bakery-ia
|
||||
|
||||
# Restart distribution service (Fix 2: skip child distribution loading)
|
||||
kubectl rollout restart deployment distribution-service -n bakery-ia
|
||||
|
||||
# Or restart all services at once
|
||||
./kubernetes_restart.sh
|
||||
```
|
||||
|
||||
### 2. Create New Enterprise Demo Session
|
||||
|
||||
**Important:** You must create a NEW demo session to test the fix. Existing sessions have already created child tenants with the wrong owner_id.
|
||||
|
||||
```bash
|
||||
# Navigate to frontend
|
||||
cd frontend
|
||||
|
||||
# Start development server if not running
|
||||
npm run dev
|
||||
|
||||
# Open browser to demo page
|
||||
# http://localhost:3000/demo
|
||||
```
|
||||
|
||||
### 3. Test Child Tenant Visibility
|
||||
|
||||
1. Click "Try Enterprise Demo" button
|
||||
2. Wait for demo session to initialize
|
||||
3. After redirect to dashboard, look for the tenant switcher in the top-left
|
||||
4. Click on the tenant switcher dropdown
|
||||
5. **Expected Result:** You should see 6 organizations:
|
||||
- Panadería Artesana España - Central (parent)
|
||||
- Madrid - Salamanca (child)
|
||||
- Barcelona - Eixample (child)
|
||||
- Valencia - Ruzafa (child)
|
||||
- Seville - Triana (child)
|
||||
- Bilbao - Casco Viejo (child)
|
||||
|
||||
### 4. Test Distribution Page
|
||||
|
||||
1. From the enterprise dashboard, navigate to "Distribution"
|
||||
2. Check if routes and shipments are displayed
|
||||
3. **Expected Result:** You should see:
|
||||
- Active routes count
|
||||
- Pending deliveries count
|
||||
- Distribution map with route visualization
|
||||
- List of routes in the "Rutas" tab
|
||||
|
||||
### 5. Verify Database (Optional)
|
||||
|
||||
If you have database access:
|
||||
|
||||
```sql
|
||||
-- Check child tenant owner_ids
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
tenant_type,
|
||||
owner_id,
|
||||
demo_session_id
|
||||
FROM tenants
|
||||
WHERE tenant_type = 'child'
|
||||
AND is_demo = true
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 10;
|
||||
|
||||
-- Should show owner_id = 'd2e3f4a5-b6c7-48d9-e0f1-a2b3c4d5e6f7' for all child tenants
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Child Tenants Still Not Visible
|
||||
|
||||
1. **Verify you created a NEW demo session** after deploying the fix
|
||||
- Old sessions have child tenants with wrong owner_id
|
||||
- Solution: Create a new demo session
|
||||
|
||||
2. **Check logs for child tenant creation**
|
||||
```bash
|
||||
kubectl logs -f deployment/tenant-service -n bakery-ia | grep "Child outlet created"
|
||||
```
|
||||
- Should show: `owner_id=d2e3f4a5-b6c7-48d9-e0f1-a2b3c4d5e6f7`
|
||||
|
||||
3. **Verify demo session ID in JWT**
|
||||
- Open browser DevTools > Application > Storage > Local Storage
|
||||
- Check if `demo_session_id` is present in token
|
||||
- Should match the session_id in database
|
||||
|
||||
### Distribution Data Not Showing
|
||||
|
||||
1. **Check date parameter**
|
||||
- Distribution page defaults to today's date
|
||||
- Demo data uses BASE_TS (session creation time)
|
||||
- Routes might be scheduled for BASE_TS + 2h, BASE_TS + 3h, etc.
|
||||
- Solution: Try querying without date filter or use session date
|
||||
|
||||
2. **Verify distribution data was cloned**
|
||||
```bash
|
||||
kubectl logs -f deployment/demo-session-service -n bakery-ia | grep "distribution"
|
||||
```
|
||||
- Should show: "Distribution data cloning completed"
|
||||
- Should show: records_cloned > 0
|
||||
|
||||
3. **Check backend endpoint**
|
||||
```bash
|
||||
# Get tenant ID from tenant switcher
|
||||
TENANT_ID="your-virtual-tenant-id"
|
||||
|
||||
# Query routes directly
|
||||
curl -H "Authorization: Bearer YOUR_TOKEN" \
|
||||
"http://localhost:8000/tenants/${TENANT_ID}/distribution/routes"
|
||||
```
|
||||
|
||||
4. **Check browser console for errors**
|
||||
- Open DevTools > Console
|
||||
- Look for API errors or failed requests
|
||||
- Check Network tab for distribution API calls
|
||||
|
||||
## Files Changed
|
||||
|
||||
1. **services/tenant/app/api/internal_demo.py**
|
||||
- Lines 599-614: Added parent tenant lookup
|
||||
- Line 637: Fixed child tenant owner_id
|
||||
- Line 711: Fixed TenantMember owner_id
|
||||
- Line 764: Enhanced logging
|
||||
|
||||
2. **services/distribution/app/api/internal_demo.py**
|
||||
- Lines 147-166: Skip distribution cloning for child tenants
|
||||
- Lines 261-267: Removed unsupported `estimated_delivery_time` field
|
||||
- Lines 273-292: Fixed `items` field issue (model doesn't support it)
|
||||
- Stored items data in `delivery_notes` field for demo display
|
||||
- Added clear logging explaining why child tenants don't get distribution data
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
- [x] Child tenant owner_id now matches parent tenant owner_id
|
||||
- [x] Child tenants include demo_session_id for session-based queries
|
||||
- [x] TenantMember records use consistent owner_id
|
||||
- [x] Distribution fixture exists with proper structure
|
||||
- [x] Distribution API endpoints are correctly implemented
|
||||
- [x] Frontend hooks properly call distribution API
|
||||
- [x] Distribution cloning skips child tenants (they don't manage distribution)
|
||||
- [x] FileNotFoundError for child distribution files is resolved
|
||||
- [x] Shipment model field compatibility issues resolved
|
||||
- [x] Items data stored in delivery_notes for demo display
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Deploy Fixes**
|
||||
```bash
|
||||
kubectl rollout restart deployment tenant-service -n bakery-ia
|
||||
kubectl rollout restart deployment distribution-service -n bakery-ia
|
||||
```
|
||||
|
||||
2. **Create New Demo Session**
|
||||
- Must be a new session, old sessions have wrong data
|
||||
|
||||
3. **Test Multi-Tenant Menu**
|
||||
- Verify all 6 tenants visible
|
||||
- Test switching between tenants
|
||||
|
||||
4. **Test Distribution Page**
|
||||
- Check if data displays
|
||||
- If not, investigate date filtering
|
||||
|
||||
5. **Monitor Logs**
|
||||
```bash
|
||||
# Watch tenant service logs
|
||||
kubectl logs -f deployment/tenant-service -n bakery-ia
|
||||
|
||||
# Watch distribution service logs
|
||||
kubectl logs -f deployment/distribution-service -n bakery-ia
|
||||
```
|
||||
|
||||
## Additional Notes
|
||||
|
||||
### Why This Fix Works
|
||||
|
||||
The tenant visibility is controlled by the `owner_id` field. When a user logs in and requests their tenants:
|
||||
|
||||
1. Backend extracts user_id from JWT: `d2e3f4a5-b6c7-48d9-e0f1-a2b3c4d5e6f7`
|
||||
2. Queries database: `SELECT * FROM tenants WHERE owner_id = ? AND demo_session_id = ?`
|
||||
3. Previously: Parent had correct owner_id, children had wrong owner_id → Only parent returned
|
||||
4. Now: Parent AND children have same owner_id → All tenants returned ✅
|
||||
|
||||
### Distribution Data Structure
|
||||
|
||||
The distribution fixture creates a realistic enterprise distribution scenario:
|
||||
- **Routes:** Delivery routes from central production to retail outlets
|
||||
- **Shipments:** Individual shipments assigned to routes
|
||||
- **Child References:** Shipments reference child_tenant_id for destination tracking
|
||||
- **Time Offsets:** Uses BASE_TS + offset for realistic scheduling
|
||||
|
||||
Example:
|
||||
```json
|
||||
{
|
||||
"route_number": "MAD-BCN-001",
|
||||
"route_date": "BASE_TS + 2h", // 2 hours after session creation
|
||||
"route_sequence": [
|
||||
{"stop_number": 1, "location_id": "parent-id"},
|
||||
{"stop_number": 2, "location_id": "child-A-id"},
|
||||
{"stop_number": 3, "location_id": "child-B-id"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
This creates a distribution network where:
|
||||
- Central production (parent) produces goods
|
||||
- Distribution routes deliver to retail outlets (children)
|
||||
- Shipments track individual deliveries
|
||||
- All entities are linked for network-wide visibility
|
||||
|
||||
---
|
||||
|
||||
## Summary of All Changes
|
||||
|
||||
### Services Modified
|
||||
1. **tenant-service** - Fixed child tenant owner_id
|
||||
2. **distribution-service** - Fixed child cloning + shipment fields
|
||||
|
||||
### Database Impact
|
||||
- Child tenants created in new sessions will have correct owner_id
|
||||
- Distribution routes and shipments will be created successfully
|
||||
- No migration needed (only affects new demo sessions)
|
||||
|
||||
### Deployment Commands
|
||||
```bash
|
||||
# Restart affected services
|
||||
kubectl rollout restart deployment tenant-service -n bakery-ia
|
||||
kubectl rollout restart deployment distribution-service -n bakery-ia
|
||||
|
||||
# Verify deployments
|
||||
kubectl rollout status deployment tenant-service -n bakery-ia
|
||||
kubectl rollout status deployment distribution-service -n bakery-ia
|
||||
```
|
||||
|
||||
### Testing Checklist
|
||||
- [ ] Create new enterprise demo session
|
||||
- [ ] Verify 6 tenants visible in tenant switcher
|
||||
- [ ] Switch between parent and child tenants
|
||||
- [ ] Navigate to Distribution page on parent tenant
|
||||
- [ ] Verify routes and shipments are displayed
|
||||
- [ ] Check demo session logs for errors
|
||||
|
||||
---
|
||||
|
||||
**Fix Status:** ✅ ALL FIXES COMPLETED
|
||||
**Testing Status:** ⏳ PENDING USER VERIFICATION
|
||||
**Production Ready:** ✅ YES (after testing)
|
||||
Reference in New Issue
Block a user