From 868209074b8a418c02b6227c98762b5078342678 Mon Sep 17 00:00:00 2001 From: Balaji Jayaraman Date: Sun, 19 Oct 2025 11:46:34 +0530 Subject: [PATCH] added delete and restore envelope how to code snippets --- app/__init__.py | 1 + .../examples/eg045_delete_restore_envelope.py | 48 ++++++ app/eSignature/utils.py | 10 ++ app/eSignature/views/__init__.py | 1 + .../views/eg045_delete_restore_envelope.py | 155 ++++++++++++++++++ .../eSignature/eg045_delete_envelope.html | 24 +++ .../eSignature/eg045_restore_envelope.html | 25 +++ app/templates/example_info.html | 4 +- app/templates/submit_button.html | 2 +- requirements.txt | 2 +- 10 files changed, 268 insertions(+), 4 deletions(-) create mode 100644 app/eSignature/examples/eg045_delete_restore_envelope.py create mode 100644 app/eSignature/utils.py create mode 100644 app/eSignature/views/eg045_delete_restore_envelope.py create mode 100644 app/templates/eSignature/eg045_delete_envelope.html create mode 100644 app/templates/eSignature/eg045_restore_envelope.html diff --git a/app/__init__.py b/app/__init__.py index f1f1a296..2f38180a 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -114,6 +114,7 @@ app.register_blueprint(esignature_views.eg042) app.register_blueprint(esignature_views.eg043) app.register_blueprint(esignature_views.eg044) +app.register_blueprint(esignature_views.eg045) app.register_blueprint(connect_views.cneg001) diff --git a/app/eSignature/examples/eg045_delete_restore_envelope.py b/app/eSignature/examples/eg045_delete_restore_envelope.py new file mode 100644 index 00000000..c7def3b6 --- /dev/null +++ b/app/eSignature/examples/eg045_delete_restore_envelope.py @@ -0,0 +1,48 @@ +from docusign_esign import FoldersApi, FoldersRequest + +from ...docusign import create_api_client + + +class Eg045DeleteRestoreEnvelopeController: + @staticmethod + def delete_envelope(args): + #ds-snippet-start:eSign45Step2 + api_client = create_api_client(base_path=args["base_path"], access_token=args["access_token"]) + folders_api = FoldersApi(api_client) + #ds-snippet-end:eSign45Step2 + + #ds-snippet-start:eSign45Step3 + folders_request = FoldersRequest( + envelope_ids=[args["envelope_id"]] + ) + #ds-snippet-end:eSign45Step3 + + #ds-snippet-start:eSign45Step4 + results = folders_api.move_envelopes(account_id=args["account_id"], folder_id=args["delete_folder_id"], folders_request=folders_request) + #ds-snippet-end:eSign45Step4 + return results + + @staticmethod + def move_envelope_to_folder(args): + api_client = create_api_client(base_path=args["base_path"], access_token=args["access_token"]) + folders_api = FoldersApi(api_client) + + #ds-snippet-start:eSign45Step6 + folders_request = FoldersRequest( + envelope_ids=[args["envelope_id"]], + from_folder_id=args["from_folder_id"] + ) + + results = folders_api.move_envelopes(account_id=args["account_id"], folder_id=args["folder_id"], folders_request=folders_request) + #ds-snippet-end:eSign45Step6 + return results + + @staticmethod + def get_folders(args): + api_client = create_api_client(base_path=args["base_path"], access_token=args["access_token"]) + folders_api = FoldersApi(api_client) + + #ds-snippet-start:eSign45Step5 + results = folders_api.list(account_id=args["account_id"]) + #ds-snippet-end:eSign45Step5 + return results diff --git a/app/eSignature/utils.py b/app/eSignature/utils.py new file mode 100644 index 00000000..b1d72d79 --- /dev/null +++ b/app/eSignature/utils.py @@ -0,0 +1,10 @@ +def get_folder_id_by_name(folders, folder_name): + for folder in folders: + if folder.name.lower() == folder_name.lower(): + return folder.folder_id + + subfolders = folder.folders + if subfolders is not None and len(subfolders) > 0: + folder_id = get_folder_id_by_name(subfolders, folder_name) + if folder_id is not None: + return folder_id \ No newline at end of file diff --git a/app/eSignature/views/__init__.py b/app/eSignature/views/__init__.py index 7fcacd6d..00c5cc90 100644 --- a/app/eSignature/views/__init__.py +++ b/app/eSignature/views/__init__.py @@ -41,3 +41,4 @@ from .eg042_document_generation import eg042 from .eg043_shared_access import eg043 from .eg044_focused_view import eg044 +from .eg045_delete_restore_envelope import eg045 diff --git a/app/eSignature/views/eg045_delete_restore_envelope.py b/app/eSignature/views/eg045_delete_restore_envelope.py new file mode 100644 index 00000000..34289069 --- /dev/null +++ b/app/eSignature/views/eg045_delete_restore_envelope.py @@ -0,0 +1,155 @@ +""" Example 045: Delete and undelete an Envelope """ + +from os import path + +from docusign_esign.client.api_exception import ApiException +from flask import render_template, session, Blueprint, request, redirect + +from ..examples.eg045_delete_restore_envelope import Eg045DeleteRestoreEnvelopeController +from ..utils import get_folder_id_by_name +from ...docusign import authenticate, ensure_manifest, get_example_by_number +from ...ds_config import DS_CONFIG +from ...error_handlers import process_error +from ...consts import pattern, API_TYPE + +example_number = 45 +api = API_TYPE["ESIGNATURE"] +eg = f"eg0{example_number}" # reference (and url) for this example +restore_endpoint = f"{eg}restore" +delete_folder_id = "recyclebin" +restore_folder_id = "sentitems" +eg045 = Blueprint(eg, __name__) + +@eg045.route(f"/{eg}", methods=["POST"]) +@authenticate(eg=eg, api=api) +@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"]) +def delete_envelope(): + """ + 1. Get required arguments + 2. Call the worker method + 3. Render success response + """ + + # 1. Get required arguments + args = { + "account_id": session["ds_account_id"], + "base_path": session["ds_base_path"], + "access_token": session["ds_access_token"], + "envelope_id": pattern.sub("", request.form.get("envelope_id")), + "delete_folder_id": delete_folder_id + } + try: + # 2. Call the worker method + Eg045DeleteRestoreEnvelopeController.delete_envelope(args) + except ApiException as err: + return process_error(err) + + session["envelope_id"] = args["envelope_id"] # Save for use by second part of example + + # 3. Render success response + example = get_example_by_number(session["manifest"], example_number, api) + additional_page_data = next( + (p for p in example["AdditionalPage"] if p["Name"] == "envelope_is_deleted"), + None + ) + return render_template( + "example_done.html", + title=example["ExampleName"], + message=additional_page_data["ResultsPageText"].format(args["envelope_id"]), + redirect_url=restore_endpoint + ) + +@eg045.route(f"/{restore_endpoint}", methods=["POST"]) +@authenticate(eg=eg, api=api) +@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"]) +def restore_envelope(): + """ + 1. Get required arguments + 2. Call the worker method + 3. Render success response + """ + + # 1. Get required arguments + folder_name = pattern.sub("", request.form.get("folder_name")) + args = { + "account_id": session["ds_account_id"], + "base_path": session["ds_base_path"], + "access_token": session["ds_access_token"], + "envelope_id": pattern.sub("", session.get("envelope_id")), + "from_folder_id": delete_folder_id + } + + example = get_example_by_number(session["manifest"], example_number, api) + try: + # 2. Call the worker method + folders = Eg045DeleteRestoreEnvelopeController.get_folders(args) + args["folder_id"] = get_folder_id_by_name(folders.folders, folder_name) + + if args["folder_id"] is None: + additional_page_data = next( + (p for p in example["AdditionalPage"] if p["Name"] == "folder_does_not_exist"), + None + ) + + return render_template( + "example_done.html", + title=example["ExampleName"], + message=additional_page_data["ResultsPageText"].format(folder_name), + redirect_url=restore_endpoint + ) + + Eg045DeleteRestoreEnvelopeController.move_envelope_to_folder(args) + except ApiException as err: + return process_error(err) + + # 3. Render success response with envelopeId + return render_template( + "example_done.html", + title=example["ExampleName"], + message=example["ResultsPageText"].format(session.get("envelope_id", ""), args["folder_id"], folder_name) + ) + +@eg045.route(f"/{eg}", methods=["GET"]) +@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"]) +@authenticate(eg=eg, api=api) +def get_view(): + """responds with the form for the example""" + example = get_example_by_number(session["manifest"], example_number, api) + + return render_template( + "eSignature/eg045_delete_envelope.html", + title=example["ExampleName"], + example=example, + envelope_id=session.get("envelope_id", ""), + submit_button_text=session["manifest"]["SupportingTexts"]["HelpingTexts"]["SubmitButtonDeleteText"], + source_file="eg045_delete_restore_envelope.py", + source_url=DS_CONFIG["github_example_url"] + "eg045_delete_restore_envelope.py", + documentation=DS_CONFIG["documentation"] + eg, + show_doc=DS_CONFIG["documentation"], + signer_name=DS_CONFIG["signer_name"], + signer_email=DS_CONFIG["signer_email"] + ) + +@eg045.route(f"/{restore_endpoint}", methods=["GET"]) +@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"]) +@authenticate(eg=eg, api=api) +def get_restore_view(): + """responds with the form for the example""" + example = get_example_by_number(session["manifest"], example_number, api) + + if not session.get("envelope_id"): + return redirect(eg) + + return render_template( + "eSignature/eg045_restore_envelope.html", + title=example["ExampleName"], + example=example, + envelope_id=session.get("envelope_id"), + submit_button_text=session["manifest"]["SupportingTexts"]["HelpingTexts"]["SubmitButtonRestoreText"], + source_file="eg045_delete_restore_envelope.py", + source_url=DS_CONFIG["github_example_url"] + "eg045_delete_restore_envelope.py", + documentation=DS_CONFIG["documentation"] + eg, + show_doc=DS_CONFIG["documentation"], + signer_name=DS_CONFIG["signer_name"], + signer_email=DS_CONFIG["signer_email"] + ) diff --git a/app/templates/eSignature/eg045_delete_envelope.html b/app/templates/eSignature/eg045_delete_envelope.html new file mode 100644 index 00000000..80589023 --- /dev/null +++ b/app/templates/eSignature/eg045_delete_envelope.html @@ -0,0 +1,24 @@ + {% extends "base.html" %} {% block content %} + +{% include 'example_info.html' %} + +{% set form_index = 0 %} +{% set envelope_id_index = 0 %} + +
+ {% if 'FormName' in example['Forms'][form_index] %} +

