1- from docusign_esign import EnvelopesApi , ReturnUrlRequest
1+ import base64
2+ from os import path
3+
4+ from docusign_esign import EnvelopesApi , ReturnUrlRequest , EnvelopesApi , EnvelopeDefinition , \
5+ Document , Signer , CarbonCopy , SignHere , Tabs , Recipients
26from flask import url_for , session , request
37
4- from .eg002_signing_via_email import Eg002SigningViaEmailController
58from ...consts import pattern , demo_docs_path
69from ...docusign import create_api_client
710
@@ -24,7 +27,7 @@ def get_args():
2427 "signer_name" : signer_name ,
2528 "cc_email" : cc_email ,
2629 "cc_name" : cc_name ,
27- "status" : "sent " ,
30+ "status" : "created " ,
2831 }
2932 args = {
3033 "starting_view" : starting_view ,
@@ -36,36 +39,196 @@ def get_args():
3639 }
3740 return args
3841
39- @staticmethod
40- def worker (args ,doc_docx_path ,doc_pdf_path ):
42+ @classmethod
43+ def worker (cls , args , doc_docx_path , doc_pdf_path ):
4144 """
4245 This function does the work of creating the envelope in
4346 draft mode and returning a URL for the sender"s view
4447 """
4548
4649 # Step 2. Create the envelope with "created" (draft) status
47- args ["envelope_args" ]["status" ] = "created"
48- # Using worker from example 002
49- results = Eg002SigningViaEmailController .worker (args , doc_docx_path , doc_pdf_path )
50- envelope_id = results ["envelope_id" ]
50+ envelope = cls .create_envelope (args , doc_docx_path , doc_pdf_path )
51+ envelope_id = envelope .envelope_id
5152
5253 # Step 3. Create the sender view
54+ sender_view_url = cls .create_sender_view (args , envelope_id )
55+
56+ return {"envelope_id" : envelope_id , "redirect_url" : sender_view_url }
57+
58+ @classmethod
59+ #ds-snippet-start:eSign11Step3
60+ def create_sender_view (cls , args , envelope_id ):
5361 view_request = ReturnUrlRequest (return_url = args ["ds_return_url" ])
5462 # Exceptions will be caught by the calling function
55- #ds-snippet-start:eSign11Step3
5663 api_client = create_api_client (base_path = args ["base_path" ], access_token = args ["access_token" ])
5764
5865 envelope_api = EnvelopesApi (api_client )
59- results = envelope_api .create_sender_view (
66+ sender_view = envelope_api .create_sender_view (
6067 account_id = args ["account_id" ],
6168 envelope_id = envelope_id ,
6269 return_url_request = view_request
6370 )
6471
6572 # Switch to Recipient and Documents view if requested by the user
66- url = results .url
73+ url = sender_view .url
6774 if args ["starting_view" ] == "recipient" :
6875 url = url .replace ("send=1" , "send=0" )
69- #ds-snippet-end:eSign13Step3
7076
71- return {"envelope_id" : envelope_id , "redirect_url" : url }
77+ return url
78+ #ds-snippet-end:eSign11Step3
79+
80+ @classmethod
81+ #ds-snippet-start:eSign11Step2
82+ def create_envelope (cls , args , doc_docx_path , doc_pdf_path ):
83+ envelope_args = args ["envelope_args" ]
84+ # Create the envelope request object
85+ envelope_definition = cls .make_envelope (envelope_args , doc_docx_path , doc_pdf_path )
86+ api_client = create_api_client (base_path = args ["base_path" ], access_token = args ["access_token" ])
87+ # Call Envelopes::create API method
88+ # Exceptions will be caught by the calling function
89+ envelopes_api = EnvelopesApi (api_client )
90+ return envelopes_api .create_envelope (account_id = args ["account_id" ], envelope_definition = envelope_definition )
91+
92+ @classmethod
93+ def make_envelope (cls , args , doc_docx_path , doc_pdf_path ):
94+ """
95+ Creates envelope
96+ Document 1: An HTML document.
97+ Document 2: A Word .docx document.
98+ Document 3: A PDF document.
99+ DocuSign will convert all of the documents to the PDF format.
100+ The recipients" field tags are placed using <b>anchor</b> strings.
101+ """
102+
103+ # document 1 (html) has sign here anchor tag **signature_1**
104+ # document 2 (docx) has sign here anchor tag /sn1/
105+ # document 3 (pdf) has sign here anchor tag /sn1/
106+ #
107+ # The envelope has two recipients.
108+ # recipient 1 - signer
109+ # recipient 2 - cc
110+ # The envelope will be sent first to the signer.
111+ # After it is signed, a copy is sent to the cc person.
112+
113+ # create the envelope definition
114+ env = EnvelopeDefinition (
115+ email_subject = "Please sign this document set"
116+ )
117+ doc1_b64 = base64 .b64encode (bytes (cls .create_document1 (args ), "utf-8" )).decode ("ascii" )
118+ # read files 2 and 3 from a local directory
119+ # The reads could raise an exception if the file is not available!
120+ with open (path .join (demo_docs_path , doc_docx_path ), "rb" ) as file :
121+ doc2_docx_bytes = file .read ()
122+ doc2_b64 = base64 .b64encode (doc2_docx_bytes ).decode ("ascii" )
123+ with open (path .join (demo_docs_path , doc_pdf_path ), "rb" ) as file :
124+ doc3_pdf_bytes = file .read ()
125+ doc3_b64 = base64 .b64encode (doc3_pdf_bytes ).decode ("ascii" )
126+
127+ # Create the document models
128+ document1 = Document ( # create the DocuSign document object
129+ document_base64 = doc1_b64 ,
130+ name = "Order acknowledgement" , # can be different from actual file name
131+ file_extension = "html" , # many different document types are accepted
132+ document_id = "1" # a label used to reference the doc
133+ )
134+ document2 = Document ( # create the DocuSign document object
135+ document_base64 = doc2_b64 ,
136+ name = "Battle Plan" , # can be different from actual file name
137+ file_extension = "docx" , # many different document types are accepted
138+ document_id = "2" # a label used to reference the doc
139+ )
140+ document3 = Document ( # create the DocuSign document object
141+ document_base64 = doc3_b64 ,
142+ name = "Lorem Ipsum" , # can be different from actual file name
143+ file_extension = "pdf" , # many different document types are accepted
144+ document_id = "3" # a label used to reference the doc
145+ )
146+ # The order in the docs array determines the order in the envelope
147+ env .documents = [document1 , document2 , document3 ]
148+
149+ # Create the signer recipient model
150+ signer1 = Signer (
151+ email = args ["signer_email" ],
152+ name = args ["signer_name" ],
153+ recipient_id = "1" ,
154+ routing_order = "1"
155+ )
156+ # routingOrder (lower means earlier) determines the order of deliveries
157+ # to the recipients. Parallel routing order is supported by using the
158+ # same integer as the order for two or more recipients.
159+
160+ # create a cc recipient to receive a copy of the documents
161+ cc1 = CarbonCopy (
162+ email = args ["cc_email" ],
163+ name = args ["cc_name" ],
164+ recipient_id = "2" ,
165+ routing_order = "2"
166+ )
167+
168+ # Create signHere fields (also known as tabs) on the documents,
169+ # We"re using anchor (autoPlace) positioning
170+ #
171+ # The DocuSign platform searches throughout your envelope"s
172+ # documents for matching anchor strings. So the
173+ # signHere2 tab will be used in both document 2 and 3 since they
174+ # use the same anchor string for their "signer 1" tabs.
175+ sign_here1 = SignHere (
176+ anchor_string = "**signature_1**" ,
177+ anchor_units = "pixels" ,
178+ anchor_y_offset = "10" ,
179+ anchor_x_offset = "20"
180+ )
181+
182+ sign_here2 = SignHere (
183+ anchor_string = "/sn1/" ,
184+ anchor_units = "pixels" ,
185+ anchor_y_offset = "10" ,
186+ anchor_x_offset = "20"
187+ )
188+
189+ # Add the tabs model (including the sign_here tabs) to the signer
190+ # The Tabs object wants arrays of the different field/tab types
191+ signer1 .tabs = Tabs (sign_here_tabs = [sign_here1 , sign_here2 ])
192+
193+ # Add the recipients to the envelope object
194+ recipients = Recipients (signers = [signer1 ], carbon_copies = [cc1 ])
195+ env .recipients = recipients
196+
197+ # Request that the envelope be sent by setting |status| to "sent".
198+ # To request that the envelope be created as a draft, set to "created"
199+ env .status = args ["status" ]
200+
201+ return env
202+
203+ @classmethod
204+ def create_document1 (cls , args ):
205+ """ Creates document 1 -- an html document"""
206+
207+ return f"""
208+ <!DOCTYPE html>
209+ <html>
210+ <head>
211+ <meta charset="UTF-8">
212+ </head>
213+ <body style="font-family:sans-serif;margin-left:2em;">
214+ <h1 style="font-family: "Trebuchet MS", Helvetica, sans-serif;
215+ color: darkblue;margin-bottom: 0;">World Wide Corp</h1>
216+ <h2 style="font-family: "Trebuchet MS", Helvetica, sans-serif;
217+ margin-top: 0px;margin-bottom: 3.5em;font-size: 1em;
218+ color: darkblue;">Order Processing Division</h2>
219+ <h4>Ordered by { args ["signer_name" ]} </h4>
220+ <p style="margin-top:0em; margin-bottom:0em;">Email: { args ["signer_email" ]} </p>
221+ <p style="margin-top:0em; margin-bottom:0em;">Copy to: { args ["cc_name" ]} , { args ["cc_email" ]} </p>
222+ <p style="margin-top:3em;">
223+ Candy bonbon pastry jujubes lollipop wafer biscuit biscuit. Topping brownie sesame snaps sweet roll pie.
224+ Croissant danish biscuit soufflé caramels jujubes jelly. Dragée danish caramels lemon drops dragée.
225+ Gummi bears cupcake biscuit tiramisu sugar plum pastry. Dragée gummies applicake pudding liquorice.
226+ Donut jujubes oat cake jelly-o.
227+ Dessert bear claw chocolate cake gummies lollipop sugar plum ice cream gummies cheesecake.
228+ </p>
229+ <!-- Note the anchor tag for the signature field is in white. -->
230+ <h3 style="margin-top:3em;">Agreed: <span style="color:white;">**signature_1**/</span></h3>
231+ </body>
232+ </html>
233+ """
234+ #ds-snippet-end:eSign11Step2
0 commit comments