def edit_brief_question(framework_slug, lot_slug, brief_id, section_slug, question_id): get_framework_and_lot(framework_slug, lot_slug, data_api_client, status='live', must_allow_brief=True) brief = data_api_client.get_brief(brief_id)["briefs"] if not is_brief_correct( brief, framework_slug, lot_slug, current_user.id, data_api_client ) or not brief_can_be_edited(brief): abort(404) if not has_permission_to_edit_brief(brief): return redirect('/2/request-access/create_drafts') content = content_loader.get_manifest(brief['frameworkSlug'], 'edit_brief').filter( {'lot': brief['lotSlug']} ) section = content.get_section(section_slug) if section is None or not section.editable: abort(404) remove_non_cascade_fields(brief, section, question_id) question = section.get_question(question_id) if not question: abort(404) return render_template_with_csrf( "buyers/edit_brief_question.html", brief=brief, section=section, question=question )
def view_brief_section_summary(framework_slug, lot_slug, brief_id, section_slug): get_framework_and_lot(framework_slug, lot_slug, data_api_client, status='live', must_allow_brief=True) brief = data_api_client.get_brief(brief_id)["briefs"] if not is_brief_correct( brief, framework_slug, lot_slug, current_user.id, data_api_client ) or not brief_can_be_edited(brief): abort(404) if not has_permission_to_edit_brief(brief): return redirect('/2/request-access/create_drafts') content = content_loader.get_manifest(brief['frameworkSlug'], 'edit_brief').filter({'lot': brief['lotSlug']}) sections = content.summary(brief) section = sections.get_section(section_slug) remove_non_cascade_fields(brief, section, 'description-of-training') if not section: abort(404) return render_template( "buyers/section_summary.html", brief=brief, section=section ), 200
def edit_brief_question(framework_slug, lot_slug, brief_id, section_slug, question_id): get_framework_and_lot(framework_slug, lot_slug, data_api_client, status='live', must_allow_brief=True) brief = data_api_client.get_brief(brief_id)["briefs"] if not is_brief_correct( brief, framework_slug, lot_slug, current_user.id ) or not brief_can_be_edited(brief): abort(404) content = content_loader.get_manifest(brief['frameworkSlug'], 'edit_brief').filter( {'lot': brief['lotSlug']} ) section = content.get_section(section_slug) if section is None or not section.editable: abort(404) remove_non_cascade_fields(brief, section, question_id) question = section.get_question(question_id) if not question: abort(404) return render_template_with_csrf( "buyers/edit_brief_question.html", brief=brief, section=section, question=question )
def view_brief_section_summary(framework_slug, lot_slug, brief_id, section_slug): get_framework_and_lot(framework_slug, lot_slug, data_api_client, status='live', must_allow_brief=True) brief = data_api_client.get_brief(brief_id)["briefs"] if not is_brief_correct( brief, framework_slug, lot_slug, current_user.id ) or not brief_can_be_edited(brief): abort(404) content = content_loader.get_manifest(brief['frameworkSlug'], 'edit_brief').filter({'lot': brief['lotSlug']}) sections = content.summary(brief) section = sections.get_section(section_slug) remove_non_cascade_fields(brief, section, 'description-of-training') if not section: abort(404) return render_template( "buyers/section_summary.html", brief=brief, section=section ), 200
def publish_brief(framework_slug, lot_slug, brief_id): if lot_slug in ['digital-outcome', 'digital-professionals', 'training']: abort(404) TZ = current_app.config['DM_TIMEZONE'] get_framework_and_lot(framework_slug, lot_slug, data_api_client, status='live', must_allow_brief=True) brief = data_api_client.get_brief(brief_id)["briefs"] if not is_brief_correct( brief, framework_slug, lot_slug, current_user.id, data_api_client ) or not brief_can_be_edited(brief): abort(404) if not has_permission_to_edit_brief(brief): return redirect('/2/request-access/publish_opportunities') content = content_loader.get_manifest(brief['frameworkSlug'], 'edit_brief').filter({'lot': brief['lotSlug']}) sections = content.summary(brief) question_and_answers = {} question_and_answers_content = sections.get_question('questionAndAnswerSessionDetails') question_and_answers['id'] = question_and_answers_content['id'] for section in sections: if section.get_question('questionAndAnswerSessionDetails') == question_and_answers_content: question_and_answers['slug'] = section['id'] for question_id in section.get_section_question_ids(): remove_non_cascade_fields(brief, section, question_id) unanswered_required, unanswered_optional = count_unanswered_questions(sections) if request.method == 'POST': if unanswered_required > 0: abort(400, 'There are still unanswered required questions') if not current_user.has_permission('publish_opportunities'): return redirect('/2/request-access/publish_opportunities') data_api_client.publish_brief(brief_id, current_user.name) brief_url = '/2/brief/{}/published'.format(brief_id) brief_url_external = url_for('main.get_brief_by_id', framework_slug=brief['frameworkSlug'], brief_id=brief['id'], _external=True) send_new_opportunity_email_to_sellers(brief, brief_url_external) notification_message = '{}\n{}\nBy: {} ({})'.format( brief['title'], brief['organisation'], current_user.name, current_user.email_address ) notify_team('A buyer has published a new opportunity', notification_message, brief_url_external) return redirect(brief_url) else: email_address = current_user.email_address return render_template_with_csrf( "buyers/brief_publish_confirmation.html", email_address=email_address, question_and_answers=question_and_answers, unanswered_required=unanswered_required, sections=sections, brief=brief, current_date=pendulum.now(TZ) )
def update_brief_submission(framework_slug, lot_slug, brief_id, section_id, question_id): get_framework_and_lot(framework_slug, lot_slug, data_api_client, status='live', must_allow_brief=True) brief = data_api_client.get_brief(brief_id)["briefs"] if not is_brief_correct( brief, framework_slug, lot_slug, current_user.id, data_api_client ) or not brief_can_be_edited(brief): abort(404) if not has_permission_to_edit_brief(brief): return redirect('/2/request-access/create_drafts') content = content_loader.get_manifest(brief['frameworkSlug'], 'edit_brief').filter({'lot': brief['lotSlug']}) section = content.get_section(section_id) if section is None or not section.editable: abort(404) question = section.get_question(question_id) if not question: abort(404) update_data = question.get_data(request.form) remove_non_cascade_fields(brief, section, question_id, update_data) question_ids = section.get_section_question_ids() question_id_index = None if question_id in question_ids: question_id_index = question_ids.index(question_id) try: data_api_client.update_brief( brief_id, update_data, updated_by=current_user.email_address, page_questions=question.form_fields ) except HTTPError as e: update_data = section.unformat_data(update_data) mapped = {} for k, v in e.message.iteritems(): if ((k == 'sellerEmailList' or k == 'sellerEmail') and v.startswith('email_not_found~')): mapped[k] = v.split('~')[0] else: mapped[k] = v errors = section.get_error_messages(mapped) for k, v in errors.iteritems(): if ((k == 'sellerEmailList' or k == 'sellerEmail') and e.message[k].startswith('email_not_found~')): v['message'] = '{} {}'.format(e.message[k].split('~')[1], v['message']) # we need the brief_id to build breadcrumbs and the update_data to fill in the form. brief.update(update_data) return render_template_with_csrf( "buyers/edit_brief_question.html", status_code=400, brief=brief, section=section, question=question, errors=errors ) if section.has_summary_page: # If there are more than 1 questions and it is not the last one. if (question_id_index is not None and len(question_ids) > 1 and question_id_index != len(question_ids) - 1): return redirect( url_for( '.edit_brief_question', framework_slug=brief['frameworkSlug'], lot_slug=brief['lotSlug'], brief_id=brief['id'], section_slug=section.slug, question_id=question_ids[question_id_index + 1])) response = __navigate_next(content, brief, lot_slug, section_id) if response: return response if lot_slug != 'training': return redirect( url_for( ".view_brief_section_summary", framework_slug=brief['frameworkSlug'], lot_slug=brief['lotSlug'], brief_id=brief['id'], section_slug=section.slug)) else: response = __navigate_next(content, brief, lot_slug, section_id) if response: return response return redirect( url_for( ".view_brief_overview", framework_slug=brief['frameworkSlug'], lot_slug=brief['lotSlug'], brief_id=brief['id'] ) )
def publish_brief(framework_slug, lot_slug, brief_id): if lot_slug == 'digital-outcome': abort(404) TZ = current_app.config['DM_TIMEZONE'] get_framework_and_lot(framework_slug, lot_slug, data_api_client, status='live', must_allow_brief=True) brief = data_api_client.get_brief(brief_id)["briefs"] if not is_brief_correct( brief, framework_slug, lot_slug, current_user.id ) or not brief_can_be_edited(brief): abort(404) content = content_loader.get_manifest(brief['frameworkSlug'], 'edit_brief').filter({'lot': brief['lotSlug']}) brief_users = brief['users'][0] brief_user_name = brief_users['name'] sections = content.summary(brief) question_and_answers = {} question_and_answers_content = sections.get_question('questionAndAnswerSessionDetails') question_and_answers['id'] = question_and_answers_content['id'] for section in sections: if section.get_question('questionAndAnswerSessionDetails') == question_and_answers_content: question_and_answers['slug'] = section['id'] for question_id in section.get_section_question_ids(): remove_non_cascade_fields(brief, section, question_id) unanswered_required, unanswered_optional = count_unanswered_questions(sections) if request.method == 'POST': if unanswered_required > 0: abort(400, 'There are still unanswered required questions') data_api_client.publish_brief(brief_id, brief_user_name) brief_url = '/2/brief/{}/published'.format(brief_id) brief_url_external = url_for('main.get_brief_by_id', framework_slug=brief['frameworkSlug'], brief_id=brief['id'], _external=True) send_new_opportunity_email_to_sellers(brief, brief_url_external) notification_message = '{}\n{}\nBy: {} ({})'.format( brief['title'], brief['organisation'], current_user.name, current_user.email_address ) notify_team('A buyer has published a new opportunity', notification_message, brief_url_external) return redirect(brief_url) else: email_address = brief_users['emailAddress'] return render_template_with_csrf( "buyers/brief_publish_confirmation.html", email_address=email_address, question_and_answers=question_and_answers, unanswered_required=unanswered_required, sections=sections, brief=brief, current_date=pendulum.now(TZ) )
def update_brief_submission(framework_slug, lot_slug, brief_id, section_id, question_id): get_framework_and_lot(framework_slug, lot_slug, data_api_client, status='live', must_allow_brief=True) brief = data_api_client.get_brief(brief_id)["briefs"] if not is_brief_correct( brief, framework_slug, lot_slug, current_user.id ) or not brief_can_be_edited(brief): abort(404) content = content_loader.get_manifest(brief['frameworkSlug'], 'edit_brief').filter({'lot': brief['lotSlug']}) section = content.get_section(section_id) if section is None or not section.editable: abort(404) question = section.get_question(question_id) if not question: abort(404) update_data = question.get_data(request.form) remove_non_cascade_fields(brief, section, question_id, update_data) question_ids = section.get_section_question_ids() question_id_index = None if question_id in question_ids: question_id_index = question_ids.index(question_id) try: data_api_client.update_brief( brief_id, update_data, updated_by=current_user.email_address, page_questions=question.form_fields ) except HTTPError as e: update_data = section.unformat_data(update_data) mapped = {} for k, v in e.message.iteritems(): if ((k == 'sellerEmailList' or k == 'sellerEmail') and v.startswith('email_not_found~')): mapped[k] = v.split('~')[0] else: mapped[k] = v errors = section.get_error_messages(mapped) for k, v in errors.iteritems(): if ((k == 'sellerEmailList' or k == 'sellerEmail') and e.message[k].startswith('email_not_found~')): v['message'] = '{} {}'.format(e.message[k].split('~')[1], v['message']) # we need the brief_id to build breadcrumbs and the update_data to fill in the form. brief.update(update_data) return render_template_with_csrf( "buyers/edit_brief_question.html", status_code=400, brief=brief, section=section, question=question, errors=errors ) if section.has_summary_page: # If there are more than 1 questions and it is not the last one. if (question_id_index is not None and len(question_ids) > 1 and question_id_index != len(question_ids) - 1): return redirect( url_for( '.edit_brief_question', framework_slug=brief['frameworkSlug'], lot_slug=brief['lotSlug'], brief_id=brief['id'], section_slug=section.slug, question_id=question_ids[question_id_index + 1])) response = __navigate_next(content, brief, lot_slug, section_id) if response: return response if lot_slug != 'training': return redirect( url_for( ".view_brief_section_summary", framework_slug=brief['frameworkSlug'], lot_slug=brief['lotSlug'], brief_id=brief['id'], section_slug=section.slug)) else: response = __navigate_next(content, brief, lot_slug, section_id) if response: return response return redirect( url_for( ".view_brief_overview", framework_slug=brief['frameworkSlug'], lot_slug=brief['lotSlug'], brief_id=brief['id'] ) )