Files
MagoRevisited/models.py
T
Alby96andClaude Sonnet 4.6 8a9fb5085a Add Mago4 demo ERP with Python FastAPI
Implements a working in-memory ERP demo inspired by Mago4, covering
the core modules: dashboard with KPI widgets, customers, suppliers,
products, sales orders, purchase orders, and warehouse inventory.

- FastAPI backend with Pydantic models and REST API (auto-docs at /docs)
- Jinja2 HTML templates with Mago4-style UI (dark sidebar, blue/orange/
  green/red palette, Material Design icons)
- In-memory fake database seeded with sample customers, suppliers,
  products, and orders — ready to swap for SQLAlchemy + SQL Server
- Workarounds for Python 3.14 + Starlette 1.3 / Jinja2 compatibility
  (cache_size=0, new TemplateResponse(request, name, ctx) signature)
- launch.json for one-click preview; run.bat for manual startup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 10:17:57 +02:00

194 lines
4.7 KiB
Python

from pydantic import BaseModel
from typing import Optional, List
from datetime import datetime
from enum import Enum
class OrderStatus(str, Enum):
DRAFT = "draft"
CONFIRMED = "confirmed"
PARTIALLY_RECEIVED = "partially_received"
RECEIVED = "received"
CANCELLED = "cancelled"
class OrderType(str, Enum):
SALES = "sales"
PURCHASE = "purchase"
class Customer(BaseModel):
id: int
code: str
name: str
email: str
phone: str
address: str
city: str
country: str
credit_limit: float
balance: float
class Config:
json_schema_extra = {
"example": {
"id": 1,
"code": "CUST001",
"name": "Acme Corp",
"email": "info@acme.com",
"phone": "+39 02 1234567",
"address": "Via Roma 10",
"city": "Milano",
"country": "IT",
"credit_limit": 50000,
"balance": 15000
}
}
class Supplier(BaseModel):
id: int
code: str
name: str
email: str
phone: str
address: str
city: str
country: str
payment_terms_days: int
balance: float
class Config:
json_schema_extra = {
"example": {
"id": 1,
"code": "SUPP001",
"name": "Global Components Ltd",
"email": "sales@globalcomp.com",
"phone": "+44 20 7946 0958",
"address": "123 Oxford Street",
"city": "London",
"country": "UK",
"payment_terms_days": 30,
"balance": 5000
}
}
class Product(BaseModel):
id: int
code: str
description: str
category: str
unit_price: float
quantity_in_stock: int
reorder_level: int
supplier_id: Optional[int] = None
class Config:
json_schema_extra = {
"example": {
"id": 1,
"code": "PROD001",
"description": "Industrial Widget A",
"category": "Electronics",
"unit_price": 125.50,
"quantity_in_stock": 250,
"reorder_level": 50,
"supplier_id": 1
}
}
class OrderLine(BaseModel):
id: int
product_id: int
product_code: str
product_description: str
quantity: float
unit_price: float
total_amount: float
class Config:
json_schema_extra = {
"example": {
"id": 1,
"product_id": 1,
"product_code": "PROD001",
"product_description": "Industrial Widget A",
"quantity": 10,
"unit_price": 125.50,
"total_amount": 1255.00
}
}
class SalesOrder(BaseModel):
id: int
order_number: str
order_date: datetime
customer_id: int
customer_name: str
status: OrderStatus
lines: List[OrderLine]
total_amount: float
delivery_date: Optional[datetime] = None
class Config:
json_schema_extra = {
"example": {
"id": 1,
"order_number": "SO-2024-001",
"order_date": "2024-01-15T10:30:00",
"customer_id": 1,
"customer_name": "Acme Corp",
"status": "confirmed",
"lines": [],
"total_amount": 2500.00,
"delivery_date": "2024-02-15T00:00:00"
}
}
class PurchaseOrder(BaseModel):
id: int
order_number: str
order_date: datetime
supplier_id: int
supplier_name: str
status: OrderStatus
lines: List[OrderLine]
total_amount: float
expected_delivery_date: Optional[datetime] = None
class Config:
json_schema_extra = {
"example": {
"id": 1,
"order_number": "PO-2024-001",
"order_date": "2024-01-10T14:00:00",
"supplier_id": 1,
"supplier_name": "Global Components Ltd",
"status": "confirmed",
"lines": [],
"total_amount": 5000.00,
"expected_delivery_date": "2024-02-10T00:00:00"
}
}
class DashboardWidget(BaseModel):
title: str
subtitle: Optional[str] = None
style: str # "stats", "chart", "grid"
size: str = "small" # "small", "medium", "large"
icon: Optional[str] = None
color: Optional[str] = None
value: Optional[str] = None
format: Optional[str] = None # "money", "number", "date"
data: Optional[dict] = None
class Dashboard(BaseModel):
widgets: List[List[DashboardWidget]]