diff --git a/app.py b/app.py index bc23b18..eeb6e7e 100644 --- a/app.py +++ b/app.py @@ -13,7 +13,6 @@ from bp import ( register_cart_overview, register_page_cart, register_cart_global, - register_cart_api, register_orders, ) from bp.cart.services import ( @@ -145,9 +144,6 @@ def create_app() -> "Quart": # --- Blueprint registration --- # Static prefixes first, dynamic (page_slug) last - # Internal API (server-to-server, CSRF-exempt) - app.register_blueprint(register_cart_api()) - # Orders blueprint app.register_blueprint(register_orders(url_prefix="/orders")) diff --git a/bp/__init__.py b/bp/__init__.py index 54b3022..dead062 100644 --- a/bp/__init__.py +++ b/bp/__init__.py @@ -1,6 +1,5 @@ from .cart.overview_routes import register as register_cart_overview from .cart.page_routes import register as register_page_cart from .cart.global_routes import register as register_cart_global -from .cart.api import register as register_cart_api from .order.routes import register as register_order from .orders.routes import register as register_orders diff --git a/bp/cart/api.py b/bp/cart/api.py deleted file mode 100644 index 22110f8..0000000 --- a/bp/cart/api.py +++ /dev/null @@ -1,111 +0,0 @@ -""" -Internal JSON API for the cart app. - -These endpoints are called by other apps (coop, market) over HTTP. -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 -from sqlalchemy.orm import selectinload - -from shared.models.market import CartItem -from shared.models.market_place import MarketPlace -from shared.browser.app.csrf import csrf_exempt -from shared.infrastructure.cart_identity import current_cart_identity -from shared.services.registry import services - - -def register() -> Blueprint: - bp = Blueprint("cart_api", __name__, url_prefix="/internal/cart") - - @bp.get("/summary") - @csrf_exempt - async def summary(): - """ - Return a lightweight cart summary (count + total) for the - current session/user. Called by coop and market apps to - populate the cart-mini widget without importing cart services. - - Optional query param: ?page_slug= - When provided, returns only items scoped to that page. - """ - ident = current_cart_identity() - - # Resolve optional page filter - page_slug = request.args.get("page_slug") - page_post_id = None - if page_slug: - post = await services.blog.get_post_by_slug(g.s, page_slug) - if post and post.is_page: - page_post_id = post.id - - # --- product cart --- - cart_q = select(CartItem).where(CartItem.deleted_at.is_(None)) - if ident["user_id"] is not None: - cart_q = cart_q.where(CartItem.user_id == ident["user_id"]) - else: - cart_q = cart_q.where(CartItem.session_id == ident["session_id"]) - - if page_post_id is not None: - mp_ids = select(MarketPlace.id).where( - MarketPlace.container_type == "page", - MarketPlace.container_id == page_post_id, - MarketPlace.deleted_at.is_(None), - ).scalar_subquery() - cart_q = cart_q.where(CartItem.market_place_id.in_(mp_ids)) - - cart_q = cart_q.options(selectinload(CartItem.product)).order_by(CartItem.created_at.desc()) - - result = await g.s.execute(cart_q) - cart_items = result.scalars().all() - - cart_count = sum(ci.quantity for ci in cart_items) - cart_total = sum( - (ci.product.special_price or ci.product.regular_price or 0) * ci.quantity - for ci in cart_items - if ci.product and (ci.product.special_price or ci.product.regular_price) - ) - - # --- calendar entries via service --- - if page_post_id is not None: - cal_entries = await services.calendar.entries_for_page( - g.s, page_post_id, - user_id=ident["user_id"], - session_id=ident["session_id"], - ) - else: - cal_entries = await services.calendar.pending_entries( - g.s, - user_id=ident["user_id"], - session_id=ident["session_id"], - ) - - calendar_count = len(cal_entries) - calendar_total = sum((e.cost or 0) for e in cal_entries if e.cost is not None) - - items = [ - { - "slug": ci.product.slug if ci.product else None, - "title": ci.product.title if ci.product else None, - "image": ci.product.image if ci.product else None, - "quantity": ci.quantity, - "price": float(ci.product.special_price or ci.product.regular_price or 0) - if ci.product - else 0, - } - for ci in cart_items - ] - - return jsonify( - { - "count": cart_count, - "total": float(cart_total), - "calendar_count": calendar_count, - "calendar_total": float(calendar_total), - "items": items, - } - ) - - return bp diff --git a/shared b/shared index 7ee8638..e83df2f 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 7ee8638d6e41de1f58aadd1f108cd7de8e920d07 +Subproject commit e83df2f742c8b64e7b4a6bc218fd1bd0a9637d21