def download_brief_responses(brief_id): brief = Brief.query.filter( Brief.id == brief_id ).first_or_404() brief_user_ids = [user.id for user in brief.users] if current_user.id not in brief_user_ids: return forbidden("Unauthorised to view brief or brief does not exist") if brief.status != 'closed': return forbidden("You can only download documents for closed briefs") response = ('', 404) if brief.lot.slug in ['digital-professionals', 'training', 'rfx', 'atm']: try: file = s3_download_file( 'brief-{}-resumes.zip'.format(brief_id), os.path.join(brief.framework.slug, 'archives', 'brief-{}'.format(brief_id)) ) except botocore.exceptions.ClientError as e: rollbar.report_exc_info() not_found("Brief documents not found for brief id '{}'".format(brief_id)) response = Response(file, mimetype='application/zip') response.headers['Content-Disposition'] = 'attachment; filename="brief-{}-responses.zip"'.format(brief_id) elif brief.lot.slug == 'digital-outcome': responses = BriefResponse.query.filter( BriefResponse.brief_id == brief_id, BriefResponse.withdrawn_at.is_(None) ).all() csvdata = generate_brief_responses_csv(brief, responses) response = Response(csvdata, mimetype='text/csv') response.headers['Content-Disposition'] = ( 'attachment; filename="responses-to-requirements-{}.csv"'.format(brief_id)) return response
def update_evidence(evidence_id): evidence = evidence_service.get_evidence_by_id(evidence_id) if not evidence or current_user.supplier_code != evidence.supplier_code: not_found("No evidence for id '%s' found" % (evidence_id)) if evidence.status != 'draft': abort('Only draft submissions can be edited') data = get_json_from_request() publish = False if 'publish' in data and data['publish']: del data['publish'] publish = True if 'maxDailyRate' in data: try: data['maxDailyRate'] = int(data['maxDailyRate']) except ValueError as e: data['maxDailyRate'] = 0 # Validate the evidence request data errors = EvidenceDataValidator(data, evidence=evidence).validate(publish=publish) if len(errors) > 0: abort(', '.join(errors)) if publish: evidence.submit() if current_app.config['JIRA_FEATURES']: create_evidence_assessment_in_jira.delay(evidence_id) try: send_evidence_assessment_requested_notification( evidence.domain_id, current_user.email_address) except Exception as e: current_app.logger.warn( 'Failed to send requested assessment email for evidence id: {}, {}' .format(evidence_id, e)) evidence.data = data evidence_service.save_evidence(evidence) try: publish_tasks.evidence.delay(publish_tasks.compress_evidence(evidence), 'updated', name=current_user.name, domain=evidence.domain.name, supplier_code=current_user.supplier_code) if publish: publish_tasks.evidence.delay( publish_tasks.compress_evidence(evidence), 'submitted', name=current_user.name, domain=evidence.domain.name, supplier_code=current_user.supplier_code) except Exception as e: pass return jsonify(evidence.serialize())
def decline_join_request(team_id, token): data = get_json_from_request() if 'reason' not in data or not data['reason']: abort('Must provide reason for decline') try: team = team_business.get_team(team_id) except NotFoundError as e: return not_found(e.message) except UnauthorisedError as e: return forbidden(e.message) join_request = team_business.get_join_request(token) if not join_request or int(join_request.data['team_id']) != team_id: return not_found( 'The token is invalid, or this request has already been declined or accepted' ) if ('user_id' in join_request.data and (team_member_service.get_team_members_by_user_id( team_id, [int(join_request.data['user_id'])]) or team_member_service.get_team_leads_by_user_id( team_id, [int(join_request.data['user_id'])]))): abort('This user is already a member of the team') team_business.decline_join_request(join_request, data['reason'], team_id) return jsonify(success=True)
def withdraw_brief_response(brief_response_id): """Withdraw brief responses (role=supplier) --- tags: - "Brief Response" security: - basicAuth: [] parameters: - name: brief_response_id in: path type: number required: true responses: 200: description: Successfully withdrawn a candidate schema: id: BriefResponse 400: description: brief_response_id not found """ brief_response = (brief_responses_service.find( id=brief_response_id, supplier_code=current_user.supplier_code).one_or_none()) if brief_response: if brief_response.withdrawn_at is None: brief_response.withdrawn_at = utcnow() brief_responses_service.save(brief_response) try: audit = AuditEvent( audit_type=audit_types.update_brief_response, user=current_user.email_address, data={'briefResponseId': brief_response.id}, db_object=brief_response) audit_service.save(audit) except Exception as e: extra_data = { 'audit_type': audit_types.update_brief_response, 'briefResponseId': brief_response.id } rollbar.report_exc_info(extra_data=extra_data) publish_tasks.brief_response.delay( publish_tasks.compress_brief_response(brief_response), 'withdrawn', user=current_user.email_address) else: abort( 'Brief response with brief_response_id "{}" is already withdrawn' .format(brief_response_id)) else: not_found( 'Cannot find brief response with brief_response_id :{} and supplier_code: {}' .format(brief_response_id, current_user.supplier_code)) return jsonify(briefResponses=brief_response.serialize()), 200
def withdraw_brief_response(brief_response_id): """Withdraw brief responses (role=supplier) --- tags: - "Brief Response" security: - basicAuth: [] parameters: - name: brief_response_id in: path type: number required: true responses: 200: description: Successfully withdrawn a candidate schema: id: BriefResponse 400: description: brief_response_id not found """ brief_response = (brief_responses_service .find(id=brief_response_id, supplier_code=current_user.supplier_code) .one_or_none()) if brief_response: if brief_response.withdrawn_at is None: brief_response.withdrawn_at = utcnow() brief_responses_service.save(brief_response) try: audit = AuditEvent( audit_type=audit_types.update_brief_response, user=current_user.email_address, data={ 'briefResponseId': brief_response.id }, db_object=brief_response ) audit_service.save(audit) except Exception as e: extra_data = {'audit_type': audit_types.update_brief_response, 'briefResponseId': brief_response.id} rollbar.report_exc_info(extra_data=extra_data) publish_tasks.brief_response.delay( publish_tasks.compress_brief_response(brief_response), 'withdrawn', user=current_user.email_address ) else: abort('Brief response with brief_response_id "{}" is already withdrawn'.format(brief_response_id)) else: not_found('Cannot find brief response with brief_response_id :{} and supplier_code: {}' .format(brief_response_id, current_user.supplier_code)) return jsonify(briefResponses=brief_response.serialize()), 200
def get_questions(brief_id): result = None try: result = questions_business.get_questions(current_user, brief_id) except NotFoundError as nfe: not_found(nfe.message) except UnauthorisedError as ue: return forbidden(ue.message) return jsonify(result), 200
def get_insight(): now = None incoming_month_ending = request.args.get('monthEnding', None) if incoming_month_ending: now = pendulum.parse(incoming_month_ending) try: insight = insight_business.get_insight(current_user, now) except NotFoundError as nfe: not_found(nfe.message) return jsonify(insight), 200
def get_join_request(team_id, token): try: team = team_business.get_team(team_id) except NotFoundError as e: return not_found(e.message) except UnauthorisedError as e: return forbidden(e.message) join_request = team_business.get_join_request(token) if not join_request or int(join_request.data['team_id']) != team_id: return not_found( 'The token is invalid, or this request has already been declined or accepted' ) return jsonify(join_request=join_request)
def download_brief_attachment(brief_id, slug): """Get brief attachments. --- tags: - brief parameters: - name: brief_id in: path type: number required: true - name: slug in: path type: string required: true responses: 200: description: Attachment retrieved successfully. 404: description: Attachment not found. 500: description: Unexpected error. """ brief = briefs.get(brief_id) brief_user_ids = [user.id for user in brief.users] if (hasattr(current_user, 'role') and (current_user.role == 'buyer' or (current_user.role == 'supplier' and _can_do_brief_response(brief_id)))): file = s3_download_file(slug, os.path.join(brief.framework.slug, 'attachments', 'brief-' + str(brief_id))) mimetype = mimetypes.guess_type(slug)[0] or 'binary/octet-stream' return Response(file, mimetype=mimetype) else: return not_found('File not found')
def get_answers(brief_id): result = None try: result = questions_business.get_answers(brief_id) except NotFoundError as nfe: return not_found(nfe.message) return jsonify(result), 200
def get_brief_response(brief_response_id): """Get brief response (role=supplier) --- tags: - "Brief Response" security: - basicAuth: [] parameters: - name: brief_response_id in: path type: number required: true definitions: BriefResponse: type: object properties: id: type: number data: type: object brief_id: type: number supplier_code: type: number responses: 200: description: A brief response on id schema: id: BriefResponse 404: description: brief_response_id not found """ brief_response = brief_responses_service.find( id=brief_response_id, supplier_code=current_user.supplier_code).one_or_none() if brief_response: if brief_response.withdrawn_at is not None: abort('Brief response {} is withdrawn'.format(brief_response_id)) else: not_found( 'Cannot find brief response with brief_response_id :{} and supplier_code: {}' .format(brief_response_id, current_user.supplier_code)) return jsonify(brief_response.serialize())
def get_brief_response(brief_response_id): """Get brief response (role=supplier) --- tags: - "Brief Response" security: - basicAuth: [] parameters: - name: brief_response_id in: path type: number required: true definitions: BriefResponse: type: object properties: id: type: number data: type: object brief_id: type: number supplier_code: type: number responses: 200: description: A brief response on id schema: id: BriefResponse 404: description: brief_response_id not found """ brief_response = brief_responses_service.find(id=brief_response_id, supplier_code=current_user.supplier_code).one_or_none() if brief_response: if brief_response.withdrawn_at is not None: abort('Brief response {} is withdrawn'.format(brief_response_id)) else: not_found('Cannot find brief response with brief_response_id :{} and supplier_code: {}' .format(brief_response_id, current_user.supplier_code)) return jsonify(brief_response.serialize())
def get_team(team_id): team = None try: team = team_business.get_team(team_id) except NotFoundError as e: return not_found(e.message) except UnauthorisedError as e: return forbidden(e.message) return jsonify(team)
def get_evidence(evidence_id): evidence = evidence_service.get_evidence_by_id(evidence_id) if not evidence or current_user.supplier_code != evidence.supplier_code: not_found("No evidence for id '%s' found" % (evidence_id)) data = evidence.serialize() data['failed_criteria'] = {} data['previous_evidence_id'] = None previous_evidence = evidence_service.get_previous_submitted_evidence_for_supplier_and_domain( evidence.id, evidence.domain.id, current_user.supplier_code) if previous_evidence and previous_evidence.status == 'rejected': previous_assessment = evidence_assessment_service.get_assessment_for_rejected_evidence( previous_evidence.id) if previous_assessment: data['failed_criteria'] = previous_assessment.data.get( 'failed_criteria', {}) data['previous_evidence_id'] = previous_evidence.id return jsonify(data)
def create_team(): try: team = team_business.create_team() except TeamError as e: abort(e.message) except NotFoundError as e: return not_found(e.message) except UnauthorisedError as e: return forbidden(e.message) return jsonify(team)
def request_to_join(team_id): try: team_business.request_to_join(current_user.email_address, team_id, current_user.agency_id) except NotFoundError as e: return not_found(e.message) except UnauthorisedError as e: return forbidden(e.message) except ValidationError as e: abort(e.message) return jsonify(success=True)
def publish_answer(brief_id): data = get_json_from_request() try: questions_business.publish_answer(current_user, brief_id, data) except NotFoundError as nfe: return not_found(nfe.message) except ValidationError as ve: return abort(ve.message) except UnauthorisedError as ue: return forbidden(ue.message) return jsonify(success=True), 200
def get_redirect(key): """Get redirect --- tags: - redirects parameters: - name: key in: path type: string required: true responses: 302: description: a redirect """ key_value = key_values_service.get_by_key('redirects') redirect_url = key_value.get('data', {}).get(key) if not redirect_url: not_found('redirect not found') return redirect(redirect_url)
def update_team(team_id): data = get_json_from_request() try: team = team_business.update_team(team_id, data) except ValidationError as e: return abort(e.message) except NotFoundError as e: return not_found(e.message) except UnauthorisedError as e: return forbidden(e.message) return jsonify(team)
def upload_brief_rfx_attachment_file(brief_id, slug): """Add brief attachments (role=buyer) --- tags: - brief parameters: - name: brief_id in: path type: number required: true - name: slug in: path type: string required: true - name: file in: body required: true responses: 200: description: Attachment uploaded successfully. 403: description: Unauthorised to update brief. 404: description: Brief not found. 500: description: Unexpected error. """ brief = briefs.get(brief_id) if not brief: not_found("Invalid brief id '{}'".format(brief_id)) brief_user_ids = [user.id for user in brief.users] if current_user.id not in brief_user_ids: return forbidden('Unauthorised to update brief') return jsonify({"filename": s3_upload_file_from_request(request, slug, os.path.join(brief.framework.slug, 'attachments', 'brief-' + str(brief_id))) })
def get_notification_template(brief_id, template): brief = briefs.get(brief_id) if brief: frontend_url = current_app.config['FRONTEND_ADDRESS'] return render_email_template( '{}.md'.format(template), frontend_url=frontend_url, brief_name=brief.data['title'], brief_id=brief.id, brief_url='{}/digital-marketplace/opportunities/{}'.format(frontend_url, brief_id) ) return not_found('brief not found')
def get_domain(domain_id): domain = domain_service.get_by_name_or_id(domain_id, show_legacy=False) if not domain: return not_found('Domain does not exist') data = domain.serialize() data['criteriaEnforcementCutoffDate'] = None key_value = key_values_service.get_by_key('criteria_enforcement_cutoff_date') if key_value: data['criteriaEnforcementCutoffDate'] = ( pendulum.parse(key_value['data']['value'], tz='Australia/Canberra').isoformat() ) return jsonify(data)
def get_suppliers_responded(brief_id): """Get suppliers responded (role=buyer) --- tags: - "Brief Response" security: - basicAuth: [] parameters: - name: brief_response_id in: path type: number required: true definitions: BriefResponse: type: object properties: id: type: number data: type: object brief_id: type: number supplier_code: type: number responses: 200: description: Suppliers that have responded to brief_id schema: id: BriefResponse 404: description: brief_response_id not found """ brief = briefs.get(brief_id) if not brief: return not_found('brief {} not found'.format(brief_id)) if not briefs.has_permission_to_brief(current_user.id, brief.id): return forbidden('Unauthorised to get suppliers responded') suppliers = brief_responses_service.get_suppliers_responded(brief_id) work_order = work_order_service.find(brief_id=brief_id).one_or_none() return jsonify(brief=brief.serialize(with_users=False), suppliers=suppliers, workOrderCreated=True if work_order else False)
def update_brief(brief_id): """Update RFX brief (role=buyer) --- tags: - brief definitions: RFXBrief: type: object properties: title: type: string organisation: type: string location: type: array items: type: string summary: type: string industryBriefing: type: string sellerCategory: type: string sellers: type: object attachments: type: array items: type: string requirementsDocument: type: array items: type: string responseTemplate: type: array items: type: string evaluationType: type: array items: type: string proposalType: type: array items: type: string evaluationCriteria: type: array items: type: object includeWeightings: type: boolean closedAt: type: string contactNumber: type: string startDate: type: string contractLength: type: string contractExtensions: type: string budgetRange: type: string workingArrangements: type: string securityClearance: type: string parameters: - name: brief_id in: path type: number required: true - name: body in: body required: true schema: $ref: '#/definitions/RFXBrief' responses: 200: description: Brief updated successfully. schema: $ref: '#/definitions/RFXBrief' 400: description: Bad request. 403: description: Unauthorised to update RFX brief. 404: description: Brief not found. 500: description: Unexpected error. """ brief = briefs.get(brief_id) if not brief: not_found("Invalid brief id '{}'".format(brief_id)) if brief.status != 'draft': abort('Cannot edit a {} brief'.format(brief.status)) if brief.lot.slug not in ['rfx', 'atm']: abort('Brief lot not supported for editing') if current_user.role == 'buyer': brief_user_ids = [user.id for user in brief.users] if current_user.id not in brief_user_ids: return forbidden('Unauthorised to update brief') data = get_json_from_request() publish = False if 'publish' in data and data['publish']: del data['publish'] publish = True if brief.lot.slug == 'rfx': # validate the RFX JSON request data errors = RFXDataValidator(data).validate(publish=publish) if len(errors) > 0: abort(', '.join(errors)) if brief.lot.slug == 'atm': # validate the ATM JSON request data errors = ATMDataValidator(data).validate(publish=publish) if len(errors) > 0: abort(', '.join(errors)) if brief.lot.slug == 'rfx' and 'evaluationType' in data: if 'Written proposal' not in data['evaluationType']: data['proposalType'] = [] if 'Response template' not in data['evaluationType']: data['responseTemplate'] = [] if brief.lot.slug == 'rfx' and 'sellers' in data and len(data['sellers']) > 0: data['sellerSelector'] = 'someSellers' if len(data['sellers']) > 1 else 'oneSeller' data['areaOfExpertise'] = '' if brief.lot.slug == 'atm' and 'openTo' in data: if data['openTo'] == 'all': data['sellerSelector'] = 'allSellers' data['sellerCategory'] = '' elif data['openTo'] == 'category': data['sellerSelector'] = 'someSellers' brief_domain = ( domain_service.get_by_name_or_id(int(data['sellerCategory'])) if data['sellerCategory'] else None ) if brief_domain: data['areaOfExpertise'] = brief_domain.name previous_status = brief.status if publish: brief.publish(closed_at=data['closedAt']) if 'sellers' in brief.data and data['sellerSelector'] != 'allSellers': for seller_code, seller in brief.data['sellers'].iteritems(): supplier = suppliers.get_supplier_by_code(seller_code) if brief.lot.slug == 'rfx': send_seller_invited_to_rfx_email(brief, supplier) try: brief_url_external = '{}/2/digital-marketplace/opportunities/{}'.format( current_app.config['FRONTEND_ADDRESS'], brief_id ) _notify_team_brief_published( brief.data['title'], brief.data['organisation'], current_user.name, current_user.email_address, brief_url_external ) except Exception as e: pass brief.data = data briefs.save_brief(brief) if publish: brief_url_external = '{}/2/digital-marketplace/opportunities/{}'.format( current_app.config['FRONTEND_ADDRESS'], brief_id ) publish_tasks.brief.delay( publish_tasks.compress_brief(brief), 'published', previous_status=previous_status, name=current_user.name, email_address=current_user.email_address, url=brief_url_external ) try: audit_service.log_audit_event( audit_type=AuditTypes.update_brief, user=current_user.email_address, data={ 'briefId': brief.id, 'briefData': brief.data }, db_object=brief) except Exception as e: rollbar.report_exc_info() return jsonify(brief.serialize(with_users=False))
def delete_brief(brief_id): """Delete brief (role=buyer) --- tags: - brief definitions: DeleteBrief: type: object properties: message: type: string parameters: - name: brief_id in: path type: number required: true responses: 200: description: Brief deleted successfully. schema: $ref: '#/definitions/DeleteBrief' 400: description: Bad request. Brief status must be 'draft'. 403: description: Unauthorised to delete brief. 404: description: brief_id not found. 500: description: Unexpected error. """ brief = briefs.get(brief_id) if not brief: not_found("Invalid brief id '{}'".format(brief_id)) if current_user.role == 'buyer': brief_user_ids = [user.id for user in brief.users] if current_user.id not in brief_user_ids: return forbidden('Unauthorised to delete brief') if brief.status != 'draft': abort('Cannot delete a {} brief'.format(brief.status)) audit = AuditEvent( audit_type=AuditTypes.delete_brief, user=current_user.email_address, data={ 'briefId': brief_id }, db_object=None ) try: deleted_brief = publish_tasks.compress_brief(brief) audit_service.save(audit) briefs.delete(brief) publish_tasks.brief.delay( deleted_brief, 'deleted', user=current_user.email_address ) except Exception as e: extra_data = {'audit_type': AuditTypes.delete_brief, 'briefId': brief.id, 'exception': e.message} rollbar.report_exc_info(extra_data=extra_data) return jsonify(message='Brief {} deleted'.format(brief_id)), 200
def get_domain(domain_id): domain = domain_service.get_by_name_or_id(domain_id, show_legacy=False) if not domain: return not_found('Domain does not exist') return jsonify(domain.serialize())
def get_brief_overview(brief_id): """Overview (role=buyer) --- tags: - brief definitions: BriefOverview: type: object properties: sections: type: array items: $ref: '#/definitions/BriefOverviewSections' title: type: string BriefOverviewSections: type: array items: $ref: '#/definitions/BriefOverviewSection' BriefOverviewSection: type: object properties: links: type: array items: $ref: '#/definitions/BriefOverviewSectionLinks' title: type: string BriefOverviewSectionLinks: type: array items: $ref: '#/definitions/BriefOverviewSectionLink' BriefOverviewSectionLink: type: object properties: complete: type: boolean path: type: string nullable: true text: type: string responses: 200: description: Data for the Overview page schema: $ref: '#/definitions/BriefOverview' 400: description: Lot not supported. 403: description: Unauthorised to view brief. 404: description: brief_id not found """ brief = briefs.get(brief_id) if not brief: not_found("Invalid brief id '{}'".format(brief_id)) if current_user.role == 'buyer': brief_user_ids = [user.id for user in brief.users] if current_user.id not in brief_user_ids: return forbidden('Unauthorised to view brief') if not (brief.lot.slug == 'digital-professionals' or brief.lot.slug == 'training'): abort('Lot {} is not supported'.format(brief.lot.slug)) sections = brief_overview_service.get_sections(brief) return jsonify(sections=sections, status=brief.status, title=brief.data['title']), 200
def get_evidence_feedback(evidence_id): evidence = evidence_service.get_evidence_by_id(evidence_id) if not evidence or current_user.supplier_code != evidence.supplier_code: not_found("No evidence for id '%s' found" % (evidence_id)) if not evidence.status == 'rejected': abort('Only rejected submissions can contain feedback') evidence_assessment = evidence_assessment_service.get_assessment_for_rejected_evidence( evidence_id) if not evidence_assessment: abort('Failed to get the evidence assessment') try: domain_criteria = DomainCriteria(domain_id=evidence.domain.id, rate=evidence.data.get( 'maxDailyRate', None)) criteria_needed = domain_criteria.get_criteria_needed() except Exception as e: abort(str(e)) criteria_from_domain = {} domain_criteria = domain_criteria_service.get_criteria_by_domain_id( evidence.domain.id) for criteria in domain_criteria: criteria_from_domain[str(criteria.id)] = criteria.name criteria = {} failed_criteria = evidence_assessment.data.get('failed_criteria', {}) vfm = evidence_assessment.data.get('vfm', None) for criteria_id, criteria_response in evidence.get_criteria_responses( ).iteritems(): has_feedback = True if criteria_id in failed_criteria.keys() else False criteria[criteria_id] = { "response": criteria_response, "name": criteria_from_domain[criteria_id] if criteria_id in criteria_from_domain else '', "has_feedback": has_feedback, "assessment": failed_criteria[criteria_id] if has_feedback else {} } current_evidence = evidence_service.get_latest_evidence_for_supplier_and_domain( evidence.domain.id, current_user.supplier_code) data = { 'domain_id': evidence.domain.id, 'domain_name': evidence.domain.name, 'criteria': criteria, 'criteria_needed': criteria_needed, 'current_evidence_id': current_evidence.id if current_evidence.status == 'draft' else None, 'vfm': vfm } return jsonify(data)
def get_brief_responses(brief_id): """All brief responses (role=supplier,buyer) --- tags: - brief security: - basicAuth: [] parameters: - name: brief_id in: path type: number required: true definitions: BriefResponses: properties: briefResponses: type: array items: id: BriefResponse responses: 200: description: A list of brief responses schema: id: BriefResponses 404: description: brief_id not found """ brief = briefs.get(brief_id) if not brief: not_found("Invalid brief id '{}'".format(brief_id)) if current_user.role == 'buyer': brief_user_ids = [user.id for user in brief.users] if current_user.id not in brief_user_ids: return forbidden("Unauthorised to view brief or brief does not exist") supplier_code = getattr(current_user, 'supplier_code', None) if current_user.role == 'supplier': validation_result = supplier_business.get_supplier_messages(supplier_code, True) if len(validation_result.errors) > 0: abort(validation_result.errors) # strip data from seller view if 'sellers' in brief.data: brief.data['sellers'] = {} if brief.responses_zip_filesize: brief.responses_zip_filesize = None if 'industryBriefing' in brief.data: brief.data['industryBriefing'] = '' if 'attachments' in brief.data: brief.data['attachments'] = [] if 'backgroundInformation' in brief.data: brief.data['backgroundInformation'] = '' if 'outcome' in brief.data: brief.data['outcome'] = '' if 'endUsers' in brief.data: brief.data['endUsers'] = '' if 'workAlreadyDone' in brief.data: brief.data['workAlreadyDone'] = '' if 'timeframeConstraints' in brief.data: brief.data['timeframeConstraints'] = '' if 'contactNumber' in brief.data: brief.data['contactNumber'] = '' if current_user.role == 'buyer' and brief.status != 'closed': brief_responses = [] else: brief_responses = brief_responses_service.get_brief_responses(brief_id, supplier_code) return jsonify(brief=brief.serialize(with_users=False, with_author=False), briefResponses=brief_responses)
def get_brief(brief_id): """Get brief --- tags: - brief parameters: - name: brief_id in: path type: number required: true responses: 200: description: Brief retrieved successfully. schema: type: object properties: brief: type: object brief_response_count: type: number invited_seller_count: type: number can_respond: type: boolean open_to_all: type: boolean is_brief_owner: type: boolean is_buyer: type: boolean has_responded: type: boolean has_chosen_brief_category: type: boolean is_assessed_for_category: type: boolean is_assessed_in_any_category: type: boolean is_approved_seller: type: boolean is_awaiting_application_assessment: type: boolean is_awaiting_domain_assessment: type: boolean has_been_assessed_for_brief: type: boolean open_to_category: type: boolean is_applicant: type: boolean is_recruiter: type: boolean domains: type: array items: type: object 403: description: Unauthorised to view brief. 404: description: Brief not found. 500: description: Unexpected error. """ brief = briefs.find(id=brief_id).one_or_none() if not brief: not_found("No brief for id '%s' found" % (brief_id)) user_role = current_user.role if hasattr(current_user, 'role') else None invited_sellers = brief.data['sellers'] if 'sellers' in brief.data else {} is_buyer = False is_brief_owner = False brief_user_ids = [user.id for user in brief.users] if user_role == 'buyer': is_buyer = True if current_user.id in brief_user_ids: is_brief_owner = True if brief.status == 'draft' and not is_brief_owner: return forbidden("Unauthorised to view brief") brief_response_count = len(brief_responses_service.get_brief_responses(brief_id, None)) invited_seller_count = len(invited_sellers) open_to_all = brief.lot.slug == 'atm' and brief.data.get('openTo', '') == 'all' open_to_category = brief.lot.slug == 'atm' and brief.data.get('openTo', '') == 'category' is_applicant = user_role == 'applicant' # gather facts about the user's status against this brief user_status = BriefUserStatus(brief, current_user) has_chosen_brief_category = user_status.has_chosen_brief_category() is_assessed_for_category = user_status.is_assessed_for_category() is_assessed_in_any_category = user_status.is_assessed_in_any_category() is_awaiting_application_assessment = user_status.is_awaiting_application_assessment() is_awaiting_domain_assessment = user_status.is_awaiting_domain_assessment() has_been_assessed_for_brief = user_status.has_been_assessed_for_brief() is_recruiter_only = user_status.is_recruiter_only() is_approved_seller = user_status.is_approved_seller() can_respond = user_status.can_respond() has_responded = user_status.has_responded() # remove private data for non brief owners brief.data['contactEmail'] = '' brief.data['users'] = None if not is_buyer: if 'sellers' in brief.data: brief.data['sellers'] = {} brief.responses_zip_filesize = None brief.data['contactNumber'] = '' if not can_respond: brief.data['proposalType'] = [] brief.data['evaluationType'] = [] brief.data['responseTemplate'] = [] brief.data['requirementsDocument'] = [] brief.data['industryBriefing'] = '' brief.data['backgroundInformation'] = '' brief.data['outcome'] = '' brief.data['endUsers'] = '' brief.data['workAlreadyDone'] = '' brief.data['timeframeConstraints'] = '' brief.data['attachments'] = [] else: brief.data['contactEmail'] = [user.email_address for user in brief.users][0] if not is_brief_owner: if 'sellers' in brief.data: brief.data['sellers'] = {} brief.data['industryBriefing'] = '' brief.data['contactNumber'] = '' domains = [] for domain in domain_service.all(): domains.append({ 'id': str(domain.id), 'name': domain.name }) return jsonify(brief=brief.serialize(with_users=False, with_author=is_brief_owner), brief_response_count=brief_response_count, invited_seller_count=invited_seller_count, can_respond=can_respond, has_chosen_brief_category=has_chosen_brief_category, is_assessed_for_category=is_assessed_for_category, is_assessed_in_any_category=is_assessed_in_any_category, is_approved_seller=is_approved_seller, is_awaiting_application_assessment=is_awaiting_application_assessment, is_awaiting_domain_assessment=is_awaiting_domain_assessment, has_been_assessed_for_brief=has_been_assessed_for_brief, open_to_all=open_to_all, open_to_category=open_to_category, is_brief_owner=is_brief_owner, is_buyer=is_buyer, is_applicant=is_applicant, is_recruiter_only=is_recruiter_only, has_responded=has_responded, domains=domains)