def handle_request_invoice(user_id, params): plan = params.get('plan', None) plan_from_db = db_session_users.query(Plan).filter_by( stripe_id=plan).first() if not plan_from_db: return 'Invalid plan' plan_name = plan_from_db.name plan_id = plan_from_db.id current_user = db_session_users.query(User).filter_by(id=user_id).first() message = current_user.first_name + ' ' + current_user.last_name + ' is requesting to pay by invoice for the ' + plan_name + ' subscription. ' + current_user.first_name + ', the team at Compliance.ai will respond to your request soon!' try: email_helper.send_email( '*****@*****.**', current_user.email, 'Invoice request from ' + current_user.first_name, template='feedback-inline', vars={ 'feedback': message, 'User_first_name': current_user.first_name, 'User_last_name': current_user.last_name, }, ) except SMTPException as e: return error_response('Could not send invoice email.', code=500) invoice_for_db = { 'user_id': user_id, 'plan_id': plan_id, 'status': 'requested' } invoice_for_db = Invoice(invoice_for_db) db_session_users.add(invoice_for_db) db_session_users.commit() db_session_users.refresh(invoice_for_db) return {'invoice': 'invoice request sent'}
def update_saved_search(user_id, saved_search_id, params): name = params.get('name', None) name_conflict_user = db_session_users.query(UserSavedSearch).filter_by( user_id=user_id, name=name).first() if name_conflict_user: return jsonify({ 'errors': "Saved search name: " + name + " is already being used" }), 409 search_args = params.get('search_args', None) saved_search = db_session_users.query(UserSavedSearch).filter_by( id=saved_search_id, user_id=user_id).first() if not saved_search: return jsonify({"errors": "No saved search for this user and id"}), 404 if name: saved_search.name = name if search_args: saved_search.search_args = search_args db_session_users.add(saved_search) db_session_users.commit() db_session_users.refresh(saved_search) return jsonify({"saved_search": saved_search.to_dict()})
def delete_annotation_task(annotation_task_id, params): # n.b. delete_with_annotations flags is intended to make it more difficult to delete tasks that have actual # annotations associated with them, the extra flag means users will need to take the extra step before # blowing them away delete_with_annotations = params[ 'delete_with_annotations'] if 'delete_with_annotations' in params else False annotation_task = db_session_users.query(AnnotationTask).filter_by( id=annotation_task_id).first() if annotation_task.active_task_id is not None: old_annotation_tasks = db_session_users.query( AnnotationTask).filter_by(active_task_id=annotation_task.id).all() all_task_ids = [annotation_task.id ] + [o.id for o in old_annotation_tasks] # make sure we do a top-level check for all of the tasks if there are annotations, and return the error # if the delete_with_annotations flag is not set if db_session_users.query(TopicAnnotation).filter(TopicAnnotation.annotation_task_id.in_(all_task_ids)).count()\ > 0 and not delete_with_annotations: return jsonify({'errors': 'Annotations exist for this task'}), 400 for old_annotation_task in old_annotation_tasks: delete_annotation_task_by_obj(old_annotation_task, delete_with_annotations) delete_annotation_task_by_obj(annotation_task, delete_with_annotations) else: if db_session_users.query(TopicAnnotation).filter_by(annotation_task_id=annotation_task.id).count() > 0\ and not delete_with_annotations: return jsonify({'errors': 'Annotations exist for this task'}), 400 delete_annotation_task_by_obj(annotation_task, delete_with_annotations) db_session_users.commit() return jsonify({"success": True})
def remove_saved_search(user_id, saved_search_id): db_session_users.query(UserSavedSearch).filter_by( id=saved_search_id, user_id=user_id).delete() db_session_users.commit() # TODO is it worth validating this? return {"deleted": True}
def get_flagged_hidden_documents(user_id, params): subquery = db_session_users.query( UserFlaggedDocument.doc_id).filter_by(user_id=user_id, issue_severity="show_now", status="flagged").subquery() documents = db_session_users.query(UserFlaggedDocument).filter_by( user_id=user_id, status="hidden").filter( UserFlaggedDocument.doc_id.notin_(subquery)).all() return jsonify({'hidden_documents': [doc.to_dict() for doc in documents]})
def get_all_annotation_task_groups(): task_groups = [ g.to_dict() for g in db_session_users.query(AnnotationTaskTopicGroup) ] for group in task_groups: group['gold_annotator_users'] = [ u.to_dict() for u in db_session_users.query(User).filter( User.id.in_(group['gold_annotator_user_ids'])).all() ] return {"annotation_task_groups": task_groups}
def get_annotation_job_by_id(annotation_task_id, annotation_job_id, user_id): # n.b. user_id is redundant but this should prevent shenanigans here annotation_job = db_session_users.query(AnnotationJob).\ filter_by(id=annotation_job_id, user_id=user_id).first() annotation_job_dict = annotation_job.to_dict() # n.b. i deliberately left the user_id restriction here in case future QA tasks might allow super annotators # to edit user annotations topic_annotations = db_session_users.query(TopicAnnotation).filter_by(annotation_job_id=annotation_job_id) annotation_job_dict['topic_annotations'] = [t.to_dict() for t in topic_annotations] doc_dict = jsearch.get_record(annotation_job.doc_id) return {'annotation_job': annotation_job_dict, 'document': doc_dict}
def get_all_followed_entities(user_id, params): if params: entity_type = params['entity_type'] all_entities = db_session_users.query(UserFollowedEntity).filter_by( user_id=user_id, entity_type=entity_type, following=True).all() else: all_entities = db_session_users.query(UserFollowedEntity).filter_by( user_id=user_id, following=True).all() return { "followed_entities": [ merge_two_dicts(e.to_dict(), get_entity_from_es(e)) for e in all_entities ] }
def get_all_created_documents(params): query = db_session_users.query(UserCreatedDocument) if 'user_id' in params: query = query.filter_by(user_id=params['user_id']) if 'status' in params: query = query.filter_by(status=params['status']) return {"user_created_documents": [d.to_dict() for d in query]}
def create_review_for_job(annotation_task_id, annotation_job_id, user_id, params): annotation_job = db_session_users.query(AnnotationJob).filter_by(id=annotation_job_id).first() annotation_job.status = AnnotationJob.COMPLETE_STATUS annotation_job.completed_at = datetime.datetime.now() db_session_users.add(annotation_job) db_session_users.commit() db_session_users.refresh(annotation_job) job = annotation_job.to_dict() doc = None if 'multiple_field' in params: multiple_field = params.get('multiple_field', None) flagged_doc = UserFlaggedDocument({ 'user_id': user_id, 'doc_id': annotation_job.doc_id, 'issue_type': UserFlaggedDocument.CONTRIBUTOR_ISSUE_TYPE, 'multiple_field': multiple_field }) db_session_users.add(flagged_doc) db_session_users.commit() db_session_users.refresh(flagged_doc) doc = flagged_doc.to_dict() return {"annotation_job": job, "flagged_doc": doc}
def create_annotation_task(params): new_annotation_task = AnnotationTask(params) term_sampling_group_ids = params.get("term_sampling_group_ids", None) # FIXME: enforcing default values until the front-end has been updated to provide this explicitly if new_annotation_task.type is None: new_annotation_task.type = AnnotationTask.TOPIC_ANNOTATION_TYPE elif new_annotation_task.type == 'contributor': new_annotation_task.is_contributor_task = True db_session_users.add(new_annotation_task) db_session_users.commit() db_session_users.refresh(new_annotation_task) if term_sampling_group_ids is not None: for term_sampling_group_id in term_sampling_group_ids: attsg = AnnotationTaskTermSamplingGroup({ 'annotation_task_id': new_annotation_task.id, 'term_sampling_group_id': term_sampling_group_id }) db_session_users.add(attsg) db_session_users.commit() task_dict = new_annotation_task.to_dict() term_sampling_group_ids = db_session_users.query(AnnotationTaskTermSamplingGroup.term_sampling_group_id) \ .filter_by(annotation_task_id=new_annotation_task.id) task_dict["term_sampling_group_ids"] = [ t[0] for t in term_sampling_group_ids ] return {"annotation_task": task_dict}
def get_annotation_jobs_for_task(annotation_task_id, params): base_query = db_session_users.query(AnnotationJob).filter_by(annotation_task_id=annotation_task_id) if 'status' in params: base_query = base_query.filter_by(status=params['status']) if 'type' in params: base_query = base_query.filter_by(status=params['type']) # get the total number of annotation jobs before the limit+offset breakdown job_count_total = base_query.count() if 'count_only' in params: return {'total': job_count_total} # n.b. allows pagination if 'offset' in params: base_query = base_query.offset(params['offset']) # n.b. 20 seems a reasonable default limit limit = params.get('limit', 20) base_query = base_query.limit(limit) annotation_jobs = [aj.to_dict({'topic_annotation_count': True}) for aj in base_query] return {'annotation_jobs': annotation_jobs, 'total': job_count_total}
def get_all_saved_searches(user_id): all_searches = db_session_users.query(UserSavedSearch).filter_by( user_id=user_id).all() return { "saved_searches": [get_decorated_saved_search(s) for s in all_searches] }
def updated_followed_entity(user_id, params): entities = params['entities'] followed_entities = [] for entity in entities: entity_id = entity['entity_id'] entity_type = entity['entity_type'] following = entity['following'] followed_entity = db_session_users.query(UserFollowedEntity).filter_by( entity_id=entity_id, entity_type=entity_type, user_id=user_id).first() if not followed_entity: followed_entity = UserFollowedEntity({ 'entity_id': entity_id, 'entity_type': entity_type, 'user_id': user_id }) followed_entity.following = following followed_entities.append(followed_entity) db_session_users.add_all(followed_entities) db_session_users.commit() return { "followed_entities": [ merge_two_dicts(e.to_dict(), get_entity_from_es(e)) for e in followed_entities ] }
def get_topic_annotation_breakdown_for_task(annotation_task_id, params): # fetch all previous incarnations of this task, so they can be included in statistics all_task_ids = [ t[0] for t in db_session_users.query(AnnotationTask.id).filter_by(active_task_id=annotation_task_id).distinct().all() ] all_task_ids.append(annotation_task_id) # get annotation counts for user_id / is_positive pairings base_query = db_session_users.query(TopicAnnotation.user_id, TopicAnnotation.is_positive, func.count(TopicAnnotation.user_id))\ .filter(TopicAnnotation.annotation_task_id.in_(all_task_ids)) if 'to_date' in params and 'from_date' in params: base_query = base_query.filter(TopicAnnotation.created_at > params['from_date'])\ .filter(TopicAnnotation.created_at < params['to_date']) elif 'from_date' in params: base_query = base_query.filter(TopicAnnotation.created_at > params['from_date']) elif 'to_date' in params: base_query = base_query.filter(TopicAnnotation.created_at < params['to_date']) all_counts = base_query.group_by(TopicAnnotation.user_id).group_by(TopicAnnotation.is_positive).all() # user_id -> email mapping for response user_ids = list(set([r[0] for r in all_counts])) user_result = db_session_users.query(User.id, User.email).filter(User.id.in_(user_ids)).all() user_id_email_map = {u[0]: u[1] for u in user_result} # get all skipped annotations all_skipped = db_session_users.query(AnnotationJob.user_id, func.count(AnnotationJob.user_id)).filter_by(was_skipped=True)\ .group_by(AnnotationJob.user_id).all() user_id_total_skipped_map = {s[0]: s[1] for s in all_skipped} # build the structure of the actual response result = defaultdict(dict) totals = {"positive": 0, "negative": 0} for user_id, is_positive, num_annotations in all_counts: user_email = user_id_email_map[user_id] polarity = "positive" if is_positive else "negative" result[user_email][polarity] = num_annotations totals[polarity] += num_annotations # add number of skipped docs if user_id in user_id_total_skipped_map: result[user_email]["skipped"] = user_id_total_skipped_map[user_id] else: result[user_email]["skipped"] = 0 result["total"] = totals return result
def update_subscription(subscription_id, params): original_subscription = db_session_users.query(Subscription).filter_by( id=subscription_id).first() new_subscription_dict = original_subscription.__dict__ today = datetime.datetime.utcnow() new_subscription_dict['latest'] = True new_subscription_dict['notes'] = None if 'expiration_date' in params: new_exiration_date = params['expiration_date'] new_exiration_date_obj = datetime.datetime.strptime( new_exiration_date, "%Y-%m-%d") new_subscription_dict['expiration_date'] = new_exiration_date_obj # update status of subscription depending on new expiration date if new_exiration_date_obj < today or new_exiration_date_obj.date( ) == today.date(): new_subscription_dict[ 'status_reason'] = Subscription.EXPIRED_STATUS_REASON new_subscription_dict['status'] = Subscription.INACTIVE_STATUS elif new_subscription_dict['status'] != Subscription.ACTIVE_STATUS: new_subscription_dict[ 'status_reason'] = Subscription.REACTIVATED_STATUS_REASON new_subscription_dict['status'] = Subscription.ACTIVE_STATUS if 'plan_id' in params: new_plan_id = params['plan_id'] plan = db_session_users().query(Plan).filter_by(id=new_plan_id).first() if plan: new_subscription_dict['plan_id'] = new_plan_id new_subscription_dict['stripe_id'] = plan.stripe_id new_subscription_dict['start_date'] = datetime.datetime.utcnow() new_subscription_dict[ 'status_reason'] = Subscription.REACTIVATED_STATUS_REASON new_subscription_dict['status'] = Subscription.ACTIVE_STATUS if plan.recurring: new_subscription_dict['expiration_date'] = None else: new_subscription_dict[ 'expiration_date'] = get_default_expiration_date(plan) else: return {'errors': "Plan is not found"} if 'payment_type' in params: new_subscription_dict['payment_type'] = params['payment_type'] if 'notes' in params: new_subscription_dict['notes'] = params['notes'] new_subscription_dict['modified_by_user_id'] = g.user_id new_subscription = Subscription(new_subscription_dict) db_session_users.add(new_subscription) # deactivate old subscription deactivate_subscriptions(new_subscription_dict['user_id']) db_session_users.commit() db_session_users.refresh(new_subscription) return {'new_subscription': new_subscription.to_dict()}
def get_all_plans(): plans = db_session_users.query(Plan).values(Plan.id, Plan.name) results = [] for plan_id, plan_name in plans: results.append({'id': plan_id, 'name': plan_name}) return {'all_plans': results}
def get_marketing_campaign_details(marketing_campaign_id): marketing_campaign = db_session_users.query(MarketingCampaign).filter_by( id=marketing_campaign_id).first() marketing_campaign_details = marketing_campaign.to_dict() marketing_campaign_details['users'] = [ u.to_dict() for u in marketing_campaign.users ] return {"marketing_campaign": marketing_campaign_details}
def get_all_annotation_tasks(user_id, params, is_qa_user=False, is_contributor_user=False): tasks = [] # n.b. notin_ omits cases where type is null annotation_task_query = db_session_users.query(AnnotationTask).filter(AnnotationTask.active_task_id == None)\ .filter(or_(AnnotationTask.type.notin_(TASK_TYPES_TO_SKIP), AnnotationTask.type == None)) annotation_type = params.get("type", None) if is_qa_user: annotation_task_query = annotation_task_query.filter( AnnotationTask.user_ids.any(user_id)) if is_contributor_user: # n.b. using is_contributor_task=True is not required right now for topic annotation type tasks # TODO? should this be required in the future? if annotation_type == 'topic_annotation': annotation_task_query = annotation_task_query.filter( AnnotationTask.user_ids.any(user_id)) annotation_task_query = annotation_task_query.filter_by( type=annotation_type) else: annotation_task_query = annotation_task_query.filter_by( is_contributor_task=True) # FIXME use queries on the specific type moving forward (type filter on document_review or topic_annotation) annotation_task_query = annotation_task_query.filter_by( type='contributor') for task in annotation_task_query.order_by(AnnotationTask.name): task_dict = task.to_dict() task_dict["old_tasks"] = [ t.to_dict() for t in db_session_users.query(AnnotationTask).filter_by( active_task_id=task.id) ] term_sampling_group_ids = db_session_users.query(AnnotationTaskTermSamplingGroup.term_sampling_group_id)\ .filter_by(annotation_task_id=task.id) task_dict["term_sampling_group_ids"] = [ t[0] for t in term_sampling_group_ids ] tasks.append(task_dict) return {"annotation_tasks": tasks}
def subscribe_users_to_plan(user_ids, plan_stripe_id, payment_type=None, modified_by_user_id=None): if not (payment_type == 'invoice' or payment_type == 'stripe' or payment_type == None): return 'please use a valid payment_type' for user_id in user_ids: user = db_session_users.query(User).filter_by(id=user_id).first() if user is None: return "user doesn't exist" plan = db_session_users.query(Plan).filter_by( stripe_id=plan_stripe_id).first() if plan is None: return 'please use a valid plan' subscription_for_db = { 'user_id': user_id, 'stripe_id': plan.stripe_id, 'plan_id': plan.id, 'latest': True, 'start_date': datetime.datetime.utcnow(), 'status': 'active' } if modified_by_user_id is not None: subscription_for_db['modified_by_user_id'] = modified_by_user_id if payment_type == 'invoice' or payment_type == 'invoice': subscription_for_db['payment_type'] = payment_type else: # currently only free_trials have exiration dates. all other plans are recurring subscription_for_db[ 'expiration_date'] = get_default_expiration_date(plan) try: deactivate_subscriptions(user_id) except: return 'unable to deactivate existing subscriptions' try: subscription_for_db = Subscription(subscription_for_db) db_session_users.add(subscription_for_db) db_session_users.commit() except: return 'unable to post subscription to database'
def deactivate_subscriptions(user_id): # a user should have only 1 current subscription at a time latest_subscriptions = db_session_users.query(Subscription).filter_by( user_id=user_id, latest=True).all() if latest_subscriptions is not None: for latest_subscription in latest_subscriptions: latest_subscription.latest = False latest_subscription.status = Subscription.INACTIVE_STATUS latest_subscription.end_date = datetime.datetime.utcnow() db_session_users.add(latest_subscription) db_session_users.commit() db_session_users.refresh(latest_subscription)
def get_subscriptions(user_id): subscriptions = db_session_users.query(Subscription).filter_by( user_id=user_id).join(Plan, Subscription.plan_id == Plan.id).values( Subscription.created_at, Subscription.latest, Subscription.user_id, Subscription.payment_type, Subscription.start_date, Subscription.end_date, Subscription.status, Subscription.period_count, Subscription.expiration_date, Plan.name, Plan.category, Plan.stripe_id, Plan.price, Plan.price_period) stripe_subscription = db_session_users.query(Subscription).filter_by( user_id=user_id, payment_type='stripe', latest=True).first() if stripe_subscription: stripe_sub = stripe.Subscription.retrieve( stripe_subscription.stripe_id) next_bill_date = stripe_sub['current_period_end'] else: next_bill_date = '' results = [] for created_at, latest, user_id, payment_type, start_date, end_date, status, period_count, expiration_date, name, category, stripe_id, price, price_period in subscriptions: results.append({ 'created_at': created_at, 'latest': latest, 'user_id': user_id, 'payment_type': payment_type, 'start_date': start_date, 'end_date': end_date, 'status': status, 'period_count': period_count, 'expiration_date': expiration_date, 'name': name, 'category': category, 'stripe_id': stripe_id, 'price': price, 'price_period': price_period, 'next_bill_date': next_bill_date }) return {'subscriptions': results}
def delete_annotation_task_by_obj(ann_task, delete_with_annotations=False): if db_session_users.query(TopicAnnotation).filter_by(annotation_task_id=ann_task.id).count() > 0\ and delete_with_annotations: db_session_users.query(TopicAnnotation).filter_by( annotation_task_id=ann_task.id).delete() if db_session_users.query(AnnotationJob).filter_by( annotation_task_id=ann_task.id).count() > 0: db_session_users.query(AnnotationJob).filter_by( annotation_task_id=ann_task.id).delete() db_session_users.query(AnnotationTaskTermSamplingGroup).filter_by( annotation_task_id=ann_task.id).delete() db_session_users.delete(ann_task)
def update_annotation_task_group(annotation_task_group_id, params): # params is dict that can contain keys "name", "description", "annotation_task_ids" # and "arbitrary_tags" # get original annotation task group original_annotation_task_group = db_session_users.query(AnnotationTaskTopicGroup)\ .filter_by(id=annotation_task_group_id)\ .first() # check that task group exists if original_annotation_task_group is None: return jsonify({'errors': 'This annotation task group does not exist'}), 400 # apply easy updates to annotation task group (i.e. just overwriting name or description) if "name" in params: original_annotation_task_group.name = params["name"] if "description" in params: original_annotation_task_group.description = params["description"] # apply more difficult updates (i.e. changing arbitrary_tags or annotation_task_ids) # NB: for now these are simple overwrites - if needed can later update for more granular control if "annotation_task_ids" in params: original_annotation_task_group.annotation_task_ids = params[ "annotation_task_ids"] if "arbitrary_tags" in params: original_annotation_task_group.arbitrary_tags = params[ "arbitrary_tags"] # n.b. for case where wrong topic was chosen at outset if "topic_id" in params: original_annotation_task_group.topic_id = params['topic_id'] if "gold_annotator_user_ids" in params: original_annotation_task_group.gold_annotator_user_ids = params[ 'gold_annotator_user_ids'] if "active_topic_annotation_model_id" in params: original_annotation_task_group.active_topic_annotation_model_id = params[ 'active_topic_annotation_model_id'] # update database with new values db_session_users.add(original_annotation_task_group) db_session_users.commit() task_group_to_return = original_annotation_task_group # original task group has been updated # return updated annotation task group task_group_dict = task_group_to_return.to_dict() return jsonify({"annotation_task_group": task_group_dict})
def update_research_mode_gold_standard(aggregated_annotation_id, params): """ Update aggregated_annotation so that it points to a new annotation task as a gold standard. If the update is None, then aggregated_annotation.is_gold_standard is set to False. :param aggregated_annotation_id: int :param params: dict, must contain 'topic_annotation_id' as key with topic_annotation_id as value; this is the topic_annotation that is the new gold standard If topic_annotation_id is None, then no topic_annotation is a gold standard :return: dict """ agg_annotation = db_session_users.query(AggregatedAnnotations)\ .filter_by(id=aggregated_annotation_id)\ .first() agg_annotation.gold_topic_annotation_id = params['topic_annotation_id'] # update is_gold_standard now that gold_topic_annotation_id is set if agg_annotation.gold_topic_annotation_id is not None: agg_annotation.is_gold_standard = True # update arbitrary_tags and user_difficulty of agg_annotation with values from the new gold standard annotation gold_standard_topic_annotation = db_session_users.query(TopicAnnotation)\ .filter_by(id=params['topic_annotation_id']) \ .options(subqueryload(TopicAnnotation.annotation_job))\ .first() agg_annotation.arbitrary_tags = gold_standard_topic_annotation.annotation_job.arbitrary_tags agg_annotation.gold_difficulty = gold_standard_topic_annotation.annotation_job.user_difficulty else: agg_annotation.is_gold_standard = False # update aggregated_annotation.arbitrary_tags to be nothing agg_annotation.arbitrary_tags = [] agg_annotation.gold_difficulty = None # commit change db_session_users.commit() # n.b. return a deliberately simple response here to avoid a large json response that isn't strictly needed return jsonify({"success": True})
def get_reviews_count_for_user(annotation_task_id, user_id, params): # fetch all previous incarnations of this task, so they can be included in statistics all_task_ids = [ t[0] for t in db_session_users.query(AnnotationTask.id).filter_by(active_task_id=annotation_task_id).distinct().all() ] all_task_ids.append(annotation_task_id) # use the utc value for the start of the day pacific time now = datetime.datetime.now() - datetime.timedelta(hours=8) today_date = str(now.month) + "/" + str(now.day) + "/" + str(now.year) # get start date of the billing month subscription_created = db_session_users.query(Subscription.created_at).filter_by(user_id=user_id, latest=True).first() month_start_date = get_currentsubscription_month_date(subscription_created[0]) # get annotation counts for user_id / is_positive pairings base_query = db_session_users.query(AnnotationJob).filter(AnnotationJob.annotation_task_id.in_(all_task_ids)).filter_by(user_id=user_id)\ .filter(AnnotationJob.status == AnnotationJob.COMPLETE_STATUS) today_total = base_query.filter(AnnotationJob.completed_at >= today_date).count() current_month_total = base_query.filter(AnnotationJob.completed_at >= month_start_date).count() return {'today_total': today_total, 'current_month_total': current_month_total}
def delete_annotation_task_group(annotation_task_group_id, params): # find if task with this id in database annotation_task_group = db_session_users.query(AnnotationTaskTopicGroup)\ .filter_by(id=annotation_task_group_id)\ .first() if annotation_task_group is None: return jsonify({'errors': 'This annotation task group does not exist'}), 400 # if this annotation task group exists, delete it from database db_session_users.delete(annotation_task_group) db_session_users.commit() return jsonify({"success": True})
def get_all_annotation_tasks_in_group(annotation_task_group_id): # get list of annotation task ids for annotation task group task_group = db_session_users.query(AnnotationTaskTopicGroup)\ .filter_by(id=annotation_task_group_id)\ .first() if task_group is None: return jsonify({'errors': 'This annotation task group does not exist'}), 400 task_group_dict = task_group.to_dict() task_ids = task_group_dict["annotation_task_ids"] # create annotation task dicts tasks = [ db_session_users.query(AnnotationTask).filter_by( id=task_id).first().to_dict() for task_id in task_ids ] # return list of annotation task dicts, total number of tasks, and annotation task group dict return jsonify({ "annotation_tasks_in_group": tasks, "total_tasks": len(tasks), "annotation_task_group_dict": task_group_dict })
def flag_document(user_id, doc_id, params): issue_severity = params.get('issue_severity', UserFlaggedDocument.REVIEW_SEVERITY) issue_type = params.get('issue_type', None) notes = params.get('notes', None) field = params.get('field', None) user_flagged_document_id = params.get('id', None) status = params.get('status', None) # for creating new user flagged documents if user_flagged_document_id is None: if not issue_type or issue_type not in ValidIssueTypes: return { 'errors': "Issue type must be one of: " + str(ValidIssueTypes) } if issue_severity not in ValidIssueSeverities: return { 'errors': "Issue severity must be one of: " + str(ValidIssueSeverities) } flagged_doc = UserFlaggedDocument({ 'user_id': user_id, 'doc_id': doc_id, 'issue_severity': issue_severity, 'issue_type': issue_type, 'notes': notes, 'field': field, }) # for updating an existing user flagged document (status is the only relevant use-case) else: flagged_doc = db_session_users.query(UserFlaggedDocument).filter_by( id=user_flagged_document_id).first() if status is not None: if status in ValidIssueStatuses: flagged_doc.status = status else: return { 'errors': "Issue status must be one of: " + str(ValidIssueStatuses) } db_session_users.add(flagged_doc) db_session_users.commit() db_session_users.refresh(flagged_doc) return flagged_doc.to_dict()
def get_most_popular_sources(params): num_queries = params.get("num_queries", 5) # n.b. 5 is an arbitrary default fed_agency_ids = get_all_fed_agency_ids() most_popular_sources = db_session_users.query(UserAgency.agency_id, func.count(UserAgency.agency_id).label('total')) \ .filter(UserAgency.user_id.in_(get_external_user_id_subquery()))\ .filter(UserAgency.agency_id.in_(fed_agency_ids)).group_by(UserAgency.agency_id).order_by(text('total desc'))\ .limit(num_queries).all() return { "popular_sources": [{ "agency_id": d[0], "count": d[1] } for d in most_popular_sources] }