Skip to main content

A Python Document Management Framework for generating and sending (pdf, docx, etc) documents to customers

Project description

PyPI

Creates, merges, splits, edits documents(mainly docx/pdf) as well as sending them by email. Originally created for QR bills integration but is generic and can be used for much more.

Installation

Installation with pip:

$ pip install doc-workflow

Usage

From the command line:

$ docwf <path_to_json_config_file>

From Python:

from docwf import DocWorkflow

config_obj = {
    "globals": {
        "data": {
            "workbook": "source.xlsx",
            "sheet": "mailmergesheet",
        },
        "constants": {
            "language": "fr"
        }
    },
    "tasks": [
        {
            "active": 1, # you can activate/deactivate tasks
            "name": "create bills", # name for debug purpose
            "locals": {
                "data" : {
                    "sheet": "overridesheetfortask"
                },
                "key" : "value", # overrides global arguments for the task
            },
            "task": {
                "type": "myplugin", # or builtin plugins (see below)
                "task_dependent_argument": "value{param}",
            }
        },
    ]
}
my_plugins = {
    "myplugin": MyPluginClass
}
DocWorkflow(config_obj, plugins=my_plugins).gen()

Typical workflow tasks

Assume the data is in the source.xlsx in the sheet named bills

clientnr

email

send_email

total

reference

etc

1

c1@gmail.com

yes

1032

ref2022c1

2

c2@gmail.com

yes

1232

ref2022c2

Create bills from Word template

{
    "active": 1, # you can activate/deactivate tasks
    "name": "create bills", # name for debug purpose
    "task": {
        "type": "mailmerge",
        "input_docx": "templates/template_bill.docx",
        "output_docx": "bills/bill_{year}.docx" # output depends on the column year, it should be constant throughout all rows
    }
},

Create pdf from the generated docx

It uses the Word Application (Mac/Windows). If the docx template has dynamic fields (IF, etc), the generated docx will ask permission to update all fields before saving it as pdf.

{
    "name": "save pdf from docx (uses Word)",
    "task": {
        "type": "makepdf",
        "input_docx": "bills/bill_{year}.docx",
        "output_pdf": "bills/bill_{year}.pdf"
    }
},

Fills in QR codes

for the bills by adding a page to each bill or by merging the QR bill into one of the pages.

{
    "name": "create qr bills",
    "locals": {
        "creditor": {
            "iban": "CH....",
            "name": "The Good Company",
            "pcode": "xyzt",
            "city": "Bern",
            "street": "Dorfstrasse 1"
        },
        "task_params": {
            "extra_infos": "reference", # fixed keys for bill reason ...
            "amount": "total"   # and the amount. With task_params you can create data entries out of existing columns
        }
    },
    "task": {
        "type": "qr",
        "merge_type": "merge", # or "append"
        "input_filename": "bills/bill_{year}.pdf",
        "delete_input": true, # delete the input filename after creating the output
        "pages": 2, # the number of pages per each bill
        "merge_pos": 2, # or "insert_pos" if "append"
        "output_filename": "bills/bill_{year}_with_qr.pdf"
    }
},

Split the bills into separate pdf files.

From one input to multiple outputs

{
    "name": "split bills",
    "task": {
        "type": "split_pdf",
        "input_filename": "bills/bill_{year}_with_qr.pdf",
        "pages": 2,
        "makedir": "bills/bills_{year}", # if the output directory doesn't exist, create it
        "output_filename": "bills/bills_{year}/bill_{year}_{clientnr}.pdf" # output filename using unique name for each customer
    }
},

Unify bills that are to be printed

This shows how to filter rows. The same split_pdf plugin is used, from multiple inputs to one output.

{
    "name": "unify bills for print",
    "filter": {"column": "send_email", "value": "no"},
    "task": {
        "type": "split_pdf",
        "input_filename": "bills/bills_{year}/bill_{year}_{clientnr}.pdf",
        "delete_input": true,
        "pages": 2,
        "output_filename": "bills/bills_{year}_paper.pdf"
    }
},

Send the bills by email

{
    "name": "send emails",
    "locals": {
        "sender": {
            "email": "info@domain.com",
            "name": "Info",
            "server": "smtp.gmail.com:587",
            "username": "info@domain.com",
            "password": "strongpassword",
            "bcc": "bills@domain.com",
            "headers": {
                "Reply-To": "contability@domain.com"
            }
        },
    },
    "filter": {"column": "send_email", "value": "yes"},
    "task": {
        "type": "email",
        "recipient": "email", # the key/column name for the customer email
        "subject" : "Bill for year {year}", # can contain dynamic parts
        "body_template_file" : "templates/email_template.txt", # text template for the email body
        "attachments" : [ "bills/bills_{year}/bill_{year}_{clientnr}.pdf" ] # list of attachments
    }
},

