- New clients table with PF/PJ support, fiscal data (CUI, IBAN, eFactura fields) - Full CRUD API for clients with search, sync integration - Order lifecycle: edit header (DRAFT), devalidate (VALIDAT→DRAFT), delete order/invoice - Invoice types: FACTURA (B2B) vs BON_FISCAL (B2C) with different nr formats - OrderCreateView redesigned as multi-step flow (client→vehicle→details) - Autocomplete from catalog_norme/catalog_preturi in OrderLineForm - Dashboard now combines stats + full orders table with filter tabs and search - ClientPicker and VehiclePicker with inline creation capability - Frontend schema aligned with backend (missing columns causing sync errors) - Mobile responsive fixes for OrderDetailView buttons Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
144 lines
3.3 KiB
Python
144 lines
3.3 KiB
Python
from datetime import UTC, datetime
|
|
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.db.base import uuid7
|
|
from app.db.models.catalog import (
|
|
CatalogAnsamblu,
|
|
CatalogMarca,
|
|
CatalogPret,
|
|
CatalogTipDeviz,
|
|
CatalogTipMotor,
|
|
)
|
|
|
|
MARCI = [
|
|
"Audi",
|
|
"BMW",
|
|
"Citroen",
|
|
"Dacia",
|
|
"Fiat",
|
|
"Ford",
|
|
"Honda",
|
|
"Hyundai",
|
|
"Kia",
|
|
"Mazda",
|
|
"Mercedes-Benz",
|
|
"Mitsubishi",
|
|
"Nissan",
|
|
"Opel",
|
|
"Peugeot",
|
|
"Renault",
|
|
"Seat",
|
|
"Skoda",
|
|
"Suzuki",
|
|
"Toyota",
|
|
"Volkswagen",
|
|
"Volvo",
|
|
"Alfa Romeo",
|
|
"Jeep",
|
|
]
|
|
|
|
ANSAMBLE = [
|
|
"Motor",
|
|
"Cutie de viteze",
|
|
"Frane",
|
|
"Directie",
|
|
"Suspensie",
|
|
"Climatizare",
|
|
"Electrica",
|
|
"Caroserie",
|
|
"Esapament",
|
|
"Transmisie",
|
|
"Revizie",
|
|
]
|
|
|
|
TIPURI_DEVIZ = ["Service", "ITP", "Regie", "Constatare"]
|
|
|
|
TIPURI_MOTOARE = ["Benzina", "Diesel", "Hibrid", "Electric", "GPL"]
|
|
|
|
PRETURI = [
|
|
{"denumire": "Manopera standard", "pret": 150.0, "um": "ora"},
|
|
{"denumire": "Revizie ulei + filtru", "pret": 250.0, "um": "buc"},
|
|
{"denumire": "Diagnosticare", "pret": 100.0, "um": "buc"},
|
|
]
|
|
|
|
|
|
async def seed_demo(db: AsyncSession) -> None:
|
|
from app.auth.service import register
|
|
from sqlalchemy import select
|
|
from app.db.models.user import User
|
|
|
|
r = await db.execute(select(User).where(User.email == "demo@roaauto.ro"))
|
|
if r.scalar_one_or_none():
|
|
print("Demo user already exists.")
|
|
return
|
|
user, tenant = await register(db, "demo@roaauto.ro", "demo123", "ROA AUTO Demo", "0722000000")
|
|
print(f"Created demo tenant: {tenant.id}, user: {user.email}")
|
|
counts = await seed_catalog(db, tenant.id)
|
|
print(f"Seeded catalog: {counts}")
|
|
|
|
|
|
async def seed_catalog(db: AsyncSession, tenant_id: str) -> dict:
|
|
now = datetime.now(UTC).isoformat()
|
|
counts = {}
|
|
|
|
# Marci
|
|
for name in MARCI:
|
|
db.add(
|
|
CatalogMarca(id=uuid7(), tenant_id=tenant_id, denumire=name)
|
|
)
|
|
counts["marci"] = len(MARCI)
|
|
|
|
# Ansamble
|
|
for name in ANSAMBLE:
|
|
db.add(
|
|
CatalogAnsamblu(id=uuid7(), tenant_id=tenant_id, denumire=name)
|
|
)
|
|
counts["ansamble"] = len(ANSAMBLE)
|
|
|
|
# Tipuri deviz
|
|
for name in TIPURI_DEVIZ:
|
|
db.add(
|
|
CatalogTipDeviz(id=uuid7(), tenant_id=tenant_id, denumire=name)
|
|
)
|
|
counts["tipuri_deviz"] = len(TIPURI_DEVIZ)
|
|
|
|
# Tipuri motoare
|
|
for name in TIPURI_MOTOARE:
|
|
db.add(
|
|
CatalogTipMotor(id=uuid7(), tenant_id=tenant_id, denumire=name)
|
|
)
|
|
counts["tipuri_motoare"] = len(TIPURI_MOTOARE)
|
|
|
|
# Preturi
|
|
for p in PRETURI:
|
|
db.add(
|
|
CatalogPret(
|
|
id=uuid7(),
|
|
tenant_id=tenant_id,
|
|
denumire=p["denumire"],
|
|
pret=p["pret"],
|
|
um=p["um"],
|
|
)
|
|
)
|
|
counts["preturi"] = len(PRETURI)
|
|
|
|
await db.commit()
|
|
return counts
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import asyncio
|
|
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
|
|
from app.config import settings
|
|
import app.db.models # noqa
|
|
|
|
async def main():
|
|
engine = create_async_engine(settings.DATABASE_URL)
|
|
Session = async_sessionmaker(engine, expire_on_commit=False)
|
|
async with Session() as db:
|
|
await seed_demo(db)
|
|
await engine.dispose()
|
|
|
|
asyncio.run(main())
|