示例#1
0
    def test_count_unanswered_questions(self):
        brief = {
            'status': 'draft',
            'frameworkSlug': 'dos',
            'lotSlug': 'digital-specialists',
            'required1': True
        }
        content = content_loader.get_manifest('dos', 'edit_brief').filter(
            {'lot': 'digital-specialists'})
        sections = content.summary(brief)

        unanswered_required, unanswered_optional = buyers_helpers.count_unanswered_questions(
            sections)
        assert unanswered_required == 2
        assert unanswered_optional == 2
示例#2
0
def view_brief_overview(framework_slug, lot_slug, brief_id):
    if lot_slug == 'digital-professionals' or lot_slug == 'training':
        return redirect('/2/brief/{}/overview'.format(brief_id))
    if lot_slug in ['rfx', 'atm', 'specialist', 'training2']:
        return redirect('/2/brief/{}/overview/{}'.format(brief_id, lot_slug))

    framework, lot = 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) and not allowed_email_domain(
                                current_user.id, brief, data_api_client):
        abort(404)

    content = content_loader.get_manifest(
        brief['frameworkSlug'], 'edit_brief').filter({'lot': brief['lotSlug']})
    sections = content.summary(brief)
    delete_requested = True if request.args.get('delete_requested') else False

    completed_sections = {}
    for section in sections:
        required, optional = count_unanswered_questions([section])
        if section_has_at_least_one_required_question(section):
            completed_sections[section.slug] = True if required == 0 else False
        else:
            completed_sections[section.slug] = True if optional == 0 else False

    brief['clarificationQuestions'] = [
        dict(question, number=index + 1)
        for index, question in enumerate(brief['clarificationQuestions'])
    ]

    return render_template_with_csrf(
        "buyers/brief_overview.html",
        framework=framework,
        confirm_remove=request.args.get("confirm_remove", None),
        brief=brief,
        sections=sections,
        completed_sections=completed_sections,
        step_sections=[
            section.step for section in sections if hasattr(section, 'step')
        ],
        delete_requested=delete_requested,
    )
def view_brief_overview(framework_slug, lot_slug, brief_id):
    if lot_slug == 'digital-professionals' or lot_slug == 'training':
        return redirect('/2/brief/{}/overview'.format(brief_id))
    if lot_slug in ['rfx', 'atm']:
        return redirect('/2/brief/{}/overview/{}'.format(brief_id, lot_slug))

    framework, lot = 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
    ) and not allowed_email_domain(current_user.id, brief, data_api_client):
        abort(404)

    content = content_loader.get_manifest(brief['frameworkSlug'], 'edit_brief').filter({'lot': brief['lotSlug']})
    sections = content.summary(brief)
    delete_requested = True if request.args.get('delete_requested') else False

    completed_sections = {}
    for section in sections:
        required, optional = count_unanswered_questions([section])
        if section_has_at_least_one_required_question(section):
            completed_sections[section.slug] = True if required == 0 else False
        else:
            completed_sections[section.slug] = True if optional == 0 else False

    brief['clarificationQuestions'] = [
        dict(question, number=index+1)
        for index, question in enumerate(brief['clarificationQuestions'])
    ]

    return render_template_with_csrf(
        "buyers/brief_overview.html",
        framework=framework,
        confirm_remove=request.args.get("confirm_remove", None),
        brief=brief,
        sections=sections,
        completed_sections=completed_sections,
        step_sections=[section.step for section in sections if hasattr(section, 'step')],
        delete_requested=delete_requested,
    )
示例#4
0
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)
        )