Watermark PDF files

Mark reminder bills

{
    "name": "save reminder",
    "filter": {"column": "reminder", "value": "yes"},
    "task": {
        "type": "watermark",
        "makedir": "bills/bills_{key_year}/reminders/",
        "watermark": "REMINDER",
        "input_filename": "bills/bills_{year}/bill_{year}_{clientnr}.pdf",
        "pages": 2,
        "output_filename": "bills/bills_{year}/reminders/bill_{year}_{clientnr}_reminder.pdf"
    }
},

Send reminder bills

{
    "name": "send reminder emails",
    "locals": {
        "sender": {
            ...
        },
    },
    "filter": [
        {"column": "send_email", "value": "yes"},
        {"column": "reminder", "value": "yes"}
    ],
    "task": {
        "type": "email",
        "recipient": "email", # the key/column name for the customer email
        "subject" : "Bill for year {year} (reminder)", # can contain dynamic parts
        "body_template_file" : "templates/reminder_email_template.txt", # text template for the email body
        "attachments" : [ "bills/bills_{year}/reminders/bill_{year}_{clientnr}_reminder.pdf" ] # list of attachments
    }
},

Use Google Spreadsheets instead of Excel

To support google spreadsheets you need a service account and credentials as JSON. Follow the tutorial gspread with service account.

Change the “workbook” value

"globals": {
    "data": {
        "workbook": "https://docs.google.com/spreadsheets/d/1u...",
        "sheet": "mailmergesheet",
        "credentials": {
            "type": "service_account",
            "project_id": "...",
            "private_key_id": "...",
            "private_key": "-----BEGIN PRIVATE KEY....\n-----END PRIVATE KEY-----\n",
            "client_email": "project@project-123.iam.gserviceaccount.com",
            "client_id": "...",
            "auth_uri": "https://accounts.google.com/o/oauth2/auth",
            "token_uri": "https://oauth2.googleapis.com/token",
            "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
            "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/..."
        }
    },
    ...
}

Export Google Spreadsheets in a PDF file

Only works with gspread type data

{
    "#import": ["inc/inc_workbook_gspread.json"]
    "name": "export sheets as pdf",
    "globals": {
        "printsheets_defaults" : {
            "gridlines": true,
            "printnotes": false
        }
    },
    "tasks": [
        {
            "active": 1,
            "name": "bill documents",
            "task": {
                "makedir": "bills/web",
                "type": "printsheets",
                "printsheets": [
                    {
                        "gid": "1571231333"
                    },
                    {
                        "gid": "291382312357"
                    },
                    {
                        "gid": "3712318114",
                        "portrait": false,
                        "printnotes": true
                    }
                ],
                "output_filename": "bills/web/heizung_unterlagen_{key_year}.pdf"
            }
        }
    ]
}

Todo / Wish List

  • Create unit tests

  • Develop the command line to be able to run simple tasks directly

  • Create more advanced filters

  • Auto-magically create directories (remove the makedir argument)

Contributing

  • Fork the repository on GitHub and start hacking

  • Send a pull request with your changes

Credits

This repository is created and maintained by Iulian Ciorăscu.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

doc-workflow-0.1.1a3.tar.gz (15.5 kB view details)

Uploaded Source

Built Distribution

doc_workflow-0.1.1a3-py3-none-any.whl (20.0 kB view details)

Uploaded Python 3

File details

Details for the file doc-workflow-0.1.1a3.tar.gz.

File metadata

  • Download URL: doc-workflow-0.1.1a3.tar.gz
  • Upload date:
  • Size: 15.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.11.1

File hashes

Hashes for doc-workflow-0.1.1a3.tar.gz
Algorithm Hash digest
SHA256 936404f32df15f6a27d4628114453929d93bb28b9ad4df06ce625a580e6758f7
MD5 3d01528b9dba023e7e1987b2ef42d576
BLAKE2b-256 02dcedf749f885475026317b39f2184ed1b7ff5e1a0dd848ed1c503779900abb

See more details on using hashes here.

File details

Details for the file doc_workflow-0.1.1a3-py3-none-any.whl.

File metadata

File hashes

Hashes for doc_workflow-0.1.1a3-py3-none-any.whl
Algorithm Hash digest
SHA256 79e09a948908a3572f3c08514a8ebcfd8debed1d90db2a0f5c1bdc20d0ca867f
MD5 c0f7a42ab46d73de1fec1e1fb87e4c64
BLAKE2b-256 c02d3b8c991d60c9ff775eb030d004748ad0b5b645f005d840469bc99073b81f

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page