def get_previous_evidence_and_feedback(evidence_id): evidence = evidence_service.get_evidence_by_id(evidence_id) if not evidence: abort(404) if evidence.status not in ['assessed', 'rejected']: abort(404) evidence_data = evidence.serialize() if evidence_data: domain_criteria = domain_criteria_service.get_criteria_by_domain_id(evidence_data['domainId']) evidence_data['domain_criteria'] = [x.serialize() for x in domain_criteria] evidence_data['domain_price_maximum'] = evidence.domain.price_maximum feedback = evidence_assessment_service.find(evidence_id=evidence.id).one_or_none() if feedback: evidence_data['feedback'] = feedback.serialize() assessor = users.find(id=int(feedback.user_id)).one_or_none() evidence_data['assessor'] = assessor.name if assessor else '' evidence_data['domainName'] = evidence.domain.name supplier = suppliers.get_supplier_by_code(evidence.supplier_code) evidence_data['supplierName'] = supplier.name if supplier else '' try: evidence_data['criteriaNeeded'] = int( DomainCriteria( domain_id=evidence_data.get('domainId', None), rate=evidence_data.get('maxDailyRate', None) ).get_criteria_needed() ) except DomainCriteriaInvalidRateException as e: abort(400, str(e)) return jsonify(evidence=evidence_data), 200
def decline_agreement(user_info): supplier_code = user_info.get('supplier_code') email_address = user_info.get('email_address') supplier = suppliers.get_supplier_by_code(supplier_code) mandatory_supplier_checks(supplier) if email_address != supplier.data.get('email'): raise UnauthorisedError('Unauthorised to decline agreement') supplier_users = users.find(supplier_code=supplier_code).all() supplier.status = 'deleted' for user in supplier_users: user.active = False users.add_to_session(user) users.commit_changes() suppliers.save(supplier) send_decline_master_agreement_email(supplier.code) publish_tasks.supplier.delay(publish_tasks.compress_supplier(supplier), 'declined_agreement', updated_by=email_address) audit_service.log_audit_event( audit_type=audit_types.declined_master_agreement, user=email_address, data={ 'supplierCode': supplier.code, 'supplierData': supplier.data }, db_object=supplier)
def update_brief_add_rfx_seller(brief_id, supplier_code): updater_json = validate_and_return_updater_request() # Using the helper.py methods to get the matching brief. brief = briefs.get(brief_id) supplier = suppliers.get_supplier_by_code(supplier_code) if not supplier: raise ValidationError("No supplier found: " + supplier_code) sellers = brief.data['sellers'] sellers[str(supplier_code)] = {'name': supplier.name} brief.data['sellers'] = sellers audit = AuditEvent( audit_type=AuditTypes.seller_added_to_rfx_opportunity_admin, user=updater_json['updated_by'], data={ 'briefId': brief.id, 'supplier_code': supplier_code, }, db_object=brief, ) db.session.add(brief) db.session.add(audit) db.session.commit() return jsonify(briefs=brief.serialize(with_users=True)), 200
def get_supplier_messages(code, skip_application_check): applications = application_service.find( supplier_code=code, type='edit' ).all() supplier = suppliers.get_supplier_by_code(code) validation_result = SupplierValidator(supplier).validate_all() if any([a for a in applications if a.status == 'saved']): validation_result.warnings.append({ 'message': 'You have saved updates on your profile. ' 'You must submit these changes to the Marketplace for review. ' 'If you did not make any changes, select \'Discard all updates\'.', 'severity': 'warning', 'step': 'update', 'id': 'SB001' }) if not skip_application_check: if any([a for a in applications if a.status == 'submitted']): del validation_result.warnings[:] del validation_result.errors[:] if not has_signed_current_agreement(supplier): if get_current_agreement(): message = ( 'Your authorised representative {must accept the new Master Agreement} ' 'before you can apply for opportunities.' ) validation_result.errors.append({ 'message': message, 'severity': 'error', 'step': 'representative', 'id': 'SB002', 'links': { 'must accept the new Master Agreement': '/2/seller-edit/{}/representative'.format(code) } }) else: new_master_agreement = get_new_agreement() if new_master_agreement: start_date = new_master_agreement.start_date.in_tz('Australia/Canberra').date() message = ( 'From {}, your authorised representative must ' 'accept the new Master Agreement ' 'before you can apply for opportunities.' ).format(start_date.strftime('%-d %B %Y')) validation_result.warnings.append({ 'message': message, 'severity': 'warning', 'step': 'representative', 'id': 'SB002' }) return validation_result
def approve_domain(self): supplier = suppliers.get_supplier_by_code(self.evidence.supplier_code) if not supplier: raise DomainApprovalException('Invalid suppier code in evidence') domain = domain_service.find(id=self.evidence.domain_id).one_or_none() if not domain: raise DomainApprovalException('Invalid domain id in evidence') # insert the supplier_domain as assessed for this supplier and domain supplier_domain_service.set_supplier_domain_status( supplier.id, domain.id, 'assessed', 'approved', do_commit=False ) # set the evidence as approved self.evidence.approve() evidence_service.save_evidence(self.evidence, do_commit=False) # update the supplier's pricing for the evidence's domain supplier_data = supplier.data.copy() if 'pricing' not in supplier_data: supplier_data['pricing'] = {} supplier_data['pricing'][domain.name] = {'maxPrice': str(self.evidence.data['maxDailyRate'])} supplier.data.update({'pricing': supplier_data['pricing']}) suppliers.save_supplier(supplier, do_commit=False) # create the evidence assessment outcome evidence_assessment = evidence_assessment_service.create_assessment( evidence_id=self.evidence.id, user_id=self.actioned_by, status='approved', do_commit=False ) self.__commit() try: publish_tasks.evidence.delay( publish_tasks.compress_evidence(self.evidence), 'approved', actioned_by=self.actioned_by, evidence_assessment=evidence_assessment.serialize(), domain=domain.name, supplier_code=supplier.code ) except Exception as e: pass return evidence_assessment
def validate_sellers(self): if not self.data['sellers']: return False if not len(self.data['sellers']) > 0: return False for supplier_code in self.data['sellers']: supplier = suppliers.get_supplier_by_code(int(supplier_code)) if not supplier: return False if suppliers.get_supplier_assessed_status(supplier.id, int(self.data['sellerCategory'])) != 'assessed': return False return True
def send_notify_auth_rep_email(supplier_code): from app.api.services import ( audit_service, audit_types, suppliers, key_values_service ) supplier = suppliers.get_supplier_by_code(supplier_code) to_address = supplier.data.get('email', '').encode('utf-8') agreement = get_new_agreement() if agreement is None: agreement = get_current_agreement() start_date = pendulum.now('Australia/Canberra').date() if agreement: start_date = agreement.start_date.in_tz('Australia/Canberra') # prepare copy email_body = render_email_template( 'seller_edit_notify_auth_rep.md', ma_start_date=start_date.strftime('%-d %B %Y'), supplier_name=supplier.name, supplier_code=supplier.code, auth_rep_name=escape_markdown(supplier.data.get('representative', '')), frontend_url=current_app.config['FRONTEND_ADDRESS'] ) subject = "Accept the Master Agreement for the Digital Marketplace" send_or_handle_error( to_address, email_body, subject, current_app.config['DM_GENERIC_NOREPLY_EMAIL'], current_app.config['DM_GENERIC_SUPPORT_NAME'], event_description_for_errors='notify auth rep email' ) audit_service.log_audit_event( audit_type=audit_types.notify_auth_rep_accept_master_agreement, user='', data={ "to_address": to_address, "email_body": email_body, "subject": subject }, db_object=supplier)
def notify_auth_rep(user_info): supplier_code = user_info.get('supplier_code') email_address = user_info.get('email_address') supplier = suppliers.get_supplier_by_code(supplier_code) mandatory_supplier_checks(supplier) send_notify_auth_rep_email(supplier.code) audit_service.log_audit_event( audit_type=audit_types.notify_auth_rep_accept_master_agreement, user=email_address, data={ 'supplierCode': supplier.code, 'supplierData': supplier.data }, db_object=supplier)
def __init__(self, brief, current_user): self.brief = brief self.current_user = current_user self.supplier = None self.supplier_code = None self.user_role = current_user.role if hasattr(current_user, 'role') else None self.brief_category = None self.brief_domain = None self.invited_sellers = {} if self.user_role == 'supplier' and hasattr(current_user, 'supplier_code'): self.supplier_code = current_user.supplier_code self.supplier = suppliers.get_supplier_by_code(self.supplier_code) if brief: self.brief_category = self.brief.data.get('sellerCategory', '') self.brief_domain = ( domain_service.get_by_name_or_id(int(self.brief_category)) if self.brief_category else None ) self.invited_sellers = self.brief.data['sellers'] if 'sellers' in self.brief.data else {}
def get_supplier_edit_info(user_info): supplier_code = user_info.get('supplier_code') email_address = user_info.get('email_address') supplier = suppliers.get_supplier_by_code(supplier_code) agreementStatus = get_agreement_status(supplier, user_info) return { 'supplier': { 'name': supplier.name, 'code': supplier.code, 'abn': supplier.abn, 'data': { 'representative': supplier.data.get('representative'), 'email': supplier.data.get('email'), 'phone': supplier.data.get('phone') } }, 'agreementStatus': agreementStatus }
def __init__(self, brief, current_user): self.brief = brief self.current_user = current_user self.supplier = None self.supplier_code = None self.user_role = current_user.role if hasattr(current_user, 'role') else None self.brief_category = None self.brief_domain = None self.invited_sellers = {} if self.user_role == 'supplier' and hasattr(current_user, 'supplier_code'): self.supplier_code = current_user.supplier_code self.supplier = suppliers.get_supplier_by_code(self.supplier_code) if brief: self.brief_category = self.brief.data.get('sellerCategory', '') self.brief_domain = (domain_service.get_by_name_or_id( int(self.brief_category)) if self.brief_category else None) self.invited_sellers = self.brief.data[ 'sellers'] if 'sellers' in self.brief.data else {}
def accept_agreement(user_info): supplier_code = user_info.get('supplier_code') email_address = user_info.get('email_address') user_id = user_info.get('user_id') supplier = suppliers.get_supplier_by_code(supplier_code) mandatory_supplier_checks(supplier) if email_address != supplier.data.get('email'): raise UnauthorisedError('Unauthorised to accept agreement') agreement = get_current_agreement() if agreement is None: raise NotFoundError('Current master agreement not found') already_signed = signed_agreement_service.first( agreement_id=agreement.id, supplier_code=supplier_code) if already_signed: raise ValidationError('Already signed agreement') signed_agreement = SignedAgreement( agreement_id=agreement.id, user_id=user_id, signed_at=pendulum.now('Australia/Canberra'), supplier_code=supplier_code) signed_agreement_service.save(signed_agreement) publish_tasks.supplier.delay(publish_tasks.compress_supplier(supplier), 'accepted_agreement', updated_by=email_address) audit_service.log_audit_event( audit_type=audit_types.accepted_master_agreement, user=email_address, data={ 'supplierCode': supplier.code, 'supplierData': supplier.data }, db_object=supplier)
def send_decline_master_agreement_email(supplier_code): from app.api.services import ( audit_service, audit_types, suppliers ) supplier = suppliers.get_supplier_by_code(supplier_code) to_addresses = [ e['email_address'] for e in suppliers.get_supplier_contacts(supplier_code) ] # prepare copy email_body = render_email_template( 'seller_edit_decline.md', frontend_url=current_app.config['FRONTEND_ADDRESS'] ) subject = "You declined the new Master Agreement" send_or_handle_error( to_addresses, email_body, subject, current_app.config['DM_GENERIC_NOREPLY_EMAIL'], current_app.config['DM_GENERIC_SUPPORT_NAME'], event_description_for_errors='declined master agreement email' ) audit_service.log_audit_event( audit_type=audit_types.declined_master_agreement_email, user='', data={ "to_address": to_addresses, "email_body": email_body, "subject": subject }, db_object=supplier)
def get_categories(): """Supplier dashboard (Categories) (role=supplier) --- tags: - dashboard definitions: SellerDashboardCategoryItems: type: object properties: categories: type: array items: $ref: '#/definitions/SellerDashboardCategoryItem' SellerDashboardCategoryItem: type: object properties: id: type: number name: type: string status: type: string is_approved: type: boolean evidence_id: type: number responses: 200: description: Seller dashboard data for the 'Categories' tab schema: $ref: '#/definitions/SellerDashboardCategoryItems' """ categories = [] supplier = suppliers.get_supplier_by_code(current_user.supplier_code) for domain in domain_service.get_active_domains(): is_approved = True if domain.name in supplier.assessed_domains else False data = { "id": domain.id, "name": domain.name, "previous_evidence_id": None, "evidence_id": None, "is_approved": is_approved } domain_evidence = evidence_service.get_latest_evidence_for_supplier_and_domain( domain.id, current_user.supplier_code, ) if domain_evidence: previous_evidence = evidence_service.get_previous_submitted_evidence_for_supplier_and_domain( domain_evidence.id, domain.id, current_user.supplier_code) if previous_evidence and previous_evidence.status == 'rejected': data['previous_evidence_id'] = previous_evidence.id data['status'] = domain_evidence.status data['evidence_id'] = domain_evidence.id else: # is there a submitted case study assessment in progress? open_assessment = assessments.get_open_assessments( domain_id=domain.id, supplier_code=supplier.code) if open_assessment: data['status'] = 'submitted' else: assessed_status = suppliers.get_supplier_assessed_status( supplier.id, domain.id) data[ 'status'] = assessed_status if assessed_status else 'unassessed' # override the status as unassessed if the domain is not in the assessed domains if data['status'] == 'assessed' and not is_approved: data['status'] = 'unassessed' data['rate'] = suppliers.get_supplier_max_price_for_domain( current_user.supplier_code, domain.name) categories.append(data) # sort by status categories_sorted = [] categories_sorted += [ x for x in categories if x['status'] == 'rejected' ] categories_sorted += [x for x in categories if x['status'] == 'draft'] categories_sorted += [ x for x in categories if x['status'] == 'submitted' ] categories_sorted += [ x for x in categories if x['status'] == 'assessed' ] categories_sorted += [ x for x in categories if x['status'] == 'unassessed' ] return jsonify(categories={'items': categories_sorted}), 200
def edit_opportunity(user_id, brief_id, edits): brief = brief_service.get(brief_id) if not brief: raise NotFoundError('Opportunity {} does not exist'.format(brief_id)) if not brief_service.has_permission_to_brief(user_id, brief_id): raise UnauthorisedError( 'Not authorised to edit opportunity {}'.format(brief_id)) if brief.status != 'live': raise BriefError('Unable to edit opportunity {}'.format(brief_id)) user = user_service.get(user_id) if not user: raise NotFoundError('User {} does not exist'.format(user_id)) previous_data = copy.deepcopy(brief.data) previous_data['closed_at'] = brief.closed_at.to_iso8601_string( extended=True) edit_title(brief, edits['title']) edit_summary(brief, edits['summary']) edit_closing_date(brief, edits['closingDate']) if 'documentsEdited' in edits and edits['documentsEdited']: if 'attachments' in edits: edit_attachments(brief, edits['attachments']) if 'requirementsDocument' in edits and 'requirementsDocument' in brief.data: edit_requirements_document(brief, edits['requirementsDocument']) if 'responseTemplate' in edits and 'responseTemplate' in brief.data: edit_response_template(brief, edits['responseTemplate']) organisation = None sellers_to_contact = [] if (title_was_edited(brief.data['title'], previous_data['title']) or summary_was_edited(brief.data['summary'], previous_data['summary']) or closing_date_was_edited( brief.closed_at.to_iso8601_string(extended=True), previous_data['closed_at']) or documents_were_edited(brief.data.get('attachments', []), previous_data.get('attachments', [])) or documents_were_edited( brief.data.get('requirementsDocument', []), previous_data.get('requirementsDocument', [])) or documents_were_edited(brief.data.get('responseTemplate', []), previous_data.get('responseTemplate', []))): organisation = agency_service.get_agency_name(user.agency_id) # We need to find sellers to contact about the current incoming edits before sellers are edited as we're # not sending additional sellers emails about the current edits that have been made. sellers_to_contact = brief_service.get_sellers_to_notify( brief, brief_business.is_open_to_all(brief)) sellers_to_invite = {} if 'sellers' in edits and sellers_were_edited( edits['sellers'], brief.data.get('sellers', {})): sellers_to_invite = get_sellers_to_invite(brief, edits['sellers']) edit_sellers(brief, sellers_to_invite) edit_seller_selector(brief, sellers_to_invite) # strip out any data keys not whitelisted brief = brief_business.remove_keys_not_whitelisted(brief) data_to_validate = copy.deepcopy(brief.data) # only validate the sellers being added in the edit if 'sellers' in edits and len(edits['sellers'].keys()) > 0: data_to_validate['sellers'] = copy.deepcopy(edits.get('sellers', {})) validator = None if brief.lot.slug == 'rfx': validator = RFXDataValidator(data_to_validate) elif brief.lot.slug == 'training2': validator = TrainingDataValidator(data_to_validate) elif brief.lot.slug == 'atm': validator = ATMDataValidator(data_to_validate) elif brief.lot.slug == 'specialist': validator = SpecialistDataValidator(data_to_validate) if validator is None: raise ValidationError('Validator not found for {}'.format( brief.lot.slug)) errors = [] if (title_was_edited(brief.data['title'], previous_data['title']) and not validator.validate_title()): errors.append('You must add a title') if (summary_was_edited(brief.data['summary'], previous_data['summary']) and not validator.validate_summary()): message = ('You must add what the specialist will do' if brief.lot.slug == 'specialist' else 'You must add a summary of work to be done') errors.append(message) if (brief.lot.slug != 'atm' and 'sellers' in edits and sellers_were_edited( edits['sellers'], brief.data.get('sellers', {})) and not validator.validate_sellers()): message = ( 'You must select some sellers' if brief.lot.slug == 'specialist' else 'You must select at least one seller and each seller must be assessed for the chosen category' ) errors.append(message) if (closing_date_was_edited( brief.closed_at.to_iso8601_string(extended=True), previous_data['closed_at']) and not validator.validate_closed_at(minimum_days=1)): message = ( 'The closing date must be at least 1 day into the future or not more than one year long' if brief.lot.slug == 'specialist' else 'The closing date must be at least 1 day into the future') errors.append(message) if len(errors) > 0: raise ValidationError(', '.join(errors)) brief_service.save(brief, do_commit=False) edit = BriefHistory(brief_id=brief.id, user_id=user_id, data=previous_data) brief_history_service.save(edit, do_commit=False) brief_service.commit_changes() if len(sellers_to_contact) > 0 and organisation: for email_address in sellers_to_contact: send_opportunity_edited_email_to_seller(brief, email_address, organisation) for code, data in sellers_to_invite.items(): supplier = supplier_service.get_supplier_by_code(code) if supplier: if brief.lot.slug == 'rfx': send_seller_invited_to_rfx_email(brief, supplier) elif brief.lot.slug == 'specialist': send_specialist_brief_seller_invited_email(brief, supplier) elif brief.lot.slug == 'training': send_seller_invited_to_training_email(brief, supplier) send_opportunity_edited_email_to_buyers(brief, user, edit) try: audit_service.log_audit_event( audit_type=audit_types.opportunity_edited, data={'briefId': brief.id}, db_object=brief, user=user.email_address) publish_tasks.brief.delay(publish_tasks.compress_brief(brief), 'edited', email_address=user.email_address, name=user.name) except Exception as e: rollbar.report_exc_info() return brief
def create_evidence(domain_id, brief_id=None): """Create evidence (role=supplier) --- tags: - evidence definitions: EvidenceCreated: type: object properties: id: type: number domain_id: type: number supplier_code: type: number responses: 200: description: Evidence created successfully. schema: $ref: '#/definitions/EvidenceCreated' 400: description: Bad request. 403: description: Unauthorised to create evidence. 500: description: Unexpected error. """ domain = domain_service.get_by_name_or_id(domain_id, show_legacy=False) if not domain: abort('Unknown domain id') supplier = suppliers.get_supplier_by_code(current_user.supplier_code) if supplier.data.get('recruiter', '') == 'yes': abort('Assessment can\'t be started against a recruiter only supplier') existing_evidence = evidence_service.get_latest_evidence_for_supplier_and_domain( domain_id, current_user.supplier_code) if domain.name in supplier.assessed_domains: abort('This supplier is already assessed for this domain') open_assessment = assessments.get_open_assessments( domain_id=domain_id, supplier_code=current_user.supplier_code) if open_assessment or (existing_evidence and existing_evidence.status in ['draft', 'submitted']): abort( 'This supplier already has a draft assessment or is awaiting assessment for this domain' ) if brief_id: brief = briefs.find(id=brief_id).one_or_none() if not brief or brief.status != 'live': abort('Brief id does not exist or is not open for responses') try: data = {} if existing_evidence and existing_evidence.status == 'rejected': data = existing_evidence.data.copy() else: # does this supplier already have a max price for this domain set? if so, pre-populate current_max_price = suppliers.get_supplier_max_price_for_domain( current_user.supplier_code, domain.name) if current_max_price: data['maxDailyRate'] = int(current_max_price) evidence = evidence_service.create_evidence(domain_id, current_user.supplier_code, current_user.id, brief_id=brief_id, data=data) except Exception as e: rollbar.report_exc_info() abort(e.message) publish_tasks.evidence.delay(publish_tasks.compress_evidence(evidence), 'created', name=current_user.name, domain=domain.name, supplier_code=current_user.supplier_code) return jsonify(evidence.serialize())
def get_categories(): categories = [] supplier = suppliers.get_supplier_by_code(current_user.supplier_code) for domain in domain_service.get_active_domains(): is_approved = True if domain.name in supplier.assessed_domains else False data = { "id": domain.id, "name": domain.name, "previous_evidence_id": None, "evidence_id": None, "is_approved": is_approved } domain_evidence = evidence_service.get_latest_evidence_for_supplier_and_domain( domain.id, current_user.supplier_code, ) if domain_evidence: previous_evidence = evidence_service.get_previous_submitted_evidence_for_supplier_and_domain( domain_evidence.id, domain.id, current_user.supplier_code) if previous_evidence and previous_evidence.status == 'rejected': data['previous_evidence_id'] = previous_evidence.id data['status'] = domain_evidence.status data['evidence_id'] = domain_evidence.id else: # is there a submitted case study assessment in progress? open_assessment = assessments.get_open_assessments( domain_id=domain.id, supplier_code=supplier.code) if open_assessment: data['status'] = 'submitted' else: assessed_status = suppliers.get_supplier_assessed_status( supplier.id, domain.id) data[ 'status'] = assessed_status if assessed_status else 'unassessed' # override the status as unassessed if the domain is not in the assessed domains if data['status'] == 'assessed' and not is_approved: data['status'] = 'unassessed' data['rate'] = suppliers.get_supplier_max_price_for_domain( current_user.supplier_code, domain.name) categories.append(data) # sort by status categories_sorted = [] categories_sorted += [ x for x in categories if x['status'] == 'rejected' ] categories_sorted += [x for x in categories if x['status'] == 'draft'] categories_sorted += [ x for x in categories if x['status'] == 'submitted' ] categories_sorted += [ x for x in categories if x['status'] == 'assessed' ] categories_sorted += [ x for x in categories if x['status'] == 'unassessed' ] return jsonify(categories={'items': categories_sorted}), 200
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 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: status_before_withdrawn = brief_response.status 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, 'withdrawn': True }, 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) if status_before_withdrawn == 'submitted': brief = briefs.get(id=brief_response.brief_id) supplier = suppliers.get_supplier_by_code( brief_response.supplier_code) if brief and supplier: if brief.lot.slug == 'specialist': send_specialist_brief_response_withdrawn_email( supplier, brief, brief_response, supplier_user=current_user.name) else: send_brief_response_withdrawn_email( supplier, brief, brief_response, supplier_user=current_user.name) 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