"""Highlight Model. Model representing marketing highlight metadata. """ from oto import response from oto import status import sqlalchemy from marketing.connectors import mysql from marketing.models import entities from marketing.models import pagination from marketing.models import validators from marketing.utils import json DRAFT_VALIDATOR = json.create_draft_validator_from_model('highlight') CLIENTS, SCOPES, ATTACHMENT, ENTITY_TYPES = json.get_enums_from_draft( DRAFT_VALIDATOR, 'client', 'scope', 'attachment', 'entity') NORMALIZED_ENTITY_TYPES = {'product': 'release'} GET_OPERATION_REQUIRED_FIELDS = ['entity', 'entity_id'] GET_BY_ID_OPERATION_REQUIRED_FIELDS = ['highlight_id'] CREATE_OPERATION_REQUIRED_FIELDS = [ 'mkt_program_id', 'entity', 'entity_id', 'subject', 'description', 'scope', 'client', 'attachment'] UPDATE_OPERATION_REQUIRED_FIELDS = [ 'highlight_id'] UPDATE_OPERATION_EXCLUDED_FIELDS = [ 'mkt_program_id', 'entity', 'entity_id', 'client', 'attachment'] class Highlight(mysql.BaseModel): """Highlight Model.""" __tablename__ = 'mkt_program_info' highlight_id = sqlalchemy.Column( 'mkt_program_info_id', sqlalchemy.Integer, primary_key=True, autoincrement=True) mkt_program_id = sqlalchemy.Column(sqlalchemy.Integer) entity = sqlalchemy.Column('info_for', sqlalchemy.Enum(*ENTITY_TYPES)) entity_id = sqlalchemy.Column('info_for_id', sqlalchemy.BigInteger) subject = sqlalchemy.Column(sqlalchemy.VARCHAR(255)) description = sqlalchemy.Column(sqlalchemy.Text) attachment = sqlalchemy.Column(sqlalchemy.Enum(*ATTACHMENT)) scope = sqlalchemy.Column(sqlalchemy.Enum(*SCOPES)) client = sqlalchemy.Column(sqlalchemy.Enum(*CLIENTS)) date_added = sqlalchemy.Column( sqlalchemy.DateTime, default=sqlalchemy.func.now()) last_updated = sqlalchemy.Column( sqlalchemy.DateTime, onupdate=sqlalchemy.func.now()) def to_dict(self): """Create a dictionary representation of the object. Note: this dictionary does not return the dates (date_added and last_updated). If you need to return the dates, make sure you cast them into a ISO-8601, and if possible, UTC. Returns: dict: the representation of the object. """ return { 'highlight_id': self.highlight_id, 'mkt_program_id': self.mkt_program_id, 'entity': self.entity, 'entity_id': self.entity_id, 'subject': self.subject, 'description': self.description, 'attachment': self.attachment, 'scope': self.scope, 'client': self.client } DEFAULT_FIELDS = ( Highlight.highlight_id, Highlight.mkt_program_id, Highlight.entity, Highlight.entity_id, Highlight.subject, Highlight.description, Highlight.attachment, Highlight.date_added, Highlight.last_updated, Highlight.scope, Highlight.client) DEFAULT_PAGE_LIMIT = 50 @mysql.autosession() def get_marketing_highlights( entity, entity_id, session, client=None, offset=None, limit=None, mkt_program_id=None): """Fetch a paginated list of marketing highlight records. Args: entity (str): Describes whether marketing highlight is for a vendor, artist, release or track. entity_id (int): Unique identifier for the given entity. session (Session): the mysql session. client (str): Describes whether records added/updated from oa or alw. offset (int): record index used to start limit (int): number of records to fetch Returns: response.Response: object containing paginated result set if available else not found response. """ data = { 'entity': entities.get_normalized_entity_type(entity), 'entity_id': entity_id, 'offset': offset or 0, 'limit': limit or DEFAULT_PAGE_LIMIT } if client: data.update(client=client) validation = validators.validate( DRAFT_VALIDATOR, data=data, required_fields=GET_OPERATION_REQUIRED_FIELDS, new_fields=pagination.PAGINATION_VALIDATOR_PROPERTIES) if not validation: return validation data = validation.message conditions = [ Highlight.entity == data.get('entity'), Highlight.entity_id == data.get('entity_id')] if mkt_program_id: conditions.append(Highlight.mkt_program_id == mkt_program_id) if data.get('client'): conditions.append(Highlight.client == data.get('client')) query = session.query(*DEFAULT_FIELDS).filter(*conditions) total = query.count() results = query.offset(data.get('offset')).limit(data.get('limit')) highlights = [Highlight(**row._asdict()).to_dict() for row in results] if highlights: return response.Response({ 'items': highlights, 'pagination': { 'type': 'standard', 'offset': data.get('offset'), 'limit': data.get('limit'), 'total_records': total } }) return response.create_not_found_response() @mysql.autosession() def create_marketing_highlight(session, **data): """Create a marketing highlight from user data. Args: session (Session): the mysql session. data (dict): a dictionary that represents what the user has entered. Returns: Response: result of the create operation, contains the highlight information if successful. """ data = data or {} if 'entity' in data: data.update( entity=entities.get_normalized_entity_type(data.get('entity'))) validation = validators.validate( DRAFT_VALIDATOR, data=data, excluded_fields=['highlight_id'], required_fields=CREATE_OPERATION_REQUIRED_FIELDS) if not validation: return validation highlight_data = validation.message highlight = Highlight(**highlight_data) session.add(highlight) session.commit() return response.Response(highlight.to_dict(), status=status.CREATED) @mysql.autosession() def get_marketing_highlight_by_id(highlight_id, session): """Get a single marketing highlight. Args: highlight_id (int): the marketing highlight id. session (Session): the mysql session. Returns: Response: contains the marketing highlight information or errors otherwise. """ highlight = _get_highlight_by_id(highlight_id, session) if not highlight: return highlight return response.Response(highlight.to_dict()) @mysql.autosession() def update_marketing_highlight(highlight_id, session, **data): """Update a marketing highlight. Args: highlight_id (str, int): the highlight id. session (Sesssion): the mysql session. data (dict): a dictionary that represents what the user has entered. Returns: Response: result of the create operation, contains the highlight information if successful. """ data.update(highlight_id=highlight_id) validation = validators.validate( DRAFT_VALIDATOR, data, required_fields=UPDATE_OPERATION_REQUIRED_FIELDS, excluded_fields=UPDATE_OPERATION_EXCLUDED_FIELDS) if not validation: return validation elif not validation.message: return response.Response() data = validation.message highlight = _get_highlight_by_id(data.pop('highlight_id'), session) if not highlight: return highlight for field_name, field_data in data.items(): setattr(highlight, field_name, field_data) session.commit() return response.Response(highlight.to_dict(), status=status.OK) @mysql.autosession() def delete_marketing_highlight(highlight_id, session): """Delete a marketing highlight id. Args: highlight_id (int): the highlight id. session (Session): the sql alchemy session. Returns: Response: result of the delete operation. """ highlight = _get_highlight_by_id(highlight_id, session) if not highlight: return highlight session.delete(highlight) session.commit() return response.Response() @mysql.autosession() def table_health_check(session): """Health check: if the microservice can access the table. Args: session (Session): the sql alchemy session. Returns: Response: the health check status. """ query = 'SELECT * FROM {} LIMIT 1'.format(Highlight.__tablename__) session.execute(query) return response.Response( message={ Highlight.__tablename__: 'ok' }) def _get_highlight_by_id(highlight_id, session): """Get highlight by its id. Args: highlight_id (int): the id of the highlight. session (Session): the current active session. Returns: mixed: the highlight object if found otherwise response (either empty or with errors from the validation). """ validation = validators.validate( DRAFT_VALIDATOR, {'highlight_id': highlight_id}, required_fields=GET_BY_ID_OPERATION_REQUIRED_FIELDS) if not validation: return validation highlight = session.query(Highlight).get(highlight_id) return highlight or response.create_not_found_response() @mysql.autosession() def delete_highlight_by_entity(entity_id, entity_type, session): """Delete a marketing highlight by release id. Args: entity_id (str): Unique identifier for the given entity. entity_type (str): Describes whether marketing highlight is for a vendor, artist, release or track. session (Session): database session. Returns: Response: result of the delete query """ delete_query = sqlalchemy.delete(Highlight). \ where(Highlight.entity == entity_type). \ where(Highlight.entity_id == entity_id) session.execute(delete_query) return response.Response(message={'status': 'ok'}, status=200)