ERPNext 14:如何在保存报价单时自动附加指定打印格式PDF
ERPNext 14 报价单自动附加指定打印格式PDF方案
服务器端脚本实现(推荐)
直接利用ERPNext的文档事件钩子,在报价单保存/更新时自动生成指定打印格式的PDF并附加到附件栏,同时避免重复添加。
代码实现
在你的自定义应用中创建Python脚本(比如custom_quotation_pdf.py),或者通过自定义脚本(服务器端)添加以下代码:
import frappe from frappe.utils.file_manager import save_file def attach_custom_pdfs_to_quotation(doc, method): # 定义需要生成的打印格式与对应附件文件名 print_formats = [ {"name": "Scope of Work", "filename": "Scope of Work.pdf"}, {"name": "Scope of Work Arabic", "filename": "Scope of Work Arabic.pdf"} ] for pf in print_formats: # 检查当前文档是否已存在该附件,避免重复添加 existing_attachment = frappe.db.exists( "File", { "attached_to_doctype": "Quotation", "attached_to_name": doc.name, "file_name": pf["filename"] } ) if not existing_attachment: # 生成指定打印格式的PDF内容 pdf_content = frappe.get_print( doc.doctype, doc.name, print_format=pf["name"], as_pdf=True ) # 将PDF保存为附件并关联到当前报价单 save_file( pf["filename"], pdf_content, doc.doctype, doc.name, is_private=0 # 设置为0表示公开附件,侧边栏可见 ) # 注册事件钩子:报价单更新/保存时触发 frappe.get_doc("DocType", "Quotation").on_update.append("your_custom_app.custom_quotation_pdf.attach_custom_pdfs_to_quotation") frappe.db.commit()
配置说明
- 替换
your_custom_app为你的自定义应用名称;如果用自定义脚本,可直接去掉最后一行的应用路径,改为frappe.get_doc("DocType", "Quotation").on_update.append("attach_custom_pdfs_to_quotation") - 确保
print_formats列表中的打印格式名称与你创建的完全一致,大小写敏感 is_private=0确保附件在左侧边栏的“附件”中可见,若设为1则仅内部可见
替代方案:自定义按钮触发
如果不想每次保存都自动生成,也可以添加自定义按钮手动触发:
- 在报价单的自定义字段中添加一个按钮类型字段,比如
btn_generate_attach_pdfs,标签设为“生成并附加PDF” - 添加客户端脚本:
frappe.ui.form.on('Quotation', { btn_generate_attach_pdfs: function(frm) { frappe.call({ method: "your_custom_app.custom_quotation_pdf.attach_custom_pdfs_to_quotation", args: {doc: frm.doc}, callback: function(r) { if(r.message) { frm.reload_doc(); // 刷新页面显示新附件 frappe.msgprint("指定PDF已成功附加到报价单"); } } }); } });
- 对应的服务器端函数调整为接收
doc参数:
def attach_custom_pdfs_to_quotation(doc): # 内容同之前的函数逻辑,去掉method参数 print_formats = [ {"name": "Scope of Work", "filename": "Scope of Work.pdf"}, {"name": "Scope of Work Arabic", "filename": "Scope of Work Arabic.pdf"} ] for pf in print_formats: existing_attachment = frappe.db.exists( "File", { "attached_to_doctype": "Quotation", "attached_to_name": doc.name, "file_name": pf["filename"] } ) if not existing_attachment: pdf_content = frappe.get_print( doc.doctype, doc.name, print_format=pf["name"], as_pdf=True ) save_file( pf["filename"], pdf_content, doc.doctype, doc.name, is_private=0 )
注意事项
- 测试前请备份数据,避免重复生成大量附件
- 确保执行脚本的用户有生成PDF和添加附件的权限
- 若生成PDF时报错,检查打印格式的HTML/CSS是否存在语法错误,或ERPNext的PDF生成服务(wkhtmltopdf)是否正常
内容的提问来源于stack exchange,提问作者Khayam Khan
相关产品推荐
相关产品推荐

