Skip to content

Commit ed821b0

Browse files
merge updates
2 parents cedc1fe + d0e4889 commit ed821b0

File tree

6 files changed

+503
-2
lines changed

6 files changed

+503
-2
lines changed

app/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
app.register_blueprint(esignature_views.eg043)
116116
app.register_blueprint(esignature_views.eg044)
117117
app.register_blueprint(esignature_views.eg045)
118+
app.register_blueprint(esignature_views.eg046)
118119

119120
app.register_blueprint(connect_views.cneg001)
120121

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
import base64
2+
from datetime import datetime as dt, timezone
3+
from os import path
4+
5+
from docusign_esign import (
6+
EnvelopesApi,
7+
EnvelopeDefinition,
8+
Document,
9+
Signer,
10+
CarbonCopy,
11+
SignHere,
12+
Tabs,
13+
Recipients,
14+
RecipientPhoneNumber,
15+
RecipientAdditionalNotification
16+
)
17+
18+
from flask import session, request
19+
20+
from ...consts import demo_docs_path, pattern
21+
from ...docusign import create_api_client
22+
from ...ds_config import DS_CONFIG
23+
24+
25+
class Eg046MultipleDeliveryController:
26+
@staticmethod
27+
def get_args():
28+
"""Get request and session arguments"""
29+
30+
# More data validation would be a good idea here
31+
# Strip anything other than characters listed
32+
signer_name = pattern.sub("", request.form.get("signer_name"))
33+
signer_email = pattern.sub("", request.form.get("signer_email"))
34+
cc_name = pattern.sub("", request.form.get("cc_name"))
35+
cc_email = pattern.sub("", request.form.get("cc_email"))
36+
signer_phone_number = request.form.get("signer_phone_number")
37+
signer_country_code = request.form.get("signer_country_code")
38+
cc_phone_number = request.form.get("cc_phone_number")
39+
cc_country_code = request.form.get("cc_country_code")
40+
delivery_method = request.form["delivery_method"]
41+
envelope_args = {
42+
"signer_name": signer_name,
43+
"signer_email": signer_email,
44+
"status": "sent",
45+
"cc_name": cc_name,
46+
"cc_email": cc_email,
47+
"signer_country_code": signer_country_code,
48+
"signer_phone_number": signer_phone_number,
49+
"cc_country_code" :cc_country_code,
50+
"cc_phone_number": cc_phone_number,
51+
"delivery_method": delivery_method
52+
}
53+
args = {
54+
"account_id": session["ds_account_id"],
55+
"base_path": session["ds_base_path"],
56+
"access_token": session["ds_access_token"],
57+
"envelope_args": envelope_args
58+
}
59+
return args
60+
61+
@classmethod
62+
def worker(cls, args):
63+
"""
64+
1. Create the envelope request object
65+
2. Send the envelope
66+
"""
67+
68+
#ds-snippet-start:eSign46Step3
69+
envelope_args = args["envelope_args"]
70+
# Create the envelope request object
71+
api_client = create_api_client(base_path=args["base_path"], access_token=args["access_token"])
72+
envelope_definition = cls.make_envelope(envelope_args)
73+
# Call Envelopes::create API method
74+
# Exceptions will be caught by the calling function
75+
envelopes_api = EnvelopesApi(api_client)
76+
(results, status, headers) = envelopes_api.create_envelope_with_http_info(account_id=args["account_id"], envelope_definition=envelope_definition)
77+
78+
remaining = headers.get("X-RateLimit-Remaining")
79+
reset = headers.get("X-RateLimit-Reset")
80+
81+
if remaining is not None and reset is not None:
82+
reset_date = dt.fromtimestamp(int(reset), tz=timezone.utc)
83+
print(f"API calls remaining: {remaining}")
84+
print(f"Next Reset: {reset_date}")
85+
86+
envelope_id = results.envelope_id
87+
88+
return {"envelope_id": envelope_id}
89+
#ds-snippet-end:eSign46Step3
90+
91+
#ds-snippet-start:eSign46Step2
92+
@classmethod
93+
def make_envelope(cls, args):
94+
"""
95+
Creates envelope:
96+
document 1 (HTML) has signHere anchor tag: **signature_1**
97+
document 2 (DOCX) has signHere anchor tag: /sn1/
98+
document 3 (PDF) has signHere anchor tag: /sn1/
99+
DocuSign will convert all of the documents to the PDF format.
100+
The recipient’s field tags are placed using anchor strings.
101+
The envelope has two recipients:
102+
recipient 1: signer
103+
recipient 2: cc
104+
The envelope will be sent first to the signer via SMS.
105+
After it is signed, a copy is sent to the cc recipient via SMS.
106+
"""
107+
# Create the envelope definition
108+
env = EnvelopeDefinition(
109+
email_subject="Please sign this document set"
110+
)
111+
doc1_b64 = base64.b64encode(bytes(cls.create_document1(args), "utf-8")).decode("ascii")
112+
# Read files 2 and 3 from a local folder
113+
# The reads could raise an exception if the file is not available!
114+
with open(path.join(demo_docs_path, DS_CONFIG["doc_docx"]), "rb") as file:
115+
doc2_docx_bytes = file.read()
116+
doc2_b64 = base64.b64encode(doc2_docx_bytes).decode("ascii")
117+
with open(path.join(demo_docs_path, DS_CONFIG["doc_pdf"]), "rb") as file:
118+
doc3_pdf_bytes = file.read()
119+
doc3_b64 = base64.b64encode(doc3_pdf_bytes).decode("ascii")
120+
121+
# Create the document models
122+
document1 = Document( # Create the DocuSign document object
123+
document_base64=doc1_b64,
124+
name="Order acknowledgement", # Can be different from actual file name
125+
file_extension="html", # Many different document types are accepted
126+
document_id="1" # A label used to reference the doc
127+
)
128+
document2 = Document( # Create the DocuSign document object
129+
document_base64=doc2_b64,
130+
name="Battle Plan", # Can be different from actual file name
131+
file_extension="docx", # Many different document types are accepted
132+
document_id="2" # A label used to reference the doc
133+
)
134+
document3 = Document( # Create the DocuSign document object
135+
document_base64=doc3_b64,
136+
name="Lorem Ipsum", # Can be different from actual file name
137+
file_extension="pdf", # Many different document types are accepted
138+
document_id="3" # A label used to reference the doc
139+
)
140+
# The order in the docs array determines the order in the envelope
141+
env.documents = [document1, document2, document3]
142+
143+
signer_phone_number = RecipientPhoneNumber(
144+
country_code=args["signer_country_code"],
145+
number=args["signer_phone_number"]
146+
)
147+
signer_additional_notification = RecipientAdditionalNotification(
148+
secondary_delivery_method=args["delivery_method"],
149+
phone_number=signer_phone_number
150+
)
151+
152+
# Create the signer recipient model
153+
signer1 = Signer(
154+
name=args["signer_name"],
155+
email=args["signer_email"],
156+
recipient_id="1",
157+
routing_order="1",
158+
delivery_method="Email",
159+
additional_notifications=[signer_additional_notification]
160+
)
161+
162+
# Create a RecipientPhoneNumber and add it to the additional SMS notification
163+
cc_phone_number = RecipientPhoneNumber(
164+
country_code=args["cc_country_code"],
165+
number=args["cc_phone_number"]
166+
)
167+
168+
cc_additional_notification = RecipientAdditionalNotification(
169+
secondary_delivery_method=args["delivery_method"],
170+
phone_number=cc_phone_number
171+
)
172+
173+
# Create a cc recipient to receive a copy of the documents
174+
cc1 = CarbonCopy(
175+
name=args["cc_name"],
176+
email=args["cc_email"],
177+
recipient_id="2",
178+
routing_order="2",
179+
delivery_method="Email",
180+
additional_notifications=[cc_additional_notification]
181+
)
182+
183+
# routingOrder (lower means earlier) determines the order of deliveries
184+
# to the recipients. Parallel routing order is supported by using the
185+
# same integer as the order for two or more recipients
186+
187+
# Create signHere fields (also known as tabs) on the documents
188+
# We're using anchor (autoPlace) positioning
189+
#
190+
# The DocuSign platform searches throughout your envelope"s
191+
# documents for matching anchor strings. So the
192+
# signHere2 tab will be used in both document 2 and 3 since they
193+
# use the same anchor string for their "signer 1" tabs
194+
sign_here1 = SignHere(
195+
anchor_string="**signature_1**",
196+
anchor_units="pixels",
197+
anchor_y_offset="10",
198+
anchor_x_offset="20"
199+
)
200+
201+
sign_here2 = SignHere(
202+
anchor_string="/sn1/",
203+
anchor_units="pixels",
204+
anchor_y_offset="10",
205+
anchor_x_offset="20"
206+
)
207+
208+
# Add the tabs model (including the SignHere tabs) to the signer
209+
# The Tabs object wants arrays of the different field/tab types
210+
signer1.tabs = Tabs(sign_here_tabs=[sign_here1, sign_here2])
211+
212+
# Add the recipients to the envelope object
213+
recipients = Recipients(signers=[signer1], carbon_copies=[cc1])
214+
env.recipients = recipients
215+
216+
# Request that the envelope be sent by setting status to "sent"
217+
# To request that the envelope be created as a draft, set to "created"
218+
env.status = args["status"]
219+
220+
return env
221+
222+
@classmethod
223+
def create_document1(cls, args):
224+
""" Creates document 1 -- an html document"""
225+
226+
return f"""
227+
<!DOCTYPE html>
228+
<html>
229+
<head>
230+
<meta charset="UTF-8">
231+
</head>
232+
<body style="font-family:sans-serif;margin-left:2em;">
233+
<h1 style="font-family: "Trebuchet MS", Helvetica, sans-serif;
234+
color: darkblue;margin-bottom: 0;">World Wide Corp</h1>
235+
<h2 style="font-family: "Trebuchet MS", Helvetica, sans-serif;
236+
margin-top: 0px;margin-bottom: 3.5em;font-size: 1em;
237+
color: darkblue;">Order Processing Division</h2>
238+
<h4>Ordered by {args["signer_name"]}</h4>
239+
<p style="margin-top:0em; margin-bottom:0em;">Phone Number: {args["signer_phone_number"]}</p>
240+
<p style="margin-top:0em; margin-bottom:0em;">Copy to: {args["cc_name"]}</p>
241+
<p style="margin-top:3em;">
242+
Candy bonbon pastry jujubes lollipop wafer biscuit biscuit. Topping brownie sesame snaps sweet roll pie.
243+
Croissant danish biscuit soufflé caramels jujubes jelly. Dragée danish caramels lemon drops dragée.
244+
Gummi bears cupcake biscuit tiramisu sugar plum pastry. Dragée gummies applicake pudding liquorice.
245+
Donut jujubes oat cake jelly-o.
246+
Dessert bear claw chocolate cake gummies lollipop sugar plum ice cream gummies cheesecake.
247+
</p>
248+
<!-- Note the anchor tag for the signature field is in white -->
249+
<h3 style="margin-top:3em;">Agreed: <span style="color:white;">**signature_1**/</span></h3>
250+
</body>
251+
</html>
252+
"""
253+
#ds-snippet-end:eSign46Step2