{{ example['Forms'][form_index]['FormName'] | safe }}

+ {% endif %} + +
+ + + {{ session['manifest']['SupportingTexts']['HelpingTexts']['DefaultEnvelopeId'] | safe}} +
+ + {% include 'submit_button.html' %} +
+ +{% endblock %} diff --git a/app/templates/eSignature/eg045_restore_envelope.html b/app/templates/eSignature/eg045_restore_envelope.html new file mode 100644 index 00000000..d2bacee9 --- /dev/null +++ b/app/templates/eSignature/eg045_restore_envelope.html @@ -0,0 +1,25 @@ + {% extends "base.html" %} {% block content %} + +

{{ title }}

+

{{ example["ExampleDescription"] | safe }}

+

{{ session["manifest"]["SupportingTexts"]["HelpingTexts"]["EnvelopeWillBeRestored"].format(envelope_id) | safe }}

+ +{% set form_index = 0 %} +{% set folder_name_index = 1 %} + +
+ {% if 'FormName' in example['Forms'][form_index] %} +

{{ example['Forms'][form_index]['FormName'] | safe }}

+ {% endif %} + +
+ + +
+ + + {% include 'submit_button.html' %} +
+ +{% endblock %} diff --git a/app/templates/example_info.html b/app/templates/example_info.html index 4c6027ed..095a207a 100644 --- a/app/templates/example_info.html +++ b/app/templates/example_info.html @@ -5,8 +5,8 @@

{{ title }}

Documentation about this example.

{% endif %} -{% if "Note" in example %} -

{{ example["Note"] | safe }}

+{% if "Notes" in example %} +

{{ example["Notes"] | safe }}

{% endif %} {% if example["LinksToAPIMethod"] | length > 0 %} diff --git a/app/templates/submit_button.html b/app/templates/submit_button.html index 3f79e452..15891df5 100644 --- a/app/templates/submit_button.html +++ b/app/templates/submit_button.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 6d37a44e..9ec341dd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ cffi==1.17.1 chardet==5.2.0 Click cryptography==45.0.3 -docusign-esign==5.0.0 +docusign-esign==5.3.0 docusign-rooms==1.3.0 docusign-monitor==1.2.0 docusign-click==1.4.0