84 lines
3.3 KiB
Python
84 lines
3.3 KiB
Python
"""
|
|
@service StorefrontService (Backend/app/services/StorefrontService.py)
|
|
@purpose Domain service handling business logic, layout assembly, review moderation workflows, and cache invalidation.
|
|
"""
|
|
from sqlalchemy.orm import Session
|
|
from typing import List, Dict, Any, Optional
|
|
import ulid
|
|
|
|
from app.repositories.StorefrontRepository import StorefrontRepository
|
|
from app.models.StorefrontContentModel import StorefrontContent, ContentStatusEnum
|
|
from app.models.ProductReviewModel import ProductReview
|
|
|
|
# In-Memory Cache Store for high performance
|
|
_IN_MEMORY_CACHE: Dict[str, Any] = {}
|
|
|
|
class StorefrontService:
|
|
def __init__(self, db: Session):
|
|
self.repo = StorefrontRepository(db)
|
|
|
|
def get_layout(self, page: str, region: Optional[str] = None) -> List[Dict[str, Any]]:
|
|
# No in-memory cache here — layout changes via admin must reflect immediately
|
|
contents = self.repo.get_active_content(page, region)
|
|
result = [
|
|
{
|
|
"content_id": c.content_id,
|
|
"page": c.page,
|
|
"region": c.region,
|
|
"type": c.type,
|
|
"title": c.title,
|
|
"subtitle": c.subtitle,
|
|
"image_url": c.image_url,
|
|
"button_text": c.button_text,
|
|
"button_url": c.button_url,
|
|
"display_order": c.display_order,
|
|
# Expose under both keys so frontend works regardless of which it checks
|
|
"metadata": c.metadata_json or {},
|
|
"metadata_json": c.metadata_json or {}
|
|
}
|
|
for c in contents
|
|
]
|
|
return result
|
|
|
|
def invalidate_cache(self, pattern: Optional[str] = None):
|
|
global _IN_MEMORY_CACHE
|
|
if pattern:
|
|
_IN_MEMORY_CACHE = {k: v for k, v in _IN_MEMORY_CACHE.items() if not k.startswith(pattern)}
|
|
else:
|
|
_IN_MEMORY_CACHE.clear()
|
|
|
|
def get_reviews(self, product_id: str) -> List[Dict[str, Any]]:
|
|
cache_key = f"reviews:{product_id}"
|
|
if cache_key in _IN_MEMORY_CACHE:
|
|
return _IN_MEMORY_CACHE[cache_key]
|
|
|
|
reviews = self.repo.get_approved_reviews(product_id)
|
|
result = [
|
|
{
|
|
"review_id": r.review_id,
|
|
"product_id": r.product_id,
|
|
"author_name": r.author_name,
|
|
"rating": r.rating,
|
|
"title": r.title,
|
|
"comment": r.comment,
|
|
"verified_buyer": r.verified_purchase,
|
|
"helpful_count": r.helpful_count,
|
|
"admin_reply": r.admin_reply,
|
|
"review_date": r.created_at.strftime("%Y-%m-%d") if r.created_at else "2026-07-25",
|
|
"images": [img.image_url for img in r.images if img.is_approved] if r.images else []
|
|
}
|
|
for r in reviews
|
|
]
|
|
|
|
_IN_MEMORY_CACHE[cache_key] = result
|
|
return result
|
|
|
|
def get_public_settings(self, group: Optional[str] = None) -> Dict[str, Any]:
|
|
cache_key = f"settings:public:{group or 'all'}"
|
|
if cache_key in _IN_MEMORY_CACHE:
|
|
return _IN_MEMORY_CACHE[cache_key]
|
|
|
|
settings = self.repo.get_public_settings(group)
|
|
result = {s.setting_key: s.setting_value for s in settings}
|
|
_IN_MEMORY_CACHE[cache_key] = result
|
|
return result
|