-
Notifications
You must be signed in to change notification settings - Fork 74
/
attach_pdf.py
149 lines (112 loc) · 4.81 KB
/
attach_pdf.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
"""
PDF on Submit. Creates a PDF when a document is submitted.
Copyright (C) 2019 Raffael Meyer <raffael@alyf.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import frappe
from frappe import _
from frappe import publish_progress
from frappe.core.doctype.file.file import create_new_folder
from frappe.utils.file_manager import save_file
from frappe.model.naming import _format_autoname
from frappe.utils.weasyprint import PrintFormatGenerator
def attach_pdf(doc, event=None):
settings = frappe.get_single("PDF on Submit Settings")
if enabled_doctypes := settings.get("enabled_for", {"document_type": doc.doctype}):
enabled_doctype = enabled_doctypes[0]
else:
return
auto_name = enabled_doctype.auto_name
print_format = enabled_doctype.print_format or doc.meta.default_print_format or "Standard"
letter_head = enabled_doctype.letter_head or None
fallback_language = frappe.db.get_single_value("System Settings", "language") or "en"
args = {
"doctype": doc.doctype,
"name": doc.name,
"title": doc.get_title(),
"lang": getattr(doc, "language", fallback_language),
"show_progress": not settings.create_pdf_in_background,
"auto_name": auto_name,
"print_format": print_format,
"letter_head": letter_head,
}
if settings.create_pdf_in_background:
enqueue(args)
else:
execute(**args)
def enqueue(args):
"""Add method `execute` with given args to the queue."""
frappe.enqueue(method=execute, queue='long',
timeout=30, is_async=True, **args)
def execute(doctype, name, title, lang=None, show_progress=True, auto_name=None, print_format=None, letter_head=None):
"""
Queue calls this method, when it's ready.
1. Create necessary folders
2. Get raw PDF data
3. Save PDF file and attach it to the document
"""
progress = frappe._dict(title=_("Creating PDF ..."), percent=0, doctype=doctype, docname=name)
if lang:
frappe.local.lang = lang
# unset lang and jenv to load new language
frappe.local.lang_full_dict = None
frappe.local.jenv = None
if show_progress:
publish_progress(**progress)
doctype_folder = create_folder(doctype, "Home")
title_folder = create_folder(title, doctype_folder)
if show_progress:
progress.percent = 33
publish_progress(**progress)
if frappe.db.get_value("Print Format", print_format, "print_format_builder_beta"):
doc = frappe.get_doc(doctype, name)
pdf_data = PrintFormatGenerator(print_format, doc, letter_head).render_pdf()
else:
pdf_data = get_pdf_data(doctype, name, print_format)
if show_progress:
progress.percent = 66
publish_progress(**progress)
save_and_attach(pdf_data, doctype, name, title_folder, auto_name)
if show_progress:
progress.percent = 100
publish_progress(**progress)
def create_folder(folder, parent):
"""Make sure the folder exists and return it's name."""
new_folder_name = "/".join([parent, folder])
if not frappe.db.exists("File", new_folder_name):
create_new_folder(folder, parent)
return new_folder_name
def get_pdf_data(doctype, name, print_format):
"""Document -> HTML -> PDF."""
html = frappe.get_print(doctype, name, print_format)
return frappe.utils.pdf.get_pdf(html)
def save_and_attach(content, to_doctype, to_name, folder, auto_name=None):
"""
Save content to disk and create a File document.
File document is linked to another document.
"""
if auto_name:
doc = frappe.get_doc(to_doctype, to_name)
# based on type of format used set_name_form_naming_option return result.
pdf_name = set_name_from_naming_options(auto_name, doc)
file_name = "{pdf_name}.pdf".format(pdf_name=pdf_name.replace("/", "-"))
else:
file_name = "{to_name}.pdf".format(to_name=to_name.replace("/", "-"))
save_file(file_name, content, to_doctype, to_name, folder=folder, is_private=1)
def set_name_from_naming_options(autoname, doc):
"""
Get a name based on the autoname field option
"""
_autoname = autoname.lower()
if _autoname.startswith("format:"):
return _format_autoname(autoname, doc)
return doc.name