refaktor címtár
This commit is contained in:
@@ -28,7 +28,9 @@ from app.models.core_logic import SubscriptionTier, OrganizationSubscription
|
||||
from app.models.marketplace.organization import Organization, OrganizationMember
|
||||
from app.models.fleet.organization import ContactPerson
|
||||
from app.models.identity import User, Person
|
||||
from app.services.address_manager import AddressManager
|
||||
from app.models.vehicle.history import AuditLog, LogSeverity
|
||||
from app.schemas.address import AddressIn, AddressOut
|
||||
from app.schemas.organization import (
|
||||
OrganizationMemberCreate,
|
||||
OrganizationMemberUpdate,
|
||||
@@ -207,30 +209,36 @@ class GarageDetailsResponse(BaseModel):
|
||||
is_active: bool
|
||||
is_verified: bool
|
||||
org_type: str
|
||||
# Cím adatok (elsődleges)
|
||||
# Cím adatok (elsődleges) — denormalizált mezők (backward compatible)
|
||||
address_city: Optional[str] = None
|
||||
address_zip: Optional[str] = None
|
||||
address_street_name: Optional[str] = None
|
||||
address_street_type: Optional[str] = None
|
||||
address_house_number: Optional[str] = None
|
||||
# P0: Unified AddressOut nested object
|
||||
address_detail: Optional[AddressOut] = None
|
||||
tax_number: Optional[str] = None
|
||||
reg_number: Optional[str] = None
|
||||
# ── Kapcsolattartó (Contact Person) ──
|
||||
contact_person_name: Optional[str] = None
|
||||
contact_email: Optional[str] = None
|
||||
contact_phone: Optional[str] = None
|
||||
# ── Számlázási cím (Billing Address) ──
|
||||
# ── Számlázási cím (Billing Address) — denormalizált mezők (backward compatible) ──
|
||||
billing_zip: Optional[str] = None
|
||||
billing_city: Optional[str] = None
|
||||
billing_street_name: Optional[str] = None
|
||||
billing_street_type: Optional[str] = None
|
||||
billing_house_number: Optional[str] = None
|
||||
# ── Értesítési cím (Notification Address) ──
|
||||
# P0: Unified AddressOut nested object for billing address
|
||||
billing_address_detail: Optional[AddressOut] = None
|
||||
# ── Értesítési cím (Notification Address) — denormalizált mezők (backward compatible) ──
|
||||
notification_zip: Optional[str] = None
|
||||
notification_city: Optional[str] = None
|
||||
notification_street_name: Optional[str] = None
|
||||
notification_street_type: Optional[str] = None
|
||||
notification_house_number: Optional[str] = None
|
||||
# P0: Unified AddressOut nested object for notification address
|
||||
notification_address_detail: Optional[AddressOut] = None
|
||||
# Előfizetés
|
||||
subscription: Optional[SubscriptionSummary] = None
|
||||
# Kapcsolattartó (ContactPerson modellből)
|
||||
@@ -421,6 +429,9 @@ async def list_organizations(
|
||||
# Resolve email: prefer contact_email, fallback to owner's email
|
||||
resolved_email = org.contact_email or (org.owner.email if org.owner else None)
|
||||
|
||||
# P1 FIX: Use relationship-based city instead of ghost column org.address_city
|
||||
resolved_city = org.address.city if org.address else None
|
||||
|
||||
garage_list.append(GarageListItem(
|
||||
id=org.id,
|
||||
name=org.name,
|
||||
@@ -432,7 +443,7 @@ async def list_organizations(
|
||||
is_verified=org.is_verified,
|
||||
is_deleted=org.is_deleted,
|
||||
org_type=org.org_type.value if hasattr(org.org_type, "value") else str(org.org_type),
|
||||
city=org.address_city,
|
||||
city=resolved_city,
|
||||
region=org.region,
|
||||
segment=org.segment,
|
||||
member_count=member_counts.get(org.id, 0),
|
||||
@@ -1078,6 +1089,19 @@ async def get_organization_details(
|
||||
f"({org.full_name}) — {len(members_list)} members"
|
||||
)
|
||||
|
||||
# ── P0 REFACTORED: Build unified AddressOut objects from relationships ──
|
||||
address_detail = None
|
||||
if org.address:
|
||||
address_detail = AddressOut.model_validate(org.address)
|
||||
|
||||
billing_address_detail = None
|
||||
if org.billing_address:
|
||||
billing_address_detail = AddressOut.model_validate(org.billing_address)
|
||||
|
||||
notification_address_detail = None
|
||||
if org.notification_address:
|
||||
notification_address_detail = AddressOut.model_validate(org.notification_address)
|
||||
|
||||
return GarageDetailsResponse(
|
||||
id=org.id,
|
||||
name=org.name,
|
||||
@@ -1087,11 +1111,13 @@ async def get_organization_details(
|
||||
is_active=org.is_active,
|
||||
is_verified=org.is_verified,
|
||||
org_type=org.org_type.value if hasattr(org.org_type, "value") else str(org.org_type),
|
||||
address_city=org.address_city,
|
||||
address_zip=org.address_zip,
|
||||
address_street_name=org.address_street_name,
|
||||
address_street_type=org.address_street_type,
|
||||
address_house_number=org.address_house_number,
|
||||
# ── P0 REFACTORED: Denormalized fields populated from relationship ──
|
||||
address_city=org.address.city if org.address else None,
|
||||
address_zip=org.address.zip if org.address else None,
|
||||
address_street_name=org.address.street_name if org.address else None,
|
||||
address_street_type=org.address.street_type if org.address else None,
|
||||
address_house_number=org.address.house_number if org.address else None,
|
||||
address_detail=address_detail,
|
||||
tax_number=org.tax_number,
|
||||
reg_number=org.reg_number,
|
||||
# ── P0: Zero-Duplication Kapcsolattartó (owner fallback) ──
|
||||
@@ -1099,17 +1125,19 @@ async def get_organization_details(
|
||||
contact_email=resolved_contact_email,
|
||||
contact_phone=resolved_contact_phone,
|
||||
# ── Számlázási cím ──
|
||||
billing_zip=org.billing_zip,
|
||||
billing_city=org.billing_city,
|
||||
billing_street_name=org.billing_street_name,
|
||||
billing_street_type=org.billing_street_type,
|
||||
billing_house_number=org.billing_house_number,
|
||||
billing_zip=org.billing_address.zip if org.billing_address else None,
|
||||
billing_city=org.billing_address.city if org.billing_address else None,
|
||||
billing_street_name=org.billing_address.street_name if org.billing_address else None,
|
||||
billing_street_type=org.billing_address.street_type if org.billing_address else None,
|
||||
billing_house_number=org.billing_address.house_number if org.billing_address else None,
|
||||
billing_address_detail=billing_address_detail,
|
||||
# ── Értesítési cím ──
|
||||
notification_zip=org.notification_zip,
|
||||
notification_city=org.notification_city,
|
||||
notification_street_name=org.notification_street_name,
|
||||
notification_street_type=org.notification_street_type,
|
||||
notification_house_number=org.notification_house_number,
|
||||
notification_zip=org.notification_address.zip if org.notification_address else None,
|
||||
notification_city=org.notification_address.city if org.notification_address else None,
|
||||
notification_street_name=org.notification_address.street_name if org.notification_address else None,
|
||||
notification_street_type=org.notification_address.street_type if org.notification_address else None,
|
||||
notification_house_number=org.notification_address.house_number if org.notification_address else None,
|
||||
notification_address_detail=notification_address_detail,
|
||||
subscription=subscription_summary,
|
||||
primary_contact=primary_contact,
|
||||
created_at=org.created_at.isoformat() if org.created_at else None,
|
||||
@@ -1224,28 +1252,34 @@ class OrganizationUpdate(BaseModel):
|
||||
# ── Org-level email/phone (used for individual garages to propagate to Person/User) ──
|
||||
email: Optional[str] = Field(None, max_length=255, description="Szervezeti e-mail (individual garages esetén a User rekordba propagálódik)")
|
||||
phone: Optional[str] = Field(None, max_length=50, description="Szervezeti telefon (individual garages esetén a Person rekordba propagálódik)")
|
||||
# ── Elsődleges cím (Primary Address) ──
|
||||
address_zip: Optional[str] = Field(None, max_length=10, description="Irányítószám")
|
||||
address_city: Optional[str] = Field(None, max_length=100, description="Város")
|
||||
address_street_name: Optional[str] = Field(None, max_length=150, description="Utca neve")
|
||||
address_street_type: Optional[str] = Field(None, max_length=50, description="Utca típusa (utca, tér, stb.)")
|
||||
address_house_number: Optional[str] = Field(None, max_length=20, description="Házszám")
|
||||
# ── Elsődleges cím (Primary Address) — DEPRECATED: Use address_detail instead ──
|
||||
address_zip: Optional[str] = Field(None, max_length=10, description="[DEPRECATED] Használd az address_detail mezőt! Irányítószám")
|
||||
address_city: Optional[str] = Field(None, max_length=100, description="[DEPRECATED] Használd az address_detail mezőt! Város")
|
||||
address_street_name: Optional[str] = Field(None, max_length=150, description="[DEPRECATED] Használd az address_detail mezőt! Utca neve")
|
||||
address_street_type: Optional[str] = Field(None, max_length=50, description="[DEPRECATED] Használd az address_detail mezőt! Utca típusa (utca, tér, stb.)")
|
||||
address_house_number: Optional[str] = Field(None, max_length=20, description="[DEPRECATED] Használd az address_detail mezőt! Házszám")
|
||||
# P0: Unified AddressIn nested object for primary address
|
||||
address_detail: Optional[AddressIn] = None
|
||||
# ── Kapcsolattartó (Contact Person) ──
|
||||
contact_person_name: Optional[str] = Field(None, max_length=255, description="Kapcsolattartó neve")
|
||||
contact_email: Optional[str] = Field(None, max_length=255, description="Kapcsolattartó e-mail címe")
|
||||
contact_phone: Optional[str] = Field(None, max_length=50, description="Kapcsolattartó telefonszáma")
|
||||
# ── Számlázási cím (Billing Address) ──
|
||||
billing_zip: Optional[str] = Field(None, max_length=10, description="Számlázási irányítószám")
|
||||
billing_city: Optional[str] = Field(None, max_length=100, description="Számlázási város")
|
||||
billing_street_name: Optional[str] = Field(None, max_length=150, description="Számlázási utca neve")
|
||||
billing_street_type: Optional[str] = Field(None, max_length=50, description="Számlázási utca típusa")
|
||||
billing_house_number: Optional[str] = Field(None, max_length=20, description="Számlázási házszám")
|
||||
# ── Értesítési cím (Notification Address) ──
|
||||
notification_zip: Optional[str] = Field(None, max_length=10, description="Értesítési irányítószám")
|
||||
notification_city: Optional[str] = Field(None, max_length=100, description="Értesítési város")
|
||||
notification_street_name: Optional[str] = Field(None, max_length=150, description="Értesítési utca neve")
|
||||
notification_street_type: Optional[str] = Field(None, max_length=50, description="Értesítési utca típusa")
|
||||
notification_house_number: Optional[str] = Field(None, max_length=20, description="Értesítési házszám")
|
||||
# ── Számlázási cím (Billing Address) — DEPRECATED: Use billing_address_detail instead ──
|
||||
billing_zip: Optional[str] = Field(None, max_length=10, description="[DEPRECATED] Használd a billing_address_detail mezőt! Számlázási irányítószám")
|
||||
billing_city: Optional[str] = Field(None, max_length=100, description="[DEPRECATED] Használd a billing_address_detail mezőt! Számlázási város")
|
||||
billing_street_name: Optional[str] = Field(None, max_length=150, description="[DEPRECATED] Használd a billing_address_detail mezőt! Számlázási utca neve")
|
||||
billing_street_type: Optional[str] = Field(None, max_length=50, description="[DEPRECATED] Használd a billing_address_detail mezőt! Számlázási utca típusa")
|
||||
billing_house_number: Optional[str] = Field(None, max_length=20, description="[DEPRECATED] Használd a billing_address_detail mezőt! Számlázási házszám")
|
||||
# P0: Unified AddressIn nested object for billing address
|
||||
billing_address_detail: Optional[AddressIn] = None
|
||||
# ── Értesítési cím (Notification Address) — DEPRECATED: Use notification_address_detail instead ──
|
||||
notification_zip: Optional[str] = Field(None, max_length=10, description="[DEPRECATED] Használd a notification_address_detail mezőt! Értesítési irányítószám")
|
||||
notification_city: Optional[str] = Field(None, max_length=100, description="[DEPRECATED] Használd a notification_address_detail mezőt! Értesítési város")
|
||||
notification_street_name: Optional[str] = Field(None, max_length=150, description="[DEPRECATED] Használd a notification_address_detail mezőt! Értesítési utca neve")
|
||||
notification_street_type: Optional[str] = Field(None, max_length=50, description="[DEPRECATED] Használd a notification_address_detail mezőt! Értesítési utca típusa")
|
||||
notification_house_number: Optional[str] = Field(None, max_length=20, description="[DEPRECATED] Használd a notification_address_detail mezőt! Értesítési házszám")
|
||||
# P0: Unified AddressIn nested object for notification address
|
||||
notification_address_detail: Optional[AddressIn] = None
|
||||
|
||||
|
||||
@router.put(
|
||||
@@ -1279,10 +1313,34 @@ async def update_organization(
|
||||
detail=f"Szervezet nem található ID-vel: {org_id}",
|
||||
)
|
||||
|
||||
# 2. Összegyűjtjük a változásokat
|
||||
# 2. P0 REFACTORED: Address FK logic via AddressManager
|
||||
raw_data = payload.model_dump(exclude_none=True)
|
||||
|
||||
# ── Primary address via AddressManager ──
|
||||
address_detail: Optional[AddressIn] = raw_data.pop("address_detail", None)
|
||||
if address_detail:
|
||||
org.address_id = await AddressManager.create_or_update(
|
||||
db, org.address_id, address_detail
|
||||
)
|
||||
|
||||
# ── Billing address via AddressManager ──
|
||||
billing_address_detail: Optional[AddressIn] = raw_data.pop("billing_address_detail", None)
|
||||
if billing_address_detail:
|
||||
org.billing_address_id = await AddressManager.create_or_update(
|
||||
db, org.billing_address_id, billing_address_detail
|
||||
)
|
||||
|
||||
# ── Notification address via AddressManager ──
|
||||
notification_address_detail: Optional[AddressIn] = raw_data.pop("notification_address_detail", None)
|
||||
if notification_address_detail:
|
||||
org.notification_address_id = await AddressManager.create_or_update(
|
||||
db, org.notification_address_id, notification_address_detail
|
||||
)
|
||||
|
||||
# 3. Összegyűjtjük a változásokat (non-address fields)
|
||||
update_fields = {}
|
||||
for field_name in payload.model_dump(exclude_none=True):
|
||||
value = getattr(payload, field_name)
|
||||
for field_name in raw_data:
|
||||
value = raw_data[field_name]
|
||||
if value is not None and hasattr(org, field_name):
|
||||
setattr(org, field_name, value)
|
||||
update_fields[field_name] = value
|
||||
@@ -1333,6 +1391,11 @@ async def update_organization(
|
||||
f"({org.full_name}): fields={list(update_fields.keys())}"
|
||||
)
|
||||
|
||||
# ── P0 REFACTORED: Build unified AddressOut from relationship ──
|
||||
resp_address_detail = None
|
||||
if org.address:
|
||||
resp_address_detail = AddressOut.model_validate(org.address)
|
||||
|
||||
return {
|
||||
"status": "success",
|
||||
"message": f"A(z) '{org.full_name}' garázs adatai frissítve.",
|
||||
@@ -1345,11 +1408,7 @@ async def update_organization(
|
||||
"display_name": org.display_name,
|
||||
"tax_number": org.tax_number,
|
||||
"reg_number": org.reg_number,
|
||||
"address_zip": org.address_zip,
|
||||
"address_city": org.address_city,
|
||||
"address_street_name": org.address_street_name,
|
||||
"address_street_type": org.address_street_type,
|
||||
"address_house_number": org.address_house_number,
|
||||
"address_detail": resp_address_detail,
|
||||
"status": org.status,
|
||||
"is_active": org.is_active,
|
||||
"contact_email": org.contact_email,
|
||||
|
||||
Reference in New Issue
Block a user