def get_team(team_id): team = team_service.get_team(team_id) if not team: raise NotFoundError('Team {} does not exist'.format(team_id)) team_member = team_member_service.find( is_team_lead=True, team_id=team_id, user_id=current_user.id ).one_or_none() if not team_member: raise UnauthorisedError('Only team leads can edit a team') domain = get_email_domain(current_user.email_address) if team['teamMembers'] is not None: for user_id, team_member in team['teamMembers'].iteritems(): missing_permissions = [permission for permission in permission_types if permission not in team_member['permissions']] for permission in missing_permissions: team_member['permissions'][permission] = False team.update(domain=domain) return team
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 publish_answer(current_user, brief_id, data): brief = briefs.get(brief_id) if not brief: raise NotFoundError("Invalid brief id '{}'".format(brief_id)) if not briefs.has_permission_to_brief(current_user.id, brief.id): raise UnauthorisedError('Unauthorised to publish answer') publish_question = data.get('question') if not publish_question: raise ValidationError('Question is required') answer = data.get('answer') if not answer: raise ValidationError('Answer is required') brief_clarification_question = brief_clarification_question_service.save( BriefClarificationQuestion(_brief_id=brief.id, question=publish_question, answer=answer, user_id=current_user.id)) question_id = data.get('questionId') if question_id: question = brief_question_service.get(question_id) if question.brief_id == brief.id: question.answered = True brief_question_service.save(question) audit_service.log_audit_event( audit_type=audit_types.create_brief_clarification_question, user=current_user.email_address, data={'briefId': brief.id}, db_object=brief_clarification_question)
def get_question(current_user, brief_id, question_id): brief = briefs.find(id=brief_id).one_or_none() if not brief: raise NotFoundError("Invalid brief id '{}'".format(brief_id)) if not briefs.has_permission_to_brief(current_user.id, brief.id): raise UnauthorisedError('Unauthorised to publish answer') question = brief_question_service.find(id=question_id, brief_id=brief.id).one_or_none() question_result = None if question: question_result = {"id": question.id, "data": question.data} return { "question": question_result, "brief": { "title": brief.data.get('title'), "id": brief.id, "lot": brief.lot.slug, "questionsCloseAt": brief.questions_closed_at, "closedAt": brief.closed_at, "internalReference": brief.data.get('internalReference'), "isOpenToAll": brief_business.is_open_to_all(brief), "status": brief.status } }
def close_opportunity_early(user_id, brief_id): 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 close opportunity {}'.format(brief_id)) if not can_close_opportunity_early(brief): raise BriefError('Unable to close opportunity {}'.format(brief_id)) user = users.get(user_id) if not user: raise NotFoundError('User {} does not exist'.format(user_id)) brief = brief_service.close_opportunity_early(brief) create_responses_zip(brief.id) send_opportunity_closed_early_email(brief, user) try: audit_service.log_audit_event( audit_type=audit_types.close_opportunity_early, data={'briefId': brief.id}, db_object=brief, user=user.email_address) publish_tasks.brief.delay(publish_tasks.compress_brief(brief), 'closed_early', email_address=user.email_address, name=user.name) except Exception as e: rollbar.report_exc_info() return brief
def update_team(team_id, data): team = team_service.get_team_for_update(team_id) if not team: raise NotFoundError('Team {} does not exist'.format(team_id)) if len([tm for tm in team.team_members if tm.user_id == current_user.id and tm.is_team_lead is True]) == 0: raise UnauthorisedError('Only team leads can edit a team') update_team_information(team, data) result = update_team_leads_and_members(team, data) update_permissions(team, data) create_team = data.get('createTeam', False) saved = False if create_team: validation_result = TeamValidator(team, current_user).validate_all() if len([e for e in validation_result.errors]) > 0: raise ValidationError([e for e in validation_result.errors]) team.status = 'completed' team_service.save(team) saved = True send_team_lead_notification_emails(team_id) send_team_member_notification_emails(team_id) elif team.status == 'completed': validation_result = TeamValidator(team, current_user).validate_all() if len([e for e in validation_result.errors]) > 0: raise ValidationError([e for e in validation_result.errors]) team_service.save(team) saved = True new_team_leads = result.get('new_team_leads', []) new_team_members = result.get('new_team_members', []) removed_team_members = result.get('removed_team_members', []) if len(new_team_leads) > 0: send_team_lead_notification_emails(team_id, new_team_leads) if len(new_team_members) > 0: send_team_member_notification_emails(team_id, new_team_members) if len(removed_team_members) > 0: send_removed_team_member_notification_emails(team_id, removed_team_members) elif team.status == 'created': validation_result = TeamValidator(team, current_user).validate_all() team_member_errors = [e for e in validation_result.errors if str(e.get('id')).startswith('TM')] if team_member_errors: raise ValidationError(team_member_errors) team_service.save(team) if saved: publish_tasks.team.delay( publish_tasks.compress_team(team), 'updated' ) return get_team(team_id)
def withdraw_opportunity(user_id, brief_id, withdrawal_reason): 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 withdraw opportunity {}'.format(brief_id)) if brief.status != 'live': raise BriefError('Unable to withdraw opportunity {}'.format(brief_id)) if not withdrawal_reason: raise ValidationError( 'Withdrawal reason is required for opportunity {}'.format( brief_id)) user = users.get(user_id) if not user: raise NotFoundError('User {} does not exist'.format(user_id)) brief = brief_service.withdraw_opportunity(brief, withdrawal_reason) organisation = agency_service.get_agency_name(user.agency_id) sellers_to_contact = brief_service.get_sellers_to_notify( brief, brief_business.is_open_to_all(brief)) for email_address in sellers_to_contact: send_opportunity_withdrawn_email_to_seller(brief, email_address, organisation) send_opportunity_withdrawn_email_to_buyers(brief, user) try: audit_service.log_audit_event( audit_type=audit_types.withdraw_opportunity, data={'briefId': brief.id}, db_object=brief, user=user.email_address) publish_tasks.brief.delay(publish_tasks.compress_brief(brief), 'withdrawn', email_address=user.email_address, name=user.name) except Exception as e: rollbar.report_exc_info() return brief
def get_questions(current_user, brief_id): brief = briefs.find(id=brief_id).one_or_none() if not brief: raise NotFoundError("Invalid brief id '{}'".format(brief_id)) if not briefs.has_permission_to_brief(current_user.id, brief.id): raise UnauthorisedError('Unauthorised to publish answer') questions = brief_question_service.get_questions(brief_id) return { "questions": questions, "brief": { "title": brief.data.get('title'), "id": brief.id, "closedAt": brief.closed_at, "internalReference": brief.data.get('internalReference') }, "questionCount": get_counts(brief_id, questions=questions) }
def get_opportunity_to_edit(user_id, brief_id): 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)) domains = [] for domain in domain_service.get_active_domains(): domains.append({'id': str(domain.id), 'name': domain.name}) return { 'brief': brief.serialize(with_users=False), 'domains': domains, 'isOpenToAll': brief_business.is_open_to_all(brief) }
def request_to_join(user_email_address, team_id, agency_id): team = team_service.get_team(team_id) if not team: raise NotFoundError('Team {} does not exist'.format(team_id)) if not get_teams_by_agency(agency_id, team_id): raise UnauthorisedError('Can not request to join this team') claim = user_claims_service.make_claim(type='join_team', email_address=user_email_address, data={ "team_id": team_id, "team_name": team['name'], "agency_id": agency_id, "user_id": current_user.id, "user_name": current_user.name, "approved": False }) if not claim: raise ValidationError('Could not create join team request') send_request_to_join_team_leaders_email(team_id, claim.token) send_request_to_join_requester_email(user_email_address, team_id)
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 get_team(team_id, allow_anyone=None): team = team_service.get_team(team_id) if not team: raise NotFoundError('Team {} does not exist'.format(team_id)) if allow_anyone is None: team_member = team_member_service.find( is_team_lead=True, team_id=team_id, user_id=current_user.id).one_or_none() if not team_member: raise UnauthorisedError('Only team leads can edit a team') if team['teamMembers'] is not None: for user_id, team_member in team['teamMembers'].iteritems(): missing_permissions = [ permission for permission in permission_types if permission not in team_member['permissions'] ] for permission in missing_permissions: team_member['permissions'][permission] = False return team
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