diff --git a/bp/cart/api.py b/bp/cart/api.py index 6a9bd18..6eab95d 100644 --- a/bp/cart/api.py +++ b/bp/cart/api.py @@ -7,7 +7,7 @@ They are CSRF-exempt because they are server-to-server calls. from __future__ import annotations from quart import Blueprint, g, request, jsonify -from sqlalchemy import select, update, func +from sqlalchemy import select from sqlalchemy.orm import selectinload from market.models.market import CartItem @@ -120,57 +120,4 @@ def register() -> Blueprint: } ) - @bp.post("/adopt") - @csrf_exempt - async def adopt(): - """ - Adopt anonymous cart items + calendar entries for a user. - Called by the coop app after successful login. - - Body: {"user_id": int, "session_id": str} - """ - data = await request.get_json() or {} - user_id = data.get("user_id") - session_id = data.get("session_id") - - if not user_id or not session_id: - return jsonify({"ok": False, "error": "user_id and session_id required"}), 400 - - # --- adopt cart items --- - anon_result = await g.s.execute( - select(CartItem).where( - CartItem.deleted_at.is_(None), - CartItem.user_id.is_(None), - CartItem.session_id == session_id, - ) - ) - anon_items = anon_result.scalars().all() - - if anon_items: - # Soft-delete existing user cart - await g.s.execute( - update(CartItem) - .where(CartItem.deleted_at.is_(None), CartItem.user_id == user_id) - .values(deleted_at=func.now()) - ) - for ci in anon_items: - ci.user_id = user_id - - # --- adopt calendar entries --- - await g.s.execute( - update(CalendarEntry) - .where(CalendarEntry.deleted_at.is_(None), CalendarEntry.user_id == user_id) - .values(deleted_at=func.now()) - ) - cal_result = await g.s.execute( - select(CalendarEntry).where( - CalendarEntry.deleted_at.is_(None), - CalendarEntry.session_id == session_id, - ) - ) - for entry in cal_result.scalars().all(): - entry.user_id = user_id - - return jsonify({"ok": True}) - return bp diff --git a/bp/cart/global_routes.py b/bp/cart/global_routes.py index 2baed80..2010e78 100644 --- a/bp/cart/global_routes.py +++ b/bp/cart/global_routes.py @@ -7,6 +7,7 @@ from sqlalchemy import select from models.order import Order from shared.browser.app.utils.htmx import is_htmx_request +from glue.services.order_lifecycle import get_entries_for_order from .services import ( current_cart_identity, get_cart, @@ -187,7 +188,7 @@ def register(url_prefix: str) -> Blueprint: except Exception: status = status or "pending" - calendar_entries = order.calendar_entries or [] + calendar_entries = await get_entries_for_order(g.s, order.id) await g.s.flush() html = await render_template( diff --git a/bp/cart/services/check_sumup_status.py b/bp/cart/services/check_sumup_status.py index a5df783..7973e17 100644 --- a/bp/cart/services/check_sumup_status.py +++ b/bp/cart/services/check_sumup_status.py @@ -1,6 +1,6 @@ from shared.browser.app.payments.sumup import get_checkout as sumup_get_checkout -from sqlalchemy import update -from events.models.calendars import CalendarEntry +from shared.events import emit_event +from glue.services.order_lifecycle import confirm_entries_for_order async def check_sumup_status(session, order): @@ -13,21 +13,13 @@ async def check_sumup_status(session, order): if sumup_status == "PAID": if order.status != "paid": order.status = "paid" - filters = [ - CalendarEntry.deleted_at.is_(None), - CalendarEntry.state == "ordered", - CalendarEntry.order_id==order.id, - ] - if order.user_id is not None: - filters.append(CalendarEntry.user_id == order.user_id) - elif order.session_id is not None: - filters.append(CalendarEntry.session_id == order.session_id) - - await session.execute( - update(CalendarEntry) - .where(*filters) - .values(state="provisional") + await confirm_entries_for_order( + session, order.id, order.user_id, order.session_id ) + await emit_event(session, "order.paid", "order", order.id, { + "order_id": order.id, + "user_id": order.user_id, + }) elif sumup_status == "FAILED": order.status = "failed" else: diff --git a/bp/cart/services/checkout.py b/bp/cart/services/checkout.py index d66e399..0c955e3 100644 --- a/bp/cart/services/checkout.py +++ b/bp/cart/services/checkout.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Optional from urllib.parse import urlencode -from sqlalchemy import select, update +from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload @@ -13,6 +13,8 @@ from events.models.calendars import CalendarEntry, Calendar from models.page_config import PageConfig from market.models.market_place import MarketPlace from shared.config import config +from shared.events import emit_event +from glue.services.order_lifecycle import claim_entries_for_order async def find_or_create_cart_item( @@ -148,34 +150,17 @@ async def create_order_from_cart( ) session.add(oi) - # Update calendar entries to reference this order - calendar_filters = [ - CalendarEntry.deleted_at.is_(None), - CalendarEntry.state == "pending", - ] - - if order.user_id is not None: - calendar_filters.append(CalendarEntry.user_id == order.user_id) - elif order.session_id is not None: - calendar_filters.append(CalendarEntry.session_id == order.session_id) - - if page_post_id is not None: - cal_ids = select(Calendar.id).where( - Calendar.container_type == "page", - Calendar.container_id == page_post_id, - Calendar.deleted_at.is_(None), - ).scalar_subquery() - calendar_filters.append(CalendarEntry.calendar_id.in_(cal_ids)) - - await session.execute( - update(CalendarEntry) - .where(*calendar_filters) - .values( - state="ordered", - order_id=order.id, - ) + # Mark pending calendar entries as "ordered" via glue service + await claim_entries_for_order( + session, order.id, user_id, session_id, page_post_id ) + await emit_event(session, "order.created", "order", order.id, { + "order_id": order.id, + "user_id": user_id, + "session_id": session_id, + }) + return order @@ -234,7 +219,6 @@ async def get_order_with_details(session: AsyncSession, order_id: int) -> Option select(Order) .options( selectinload(Order.items).selectinload(OrderItem.product), - selectinload(Order.calendar_entries), ) .where(Order.id == order_id) ) diff --git a/models/order.py b/models/order.py index a374708..4f2f547 100644 --- a/models/order.py +++ b/models/order.py @@ -69,11 +69,6 @@ class Order(Base): cascade="all, delete-orphan", lazy="selectin", ) - calendar_entries: Mapped[List["CalendarEntry"]] = relationship( - "CalendarEntry", - back_populates="order", - lazy="selectin", - ) page_config: Mapped[Optional["PageConfig"]] = relationship( "PageConfig", foreign_keys=[page_config_id],