
Security News
Deno 2.2 Improves Dependency Management and Expands Node.js Compatibility
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
A Python Document Management Framework for generating and sending (pdf, docx, etc) documents to customers
.. image:: https://badge.fury.io/py/doc-workflow.png :alt: PyPI :target: https://pypi.python.org/pypi/doc-workflow
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 with pip
:
::
$ pip install doc-workflow
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()
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 ... ======== ============ ========== ====== ========= ======
::
{
"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
}
},
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"
}
},
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"
}
},
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
}
},
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"
}
},
::
{
"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
}
},
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
}
},
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/..."
}
},
...
}
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"
}
}
]
}
This repository is created and maintained by Iulian Ciorăscu
_.
.. _Iulian Ciorăscu: https://github.com/iulica/ .. _gspread with service account: https://docs.gspread.org/en/latest/oauth2.html#service-account
FAQs
A Python Document Management Framework for generating and sending (pdf, docx, etc) documents to customers
We found that doc-workflow demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
Security News
React's CRA deprecation announcement sparked community criticism over framework recommendations, leading to quick updates acknowledging build tools like Vite as valid alternatives.
Security News
Ransomware payment rates hit an all-time low in 2024 as law enforcement crackdowns, stronger defenses, and shifting policies make attacks riskier and less profitable.