Decoupling audit: remove cart API, update shared submodule
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m13s

- Delete bp/cart/api.py (dead internal API endpoint)
- Remove registration from bp/__init__.py and app.py
- Update shared submodule

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
giles
2026-02-20 11:15:28 +00:00
parent cd41b6c8ef
commit dc249ea9ce
4 changed files with 1 additions and 117 deletions

4
app.py
View File

@@ -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"))

View File

@@ -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

View File

@@ -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=<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

2
shared

Submodule shared updated: 7ee8638d6e...e83df2f742