Replace direct MarketPlace imports with MarketService calls
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 51s

Market CRUD in blog now delegates to services.market.create_marketplace()
and soft_delete_marketplace() instead of importing MarketPlace directly.
Adds TODO comments on Calendar imports in admin routes (deferred to
admin UI rework). Updates shared submodule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
giles
2026-02-19 05:44:11 +00:00
parent 6f063665b0
commit f9e39333bf
3 changed files with 11 additions and 46 deletions

View File

@@ -191,7 +191,7 @@ def register():
@require_admin @require_admin
async def calendar_view(slug: str, calendar_id: int): async def calendar_view(slug: str, calendar_id: int):
"""Show calendar month view for browsing entries""" """Show calendar month view for browsing entries"""
from shared.models.calendars import Calendar from shared.models.calendars import Calendar # TODO: service method when admin UI is reworked
from sqlalchemy import select from sqlalchemy import select
from datetime import datetime, timezone from datetime import datetime, timezone
from quart import request from quart import request
@@ -273,7 +273,7 @@ def register():
@require_admin @require_admin
async def entries(slug: str): async def entries(slug: str):
from ..services.entry_associations import get_post_entry_ids from ..services.entry_associations import get_post_entry_ids
from shared.models.calendars import Calendar from shared.models.calendars import Calendar # TODO: service method when admin UI is reworked
from sqlalchemy import select from sqlalchemy import select
post_id = g.post_data["post"]["id"] post_id = g.post_data["post"]["id"]
@@ -309,7 +309,7 @@ def register():
@require_admin @require_admin
async def toggle_entry(slug: str, entry_id: int): async def toggle_entry(slug: str, entry_id: int):
from ..services.entry_associations import toggle_entry_association, get_post_entry_ids, get_associated_entries from ..services.entry_associations import toggle_entry_association, get_post_entry_ids, get_associated_entries
from shared.models.calendars import Calendar from shared.models.calendars import Calendar # TODO: service method when admin UI is reworked
from sqlalchemy import select from sqlalchemy import select
from quart import jsonify from quart import jsonify

View File

@@ -6,11 +6,9 @@ import unicodedata
from sqlalchemy import select from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from shared.models.market_place import MarketPlace
from shared.models.page_config import PageConfig from shared.models.page_config import PageConfig
from shared.browser.app.utils import utcnow from shared.contracts.dtos import MarketPlaceDTO
from shared.services.registry import services from shared.services.registry import services
from shared.services.relationships import attach_child, detach_child
class MarketError(ValueError): class MarketError(ValueError):
@@ -30,7 +28,7 @@ def slugify(value: str, max_len: int = 255) -> str:
return value or "market" return value or "market"
async def create_market(sess: AsyncSession, post_id: int, name: str) -> MarketPlace: async def create_market(sess: AsyncSession, post_id: int, name: str) -> MarketPlaceDTO:
name = (name or "").strip() name = (name or "").strip()
if not name: if not name:
raise MarketError("Market name must not be empty.") raise MarketError("Market name must not be empty.")
@@ -49,25 +47,10 @@ async def create_market(sess: AsyncSession, post_id: int, name: str) -> MarketPl
if pc is None or not (pc.features or {}).get("market"): if pc is None or not (pc.features or {}).get("market"):
raise MarketError("Market feature is not enabled for this page. Enable it in page settings first.") raise MarketError("Market feature is not enabled for this page. Enable it in page settings first.")
# Look for existing (including soft-deleted) try:
existing = (await sess.execute( return await services.market.create_marketplace(sess, "page", post_id, name, slug)
select(MarketPlace).where(MarketPlace.container_type == "page", MarketPlace.container_id == post_id, MarketPlace.slug == slug) except ValueError as e:
)).scalar_one_or_none() raise MarketError(str(e)) from e
if existing:
if existing.deleted_at is not None:
existing.deleted_at = None # revive
existing.name = name
await sess.flush()
await attach_child(sess, "page", post_id, "market", existing.id)
return existing
raise MarketError(f'Market with slug "{slug}" already exists for this page.')
market = MarketPlace(container_type="page", container_id=post_id, name=name, slug=slug)
sess.add(market)
await sess.flush()
await attach_child(sess, "page", post_id, "market", market.id)
return market
async def soft_delete_market(sess: AsyncSession, post_slug: str, market_slug: str) -> bool: async def soft_delete_market(sess: AsyncSession, post_slug: str, market_slug: str) -> bool:
@@ -75,22 +58,4 @@ async def soft_delete_market(sess: AsyncSession, post_slug: str, market_slug: st
if not post: if not post:
return False return False
market = ( return await services.market.soft_delete_marketplace(sess, "page", post.id, market_slug)
await sess.execute(
select(MarketPlace)
.where(
MarketPlace.container_type == "page",
MarketPlace.container_id == post.id,
MarketPlace.slug == market_slug,
MarketPlace.deleted_at.is_(None),
)
)
).scalar_one_or_none()
if not market:
return False
market.deleted_at = utcnow()
await sess.flush()
await detach_child(sess, "page", market.container_id, "market", market.id)
return True

2
shared

Submodule shared updated: 9cba422aa9...b3a0e9922a