1+ import base64
2+ from os import path
3+ from typing import List
4+
5+ from docusign_esign import (
6+ EnvelopesApi ,
7+ Document ,
8+ Signer ,
9+ CarbonCopy ,
10+ EnvelopeDefinition ,
11+ SignHere ,
12+ Tabs ,
13+ Recipients ,
14+ )
15+ from flask import session , request
16+
17+ from ...consts import demo_docs_path , pattern
18+ from ...docusign import create_api_client
19+
20+
21+ class Eg040DocumentVisibility :
22+ @staticmethod
23+ def get_args ():
24+ """Get request and session arguments"""
25+ # More data validation would be a good idea here
26+ # Strip anything other than characters listed
27+ # 1. Parse request arguments
28+ signer1_email = pattern .sub ("" , request .form .get ("signer1_email" ))
29+ signer1_name = pattern .sub ("" , request .form .get ("signer1_name" ))
30+ signer2_email = pattern .sub ("" , request .form .get ("signer2_email" ))
31+ signer2_name = pattern .sub ("" , request .form .get ("signer2_name" ))
32+ cc_email = pattern .sub ("" , request .form .get ("cc_email" ))
33+ cc_name = pattern .sub ("" , request .form .get ("cc_name" ))
34+ envelope_args = {
35+ "signer1_email" : signer1_email ,
36+ "signer1_name" : signer1_name ,
37+ "signer2_email" : signer2_email ,
38+ "signer2_name" : signer2_name ,
39+ "cc_email" : cc_email ,
40+ "cc_name" : cc_name ,
41+ "status" : "sent" ,
42+ }
43+ args = {
44+ "account_id" : session ["ds_account_id" ],
45+ "base_path" : session ["ds_base_path" ],
46+ "access_token" : session ["ds_access_token" ],
47+ "envelope_args" : envelope_args
48+ }
49+ return args
50+
51+ # Step 3 start
52+ @classmethod
53+ def worker (cls , args , doc_docx_path , doc_pdf_path ):
54+ """
55+ 1. Create the envelope request object
56+ 2. Send the envelope
57+ """
58+ envelope_args = args ["envelope_args" ]
59+ # 1. Create the envelope request object
60+ envelope_definition = cls .make_envelope (envelope_args , doc_docx_path , doc_pdf_path )
61+
62+ # 2. call Envelopes::create API method
63+ # Exceptions will be caught by the calling function
64+ api_client = create_api_client (base_path = args ["base_path" ], access_token = args ["access_token" ])
65+
66+ envelope_api = EnvelopesApi (api_client )
67+ results = envelope_api .create_envelope (account_id = args ["account_id" ], envelope_definition = envelope_definition )
68+
69+ envelope_id = results .envelope_id
70+
71+ return {"envelope_id" : envelope_id }
72+ # Step 3 end
73+
74+ # Step 2 start
75+ @classmethod
76+ def make_envelope (cls , args , doc_docx_path , doc_pdf_path ):
77+ """
78+ Creates envelope
79+ args -- parameters for the envelope:
80+ signer_email, signer_name, signer_client_id
81+ returns an envelope definition
82+ """
83+ env = EnvelopeDefinition (
84+ email_subject = "Please sign this document set" ,
85+ )
86+
87+ doc1_b64 = base64 .b64encode (bytes (cls .create_document1 (args ), "utf-8" )).decode ("ascii" )
88+ # read files 2 and 3 from a local directory
89+ # The reads could raise an exception if the file is not available!
90+ with open (path .join (demo_docs_path , doc_docx_path ), "rb" ) as file :
91+ doc2_docx_bytes = file .read ()
92+ doc2_b64 = base64 .b64encode (doc2_docx_bytes ).decode ("ascii" )
93+ with open (path .join (demo_docs_path , doc_pdf_path ), "rb" ) as file :
94+ doc3_pdf_bytes = file .read ()
95+ doc3_b64 = base64 .b64encode (doc3_pdf_bytes ).decode ("ascii" )
96+
97+
98+ # Create the document models
99+ document1 = Document ( # create the DocuSign document object
100+ document_base64 = doc1_b64 ,
101+ name = "Order acknowledgement" , # can be different from actual file name
102+ file_extension = "html" , # many different document types are accepted
103+ document_id = "1" , # a label used to reference the doc
104+ )
105+ document2 = Document ( \
106+ document_base64 = doc2_b64 ,
107+ name = "Battle Plan" ,
108+ file_extension = "docx" ,
109+ document_id = "2"
110+ )
111+ document3 = Document (
112+ document_base64 = doc3_b64 ,
113+ name = "Lorem Ipsum" ,
114+ file_extension = "pdf" ,
115+ document_id = "3"
116+ )
117+
118+ # The order in the docs array determines the order in the envelope
119+ env .documents = [document1 , document2 , document3 ]
120+
121+ # Create the signer recipient model
122+ signer1 = Signer (
123+ # The signer1
124+ email = args ["signer1_email" ],
125+ name = args ["signer1_name" ],
126+ excluded_documents = ["2" ,"3" ], # Sets which documents are excluded for this signer
127+ recipient_id = "1" ,
128+ routing_order = "1" ,
129+ role_name = "Signer1"
130+ )
131+
132+ signer2 = Signer (
133+ # The signer2
134+ email = args ["signer2_email" ],
135+ name = args ["signer2_name" ],
136+ excluded_documents = ["1" ],
137+ recipient_id = "2" ,
138+ routing_order = "1" ,
139+ role_name = "Signer2"
140+ )
141+
142+ cc = CarbonCopy (
143+ email = args ["cc_email" ],
144+ name = args ["cc_name" ],
145+ recipient_id = "3" ,
146+ routing_order = "2"
147+ )
148+
149+ # Create signHere fields (also known as tabs) on the documents.
150+ sign_here1 = SignHere (
151+ document_id = "1" ,
152+ page_number = "1" ,
153+ name = "Signer1" ,
154+ x_position = "200" ,
155+ y_position = "200"
156+ )
157+ sign_here2 = SignHere (
158+ document_id = "2" ,
159+ page_number = "1" ,
160+ name = "Signer2" ,
161+ recipient_id = "2" ,
162+ x_position = "300" ,
163+ y_position = "200"
164+ )
165+
166+ sign_here3 = SignHere (
167+ document_id = "3" ,
168+ page_number = "1" ,
169+ name = "Signer2" ,
170+ recipient_id = "2" ,
171+ x_position = "300" ,
172+ y_position = "200"
173+ )
174+
175+ # Add the tabs model (including the sign_here tabs) to the signer
176+ # The Tabs object wants arrays of the different field/tab types
177+ signer1 .tabs = Tabs (
178+ sign_here_tabs = [sign_here1 , ],
179+ )
180+ signer2 .tabs = Tabs (sign_here_tabs = [sign_here2 , sign_here3 ])
181+
182+ # Add the recipients to the envelope object
183+ recipients = Recipients (signers = [signer1 , signer2 ], carbon_copies = [cc ])
184+ env .recipients = recipients
185+
186+ # Request that the envelope be sent by setting |status| to "sent".
187+ # To request that the envelope be created as a draft, set to "created"
188+ env .status = args ["status" ]
189+
190+ return env
191+
192+ @classmethod
193+ def create_document1 (cls , args ):
194+ """ Creates document 1 -- an html document"""
195+
196+ return f"""
197+ <!DOCTYPE html>
198+ <html>
199+ <head>
200+ <meta charset="UTF-8">
201+ </head>
202+ <body style="font-family:sans-serif;margin-left:2em;">
203+ <h1 style="font-family: "Trebuchet MS", Helvetica, sans-serif;
204+ color: darkblue;margin-bottom: 0;">World Wide Corp</h1>
205+ <h2 style="font-family: "Trebuchet MS", Helvetica, sans-serif;
206+ margin-top: 0px;margin-bottom: 3.5em;font-size: 1em;
207+ color: darkblue;">Order Processing Division</h2>
208+ <h4>Ordered by { args ["signer1_name" ]} </h4>
209+ <p style="margin-top:0em; margin-bottom:0em;">Email: { args ["signer1_email" ]} </p>
210+ <p style="margin-top:0em; margin-bottom:0em;">Copy to: { args ["cc_name" ]} , { args ["cc_email" ]} </p>
211+ <p style="margin-top:3em;">
212+ Candy bonbon pastry jujubes lollipop wafer biscuit biscuit. Topping brownie sesame snaps sweet roll pie.
213+ Croissant danish biscuit soufflé caramels jujubes jelly. Dragée danish caramels lemon drops dragée.
214+ Gummi bears cupcake biscuit tiramisu sugar plum pastry. Dragée gummies applicake pudding liquorice.
215+ Donut jujubes oat cake jelly-o.
216+ Dessert bear claw chocolate cake gummies lollipop sugar plum ice cream gummies cheesecake.
217+ </p>
218+ <!-- Note the anchor tag for the signature field is in white. -->
219+ <h3 style="margin-top:3em;">Agreed: <span style="color:white;">**signature_1**/</span></h3>
220+ </body>
221+ </html>
222+ """
0 commit comments