示例#5
0
def get_brief_by_id(framework_slug, brief_id):
    briefs = data_api_client.get_brief(brief_id)
    brief = briefs.get('briefs')
    if brief['lotSlug'] in ['rfx', 'atm', 'specialist', 'training2']:
        return redirect('/2/%s/opportunities/%s' % (framework_slug, brief_id), 301)
    if brief['status'] not in ['live', 'closed']:
        if (
            not current_user.is_authenticated or
            (brief['users'] and brief['users'][0]['id'] != current_user.id) or
            current_user.id not in [tb.get('userId') for tb in brief.get('teamBriefs', [])]
        ):
            abort(404, "Opportunity '{}' can not be found".format(brief_id))

    if current_user.is_authenticated and current_user.role == 'supplier':
        brief_responses = data_api_client.find_brief_responses(
            brief_id, current_user.supplier_code)["briefResponses"]
        selected_for_brief = _is_supplier_selected_for_brief(brief)
    else:
        brief_responses = None
        selected_for_brief = False

    brief['clarificationQuestions'] = [
        dict(question, number=index+1)
        for index, question in enumerate(brief['clarificationQuestions'])
    ]

    brief_content = content_loader.get_builder(framework_slug, 'display_brief').filter(
        brief
    )

    sections = brief_content.summary(brief)
    unanswered_required, unanswered_optional = count_unanswered_questions(sections)

    brief_of_current_user = False
    if not current_user.is_anonymous and len(brief.get('users')) > 0:
        brief_of_current_user = brief['users'][0]['id'] == current_user.id

    is_restricted_brief = brief.get('sellerSelector', '') in ('someSellers', 'oneSeller')

    brief_published_date = brief['dates'].get('published_date', None)
    feature_date = current_app.config['MULTI_CANDIDATE_PUBLISHED_DATE']

    published_date = pendulum.parse(brief_published_date) if brief_published_date else feature_date.subtract(days=1)
    application_url = "/2/brief/{}/respond".format(brief['id'])
    application_specialist_url = application_url
    application_specialist_submitted_url = None

    if published_date >= feature_date:
        application_specialist_url = "/2/brief/{}/specialist/respond".format(brief['id'])
        application_specialist_submitted_url = "/2/brief/{}/specialist/respond/submitted".format(brief['id'])

    application_training_url = "/2/brief/{}/training/respond".format(brief['id'])

    add_case_study_url = None

    profile_application_status = None
    supplier = None
    unassessed_domains = {}
    assessed_domains = {}
    profile_url = None
    supplier_assessments = {}
    supplier_framework = None

    if current_user.is_authenticated:
        if current_user.supplier_code is not None:
            supplier = data_api_client.get_supplier(
                current_user.supplier_code
            ).get('supplier', None)

        profile_application_id = current_user.application_id

        if supplier is not None:
            profile_url = '/supplier/{}'.format(supplier.get('code'))
            assessed_domains = supplier.get('domains').get('assessed', None)
            unassessed_domains = supplier.get('domains').get('unassessed', None)
            legacy_domains = supplier.get('domains').get('legacy', None)

            if profile_application_id is None:
                profile_application_id = supplier.get('application_id', None)

            supplier_code = supplier.get('code')
            supplier_assessments = data_api_client.req.assessments().supplier(supplier_code).get()

            if len(legacy_domains) != 0:
                for i in range(len(legacy_domains)):
                    supplier_assessments['assessed'].append(legacy_domains[i])

            supplier_framework_ids = supplier.get('frameworks')
            for i in range(len(supplier_framework_ids)):
                if supplier.get('frameworks')[i].get('framework_id') == 7:
                    supplier_framework = 'digital-marketplace'
            if supplier_framework is None:
                supplier_framework = 'digital-service-professionals'

        if profile_application_id is not None:
            try:
                profile_application = data_api_client.req.applications(profile_application_id).get()

                if unassessed_domains is None:
                    unassessed_domains = profile_application.get(
                        'application').get('supplier').get('domains', None).get('unassessed', None)
                if assessed_domains is None:
                    assessed_domains = profile_application.get(
                        'application').get('supplier').get('domains', None).get('assessed', None)

                profile_application_status = profile_application.get('application').get('status', None)
                if profile_application.get('application').get('type') == 'edit':
                    profile_application_status = 'approved'

            except APIError:
                pass
            except HTTPError:
                pass

    domain_id = None
    if brief.get('areaOfExpertise'):
        current_domain = data_api_client.req.domain(brief['areaOfExpertise']).get()
        domain_id = current_domain['domain']['id']
    elif brief['lotSlug'] == 'training':
        domain_id = 15  # training

    return render_template_with_csrf(
        'brief.html',
        add_case_study_url=add_case_study_url,
        application_url=application_url,
        application_specialist_url=application_specialist_url,
        application_specialist_submitted_url=application_specialist_submitted_url,
        application_training_url=application_training_url,
        assessed_domains=assessed_domains,
        brief=brief,
        brief_responses=brief_responses,
        brief_of_current_user=brief_of_current_user,
        content=brief_content,
        domain_id=domain_id,
        is_restricted_brief=is_restricted_brief,
        selected_for_brief=selected_for_brief,
        profile_application_status=profile_application_status,
        profile_url=profile_url,
        unassessed_domains=unassessed_domains,
        supplier_assessments=supplier_assessments,
        supplier_framework=supplier_framework,
        unanswered_required=unanswered_required,
        training_domain_name='Training, Learning and Development'
    )
