refactor: Remove TEXT fields and use only reasoning_data for i18n

Completed the migration to structured reasoning_data for multilingual
dashboard support. Removed hardcoded TEXT fields (reasoning, consequence)
and updated all related code to use JSONB reasoning_data.

Changes:

1. Models Updated (removed TEXT fields):
   - PurchaseOrder: Removed reasoning, consequence TEXT columns
   - ProductionBatch: Removed reasoning TEXT column
   - Both now use only reasoning_data (JSONB/JSON)

2. Dashboard Service Updated:
   - Changed to return reasoning_data instead of TEXT fields
   - Creates default reasoning_data if missing
   - PO actions: reasoning_data with type and parameters
   - Production timeline: reasoning_data for each batch

3. Unified Schemas Updated (no separate migration):
   - services/procurement/migrations/001_unified_initial_schema.py
   - services/production/migrations/001_unified_initial_schema.py
   - Removed reasoning/consequence columns from table definitions
   - Updated comments to reflect i18n approach

Database Schema:
- purchase_orders: Only reasoning_data (JSONB)
- production_batches: Only reasoning_data (JSON)

Backend now generates:
{
  "type": "low_stock_detection",
  "parameters": {
    "supplier_name": "Harinas del Norte",
    "days_until_stockout": 3,
    ...
  },
  "consequence": {
    "type": "stockout_risk",
    "severity": "high"
  }
}

Next Steps:
- Frontend: Create i18n translation keys
- Frontend: Update components to translate reasoning_data
- Test multilingual support (ES, EN, CA)
This commit is contained in:
Claude
2025-11-07 18:20:05 +00:00
parent ddc4928d78
commit f74b8d5402
5 changed files with 75 additions and 34 deletions

View File

@@ -119,17 +119,30 @@ class PurchaseOrder(Base):
internal_notes = Column(Text, nullable=True) # Not shared with supplier
terms_and_conditions = Column(Text, nullable=True)
# JTBD Dashboard: Reasoning and consequences for user transparency
# Deferred loading to prevent breaking queries when columns don't exist yet
reasoning = deferred(Column(Text, nullable=True)) # Why this PO was created (e.g., "Low flour stock (2 days left)")
consequence = deferred(Column(Text, nullable=True)) # What happens if not approved (e.g., "Stock out risk in 48 hours")
reasoning_data = deferred(Column(JSONB, nullable=True)) # Structured reasoning data
# reasoning_data structure: {
# "trigger": "low_stock" | "forecast_demand" | "manual",
# "ingredients_affected": [{"id": "uuid", "name": "Flour", "current_stock": 10, "days_remaining": 2}],
# "orders_impacted": [{"id": "uuid", "product": "Baguette", "quantity": 100}],
# "urgency_score": 0-100,
# "estimated_stock_out_date": "2025-11-10T00:00:00Z"
# JTBD Dashboard: Structured reasoning data for i18n support
# Backend stores structured data, frontend translates using i18n
reasoning_data = Column(JSONB, nullable=True) # Structured reasoning data for multilingual support
# reasoning_data structure (see shared/schemas/reasoning_types.py):
# {
# "type": "low_stock_detection" | "forecast_demand" | "safety_stock_replenishment" | etc.,
# "parameters": {
# "supplier_name": "Harinas del Norte",
# "product_names": ["Flour Type 55", "Flour Type 45"],
# "days_until_stockout": 3,
# "current_stock": 45.5,
# "required_stock": 200
# },
# "consequence": {
# "type": "stockout_risk",
# "severity": "high",
# "impact_days": 3,
# "affected_products": ["Baguette", "Croissant"]
# },
# "metadata": {
# "trigger_source": "orchestrator_auto",
# "forecast_confidence": 0.85,
# "ai_assisted": true
# }
# }
# Audit fields

View File

@@ -6,7 +6,7 @@ Create Date: 2025-11-07
Complete procurement service schema including:
- Procurement plans and requirements
- Purchase orders and items (with reasoning fields for JTBD dashboard)
- Purchase orders and items (with reasoning_data for i18n JTBD dashboard)
- Deliveries and delivery items
- Supplier invoices
- Replenishment planning
@@ -207,7 +207,7 @@ def upgrade() -> None:
# PURCHASE ORDER TABLES
# ========================================================================
# Create purchase_orders table (with JTBD dashboard reasoning fields)
# Create purchase_orders table (with reasoning_data for i18n)
op.create_table('purchase_orders',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('tenant_id', postgresql.UUID(as_uuid=True), nullable=False),
@@ -242,9 +242,7 @@ def upgrade() -> None:
sa.Column('notes', sa.Text(), nullable=True),
sa.Column('internal_notes', sa.Text(), nullable=True),
sa.Column('terms_and_conditions', sa.Text(), nullable=True),
# JTBD Dashboard fields
sa.Column('reasoning', sa.Text(), nullable=True),
sa.Column('consequence', sa.Text(), nullable=True),
# JTBD Dashboard: Structured reasoning for i18n support
sa.Column('reasoning_data', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), onupdate=sa.text('now()'), nullable=False),