def put(self, application_guid): # save history temp_application = Application.find_by_guid(application_guid) history = temp_application.save_application_history() application = None is_json_updated = None is_application_updated = None try: # map only specific fields application = Application.find_by_guid(application_guid) is_note_updated = application.edit_note != request.json.get( "edit_note") if is_note_updated: application.edit_note = request.json.get("edit_note") json = request.json.get("json") is_json_updated = DeepDiff( json, application.json, ignore_order=True) != {} if is_json_updated: application.json["company_contact"] = json["company_contact"] application.process_well_sites_work_items( json["well_sites"], application.iterate_application_work_items_action) is_application_updated = is_note_updated or is_json_updated except MarshmallowError as e: history.delete() raise BadRequest(e) try: if is_application_updated: if is_json_updated: flag_modified(application, "json") application.save() else: history.delete() except: history.delete() raise return application
def post(self, application_guid): application = Application.find_by_guid(application_guid) if not application: raise NotFound( 'No application was found matching the provided reference number' ) # Documents can only be uploaded for application's in the correct status or if its being done by an admin if application.application_status_code == 'WAIT_FOR_DOCS' or jwt.validate_roles( [ADMIN]): docs = request.json.get('documents', []) for doc in docs: new_doc = ApplicationDocument( document_name=doc['document_name'], object_store_path=doc['object_store_path'], application_document_code='SUPPORTING_DOC') application.documents.append(new_doc) application.save() if request.json.get('confirm_final_documents'): app_status_change = ApplicationStatusChange( application=application, application_status_code='DOC_SUBMITTED', note='Thank you for uploading the required documents.') app_status_change.save() return '', 204 raise Unauthorized( 'Not currently accepting documents on this application')
def get(self): wa_number = request.args.get('well_auth_number', type=int) operator_id = request.args.get('operator_id', None) application_guid = request.args.get('application_guid', None) wells = [] if operator_id: wells = NominatedWellSite.find_by_operator_id(operator_id) if wa_number: wells = [NominatedWellSite.find_by_wa_number(wa_number)] if application_guid: application = Application.find_by_guid(application_guid) application_wells = [ int(x['details']['well_authorization_number']) for x in application.json['well_sites'] ] wells = NominatedWellSite.query.filter( NominatedWellSite.wa_number.in_(application_wells)).all() return wells
def get(self, application_guid): application = Application.find_by_guid(application_guid) if application is None: raise NotFound( 'No application was found matching the provided reference number' ) return application.contracted_work('APPROVED', True)
def get(self, application_guid): application = Application.find_by_guid(application_guid) if application is None: raise NotFound( 'No application was found matching the provided reference number' ) return application
def post(self): data = AuthorizationResource.parser.parse_args() application_guid = data.get('application_guid') application = Application.find_by_guid(application_guid) otl_guid = uuid.uuid4() if application is None: raise NotFound( 'No application was found matching the provided reference number' ) html_content = f""" <table width="100%" style="font-size:12.0pt; color:#595959 " > <tr> <td> You have requested access to the Dormant Sites Reclamation Program site to view information about an application (see Reference Number above). <br/> <br/> Use the button below to access your application information and submit payment requests. <br/> This button can only be used once and access expires after four hours. If you need to access the application again, request another link on the website. </td> </tr> <tr> <td> <br/> <table style="margin-left: auto; margin-right: auto;"> <tr> <td style="border-radius: 2px;" bgcolor="#003366" > <a href="{ONE_TIME_LINK_FRONTEND_URL(otl_guid)}" target="_blank" style="padding: 8px 12px; border: 1px solid #003366;border-radius: 2px;font-size: 14px; color: #ffffff;text-decoration: none;font-weight:bold;display: inline-block;"> View Application </a> </td> </tr> </table> <br/> </td> </tr> </table>""" with EmailService() as es: es.send_email_to_applicant( application, f"Dormant Site Reclamation Program – Access Request", html_content) current_app.logger.debug(f"This is a OTL: {otl_guid}") cache.set( str(otl_guid), application_guid, timeout=AuthorizationResource.ONE_TIME_PASSWORD_TIMEOUT_SECONDS) return "OK", 200
def post(self, application_guid): application = Application.find_by_guid(application_guid) if not application: raise NotFound( 'No application was found matching the provided reference number' ) app_status_change = ApplicationStatusChange( application=application, application_status_code=request.json['application_status_code'], note=request.json['note']) app_status_change.save() return '', 204
def put(self, application_guid): application = Application.find_by_guid(application_guid) if application is None: raise NotFound( 'No application was found matching the provided reference number' ) try: review_json = request.json['review_json'] except Exception as e: raise BadRequest(e) application.review_json = review_json application.save() return application
def get(self): liabilities = OGCDataService.getLiabilityPerWellDataFrame() application_guid = request.args.get('application_guid', None) if application_guid is not None: application = Application.find_by_guid(application_guid) application_wells = [ int(x['details']['well_authorization_number']) for x in application.json['well_sites'] ] liabilities = liabilities[ liabilities['well_auth_number'].copy().isin(application_wells)] return liabilities.to_dict('records')
def get(self): token_guid = request.args.get('token', '') attachment = request.args.get('as_attachment', None) token_data = cache.get(DOWNLOAD_TOKEN(token_guid)) cache.delete(DOWNLOAD_TOKEN(token_guid)) current_app.logger.debug('redis_data' + str(token_data)) if not token_data: raise BadRequest('Valid token required for download') # Generation token file_resp = None if token_data.get('generation', False): application = Application.find_by_guid( token_data['application_guid']) template_path = token_data['template_path'] docgen_resp = DocumentGeneratorService.generate_document_and_stream_response( template_path, application.shared_cost_agreement_template_json, 'pdf') headers = dict(docgen_resp.headers) headers[ 'Content-Disposition'] = f'attachment; filename=shared_cost_agreement_{application.company_name}.pdf' file_resp = Response(stream_with_context( docgen_resp.iter_content(chunk_size=2048)), headers=headers) # Download token else: document_guid = token_data['document_guid'] app_doc = ApplicationDocument.query.filter_by( application_document_guid=document_guid).one_or_none() if not app_doc: raise NotFound( 'No document was found with the corresponding download token' ) if attachment is not None: attach_style = True if attachment == 'true' else False else: attach_style = '.pdf' not in app_doc.document_name.lower() file_resp = ObjectStoreStorageService().download_file( path=app_doc.object_store_path, display_name=quote(app_doc.document_name), as_attachment=attach_style) return file_resp
def put(self, application_guid, work_id): # Ensure that this work item exists on this application. application = Application.find_by_guid(application_guid) validate_application_contracted_work(application, work_id) # Get the contracted work payment. payment = ContractedWorkPayment.find_by_work_id(work_id) if not payment: raise BadRequest( 'Only contracted work items that have had information submitted can have their Interim Progress Report updated' ) # Set the contracted work payment interim report. interim_report_data = request.json interim_report = interim_report_data['interim_report'] payment.interim_report = interim_report payment.save() return '', 200
def put(self, application_guid, work_id): # Validate this contracted work item. application = Application.find_by_guid(application_guid) validate_application_contracted_work(application, work_id) # Get the contracted work payment. payment = ContractedWorkPayment.find_by_work_id(work_id) if not payment: raise BadRequest( 'The applicant must submit payment information for this work item before its audit status can be changed' ) # Update the contracted work payment's audit data. audit_data = request.json payment.audit_ind = audit_data['audit_ind'] payment.audit_user = User().get_user_username() payment.audit_timestamp = datetime.utcnow() payment.save() return '', 200
def post(self, application_guid): application = Application.find_by_guid(application_guid) work_ids = request.json['work_ids'] validate_application_contracted_work(application, work_ids) payment_document_code = request.json['payment_document_code'] if payment_document_code == 'FIRST_PRF': raise BadRequest( 'First PRFs are created when an application\'s status is set to approved.' ) try: doc = PaymentDocument(application=application, payment_document_code=payment_document_code, work_ids=work_ids) doc.save() except Exception as e: raise BadRequest(f'Failed to create the PRF: {e}') return doc, 201
def post(self): applications_disabled = DSRPSettings.find_by_setting( DISABLE_APP_SUBMIT_SETTING).setting_value if applications_disabled: raise BadRequest( "Application Submissions are disabled at this time.") try: application_json = request.json['application'] application_json[ 'application_phase_code'] = CURRENT_APPLICATION_PHASE_CODE application = Application._schema().load(application_json) application.submitter_ip = request.headers.getlist( 'X-Forwarded-For')[0] if request.headers.getlist( 'X-Forwarded-For') else request.remote_addr application.save() except MarshmallowError as e: raise BadRequest(e) application.send_confirmation_email() return application, 201
def get(self): operator_id = request.args.get('operator_id', None) well_auth_number = request.args.get('well_auth_number', None) application_guid = request.args.get('application_guid', None) wells = OGCDataService.getDormantWellsDataFrame() if operator_id: wells = wells[wells['operator_id'] == int(operator_id)] if well_auth_number: wells = wells[wells['well_auth_number'] == int(well_auth_number)] if application_guid: application = Application.find_by_guid(application_guid) application_wells = [ int(x['details']['well_authorization_number']) for x in application.json['well_sites'] ] wells = wells[wells['well_auth_number'].copy().isin( application_wells)] return wells.to_dict('records')
def get(self): # Get all approved contracted work items on all approved applications application_id = request.args.get('application_id', type=int) application_guid = request.args.get('application_guid', type=str) company_name = request.args.get('company_name', type=str) all_approved_contracted_work = Application.all_approved_contracted_work( application_id, application_guid, company_name) # Get pagination/sorting query params page_number = request.args.get('page', DEFAULT_PAGE_NUMBER, type=int) page_size = request.args.get('per_page', DEFAULT_PAGE_SIZE, type=int) sort_field = request.args.get('sort_field', 'review_deadlines', type=str) sort_dir = request.args.get('sort_dir', 'asc', type=str) # Get filtering query params work_id = request.args.get('work_id', type=str) well_authorization_number = request.args.get( 'well_authorization_number', type=str) contracted_work_type = request.args.getlist('contracted_work_type', type=str) interim_payment_status_code = request.args.getlist( 'interim_payment_status_code', type=str) final_payment_status_code = request.args.getlist( 'final_payment_status_code', type=str) application_phase_code = request.args.getlist('application_phase_code', type=str) # Apply filtering records = all_approved_contracted_work if (work_id or well_authorization_number or contracted_work_type or interim_payment_status_code or final_payment_status_code or application_phase_code): records = [] for approved_work in all_approved_contracted_work: if work_id: if approved_work['work_id'] == work_id: records.append(approved_work) break continue if well_authorization_number and approved_work[ 'well_authorization_number'] != well_authorization_number: continue if contracted_work_type and approved_work[ 'contracted_work_type'] not in contracted_work_type: continue contracted_work_payment = approved_work.get( 'contracted_work_payment', None) interim_status = 'INFORMATION_REQUIRED' if not contracted_work_payment else contracted_work_payment[ 'interim_payment_status_code'] final_status = 'INFORMATION_REQUIRED' if not contracted_work_payment else contracted_work_payment[ 'final_payment_status_code'] if interim_payment_status_code and final_payment_status_code: if interim_status not in interim_payment_status_code and final_status not in final_payment_status_code: continue else: if interim_payment_status_code and interim_status not in interim_payment_status_code: continue if final_payment_status_code and final_status not in final_payment_status_code: continue if application_phase_code and approved_work[ 'application_phase_code'] not in application_phase_code: continue records.append(approved_work) # Apply sorting reverse = sort_dir == 'desc' if sort_field == 'well_authorization_number': records.sort(key=lambda x: int(x[sort_field]), reverse=reverse) elif sort_field == 'work_id': records.sort( key=lambda x: (x['application_id'], int(x[sort_field].split('.')[1])), reverse=reverse) elif sort_field in ('application_id', 'work_id', 'contracted_work_type', 'company_name', 'application_phase_code'): records.sort(key=lambda x: x[sort_field], reverse=reverse) elif sort_field in ('review_deadlines'): records.sort( key=lambda x: (x.get('contracted_work_payment') and (x['contracted_work_payment'][sort_field] and ( (x['contracted_work_payment'][sort_field]['interim'], x[ 'contracted_work_payment'][sort_field]['final']) if x['contracted_work_payment'][sort_field]['interim'] <= x['contracted_work_payment'][sort_field]['final'] else (x['contracted_work_payment'][sort_field]['final'], x['contracted_work_payment'][sort_field]['interim']))) or (REVIEW_DEADLINE_NOT_APPLICABLE, REVIEW_DEADLINE_NOT_APPLICABLE)), reverse=reverse) elif sort_field in ('interim_payment_status_code', 'final_payment_status_code'): records.sort(key=lambda x: (x.get('contracted_work_payment') and x[ 'contracted_work_payment'][sort_field]) or 'INFORMATION_REQUIRED', reverse=reverse) # Return records with pagination applied return apply_pagination_to_records(records, page_number, page_size)
def post(self, application_guid, work_id): # Validate this contracted work item. application = Application.find_by_guid(application_guid) validate_application_contracted_work(application, work_id) # Get the payment status change data. payment_status_data = request.json # Validate the contracted work payment code. contracted_work_payment_code = payment_status_data[ 'contracted_work_payment_code'] prefix = contracted_work_payment_code.lower() if not ContractedWorkPaymentType.find_by_code( contracted_work_payment_code): raise BadRequest('Unknown contracted work payment code received!') # Validate the contracted work payment status code. contracted_work_payment_status_code = payment_status_data[ f'{prefix}_payment_status_code'] if not ContractedWorkPaymentStatus.find_by_code( contracted_work_payment_status_code): raise BadRequest( 'Unknown contracted work payment status code received!') # Get the contracted work payment. payment = ContractedWorkPayment.find_by_work_id(work_id) if not payment: raise BadRequest( 'The applicant must submit payment information for this work item before its status can be changed' ) # Validate the request to change the final payment status to approved. if contracted_work_payment_code == 'FINAL' and contracted_work_payment_status_code == 'APPROVED': if payment.interim_payment_status_code != 'APPROVED': raise BadRequest('The interim payment must first be approved!') if not payment.interim_paid_amount: raise BadRequest( 'The interim payment must have an approved amount set!') if not payment.interim_report: raise BadRequest( 'The interim progress report must be provided!') note = payment_status_data.get(f'{prefix}_note', None) if contracted_work_payment_status_code == 'APPROVED': approved_amount = payment_status_data[f'{prefix}_approved_amount'] if not approved_amount: raise BadRequest('The amount to approve must be provided!') if contracted_work_payment_code == 'INTERIM': payment.interim_paid_amount = approved_amount else: payment.final_paid_amount = approved_amount elif contracted_work_payment_status_code == 'READY_FOR_REVIEW': pass elif contracted_work_payment_status_code == 'INFORMATION_REQUIRED': if not note: BadRequest('A note is mandatory for this status!') else: raise BadRequest( 'Unknown contracted work payment status code received!') status_change = ContractedWorkPaymentStatusChange( contracted_work_payment=payment, application=application, contracted_work_payment_status_code= contracted_work_payment_status_code, contracted_work_payment_code=contracted_work_payment_code, note=note) payment.status_changes.append(status_change) payment.save() return '', 201
def put(self, application_guid, work_id): response_code = 200 # Ensure that this work item exists on this application. application = Application.find_by_guid(application_guid) validate_application_contracted_work(application, work_id) # Get the contracted work payment or create it if it doesn't exist. payment = ContractedWorkPayment.find_by_work_id(work_id) if not payment: payment = ContractedWorkPayment( application=application, application_guid=application_guid, work_id=work_id, contracted_work_payment_status_code='READY_FOR_REVIEW', contracted_work_payment_code='INTERIM') response_code = 201 else: # Applicants can only update existing contracted work payments that are in the Information Required status. if payment.interim_payment_status_code != 'INFORMATION_REQUIRED': raise BadRequest( 'Only contracted work payments with the status Information Required can be modified' ) status_change = ContractedWorkPaymentStatusChange( contracted_work_payment=payment, application=application, contracted_work_payment_status_code='READY_FOR_REVIEW', contracted_work_payment_code='INTERIM') payment.status_changes.append(status_change) # Update the required data points. interim_payment_data = request.json payment.interim_total_hours_worked_to_date = interim_payment_data[ 'interim_total_hours_worked_to_date'] payment.interim_number_of_workers = interim_payment_data[ 'interim_number_of_workers'] payment.interim_actual_cost = interim_payment_data[ 'interim_actual_cost'] payment.interim_submitter_name = interim_payment_data[ 'interim_submitter_name'] # The interim report is optional at this step. interim_report = interim_payment_data.get('interim_report') if interim_report: payment.interim_report = interim_report # The EoC is only required if it hasn't been provided yet. interim_eoc_data = interim_payment_data.get('interim_eoc', [None])[0] if not interim_eoc_data and not payment.interim_eoc_document: raise BadRequest('Evidence of Cost is required!') # Create the EoC document and soft-delete the existing one (if it exists). if interim_eoc_data: if payment.interim_eoc_document: payment.interim_eoc_document.active_ind = False filename = ApplicationDocument.create_filename( application, payment.work_id, 'INTERIM_EOC', 'pdf') interim_eoc = ApplicationDocument( document_name=filename, object_store_path=interim_eoc_data['key'], application_document_code='INTERIM_EOC') application.documents.append(interim_eoc) application.save() payment.interim_eoc_application_document_guid = interim_eoc.application_document_guid payment.save() return '', response_code
def put(self, application_guid, work_id): response_code = 200 # Ensure that this work item exists on this application. application = Application.find_by_guid(application_guid) validate_application_contracted_work(application, work_id) # Get the contracted work payment or create it if it doesn't exist. payment = ContractedWorkPayment.find_by_work_id(work_id) if not payment: payment = ContractedWorkPayment( application=application, application_guid=application_guid, work_id=work_id, contracted_work_payment_status_code='READY_FOR_REVIEW', contracted_work_payment_code='FINAL') response_code = 201 else: # Applicants can only update existing contracted work payments that are in the Information Required status. if payment.final_payment_status_code != 'INFORMATION_REQUIRED': raise BadRequest( 'Only contracted work payments with the status Information Required can be modified' ) status_change = ContractedWorkPaymentStatusChange( contracted_work_payment=payment, application=application, contracted_work_payment_status_code='READY_FOR_REVIEW', contracted_work_payment_code='FINAL') payment.status_changes.append(status_change) # Update the required data points. final_payment_data = request.json payment.final_total_hours_worked_to_date = final_payment_data[ 'final_total_hours_worked_to_date'] payment.final_number_of_workers = final_payment_data[ 'final_number_of_workers'] payment.final_actual_cost = final_payment_data['final_actual_cost'] payment.work_completion_date = final_payment_data[ 'work_completion_date'] payment.final_submitter_name = final_payment_data[ 'final_submitter_name'] # Update the general reporting data point "surface landowner". surface_landowner = final_payment_data['surface_landowner'] if surface_landowner not in ('Crown', 'Freehold', 'Both'): raise BadRequest('Unknown "surface landowner" value received!') payment.surface_landowner = surface_landowner # Update the work-type specific reporting data points. contracted_work_type = application.find_contracted_work_type_by_work_id( payment.work_id) def parseBool(value): if isinstance(value, bool): return value if value not in ('true', 'false'): raise BadRequest(f'{value} is not a valid boolean value') return value == 'true' # Update the general reporting data point "reclamation was achieved". payment.reclamation_was_achieved = parseBool( final_payment_data['reclamation_was_achieved']) # Abandonment reporting if contracted_work_type == 'abandonment': payment.abandonment_cut_and_capped_completed = parseBool( final_payment_data['abandonment_cut_and_capped_completed']) payment.abandonment_notice_of_operations_submitted = parseBool( final_payment_data[ 'abandonment_notice_of_operations_submitted']) abandonment_was_pipeline_abandoned = parseBool( final_payment_data['abandonment_was_pipeline_abandoned']) payment.abandonment_was_pipeline_abandoned = abandonment_was_pipeline_abandoned if abandonment_was_pipeline_abandoned: payment.abandonment_metres_of_pipeline_abandoned = int( final_payment_data[ 'abandonment_metres_of_pipeline_abandoned']) # Reclamation reporting elif contracted_work_type == 'reclamation': payment.reclamation_reclaimed_to_meet_cor_p2_requirements = parseBool( final_payment_data[ 'reclamation_reclaimed_to_meet_cor_p2_requirements']) payment.reclamation_surface_reclamation_criteria_met = parseBool( final_payment_data[ 'reclamation_surface_reclamation_criteria_met']) # Remediation reporting elif contracted_work_type == 'remediation': remediation_type_of_document_submitted = final_payment_data[ 'remediation_type_of_document_submitted'] if remediation_type_of_document_submitted not in ('COR_P1', 'DSAF', 'NONE'): raise BadRequest( 'Unknown "remediation type of document submitted" value received!' ) payment.remediation_type_of_document_submitted = remediation_type_of_document_submitted payment.remediation_identified_contamination_meets_standards = parseBool( final_payment_data[ 'remediation_identified_contamination_meets_standards']) payment.remediation_reclaimed_to_meet_cor_p1_requirements = parseBool( final_payment_data[ 'remediation_reclaimed_to_meet_cor_p1_requirements']) # Site investigation reporting elif contracted_work_type in ('preliminary_site_investigation', 'detailed_site_investigation'): site_investigation_type_of_document_submitted = final_payment_data[ 'site_investigation_type_of_document_submitted'] if site_investigation_type_of_document_submitted not in ('COR_P1', 'DSAF', 'NONE'): raise BadRequest( 'Unknown "site investigation type of document submitted" value received!' ) payment.site_investigation_type_of_document_submitted = site_investigation_type_of_document_submitted payment.site_investigation_concerns_identified = parseBool( final_payment_data['site_investigation_concerns_identified']) # The EoC is only required if it hasn't been provided yet. final_eoc_data = final_payment_data.get('final_eoc', [None])[0] if not final_payment_data.get('final_eoc', None) and not payment.final_eoc_document: raise BadRequest('Evidence of Cost is required!') # Create the EoC document and soft-delete the existing one (if it exists). if final_eoc_data: if payment.final_eoc_document: payment.final_eoc_document.active_ind = False filename = ApplicationDocument.create_filename( application, payment.work_id, 'FINAL_EOC', 'pdf') final_eoc = ApplicationDocument( document_name=filename, object_store_path=final_eoc_data['key'], application_document_code='FINAL_EOC') application.documents.append(final_eoc) application.save() payment.final_eoc_application_document_guid = final_eoc.application_document_guid # The Final Report is only required if it hasn't been provided yet. final_report_data = final_payment_data.get('final_report', [None])[0] if not final_report_data and not payment.final_report_document: raise BadRequest('Final Report is required!') # Create the Final Report document and soft-delete the existing one (if it exists). if final_report_data: if payment.final_report_document: payment.final_report_document.active_ind = False filename = ApplicationDocument.create_filename( application, payment.work_id, 'FINAL_REPORT', 'pdf') final_report = ApplicationDocument( document_name=filename, object_store_path=final_report_data['key'], application_document_code='FINAL_REPORT') application.documents.append(final_report) application.save() payment.final_report_application_document_guid = final_report.application_document_guid payment.save() return '', response_code