Skip to content

Commit 1f7c926

Browse files
authored
Merge pull request #175 from docusign/feature/delete-restore-envelope
Delete and Restore an Envelope Functionality is working as expected
2 parents e852e48 + df90d6e commit 1f7c926

File tree

10 files changed

+323
-71
lines changed

10 files changed

+323
-71
lines changed

app/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
app.register_blueprint(esignature_views.eg042)
115115
app.register_blueprint(esignature_views.eg043)
116116
app.register_blueprint(esignature_views.eg044)
117+
app.register_blueprint(esignature_views.eg045)
117118

118119
app.register_blueprint(connect_views.cneg001)
119120

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from docusign_esign import FoldersApi, FoldersRequest
2+
3+
from ...docusign import create_api_client
4+
5+
6+
class Eg045DeleteRestoreEnvelopeController:
7+
@staticmethod
8+
def move_envelope(args):
9+
#ds-snippet-start:eSign45Step2
10+
api_client = create_api_client(base_path=args["base_path"], access_token=args["access_token"])
11+
folders_api = FoldersApi(api_client)
12+
#ds-snippet-end:eSign45Step2
13+
14+
#ds-snippet-start:eSign45Step3
15+
folders_request = FoldersRequest(
16+
envelope_ids=[args["envelope_id"]],
17+
18+
# add from_folder_id parameter if its value is provided
19+
**({"from_folder_id": args["from_folder_id"]} if args.get("from_folder_id") else {})
20+
)
21+
#ds-snippet-end:eSign45Step3
22+
23+
#ds-snippet-start:eSign45Step4
24+
results = folders_api.move_envelopes(account_id=args["account_id"], folder_id=args["folder_id"], folders_request=folders_request)
25+
#ds-snippet-end:eSign45Step4
26+
return results
27+
28+
@staticmethod
29+
def get_folders(args):
30+
api_client = create_api_client(base_path=args["base_path"], access_token=args["access_token"])
31+
folders_api = FoldersApi(api_client)
32+
33+
#ds-snippet-start:eSign45Step5
34+
results = folders_api.list(account_id=args["account_id"])
35+
#ds-snippet-end:eSign45Step5
36+
return results

app/eSignature/utils.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
def get_folder_id_by_name(folders, folder_name):
2+
for folder in folders:
3+
if folder.name.lower() == folder_name.lower():
4+
return folder.folder_id
5+
6+
subfolders = folder.folders
7+
if subfolders is not None and len(subfolders) > 0:
8+
folder_id = get_folder_id_by_name(subfolders, folder_name)
9+
if folder_id is not None:
10+
return folder_id