app/eSignature/views/__init__.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<<<<<<< HEAD
12
from ...eg001_embedded_signing import eg001
23
from .eg002_signing_via_email import eg002
34
from .eg003_list_envelopes import eg003
@@ -42,3 +43,50 @@
4243
from .eg043_shared_access import eg043
4344
from .eg044_focused_view import eg044
4445
from .eg045_delete_restore_envelope import eg045
46+
=======
47+
from ...eg001_embedded_signing import eg001
48+
from .eg002_signing_via_email import eg002
49+
from .eg003_list_envelopes import eg003
50+
from .eg004_envelope_info import eg004
51+
from .eg005_envelope_recipients import eg005
52+
from .eg006_envelope_docs import eg006
53+
from .eg007_envelope_get_doc import eg007
54+
from .eg008_create_template import eg008
55+
from .eg009_use_template import eg009
56+
from .eg010_send_binary_docs import eg010
57+
from .eg011_embedded_sending import eg011
58+
from .eg012_embedded_console import eg012
59+
from .eg013_add_doc_to_template import eg013
60+
from .eg014_collect_payment import eg014
61+
from .eg015_envelope_tab_data import eg015
62+
from .eg016_set_tab_values import eg016
63+
from .eg017_set_template_tab_values import eg017
64+
from .eg018_envelope_custom_field_data import eg018
65+
from .eg019_access_code_authentication import eg019
66+
from .eg020_phone_authentication import eg020
67+
from .eg022_kba_authentication import eg022
68+
from .eg023_idv_authentication import eg023
69+
from .eg024_permissions_creating import eg024
70+
from .eg025_permissions_set_user_group import eg025
71+
from .eg026_permissions_change_single_setting import eg026
72+
from .eg027_permissions_delete import eg027
73+
from .eg028_brand_creating import eg028
74+
from .eg029_brands_apply_to_envelope import eg029
75+
from .eg030_brands_apply_to_template import eg030
76+
from .eg031_bulk_send import eg031
77+
from .eg032_pause_signature_workflow import eg032
78+
from .eg033_unpause_signature_workflow import eg033
79+
from .eg034_use_conditional_recipients import eg034
80+
from .eg035_scheduled_sending import eg035
81+
from .eg036_delayed_routing import eg036
82+
from .eg037_sms_delivery import eg037
83+
from .eg038_responsive_signing import eg038
84+
from .eg039_in_person_signer import eg039
85+
from .eg040_document_visibility import eg040
86+
from .eg041_cfr_embedded_signing import eg041
87+
from .eg042_document_generation import eg042
88+
from .eg043_shared_access import eg043
89+
from .eg044_focused_view import eg044
90+
from .eg045_delete_restore_envelope import eg045
91+
from .eg046_multiple_delivery import eg046
92+
>>>>>>> d0e48893160382568c4c1dd0c9fc9c5b735c12c7

0 commit comments

Comments
 (0)