byceps/byceps

View on GitHub
byceps/services/gallery/gallery_service.py

Summary

Maintainability
A
0 mins
Test Coverage
F
31%
"""
byceps.services.gallery.gallery_service
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:Copyright: 2014-2024 Jochen Kupperschmidt
:License: Revised BSD (see `LICENSE` file for details)
"""

from sqlalchemy import select

from byceps.database import db
from byceps.services.brand import brand_service
from byceps.services.brand.models import BrandID

from . import gallery_domain_service
from .dbmodels import DbGallery, DbGalleryImage
from .models import Gallery, GalleryID, GalleryImage, GalleryWithImages


# -------------------------------------------------------------------- #
# gallery


def create_gallery(
    brand_id: BrandID,
    slug: str,
    title: str,
    hidden: bool,
) -> Gallery:
    """Create a gallery."""
    db_brand = brand_service._find_db_brand(brand_id)
    if db_brand is None:
        raise ValueError(f'Unknown brand ID "{brand_id}"')

    gallery = gallery_domain_service.create_gallery(
        brand_id, slug, title, hidden
    )

    db_gallery = DbGallery(
        gallery.id,
        gallery.created_at,
        gallery.brand_id,
        gallery.slug,
        gallery.title,
        gallery.hidden,
    )
    db_brand.galleries.append(db_gallery)
    db.session.commit()

    return gallery


def find_gallery(gallery_id: GalleryID) -> Gallery | None:
    """Return the gallery, if found."""
    db_gallery = _find_db_gallery(gallery_id)

    if db_gallery is None:
        return None

    return _db_entity_to_gallery(db_gallery)


def _find_db_gallery(gallery_id: GalleryID) -> DbGallery | None:
    return db.session.get(DbGallery, gallery_id)


def _get_db_gallery(gallery_id: GalleryID) -> DbGallery:
    db_gallery = _find_db_gallery(gallery_id)

    if db_gallery is None:
        raise ValueError(f'Unknown gallery ID "{gallery_id}"')

    return db_gallery


def find_gallery_by_slug_with_images(
    brand_id: BrandID, slug: str
) -> GalleryWithImages | None:
    """Return the gallery of that brand and with that slug, if found,
    with images.
    """
    db_gallery = (
        db.session.scalars(
            select(DbGallery)
            .options(db.joinedload(DbGallery.images))
            .filter_by(brand_id=brand_id)
            .filter_by(slug=slug)
        )
        .unique()
        .one_or_none()
    )

    if db_gallery is None:
        return None

    return _db_entity_to_gallery_with_images(db_gallery)


def is_slug_available(brand_id: BrandID, slug: str) -> bool:
    """Check if the slug is yet unused."""
    return not db.session.scalar(
        select(
            db.exists()
            .where(DbGallery.brand_id == brand_id)
            .where(db.func.lower(DbGallery.slug) == slug.lower())
        )
    )


def get_galleries_for_brand(brand_id: BrandID) -> list[Gallery]:
    """Return all galeries for the brand."""
    db_galleries = (
        db.session.scalars(select(DbGallery).filter_by(brand_id=brand_id))
        .unique()
        .all()
    )

    return [_db_entity_to_gallery(db_gallery) for db_gallery in db_galleries]


def get_galleries_for_brand_with_images(
    brand_id: BrandID,
) -> list[GalleryWithImages]:
    """Return all galeries for the brand, with images."""
    db_galleries = (
        db.session.scalars(
            select(DbGallery)
            .options(db.joinedload(DbGallery.images))
            .filter(DbGallery.brand_id == brand_id)
        )
        .unique()
        .all()
    )

    return [
        _db_entity_to_gallery_with_images(db_gallery)
        for db_gallery in db_galleries
    ]


def _db_entity_to_gallery(db_gallery: DbGallery) -> Gallery:
    title_image = _find_title_image(db_gallery)

    return Gallery(
        id=db_gallery.id,
        created_at=db_gallery.created_at,
        brand_id=db_gallery.brand_id,
        position=db_gallery.position,
        slug=db_gallery.slug,
        title=db_gallery.title,
        title_image=title_image,
        hidden=db_gallery.hidden,
    )


def _db_entity_to_gallery_with_images(
    db_gallery: DbGallery,
) -> GalleryWithImages:
    title_image = _find_title_image(db_gallery)

    images = [
        _db_entity_to_image(db_image, db_gallery)
        for db_image in db_gallery.images
    ]
    images.sort(key=lambda image: image.position)

    return GalleryWithImages(
        id=db_gallery.id,
        created_at=db_gallery.created_at,
        brand_id=db_gallery.brand_id,
        position=db_gallery.position,
        slug=db_gallery.slug,
        title=db_gallery.title,
        title_image=title_image,
        hidden=db_gallery.hidden,
        images=images,
    )


# -------------------------------------------------------------------- #
# image


def create_image(
    gallery: Gallery,
    filename_full: str,
    filename_preview: str,
    *,
    caption: str | None = None,
    hidden: bool = False,
) -> GalleryImage:
    """Add an image to a gallery."""
    db_gallery = _get_db_gallery(gallery.id)

    image = gallery_domain_service.create_image(
        gallery, filename_full, filename_preview, caption, hidden
    )

    db_image = DbGalleryImage(
        image.id,
        image.created_at,
        image.gallery_id,
        image.filename_full,
        image.filename_preview,
        image.caption,
        image.hidden,
    )
    db_gallery.images.append(db_image)

    db.session.commit()

    return _db_entity_to_image(db_image, db_gallery)


def _db_entity_to_image(
    db_image: DbGalleryImage, db_gallery: DbGallery
) -> GalleryImage:
    return GalleryImage(
        id=db_image.id,
        created_at=db_image.created_at,
        brand_id=db_gallery.brand_id,
        gallery_id=db_image.gallery_id,
        gallery_slug=db_gallery.slug,
        position=db_image.position,
        filename_full=db_image.filename_full,
        filename_preview=db_image.filename_preview,
        caption=db_image.caption,
        hidden=db_image.hidden,
    )


def _find_title_image(db_gallery: DbGallery) -> GalleryImage | None:
    db_title_image = db_gallery.title_image
    if not db_title_image:
        return None

    return _db_entity_to_image(db_title_image, db_gallery)