Phase 1-3 of decoupling: - path_setup.py adds project root to sys.path - Cart-owned models in cart/models/ (order, page_config) - All imports updated: shared.infrastructure, shared.db, shared.browser, etc. - PageConfig uses container_type/container_id instead of post_id FK Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
58 lines
1.6 KiB
Python
58 lines
1.6 KiB
Python
# app/cart_merge.py
|
|
|
|
from __future__ import annotations
|
|
|
|
from quart import g, session as qsession
|
|
from sqlalchemy import select
|
|
from typing import Optional
|
|
|
|
from market.models.market import CartItem
|
|
|
|
|
|
async def merge_anonymous_cart_into_user(user_id: int) -> None:
|
|
"""
|
|
When a user logs in, move any anonymous cart (session_id) items onto their user_id.
|
|
"""
|
|
sid: Optional[str] = qsession.get("cart_sid")
|
|
if not sid:
|
|
return
|
|
|
|
# get all anon cart items for this session
|
|
anon_items = (
|
|
await g.s.execute(
|
|
select(CartItem).where(
|
|
CartItem.deleted_at.is_(None),
|
|
CartItem.session_id == sid,
|
|
)
|
|
)
|
|
).scalars().all()
|
|
if not anon_items:
|
|
return
|
|
|
|
# Existing user items keyed by product_id for quick merge
|
|
user_items_by_product = {
|
|
ci.product_id: ci
|
|
for ci in (
|
|
await g.s.execute(
|
|
select(CartItem).where(
|
|
CartItem.deleted_at.is_(None),
|
|
CartItem.user_id == user_id,
|
|
)
|
|
)
|
|
).scalars().all()
|
|
}
|
|
|
|
for anon in anon_items:
|
|
existing = user_items_by_product.get(anon.product_id)
|
|
if existing:
|
|
# merge quantities then soft-delete the anon row
|
|
existing.quantity += anon.quantity
|
|
anon.deleted_at = func.now()
|
|
else:
|
|
# reassign anonymous cart row to this user
|
|
anon.user_id = user_id
|
|
anon.session_id = None
|
|
|
|
# clear the anonymous session id now that it's "claimed"
|
|
qsession.pop("cart_sid", None)
|