Add models and routes for costs, consumption, equipment, maintenance, and production; implement CRUD operations and unit tests

This commit is contained in:
2025-10-20 19:21:47 +02:00
parent 0b19a93e0d
commit fee857637f
20 changed files with 621 additions and 6 deletions

44
routes/consumption.py Normal file
View File

@@ -0,0 +1,44 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List, Optional
from pydantic import BaseModel
from config.database import SessionLocal
from models.consumption import Consumption
router = APIRouter(prefix="/api/consumption", tags=["Consumption"])
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
# Pydantic schemas
class ConsumptionCreate(BaseModel):
scenario_id: int
amount: float
description: Optional[str] = None
class ConsumptionRead(ConsumptionCreate):
id: int
class Config:
orm_mode = True
@router.post("/", response_model=ConsumptionRead)
async def create_consumption(item: ConsumptionCreate, db: Session = Depends(get_db)):
db_item = Consumption(**item.dict())
db.add(db_item)
db.commit()
db.refresh(db_item)
return db_item
@router.get("/", response_model=List[ConsumptionRead])
async def list_consumption(db: Session = Depends(get_db)):
return db.query(Consumption).all()

75
routes/costs.py Normal file
View File

@@ -0,0 +1,75 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List, Optional
from pydantic import BaseModel
from config.database import SessionLocal
from models.capex import Capex
from models.opex import Opex
router = APIRouter(prefix="/api/costs", tags=["Costs"])
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
# Pydantic schemas for Capex
class CapexCreate(BaseModel):
scenario_id: int
amount: float
description: Optional[str] = None
class CapexRead(CapexCreate):
id: int
class Config:
orm_mode = True
# Pydantic schemas for Opex
class OpexCreate(BaseModel):
scenario_id: int
amount: float
description: Optional[str] = None
class OpexRead(OpexCreate):
id: int
class Config:
orm_mode = True
# Capex endpoints
@router.post("/capex", response_model=CapexRead)
def create_capex(item: CapexCreate, db: Session = Depends(get_db)):
db_item = Capex(**item.dict())
db.add(db_item)
db.commit()
db.refresh(db_item)
return db_item
@router.get("/capex", response_model=List[CapexRead])
def list_capex(db: Session = Depends(get_db)):
return db.query(Capex).all()
# Opex endpoints
@router.post("/opex", response_model=OpexRead)
def create_opex(item: OpexCreate, db: Session = Depends(get_db)):
db_item = Opex(**item.dict())
db.add(db_item)
db.commit()
db.refresh(db_item)
return db_item
@router.get("/opex", response_model=List[OpexRead])
def list_opex(db: Session = Depends(get_db)):
return db.query(Opex).all()

44
routes/equipment.py Normal file
View File

@@ -0,0 +1,44 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List, Optional
from pydantic import BaseModel
from config.database import SessionLocal
from models.equipment import Equipment
router = APIRouter(prefix="/api/equipment", tags=["Equipment"])
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
# Pydantic schemas
class EquipmentCreate(BaseModel):
scenario_id: int
name: str
description: Optional[str] = None
class EquipmentRead(EquipmentCreate):
id: int
class Config:
orm_mode = True
@router.post("/", response_model=EquipmentRead)
async def create_equipment(item: EquipmentCreate, db: Session = Depends(get_db)):
db_item = Equipment(**item.dict())
db.add(db_item)
db.commit()
db.refresh(db_item)
return db_item
@router.get("/", response_model=List[EquipmentRead])
async def list_equipment(db: Session = Depends(get_db)):
return db.query(Equipment).all()

45
routes/maintenance.py Normal file
View File

@@ -0,0 +1,45 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List, Optional
from pydantic import BaseModel
from datetime import datetime
from config.database import SessionLocal
from models.maintenance import Maintenance
router = APIRouter(prefix="/api/maintenance", tags=["Maintenance"])
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
# Pydantic schemas
class MaintenanceCreate(BaseModel):
scenario_id: int
details: Optional[str] = None
class MaintenanceRead(MaintenanceCreate):
id: int
performed_at: datetime
class Config:
orm_mode = True
@router.post("/", response_model=MaintenanceRead)
async def create_maintenance(item: MaintenanceCreate, db: Session = Depends(get_db)):
db_item = Maintenance(**item.dict())
db.add(db_item)
db.commit()
db.refresh(db_item)
return db_item
@router.get("/", response_model=List[MaintenanceRead])
async def list_maintenance(db: Session = Depends(get_db)):
return db.query(Maintenance).all()

44
routes/production.py Normal file
View File

@@ -0,0 +1,44 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List, Optional
from pydantic import BaseModel
from config.database import SessionLocal
from models.production_output import ProductionOutput
router = APIRouter(prefix="/api/production", tags=["Production"])
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
# Pydantic schemas
class ProductionOutputCreate(BaseModel):
scenario_id: int
amount: float
description: Optional[str] = None
class ProductionOutputRead(ProductionOutputCreate):
id: int
class Config:
orm_mode = True
@router.post("/", response_model=ProductionOutputRead)
async def create_production(item: ProductionOutputCreate, db: Session = Depends(get_db)):
db_item = ProductionOutput(**item.dict())
db.add(db_item)
db.commit()
db.refresh(db_item)
return db_item
@router.get("/", response_model=List[ProductionOutputRead])
async def list_production(db: Session = Depends(get_db)):
return db.query(ProductionOutput).all()

View File

@@ -1,4 +1,4 @@
from fastapi import APIRouter, HTTPException, Depends
from fastapi import APIRouter, HTTPException, Request
from typing import Dict, Any
from services.reporting import generate_report
@@ -7,6 +7,7 @@ from config.database import SessionLocal
router = APIRouter(prefix="/api/reporting", tags=["Reporting"])
def get_db():
db = SessionLocal()
try:
@@ -14,10 +15,12 @@ def get_db():
finally:
db.close()
@router.post("/summary", response_model=Dict[str, float])
async def summary_report(results: Any):
# Expect a list of simulation result dicts
if not isinstance(results, list):
async def summary_report(request: Request):
# Read raw JSON to handle invalid input formats
data = await request.json()
if not isinstance(data, list):
raise HTTPException(status_code=400, detail="Invalid input format")
report = generate_report(results)
report = generate_report(data)
return report

View File

@@ -18,3 +18,9 @@ async def scenario_form(request: Request):
async def parameter_form(request: Request):
"""Render the parameter input form."""
return templates.TemplateResponse("ParameterInput.html", {"request": request})
@router.get("/", response_class=HTMLResponse)
async def dashboard(request: Request):
"""Render the central dashboard page."""
return templates.TemplateResponse("Dashboard.html", {"request": request})