feat: custom newsletter slug

This commit is contained in:
Leon
2025-07-24 13:20:22 +02:00
parent f78607f506
commit 24e65a8c86
19 changed files with 386 additions and 68 deletions

View File

@@ -1,5 +1,5 @@
from nanoid import generate
from sqlalchemy import func
from sqlalchemy import func, or_
from sqlalchemy.orm import Session
from app.core.logging import get_logger
@@ -10,13 +10,13 @@ from app.schemas.newsletters import NewsletterCreate, NewsletterUpdate
logger = get_logger(__name__)
def get_newsletter(db: Session, newsletter_id: str):
"""Retrieve a single newsletter by its ID."""
logger.debug(f"Querying for newsletter with id={newsletter_id}")
def get_newsletter_by_identifier(db: Session, identifier: str):
"""Retrieve a single newsletter by its ID or slug."""
logger.debug(f"Querying for newsletter with identifier={identifier}")
result = (
db.query(Newsletter, func.count(Entry.id))
.outerjoin(Entry, Newsletter.id == Entry.newsletter_id)
.filter(Newsletter.id == newsletter_id)
.filter(or_(Newsletter.id == identifier, Newsletter.slug == identifier))
.group_by(Newsletter.id)
.first()
)
@@ -27,6 +27,11 @@ def get_newsletter(db: Session, newsletter_id: str):
return None
def get_newsletter_by_slug(db: Session, slug: str):
"""Retrieve a newsletter by its slug."""
return db.query(Newsletter).filter(Newsletter.slug == slug).first()
def get_newsletters(db: Session, skip: int = 0, limit: int = 100):
"""Retrieve a list of newsletters."""
logger.debug(f"Querying for newsletters with skip={skip}, limit={limit}")
@@ -51,9 +56,14 @@ def get_newsletters(db: Session, skip: int = 0, limit: int = 100):
def create_newsletter(db: Session, newsletter: NewsletterCreate):
"""Create a new newsletter."""
logger.info(f"Creating new newsletter with name '{newsletter.name}'")
if newsletter.slug and get_newsletter_by_slug(db, newsletter.slug):
return None # Indicates a conflict
db_newsletter = Newsletter(
id=generate(size=10),
name=newsletter.name,
slug=newsletter.slug,
extract_content=newsletter.extract_content,
move_to_folder=newsletter.move_to_folder,
)
@@ -82,9 +92,16 @@ def update_newsletter(
if not db_newsletter:
return None
db_newsletter.name = newsletter_update.name
db_newsletter.move_to_folder = newsletter_update.move_to_folder
db_newsletter.extract_content = newsletter_update.extract_content
if newsletter_update.slug:
existing_newsletter = get_newsletter_by_slug(db, newsletter_update.slug)
if existing_newsletter and existing_newsletter.id != newsletter_id:
return "conflict" # Indicates a conflict
update_data = newsletter_update.model_dump(exclude_unset=True)
for key, value in update_data.items():
if key == "sender_emails":
continue
setattr(db_newsletter, key, value)
# More efficient sender update
existing_emails = {sender.email for sender in db_newsletter.senders}
@@ -107,13 +124,13 @@ def update_newsletter(
db.refresh(db_newsletter)
logger.info(f"Successfully updated newsletter with id={db_newsletter.id}")
return get_newsletter(db, newsletter_id)
return get_newsletter_by_identifier(db, newsletter_id)
def delete_newsletter(db: Session, newsletter_id: str):
"""Delete a newsletter by its ID."""
logger.info(f"Deleting newsletter with id={newsletter_id}")
db_newsletter = get_newsletter(db, newsletter_id)
db_newsletter = get_newsletter_by_identifier(db, newsletter_id)
if not db_newsletter:
return None