frontend költség beállítások
This commit is contained in:
245
backend/scripts/seed_finance_dictionaries.py
Normal file
245
backend/scripts/seed_finance_dictionaries.py
Normal file
@@ -0,0 +1,245 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Seed script: fleet_finance dictionary tables (CostCategory & InsuranceProvider).
|
||||
|
||||
Idempotent seeder that populates:
|
||||
1. fleet_finance.cost_categories - Hierarchical cost categories (5 parents + children)
|
||||
2. fleet_finance.insurance_providers - Base insurance providers (HU/EU)
|
||||
|
||||
Usage:
|
||||
docker compose exec sf_api python -m backend.scripts.seed_finance_dictionaries
|
||||
"""
|
||||
import asyncio
|
||||
import logging
|
||||
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy import select, text
|
||||
|
||||
from app.core.config import settings
|
||||
from app.models.fleet_finance.models import CostCategory, InsuranceProvider
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# =============================================================================
|
||||
# Cost Categories - Hierarchical structure
|
||||
# =============================================================================
|
||||
# Format: (code, name, description, children)
|
||||
# Children format: (code, name, description)
|
||||
|
||||
COST_CATEGORY_TREE = [
|
||||
{
|
||||
"code": "FINANCING",
|
||||
"name": "Finanszírozás",
|
||||
"description": "Jármű finanszírozásával kapcsolatos költségek",
|
||||
"children": [
|
||||
("FINANCING_LEASE", "Lízingdíj", "Lízingdíj fizetés"),
|
||||
("FINANCING_LOAN", "Hiteltörlesztő", "Hiteltörlesztő részlet"),
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "INSURANCE",
|
||||
"name": "Biztosítás",
|
||||
"description": "Biztosítási díjak és kötvények",
|
||||
"children": [
|
||||
("INSURANCE_KGFB", "KGFB", "Kötelező gépjármű-felelősségbiztosítás"),
|
||||
("INSURANCE_CASCO", "Casco", "Casco biztosítás"),
|
||||
("INSURANCE_ASSISTANCE", "Assistance", "Assistance szolgáltatás"),
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "ADMIN_FEES",
|
||||
"name": "Hatósági díjak",
|
||||
"description": "Hatósági és adminisztratív költségek",
|
||||
"children": [
|
||||
("ADMIN_FEES_VEHICLE_TAX", "Gépjárműadó", "Gépjárműadó fizetés"),
|
||||
("ADMIN_FEES_MOT", "Műszaki vizsga", "Műszaki vizsgadíj"),
|
||||
("ADMIN_FEES_DOCS", "Okmányok", "Okmányokkal kapcsolatos díjak"),
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "OPERATION",
|
||||
"name": "Üzemeltetés",
|
||||
"description": "Jármű üzemeltetésével kapcsolatos költségek",
|
||||
"children": [
|
||||
("OPERATION_FUEL", "Üzemanyag", "Üzemanyag költség"),
|
||||
("OPERATION_ELECTRIC", "Elektromos töltés", "Elektromos töltési költség"),
|
||||
("OPERATION_TOLL", "Autópálya", "Autópálya használati díj"),
|
||||
("OPERATION_PARKING", "Parkolás", "Parkolási díj"),
|
||||
("OPERATION_WASH", "Mosás", "Járműmosás és ápolás"),
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "SERVICE",
|
||||
"name": "Szerviz",
|
||||
"description": "Szerviz és karbantartási költségek",
|
||||
"children": [
|
||||
("SERVICE_SCHEDULED", "Kötelező szerviz", "Kötelező időszakos szerviz"),
|
||||
("SERVICE_REPAIR", "Eseti javítás", "Eseti javítási költség"),
|
||||
("SERVICE_TIRES", "Gumiabroncs", "Gumiabroncs csere és tárolás"),
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
# =============================================================================
|
||||
# Insurance Providers
|
||||
# =============================================================================
|
||||
|
||||
INSURANCE_PROVIDERS = [
|
||||
{"name": "Allianz Hungária Zrt.", "claim_phone": "+36-1-301-7100", "claim_url": "https://www.allianz.hu/karterites"},
|
||||
{"name": "Generali Biztosító Zrt.", "claim_phone": "+36-1-452-3200", "claim_url": "https://www.generali.hu/karterites"},
|
||||
{"name": "K&H Biztosító Zrt.", "claim_phone": "+36-1-335-3300", "claim_url": "https://www.kh.hu/biztositas/karterites"},
|
||||
{"name": "Groupama Biztosító Zrt.", "claim_phone": "+36-1-477-4800", "claim_url": "https://www.groupama.hu/karterites"},
|
||||
{"name": "Uniqa Biztosító Zrt.", "claim_phone": "+36-1-301-7300", "claim_url": "https://www.uniqa.hu/karterites"},
|
||||
{"name": "Aegon Magyarország / Alfa Vienna Insurance Group", "claim_phone": "+36-1-477-4700", "claim_url": "https://www.alfabiztosito.hu/karterites"},
|
||||
{"name": "Signal Biztosító Zrt.", "claim_phone": "+36-1-457-4400", "claim_url": "https://www.signal.hu/karterites"},
|
||||
{"name": "Wáberer Hungária Biztosító Zrt.", "claim_phone": "+36-1-237-7000", "claim_url": "https://www.whb.hu/karterites"},
|
||||
{"name": "Posta Biztosító Zrt.", "claim_phone": "+36-1-477-4900", "claim_url": "https://www.postabiztosito.hu/karterites"},
|
||||
{"name": "Magyar Posta Életbiztosító Zrt.", "claim_phone": "+36-1-477-5000", "claim_url": "https://www.mpelb.hu/karterites"},
|
||||
]
|
||||
|
||||
|
||||
async def seed_cost_categories(db: AsyncSession) -> int:
|
||||
"""Seed cost_categories table with hierarchical data. Returns count of inserted parents."""
|
||||
inserted_count = 0
|
||||
|
||||
for parent_def in COST_CATEGORY_TREE:
|
||||
# Check if parent already exists by code
|
||||
existing_parent = await db.execute(
|
||||
select(CostCategory).where(CostCategory.code == parent_def["code"])
|
||||
)
|
||||
parent = existing_parent.scalar_one_or_none()
|
||||
|
||||
if not parent:
|
||||
parent = CostCategory(
|
||||
code=parent_def["code"],
|
||||
name=parent_def["name"],
|
||||
description=parent_def["description"],
|
||||
is_system=True,
|
||||
visibility="both",
|
||||
min_tier="free",
|
||||
parent_id=None,
|
||||
)
|
||||
db.add(parent)
|
||||
await db.flush() # Get the parent ID
|
||||
inserted_count += 1
|
||||
logger.info(f" ✅ PARENT [{parent.code:20s}] {parent.name}")
|
||||
|
||||
# Process children
|
||||
for child_code, child_name, child_desc in parent_def["children"]:
|
||||
existing_child = await db.execute(
|
||||
select(CostCategory).where(CostCategory.code == child_code)
|
||||
)
|
||||
child = existing_child.scalar_one_or_none()
|
||||
|
||||
if not child:
|
||||
child = CostCategory(
|
||||
code=child_code,
|
||||
name=child_name,
|
||||
description=child_desc,
|
||||
is_system=True,
|
||||
visibility="both",
|
||||
min_tier="free",
|
||||
parent_id=parent.id,
|
||||
)
|
||||
db.add(child)
|
||||
await db.flush()
|
||||
logger.info(f" └─ CHILD [{child.code:20s}] {child.name}")
|
||||
else:
|
||||
logger.info(f" └─ EXISTS [{child.code:20s}] {child.name}")
|
||||
|
||||
return inserted_count
|
||||
|
||||
|
||||
async def seed_insurance_providers(db: AsyncSession) -> int:
|
||||
"""Seed insurance_providers table. Returns count of inserted providers."""
|
||||
inserted_count = 0
|
||||
|
||||
for prov_def in INSURANCE_PROVIDERS:
|
||||
existing = await db.execute(
|
||||
select(InsuranceProvider).where(InsuranceProvider.name == prov_def["name"])
|
||||
)
|
||||
provider = existing.scalar_one_or_none()
|
||||
|
||||
if not provider:
|
||||
provider = InsuranceProvider(
|
||||
name=prov_def["name"],
|
||||
country_code="HU",
|
||||
claim_phone=prov_def["claim_phone"],
|
||||
claim_url=prov_def["claim_url"],
|
||||
services_offered={"kgfb": True, "casco": True},
|
||||
is_active=True,
|
||||
)
|
||||
db.add(provider)
|
||||
inserted_count += 1
|
||||
logger.info(f" ✅ {provider.name} (HU)")
|
||||
else:
|
||||
# Update existing provider's country_code if not set
|
||||
if not provider.country_code:
|
||||
provider.country_code = "HU"
|
||||
logger.info(f" UPDATED {provider.name} → country_code='HU'")
|
||||
else:
|
||||
logger.info(f" EXISTS {provider.name} (country_code='{provider.country_code}')")
|
||||
|
||||
return inserted_count
|
||||
|
||||
|
||||
async def main():
|
||||
"""Main seeder entry point."""
|
||||
engine = create_async_engine(str(settings.SQLALCHEMY_DATABASE_URI))
|
||||
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
||||
|
||||
async with async_session() as db:
|
||||
try:
|
||||
logger.info("=" * 60)
|
||||
logger.info("📦 fleet_finance dictionary seeder")
|
||||
logger.info("=" * 60)
|
||||
|
||||
# --- Cost Categories ---
|
||||
logger.info("\n📁 Cost Categories (hierarchical):")
|
||||
cat_count = await seed_cost_categories(db)
|
||||
await db.commit()
|
||||
logger.info(f" → {cat_count} new parent categories inserted")
|
||||
|
||||
# --- Insurance Providers ---
|
||||
logger.info("\n🏢 Insurance Providers:")
|
||||
prov_count = await seed_insurance_providers(db)
|
||||
await db.commit()
|
||||
logger.info(f" → {prov_count} new providers inserted")
|
||||
|
||||
# --- Summary ---
|
||||
total_cats = await db.execute(
|
||||
select(CostCategory).where(CostCategory.parent_id.is_(None))
|
||||
)
|
||||
parents = total_cats.scalars().all()
|
||||
logger.info("\n" + "=" * 60)
|
||||
logger.info("📊 SEED SUMMARY")
|
||||
logger.info("=" * 60)
|
||||
logger.info(f" CostCategory parents: {len(parents)}")
|
||||
for p in parents:
|
||||
child_count = await db.execute(
|
||||
select(CostCategory).where(CostCategory.parent_id == p.id)
|
||||
)
|
||||
children = child_count.scalars().all()
|
||||
logger.info(f" ├─ {p.code:20s} ({p.name}) → {len(children)} children")
|
||||
|
||||
total_providers = await db.execute(
|
||||
select(InsuranceProvider).where(InsuranceProvider.is_active.is_(True))
|
||||
)
|
||||
providers = total_providers.scalars().all()
|
||||
logger.info(f" InsuranceProviders (active): {len(providers)}")
|
||||
for p in providers:
|
||||
logger.info(f" ├─ {p.name}")
|
||||
|
||||
logger.info("\n✅ Seeding completed successfully!")
|
||||
|
||||
except Exception as e:
|
||||
await db.rollback()
|
||||
logger.error(f"❌ Seeding failed: {e}")
|
||||
raise
|
||||
finally:
|
||||
await engine.dispose()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user