def get_brief_by_id(framework_slug, brief_id):
    briefs = data_api_client.get_brief(brief_id)
    brief = briefs.get('briefs')
    if brief['lotSlug'] in ['rfx', 'atm']:
        return redirect('/2/%s/opportunities/%s' % (framework_slug, brief_id), 301)
    if brief['status'] not in ['live', 'closed']:
        if not current_user.is_authenticated or brief['users'][0]['id'] != current_user.id:
            abort(404, "Opportunity '{}' can not be found".format(brief_id))

    if current_user.is_authenticated and current_user.role == 'supplier':
        brief_responses = data_api_client.find_brief_responses(
            brief_id, current_user.supplier_code)["briefResponses"]
        selected_for_brief = _is_supplier_selected_for_brief(brief)
    else:
        brief_responses = None
        selected_for_brief = False

    brief['clarificationQuestions'] = [
        dict(question, number=index+1)
        for index, question in enumerate(brief['clarificationQuestions'])
    ]

    brief_content = content_loader.get_builder(framework_slug, 'display_brief').filter(
        brief
    )

    sections = brief_content.summary(brief)
    unanswered_required, unanswered_optional = count_unanswered_questions(sections)

    brief_of_current_user = False
    if not current_user.is_anonymous and len(brief.get('users')) > 0:
        brief_of_current_user = brief['users'][0]['id'] == current_user.id

    is_restricted_brief = brief.get('sellerSelector', '') in ('someSellers', 'oneSeller')

    brief_published_date = brief['dates'].get('published_date', None)
    feature_date = current_app.config['MULTI_CANDIDATE_PUBLISHED_DATE']

    published_date = pendulum.parse(brief_published_date) if brief_published_date else feature_date.subtract(days=1)
    application_url = "/2/brief/{}/respond".format(brief['id'])
    application_specialist_url = application_url
    application_specialist_submitted_url = None

    if published_date >= feature_date:
        application_specialist_url = "/2/brief/{}/specialist/respond".format(brief['id'])
        application_specialist_submitted_url = "/2/brief/{}/specialist/respond/submitted".format(brief['id'])

    application_training_url = "/2/brief/{}/training/respond".format(brief['id'])

    add_case_study_url = None

    profile_application_status = None
    supplier = None
    unassessed_domains = {}
    assessed_domains = {}
    profile_url = None
    supplier_assessments = {}
    supplier_framework = None

    if current_user.is_authenticated:
        if current_user.supplier_code is not None:
            supplier = data_api_client.get_supplier(
                current_user.supplier_code
            ).get('supplier', None)

        profile_application_id = current_user.application_id

        if supplier is not None:
            profile_url = '/supplier/{}'.format(supplier.get('code'))
            assessed_domains = supplier.get('domains').get('assessed', None)
            unassessed_domains = supplier.get('domains').get('unassessed', None)
            legacy_domains = supplier.get('domains').get('legacy', None)

            if profile_application_id is None:
                profile_application_id = supplier.get('application_id', None)

            supplier_code = supplier.get('code')
            supplier_assessments = data_api_client.req.assessments().supplier(supplier_code).get()

            if len(legacy_domains) != 0:
                for i in range(len(legacy_domains)):
                    supplier_assessments['assessed'].append(legacy_domains[i])

            supplier_framework_ids = supplier.get('frameworks')
            for i in range(len(supplier_framework_ids)):
                if supplier.get('frameworks')[i].get('framework_id') == 7:
                    supplier_framework = 'digital-marketplace'
            if supplier_framework is None:
                supplier_framework = 'digital-service-professionals'

        if profile_application_id is not None:
            try:
                profile_application = data_api_client.req.applications(profile_application_id).get()

                if unassessed_domains is None:
                    unassessed_domains = profile_application.get(
                        'application').get('supplier').get('domains', None).get('unassessed', None)
                if assessed_domains is None:
                    assessed_domains = profile_application.get(
                        'application').get('supplier').get('domains', None).get('assessed', None)

                profile_application_status = profile_application.get('application').get('status', None)
                if profile_application.get('application').get('type') == 'edit':
                    profile_application_status = 'approved'

            except APIError:
                pass
            except HTTPError:
                pass

    domain_id = None
    if brief.get('areaOfExpertise'):
        current_domain = data_api_client.req.domain(brief['areaOfExpertise']).get()
        domain_id = current_domain['domain']['id']
    elif brief['lotSlug'] == 'training':
        domain_id = 15  # training

    return render_template_with_csrf(
        'brief.html',
        add_case_study_url=add_case_study_url,
        application_url=application_url,
        application_specialist_url=application_specialist_url,
        application_specialist_submitted_url=application_specialist_submitted_url,
        application_training_url=application_training_url,
        assessed_domains=assessed_domains,
        brief=brief,
        brief_responses=brief_responses,
        brief_of_current_user=brief_of_current_user,
        content=brief_content,
        domain_id=domain_id,
        is_restricted_brief=is_restricted_brief,
        selected_for_brief=selected_for_brief,
        profile_application_status=profile_application_status,
        profile_url=profile_url,
        unassessed_domains=unassessed_domains,
        supplier_assessments=supplier_assessments,
        supplier_framework=supplier_framework,
        unanswered_required=unanswered_required,
        training_domain_name='Training, Learning and Development'
    )
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)
        )