import json from collections import OrderedDict from datetime import date from json import JSONDecodeError from typing import List, Tuple from apollo_main_db.apollo.models import NPSSurvey, NPSSurveyResult, NPSSurveyUser from src.db.base import session as db_session from src.legacy.apollo_api.constants import NPSResultStatus def get_active_user_survey(user_id: str, survey_id: int or None = None) -> NPSSurvey or None: """Returns active user survey and deactivate it if necessary. Args: user_id (str): User identifier. survey_id (int or None): Survey identifier. Returns: NPSSurvey or None: Active NPSSurvey model object if such exists. """ today = date.today() filters = [NPSSurvey.active.is_(True), NPSSurveyUser.user_id == user_id] if survey_id: filters.append(NPSSurvey.id == survey_id) active_survey = ( db_session.query(NPSSurvey) .join(NPSSurveyUser, NPSSurveyUser.survey_id == NPSSurvey.id) .filter(*filters) .first() ) if not active_survey: return if today < active_survey.start_date or today > active_survey.end_date: db_session.query(NPSSurvey).filter(NPSSurvey.id == active_survey.id).update({NPSSurvey.active: False}) db_session.commit() return return active_survey def get_survey_results(user_id: str, survey_id: int) -> NPSSurveyResult or None: """Returns survey result record for specified user. Args: user_id (str): User identifier. survey_id (int): Survey identifier. Returns: NPSSurveyResult or None: Survey result instance or none. """ survey_result = ( db_session.query(NPSSurveyResult) .filter(NPSSurveyResult.user_id == user_id, NPSSurveyResult.survey_id == survey_id) .first() ) return survey_result def save_or_update_result_record(data: dict, result_record: NPSSurveyResult or None = None) -> NPSSurveyResult: """Save new or update existing survey result record. Args: data (dict): Dictionary with a new survey result data. result_record (NPSSurveyResult or None): NPSSurveyResult object or None. Returns: NPSSurveyResult: New or updated NPSSurveyResult object. """ status = data["status"] if result_record: if status == NPSResultStatus.SKIPPED: result_record.skips_num += 1 for key, value in data.items(): setattr(result_record, key, value) else: skips_num = 1 if status == NPSResultStatus.SKIPPED else 0 result_record = NPSSurveyResult(skips_num=skips_num, **data) db_session.add(result_record) db_session.commit() return result_record def get_nps_result_records(survey_id: int) -> Tuple[NPSSurvey or None, List[dict] or None]: """ Args: survey_id (int): Survey identifier. Returns: Tuple[NPSSurvey, List[dict]]: Survey info and user results. """ nps_survey = db_session.query(NPSSurvey).filter(NPSSurvey.id == survey_id).first() if not nps_survey: return None, None nps_results = ( db_session.query( NPSSurveyResult.user_id.label("User Id"), NPSSurveyResult.email.label("Email"), NPSSurveyResult.name.label("Name"), NPSSurveyResult.answers, NPSSurveyResult.status, ) .filter(NPSSurveyResult.survey_id == survey_id) .group_by(NPSSurveyResult.user_id) .order_by(NPSSurveyResult.updated_at.desc()) ) questions_num, results = len(nps_survey.questions), [] for item in nps_results: dict_data = OrderedDict(item._asdict()) try: answers = json.loads(dict_data.pop("answers", None)) answers_map = {answer["step"]: answer["value"] for answer in answers} except (TypeError, JSONDecodeError): answers_map = {} for i in range(questions_num): step = i + 1 dict_data[f"Answer {step}"] = answers_map.get(step) dict_data["Status"] = NPSResultStatus.OUTPUT_MAP.get(dict_data.pop("status")) results.append(dict_data) return nps_survey, results