From 2def6b220169f3dc1459cf2a9b742026637cfa30 Mon Sep 17 00:00:00 2001 From: Kincses Date: Tue, 17 Feb 2026 01:26:18 +0000 Subject: [PATCH] feat(infra): Stabilized Docker env, fixed circular imports, enabled AI Enricher Robot v1.1 --- backend/app/__init__.py | 0 .../__pycache__/admin.cpython-312.pyc | Bin 7910 -> 7896 bytes .../__pycache__/auth.cpython-312.pyc | Bin 10232 -> 10196 bytes backend/app/api/v1/endpoints/admin.py | 2 +- backend/app/diagnose_system.py | 2 +- backend/app/models/__init__.py | 12 +- .../__pycache__/__init__.cpython-312.pyc | Bin 1978 -> 2136 bytes .../models/__pycache__/asset.cpython-312.pyc | Bin 10807 -> 11017 bytes .../__pycache__/gamification.cpython-312.pyc | Bin 6083 -> 6122 bytes .../__pycache__/identity.cpython-312.pyc | Bin 7896 -> 8122 bytes backend/app/models/asset.py | 6 + backend/app/models/audit.py | 34 +- backend/app/models/gamification.py | 10 +- backend/app/models/identity.py | 8 + ...{system_config.py => system_config.py.bak} | 0 backend/app/models/vehicle_definitions.py | 85 +++++ backend/app/schemas/vehicle_categories.py | 20 + backend/app/scripts/link_catalog_to_mdm.py | 78 ++++ backend/app/scripts/morning_report.py | 42 +++ backend/app/scripts/seed_system_params.py | 2 +- backend/app/scripts/seed_v1_9_system.py | 84 +++++ .../__pycache__/cost_service.cpython-312.pyc | Bin 5417 -> 5403 bytes .../gamification_service.cpython-312.pyc | Bin 6849 -> 6835 bytes .../security_service.cpython-312.pyc | Bin 8915 -> 8901 bytes backend/app/services/ai_service.py | 72 ++++ backend/app/services/cost_service.py | 2 +- backend/app/services/gamification_service.py | 2 +- backend/app/services/security_service.py | 2 +- backend/app/workers/ocr_robot.py | 66 ++++ backend/app/workers/technical_enricher.py | 180 ++++----- ...e225e904_add_vehicle_mdm_and_audit_v1_8.py | 302 +++++++++++++++ ...4_v1_9_deep_asset_catalog_and_logistics.py | 348 ++++++++++++++++++ ...005c446_v1_9_final_mdm_and_process_logs.py | 309 ++++++++++++++++ backend/requirements.txt | 3 +- 34 files changed, 1559 insertions(+), 112 deletions(-) delete mode 100755 backend/app/__init__.py rename backend/app/models/{system_config.py => system_config.py.bak} (100%) create mode 100644 backend/app/models/vehicle_definitions.py create mode 100644 backend/app/schemas/vehicle_categories.py create mode 100644 backend/app/scripts/link_catalog_to_mdm.py create mode 100644 backend/app/scripts/morning_report.py create mode 100644 backend/app/scripts/seed_v1_9_system.py create mode 100644 backend/app/services/ai_service.py create mode 100644 backend/app/workers/ocr_robot.py create mode 100644 backend/migrations/versions/495fe225e904_add_vehicle_mdm_and_audit_v1_8.py create mode 100644 backend/migrations/versions/8f09b4b22f14_v1_9_deep_asset_catalog_and_logistics.py create mode 100644 backend/migrations/versions/f30c0005c446_v1_9_final_mdm_and_process_logs.py diff --git a/backend/app/__init__.py b/backend/app/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/backend/app/api/v1/endpoints/__pycache__/admin.cpython-312.pyc b/backend/app/api/v1/endpoints/__pycache__/admin.cpython-312.pyc index cdb564fa0cd699679f359ddbd30efc23bfacc389..0e4b98f41f277f2fc52ff31570b541ccaec5faa1 100644 GIT binary patch delta 46 zcmaE6d&8FZG%qg~0}#wPI5{(HBX6=aH&X delta 60 zcmca%`^=X2G%qg~0}zx~cW0(-rYz)HUpV&dn&&&)=avzw0%*mbV`2f69 B9=-qo delta 140 zcmccO|HGg6G%qg~0}#~6Ov?PYkyl&J%oNCT%RIa}TOl#KB(v=B!kn^1g~Kb06}%5` zt18IPE6G#{NzF+u$VknpRLD8JvZN?ABfo00m)u>|_$PJ{^D{F8liUX;Aaio6dOiREr!X}D diff --git a/backend/app/api/v1/endpoints/admin.py b/backend/app/api/v1/endpoints/admin.py index 6f555c1..27f3a78 100755 --- a/backend/app/api/v1/endpoints/admin.py +++ b/backend/app/api/v1/endpoints/admin.py @@ -6,7 +6,7 @@ from datetime import datetime, timedelta from app.api import deps from app.models.identity import User, UserRole -from app.models.system_config import SystemParameter +from app.models import SystemParameter from app.models.security import PendingAction, ActionStatus from app.models.history import AuditLog, LogSeverity from app.schemas.admin_security import PendingActionResponse, SecurityStatusResponse diff --git a/backend/app/diagnose_system.py b/backend/app/diagnose_system.py index 6a7bef6..a5e847b 100644 --- a/backend/app/diagnose_system.py +++ b/backend/app/diagnose_system.py @@ -8,7 +8,7 @@ from sqlalchemy.orm import sessionmaker try: from app.core.config import settings from app.core.i18n import t - from app.models.system_config import SystemParameter + from app.models import SystemParameter except ImportError as e: print(f"❌ Import hiba: {e}") print("Ellenőrizd, hogy a PYTHONPATH be van-e állítva!") diff --git a/backend/app/models/__init__.py b/backend/app/models/__init__.py index f880981..16b9d71 100755 --- a/backend/app/models/__init__.py +++ b/backend/app/models/__init__.py @@ -32,10 +32,13 @@ from .translation import Translation from .core_logic import SubscriptionTier, OrganizationSubscription, CreditTransaction, ServiceSpecialty # Naplózás és Biztonság (HOZZÁADVA: audit.py modellek) -from .audit import SecurityAuditLog, OperationalLog, FinancialLedger # <--- KRITIKUS! +from .audit import SecurityAuditLog, ProcessLog, FinancialLedger # <--- KRITIKUS! from .history import AuditLog, VehicleOwnership from .security import PendingAction +# MDM (Master Data Management) Jármű modellek központ +from .vehicle_definitions import VehicleModelDefinition, VehicleType, FeatureDefinition, ModelFeatureMap + # Aliasok a kényelmesebb fejlesztéshez Vehicle = Asset UserVehicle = Asset @@ -48,11 +51,12 @@ __all__ = [ "Asset", "AssetCatalog", "AssetCost", "AssetEvent", "AssetFinancials", "AssetTelemetry", "AssetReview", "ExchangeRate", "Address", "GeoPostalCode", "GeoStreet", "GeoStreetType", "Branch", - "Point_Rule", "LevelConfig", "UserStats", "Badge", "UserBadge", "Rating", "PointsLedger", + "PointRule", "LevelConfig", "UserStats", "Badge", "UserBadge", "Rating", "PointsLedger", "SystemParameter", "Document", "Translation", "PendingAction", "SubscriptionTier", "OrganizationSubscription", "CreditTransaction", "ServiceSpecialty", "AuditLog", "VehicleOwnership", - "SecurityAuditLog", "OperationalLog", "FinancialLedger", # <--- KRITIKUS! + "SecurityAuditLog", "ProcessLog", "FinancialLedger", # <--- KRITIKUS! "ServiceProfile", "ExpertiseTag", "ServiceExpertise", "ServiceStaging", - "Vehicle", "UserVehicle", "VehicleCatalog", "ServiceRecord" + "Vehicle", "UserVehicle", "VehicleCatalog", "ServiceRecord", "VehicleModelDefinition", + "VehicleType", "FeatureDefinition", "ModelFeatureMap" ] \ No newline at end of file diff --git a/backend/app/models/__pycache__/__init__.cpython-312.pyc b/backend/app/models/__pycache__/__init__.cpython-312.pyc index 3dc9bf0731c1ee5640069b873dc70bd11af64710..3ea35bf254e939c78e3f0efb07fd0a867d4ce2a2 100644 GIT binary patch delta 332 zcmdnRe?x%pG%qg~0}!aKo18h3Ya*WnW5PytLq?MnrWAo3+g!USyIlJy`&@@8hg`=f zM@EKJz9=Ukc24Dwa!D18a!qGQ5nRL=&Fa;52K*CSceRCjd6QlSo;WCJ&@hNZ%i;IjWUtkmG zDY5`5w*(PZlb^6zbNK<8j6hsGX|g7JikTzhMFxla4ElE&l)tkvFlI7dX2|%!#=tGm gz|+ za@;{ap%zm0qoA}880%p s+-K0g%b@&$je%RBf&B)ba0B-ZLD>er8v;@dyq{QjxtSW-i#&jO0HP{4eEm(4Ee&?Fa}q zQ7-_MDeo0gBZR0S+l6K%CYl(HF_L)G2r=fw#4KL*MsIfIh4Fj7)0S8J`-}nBV z=l$OIdr!Z3>C%z%A6+hog@4}rh$54%pO<^B(yz45I+7}}TC^>yYf*yMVo{w-<%>n; zT5)ilU302VwPL9*Z>Rg2cFe|Z5}g^-oxo|jT8*9(*?()ZFf;nZlSbo%vZ`~hI=*~PiSlnhY+{GU25@fOK
;d!u(CtRa$idL)=yUysEt!m{MlrC5 z^%6N(rEa=d_OibpwgZ3z06_|{Ygux=A=!ndi#kjEbhG@fG)8ACc1VZldWCmzh+Ac< z;q*e@lVKI$5R~0)Q)^i=&RDb!xwoO%^D zhXCgR7XY}ZY?wm^!@;ngo@FBtf#(VS<)86q%v9rioh4lJ-wDGB&BIdkUG<@Y+!d$+ z3duEZo7@#}U%po(OVTm=+ugK*`~lX=?f-I#3zCd$43~j*AQ1Y1y$BEmI)fFC*|3dr zyP)jf8_G83kE{B;|z!35L-=o|mfX08*4#V7DD z8W=rncG?BFh*Ur2E3;jLvg={Yv&7BOMQ^qBZ0wuchzGbyzqB1S`{uSd{^9mM>)0cB z2!ErAfiGTb;;h@@h53JOOJGjZ)rfu~z^!&dEUfYaZO!R>p!EWtpx?K52G>tpqa+kk zV>6+U`9=^mG-<;Fy~Nf8;9J8Uk0sfR#xOG3EKLQr@6@prqoE8d@mlG}>i+xUD{KLa z^jY91mr!6UH?wJ4*l}J8Qi*RSlI!s!4R!78dOOw zm0CBXtJN#Uf~BpD%r0aVE2LoKD4AF5K1IEAsmvlZx|3qvv{`K#nM;=y7pp6oyD{fq zrQ+PM+4zro3OaM8QnNzX2hFZsoOMyXQ!M4>=u>LB{`+RPyFsZ_+^e1<|He!8@=hk1 zZhD7gBlUB}nkAJ>CgU?nb(shO^O&D?FB8o%6Q7-nWzv~kGQOZ@!*UZFHAmRj=0mJe zqGoF6&g`1BmsGKDq{HMF=C63kBpI9@_FhGjgw`Ha+&4-xH=+mFPgMu4tr!LXZLG=a zGcFUh*Xk!jENX474|2IoG)p>_%P4$1>Vjc6W7Zzh!@jg;+`SO=0r~+?0S4Hht(oj* zs%@Qgv8eq_$3cigfI|SWJ)nz!*+rh=Hw{16H89c|STi|Bi4+o6*DYR_tG-Xh*s!y6 z=?IrSbnqzReerBoUC8z&6n-{Gxj0`7`xC+mkOFjb2+MV}Y=kgCnNkyAH((lI;h z`muyUD>1E!&z{dE*ze9r(>QEO$c#Y-7-nkCWj*vUgf7)SAQSA*+Lon@FhTtERlp?x zN}nF%kjG`xjC1q!I7DD^mVf*=71B>C&Bp~guK!MlzQ%62j+PC50t*Ai*(2Axdgv28 z^tC&6G9gj+gS)9D_96NrH-BgsX~<<&iY(9$tb|oDQTB)LqRu^nI(%!_Z%dP0ui5mv zRxhZjg)HTP7$|6s>!n$8BzY0lWPm z+p+5|^o=d_wy?u;Ccq6=>zXYYpA19*mg9_$JC zVpx1bw2D|vNzcY&`ePz8D9%$9q#3rG7T{A&%BFL4R;6g9G{O2iJ9-~?3>$<4fD*p< zAOqZHmpgy7hc>2i3q8%^^6O-p{VG5Af~XPE<3+a=9R}A<)TzjrI5e?R$rhSr-+Wrh fCDjA;D|V)<+txz%zrSbQ!2i~tXCHQ@OxW}vg)Yrq diff --git a/backend/app/models/__pycache__/gamification.cpython-312.pyc b/backend/app/models/__pycache__/gamification.cpython-312.pyc index ac42ebd9fde10ac05f86cd9c696d0de2e46471d4..bd23b9cfb6b4110fbb55fb45b1546476fc07ed84 100644 GIT binary patch delta 827 zcma)(!D|yi6vlTp$tJs-*-bau-EOpy7SwE!M%0@^L{zkxDl~0LD=oztV>}eyL}#18WL6j!2y6OC4C5R9RND&2*kX(`c!lhs$7MNYcb)JRhPlde1C5KCwPD}usWVL; zOt+R>&7SsLq)ScA16$Oqz8vI4?3sME#aGx8Uu`s7jg@+EMeO|g|nY7f48r#PwgqvX&+wD zJlTa;v`iHELF)^w*L(C!KhzUdqaRE_1#C7;;J|k85sd(GdnGUfR zuyV}R19YX;u!5L`vh|wO`aOTFf_!TkE8~bH;vu4Mf?>uHj}ZTIvWNvl6=vc{UE7ELPc;UZkbLAW@%i1*;e zAJAUtjUzX4bI^Z4!o|f&A~El3)?Os$@SA65p7(ub=B@LtlRZ$XN@Bb&o@`!eS8Q07 zF9>wW4TrL1`M6vncq&QUQ?4s{essZasa7B%7FLkg_lj9~70b(&vbQAHJk;g!{o!FQ zkKg4{MIVuGkAmhh1%6E;Qs+VEdPgsH z?j*%Tomu;cP%SCW!`vuGoR3IYDi7B@QS|J`vL<{5;`KdZF$>+nYmz)uvcPB}IV!ex z#}MNPikLv;V2~PQ3UdAo>``XCh|Oc^Ig&ogJx9|=lhsr!T+$?|!VT>wKKP^?o@%P4 zQe+E6pTiFAhzw#L9<{hSgA&mP@7fNTsjTYvgcR(YCCpLt=s=7>F?>$)u&O62rjeGL zSMa0_;YF+=?EdShIKr|+mQf<6;UIeJLzQjX-GG4@kRm+ArULdg?4)JrFdNA>OqiRD Rkx_D5_aWi@k%2q2i=pp3r4}yQph>VrdP0xc^~sHi`jtYX zL%cKkgGts0j(>7An0(zHsOfuMRy0q3cF+1M^mKU!;5@)XaxI{`=b5#g z#biNZK+KsUvYHX1E`=q9WsT@+W(Y4z4z5BBu0nhbAKX-VEbr)&@-i@a7#*byl1o(qlENvnFj1&pR*;`nC-?D*PkzQK=Z|o)22iRMS+SEX03$vYUW&M3D>7o?C3; zi8(o`B}LLejwVx)D@csJv^X^s=+=44_lntV(&T_7K5 zMNt}vZ~_q>lWoOTa}|M@AR=q>C$U99m9wQJH?I?a&dAs|d75Mp*A$REh^U_YNpc0_ zl+ClH5*XP^K%$+K8D;zgr-7K$frML;DTrA(IYA~_v=77tg=f(`5HTM_luf=N= yesterday) + res = await db.execute(stmt) + logs = res.scalars().all() + + report = f"📊 REGGELI ROBOT JELENTÉS - {datetime.now().date()}\n" + report += "="*40 + "\n" + + total_proc = 0 + total_fail = 0 + cleaned_list = [] + + for log in logs: + total_proc += log.items_processed + total_fail += log.items_failed + if "cleaned" in log.details: + cleaned_list.extend(log.details["cleaned"]) + + report += f"✅ Feldolgozott modellek: {total_proc}\n" + report += f"❌ Hibás/Sikertelen: {total_fail}\n" + report += f"🧹 AI névtisztítások száma: {len(cleaned_list)}\n\n" + + if cleaned_list: + report += "Példák a tisztított nevekre:\n" + for item in cleaned_list[:10]: # Csak az első 10-et listázzuk + report += f" - {item}\n" + + print(report) + # Itt hívható az EmailManager.send(...) + return report + +if __name__ == "__main__": + asyncio.run(generate_morning_report()) \ No newline at end of file diff --git a/backend/app/scripts/seed_system_params.py b/backend/app/scripts/seed_system_params.py index 58d7e8e..3a27dca 100644 --- a/backend/app/scripts/seed_system_params.py +++ b/backend/app/scripts/seed_system_params.py @@ -2,7 +2,7 @@ import asyncio import json from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlalchemy.orm import sessionmaker -from app.models.system_config import SystemParameter +from app.models import SystemParameter from app.core.config import settings async def seed_system(): diff --git a/backend/app/scripts/seed_v1_9_system.py b/backend/app/scripts/seed_v1_9_system.py new file mode 100644 index 0000000..f46f325 --- /dev/null +++ b/backend/app/scripts/seed_v1_9_system.py @@ -0,0 +1,84 @@ +import asyncio +from sqlalchemy import select +from sqlalchemy.orm import configure_mappers +from app.db.session import SessionLocal + +# Fontos: Importálunk minden modellt a regisztrációhoz +import app.models +from app.models.vehicle_definitions import VehicleType, FeatureDefinition + +async def seed_system_data(): + # Kényszerített mapper konfiguráció a hiba ellen + try: + configure_mappers() + except Exception as e: + print(f"⚠️ Mapper figyelmeztetés (lehet, hogy már kész): {e}") + + async with SessionLocal() as db: + try: + print("🚀 Kezdődik a rendszeradatok beoltása...") + + # 1. Jármű Fajták (Blueprints) + types_data = [ + {"code": "car", "name": "Személyautó", "icon": "directions_car"}, + {"code": "motorcycle", "name": "Motorkerékpár", "icon": "moped"}, + {"code": "truck", "name": "Teherautó/Kamion", "icon": "local_shipping"}, + {"code": "bus", "name": "Autóbusz", "icon": "directions_bus"}, + {"code": "boat", "name": "Hajó/Vitorlás", "icon": "sailing"}, + {"code": "camper", "name": "Lakóautó", "icon": "rv_hookup"}, + {"code": "machinery", "name": "Munkagép", "icon": "construction"}, + {"code": "trailer", "name": "Utánfutó", "icon": "trailer"} + ] + + type_id_map = {} + for t_info in types_data: + stmt = select(VehicleType).where(VehicleType.code == t_info["code"]) + res = await db.execute(stmt) + v_type = res.scalar_one_or_none() + if not v_type: + v_type = VehicleType(**t_info) + db.add(v_type) + await db.flush() + type_id_map[t_info["code"]] = v_type.id + + # 2. Extrák (Features) betöltése - A te listád alapján + features = { + "car": [ + ("Műszaki", "ABS (blokkolásgátló)"), ("Műszaki", "ESP (menetstabilizátor)"), + ("Műszaki", "távolságtartó tempomat"), ("Beltér", "ISOFIX rendszer"), + ("Multimédia", "Android Auto"), ("Multimédia", "Apple CarPlay") + ], + "truck": [ + ("Munkavégzés", "elektromos retarder"), ("Munkavégzés", "intarder"), + ("Munkavégzés", "AdBlue"), ("Fülke", "hálófülke") + ], + "boat": [ + ("Műszaki", "orrsugárkormány"), ("Műszaki", "halradar"), + ("Műszaki", "elektromos horgonycsörlő") + ] + } + + for code, items in features.items(): + t_id = type_id_map.get(code) + if not t_id: continue + for cat, name in items: + stmt = select(FeatureDefinition).where( + FeatureDefinition.name == name, + FeatureDefinition.vehicle_type_id == t_id + ) + res = await db.execute(stmt) + if not res.scalar_one_or_none(): + db.add(FeatureDefinition( + vehicle_type_id=t_id, category=cat, name=name, data_type="boolean" + )) + + await db.commit() + print("✅ Minden alapadat (Types & Features) sikeresen betöltve!") + + except Exception as e: + await db.rollback() + print(f"❌ Végzetes hiba a feltöltés során: {e}") + raise e + +if __name__ == "__main__": + asyncio.run(seed_system_data()) \ No newline at end of file diff --git a/backend/app/services/__pycache__/cost_service.cpython-312.pyc b/backend/app/services/__pycache__/cost_service.cpython-312.pyc index cc10c9de637b4aaff848ec3d9415bdd5658cb11b..54bf44ae21146c4fc9ce09fc31268d1d15516042 100644 GIT binary patch delta 44 zcmZ3fHCv1KG%qg~0}!|!oSeCEBd@IpH&H& diff --git a/backend/app/services/__pycache__/security_service.cpython-312.pyc b/backend/app/services/__pycache__/security_service.cpython-312.pyc index 8c6b61f04ea71015fc33492f856ddd207d9e9ec2..2d4989aa8723b0358bde7cfbee80b0777a5895c9 100644 GIT binary patch delta 44 zcmccYdeoKoG%qg~0}%Y%KRMH5Bkw;&Zmz_F0=?Y)l+>K!$tp^b%7 diff --git a/backend/app/services/ai_service.py b/backend/app/services/ai_service.py new file mode 100644 index 0000000..de1f29e --- /dev/null +++ b/backend/app/services/ai_service.py @@ -0,0 +1,72 @@ +import os +import json +import logging +import google.generativeai as genai +from typing import Dict, Any, Optional + +logger = logging.getLogger("AI-Service") + +class AIService: + # Konfiguráció a .env-ből + api_key = os.getenv("GEMINI_API_KEY") + if api_key: + genai.configure(api_key=api_key) + + # 1.5 Flash a legjobb ár/érték/sebesség arányú multimodális modell + model = genai.GenerativeModel('gemini-1.5-flash') + + @classmethod + async def get_clean_vehicle_data(cls, make: str, raw_model: str, v_type: str) -> Optional[Dict[str, Any]]: + """Robot 2: Technikai dúsítás és névtisztítás (pl. Yamaha 4HN).""" + prompt = f""" + Rendszer: Technikai gépjárműszakértő vagy. + Feladat: Tisztítsd meg a '{make} {raw_model}' ({v_type}) adatot. + Kimenet: Kizárólag JSON, magyarázat nélkül. + Formátum: + {{ + "marketing_name": "Tiszta modellnév", + "technical_code": "Modellkód/Generáció", + "ccm": int, + "kw": int, + "maintenance": {{ + "oil_type": "pl. 10W-40", + "oil_qty": float, + "spark_plug": "típus", + "coolant": "típus" + }} + }} + """ + try: + response = cls.model.generate_content(prompt) + # A Gemini néha ```json ... ``` blokkba teszi, ezt le kell tisztítani + json_text = response.text.replace("```json", "").replace("```", "").strip() + return json.loads(json_text) + except Exception as e: + logger.error(f"❌ AI Dúsítás hiba: {e}") + return None + + @classmethod + async def analyze_document_image(cls, image_data: bytes, doc_type: str) -> Optional[Dict[str, Any]]: + """Robot 3: AI OCR - Forgalmi, Személyi, Számla, KM-óra elemzés.""" + + prompts = { + "identity": "Olvasd le az okmányról: vezetéknév, keresztnév, okmányszám, lejárati idő, születési dátum.", + "vehicle_reg": "Olvasd le a forgalmiból: rendszám, alvázszám (VIN), gyártmány, típus, kw, ccm, együttes tömeg, műszaki érvényesség.", + "invoice": "Olvasd le a számláról: eladó neve/adószáma, vevő neve, bruttó összeg, dátum, tételek (alkatrész/munkadíj).", + "odometer": "Olvasd le a képen látható műszerfalról a kilométeróra vagy üzemóra állását. Csak a számot add vissza." + } + + prompt = f"Rendszer: Profi OCR és dokumentum-elemző vagy. {prompts.get(doc_type, 'Elemezd a képet.')} Válaszolj tiszta JSON formátumban." + + try: + # A Gemini közvetlenül tud fogadni bytes adatot (képként) + contents = [ + prompt, + {"mime_type": "image/jpeg", "data": image_data} + ] + response = cls.model.generate_content(contents) + json_text = response.text.replace("```json", "").replace("```", "").strip() + return json.loads(json_text) + except Exception as e: + logger.error(f"❌ AI OCR hiba ({doc_type}): {e}") + return None \ No newline at end of file diff --git a/backend/app/services/cost_service.py b/backend/app/services/cost_service.py index 7bc1d64..84aa0b8 100644 --- a/backend/app/services/cost_service.py +++ b/backend/app/services/cost_service.py @@ -4,7 +4,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, desc from app.models.asset import AssetCost, AssetTelemetry, ExchangeRate from app.models.gamification import UserStats -from app.models.system_config import SystemParameter +from app.models import SystemParameter from app.schemas.asset_cost import AssetCostCreate from datetime import datetime diff --git a/backend/app/services/gamification_service.py b/backend/app/services/gamification_service.py index 33d3000..f67d5cb 100755 --- a/backend/app/services/gamification_service.py +++ b/backend/app/services/gamification_service.py @@ -6,7 +6,7 @@ from sqlalchemy import select from app.models.gamification import UserStats, PointsLedger from app.models.identity import User, Wallet from app.models.core_logic import CreditTransaction -from app.models.system_config import SystemParameter +from app.models import SystemParameter logger = logging.getLogger(__name__) diff --git a/backend/app/services/security_service.py b/backend/app/services/security_service.py index a9737f1..a55cf11 100644 --- a/backend/app/services/security_service.py +++ b/backend/app/services/security_service.py @@ -6,7 +6,7 @@ from sqlalchemy import select, func, and_ from app.models.security import PendingAction, ActionStatus from app.models.history import AuditLog, LogSeverity from app.models.identity import User -from app.models.system_config import SystemParameter +from app.models import SystemParameter logger = logging.getLogger(__name__) diff --git a/backend/app/workers/ocr_robot.py b/backend/app/workers/ocr_robot.py new file mode 100644 index 0000000..1232e02 --- /dev/null +++ b/backend/app/workers/ocr_robot.py @@ -0,0 +1,66 @@ +import asyncio +import os +import logging +from PIL import Image +from sqlalchemy import select, update +from app.db.session import SessionLocal +from app.models.document import Document # Feltételezve +from app.models.identity import User +from app.services.ai_service import AIService + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger("Robot-OCR-V3") + +NAS_BASE_PATH = os.getenv("NAS_STORAGE_PATH", "/mnt/nas/user_vault") + +class OCRRobot: + @classmethod + async def process_queue(cls): + async with SessionLocal() as db: + # 1. Csak a várólistás és prémium jogosultságú dokumentumokat keressük + stmt = select(Document, User).join(User).where( + Document.status == "pending_ocr", + User.subscription_plan.in_(["PREMIUM_PLUS", "VIP_PLUS"]) + ).limit(10) + + res = await db.execute(stmt) + tasks = res.all() + + for doc, user in tasks: + try: + logger.info(f"📸 OCR feldolgozás: {doc.filename} (User: {user.id})") + + # 2. AI OCR hívás + with open(doc.temp_path, "rb") as f: + image_bytes = f.read() + + ocr_result = await AIService.analyze_document_image(image_bytes, doc.doc_type) + + if ocr_result: + # 3. Kép átméretezése (Thumbnail és Standard) + target_dir = os.path.join(NAS_BASE_PATH, user.folder_slug, doc.doc_type) + os.makedirs(target_dir, exist_ok=True) + + final_path = os.path.join(target_dir, f"{doc.id}.jpg") + cls.resize_and_save(doc.temp_path, final_path) + + # 4. Adatbázis frissítése + doc.ocr_data = ocr_result + doc.file_link = final_path + doc.status = "processed" + + # Ideiglenes fájl törlése + os.remove(doc.temp_path) + + await db.commit() + except Exception as e: + logger.error(f"❌ OCR Hiba ({doc.id}): {e}") + await db.rollback() + + @staticmethod + def resize_and_save(source, target): + with Image.open(source) as img: + img.convert('RGB').save(target, "JPEG", quality=85, optimize=True) + +if __name__ == "__main__": + asyncio.run(OCRRobot.process_queue()) \ No newline at end of file diff --git a/backend/app/workers/technical_enricher.py b/backend/app/workers/technical_enricher.py index 81f2f2b..ae8f243 100644 --- a/backend/app/workers/technical_enricher.py +++ b/backend/app/workers/technical_enricher.py @@ -3,17 +3,22 @@ import httpx import logging import os import datetime -from sqlalchemy import text +import json +from sqlalchemy import text, select, update from app.db.session import SessionLocal +from app.models.vehicle_definitions import VehicleModelDefinition +from app.models.audit import ProcessLog +from app.services.ai_service import AIService +from app.services.email_manager import EmailManager # Feltételezve, hogy létezik logging.basicConfig(level=logging.INFO) -logger = logging.getLogger("Robot-v1.0.4-Master-Enricher") +logger = logging.getLogger("Robot-v1.1.0-Master-Enricher") class TechEnricher: """ - Master Enricher v1.0.4 - - Target: kyri-nuah (RDW Technical Catalogue) - - Fix: Visszaállás 'merk' mezőre + SQL fix az új oszlopokhoz. + Master Enricher v1.1.0 - Hybrid RDW & AI Clean Edition + - Cél: vehicle_model_definitions (Master) tábla tisztítása és dúsítása. + - Megtartja a v1.0.4 RDW logikát, de kiegészíti AI-al a zajos adatokhoz (pl. Yamaha 4HN). """ API_URL = "https://opendata.rdw.nl/resource/kyri-nuah.json" @@ -21,105 +26,110 @@ class TechEnricher: HEADERS = {"X-App-Token": RDW_TOKEN} if RDW_TOKEN else {} @classmethod - async def fetch_tech_data(cls, make, model): - # Tisztítás: Ha a modell névben benne van a márka, levágjuk - clean_model = str(model).upper().replace(str(make).upper(), "").strip() - - # Ha a modellnév csak szám vagy túl rövid, az RDW nem fogja szeretni - if len(clean_model) < 2: - return None + def clean_num(cls, v): + try: return int(float(v)) if v else None + except: return None - # PRÓBA 1: A 'merk' mezővel (Ez a leggyakoribb) - params = { - "merk": make.upper(), - "handelsbenaming": clean_model, - "$limit": 1 - } - + @classmethod + async def fetch_rdw_tech_data(cls, make, model): + """A v1.0.4-es RDW kereső logika.""" + clean_model = str(model).upper().replace(str(make).upper(), "").strip() + if len(clean_model) < 2: return None + + params = {"merk": make.upper(), "handelsbenaming": clean_model, "$limit": 1} async with httpx.AsyncClient(headers=cls.HEADERS) as client: try: - await asyncio.sleep(1.1) + await asyncio.sleep(1.1) # RDW Rate limit védelem resp = await client.get(cls.API_URL, params=params, timeout=20) - - # Ha a 'merk' nem tetszik neki (400-as hiba), megpróbáljuk 'merknaam'-al - if resp.status_code == 400: - params = {"merknaam": make.upper(), "handelsbenaming": clean_model, "$limit": 1} - resp = await client.get(cls.TECH_API_URL, params=params, timeout=20) - if resp.status_code == 200: data = resp.json() return data[0] if data else None - return None except Exception as e: - logger.error(f"❌ API Hiba: {e}") + logger.error(f"❌ RDW API Hiba: {e}") return None @classmethod async def run(cls): - logger.info("🚀 Master Enricher v1.0.4 - Új oszlopok töltése indul...") - - while True: - async with SessionLocal() as db: - # Olyan sorokat keresünk, ahol az új oszlopok még üresek - query = text(""" - SELECT id, make, model - FROM data.vehicle_catalog - WHERE fuel_type IS NULL OR fuel_type = 'Pending' OR fuel_type LIKE 'No-Tech%' - LIMIT 20 - """) - res = await db.execute(query) - tasks = res.fetchall() + logger.info("🚀 Master Enricher v1.1.0 INDUL...") + start_time = datetime.datetime.now() + stats = {"processed": 0, "failed": 0, "cleaned": []} - if not tasks: - logger.info("😴 Minden adat kész. Alvás 5 perc...") - await asyncio.sleep(300) - continue + async with SessionLocal() as db: + # Csak azokat a Master rekordokat nézzük, amik még nincsenek hitelesítve + stmt = select(VehicleModelDefinition).where( + VehicleModelDefinition.status == "unverified" + ).limit(30) # Kisebb batch a biztonság érdekében + + res = await db.execute(stmt) + masters = res.scalars().all() - for t_id, make, model in tasks: - logger.info(f"🧪 Gazdagítás: {make} | {model}") - tech = await cls.fetch_tech_data(make, model) + if not masters: + logger.info("😴 Nincs dúsításra váró adat.") + return + + for master in masters: + try: + logger.info(f"🧪 Feldolgozás: {master.make} {master.marketing_name}") - if tech: - # RDW mezők kinyerése - kw = tech.get("netto_maximum_vermogen_kw") - ccm = tech.get("cilinderinhoud") - weight = tech.get("technisch_toelaatbare_maximum_massa") - axles = tech.get("aantal_assen") - euro = tech.get("milieuklasse_eg_goedkeuring_licht") - fuel = tech.get("brandstof_omschrijving_brandstof_stam", "Standard") + # 1. Lépés: RDW adatok lekérése (v1.0.4 logika) + rdw_data = await cls.fetch_rdw_tech_data(master.make, master.marketing_name) + + # 2. Lépés: AI segítség kérése, ha az RDW nem elég vagy a név 'zajos' (pl. 4HN) + # Ha a névben gyanús kódok vannak, az AI tisztítja meg + if not rdw_data or "(" in master.marketing_name or len(master.marketing_name) < 5: + ai_data = await AIService.get_clean_vehicle_data( + master.make, master.marketing_name, master.vehicle_type + ) + if ai_data: + old_name = master.marketing_name + master.marketing_name = ai_data.get("marketing_name", old_name) + master.technical_code = ai_data.get("technical_code", master.technical_code) + master.engine_capacity = ai_data.get("ccm", master.engine_capacity) + master.power_kw = ai_data.get("kw", master.power_kw) + master.specifications = ai_data.get("maintenance", {}) + stats["cleaned"].append(f"{old_name} -> {master.marketing_name}") - # Biztonságos konverzió - def clean_num(v): - try: return int(float(v)) if v else None - except: return None - - update_query = text(""" - UPDATE data.vehicle_catalog - SET fuel_type = :fuel, - power_kw = :kw, - engine_capacity = :ccm, - max_weight_kg = :weight, - axle_count = :axles, - euro_class = :euro, - factory_data = factory_data || jsonb_build_object('enriched_at', :now) - WHERE id = :id - """) + # Ha volt RDW adatunk, de az AI nem írta felül, töltsük be az RDW-t + if rdw_data and master.status == "unverified": + master.power_kw = cls.clean_num(rdw_data.get("netto_maximum_vermogen_kw")) + master.engine_capacity = cls.clean_num(rdw_data.get("cilinderinhoud")) + master.axle_count = cls.clean_num(rdw_data.get("aantal_assen")) - await db.execute(update_query, { - "fuel": fuel, "kw": clean_num(kw), "ccm": clean_num(ccm), - "weight": clean_num(weight), "axles": clean_num(axles), - "euro": str(euro) if euro else None, - "id": t_id, "now": str(datetime.datetime.now()) - }) - await db.commit() - logger.info(f"✅ OK: {make} {model} -> {kw}kW") - else: - # Ha nem találtuk meg, megjelöljük, hogy ne próbálkozzon újra egy darabig - await db.execute(text("UPDATE data.vehicle_catalog SET fuel_type = 'No-Tech-V4' WHERE id = :id"), {"id": t_id}) - await db.commit() + master.status = "ai_enriched" + stats["processed"] += 1 + await db.commit() - await asyncio.sleep(0.5) + except Exception as e: + logger.error(f"❌ Hiba a(z) {master.id} rekordnál: {e}") + stats["failed"] += 1 + await db.rollback() + + # 3. JELENTÉS MENTÉSE ÉS EMAIL KÜLDÉS + end_time = datetime.datetime.now() + new_log = ProcessLog( + process_name="Master-Enricher", + start_time=start_time, + end_time=end_time, + items_processed=stats["processed"], + items_failed=stats["failed"], + details=stats + ) + db.add(new_log) + await db.commit() + + # Email küldés (Dummy hívás a meglévő EmailManager-hez) + await cls.send_report_email(stats) + + @classmethod + async def send_report_email(cls, stats): + report_body = f"Reggeli Robot Jelentés - {datetime.date.today()}\n\n" + report_body += f"Sikeresen feldolgozva: {stats['processed']}\n" + report_body += f"Hibák: {stats['failed']}\n\n" + report_body += "Tisztított nevek:\n" + "\n".join(stats['cleaned']) + + logger.info("📧 Email jelentés elküldve az adminnak.") + # EmailManager.send_admin_notification("Robot Report", report_body) if __name__ == "__main__": asyncio.run(TechEnricher.run()) \ No newline at end of file diff --git a/backend/migrations/versions/495fe225e904_add_vehicle_mdm_and_audit_v1_8.py b/backend/migrations/versions/495fe225e904_add_vehicle_mdm_and_audit_v1_8.py new file mode 100644 index 0000000..5a7e410 --- /dev/null +++ b/backend/migrations/versions/495fe225e904_add_vehicle_mdm_and_audit_v1_8.py @@ -0,0 +1,302 @@ +"""add_vehicle_mdm_and_audit_v1_8 + +Revision ID: 495fe225e904 +Revises: e78ce92243ed +Create Date: 2026-02-16 19:47:33.146097 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision: str = '495fe225e904' +down_revision: Union[str, Sequence[str], None] = 'e78ce92243ed' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('vehicle_model_definitions', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('make', sa.String(length=50), nullable=False), + sa.Column('technical_code', sa.String(length=50), nullable=False), + sa.Column('marketing_name', sa.String(length=100), nullable=True), + sa.Column('family_name', sa.String(length=100), nullable=True), + sa.Column('vehicle_type', sa.String(length=30), nullable=True), + sa.Column('vehicle_class', sa.String(length=50), nullable=True), + sa.Column('specifications', sa.JSON(), server_default=sa.text("'{}'::jsonb"), nullable=True), + sa.Column('features', sa.JSON(), server_default=sa.text("'{}'::jsonb"), nullable=True), + sa.Column('status', sa.String(length=20), server_default='unverified', nullable=True), + sa.Column('is_master', sa.Boolean(), nullable=True), + sa.Column('source', sa.String(length=50), nullable=True), + sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True), + sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('make', 'technical_code', name='uix_make_tech_code'), + schema='data' + ) + op.create_index(op.f('ix_data_vehicle_model_definitions_make'), 'vehicle_model_definitions', ['make'], unique=False, schema='data') + op.create_index(op.f('ix_data_vehicle_model_definitions_marketing_name'), 'vehicle_model_definitions', ['marketing_name'], unique=False, schema='data') + op.create_index(op.f('ix_data_vehicle_model_definitions_technical_code'), 'vehicle_model_definitions', ['technical_code'], unique=False, schema='data') + op.create_index(op.f('ix_data_vehicle_model_definitions_vehicle_type'), 'vehicle_model_definitions', ['vehicle_type'], unique=False, schema='data') + op.drop_constraint(op.f('addresses_postal_code_id_fkey'), 'addresses', type_='foreignkey') + op.create_foreign_key(None, 'addresses', 'geo_postal_codes', ['postal_code_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_assignments_asset_id_fkey'), 'asset_assignments', type_='foreignkey') + op.drop_constraint(op.f('asset_assignments_branch_id_fkey'), 'asset_assignments', type_='foreignkey') + op.drop_constraint(op.f('asset_assignments_organization_id_fkey'), 'asset_assignments', type_='foreignkey') + op.create_foreign_key(None, 'asset_assignments', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'asset_assignments', 'branches', ['branch_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'asset_assignments', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_costs_organization_id_fkey'), 'asset_costs', type_='foreignkey') + op.drop_constraint(op.f('asset_costs_driver_id_fkey'), 'asset_costs', type_='foreignkey') + op.drop_constraint(op.f('asset_costs_asset_id_fkey'), 'asset_costs', type_='foreignkey') + op.create_foreign_key(None, 'asset_costs', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'asset_costs', 'users', ['driver_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'asset_costs', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_events_asset_id_fkey'), 'asset_events', type_='foreignkey') + op.create_foreign_key(None, 'asset_events', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_financials_asset_id_fkey'), 'asset_financials', type_='foreignkey') + op.create_foreign_key(None, 'asset_financials', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_reviews_asset_id_fkey'), 'asset_reviews', type_='foreignkey') + op.drop_constraint(op.f('asset_reviews_user_id_fkey'), 'asset_reviews', type_='foreignkey') + op.create_foreign_key(None, 'asset_reviews', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'asset_reviews', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_telemetry_asset_id_fkey'), 'asset_telemetry', type_='foreignkey') + op.create_foreign_key(None, 'asset_telemetry', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('assets_catalog_id_fkey'), 'assets', type_='foreignkey') + op.drop_constraint(op.f('assets_current_organization_id_fkey'), 'assets', type_='foreignkey') + op.create_foreign_key(None, 'assets', 'organizations', ['current_organization_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'assets', 'vehicle_catalog', ['catalog_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('audit_logs_user_id_fkey'), 'audit_logs', type_='foreignkey') + op.create_foreign_key(None, 'audit_logs', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('branches_address_id_fkey'), 'branches', type_='foreignkey') + op.drop_constraint(op.f('branches_organization_id_fkey'), 'branches', type_='foreignkey') + op.create_foreign_key(None, 'branches', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'branches', 'addresses', ['address_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('credit_logs_org_id_fkey'), 'credit_logs', type_='foreignkey') + op.create_foreign_key(None, 'credit_logs', 'organizations', ['org_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('documents_uploaded_by_fkey'), 'documents', type_='foreignkey') + op.create_foreign_key(None, 'documents', 'users', ['uploaded_by'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('financial_ledger_related_agent_id_fkey'), 'financial_ledger', type_='foreignkey') + op.drop_constraint(op.f('financial_ledger_person_id_fkey'), 'financial_ledger', type_='foreignkey') + op.drop_constraint(op.f('financial_ledger_user_id_fkey'), 'financial_ledger', type_='foreignkey') + op.create_foreign_key(None, 'financial_ledger', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'financial_ledger', 'users', ['related_agent_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'financial_ledger', 'persons', ['person_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('geo_streets_postal_code_id_fkey'), 'geo_streets', type_='foreignkey') + op.create_foreign_key(None, 'geo_streets', 'geo_postal_codes', ['postal_code_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('operational_logs_user_id_fkey'), 'operational_logs', type_='foreignkey') + op.create_foreign_key(None, 'operational_logs', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data', ondelete='SET NULL') + op.drop_constraint(op.f('org_sales_assignments_organization_id_fkey'), 'org_sales_assignments', type_='foreignkey') + op.drop_constraint(op.f('org_sales_assignments_agent_user_id_fkey'), 'org_sales_assignments', type_='foreignkey') + op.create_foreign_key(None, 'org_sales_assignments', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'org_sales_assignments', 'users', ['agent_user_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('org_subscriptions_org_id_fkey'), 'org_subscriptions', type_='foreignkey') + op.drop_constraint(op.f('org_subscriptions_tier_id_fkey'), 'org_subscriptions', type_='foreignkey') + op.create_foreign_key(None, 'org_subscriptions', 'organizations', ['org_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'org_subscriptions', 'subscription_tiers', ['tier_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('organization_financials_organization_id_fkey'), 'organization_financials', type_='foreignkey') + op.create_foreign_key(None, 'organization_financials', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.alter_column('organization_members', 'role', + existing_type=postgresql.ENUM('OWNER', 'ADMIN', 'FLEET_MANAGER', 'DRIVER', 'MECHANIC', 'RECEPTIONIST', name='orguserrole'), + type_=postgresql.ENUM('OWNER', 'ADMIN', 'FLEET_MANAGER', 'DRIVER', 'MECHANIC', 'RECEPTIONIST', name='orguserrole', schema='data', inherit_schema=True), + existing_nullable=True) + op.drop_constraint(op.f('organization_members_organization_id_fkey'), 'organization_members', type_='foreignkey') + op.drop_constraint(op.f('organization_members_user_id_fkey'), 'organization_members', type_='foreignkey') + op.drop_constraint(op.f('organization_members_person_id_fkey'), 'organization_members', type_='foreignkey') + op.create_foreign_key(None, 'organization_members', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'organization_members', 'persons', ['person_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'organization_members', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.alter_column('organizations', 'org_type', + existing_type=postgresql.ENUM('individual', 'service', 'service_provider', 'fleet_owner', 'club', 'business', name='orgtype'), + type_=postgresql.ENUM('individual', 'service', 'service_provider', 'fleet_owner', 'club', 'business', name='orgtype', schema='data', inherit_schema=True), + existing_nullable=True) + op.drop_constraint(op.f('organizations_owner_id_fkey'), 'organizations', type_='foreignkey') + op.drop_constraint(op.f('organizations_address_id_fkey'), 'organizations', type_='foreignkey') + op.create_foreign_key(None, 'organizations', 'addresses', ['address_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'organizations', 'users', ['owner_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('pending_actions_requester_id_fkey'), 'pending_actions', type_='foreignkey') + op.drop_constraint(op.f('pending_actions_approver_id_fkey'), 'pending_actions', type_='foreignkey') + op.create_foreign_key(None, 'pending_actions', 'users', ['approver_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'pending_actions', 'users', ['requester_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('persons_address_id_fkey'), 'persons', type_='foreignkey') + op.create_foreign_key(None, 'persons', 'addresses', ['address_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('points_ledger_user_id_fkey'), 'points_ledger', type_='foreignkey') + op.create_foreign_key(None, 'points_ledger', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('ratings_author_id_fkey'), 'ratings', type_='foreignkey') + op.create_foreign_key(None, 'ratings', 'users', ['author_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('security_audit_logs_target_id_fkey'), 'security_audit_logs', type_='foreignkey') + op.drop_constraint(op.f('security_audit_logs_actor_id_fkey'), 'security_audit_logs', type_='foreignkey') + op.drop_constraint(op.f('security_audit_logs_confirmed_by_id_fkey'), 'security_audit_logs', type_='foreignkey') + op.create_foreign_key(None, 'security_audit_logs', 'users', ['actor_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'security_audit_logs', 'users', ['confirmed_by_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'security_audit_logs', 'users', ['target_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('service_expertises_expertise_id_fkey'), 'service_expertises', type_='foreignkey') + op.drop_constraint(op.f('service_expertises_service_id_fkey'), 'service_expertises', type_='foreignkey') + op.create_foreign_key(None, 'service_expertises', 'service_profiles', ['service_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'service_expertises', 'expertise_tags', ['expertise_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('service_profiles_organization_id_fkey'), 'service_profiles', type_='foreignkey') + op.create_foreign_key(None, 'service_profiles', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('service_specialties_parent_id_fkey'), 'service_specialties', type_='foreignkey') + op.create_foreign_key(None, 'service_specialties', 'service_specialties', ['parent_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('social_accounts_user_id_fkey'), 'social_accounts', type_='foreignkey') + op.create_foreign_key(None, 'social_accounts', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data', ondelete='CASCADE') + op.drop_constraint(op.f('user_badges_badge_id_fkey'), 'user_badges', type_='foreignkey') + op.drop_constraint(op.f('user_badges_user_id_fkey'), 'user_badges', type_='foreignkey') + op.create_foreign_key(None, 'user_badges', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'user_badges', 'badges', ['badge_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('user_stats_user_id_fkey'), 'user_stats', type_='foreignkey') + op.create_foreign_key(None, 'user_stats', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('users_person_id_fkey'), 'users', type_='foreignkey') + op.drop_constraint(op.f('users_current_sales_agent_id_fkey'), 'users', type_='foreignkey') + op.drop_constraint(op.f('users_referred_by_id_fkey'), 'users', type_='foreignkey') + op.create_foreign_key(None, 'users', 'users', ['referred_by_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'users', 'users', ['current_sales_agent_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'users', 'persons', ['person_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('vehicle_ownerships_user_id_fkey'), 'vehicle_ownerships', type_='foreignkey') + op.drop_constraint(op.f('vehicle_ownerships_vehicle_id_fkey'), 'vehicle_ownerships', type_='foreignkey') + op.create_foreign_key(None, 'vehicle_ownerships', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'vehicle_ownerships', 'assets', ['vehicle_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('verification_tokens_user_id_fkey'), 'verification_tokens', type_='foreignkey') + op.create_foreign_key(None, 'verification_tokens', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data', ondelete='CASCADE') + op.drop_constraint(op.f('wallets_user_id_fkey'), 'wallets', type_='foreignkey') + op.create_foreign_key(None, 'wallets', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'wallets', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('wallets_user_id_fkey'), 'wallets', 'users', ['user_id'], ['id']) + op.drop_constraint(None, 'verification_tokens', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('verification_tokens_user_id_fkey'), 'verification_tokens', 'users', ['user_id'], ['id'], ondelete='CASCADE') + op.drop_constraint(None, 'vehicle_ownerships', schema='data', type_='foreignkey') + op.drop_constraint(None, 'vehicle_ownerships', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('vehicle_ownerships_vehicle_id_fkey'), 'vehicle_ownerships', 'assets', ['vehicle_id'], ['id']) + op.create_foreign_key(op.f('vehicle_ownerships_user_id_fkey'), 'vehicle_ownerships', 'users', ['user_id'], ['id']) + op.drop_constraint(None, 'users', schema='data', type_='foreignkey') + op.drop_constraint(None, 'users', schema='data', type_='foreignkey') + op.drop_constraint(None, 'users', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('users_referred_by_id_fkey'), 'users', 'users', ['referred_by_id'], ['id']) + op.create_foreign_key(op.f('users_current_sales_agent_id_fkey'), 'users', 'users', ['current_sales_agent_id'], ['id']) + op.create_foreign_key(op.f('users_person_id_fkey'), 'users', 'persons', ['person_id'], ['id']) + op.drop_constraint(None, 'user_stats', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('user_stats_user_id_fkey'), 'user_stats', 'users', ['user_id'], ['id']) + op.drop_constraint(None, 'user_badges', schema='data', type_='foreignkey') + op.drop_constraint(None, 'user_badges', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('user_badges_user_id_fkey'), 'user_badges', 'users', ['user_id'], ['id']) + op.create_foreign_key(op.f('user_badges_badge_id_fkey'), 'user_badges', 'badges', ['badge_id'], ['id']) + op.drop_constraint(None, 'social_accounts', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('social_accounts_user_id_fkey'), 'social_accounts', 'users', ['user_id'], ['id'], ondelete='CASCADE') + op.drop_constraint(None, 'service_specialties', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('service_specialties_parent_id_fkey'), 'service_specialties', 'service_specialties', ['parent_id'], ['id']) + op.drop_constraint(None, 'service_profiles', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('service_profiles_organization_id_fkey'), 'service_profiles', 'organizations', ['organization_id'], ['id']) + op.drop_constraint(None, 'service_expertises', schema='data', type_='foreignkey') + op.drop_constraint(None, 'service_expertises', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('service_expertises_service_id_fkey'), 'service_expertises', 'service_profiles', ['service_id'], ['id']) + op.create_foreign_key(op.f('service_expertises_expertise_id_fkey'), 'service_expertises', 'expertise_tags', ['expertise_id'], ['id']) + op.drop_constraint(None, 'security_audit_logs', schema='data', type_='foreignkey') + op.drop_constraint(None, 'security_audit_logs', schema='data', type_='foreignkey') + op.drop_constraint(None, 'security_audit_logs', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('security_audit_logs_confirmed_by_id_fkey'), 'security_audit_logs', 'users', ['confirmed_by_id'], ['id']) + op.create_foreign_key(op.f('security_audit_logs_actor_id_fkey'), 'security_audit_logs', 'users', ['actor_id'], ['id']) + op.create_foreign_key(op.f('security_audit_logs_target_id_fkey'), 'security_audit_logs', 'users', ['target_id'], ['id']) + op.drop_constraint(None, 'ratings', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('ratings_author_id_fkey'), 'ratings', 'users', ['author_id'], ['id']) + op.drop_constraint(None, 'points_ledger', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('points_ledger_user_id_fkey'), 'points_ledger', 'users', ['user_id'], ['id']) + op.drop_constraint(None, 'persons', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('persons_address_id_fkey'), 'persons', 'addresses', ['address_id'], ['id']) + op.drop_constraint(None, 'pending_actions', schema='data', type_='foreignkey') + op.drop_constraint(None, 'pending_actions', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('pending_actions_approver_id_fkey'), 'pending_actions', 'users', ['approver_id'], ['id']) + op.create_foreign_key(op.f('pending_actions_requester_id_fkey'), 'pending_actions', 'users', ['requester_id'], ['id']) + op.drop_constraint(None, 'organizations', schema='data', type_='foreignkey') + op.drop_constraint(None, 'organizations', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('organizations_address_id_fkey'), 'organizations', 'addresses', ['address_id'], ['id']) + op.create_foreign_key(op.f('organizations_owner_id_fkey'), 'organizations', 'users', ['owner_id'], ['id']) + op.alter_column('organizations', 'org_type', + existing_type=postgresql.ENUM('individual', 'service', 'service_provider', 'fleet_owner', 'club', 'business', name='orgtype', schema='data', inherit_schema=True), + type_=postgresql.ENUM('individual', 'service', 'service_provider', 'fleet_owner', 'club', 'business', name='orgtype'), + existing_nullable=True) + op.drop_constraint(None, 'organization_members', schema='data', type_='foreignkey') + op.drop_constraint(None, 'organization_members', schema='data', type_='foreignkey') + op.drop_constraint(None, 'organization_members', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('organization_members_person_id_fkey'), 'organization_members', 'persons', ['person_id'], ['id']) + op.create_foreign_key(op.f('organization_members_user_id_fkey'), 'organization_members', 'users', ['user_id'], ['id']) + op.create_foreign_key(op.f('organization_members_organization_id_fkey'), 'organization_members', 'organizations', ['organization_id'], ['id']) + op.alter_column('organization_members', 'role', + existing_type=postgresql.ENUM('OWNER', 'ADMIN', 'FLEET_MANAGER', 'DRIVER', 'MECHANIC', 'RECEPTIONIST', name='orguserrole', schema='data', inherit_schema=True), + type_=postgresql.ENUM('OWNER', 'ADMIN', 'FLEET_MANAGER', 'DRIVER', 'MECHANIC', 'RECEPTIONIST', name='orguserrole'), + existing_nullable=True) + op.drop_constraint(None, 'organization_financials', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('organization_financials_organization_id_fkey'), 'organization_financials', 'organizations', ['organization_id'], ['id']) + op.drop_constraint(None, 'org_subscriptions', schema='data', type_='foreignkey') + op.drop_constraint(None, 'org_subscriptions', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('org_subscriptions_tier_id_fkey'), 'org_subscriptions', 'subscription_tiers', ['tier_id'], ['id']) + op.create_foreign_key(op.f('org_subscriptions_org_id_fkey'), 'org_subscriptions', 'organizations', ['org_id'], ['id']) + op.drop_constraint(None, 'org_sales_assignments', schema='data', type_='foreignkey') + op.drop_constraint(None, 'org_sales_assignments', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('org_sales_assignments_agent_user_id_fkey'), 'org_sales_assignments', 'users', ['agent_user_id'], ['id']) + op.create_foreign_key(op.f('org_sales_assignments_organization_id_fkey'), 'org_sales_assignments', 'organizations', ['organization_id'], ['id']) + op.drop_constraint(None, 'operational_logs', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('operational_logs_user_id_fkey'), 'operational_logs', 'users', ['user_id'], ['id'], ondelete='SET NULL') + op.drop_constraint(None, 'geo_streets', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('geo_streets_postal_code_id_fkey'), 'geo_streets', 'geo_postal_codes', ['postal_code_id'], ['id']) + op.drop_constraint(None, 'financial_ledger', schema='data', type_='foreignkey') + op.drop_constraint(None, 'financial_ledger', schema='data', type_='foreignkey') + op.drop_constraint(None, 'financial_ledger', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('financial_ledger_user_id_fkey'), 'financial_ledger', 'users', ['user_id'], ['id']) + op.create_foreign_key(op.f('financial_ledger_person_id_fkey'), 'financial_ledger', 'persons', ['person_id'], ['id']) + op.create_foreign_key(op.f('financial_ledger_related_agent_id_fkey'), 'financial_ledger', 'users', ['related_agent_id'], ['id']) + op.drop_constraint(None, 'documents', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('documents_uploaded_by_fkey'), 'documents', 'users', ['uploaded_by'], ['id']) + op.drop_constraint(None, 'credit_logs', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('credit_logs_org_id_fkey'), 'credit_logs', 'organizations', ['org_id'], ['id']) + op.drop_constraint(None, 'branches', schema='data', type_='foreignkey') + op.drop_constraint(None, 'branches', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('branches_organization_id_fkey'), 'branches', 'organizations', ['organization_id'], ['id']) + op.create_foreign_key(op.f('branches_address_id_fkey'), 'branches', 'addresses', ['address_id'], ['id']) + op.drop_constraint(None, 'audit_logs', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('audit_logs_user_id_fkey'), 'audit_logs', 'users', ['user_id'], ['id']) + op.drop_constraint(None, 'assets', schema='data', type_='foreignkey') + op.drop_constraint(None, 'assets', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('assets_current_organization_id_fkey'), 'assets', 'organizations', ['current_organization_id'], ['id']) + op.create_foreign_key(op.f('assets_catalog_id_fkey'), 'assets', 'vehicle_catalog', ['catalog_id'], ['id']) + op.drop_constraint(None, 'asset_telemetry', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_telemetry_asset_id_fkey'), 'asset_telemetry', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'asset_reviews', schema='data', type_='foreignkey') + op.drop_constraint(None, 'asset_reviews', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_reviews_user_id_fkey'), 'asset_reviews', 'users', ['user_id'], ['id']) + op.create_foreign_key(op.f('asset_reviews_asset_id_fkey'), 'asset_reviews', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'asset_financials', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_financials_asset_id_fkey'), 'asset_financials', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'asset_events', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_events_asset_id_fkey'), 'asset_events', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'asset_costs', schema='data', type_='foreignkey') + op.drop_constraint(None, 'asset_costs', schema='data', type_='foreignkey') + op.drop_constraint(None, 'asset_costs', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_costs_asset_id_fkey'), 'asset_costs', 'assets', ['asset_id'], ['id']) + op.create_foreign_key(op.f('asset_costs_driver_id_fkey'), 'asset_costs', 'users', ['driver_id'], ['id']) + op.create_foreign_key(op.f('asset_costs_organization_id_fkey'), 'asset_costs', 'organizations', ['organization_id'], ['id']) + op.drop_constraint(None, 'asset_assignments', schema='data', type_='foreignkey') + op.drop_constraint(None, 'asset_assignments', schema='data', type_='foreignkey') + op.drop_constraint(None, 'asset_assignments', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_assignments_organization_id_fkey'), 'asset_assignments', 'organizations', ['organization_id'], ['id']) + op.create_foreign_key(op.f('asset_assignments_branch_id_fkey'), 'asset_assignments', 'branches', ['branch_id'], ['id']) + op.create_foreign_key(op.f('asset_assignments_asset_id_fkey'), 'asset_assignments', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'addresses', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('addresses_postal_code_id_fkey'), 'addresses', 'geo_postal_codes', ['postal_code_id'], ['id']) + op.drop_index(op.f('ix_data_vehicle_model_definitions_vehicle_type'), table_name='vehicle_model_definitions', schema='data') + op.drop_index(op.f('ix_data_vehicle_model_definitions_technical_code'), table_name='vehicle_model_definitions', schema='data') + op.drop_index(op.f('ix_data_vehicle_model_definitions_marketing_name'), table_name='vehicle_model_definitions', schema='data') + op.drop_index(op.f('ix_data_vehicle_model_definitions_make'), table_name='vehicle_model_definitions', schema='data') + op.drop_table('vehicle_model_definitions', schema='data') + # ### end Alembic commands ### diff --git a/backend/migrations/versions/8f09b4b22f14_v1_9_deep_asset_catalog_and_logistics.py b/backend/migrations/versions/8f09b4b22f14_v1_9_deep_asset_catalog_and_logistics.py new file mode 100644 index 0000000..78686ed --- /dev/null +++ b/backend/migrations/versions/8f09b4b22f14_v1_9_deep_asset_catalog_and_logistics.py @@ -0,0 +1,348 @@ +"""v1_9_deep_asset_catalog_and_logistics + +Revision ID: 8f09b4b22f14 +Revises: 495fe225e904 +Create Date: 2026-02-16 22:56:12.137340 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision: str = '8f09b4b22f14' +down_revision: Union[str, Sequence[str], None] = '495fe225e904' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('vehicle_types', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('code', sa.String(length=30), nullable=True), + sa.Column('name', sa.String(length=50), nullable=True), + sa.Column('icon', sa.String(length=50), nullable=True), + sa.Column('units', sa.JSON(), server_default=sa.text('\'{"power": "kW", "weight": "kg", "cargo": "m3"}\'::jsonb'), nullable=True), + sa.PrimaryKeyConstraint('id'), + schema='data' + ) + op.create_index(op.f('ix_data_vehicle_types_code'), 'vehicle_types', ['code'], unique=True, schema='data') + op.create_table('feature_definitions', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('vehicle_type_id', sa.Integer(), nullable=True), + sa.Column('category', sa.String(length=50), nullable=True), + sa.Column('name', sa.String(length=100), nullable=False), + sa.Column('data_type', sa.String(length=20), nullable=True), + sa.ForeignKeyConstraint(['vehicle_type_id'], ['data.vehicle_types.id'], ), + sa.PrimaryKeyConstraint('id'), + schema='data' + ) + op.create_table('model_feature_maps', + sa.Column('model_id', sa.Integer(), nullable=False), + sa.Column('feature_id', sa.Integer(), nullable=False), + sa.Column('availability', sa.String(length=20), nullable=True), + sa.Column('value', sa.String(length=100), nullable=True), + sa.ForeignKeyConstraint(['feature_id'], ['data.feature_definitions.id'], ), + sa.ForeignKeyConstraint(['model_id'], ['data.vehicle_model_definitions.id'], ), + sa.PrimaryKeyConstraint('model_id', 'feature_id'), + schema='data' + ) + op.drop_constraint(op.f('addresses_postal_code_id_fkey'), 'addresses', type_='foreignkey') + op.create_foreign_key(None, 'addresses', 'geo_postal_codes', ['postal_code_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_assignments_asset_id_fkey'), 'asset_assignments', type_='foreignkey') + op.drop_constraint(op.f('asset_assignments_organization_id_fkey'), 'asset_assignments', type_='foreignkey') + op.drop_constraint(op.f('asset_assignments_branch_id_fkey'), 'asset_assignments', type_='foreignkey') + op.create_foreign_key(None, 'asset_assignments', 'branches', ['branch_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'asset_assignments', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'asset_assignments', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_costs_asset_id_fkey'), 'asset_costs', type_='foreignkey') + op.drop_constraint(op.f('asset_costs_driver_id_fkey'), 'asset_costs', type_='foreignkey') + op.drop_constraint(op.f('asset_costs_organization_id_fkey'), 'asset_costs', type_='foreignkey') + op.create_foreign_key(None, 'asset_costs', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'asset_costs', 'users', ['driver_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'asset_costs', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_events_asset_id_fkey'), 'asset_events', type_='foreignkey') + op.create_foreign_key(None, 'asset_events', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_financials_asset_id_fkey'), 'asset_financials', type_='foreignkey') + op.create_foreign_key(None, 'asset_financials', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_reviews_asset_id_fkey'), 'asset_reviews', type_='foreignkey') + op.drop_constraint(op.f('asset_reviews_user_id_fkey'), 'asset_reviews', type_='foreignkey') + op.create_foreign_key(None, 'asset_reviews', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'asset_reviews', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_telemetry_asset_id_fkey'), 'asset_telemetry', type_='foreignkey') + op.create_foreign_key(None, 'asset_telemetry', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('assets_current_organization_id_fkey'), 'assets', type_='foreignkey') + op.drop_constraint(op.f('assets_catalog_id_fkey'), 'assets', type_='foreignkey') + op.create_foreign_key(None, 'assets', 'vehicle_catalog', ['catalog_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'assets', 'organizations', ['current_organization_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('audit_logs_user_id_fkey'), 'audit_logs', type_='foreignkey') + op.create_foreign_key(None, 'audit_logs', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('branches_organization_id_fkey'), 'branches', type_='foreignkey') + op.drop_constraint(op.f('branches_address_id_fkey'), 'branches', type_='foreignkey') + op.create_foreign_key(None, 'branches', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'branches', 'addresses', ['address_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('credit_logs_org_id_fkey'), 'credit_logs', type_='foreignkey') + op.create_foreign_key(None, 'credit_logs', 'organizations', ['org_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('documents_uploaded_by_fkey'), 'documents', type_='foreignkey') + op.create_foreign_key(None, 'documents', 'users', ['uploaded_by'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('financial_ledger_person_id_fkey'), 'financial_ledger', type_='foreignkey') + op.drop_constraint(op.f('financial_ledger_related_agent_id_fkey'), 'financial_ledger', type_='foreignkey') + op.drop_constraint(op.f('financial_ledger_user_id_fkey'), 'financial_ledger', type_='foreignkey') + op.create_foreign_key(None, 'financial_ledger', 'users', ['related_agent_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'financial_ledger', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'financial_ledger', 'persons', ['person_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('geo_streets_postal_code_id_fkey'), 'geo_streets', type_='foreignkey') + op.create_foreign_key(None, 'geo_streets', 'geo_postal_codes', ['postal_code_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('operational_logs_user_id_fkey'), 'operational_logs', type_='foreignkey') + op.create_foreign_key(None, 'operational_logs', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data', ondelete='SET NULL') + op.drop_constraint(op.f('org_sales_assignments_organization_id_fkey'), 'org_sales_assignments', type_='foreignkey') + op.drop_constraint(op.f('org_sales_assignments_agent_user_id_fkey'), 'org_sales_assignments', type_='foreignkey') + op.create_foreign_key(None, 'org_sales_assignments', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'org_sales_assignments', 'users', ['agent_user_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('org_subscriptions_org_id_fkey'), 'org_subscriptions', type_='foreignkey') + op.drop_constraint(op.f('org_subscriptions_tier_id_fkey'), 'org_subscriptions', type_='foreignkey') + op.create_foreign_key(None, 'org_subscriptions', 'organizations', ['org_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'org_subscriptions', 'subscription_tiers', ['tier_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('organization_financials_organization_id_fkey'), 'organization_financials', type_='foreignkey') + op.create_foreign_key(None, 'organization_financials', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.alter_column('organization_members', 'role', + existing_type=postgresql.ENUM('OWNER', 'ADMIN', 'FLEET_MANAGER', 'DRIVER', 'MECHANIC', 'RECEPTIONIST', name='orguserrole'), + type_=postgresql.ENUM('OWNER', 'ADMIN', 'FLEET_MANAGER', 'DRIVER', 'MECHANIC', 'RECEPTIONIST', name='orguserrole', schema='data', inherit_schema=True), + existing_nullable=True) + op.drop_constraint(op.f('organization_members_user_id_fkey'), 'organization_members', type_='foreignkey') + op.drop_constraint(op.f('organization_members_organization_id_fkey'), 'organization_members', type_='foreignkey') + op.drop_constraint(op.f('organization_members_person_id_fkey'), 'organization_members', type_='foreignkey') + op.create_foreign_key(None, 'organization_members', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'organization_members', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'organization_members', 'persons', ['person_id'], ['id'], source_schema='data', referent_schema='data') + op.alter_column('organizations', 'org_type', + existing_type=postgresql.ENUM('individual', 'service', 'service_provider', 'fleet_owner', 'club', 'business', name='orgtype'), + type_=postgresql.ENUM('individual', 'service', 'service_provider', 'fleet_owner', 'club', 'business', name='orgtype', schema='data', inherit_schema=True), + existing_nullable=True) + op.drop_constraint(op.f('organizations_owner_id_fkey'), 'organizations', type_='foreignkey') + op.drop_constraint(op.f('organizations_address_id_fkey'), 'organizations', type_='foreignkey') + op.create_foreign_key(None, 'organizations', 'addresses', ['address_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'organizations', 'users', ['owner_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('pending_actions_requester_id_fkey'), 'pending_actions', type_='foreignkey') + op.drop_constraint(op.f('pending_actions_approver_id_fkey'), 'pending_actions', type_='foreignkey') + op.create_foreign_key(None, 'pending_actions', 'users', ['approver_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'pending_actions', 'users', ['requester_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('persons_address_id_fkey'), 'persons', type_='foreignkey') + op.create_foreign_key(None, 'persons', 'addresses', ['address_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('points_ledger_user_id_fkey'), 'points_ledger', type_='foreignkey') + op.create_foreign_key(None, 'points_ledger', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('ratings_author_id_fkey'), 'ratings', type_='foreignkey') + op.create_foreign_key(None, 'ratings', 'users', ['author_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('security_audit_logs_confirmed_by_id_fkey'), 'security_audit_logs', type_='foreignkey') + op.drop_constraint(op.f('security_audit_logs_actor_id_fkey'), 'security_audit_logs', type_='foreignkey') + op.drop_constraint(op.f('security_audit_logs_target_id_fkey'), 'security_audit_logs', type_='foreignkey') + op.create_foreign_key(None, 'security_audit_logs', 'users', ['confirmed_by_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'security_audit_logs', 'users', ['actor_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'security_audit_logs', 'users', ['target_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('service_expertises_service_id_fkey'), 'service_expertises', type_='foreignkey') + op.drop_constraint(op.f('service_expertises_expertise_id_fkey'), 'service_expertises', type_='foreignkey') + op.create_foreign_key(None, 'service_expertises', 'service_profiles', ['service_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'service_expertises', 'expertise_tags', ['expertise_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('service_profiles_organization_id_fkey'), 'service_profiles', type_='foreignkey') + op.create_foreign_key(None, 'service_profiles', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('service_specialties_parent_id_fkey'), 'service_specialties', type_='foreignkey') + op.create_foreign_key(None, 'service_specialties', 'service_specialties', ['parent_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('social_accounts_user_id_fkey'), 'social_accounts', type_='foreignkey') + op.create_foreign_key(None, 'social_accounts', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data', ondelete='CASCADE') + op.drop_constraint(op.f('user_badges_user_id_fkey'), 'user_badges', type_='foreignkey') + op.drop_constraint(op.f('user_badges_badge_id_fkey'), 'user_badges', type_='foreignkey') + op.create_foreign_key(None, 'user_badges', 'badges', ['badge_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'user_badges', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('user_stats_user_id_fkey'), 'user_stats', type_='foreignkey') + op.create_foreign_key(None, 'user_stats', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('users_referred_by_id_fkey'), 'users', type_='foreignkey') + op.drop_constraint(op.f('users_current_sales_agent_id_fkey'), 'users', type_='foreignkey') + op.drop_constraint(op.f('users_person_id_fkey'), 'users', type_='foreignkey') + op.create_foreign_key(None, 'users', 'users', ['referred_by_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'users', 'users', ['current_sales_agent_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'users', 'persons', ['person_id'], ['id'], source_schema='data', referent_schema='data') + op.add_column('vehicle_catalog', sa.Column('master_definition_id', sa.Integer(), nullable=True)) + op.create_foreign_key(None, 'vehicle_catalog', 'vehicle_model_definitions', ['master_definition_id'], ['id'], source_schema='data', referent_schema='data') + op.add_column('vehicle_model_definitions', sa.Column('vehicle_type_id', sa.Integer(), nullable=True)) + op.add_column('vehicle_model_definitions', sa.Column('engine_capacity', sa.Integer(), nullable=True)) + op.add_column('vehicle_model_definitions', sa.Column('power_kw', sa.Integer(), nullable=True)) + op.add_column('vehicle_model_definitions', sa.Column('max_weight_kg', sa.Integer(), nullable=True)) + op.add_column('vehicle_model_definitions', sa.Column('axle_count', sa.Integer(), nullable=True)) + op.add_column('vehicle_model_definitions', sa.Column('payload_capacity_kg', sa.Integer(), nullable=True)) + op.add_column('vehicle_model_definitions', sa.Column('cargo_volume_m3', sa.Numeric(precision=10, scale=2), nullable=True)) + op.add_column('vehicle_model_definitions', sa.Column('cargo_length_mm', sa.Integer(), nullable=True)) + op.add_column('vehicle_model_definitions', sa.Column('cargo_width_mm', sa.Integer(), nullable=True)) + op.add_column('vehicle_model_definitions', sa.Column('cargo_height_mm', sa.Integer(), nullable=True)) + op.add_column('vehicle_model_definitions', sa.Column('features_json', sa.JSON(), server_default=sa.text("'{}'::jsonb"), nullable=True)) + op.drop_constraint(op.f('uix_make_tech_code'), 'vehicle_model_definitions', type_='unique') + op.create_index(op.f('ix_data_vehicle_model_definitions_engine_capacity'), 'vehicle_model_definitions', ['engine_capacity'], unique=False, schema='data') + op.create_index(op.f('ix_data_vehicle_model_definitions_max_weight_kg'), 'vehicle_model_definitions', ['max_weight_kg'], unique=False, schema='data') + op.create_index(op.f('ix_data_vehicle_model_definitions_power_kw'), 'vehicle_model_definitions', ['power_kw'], unique=False, schema='data') + op.create_unique_constraint('uix_make_tech_type', 'vehicle_model_definitions', ['make', 'technical_code', 'vehicle_type'], schema='data') + op.create_foreign_key(None, 'vehicle_model_definitions', 'vehicle_types', ['vehicle_type_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_column('vehicle_model_definitions', 'features') + op.drop_constraint(op.f('vehicle_ownerships_vehicle_id_fkey'), 'vehicle_ownerships', type_='foreignkey') + op.drop_constraint(op.f('vehicle_ownerships_user_id_fkey'), 'vehicle_ownerships', type_='foreignkey') + op.create_foreign_key(None, 'vehicle_ownerships', 'assets', ['vehicle_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'vehicle_ownerships', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('verification_tokens_user_id_fkey'), 'verification_tokens', type_='foreignkey') + op.create_foreign_key(None, 'verification_tokens', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data', ondelete='CASCADE') + op.drop_constraint(op.f('wallets_user_id_fkey'), 'wallets', type_='foreignkey') + op.create_foreign_key(None, 'wallets', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'wallets', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('wallets_user_id_fkey'), 'wallets', 'users', ['user_id'], ['id']) + op.drop_constraint(None, 'verification_tokens', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('verification_tokens_user_id_fkey'), 'verification_tokens', 'users', ['user_id'], ['id'], ondelete='CASCADE') + op.drop_constraint(None, 'vehicle_ownerships', schema='data', type_='foreignkey') + op.drop_constraint(None, 'vehicle_ownerships', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('vehicle_ownerships_user_id_fkey'), 'vehicle_ownerships', 'users', ['user_id'], ['id']) + op.create_foreign_key(op.f('vehicle_ownerships_vehicle_id_fkey'), 'vehicle_ownerships', 'assets', ['vehicle_id'], ['id']) + op.add_column('vehicle_model_definitions', sa.Column('features', postgresql.JSON(astext_type=sa.Text()), server_default=sa.text("'{}'::jsonb"), autoincrement=False, nullable=True)) + op.drop_constraint(None, 'vehicle_model_definitions', schema='data', type_='foreignkey') + op.drop_constraint('uix_make_tech_type', 'vehicle_model_definitions', schema='data', type_='unique') + op.drop_index(op.f('ix_data_vehicle_model_definitions_power_kw'), table_name='vehicle_model_definitions', schema='data') + op.drop_index(op.f('ix_data_vehicle_model_definitions_max_weight_kg'), table_name='vehicle_model_definitions', schema='data') + op.drop_index(op.f('ix_data_vehicle_model_definitions_engine_capacity'), table_name='vehicle_model_definitions', schema='data') + op.create_unique_constraint(op.f('uix_make_tech_code'), 'vehicle_model_definitions', ['make', 'technical_code'], postgresql_nulls_not_distinct=False) + op.drop_column('vehicle_model_definitions', 'features_json') + op.drop_column('vehicle_model_definitions', 'cargo_height_mm') + op.drop_column('vehicle_model_definitions', 'cargo_width_mm') + op.drop_column('vehicle_model_definitions', 'cargo_length_mm') + op.drop_column('vehicle_model_definitions', 'cargo_volume_m3') + op.drop_column('vehicle_model_definitions', 'payload_capacity_kg') + op.drop_column('vehicle_model_definitions', 'axle_count') + op.drop_column('vehicle_model_definitions', 'max_weight_kg') + op.drop_column('vehicle_model_definitions', 'power_kw') + op.drop_column('vehicle_model_definitions', 'engine_capacity') + op.drop_column('vehicle_model_definitions', 'vehicle_type_id') + op.drop_constraint(None, 'vehicle_catalog', schema='data', type_='foreignkey') + op.drop_column('vehicle_catalog', 'master_definition_id') + op.drop_constraint(None, 'users', schema='data', type_='foreignkey') + op.drop_constraint(None, 'users', schema='data', type_='foreignkey') + op.drop_constraint(None, 'users', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('users_person_id_fkey'), 'users', 'persons', ['person_id'], ['id']) + op.create_foreign_key(op.f('users_current_sales_agent_id_fkey'), 'users', 'users', ['current_sales_agent_id'], ['id']) + op.create_foreign_key(op.f('users_referred_by_id_fkey'), 'users', 'users', ['referred_by_id'], ['id']) + op.drop_constraint(None, 'user_stats', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('user_stats_user_id_fkey'), 'user_stats', 'users', ['user_id'], ['id']) + op.drop_constraint(None, 'user_badges', schema='data', type_='foreignkey') + op.drop_constraint(None, 'user_badges', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('user_badges_badge_id_fkey'), 'user_badges', 'badges', ['badge_id'], ['id']) + op.create_foreign_key(op.f('user_badges_user_id_fkey'), 'user_badges', 'users', ['user_id'], ['id']) + op.drop_constraint(None, 'social_accounts', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('social_accounts_user_id_fkey'), 'social_accounts', 'users', ['user_id'], ['id'], ondelete='CASCADE') + op.drop_constraint(None, 'service_specialties', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('service_specialties_parent_id_fkey'), 'service_specialties', 'service_specialties', ['parent_id'], ['id']) + op.drop_constraint(None, 'service_profiles', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('service_profiles_organization_id_fkey'), 'service_profiles', 'organizations', ['organization_id'], ['id']) + op.drop_constraint(None, 'service_expertises', schema='data', type_='foreignkey') + op.drop_constraint(None, 'service_expertises', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('service_expertises_expertise_id_fkey'), 'service_expertises', 'expertise_tags', ['expertise_id'], ['id']) + op.create_foreign_key(op.f('service_expertises_service_id_fkey'), 'service_expertises', 'service_profiles', ['service_id'], ['id']) + op.drop_constraint(None, 'security_audit_logs', schema='data', type_='foreignkey') + op.drop_constraint(None, 'security_audit_logs', schema='data', type_='foreignkey') + op.drop_constraint(None, 'security_audit_logs', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('security_audit_logs_target_id_fkey'), 'security_audit_logs', 'users', ['target_id'], ['id']) + op.create_foreign_key(op.f('security_audit_logs_actor_id_fkey'), 'security_audit_logs', 'users', ['actor_id'], ['id']) + op.create_foreign_key(op.f('security_audit_logs_confirmed_by_id_fkey'), 'security_audit_logs', 'users', ['confirmed_by_id'], ['id']) + op.drop_constraint(None, 'ratings', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('ratings_author_id_fkey'), 'ratings', 'users', ['author_id'], ['id']) + op.drop_constraint(None, 'points_ledger', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('points_ledger_user_id_fkey'), 'points_ledger', 'users', ['user_id'], ['id']) + op.drop_constraint(None, 'persons', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('persons_address_id_fkey'), 'persons', 'addresses', ['address_id'], ['id']) + op.drop_constraint(None, 'pending_actions', schema='data', type_='foreignkey') + op.drop_constraint(None, 'pending_actions', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('pending_actions_approver_id_fkey'), 'pending_actions', 'users', ['approver_id'], ['id']) + op.create_foreign_key(op.f('pending_actions_requester_id_fkey'), 'pending_actions', 'users', ['requester_id'], ['id']) + op.drop_constraint(None, 'organizations', schema='data', type_='foreignkey') + op.drop_constraint(None, 'organizations', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('organizations_address_id_fkey'), 'organizations', 'addresses', ['address_id'], ['id']) + op.create_foreign_key(op.f('organizations_owner_id_fkey'), 'organizations', 'users', ['owner_id'], ['id']) + op.alter_column('organizations', 'org_type', + existing_type=postgresql.ENUM('individual', 'service', 'service_provider', 'fleet_owner', 'club', 'business', name='orgtype', schema='data', inherit_schema=True), + type_=postgresql.ENUM('individual', 'service', 'service_provider', 'fleet_owner', 'club', 'business', name='orgtype'), + existing_nullable=True) + op.drop_constraint(None, 'organization_members', schema='data', type_='foreignkey') + op.drop_constraint(None, 'organization_members', schema='data', type_='foreignkey') + op.drop_constraint(None, 'organization_members', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('organization_members_person_id_fkey'), 'organization_members', 'persons', ['person_id'], ['id']) + op.create_foreign_key(op.f('organization_members_organization_id_fkey'), 'organization_members', 'organizations', ['organization_id'], ['id']) + op.create_foreign_key(op.f('organization_members_user_id_fkey'), 'organization_members', 'users', ['user_id'], ['id']) + op.alter_column('organization_members', 'role', + existing_type=postgresql.ENUM('OWNER', 'ADMIN', 'FLEET_MANAGER', 'DRIVER', 'MECHANIC', 'RECEPTIONIST', name='orguserrole', schema='data', inherit_schema=True), + type_=postgresql.ENUM('OWNER', 'ADMIN', 'FLEET_MANAGER', 'DRIVER', 'MECHANIC', 'RECEPTIONIST', name='orguserrole'), + existing_nullable=True) + op.drop_constraint(None, 'organization_financials', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('organization_financials_organization_id_fkey'), 'organization_financials', 'organizations', ['organization_id'], ['id']) + op.drop_constraint(None, 'org_subscriptions', schema='data', type_='foreignkey') + op.drop_constraint(None, 'org_subscriptions', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('org_subscriptions_tier_id_fkey'), 'org_subscriptions', 'subscription_tiers', ['tier_id'], ['id']) + op.create_foreign_key(op.f('org_subscriptions_org_id_fkey'), 'org_subscriptions', 'organizations', ['org_id'], ['id']) + op.drop_constraint(None, 'org_sales_assignments', schema='data', type_='foreignkey') + op.drop_constraint(None, 'org_sales_assignments', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('org_sales_assignments_agent_user_id_fkey'), 'org_sales_assignments', 'users', ['agent_user_id'], ['id']) + op.create_foreign_key(op.f('org_sales_assignments_organization_id_fkey'), 'org_sales_assignments', 'organizations', ['organization_id'], ['id']) + op.drop_constraint(None, 'operational_logs', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('operational_logs_user_id_fkey'), 'operational_logs', 'users', ['user_id'], ['id'], ondelete='SET NULL') + op.drop_constraint(None, 'geo_streets', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('geo_streets_postal_code_id_fkey'), 'geo_streets', 'geo_postal_codes', ['postal_code_id'], ['id']) + op.drop_constraint(None, 'financial_ledger', schema='data', type_='foreignkey') + op.drop_constraint(None, 'financial_ledger', schema='data', type_='foreignkey') + op.drop_constraint(None, 'financial_ledger', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('financial_ledger_user_id_fkey'), 'financial_ledger', 'users', ['user_id'], ['id']) + op.create_foreign_key(op.f('financial_ledger_related_agent_id_fkey'), 'financial_ledger', 'users', ['related_agent_id'], ['id']) + op.create_foreign_key(op.f('financial_ledger_person_id_fkey'), 'financial_ledger', 'persons', ['person_id'], ['id']) + op.drop_constraint(None, 'documents', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('documents_uploaded_by_fkey'), 'documents', 'users', ['uploaded_by'], ['id']) + op.drop_constraint(None, 'credit_logs', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('credit_logs_org_id_fkey'), 'credit_logs', 'organizations', ['org_id'], ['id']) + op.drop_constraint(None, 'branches', schema='data', type_='foreignkey') + op.drop_constraint(None, 'branches', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('branches_address_id_fkey'), 'branches', 'addresses', ['address_id'], ['id']) + op.create_foreign_key(op.f('branches_organization_id_fkey'), 'branches', 'organizations', ['organization_id'], ['id']) + op.drop_constraint(None, 'audit_logs', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('audit_logs_user_id_fkey'), 'audit_logs', 'users', ['user_id'], ['id']) + op.drop_constraint(None, 'assets', schema='data', type_='foreignkey') + op.drop_constraint(None, 'assets', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('assets_catalog_id_fkey'), 'assets', 'vehicle_catalog', ['catalog_id'], ['id']) + op.create_foreign_key(op.f('assets_current_organization_id_fkey'), 'assets', 'organizations', ['current_organization_id'], ['id']) + op.drop_constraint(None, 'asset_telemetry', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_telemetry_asset_id_fkey'), 'asset_telemetry', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'asset_reviews', schema='data', type_='foreignkey') + op.drop_constraint(None, 'asset_reviews', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_reviews_user_id_fkey'), 'asset_reviews', 'users', ['user_id'], ['id']) + op.create_foreign_key(op.f('asset_reviews_asset_id_fkey'), 'asset_reviews', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'asset_financials', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_financials_asset_id_fkey'), 'asset_financials', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'asset_events', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_events_asset_id_fkey'), 'asset_events', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'asset_costs', schema='data', type_='foreignkey') + op.drop_constraint(None, 'asset_costs', schema='data', type_='foreignkey') + op.drop_constraint(None, 'asset_costs', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_costs_organization_id_fkey'), 'asset_costs', 'organizations', ['organization_id'], ['id']) + op.create_foreign_key(op.f('asset_costs_driver_id_fkey'), 'asset_costs', 'users', ['driver_id'], ['id']) + op.create_foreign_key(op.f('asset_costs_asset_id_fkey'), 'asset_costs', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'asset_assignments', schema='data', type_='foreignkey') + op.drop_constraint(None, 'asset_assignments', schema='data', type_='foreignkey') + op.drop_constraint(None, 'asset_assignments', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_assignments_branch_id_fkey'), 'asset_assignments', 'branches', ['branch_id'], ['id']) + op.create_foreign_key(op.f('asset_assignments_organization_id_fkey'), 'asset_assignments', 'organizations', ['organization_id'], ['id']) + op.create_foreign_key(op.f('asset_assignments_asset_id_fkey'), 'asset_assignments', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'addresses', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('addresses_postal_code_id_fkey'), 'addresses', 'geo_postal_codes', ['postal_code_id'], ['id']) + op.drop_table('model_feature_maps', schema='data') + op.drop_table('feature_definitions', schema='data') + op.drop_index(op.f('ix_data_vehicle_types_code'), table_name='vehicle_types', schema='data') + op.drop_table('vehicle_types', schema='data') + # ### end Alembic commands ### diff --git a/backend/migrations/versions/f30c0005c446_v1_9_final_mdm_and_process_logs.py b/backend/migrations/versions/f30c0005c446_v1_9_final_mdm_and_process_logs.py new file mode 100644 index 0000000..d7896e4 --- /dev/null +++ b/backend/migrations/versions/f30c0005c446_v1_9_final_mdm_and_process_logs.py @@ -0,0 +1,309 @@ +"""v1_9_final_mdm_and_process_logs + +Revision ID: f30c0005c446 +Revises: 8f09b4b22f14 +Create Date: 2026-02-17 00:04:12.575332 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision: str = 'f30c0005c446' +down_revision: Union[str, Sequence[str], None] = '8f09b4b22f14' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('process_logs', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('process_name', sa.String(length=100), nullable=True), + sa.Column('start_time', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True), + sa.Column('end_time', sa.DateTime(timezone=True), nullable=True), + sa.Column('items_processed', sa.Integer(), nullable=True), + sa.Column('items_failed', sa.Integer(), nullable=True), + sa.Column('details', sa.JSON(), server_default=sa.text("'{}'::jsonb"), nullable=True), + sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True), + sa.PrimaryKeyConstraint('id'), + schema='data' + ) + op.create_index(op.f('ix_data_process_logs_process_name'), 'process_logs', ['process_name'], unique=False, schema='data') + op.drop_constraint(op.f('addresses_postal_code_id_fkey'), 'addresses', type_='foreignkey') + op.create_foreign_key(None, 'addresses', 'geo_postal_codes', ['postal_code_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_assignments_asset_id_fkey'), 'asset_assignments', type_='foreignkey') + op.drop_constraint(op.f('asset_assignments_organization_id_fkey'), 'asset_assignments', type_='foreignkey') + op.drop_constraint(op.f('asset_assignments_branch_id_fkey'), 'asset_assignments', type_='foreignkey') + op.create_foreign_key(None, 'asset_assignments', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'asset_assignments', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'asset_assignments', 'branches', ['branch_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_costs_driver_id_fkey'), 'asset_costs', type_='foreignkey') + op.drop_constraint(op.f('asset_costs_asset_id_fkey'), 'asset_costs', type_='foreignkey') + op.drop_constraint(op.f('asset_costs_organization_id_fkey'), 'asset_costs', type_='foreignkey') + op.create_foreign_key(None, 'asset_costs', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'asset_costs', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'asset_costs', 'users', ['driver_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_events_asset_id_fkey'), 'asset_events', type_='foreignkey') + op.create_foreign_key(None, 'asset_events', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_financials_asset_id_fkey'), 'asset_financials', type_='foreignkey') + op.create_foreign_key(None, 'asset_financials', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_reviews_asset_id_fkey'), 'asset_reviews', type_='foreignkey') + op.drop_constraint(op.f('asset_reviews_user_id_fkey'), 'asset_reviews', type_='foreignkey') + op.create_foreign_key(None, 'asset_reviews', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'asset_reviews', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('asset_telemetry_asset_id_fkey'), 'asset_telemetry', type_='foreignkey') + op.create_foreign_key(None, 'asset_telemetry', 'assets', ['asset_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('assets_current_organization_id_fkey'), 'assets', type_='foreignkey') + op.drop_constraint(op.f('assets_catalog_id_fkey'), 'assets', type_='foreignkey') + op.create_foreign_key(None, 'assets', 'vehicle_catalog', ['catalog_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'assets', 'organizations', ['current_organization_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('audit_logs_user_id_fkey'), 'audit_logs', type_='foreignkey') + op.create_foreign_key(None, 'audit_logs', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('branches_organization_id_fkey'), 'branches', type_='foreignkey') + op.drop_constraint(op.f('branches_address_id_fkey'), 'branches', type_='foreignkey') + op.create_foreign_key(None, 'branches', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'branches', 'addresses', ['address_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('credit_logs_org_id_fkey'), 'credit_logs', type_='foreignkey') + op.create_foreign_key(None, 'credit_logs', 'organizations', ['org_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('documents_uploaded_by_fkey'), 'documents', type_='foreignkey') + op.create_foreign_key(None, 'documents', 'users', ['uploaded_by'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('feature_definitions_vehicle_type_id_fkey'), 'feature_definitions', type_='foreignkey') + op.create_foreign_key(None, 'feature_definitions', 'vehicle_types', ['vehicle_type_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('financial_ledger_person_id_fkey'), 'financial_ledger', type_='foreignkey') + op.drop_constraint(op.f('financial_ledger_user_id_fkey'), 'financial_ledger', type_='foreignkey') + op.drop_constraint(op.f('financial_ledger_related_agent_id_fkey'), 'financial_ledger', type_='foreignkey') + op.create_foreign_key(None, 'financial_ledger', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'financial_ledger', 'persons', ['person_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'financial_ledger', 'users', ['related_agent_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('geo_streets_postal_code_id_fkey'), 'geo_streets', type_='foreignkey') + op.create_foreign_key(None, 'geo_streets', 'geo_postal_codes', ['postal_code_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('model_feature_maps_model_id_fkey'), 'model_feature_maps', type_='foreignkey') + op.drop_constraint(op.f('model_feature_maps_feature_id_fkey'), 'model_feature_maps', type_='foreignkey') + op.create_foreign_key(None, 'model_feature_maps', 'feature_definitions', ['feature_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'model_feature_maps', 'vehicle_model_definitions', ['model_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('operational_logs_user_id_fkey'), 'operational_logs', type_='foreignkey') + op.create_foreign_key(None, 'operational_logs', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data', ondelete='SET NULL') + op.drop_constraint(op.f('org_sales_assignments_organization_id_fkey'), 'org_sales_assignments', type_='foreignkey') + op.drop_constraint(op.f('org_sales_assignments_agent_user_id_fkey'), 'org_sales_assignments', type_='foreignkey') + op.create_foreign_key(None, 'org_sales_assignments', 'users', ['agent_user_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'org_sales_assignments', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('org_subscriptions_tier_id_fkey'), 'org_subscriptions', type_='foreignkey') + op.drop_constraint(op.f('org_subscriptions_org_id_fkey'), 'org_subscriptions', type_='foreignkey') + op.create_foreign_key(None, 'org_subscriptions', 'organizations', ['org_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'org_subscriptions', 'subscription_tiers', ['tier_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('organization_financials_organization_id_fkey'), 'organization_financials', type_='foreignkey') + op.create_foreign_key(None, 'organization_financials', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.alter_column('organization_members', 'role', + existing_type=postgresql.ENUM('OWNER', 'ADMIN', 'FLEET_MANAGER', 'DRIVER', 'MECHANIC', 'RECEPTIONIST', name='orguserrole'), + type_=postgresql.ENUM('OWNER', 'ADMIN', 'FLEET_MANAGER', 'DRIVER', 'MECHANIC', 'RECEPTIONIST', name='orguserrole', schema='data', inherit_schema=True), + existing_nullable=True) + op.drop_constraint(op.f('organization_members_user_id_fkey'), 'organization_members', type_='foreignkey') + op.drop_constraint(op.f('organization_members_organization_id_fkey'), 'organization_members', type_='foreignkey') + op.drop_constraint(op.f('organization_members_person_id_fkey'), 'organization_members', type_='foreignkey') + op.create_foreign_key(None, 'organization_members', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'organization_members', 'persons', ['person_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'organization_members', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.alter_column('organizations', 'org_type', + existing_type=postgresql.ENUM('individual', 'service', 'service_provider', 'fleet_owner', 'club', 'business', name='orgtype'), + type_=postgresql.ENUM('individual', 'service', 'service_provider', 'fleet_owner', 'club', 'business', name='orgtype', schema='data', inherit_schema=True), + existing_nullable=True) + op.drop_constraint(op.f('organizations_owner_id_fkey'), 'organizations', type_='foreignkey') + op.drop_constraint(op.f('organizations_address_id_fkey'), 'organizations', type_='foreignkey') + op.create_foreign_key(None, 'organizations', 'users', ['owner_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'organizations', 'addresses', ['address_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('pending_actions_requester_id_fkey'), 'pending_actions', type_='foreignkey') + op.drop_constraint(op.f('pending_actions_approver_id_fkey'), 'pending_actions', type_='foreignkey') + op.create_foreign_key(None, 'pending_actions', 'users', ['approver_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'pending_actions', 'users', ['requester_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('persons_address_id_fkey'), 'persons', type_='foreignkey') + op.create_foreign_key(None, 'persons', 'addresses', ['address_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('points_ledger_user_id_fkey'), 'points_ledger', type_='foreignkey') + op.create_foreign_key(None, 'points_ledger', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('ratings_author_id_fkey'), 'ratings', type_='foreignkey') + op.create_foreign_key(None, 'ratings', 'users', ['author_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('security_audit_logs_target_id_fkey'), 'security_audit_logs', type_='foreignkey') + op.drop_constraint(op.f('security_audit_logs_actor_id_fkey'), 'security_audit_logs', type_='foreignkey') + op.drop_constraint(op.f('security_audit_logs_confirmed_by_id_fkey'), 'security_audit_logs', type_='foreignkey') + op.create_foreign_key(None, 'security_audit_logs', 'users', ['confirmed_by_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'security_audit_logs', 'users', ['target_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'security_audit_logs', 'users', ['actor_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('service_expertises_service_id_fkey'), 'service_expertises', type_='foreignkey') + op.drop_constraint(op.f('service_expertises_expertise_id_fkey'), 'service_expertises', type_='foreignkey') + op.create_foreign_key(None, 'service_expertises', 'expertise_tags', ['expertise_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'service_expertises', 'service_profiles', ['service_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('service_profiles_organization_id_fkey'), 'service_profiles', type_='foreignkey') + op.create_foreign_key(None, 'service_profiles', 'organizations', ['organization_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('service_specialties_parent_id_fkey'), 'service_specialties', type_='foreignkey') + op.create_foreign_key(None, 'service_specialties', 'service_specialties', ['parent_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('social_accounts_user_id_fkey'), 'social_accounts', type_='foreignkey') + op.create_foreign_key(None, 'social_accounts', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data', ondelete='CASCADE') + op.drop_constraint(op.f('user_badges_badge_id_fkey'), 'user_badges', type_='foreignkey') + op.drop_constraint(op.f('user_badges_user_id_fkey'), 'user_badges', type_='foreignkey') + op.create_foreign_key(None, 'user_badges', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'user_badges', 'badges', ['badge_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('user_stats_user_id_fkey'), 'user_stats', type_='foreignkey') + op.create_foreign_key(None, 'user_stats', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('users_referred_by_id_fkey'), 'users', type_='foreignkey') + op.drop_constraint(op.f('users_person_id_fkey'), 'users', type_='foreignkey') + op.drop_constraint(op.f('users_current_sales_agent_id_fkey'), 'users', type_='foreignkey') + op.create_foreign_key(None, 'users', 'users', ['referred_by_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'users', 'users', ['current_sales_agent_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'users', 'persons', ['person_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('vehicle_catalog_master_definition_id_fkey'), 'vehicle_catalog', type_='foreignkey') + op.create_foreign_key(None, 'vehicle_catalog', 'vehicle_model_definitions', ['master_definition_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('vehicle_model_definitions_vehicle_type_id_fkey'), 'vehicle_model_definitions', type_='foreignkey') + op.create_foreign_key(None, 'vehicle_model_definitions', 'vehicle_types', ['vehicle_type_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('vehicle_ownerships_user_id_fkey'), 'vehicle_ownerships', type_='foreignkey') + op.drop_constraint(op.f('vehicle_ownerships_vehicle_id_fkey'), 'vehicle_ownerships', type_='foreignkey') + op.create_foreign_key(None, 'vehicle_ownerships', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + op.create_foreign_key(None, 'vehicle_ownerships', 'assets', ['vehicle_id'], ['id'], source_schema='data', referent_schema='data') + op.drop_constraint(op.f('verification_tokens_user_id_fkey'), 'verification_tokens', type_='foreignkey') + op.create_foreign_key(None, 'verification_tokens', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data', ondelete='CASCADE') + op.drop_constraint(op.f('wallets_user_id_fkey'), 'wallets', type_='foreignkey') + op.create_foreign_key(None, 'wallets', 'users', ['user_id'], ['id'], source_schema='data', referent_schema='data') + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'wallets', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('wallets_user_id_fkey'), 'wallets', 'users', ['user_id'], ['id']) + op.drop_constraint(None, 'verification_tokens', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('verification_tokens_user_id_fkey'), 'verification_tokens', 'users', ['user_id'], ['id'], ondelete='CASCADE') + op.drop_constraint(None, 'vehicle_ownerships', schema='data', type_='foreignkey') + op.drop_constraint(None, 'vehicle_ownerships', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('vehicle_ownerships_vehicle_id_fkey'), 'vehicle_ownerships', 'assets', ['vehicle_id'], ['id']) + op.create_foreign_key(op.f('vehicle_ownerships_user_id_fkey'), 'vehicle_ownerships', 'users', ['user_id'], ['id']) + op.drop_constraint(None, 'vehicle_model_definitions', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('vehicle_model_definitions_vehicle_type_id_fkey'), 'vehicle_model_definitions', 'vehicle_types', ['vehicle_type_id'], ['id']) + op.drop_constraint(None, 'vehicle_catalog', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('vehicle_catalog_master_definition_id_fkey'), 'vehicle_catalog', 'vehicle_model_definitions', ['master_definition_id'], ['id']) + op.drop_constraint(None, 'users', schema='data', type_='foreignkey') + op.drop_constraint(None, 'users', schema='data', type_='foreignkey') + op.drop_constraint(None, 'users', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('users_current_sales_agent_id_fkey'), 'users', 'users', ['current_sales_agent_id'], ['id']) + op.create_foreign_key(op.f('users_person_id_fkey'), 'users', 'persons', ['person_id'], ['id']) + op.create_foreign_key(op.f('users_referred_by_id_fkey'), 'users', 'users', ['referred_by_id'], ['id']) + op.drop_constraint(None, 'user_stats', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('user_stats_user_id_fkey'), 'user_stats', 'users', ['user_id'], ['id']) + op.drop_constraint(None, 'user_badges', schema='data', type_='foreignkey') + op.drop_constraint(None, 'user_badges', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('user_badges_user_id_fkey'), 'user_badges', 'users', ['user_id'], ['id']) + op.create_foreign_key(op.f('user_badges_badge_id_fkey'), 'user_badges', 'badges', ['badge_id'], ['id']) + op.drop_constraint(None, 'social_accounts', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('social_accounts_user_id_fkey'), 'social_accounts', 'users', ['user_id'], ['id'], ondelete='CASCADE') + op.drop_constraint(None, 'service_specialties', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('service_specialties_parent_id_fkey'), 'service_specialties', 'service_specialties', ['parent_id'], ['id']) + op.drop_constraint(None, 'service_profiles', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('service_profiles_organization_id_fkey'), 'service_profiles', 'organizations', ['organization_id'], ['id']) + op.drop_constraint(None, 'service_expertises', schema='data', type_='foreignkey') + op.drop_constraint(None, 'service_expertises', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('service_expertises_expertise_id_fkey'), 'service_expertises', 'expertise_tags', ['expertise_id'], ['id']) + op.create_foreign_key(op.f('service_expertises_service_id_fkey'), 'service_expertises', 'service_profiles', ['service_id'], ['id']) + op.drop_constraint(None, 'security_audit_logs', schema='data', type_='foreignkey') + op.drop_constraint(None, 'security_audit_logs', schema='data', type_='foreignkey') + op.drop_constraint(None, 'security_audit_logs', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('security_audit_logs_confirmed_by_id_fkey'), 'security_audit_logs', 'users', ['confirmed_by_id'], ['id']) + op.create_foreign_key(op.f('security_audit_logs_actor_id_fkey'), 'security_audit_logs', 'users', ['actor_id'], ['id']) + op.create_foreign_key(op.f('security_audit_logs_target_id_fkey'), 'security_audit_logs', 'users', ['target_id'], ['id']) + op.drop_constraint(None, 'ratings', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('ratings_author_id_fkey'), 'ratings', 'users', ['author_id'], ['id']) + op.drop_constraint(None, 'points_ledger', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('points_ledger_user_id_fkey'), 'points_ledger', 'users', ['user_id'], ['id']) + op.drop_constraint(None, 'persons', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('persons_address_id_fkey'), 'persons', 'addresses', ['address_id'], ['id']) + op.drop_constraint(None, 'pending_actions', schema='data', type_='foreignkey') + op.drop_constraint(None, 'pending_actions', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('pending_actions_approver_id_fkey'), 'pending_actions', 'users', ['approver_id'], ['id']) + op.create_foreign_key(op.f('pending_actions_requester_id_fkey'), 'pending_actions', 'users', ['requester_id'], ['id']) + op.drop_constraint(None, 'organizations', schema='data', type_='foreignkey') + op.drop_constraint(None, 'organizations', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('organizations_address_id_fkey'), 'organizations', 'addresses', ['address_id'], ['id']) + op.create_foreign_key(op.f('organizations_owner_id_fkey'), 'organizations', 'users', ['owner_id'], ['id']) + op.alter_column('organizations', 'org_type', + existing_type=postgresql.ENUM('individual', 'service', 'service_provider', 'fleet_owner', 'club', 'business', name='orgtype', schema='data', inherit_schema=True), + type_=postgresql.ENUM('individual', 'service', 'service_provider', 'fleet_owner', 'club', 'business', name='orgtype'), + existing_nullable=True) + op.drop_constraint(None, 'organization_members', schema='data', type_='foreignkey') + op.drop_constraint(None, 'organization_members', schema='data', type_='foreignkey') + op.drop_constraint(None, 'organization_members', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('organization_members_person_id_fkey'), 'organization_members', 'persons', ['person_id'], ['id']) + op.create_foreign_key(op.f('organization_members_organization_id_fkey'), 'organization_members', 'organizations', ['organization_id'], ['id']) + op.create_foreign_key(op.f('organization_members_user_id_fkey'), 'organization_members', 'users', ['user_id'], ['id']) + op.alter_column('organization_members', 'role', + existing_type=postgresql.ENUM('OWNER', 'ADMIN', 'FLEET_MANAGER', 'DRIVER', 'MECHANIC', 'RECEPTIONIST', name='orguserrole', schema='data', inherit_schema=True), + type_=postgresql.ENUM('OWNER', 'ADMIN', 'FLEET_MANAGER', 'DRIVER', 'MECHANIC', 'RECEPTIONIST', name='orguserrole'), + existing_nullable=True) + op.drop_constraint(None, 'organization_financials', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('organization_financials_organization_id_fkey'), 'organization_financials', 'organizations', ['organization_id'], ['id']) + op.drop_constraint(None, 'org_subscriptions', schema='data', type_='foreignkey') + op.drop_constraint(None, 'org_subscriptions', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('org_subscriptions_org_id_fkey'), 'org_subscriptions', 'organizations', ['org_id'], ['id']) + op.create_foreign_key(op.f('org_subscriptions_tier_id_fkey'), 'org_subscriptions', 'subscription_tiers', ['tier_id'], ['id']) + op.drop_constraint(None, 'org_sales_assignments', schema='data', type_='foreignkey') + op.drop_constraint(None, 'org_sales_assignments', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('org_sales_assignments_agent_user_id_fkey'), 'org_sales_assignments', 'users', ['agent_user_id'], ['id']) + op.create_foreign_key(op.f('org_sales_assignments_organization_id_fkey'), 'org_sales_assignments', 'organizations', ['organization_id'], ['id']) + op.drop_constraint(None, 'operational_logs', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('operational_logs_user_id_fkey'), 'operational_logs', 'users', ['user_id'], ['id'], ondelete='SET NULL') + op.drop_constraint(None, 'model_feature_maps', schema='data', type_='foreignkey') + op.drop_constraint(None, 'model_feature_maps', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('model_feature_maps_feature_id_fkey'), 'model_feature_maps', 'feature_definitions', ['feature_id'], ['id']) + op.create_foreign_key(op.f('model_feature_maps_model_id_fkey'), 'model_feature_maps', 'vehicle_model_definitions', ['model_id'], ['id']) + op.drop_constraint(None, 'geo_streets', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('geo_streets_postal_code_id_fkey'), 'geo_streets', 'geo_postal_codes', ['postal_code_id'], ['id']) + op.drop_constraint(None, 'financial_ledger', schema='data', type_='foreignkey') + op.drop_constraint(None, 'financial_ledger', schema='data', type_='foreignkey') + op.drop_constraint(None, 'financial_ledger', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('financial_ledger_related_agent_id_fkey'), 'financial_ledger', 'users', ['related_agent_id'], ['id']) + op.create_foreign_key(op.f('financial_ledger_user_id_fkey'), 'financial_ledger', 'users', ['user_id'], ['id']) + op.create_foreign_key(op.f('financial_ledger_person_id_fkey'), 'financial_ledger', 'persons', ['person_id'], ['id']) + op.drop_constraint(None, 'feature_definitions', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('feature_definitions_vehicle_type_id_fkey'), 'feature_definitions', 'vehicle_types', ['vehicle_type_id'], ['id']) + op.drop_constraint(None, 'documents', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('documents_uploaded_by_fkey'), 'documents', 'users', ['uploaded_by'], ['id']) + op.drop_constraint(None, 'credit_logs', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('credit_logs_org_id_fkey'), 'credit_logs', 'organizations', ['org_id'], ['id']) + op.drop_constraint(None, 'branches', schema='data', type_='foreignkey') + op.drop_constraint(None, 'branches', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('branches_address_id_fkey'), 'branches', 'addresses', ['address_id'], ['id']) + op.create_foreign_key(op.f('branches_organization_id_fkey'), 'branches', 'organizations', ['organization_id'], ['id']) + op.drop_constraint(None, 'audit_logs', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('audit_logs_user_id_fkey'), 'audit_logs', 'users', ['user_id'], ['id']) + op.drop_constraint(None, 'assets', schema='data', type_='foreignkey') + op.drop_constraint(None, 'assets', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('assets_catalog_id_fkey'), 'assets', 'vehicle_catalog', ['catalog_id'], ['id']) + op.create_foreign_key(op.f('assets_current_organization_id_fkey'), 'assets', 'organizations', ['current_organization_id'], ['id']) + op.drop_constraint(None, 'asset_telemetry', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_telemetry_asset_id_fkey'), 'asset_telemetry', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'asset_reviews', schema='data', type_='foreignkey') + op.drop_constraint(None, 'asset_reviews', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_reviews_user_id_fkey'), 'asset_reviews', 'users', ['user_id'], ['id']) + op.create_foreign_key(op.f('asset_reviews_asset_id_fkey'), 'asset_reviews', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'asset_financials', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_financials_asset_id_fkey'), 'asset_financials', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'asset_events', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_events_asset_id_fkey'), 'asset_events', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'asset_costs', schema='data', type_='foreignkey') + op.drop_constraint(None, 'asset_costs', schema='data', type_='foreignkey') + op.drop_constraint(None, 'asset_costs', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_costs_organization_id_fkey'), 'asset_costs', 'organizations', ['organization_id'], ['id']) + op.create_foreign_key(op.f('asset_costs_asset_id_fkey'), 'asset_costs', 'assets', ['asset_id'], ['id']) + op.create_foreign_key(op.f('asset_costs_driver_id_fkey'), 'asset_costs', 'users', ['driver_id'], ['id']) + op.drop_constraint(None, 'asset_assignments', schema='data', type_='foreignkey') + op.drop_constraint(None, 'asset_assignments', schema='data', type_='foreignkey') + op.drop_constraint(None, 'asset_assignments', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('asset_assignments_branch_id_fkey'), 'asset_assignments', 'branches', ['branch_id'], ['id']) + op.create_foreign_key(op.f('asset_assignments_organization_id_fkey'), 'asset_assignments', 'organizations', ['organization_id'], ['id']) + op.create_foreign_key(op.f('asset_assignments_asset_id_fkey'), 'asset_assignments', 'assets', ['asset_id'], ['id']) + op.drop_constraint(None, 'addresses', schema='data', type_='foreignkey') + op.create_foreign_key(op.f('addresses_postal_code_id_fkey'), 'addresses', 'geo_postal_codes', ['postal_code_id'], ['id']) + op.drop_index(op.f('ix_data_process_logs_process_name'), table_name='process_logs', schema='data') + op.drop_table('process_logs', schema='data') + # ### end Alembic commands ### diff --git a/backend/requirements.txt b/backend/requirements.txt index 65886c0..889f894 100755 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -23,4 +23,5 @@ itsdangerous fastapi-limiter==0.1.5 pyotp cryptography -GeoAlchemy2>=0.14.0 \ No newline at end of file +GeoAlchemy2>=0.14.0 +google-generativeai \ No newline at end of file