"""Product Physical Supply Chain Info Model.""" import datetime from oto import response from oto.response import create_error_response import sentry_sdk from sqlalchemy import Column from sqlalchemy import Enum from sqlalchemy import exc from sqlalchemy import Integer from sqlalchemy import null from sqlalchemy import String from ows_product_physical.connector import mysql from ows_product_physical.constant import error class ProductPhysicalSupplyChainInfo(mysql.BaseModel): """Product physical supply chain info model.""" __tablename__ = 'product_physical_supply_chain_info' product_physical_supply_chain_id = Column( 'id', Integer, primary_key=True, autoincrement=True, nullable=False) product_id = Column(Integer, nullable=False) returnability = Column(Enum('Y', 'N'), nullable=True) return_disposition = Column(Enum('Keep', 'Scrap'), nullable=True) store_id = Column(Integer, nullable=False) updated_date = Column(String, default=null) def to_dict(self): """Dict representation of a ProductPhysicalSupplyChainInfo row.""" return { 'id': self.product_physical_supply_chain_id, 'product_id': self.product_id, 'returnability': self.returnability, 'return_disposition': self.return_disposition, 'store_id': self.store_id, 'updated_date': self.updated_date } def get_product_physical_supply_chain_info(product_id): """Fetch product physical supply chain info by product id. Args: product_id (int): product id of existing product Returns: Response: A response object with existing data. """ with mysql.db_session() as session: try: product_physical_supply_chain_info = ( session.query( ProductPhysicalSupplyChainInfo. product_physical_supply_chain_id, ProductPhysicalSupplyChainInfo.product_id, ProductPhysicalSupplyChainInfo.returnability, ProductPhysicalSupplyChainInfo.return_disposition, ProductPhysicalSupplyChainInfo.store_id ).filter( ProductPhysicalSupplyChainInfo.product_id == product_id)) result = _map_product_physical_supply_chain_info( product_physical_supply_chain_info) return result except Exception as exception: sentry_sdk.capture_exception(exception) return response.create_error_response( code=error.INTERNAL_ERROR, message='mysql error', status=500) def _map_product_physical_supply_chain_info( product_physical_supply_chain_info): """Map results from product physical supply chain info to a dictionary. Args: product_physical_supply_chain_info (tuple): product physical supply chain info query result Returns: dict: with product physical supply chain info data. """ return [{ 'product_physical_supply_chain_id': product_physical_supply_chain_id, 'product_id': product_id, 'returnability': returnability, 'return_disposition': return_disposition, 'store_id': store_id } for product_physical_supply_chain_id, product_id, returnability, return_disposition, store_id in product_physical_supply_chain_info] def create(data): """Insert data in product_physical_supply_chain_info table. Args: data (list): list of supply chain data for physical product Response: Response: A response object with inserted data. """ product_physical_supply_chain_info = ProductPhysicalSupplyChainInfo(**data) with mysql.db_session() as session: try: session.add(product_physical_supply_chain_info) session.flush() except (exc.SQLAlchemyError, exc.DBAPIError) as exception: sentry_sdk.capture_exception(exception) return create_error_response( code=error.INTERNAL_ERROR, message='mysql error', status=500) return response.Response( message=product_physical_supply_chain_info.to_dict(), status=201) def get_product_supply_chain_info_by_product_store_id( product_id, store_id=None): """Fetch supply chain info by product and store id. Args: product_id (int): product id of existing product store_id (int): id of store Returns: Response: A response object with existing data. """ with mysql.db_session() as session: try: result = session.query(ProductPhysicalSupplyChainInfo)\ .filter_by(product_id=product_id, store_id=store_id).first() if not result: return response.Response( message=error.SUPPLY_CHAIN_INFO_EMPTY, status=404) supplychain_info = result.to_dict() return response.Response(message=supplychain_info, status=200) except Exception as exception: sentry_sdk.capture_exception(exception) return response.create_error_response( code=error.INTERNAL_ERROR, message='mysql error', status=500) def update_product_supply_chain_info_by_product_store_id( product_id, supplychain_info_data): """Update supply chain info by product and store id. Args: product_id (int): product id of existing product supplychain_info_data (list): list of records to be updated Returns: Response: A response of updated data. """ with mysql.db_session() as session: try: dafaults_data = [] for supplychain_data in supplychain_info_data: store_id = supplychain_data.get('store_id') supplychain_info = \ get_product_supply_chain_info_by_product_store_id( product_id, store_id) if supplychain_info.status != 200: return supplychain_info supplychain_data.update({ 'updated_date': datetime.datetime.now(datetime.UTC), 'product_id': product_id }) result = session.query(ProductPhysicalSupplyChainInfo)\ .filter_by(product_id=product_id, store_id=store_id)\ .update(supplychain_data) if result: supplychain_data.update({ 'id': supplychain_info.message.get('id'), 'updated_date': datetime.datetime.now( datetime.UTC).strftime('%Y-%m-%d') }) dafaults_data.append(supplychain_data) return response.Response(message=dafaults_data, status=200) except Exception as exception: sentry_sdk.capture_exception(exception) return response.create_error_response( code=error.INTERNAL_ERROR, message='mysql error', status=500) def set_supply_chain_info_by_product_id( product_id, supplychain_info): """Insert data in product_physical_supply_chain_info table. Args: data (list): list of supply chain data for physical product Response: Response: A response object with inserted data. """ with mysql.db_session() as session: try: data = [] for item in supplychain_info: item.update({ 'updated_date': datetime.datetime.now().strftime( '%Y-%m-%d %H:%M:%S'), 'product_id': product_id }) product_physical_supply_chain_info = \ ProductPhysicalSupplyChainInfo(**item) session.add(product_physical_supply_chain_info) session.flush() data.append( product_physical_supply_chain_info.to_dict()) return response.Response(message=data, status=201) except Exception as exception: sentry_sdk.capture_exception(exception) return response.create_error_response( code=error.INTERNAL_ERROR, message='mysql error', status=500)