"""Canned Response model.""" from datetime import datetime, timezone from owsresponse import status as owsresponse_status from sqlalchemy.orm import joinedload, relationship from product_review.api import db from product_review.constants.error import ( ERROR_CODE_CANNED_RESPONSE_NOT_CREATED, ERROR_CODE_NOT_FOUND, ERROR_MESSAGE_DUPLICATE_CANNED_RESPONSE, ERROR_MESSAGE_NOT_FOUND, ) from product_review.models import ( canned_response_category as canned_response_category_model, ) from product_review.models import canned_response_note as canned_response_note_model from product_review.util.exception import raise_exception_for_ows_response DEFAULT_PAGE_LIMIT = 10 class CannedResponse(db.Model): """Canned Response model.""" __tablename__ = "canned_response" canned_response_id = db.Column( "id", db.Integer, primary_key=True, autoincrement=True, nullable=False ) category_id = db.Column( db.Integer, db.ForeignKey("canned_response_category.id"), nullable=False ) keyword = db.Column(db.String(255), nullable=False) review_context = db.Column(db.Enum("approval", "rejection"), nullable=False) modified_by_user_id = db.Column(db.String(36), nullable=False) for_deletion = db.Column( db.Boolean(create_constraint=True, name="ck_canned_response_for_deletion"), default=0, ) last_updated = db.Column( db.DateTime, nullable=False, server_default=db.func.current_timestamp(), ) canned_response_notes = relationship( "CannedResponseNote", foreign_keys=[canned_response_note_model.CannedResponseNote.canned_response_id], primaryjoin="CannedResponse.canned_response_id==CannedResponseNote.canned_response_id", # noqa: E501 uselist=True, lazy="select", ) canned_response_category = relationship( "CannedResponseCategory", foreign_keys=[ canned_response_category_model.CannedResponseCategory.category_id ], primaryjoin="CannedResponse.category_id==CannedResponseCategory.category_id", uselist=False, lazy="select", ) def to_dict(self, include_note_for_language=None): """Convert the CannedResponse object to a dictionary representation.""" item = {} for c in self.__table__.columns: if c.name == "category_id": continue column_name = "canned_response_id" if c.name == "id" else c.name item[column_name] = getattr(self, column_name) item["canned_response_category"] = self.canned_response_category.to_dict() item["language_codes"] = [ note.language_code for note in self.canned_response_notes ] if include_note_for_language: try: item["note"] = ( list( filter( lambda x: x.language_code == include_note_for_language, self.canned_response_notes, ) ) .pop() .to_dict() ) except IndexError: item["note"] = None return item def get_items( category_id=None, modified_by_user_id=None, review_context=None, language_code=None, page_limit=None, page_offset=None, ): """Return list of items.""" offset = int(page_offset or 0) limit = int(page_limit or DEFAULT_PAGE_LIMIT) canned_response_query = db.session.query(CannedResponse).filter( CannedResponse.for_deletion == False # noqa: E712 ) if category_id: canned_response_query = ( canned_response_query.options( joinedload(CannedResponse.canned_response_category) ) .join(CannedResponse.canned_response_category, isouter=True) .filter(CannedResponse.category_id == category_id) ) if modified_by_user_id: canned_response_query = canned_response_query.filter( CannedResponse.modified_by_user_id == modified_by_user_id ) if review_context: canned_response_query = canned_response_query.filter( CannedResponse.review_context == review_context ) if language_code: canned_response_query = ( canned_response_query.options( joinedload(CannedResponse.canned_response_notes) ) .join(CannedResponse.canned_response_notes, isouter=True) .filter( canned_response_note_model.CannedResponseNote.language_code == language_code ) ) total_records = canned_response_query.count() if page_limit is None and page_offset is None: result = canned_response_query.order_by( CannedResponse.last_updated.desc() ).all() else: result = ( canned_response_query.order_by(CannedResponse.last_updated.desc()) .limit(limit) .offset(offset) .all() ) return result, total_records def get_canned_response_item(canned_response_id, language_code=None): """Get a single canned response item.""" canned_response_query = db.session.query(CannedResponse).filter( CannedResponse.canned_response_id == canned_response_id ) if language_code: canned_response_query = ( canned_response_query.options( joinedload(CannedResponse.canned_response_notes) ) .join(CannedResponse.canned_response_notes, isouter=True) .filter( canned_response_note_model.CannedResponseNote.language_code == language_code ) ) item = canned_response_query.first() if not item: raise_exception_for_ows_response( status=owsresponse_status.NOT_FOUND, code=ERROR_CODE_NOT_FOUND, message=ERROR_MESSAGE_NOT_FOUND, ) return item.to_dict(include_note_for_language=language_code) def create_canned_response( category_id, keyword, review_context, modified_by_user_id, last_updated=None ): """Add a record to canned_response table.""" existing_item = ( db.session.query(CannedResponse) .filter(CannedResponse.keyword == keyword) .filter(CannedResponse.category_id == category_id) .first() ) if existing_item: raise_exception_for_ows_response( status=owsresponse_status.BAD_REQUEST, code=ERROR_CODE_CANNED_RESPONSE_NOT_CREATED, message=ERROR_MESSAGE_DUPLICATE_CANNED_RESPONSE, ) new_entry = CannedResponse( category_id=category_id, keyword=keyword, review_context=review_context, modified_by_user_id=modified_by_user_id, last_updated=last_updated or datetime.now(timezone.utc), ) db.session.add(new_entry) return new_entry def update_canned_response(canned_response_id, modified_by_user_id, for_deletion=None): """Update a record in canned_response table.""" entry = db.session.get(CannedResponse, canned_response_id) if not entry: raise_exception_for_ows_response( status=owsresponse_status.NOT_FOUND, code=ERROR_CODE_NOT_FOUND, message=ERROR_MESSAGE_NOT_FOUND, ) entry.modified_by_user_id = modified_by_user_id entry.last_updated = datetime.now(timezone.utc) if for_deletion is not None: entry.for_deletion = for_deletion return entry.to_dict()