byceps/byceps

View on GitHub
byceps/services/shop/catalog/dbmodels.py

Summary

Maintainability
A
0 mins
Test Coverage
B
80%
"""
byceps.services.shop.catalog.dbmodels
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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

from sqlalchemy.ext.orderinglist import ordering_list
from sqlalchemy.orm import Mapped, mapped_column, relationship

from byceps.database import db
from byceps.services.shop.article.models import ArticleID
from byceps.services.shop.shop.models import ShopID
from byceps.util.instances import ReprBuilder
from byceps.util.uuid import generate_uuid7

from .models import CatalogArticleID, CatalogID, CollectionID


class DbCatalog(db.Model):
    """A catalog to offer articles."""

    __tablename__ = 'shop_catalogs'

    id: Mapped[CatalogID] = mapped_column(
        db.Uuid, default=generate_uuid7, primary_key=True
    )
    shop_id: Mapped[ShopID] = mapped_column(
        db.UnicodeText, db.ForeignKey('shops.id'), index=True
    )
    title: Mapped[str] = mapped_column(db.UnicodeText, unique=True)

    def __init__(self, shop_id: ShopID, title: str) -> None:
        self.shop_id = shop_id
        self.title = title

    def __repr__(self) -> str:
        return ReprBuilder(self).add_with_lookup('id').build()


class DbCollection(db.Model):
    """A group of articles inside of catalog."""

    __tablename__ = 'shop_catalog_collections'
    __table_args__ = (db.UniqueConstraint('catalog_id', 'title'),)

    id: Mapped[CollectionID] = mapped_column(
        db.Uuid, default=generate_uuid7, primary_key=True
    )
    catalog_id: Mapped[CatalogID] = mapped_column(
        db.Uuid, db.ForeignKey('shop_catalogs.id'), index=True
    )
    title: Mapped[str] = mapped_column(db.UnicodeText)
    position: Mapped[int] = mapped_column(db.Integer)

    catalog: Mapped[DbCatalog] = relationship(
        DbCatalog,
        backref=db.backref(
            'collections',
            order_by=position,
            collection_class=ordering_list('position', count_from=1),
        ),
    )

    def __init__(self, catalog_id: CatalogID, title: str) -> None:
        self.catalog_id = catalog_id
        self.title = title

    def __repr__(self) -> str:
        return (
            ReprBuilder(self)
            .add_with_lookup('catalog_id')
            .add_with_lookup('title')
            .build()
        )


class DbCatalogArticle(db.Model):
    """The assignment of an article to a collection."""

    __tablename__ = 'shop_catalog_articles'
    __table_args__ = (db.UniqueConstraint('collection_id', 'article_id'),)

    id: Mapped[CatalogArticleID] = mapped_column(
        db.Uuid, default=generate_uuid7, primary_key=True
    )
    collection_id: Mapped[CollectionID] = mapped_column(
        db.Uuid,
        db.ForeignKey('shop_catalog_collections.id'),
        index=True,
        nullable=False,
    )
    article_id: Mapped[ArticleID] = mapped_column(
        db.Uuid, db.ForeignKey('shop_articles.id'), index=True
    )
    position: Mapped[int] = mapped_column(db.Integer)

    collection: Mapped[DbCollection] = relationship(
        DbCollection,
        backref=db.backref(
            'catalog_articles',
            order_by=position,
            collection_class=ordering_list('position', count_from=1),
        ),
    )

    def __init__(
        self, collection_id: CollectionID, article_id: ArticleID
    ) -> None:
        self.collection_id = collection_id
        self.article_id = article_id