Generate a Custom Business Contract in Just 10 Seconds with This Python Script

Caden Chen
The Pythoneers
Published in
6 min readMay 14, 2024

Are you a business owner or freelancer who frequently needs to draft business contracts? If you find editing them tedious and are looking to automate the process, this article is for you.

I will show you how to create a short 50 lines Python script that collects custom values from you and generates a PDF contract, ready for signing.

As you can see, when this script is run, it prompts you for the variables of the contract. These include the

  • contract file name
  • parties’ names
  • service cost
  • days for completion
  • today’s date, etc.

After gathering all the necessary details, the script will save and open the contract in PDF format. All these can be customised to your liking once you know how the script works.

Prerequisites

Before we get started, ensure you have the following:

  • A Python Environment set up.
  • PyFPDF library installed pip install fpdf
Files used in this article

Step 1: Create your contract template

To begin, you’ll need to prepare a default contract template. This template should be a text file that includes placeholders for variable information specific to each contract. Use curly braces {} to denote these placeholders and label them with descriptive variable names.

For example, your contract template might look something like this:
MediumContract.txt

MEDIUM CONTRACT

SERVICE AGREEMENT

This Services Agreement shall become effective on {Execution_Date} (the "Execution Date") and is subject to the terms and conditions stated below between {Service_Provider_Name} (the "Service Provider") and {Client_Name} (the "Client"), collectively referred to as the "Parties".

THEREFORE, the Parties hereby agree to enter into this Agreement according to the following terms and conditions contained herein.


1. SERVICE PAYMENT TERMS.

a. The Service Provider shall charge the Client a flat fee of SGD {Service_Fee} for the Services (the "Services Fee").

b. An upfront payment of SGD {Upfront_Fee} is payable by the Client upon signing of this Agreement. This upfront payment is non-refundable.

c. The remaining amount of SGD {Development_Fee} will be billed to the Client when the Client receives the website design and decides to proceed with the development of the website. Invoices submitted by the Service Provider to the Client are due within seven (7) days of receipt. This payment is non-refundable.

