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 test_csv_rfx(app, briefs, brief_responses): csvdata = generate_brief_responses_csv(briefs[0], brief_responses) lines = [ u'Seller name,Test Supplier1', u'ABN,1', u'Email,[email protected]', u'Phone number,1234' ] assert csvdata.splitlines() == lines
def test_csv_training(app, briefs, brief_responses): csvdata = generate_brief_responses_csv(briefs[0], brief_responses) lines = [ u'Seller name,Test Supplier1', u'ABN,1', u'Email,[email protected]', u'Availability date,\u275dNext \u2014 Tuesday\u275e', u'Phone number,1234', u'MS Paint,True', u'GIMP,True', u'LISP,True' ] assert csvdata.splitlines() == lines
def test_csv_rfx(app, briefs, brief_responses): csvdata = generate_brief_responses_csv(briefs[0], brief_responses) lines = [ u'Seller name,Test Supplier1', u'Email,[email protected]', u'Phone number,1234', u'ABN,1' ] assert csvdata.splitlines() == lines
def test_csv_handles_tricky_characters_1(app, briefs, brief_responses): csvdata = generate_brief_responses_csv(briefs[0], brief_responses) lines = [ u'Seller name,Test Supplier1', u'ABN,1', u'Email,[email protected]', u'Specialist name,"Bu,tties K,ev\u2019s """', u'Availability date,\u275dNext \u2014 Tuesday\u275e', u'Day rate,1.49', u'Contact number,123', u'MS Paint,True', u'GIMP,True', u'LISP,True' ] assert csvdata.splitlines() == lines
def test_csv_handles_tricky_characters_2(app, briefs, brief_responses): csvdata = generate_brief_responses_csv(briefs[0], brief_responses) lines = [ u'Seller name,Test Supplier1', u'ABN,1', u'Email,"te,[email protected]"', u"Specialist name,'Pies Kev's", u'Availability date,"A week Friday&rdquot;', u'Day rate,3.50', u'Contact number,123', u'MS Paint,True', u'GIMP,True', u'LISP,False' ] assert csvdata.splitlines() == lines
def test_csv_handles_tricky_characters_3(app, briefs, brief_responses): csvdata = generate_brief_responses_csv(briefs[0], brief_responses) lines = [ u'Seller name,Test Supplier1', u'ABN,1', u"Email,SUM(1+1)*cmd|' /C calc'!A0", u"Specialist name,SUM(1+1)*cmd|' /C calc'!A0", u"Availability date,cmd| '/c calc'!A0", u'Day rate,"2+2,"', u'Contact number,123', u'MS Paint,True', u'GIMP,True', u'LISP,False' ] assert csvdata.splitlines() == lines
def test_csv_training(app, briefs, brief_responses): csvdata = generate_brief_responses_csv(briefs[0], brief_responses) lines = [ u'Seller name,Test Supplier1', u'Email,[email protected]', u'Availability Date,\u275dNext \u2014 Tuesday\u275e', u'Phone number,1234', u'ABN,1', u'MS Paint,True', u'GIMP,True', u'LISP,True' ] assert csvdata.splitlines() == lines
def test_csv_specialist_hourly_rate(app, briefs, brief_responses): csvdata = generate_brief_responses_csv(briefs[0], brief_responses) lines = [ u'Seller name,Test Supplier1', u'ABN,1', u'Email,[email protected]', u'Specialist given name(s),foo', u'Specialist surname,bar', u'Availability date,in the future', u'Hourly rate (including GST),11', u'Hourly rate (excluding GST),10', u'Eligibility to work,Australian citizen', u'Previous agency experience,Yes', u'Security clearance,N/A', u'Contact number,123', u'ess critiera 1,ess criteria 1 answer', u'ess critiera 2,ess criteria 2 answer', u'nth critiera 1,' ] assert csvdata.splitlines() == lines
def test_csv_handles_tricky_characters_3(app, briefs, brief_responses): csvdata = generate_brief_responses_csv(briefs[0], brief_responses) lines = [ u'Seller name,Test Supplier1', u"Email,SUM(1+1)*cmd|' /C calc'!A0", u"Specialist Name,SUM(1+1)*cmd|' /C calc'!A0", u"Availability Date,cmd| '/c calc'!A0", u'Day rate,"2+2,"', u'ABN,1', u'MS Paint,True', u'GIMP,True', u'LISP,False' ] assert csvdata.splitlines() == lines
def test_csv_handles_tricky_characters_1(app, briefs, brief_responses): csvdata = generate_brief_responses_csv(briefs[0], brief_responses) lines = [ u'Seller name,Test Supplier1', u'Email,[email protected]', u'Specialist Name,"Bu,tties K,ev\u2019s """', u'Availability Date,\u275dNext \u2014 Tuesday\u275e', u'Day rate,1.49', u'ABN,1', u'MS Paint,True', u'GIMP,True', u'LISP,True' ] assert csvdata.splitlines() == lines
def test_csv_handles_tricky_characters_2(app, briefs, brief_responses): csvdata = generate_brief_responses_csv(briefs[0], brief_responses) lines = [ u'Seller name,Test Supplier1', u'Email,"te,[email protected]"', u"Specialist Name,'Pies Kev's", u'Availability Date,"A week Friday&rdquot;', u'Day rate,3.50', u'ABN,1', u'MS Paint,True', u'GIMP,True', u'LISP,False' ] assert csvdata.splitlines() == lines
def test_csv_handles_tricky_characters_2(app, briefs, brief_responses): csvdata = generate_brief_responses_csv(briefs[0], brief_responses) lines = [ u'Seller name,Test Supplier1', u'ABN,1', u'Email,"te,[email protected]"', u"Specialist given name(s),Kev's", u"Specialist surname,'Pies", u'Availability date,"A week Friday&rdquot;', u'Day rate (including GST),3.50', u'Day rate (excluding GST),', u'Previous agency experience,', u'Security clearance,N/A', u'Contact number,123', u'TEST,x', u'TEST 2,y', u'LISP,', u'Victoria Labour hire licence,', u'Victoria Labour hire licence expiry,', u'Queensland Labour hire licence,', u'Queensland Labour hire licence expiry,' ] assert csvdata.splitlines() == lines
def test_csv_handles_tricky_characters_1(app, briefs, brief_responses): csvdata = generate_brief_responses_csv(briefs[0], brief_responses) lines = [ u'Seller name,Test Supplier1', u'ABN,1', u'Email,[email protected]', u'Specialist given name(s),"Bu,tties"', u'Specialist surname,"K,ev\u2019s """', u'Availability date,\u275dNext \u2014 Tuesday\u275e', u'Day rate (including GST),1.49', u'Day rate (excluding GST),', u'Previous agency experience,', u'Security clearance,N/A', u'Contact number,123', u'TEST,x', u'TEST 2,y', u'LISP,', u'Victoria Labour hire licence,', u'Victoria Labour hire licence expiry,', u'Queensland Labour hire licence,', u'Queensland Labour hire licence expiry,' ] assert csvdata.splitlines() == lines
def test_csv_handles_tricky_characters_3(app, briefs, brief_responses): csvdata = generate_brief_responses_csv(briefs[0], brief_responses) lines = [ u'Seller name,Test Supplier1', u'ABN,1', u"Email,SUM(1+1)*cmd|' /C calc'!A0", u"Specialist given name(s),SUM(1+1)*cmd|'", u"Specialist surname,/C calc'!A0", u"Availability date,cmd| '/c calc'!A0", u'Day rate (including GST),"2+2,"', u'Day rate (excluding GST),', u'Previous agency experience,', u'Security clearance,N/A', u'Contact number,123', u'TEST,x', u'TEST 2,y', u'LISP,', u'Victoria Labour hire licence,', u'Victoria Labour hire licence expiry,', u'Queensland Labour hire licence,', u'Queensland Labour hire licence expiry,' ] assert csvdata.splitlines() == lines
def test_csv_specialist_daily_rate(app, briefs, brief_responses): csvdata = generate_brief_responses_csv(briefs[0], brief_responses) lines = [ u'Seller name,Test Supplier1', u'ABN,1', u'Email,[email protected]', u'Specialist given name(s),foo', u'Specialist surname,bar', u'Availability date,in the future', u'Day rate (including GST),11', u'Day rate (excluding GST),10', u'Eligibility to work,Australian citizen', u'Previous agency experience,Yes', u'Holds a negative vetting level 1 security clearance,Yes', u'Contact number,123', u'ess critiera 1,ess criteria 1 answer', u'ess critiera 2,ess criteria 2 answer', u'Victoria Labour hire licence,', u'Victoria Labour hire licence expiry,', u'Queensland Labour hire licence,', u'Queensland Labour hire licence expiry,' ] assert csvdata.splitlines() == lines
def create_responses_zip(brief_id): brief = briefs.find(id=brief_id).one_or_none() if not brief: raise CreateResponsesZipException( 'Failed to load brief for id {}'.format(brief_id)) responses = brief_responses_service.get_responses_to_zip( brief_id, brief.lot.slug) if not responses: raise CreateResponsesZipException( 'There were no respones for brief id {}'.format(brief_id)) if brief.lot.slug not in [ 'digital-professionals', 'training', 'rfx', 'training2', 'atm', 'specialist' ]: raise CreateResponsesZipException( 'Brief id {} is not a compatible lot'.format(brief_id)) print 'Generating zip for brief id: {}'.format(brief_id) BUCKET_NAME = getenv('S3_BUCKET_NAME') s3 = boto3.resource('s3', region_name=getenv('AWS_REGION'), aws_access_key_id=getenv('AWS_ACCESS_KEY_ID'), aws_secret_access_key=getenv('AWS_SECRET_ACCESS_KEY'), endpoint_url=getenv('AWS_S3_URL')) bucket = s3.Bucket(BUCKET_NAME) files = [] attachments = brief_responses_service.get_all_attachments(brief_id) for attachment in attachments: if attachment['file_name'].startswith( 'digital-marketplace') and '/' in attachment['file_name']: key = attachment['file_name'] zip_file_name = attachment['file_name'].split('/')[-1] else: key = 'digital-marketplace/documents/brief-{}/supplier-{}/{}'.format( brief_id, attachment['supplier_code'], attachment['file_name']) zip_file_name = attachment['file_name'] files.append({ 'key': key, 'zip_name': 'opportunity-{}-documents/{}/{}'.format( brief_id, secure_filename(attachment['supplier_name']), zip_file_name) }) with tempfile.TemporaryFile() as archive: with zipfile.ZipFile(archive, mode='w', compression=zipfile.ZIP_DEFLATED) as zf: for file in files: s3file = file['key'] with BytesIO() as s3_stream: try: bucket.download_fileobj(s3file, s3_stream) zf.writestr(file['zip_name'], s3_stream.getvalue()) except botocore.exceptions.ClientError as e: raise CreateResponsesZipException( 'The file "{}" failed to download'.format(s3file)) finally: s3_stream.close() csvdata = generate_brief_responses_csv(brief, responses) csv_file_name = ( 'opportunity-{}-raw.csv'.format(brief_id) if brief.lot.slug == 'digital-professionals' else 'responses-to-requirements-{}.csv'.format(brief_id)) zf.writestr(csv_file_name, csvdata.encode('utf-8')) if brief.lot.slug == 'digital-professionals': compliance_check_template = template_env.get_template( 'compliance-check.html') compliance_check_html = render_template( compliance_check_template, brief=brief, responses=responses) zf.writestr('compliance-check-{}.html'.format(brief_id), compliance_check_html.encode('utf-8')) candidates = prepare_specialist_responses(brief, responses) response_criteria_template = template_env.get_template( 'response-criteria.html') response_criteria_html = render_template( response_criteria_template, brief=brief, candidates=candidates) zf.writestr('responses-{}.html'.format(brief_id), response_criteria_html.encode('utf-8')) elif brief.lot.slug == 'specialist': compliance_check_template = template_env.get_template( 'compliance-check-specialist.html') supplier_labour_hire = {} for response in responses: labour_hire = [] for state, state_value in response.supplier.data.get( 'labourHire', {}).iteritems(): if state_value.get( 'licenceNumber') and state_value.get('expiry'): state_value['state'] = state.upper() state_value['expiry'] = (pendulum.parse( state_value['expiry']).format( 'DD MMMM YYYY', formatter='alternative')) labour_hire.append(state_value) supplier_labour_hire[response.supplier.code] = labour_hire compliance_check_html = render_template( compliance_check_template, brief=brief, supplier_labour_hire=supplier_labour_hire, responses=responses) zf.writestr('Compliance check ({}).html'.format(brief_id), compliance_check_html.encode('utf-8')) response_criteria_template = template_env.get_template( 'response-criteria-specialist.html') candidates = [] for response in responses: data = response.data candidates.append({ 'essential_requirement_responses': data.get('essentialRequirements', {}), 'nice_to_have_requirement_responses': data.get('niceToHaveRequirements', {}), 'name': '{} {}'.format(data.get('specialistGivenNames', ''), data.get('specialistSurname', '')), 'seller': response.supplier.name }) response_criteria_html = render_template( response_criteria_template, brief=brief, candidates=candidates, essential_requirements=brief.data.get( 'essentialRequirements', {}), nice_to_have_requirements=brief.data.get( 'niceToHaveRequirements', {})) zf.writestr('Responses ({}).html'.format(brief_id), response_criteria_html.encode('utf-8')) archive.seek(0) try: brief.responses_zip_filesize = len(archive.read()) archive.seek(0) db.session.add(brief) db.session.commit() except Exception as e: raise CreateResponsesZipException(str(e)) try: bucket.upload_fileobj( archive, 'digital-marketplace/archives/brief-{}/brief-{}-resumes.zip'. format(brief_id, brief_id)) except botocore.exceptions.ClientError as e: raise CreateResponsesZipException( 'The responses archive for brief id "{}" failed to upload'. format(brief_id))