from datetime import datetime from sqlalchemy.inspection import inspect def encode_value(value): if isinstance(value, datetime): return value.isoformat() if isinstance(value, list): return [encode_value(item) for item in value] if isinstance(value, dict): return {key: encode_value(item) for key, item in value.items()} return value def model_dict(instance, include: dict[str, object] | None = None) -> dict: data = {column.key: encode_value(getattr(instance, column.key)) for column in inspect(instance).mapper.column_attrs} if include: for key, value in include.items(): data[key] = encode_value(value) return data def _sorted_aliases(destination) -> list: return sorted(destination.aliases or [], key=lambda item: ((item.alias or "").lower(), item.id or "")) def _sorted_images(product) -> list: return sorted(product.images or [], key=lambda item: (item.sortOrder, item.id or "", item.url)) def _product_images(product) -> list[dict]: return [model_dict(image) for image in _sorted_images(product)] def _detail_sections(product) -> list: return encode_value(product.detailSections or []) def admin_product_dict(product) -> dict: return model_dict( product, { "tags": list(product.tags or []), "detailSections": _detail_sections(product), "destination": destination_dict(product.destination) if product.destination else None, "images": _product_images(product), }, ) def public_product_dict(product) -> dict: return { "id": product.id, "sourceId": product.sourceId, "title": product.title, "subtitle": product.subtitle, "destination": {"id": product.destination.id, "name": product.destination.name} if product.destination else None, "priceAmount": product.priceAmount, "priceUnit": product.priceUnit, "tags": list(product.tags or []), "coverImage": product.coverImage, "summary": product.summary, "images": _product_images(product), "detailSections": _detail_sections(product), "status": product.status, } def product_dict(product) -> dict: return admin_product_dict(product) def hotel_group_dict(group) -> dict: data = model_dict(group) if not data.get("coverImage"): data["coverImage"] = data.get("image") if not data.get("image"): data["image"] = data.get("coverImage") data["tags"] = list(group.tags or []) return data def destination_dict(destination, include_count: bool = False, product_count: int | None = None) -> dict: data = model_dict(destination, {"aliases": [model_dict(alias) for alias in _sorted_aliases(destination)]}) if include_count: data["_count"] = {"products": product_count if product_count is not None else len(destination.products or [])} return data def lead_dict(lead) -> dict: return model_dict( lead, { "sourceProduct": {"id": lead.sourceProduct.id, "title": lead.sourceProduct.title} if lead.sourceProduct else None, "assignedUser": {"id": lead.assignedUser.id, "name": lead.assignedUser.name} if lead.assignedUser else None, }, )