def edit_section(framework_slug, service_id, section_id): service = data_api_client.get_service(service_id) if service is None: abort(404) service = service['services'] if not is_service_associated_with_supplier(service): abort(404) if service["frameworkSlug"] != framework_slug: abort(404) # we don't actually need the framework here; using this to 404 if framework for the service is not live get_framework_or_404(data_api_client, service['frameworkSlug'], allowed_statuses=['live']) try: content = content_loader.get_manifest(service["frameworkSlug"], 'edit_service').filter( service, inplace_allowed=True, ) except ContentNotFoundError: abort(404) section = content.get_section(section_id) if section is None or not section.editable: abort(404) session_timeout = displaytimeformat(datetime.utcnow() + timedelta(hours=1)) return render_template( "services/edit_section.html", section=section, service_data=service, service_id=service_id, session_timeout=session_timeout, )
def test_displaytimeformat(dt, formatted_time): assert displaytimeformat(dt) == formatted_time
def edit_service_submission(framework_slug, lot_slug, service_id, section_id, question_slug=None): """ Also accepts URL parameter `force_continue_button` which will allow rendering of a 'Save and continue' button, used for when copying services. """ framework, lot = get_framework_and_lot_or_404(data_api_client, framework_slug, lot_slug, allowed_statuses=['open']) # Suppliers must have registered interest in a framework before they can edit draft services if not get_supplier_framework_info(data_api_client, framework_slug): abort(404) force_return_to_summary = framework['framework'] == "digital-outcomes-and-specialists" force_continue_button = request.args.get('force_continue_button') next_question = None try: draft = data_api_client.get_draft_service(service_id)['services'] except HTTPError as e: abort(e.status_code) if draft['lotSlug'] != lot_slug or draft['frameworkSlug'] != framework_slug: abort(404) if not is_service_associated_with_supplier(draft): abort(404) content = content_loader.get_manifest(framework_slug, 'edit_submission').filter(draft, inplace_allowed=True) section = content.get_section(section_id) if section and (question_slug is not None): next_question = section.get_question_by_slug(section.get_next_question_slug(question_slug)) section = section.get_question_as_section(question_slug) if section is None or not section.editable: abort(404) errors = None if request.method == "POST": update_data = section.get_data(request.form) if request.files: uploader = s3.S3(current_app.config['DM_SUBMISSIONS_BUCKET']) documents_url = url_for('.dashboard', _external=True) + '/assets/' # This utils method filters out any empty documents and validates against service document rules uploaded_documents, document_errors = upload_service_documents( uploader, 'submissions', documents_url, draft, request.files, section, public=False) if document_errors: errors = section.get_error_messages(document_errors, question_descriptor_from="question") else: update_data.update(uploaded_documents) if not errors and section.has_changes_to_save(draft, update_data): try: data_api_client.update_draft_service( service_id, update_data, current_user.email_address, page_questions=section.get_field_names() ) except HTTPError as e: update_data = section.unformat_data(update_data) errors = section.get_error_messages(e.message, question_descriptor_from="question") if not errors: if next_question and not force_return_to_summary: return redirect(url_for(".edit_service_submission", framework_slug=framework['slug'], lot_slug=draft['lotSlug'], service_id=service_id, section_id=section_id, question_slug=next_question.slug)) else: return redirect(url_for(".view_service_submission", framework_slug=framework['slug'], lot_slug=draft['lotSlug'], service_id=service_id, _anchor=section_id)) update_data.update( (k, draft[k]) for k in ('serviceName', 'lot', 'lotName',) if k in draft and k not in update_data ) service_data = update_data # fall through to regular GET path to display errors else: service_data = section.unformat_data(draft) session_timeout = displaytimeformat(datetime.utcnow() + timedelta(hours=1)) return render_template( "services/edit_submission_section.html", section=section, framework=framework, lot=lot, next_question=next_question, service_data=service_data, service_id=service_id, force_return_to_summary=force_return_to_summary, force_continue_button=force_continue_button, session_timeout=session_timeout, errors=errors, )
def start_new_draft_service(framework_slug, lot_slug): """Page to kick off creation of a new service.""" framework, lot = get_framework_and_lot_or_404(data_api_client, framework_slug, lot_slug, allowed_statuses=['open']) # Suppliers must have registered interest in a framework before they can create draft services if not get_supplier_framework_info(data_api_client, framework_slug): abort(404) content = content_loader.get_manifest(framework_slug, 'edit_submission').filter( {'lot': lot['slug']}, inplace_allowed=True, ) section = content.get_section(content.get_next_editable_section_id()) if section is None: section = content.get_section(content.get_next_edit_questions_section_id(None)) if section is None: abort(404) section = section.get_question_as_section(section.get_next_question_slug()) session_timeout = displaytimeformat(datetime.utcnow() + timedelta(hours=1)) if request.method == 'POST': update_data = section.get_data(request.form) try: draft_service = data_api_client.create_new_draft_service( framework_slug, lot['slug'], current_user.supplier_id, update_data, current_user.email_address, page_questions=section.get_field_names() )['services'] except HTTPError as e: update_data = section.unformat_data(update_data) errors = section.get_error_messages(e.message) return render_template( "services/edit_submission_section.html", framework=framework, section=section, session_timeout=session_timeout, service_data=update_data, errors=errors ), 400 return redirect( url_for( ".view_service_submission", framework_slug=framework['slug'], lot_slug=draft_service['lotSlug'], service_id=draft_service['id'], ) ) return render_template( "services/edit_submission_section.html", framework=framework, lot=lot, service_data={}, section=section, session_timeout=session_timeout, force_continue_button=True, ), 200
def update_section(framework_slug, service_id, section_id): service = data_api_client.get_service(service_id) if service is None: abort(404) service = service['services'] if not is_service_associated_with_supplier(service): abort(404) if service["frameworkSlug"] != framework_slug: abort(404) # we don't actually need the framework here; using this to 404 if framework for the service is not live get_framework_or_404(data_api_client, service['frameworkSlug'], allowed_statuses=['live']) try: content = content_loader.get_manifest(service["frameworkSlug"], 'edit_service').filter( service, inplace_allowed=True, ) except ContentNotFoundError: abort(404) section = content.get_section(section_id) if section is None or not section.editable: abort(404) posted_data = section.get_data(request.form) errors = None # This utils method filters out any empty documents and validates against service document rules uploaded_documents, document_errors = upload_service_documents( s3.S3(current_app.config['DM_DOCUMENTS_BUCKET']), 'documents', current_app.config['DM_ASSETS_URL'], service, request.files, section, ) if document_errors: errors = section.get_error_messages(document_errors) else: posted_data.update(uploaded_documents) if not errors and section.has_changes_to_save(service, posted_data): try: data_api_client.update_service( service_id, posted_data, current_user.email_address) except HTTPError as e: errors = section.get_error_messages(e.message) if errors: session_timeout = displaytimeformat(datetime.utcnow() + timedelta(hours=1)) return render_template( "services/edit_section.html", section=section, service_data=service, service_id=service_id, session_timeout=session_timeout, errors=errors, ), 400 flash(SERVICE_UPDATED_MESSAGE, "success") return redirect(url_for(".edit_service", service_id=service_id, framework_slug=service["frameworkSlug"]))