d. The aforementioned Service Fee covers the Service Provider`s work for a period of {Estimated_Days_for_Completion} days following the commencement
of the website development. Should the scope of work extend beyond this {Estimated_Days_for_Completion} days period due to additional requirements or changes requested by the Client, the Service Provider reserves the right to charge an additional hourly rate of ninety Singapore Dollars (SGD 90) per hour. The Client will be informed of any such additional charges, which must be paid in advance before the continuation of work.


Client: ________________________

Date: {Execution_Date}


Service Provider: ________________________

Date: {Execution_Date}

In this template, placeholders such as {Client_Name}, {Service_Provider_Name}, {Execution_Date}, and others should be replaced with actual data during the contract generation process.

Step 2: Code the Python Script

MediumContractGenerator.py

import os
from fpdf import FPDF
from datetime import datetime, timedelta

def display_header():
header = """




/$$ /$$ /$$$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$ /$$ /$$
| $$$ /$$$| $$_____/| $$__ $$|_ $$_/| $$ | $$| $$$ /$$$
| $$$$ /$$$$| $$ | $$ \ $$ | $$ | $$ | $$| $$$$ /$$$$
| $$ $$/$$ $$| $$$$$ | $$ | $$ | $$ | $$ | $$| $$ $$/$$ $$
| $$ $$$| $$| $$__/ | $$ | $$ | $$ | $$ | $$| $$ $$$| $$
| $$\ $ | $$| $$ | $$ | $$ | $$ | $$ | $$| $$\ $ | $$
| $$ \/ | $$| $$$$$$$$| $$$$$$$/ /$$$$$$| $$$$$$/| $$ \/ | $$
|__/ |__/|________/|_______/ |______/ \______/ |__/ |__/
/$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$$
/$$__ $$ /$$__ $$| $$$ | $$|__ $$__/| $$__ $$ /$$__ $$ /$$__ $$|__ $$__/
| $$ \__/| $$ \ $$| $$$$| $$ | $$ | $$ \ $$| $$ \ $$| $$ \__/ | $$
| $$ | $$ | $$| $$ $$ $$ | $$ | $$$$$$$/| $$$$$$$$| $$ | $$
| $$ | $$ | $$| $$ $$$$ | $$ | $$__ $$| $$__ $$| $$ | $$
| $$ $$| $$ | $$| $$\ $$$ | $$ | $$ \ $$| $$ | $$| $$ $$ | $$
| $$$$$$/| $$$$$$/| $$ \ $$ | $$ | $$ | $$| $$ | $$| $$$$$$/ | $$
\______/ \______/ |__/ \__/ |__/ |__/ |__/|__/ |__/ \______/ |__/
/$$$$$$ /$$$$$$$$ /$$ /$$ /$$$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$$$ /$$$$$$ /$$$$$$$
/$$__ $$| $$_____/| $$$ | $$| $$_____/| $$__ $$ /$$__ $$|__ $$__//$$__ $$| $$__ $$
| $$ \__/| $$ | $$$$| $$| $$ | $$ \ $$| $$ \ $$ | $$ | $$ \ $$| $$ \ $$
| $$ /$$$$| $$$$$ | $$ $$ $$| $$$$$ | $$$$$$$/| $$$$$$$$ | $$ | $$ | $$| $$$$$$$/
| $$|_ $$| $$__/ | $$ $$$$| $$__/ | $$__ $$| $$__ $$ | $$ | $$ | $$| $$__ $$
| $$ \ $$| $$ | $$\ $$$| $$ | $$ \ $$| $$ | $$ | $$ | $$ | $$| $$ \ $$
| $$$$$$/| $$$$$$$$| $$ \ $$| $$$$$$$$| $$ | $$| $$ | $$ | $$ | $$$$$$/| $$ | $$
\______/ |________/|__/ \__/|________/|__/ |__/|__/ |__/ |__/ \______/ |__/ |__/







"""
print(header)

def update_contract_content(service_provider_name, client_name, service_fee, estimated_days, contract_name):
# Get today's date
execution_date = datetime.now().strftime("%Y-%m-%d")

# Calculate deployment end date
deployment_end_date = datetime.strptime(execution_date, "%Y-%m-%d") + timedelta(days=5*365)

with open("/Users/chenqixuan1/Documents/Programming/Python/PROJECTS/Work/MediumContract.txt", "r", encoding="utf-8") as file:
contract_text = file.read()

# Replace placeholders with user input and calculated dates
updated_contract_text = contract_text.replace("{Execution_Date}", execution_date)
updated_contract_text = updated_contract_text.replace("{Post_Deployment_End_Date}", deployment_end_date.strftime("%Y-%m-%d"))
updated_contract_text = updated_contract_text.replace("{Service_Provider_Name}", service_provider_name)
updated_contract_text = updated_contract_text.replace("{Client_Name}", client_name)
updated_contract_text = updated_contract_text.replace("{Service_Fee}", "{:.2f}".format(service_fee))
updated_contract_text = updated_contract_text.replace("{Upfront_Fee}", "{:.2f}".format(upfront_fee))
updated_contract_text = updated_contract_text.replace("{Development_Fee}", "{:.2f}".format(development_fee))
updated_contract_text = updated_contract_text.replace("{Estimated_Days_for_Completion}", str(estimated_days))

# Create instance of FPDF class
pdf = FPDF()

# Add a page
pdf.add_page()

# Set font for the text
pdf.set_font("Arial", size=11)

# Add the updated contract text to the PDF
pdf.multi_cell(0, 6, updated_contract_text.encode('utf-8').decode('latin1')) # Encode as UTF-8 and decode as latin1

# Save the PDF to a file
pdf_output_path = f"/Users/chenqixuan1/Downloads/{contract_name}.pdf"
pdf.output(pdf_output_path)

print(f"Contract updated successfully and saved as {pdf_output_path}!")

# Automatically open the generated PDF file
os.system(f"open {pdf_output_path}")

if __name__ == "__main__":

display_header()

# Ask user for input
contract_name = input("Enter the Contract Name / File Name (No Spacing): ")
service_provider_name = input("Enter the Service Provider Name: ")
client_name = input("Enter the Client Name: ")
service_fee = float(input("Enter the Service Fee (SGD): "))
upfront_fee = service_fee * 0.5
development_fee = service_fee * 0.5
estimated_days = int(input("Enter the Estimated Days for Completion: "))

# Call the function to update and generate the contract
update_contract_content(service_provider_name, client_name, service_fee, estimated_days, contract_name)

Explanation:

Importing Necessary Libraries:

  • os: Used to interact with the operating system, such as opening files.
  • FPDF: A Python library for creating PDF documents.
  • datetime, timedelta: These are used to handle dates and times, specifically for setting contract dates and durations.

Display Header Function (display_header):

  • This function prints a stylized ASCII art header in the console when the script runs. It’s purely aesthetic and serves to give a visual cue of the script’s purpose when it starts.
  • You can generate one here http://patorjk.com/software/taag/

Update Contract Content Function (update_contract_content):

  • Inputs: This function takes multiple parameters, including names of the parties involved, service fee, duration of the project, and the contract name.
  • Process: The current date is fetched and formatted. A deployment end date is calculated by adding five years to today’s date, using timedelta. The script reads a template contract from a specified file, replacing placeholders in the contract template with the actual data provided by the user. The contract is then converted into a PDF format using the FPDF library. The text is added to the PDF with appropriate encoding to handle special characters.
  • Output: The finalised contract is saved to a PDF file in a specified directory and automatically opened for review using a system call that invokes the default PDF viewer.

And there you have it — a fully functional contract generator built with Python!

This automation tool is particularly useful for freelancers, service providers, and any business entities that require frequent and rapid generation of customised contracts, minimising manual errors and saving time. The underlying concept revolves around editing PDFs with Python, which can be applied to various other applications such as:

  • Generating Invoices and Receipts
  • Educational Materials and Certificates
  • Automating Reports

Check out my Github for the full code.

--

--

Caden Chen
The Pythoneers

A collection of React, Tailwind and Framer Motion features. Sometimes I write about Figma and Jitter too.