"""ProductReviewStatus.""" import datetime from oto import response from sqlalchemy import Column from sqlalchemy import DateTime from sqlalchemy import desc from sqlalchemy import ForeignKey from sqlalchemy import Integer from content_review.connectors import mysql from content_review.constants import mysql as mysql_const from content_review.constants import pagination from content_review.models import product_review_status_history as prsh from content_review.models import review_status_type as rst_model class ProductReviewStatus(mysql.BaseModel): """ProductReviewStatus Model.""" __tablename__ = 'product_review_status' product_review_status_id = Column( 'id', Integer, primary_key=True, key='product_review_status_id') product_id = Column('product_id', Integer, index=True) review_type_id = Column( 'review_type_id', Integer, ForeignKey('review_type.id'), index=True) review_status_type_id = Column( 'review_status_type_id', Integer, ForeignKey('review_status_type.id'), index=True) created_timestamp = Column('created_timestamp', DateTime) updated_timestamp = Column('updated_timestamp', DateTime) DEFAULT_FIELDS = { ProductReviewStatus.product_review_status_id, ProductReviewStatus.product_id, ProductReviewStatus.review_type_id, ProductReviewStatus.review_status_type_id, ProductReviewStatus.created_timestamp, ProductReviewStatus.updated_timestamp } def get_products_status_review(product_list): """Get review for product_id. Args: product_list (list): The product id. Returns: response.Response: contain 201 for created resource. """ with mysql.db_session() as session: rows = session.query(*DEFAULT_FIELDS).filter( ProductReviewStatus.product_id.in_(product_list) ).all() if rows: response_data = [] for row in rows: response_data.append({ 'product_review_status_id': row.product_review_status_id, 'product_id': row.product_id, 'review_type_id': row.review_type_id, 'review_status_type_id': row.review_status_type_id, 'created_timestamp': row.created_timestamp.strftime( mysql_const.DATE_TIME_FORMAT ), 'updated_timestamp': row.updated_timestamp.strftime( mysql_const.DATE_TIME_FORMAT ) if row.updated_timestamp else None }) return response.Response(response_data) return response.create_not_found_response() def get_product_status_review_history( product_id, page_offset=None, page_limit=None): """Get review history for product_id. Args: product_id (int): The product id. page_offset (int): offset to use for pagination. page_limit (int): max number of items per page. Returns: response.Response: contain 200 for resource found. """ page_offset = int(page_offset or 0) page_limit = int(page_limit or pagination.PAGE_LIMIT_DEFAULT) with mysql.db_session() as session: rst_value = rst_model.get_status_types(flipped_dict=True) rst_value_reversed = {v: k for k, v in rst_value.message.items()} rows = [] total_records = 0 current_product_query = session.query( ProductReviewStatus.product_id, ProductReviewStatus.review_status_type_id, ProductReviewStatus.updated_timestamp .label('review_timestamp'), ProductReviewStatus.created_timestamp ).filter( ProductReviewStatus.product_id == product_id ).order_by(desc(ProductReviewStatus.created_timestamp)) total_records += current_product_query.count() history_query = session.query( prsh.ProductReviewStatusHistory.product_id, prsh.ProductReviewStatusHistory.review_status_type_id, prsh.ProductReviewStatusHistory.review_timestamp, prsh.ProductReviewStatusHistory.created_timestamp, ).filter( prsh.ProductReviewStatusHistory.product_id == product_id, ).order_by( desc(prsh.ProductReviewStatusHistory.created_timestamp) ) sql_history_limit = page_limit - total_records if page_offset >= 1 and page_limit == 1: sql_history_limit = page_limit sql_history_offset = page_offset if (page_offset == 0 and page_limit > 1) or page_offset > 0: sql_history_offset = page_offset - total_records total_records += history_query.count() if page_limit > 0: if page_offset == 0: rows.extend(current_product_query.all()) rows.extend( history_query.offset(max(sql_history_offset, 0)).limit( sql_history_limit ).all() ) if rows: response_data = [] for row in rows: if row.review_timestamp: review_timestamp = row.review_timestamp.strftime( mysql_const.DATE_TIME_FORMAT ) else: review_timestamp = row.created_timestamp.strftime( mysql_const.DATE_TIME_FORMAT ) response_data.append({ 'product_id': row.product_id, 'review_status': rst_value_reversed.get( row.review_status_type_id), 'review_timestamp': review_timestamp, 'created_timestamp': row.created_timestamp.strftime( mysql_const.DATE_TIME_FORMAT) }) response_body = { 'items': response_data, 'pagination': { 'type': 'standard', 'offset': page_offset, 'limit': page_limit, 'total_records': total_records } } return response.Response(response_body) return response.create_not_found_response() def create_product_status_review( product_list, review_type_id, review_status_type_id): """Create new review. Args: product_list (list): The product id. review_type_id (int): References the review_type. review_status_type_id (int): References the review_status_type Returns: response.Response: respond with success or failure """ with mysql.db_session() as session: existing_products = get_products_status_review(product_list) if existing_products: for item in existing_products.message: product_list.remove(item.get('product_id')) new_reviews = [] for product_id in product_list: new_reviews.append( ProductReviewStatus( product_id=product_id, review_type_id=review_type_id, review_status_type_id=review_status_type_id, created_timestamp=datetime.datetime.utcnow() ) ) session.bulk_save_objects(new_reviews) return response.Response( message={'processed_records': len(product_list)}, status=201) def update_product_status_review(review_type_id, update_list): """Create or update review. Args: review_type_id (int): The id of the review type. update_list (list): A list of objects to update. Returns: response.Response: respond with success or failure """ with mysql.db_session() as session: rst_value = rst_model.get_status_types(flipped_dict=True) product_id_list = [] list_of_products_by_id = {} for item in update_list: product_id_list.append(item.get('product_id')) list_of_products_by_id[item.get('product_id')] = item products_to_insert = list(product_id_list) products_to_update = get_products_status_review(product_id_list) if products_to_update.status == 200: response_body = products_to_update.message review_updates = [] review_history = [] for product in response_body: history_object = prsh.create_history_object( product_id=product.get('product_id'), review_type_id=product.get('review_type_id'), review_status_type_id=product.get('review_status_type_id'), created_timestamp=datetime.datetime.utcnow(), review_timestamp=datetime.datetime.strptime( product.get('created_timestamp'), mysql_const.DATE_TIME_FORMAT ) ) products_to_insert.remove(product.get('product_id')) get_record_from_request = list_of_products_by_id.get( product.get('product_id') ) new_review_status_id = rst_value.message.get( get_record_from_request.get('review_status') ) new_review_object = { 'product_review_status_id': product.get( 'product_review_status_id'), 'review_type_id': review_type_id, 'review_status_type_id': new_review_status_id, 'created_timestamp': datetime.datetime.strptime( get_record_from_request.get( 'review_timestamp' ), '%Y-%m-%d %H:%M:%S' ), 'updated_timestamp': datetime.datetime.utcnow() } review_history.append(history_object) review_updates.append(new_review_object) session.bulk_save_objects(review_history) session.bulk_update_mappings( ProductReviewStatus, review_updates) new_reviews = [] if products_to_insert: for product_id in products_to_insert: get_record_from_request = list_of_products_by_id.get( product_id ) new_review_status_id = rst_value.message.get( get_record_from_request.get('review_status') ) new_review = ProductReviewStatus( product_id=product_id, review_type_id=review_type_id, review_status_type_id=new_review_status_id, created_timestamp=datetime.datetime.utcnow() ) new_reviews.append(new_review) session.bulk_save_objects(new_reviews) return response.Response( message={'processed_records': len(product_id_list)}, status=201)