"""Score History model.""" from decimal import Decimal from datetime import datetime from owsresponse import status from product_review.api import db from product_review.models.review_queue import ReviewQueue from product_review.util import exception as exception_util from product_review.util.db import db_transaction class ScoreHistory(db.Model): """Score history model.""" __tablename__ = "score_history" score_history_id = db.Column( "id", db.Integer, primary_key=True, autoincrement=True, nullable=False ) review_queue_id = db.Column( db.Integer, db.ForeignKey("review_queue.id"), nullable=False ) created_datetime = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) validation_result = db.Column( db.Enum("PASS", "FAIL"), nullable=False ) failed_validations = db.Column(db.JSON, nullable=True) confidence_score = db.Column(db.Integer, nullable=True) score_reasoning = db.Column(db.JSON, nullable=True) auto_approved = db.Column(db.Boolean, nullable=True, default=False) score_version = db.Column(db.Numeric(3, 1), nullable=True) def to_dict(self): """Return a dictionary of output properties.""" items = {} for c in self.__table__.columns: column_name = "score_history_id" if c.name == "id" else c.name attr_value = getattr(self, column_name) items[column_name] = float(attr_value) if isinstance(attr_value, Decimal) else attr_value return items def delete(review_queue_id): """For integration testing purposes only, delete score history.""" ScoreHistory.query.filter(ScoreHistory.review_queue_id == review_queue_id).delete() def add_score(review_queue_id, validation_result, failed_validations, confidence_score, score_reasoning, auto_approved, score_version): """Add a score history record.""" exists = ReviewQueue.query.get(review_queue_id) if not exists: exception_util.raise_exception_for_ows_response( status=status.NOT_FOUND, code="not_found", message=f'Review queue item with id "{review_queue_id}" not found.', ) already_scored = ScoreHistory.query.filter( ScoreHistory.review_queue_id == review_queue_id, ScoreHistory.score_version == score_version ).first() if already_scored: exception_util.raise_exception_for_ows_response( status=status.CONFLICT, code="exists", message=f'There is already a score record for "review_queue_id: {review_queue_id}" and "score_version: {score_version}".', # noqa ) with db_transaction: db.session.add(ScoreHistory( review_queue_id=review_queue_id, validation_result=validation_result, failed_validations=failed_validations, confidence_score=confidence_score, score_reasoning=score_reasoning, score_version=score_version, auto_approved=auto_approved )) def get_score(review_queue_id): """Get the score entry with the latest score_version for the given review_queue_id.""" entry = ( db.session.query(ScoreHistory) .filter(ScoreHistory.review_queue_id == review_queue_id) .order_by(ScoreHistory.score_version.desc()) .first() ) if not entry: return None return entry.to_dict()