Improve the frontend and repository layer
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
"""add tenant_settings
|
||||
|
||||
Revision ID: 20251022_0000
|
||||
Revises: 20251017_0000
|
||||
Create Date: 2025-10-22
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
from uuid import uuid4
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '20251022_0000'
|
||||
down_revision = '20251017_0000'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def get_default_settings():
|
||||
"""Get default settings for all categories"""
|
||||
return {
|
||||
"procurement_settings": {
|
||||
"auto_approve_enabled": True,
|
||||
"auto_approve_threshold_eur": 500.0,
|
||||
"auto_approve_min_supplier_score": 0.80,
|
||||
"require_approval_new_suppliers": True,
|
||||
"require_approval_critical_items": True,
|
||||
"procurement_lead_time_days": 3,
|
||||
"demand_forecast_days": 14,
|
||||
"safety_stock_percentage": 20.0,
|
||||
"po_approval_reminder_hours": 24,
|
||||
"po_critical_escalation_hours": 12
|
||||
},
|
||||
"inventory_settings": {
|
||||
"low_stock_threshold": 10,
|
||||
"reorder_point": 20,
|
||||
"reorder_quantity": 50,
|
||||
"expiring_soon_days": 7,
|
||||
"expiration_warning_days": 3,
|
||||
"quality_score_threshold": 8.0,
|
||||
"temperature_monitoring_enabled": True,
|
||||
"refrigeration_temp_min": 1.0,
|
||||
"refrigeration_temp_max": 4.0,
|
||||
"freezer_temp_min": -20.0,
|
||||
"freezer_temp_max": -15.0,
|
||||
"room_temp_min": 18.0,
|
||||
"room_temp_max": 25.0,
|
||||
"temp_deviation_alert_minutes": 15,
|
||||
"critical_temp_deviation_minutes": 5
|
||||
},
|
||||
"production_settings": {
|
||||
"planning_horizon_days": 7,
|
||||
"minimum_batch_size": 1.0,
|
||||
"maximum_batch_size": 100.0,
|
||||
"production_buffer_percentage": 10.0,
|
||||
"working_hours_per_day": 12,
|
||||
"max_overtime_hours": 4,
|
||||
"capacity_utilization_target": 0.85,
|
||||
"capacity_warning_threshold": 0.95,
|
||||
"quality_check_enabled": True,
|
||||
"minimum_yield_percentage": 85.0,
|
||||
"quality_score_threshold": 8.0,
|
||||
"schedule_optimization_enabled": True,
|
||||
"prep_time_buffer_minutes": 30,
|
||||
"cleanup_time_buffer_minutes": 15,
|
||||
"labor_cost_per_hour_eur": 15.0,
|
||||
"overhead_cost_percentage": 20.0
|
||||
},
|
||||
"supplier_settings": {
|
||||
"default_payment_terms_days": 30,
|
||||
"default_delivery_days": 3,
|
||||
"excellent_delivery_rate": 95.0,
|
||||
"good_delivery_rate": 90.0,
|
||||
"excellent_quality_rate": 98.0,
|
||||
"good_quality_rate": 95.0,
|
||||
"critical_delivery_delay_hours": 24,
|
||||
"critical_quality_rejection_rate": 10.0,
|
||||
"high_cost_variance_percentage": 15.0
|
||||
},
|
||||
"pos_settings": {
|
||||
"sync_interval_minutes": 5,
|
||||
"auto_sync_products": True,
|
||||
"auto_sync_transactions": True
|
||||
},
|
||||
"order_settings": {
|
||||
"max_discount_percentage": 50.0,
|
||||
"default_delivery_window_hours": 48,
|
||||
"dynamic_pricing_enabled": False,
|
||||
"discount_enabled": True,
|
||||
"delivery_tracking_enabled": True
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def upgrade():
|
||||
"""Create tenant_settings table and seed existing tenants"""
|
||||
# Create tenant_settings table
|
||||
op.create_table(
|
||||
'tenant_settings',
|
||||
sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, default=uuid4),
|
||||
sa.Column('tenant_id', postgresql.UUID(as_uuid=True), nullable=False),
|
||||
sa.Column('procurement_settings', postgresql.JSON(), nullable=False),
|
||||
sa.Column('inventory_settings', postgresql.JSON(), nullable=False),
|
||||
sa.Column('production_settings', postgresql.JSON(), nullable=False),
|
||||
sa.Column('supplier_settings', postgresql.JSON(), nullable=False),
|
||||
sa.Column('pos_settings', postgresql.JSON(), nullable=False),
|
||||
sa.Column('order_settings', postgresql.JSON(), nullable=False),
|
||||
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()'), nullable=False),
|
||||
sa.ForeignKeyConstraint(['tenant_id'], ['tenants.id'], ondelete='CASCADE'),
|
||||
sa.UniqueConstraint('tenant_id', name='uq_tenant_settings_tenant_id')
|
||||
)
|
||||
|
||||
# Create indexes
|
||||
op.create_index('ix_tenant_settings_tenant_id', 'tenant_settings', ['tenant_id'])
|
||||
|
||||
# Seed existing tenants with default settings
|
||||
connection = op.get_bind()
|
||||
|
||||
# Get all existing tenant IDs
|
||||
result = connection.execute(sa.text("SELECT id FROM tenants"))
|
||||
tenant_ids = [row[0] for row in result]
|
||||
|
||||
# Insert default settings for each existing tenant
|
||||
defaults = get_default_settings()
|
||||
for tenant_id in tenant_ids:
|
||||
connection.execute(
|
||||
sa.text("""
|
||||
INSERT INTO tenant_settings (
|
||||
id, tenant_id, procurement_settings, inventory_settings,
|
||||
production_settings, supplier_settings, pos_settings, order_settings
|
||||
) VALUES (
|
||||
:id, :tenant_id, :procurement_settings::jsonb, :inventory_settings::jsonb,
|
||||
:production_settings::jsonb, :supplier_settings::jsonb,
|
||||
:pos_settings::jsonb, :order_settings::jsonb
|
||||
)
|
||||
"""),
|
||||
{
|
||||
"id": str(uuid4()),
|
||||
"tenant_id": tenant_id,
|
||||
"procurement_settings": str(defaults["procurement_settings"]).replace("'", '"').replace("True", "true").replace("False", "false"),
|
||||
"inventory_settings": str(defaults["inventory_settings"]).replace("'", '"').replace("True", "true").replace("False", "false"),
|
||||
"production_settings": str(defaults["production_settings"]).replace("'", '"').replace("True", "true").replace("False", "false"),
|
||||
"supplier_settings": str(defaults["supplier_settings"]).replace("'", '"').replace("True", "true").replace("False", "false"),
|
||||
"pos_settings": str(defaults["pos_settings"]).replace("'", '"').replace("True", "true").replace("False", "false"),
|
||||
"order_settings": str(defaults["order_settings"]).replace("'", '"').replace("True", "true").replace("False", "false")
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
"""Drop tenant_settings table"""
|
||||
op.drop_index('ix_tenant_settings_tenant_id', table_name='tenant_settings')
|
||||
op.drop_table('tenant_settings')
|
||||
Reference in New Issue
Block a user