app/eSignature/views/__init__.py

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,44 @@
1-
from ...eg001_embedded_signing import eg001
2-
from .eg002_signing_via_email import eg002
3-
from .eg003_list_envelopes import eg003
4-
from .eg004_envelope_info import eg004
5-
from .eg005_envelope_recipients import eg005
6-
from .eg006_envelope_docs import eg006
7-
from .eg007_envelope_get_doc import eg007
8-
from .eg008_create_template import eg008
9-
from .eg009_use_template import eg009
10-
from .eg010_send_binary_docs import eg010
11-
from .eg011_embedded_sending import eg011
12-
from .eg012_embedded_console import eg012
13-
from .eg013_add_doc_to_template import eg013
14-
from .eg014_collect_payment import eg014
15-
from .eg015_envelope_tab_data import eg015
16-
from .eg016_set_tab_values import eg016
17-
from .eg017_set_template_tab_values import eg017
18-
from .eg018_envelope_custom_field_data import eg018
19-
from .eg019_access_code_authentication import eg019
20-
from .eg020_phone_authentication import eg020
21-
from .eg022_kba_authentication import eg022
22-
from .eg023_idv_authentication import eg023
23-
from .eg024_permissions_creating import eg024
24-
from .eg025_permissions_set_user_group import eg025
25-
from .eg026_permissions_change_single_setting import eg026
26-
from .eg027_permissions_delete import eg027
27-
from .eg028_brand_creating import eg028
28-
from .eg029_brands_apply_to_envelope import eg029
29-
from .eg030_brands_apply_to_template import eg030
30-
from .eg031_bulk_send import eg031
31-
from .eg032_pause_signature_workflow import eg032
32-
from .eg033_unpause_signature_workflow import eg033
33-
from .eg034_use_conditional_recipients import eg034
34-
from .eg035_scheduled_sending import eg035
35-
from .eg036_delayed_routing import eg036
36-
from .eg037_sms_delivery import eg037
37-
from .eg038_responsive_signing import eg038
38-
from .eg039_in_person_signer import eg039
39-
from .eg040_document_visibility import eg040
40-
from .eg041_cfr_embedded_signing import eg041
41-
from .eg042_document_generation import eg042
42-
from .eg043_shared_access import eg043
43-
from .eg044_focused_view import eg044
1+
from ...eg001_embedded_signing import eg001
2+
from .eg002_signing_via_email import eg002
3+
from .eg003_list_envelopes import eg003
4+
from .eg004_envelope_info import eg004
5+
from .eg005_envelope_recipients import eg005
6+
from .eg006_envelope_docs import eg006
7+
from .eg007_envelope_get_doc import eg007
8+
from .eg008_create_template import eg008
9+
from .eg009_use_template import eg009
10+
from .eg010_send_binary_docs import eg010
11+
from .eg011_embedded_sending import eg011
12+
from .eg012_embedded_console import eg012
13+
from .eg013_add_doc_to_template import eg013
14+
from .eg014_collect_payment import eg014
15+
from .eg015_envelope_tab_data import eg015
16+
from .eg016_set_tab_values import eg016
17+
from .eg017_set_template_tab_values import eg017
18+
from .eg018_envelope_custom_field_data import eg018
19+
from .eg019_access_code_authentication import eg019
20+
from .eg020_phone_authentication import eg020
21+
from .eg022_kba_authentication import eg022
22+
from .eg023_idv_authentication import eg023
23+
from .eg024_permissions_creating import eg024
24+
from .eg025_permissions_set_user_group import eg025
25+
from .eg026_permissions_change_single_setting import eg026
26+
from .eg027_permissions_delete import eg027
27+
from .eg028_brand_creating import eg028
28+
from .eg029_brands_apply_to_envelope import eg029
29+
from .eg030_brands_apply_to_template import eg030
30+
from .eg031_bulk_send import eg031
31+
from .eg032_pause_signature_workflow import eg032
32+
from .eg033_unpause_signature_workflow import eg033
33+
from .eg034_use_conditional_recipients import eg034
34+
from .eg035_scheduled_sending import eg035
35+
from .eg036_delayed_routing import eg036
36+
from .eg037_sms_delivery import eg037
37+
from .eg038_responsive_signing import eg038
38+
from .eg039_in_person_signer import eg039
39+
from .eg040_document_visibility import eg040
40+
from .eg041_cfr_embedded_signing import eg041
41+
from .eg042_document_generation import eg042
42+
from .eg043_shared_access import eg043
43+
from .eg044_focused_view import eg044
44+
from .eg045_delete_restore_envelope import eg045
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
""" Example 045: Delete and undelete an Envelope """
2+
3+
from os import path
4+
5+
from docusign_esign.client.api_exception import ApiException
6+
from flask import render_template, session, Blueprint, request, redirect
7+
8+
from ..examples.eg045_delete_restore_envelope import Eg045DeleteRestoreEnvelopeController
9+
from ..utils import get_folder_id_by_name
10+
from ...docusign import authenticate, ensure_manifest, get_example_by_number
11+
from ...ds_config import DS_CONFIG
12+
from ...error_handlers import process_error
13+
from ...consts import pattern, API_TYPE
14+
15+
example_number = 45
16+
api = API_TYPE["ESIGNATURE"]
17+
eg = f"eg0{example_number}" # reference (and url) for this example
18+
restore_endpoint = f"{eg}restore"
19+
delete_folder_id = "recyclebin"
20+
restore_folder_id = "sentitems"
21+
eg045 = Blueprint(eg, __name__)
22+
23+
@eg045.route(f"/{eg}", methods=["POST"])
24+
@authenticate(eg=eg, api=api)
25+
@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
26+
def delete_envelope():
27+
"""
28+
1. Get required arguments
29+
2. Call the worker method
30+
3. Render success response
31+
"""
32+
33+
# 1. Get required arguments
34+
args = {
35+
"account_id": session["ds_account_id"],
36+
"base_path": session["ds_base_path"],
37+
"access_token": session["ds_access_token"],
38+
"envelope_id": pattern.sub("", request.form.get("envelope_id")),
39+
"folder_id": delete_folder_id
40+
}
41+
try:
42+
# 2. Call the worker method
43+
Eg045DeleteRestoreEnvelopeController.move_envelope(args)
44+
except ApiException as err:
45+
return process_error(err)
46+
47+
session["envelope_id"] = args["envelope_id"] # Save for use by second part of example
48+
49+
# 3. Render success response
50+
example = get_example_by_number(session["manifest"], example_number, api)
51+
additional_page_data = next(
52+
(p for p in example["AdditionalPage"] if p["Name"] == "envelope_is_deleted"),
53+
None
54+
)
55+
return render_template(
56+
"example_done.html",
57+
title=example["ExampleName"],
58+
message=additional_page_data["ResultsPageText"].format(args["envelope_id"]),
59+
redirect_url=restore_endpoint
60+
)
61+
62+
@eg045.route(f"/{restore_endpoint}", methods=["POST"])
63+
@authenticate(eg=eg, api=api)
64+
@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
65+
def restore_envelope():
66+
"""
67+
1. Get required arguments
68+
2. Call the worker method
69+
3. Render success response
70+
"""
71+
72+
# 1. Get required arguments
73+
folder_name = pattern.sub("", request.form.get("folder_name"))
74+
args = {
75+
"account_id": session["ds_account_id"],
76+
"base_path": session["ds_base_path"],
77+
"access_token": session["ds_access_token"],
78+
"envelope_id": pattern.sub("", session.get("envelope_id")),
79+
"from_folder_id": delete_folder_id
80+
}
81+
82+
example = get_example_by_number(session["manifest"], example_number, api)
83+
try:
84+
# 2. Call the worker method
85+
folders = Eg045DeleteRestoreEnvelopeController.get_folders(args)
86+
args["folder_id"] = get_folder_id_by_name(folders.folders, folder_name)
87+
88+
if args["folder_id"] is None:
89+
additional_page_data = next(
90+
(p for p in example["AdditionalPage"] if p["Name"] == "folder_does_not_exist"),
91+
None
92+
)
93+
94+
return render_template(
95+
"example_done.html",
96+
title=example["ExampleName"],
97+
message=additional_page_data["ResultsPageText"].format(folder_name),
98+
redirect_url=restore_endpoint
99+
)
100+
101+
Eg045DeleteRestoreEnvelopeController.move_envelope(args)
102+
except ApiException as err:
103+
return process_error(err)
104+
105+
# 3. Render success response with envelopeId
106+
return render_template(
107+
"example_done.html",
108+
title=example["ExampleName"],
109+
message=example["ResultsPageText"].format(session.get("envelope_id", ""), args["folder_id"], folder_name)
110+
)
111+
112+
@eg045.route(f"/{eg}", methods=["GET"])
113+
@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
114+
@authenticate(eg=eg, api=api)
115+
def get_view():
116+
"""responds with the form for the example"""
117+
example = get_example_by_number(session["manifest"], example_number, api)
118+
119+
return render_template(
120+
"eSignature/eg045_delete_envelope.html",
121+
title=example["ExampleName"],
122+
example=example,
123+
envelope_id=session.get("envelope_id", ""),
124+
submit_button_text=session["manifest"]["SupportingTexts"]["HelpingTexts"]["SubmitButtonDeleteText"],
125+
source_file="eg045_delete_restore_envelope.py",
126+
source_url=DS_CONFIG["github_example_url"] + "eg045_delete_restore_envelope.py",
127+
documentation=DS_CONFIG["documentation"] + eg,
128+
show_doc=DS_CONFIG["documentation"],
129+
signer_name=DS_CONFIG["signer_name"],
130+
signer_email=DS_CONFIG["signer_email"]
131+
)
132+
133+
@eg045.route(f"/{restore_endpoint}", methods=["GET"])
134+
@ensure_manifest(manifest_url=DS_CONFIG["example_manifest_url"])
135+
@authenticate(eg=eg, api=api)
136+
def get_restore_view():
137+
"""responds with the form for the example"""
138+
example = get_example_by_number(session["manifest"], example_number, api)
139+
140+
if not session.get("envelope_id"):
141+
return redirect(eg)
142+
143+
return render_template(
144+
"eSignature/eg045_restore_envelope.html",
145+
title=example["ExampleName"],
146+
example=example,
147+
envelope_id=session.get("envelope_id"),
148+
submit_button_text=session["manifest"]["SupportingTexts"]["HelpingTexts"]["SubmitButtonRestoreText"],
149+
source_file="eg045_delete_restore_envelope.py",
150+
source_url=DS_CONFIG["github_example_url"] + "eg045_delete_restore_envelope.py",
151+
documentation=DS_CONFIG["documentation"] + eg,
152+
show_doc=DS_CONFIG["documentation"],
153+
signer_name=DS_CONFIG["signer_name"],
154+
signer_email=DS_CONFIG["signer_email"]
155+
)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!-- extend base layout --> {% extends "base.html" %} {% block content %}
2+
3+
{% include 'example_info.html' %}
4+
5+
{% set form_index = 0 %}
6+
{% set envelope_id_index = 0 %}
7+
8+
<form class="eg" action="" method="post" data-busy="form">
9+
{% if 'FormName' in example['Forms'][form_index] %}
10+
<p>{{ example['Forms'][form_index]['FormName'] | safe }}</p>
11+
{% endif %}
12+
13+
<div class="form-group">
14+
<label for="envelope_id">{{ example['Forms'][form_index]['Inputs'][envelope_id_index]['InputName'] }}</label>
15+
<input type="text" class="form-control" id="envelope_id" name="envelope_id"
16+
aria-describedby="envelope_id_help" placeholder="{{ example['Forms'][form_index]['Inputs'][envelope_id_index]['InputPlaceholder'] }}" required
17+
value="{{ envelope_id }}" />
18+
<small id="envelope_id_help" class="form-text text-muted">{{ session['manifest']['SupportingTexts']['HelpingTexts']['DefaultEnvelopeId'] | safe}}</small>
19+
</div>
20+
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
21+
{% include 'submit_button.html' %}
22+
</form>
23+
24+
{% endblock %}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<!-- extend base layout --> {% extends "base.html" %} {% block content %}
2+
3+
<h4>{{ title }}</h4>
4+
<p>{{ example["ExampleDescription"] | safe }}</p>
5+
<p>{{ session["manifest"]["SupportingTexts"]["HelpingTexts"]["EnvelopeWillBeRestored"].format(envelope_id) | safe }}</p>
6+
7+
{% set form_index = 0 %}
8+
{% set folder_name_index = 1 %}
9+
10+
<form class="eg" action="" method="post" data-busy="form">
11+
{% if 'FormName' in example['Forms'][form_index] %}
12+
<p>{{ example['Forms'][form_index]['FormName'] | safe }}</p>
13+
{% endif %}
14+
15+
<div class="form-group">
16+
<label for="folder_name">{{ example['Forms'][form_index]['Inputs'][folder_name_index]['InputName'] }}</label>
17+
<input type="text" class="form-control" id="folder_name" name="folder_name"
18+
placeholder="{{ example['Forms'][form_index]['Inputs'][folder_name_index]['InputPlaceholder'] }}" required/>
19+
</div>
20+
21+
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
22+
{% include 'submit_button.html' %}
23+
</form>
24+
25+
{% endblock %}

0 commit comments

Comments
 (0)