"""Model and functions to work with product data.""" from oto import response from sqlalchemy import BigInteger from sqlalchemy import Column from sqlalchemy import Enum from sqlalchemy import String from sqlalchemy import UniqueConstraint from sqlalchemy.dialects import mysql from availability.connectors import sql from availability.constants import error from availability.constants import field_const from availability.constants import models from availability.models import error_handlers class Product(sql.BaseModel): """Class representing the product table.""" __tablename__ = models.PRODUCT_TABLE __table_args__ = ( UniqueConstraint( 'provider', 'itunes_vendor_id', name='unique_itunes_id_within_provider'),) # product_id matches the value from art_relations.releases.release_id product_id = Column( mysql.INTEGER(unsigned=True), primary_key=True, autoincrement=False) orchard_product_id = Column(BigInteger, unique=True, nullable=False) upc = Column(String(14), index=True, nullable=False) itunes_vendor_id = Column(String(25), nullable=True) provider = Column(Enum(*models.PROVIDERS_ENUM), default=models.ORCHARD) def as_dict(self): """Return dictionary representation of the product data. Returns: dict: Product fields. """ return { field_const.PRODUCT_ID: self.product_id, field_const.ORCHARD_PRODUCT_ID: self.orchard_product_id, field_const.UPC: self.upc, field_const.ITUNES_VENDOR_ID: self.itunes_vendor_id, field_const.PROVIDER: self.provider, } @error_handlers.sqlalchemy_error_handler @error_handlers.integrity_error_handler( error_code=error.ERROR_CODE_MODEL_VALIDATION) def create_product( product_id, orchard_product_id, upc, itunes_vendor_id=None, provider=models.ORCHARD): """Create a new record in the product table. Args: product_id (int): Product PK. orchard_product_id (int): The Orchard's unique product ID. upc (str): The Universal Product Code. itunes_vendor_id (str): Vendor-specific product ID in iTunes. provider (str): One of models.PROVIDERS_ENUM. Returns: response.Response: Product.as_dict() or error in message attribute. """ product = get_product_by_id(product_id) if product: return product product = Product( product_id=product_id, orchard_product_id=orchard_product_id, upc=upc, itunes_vendor_id=itunes_vendor_id, provider=provider) if not itunes_vendor_id: product.itunes_vendor_id = upc with sql.session_scope() as session: session.add(product) return response.Response(product.as_dict()) @error_handlers.sqlalchemy_error_handler def get_product_by_id(product_id): """Get product data from db by product id. Args: product_id (int): Product PK. Returns: response.Response: Product.as_dict() or error in message attribute. """ with sql.session_scope() as session: product = session.query(Product).filter_by( product_id=product_id).first() if not product: return response.create_not_found_response( error.ERROR_MESSAGE_RELEASE_NOT_FOUND) return response.Response(product.as_dict())