generate zugferd-pdf
This commit is contained in:
parent
26388d3816
commit
7f433d9b80
5 changed files with 171 additions and 29 deletions
16
locale/de.po
16
locale/de.po
|
@ -3,6 +3,22 @@ msgid ""
|
||||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||||
|
|
||||||
|
|
||||||
|
##############
|
||||||
|
# ir.message #
|
||||||
|
##############
|
||||||
|
msgctxt "model:ir.message,text:msg_invoice_must_posted"
|
||||||
|
msgid "Invoice '%(invname)s' must be posted."
|
||||||
|
msgstr "Rechnung '%(invname)s' muß festgeschrieben sein."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,text:msg_no_report_found"
|
||||||
|
msgid "No report found for invoices in PDF format."
|
||||||
|
msgstr "Kein Report für Rechnungen im PDF-Format gefunden."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,text:msg_invalid_cachecontent"
|
||||||
|
msgid "No PDF has yet been generated for the invoice '%(invoice_name)s' or the saved document has an incorrect format."
|
||||||
|
msgstr "Für die Rechnung '%(invoice_name)s' wurde noch keine PDF erzeugt oder das gespeicherte Dokument hat ein falsches Format."
|
||||||
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# ir.action #
|
# ir.action #
|
||||||
#############
|
#############
|
||||||
|
|
12
locale/en.po
12
locale/en.po
|
@ -2,6 +2,18 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,text:msg_invoice_must_posted"
|
||||||
|
msgid "Invoice '%(invname)s' must be posted."
|
||||||
|
msgstr "Invoice '%(invname)s' must be posted."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,text:msg_no_report_found"
|
||||||
|
msgid "No report found for invoices in PDF format."
|
||||||
|
msgstr "No report found for invoices in PDF format."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,text:msg_invalid_cachecontent"
|
||||||
|
msgid "No PDF has yet been generated for the invoice '%(invoice_name)s' or the saved document has an incorrect format."
|
||||||
|
msgstr "No PDF has yet been generated for the invoice '%(invoice_name)s' or the saved document has an incorrect format."
|
||||||
|
|
||||||
msgctxt "model:ir.action,name:act_wizard_report"
|
msgctxt "model:ir.action,name:act_wizard_report"
|
||||||
msgid "eDocument Export"
|
msgid "eDocument Export"
|
||||||
msgstr "eDocument Export"
|
msgstr "eDocument Export"
|
||||||
|
|
|
@ -8,6 +8,12 @@
|
||||||
<record model="ir.message" id="msg_invoice_must_posted">
|
<record model="ir.message" id="msg_invoice_must_posted">
|
||||||
<field name="text">Invoice '%(invname)s' must be posted.</field>
|
<field name="text">Invoice '%(invname)s' must be posted.</field>
|
||||||
</record>
|
</record>
|
||||||
|
<record model="ir.message" id="msg_no_report_found">
|
||||||
|
<field name="text">No report found for invoices in PDF format.</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_invalid_cachecontent">
|
||||||
|
<field name="text">No PDF has yet been generated for the invoice '%(invoice_name)s' or the saved document has an incorrect format.</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</tryton>
|
</tryton>
|
||||||
|
|
|
@ -78,14 +78,48 @@ class RunXRechnungReport(Wizard):
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
Invoice = pool.get('account.invoice')
|
Invoice = pool.get('account.invoice')
|
||||||
WizRepStart = pool.get('account_invoice_xrechnung.runrep.start')
|
WizRepStart = pool.get('account_invoice_xrechnung.runrep.start')
|
||||||
|
Configuration = pool.get('account.configuration')
|
||||||
|
|
||||||
|
cfg1 = Configuration.get_singleton()
|
||||||
invoice = Invoice.browse([context.get('active_id', -1)])
|
invoice = Invoice.browse([context.get('active_id', -1)])
|
||||||
result = {
|
result = {
|
||||||
'edocument': WizRepStart.default_edocument(),
|
'edocument': WizRepStart.default_edocument(),
|
||||||
'invoice': context.get('active_id', -1),
|
'invoice': context.get('active_id', -1),
|
||||||
'state': invoice[0].state if invoice else ''}
|
'state': invoice[0].state if invoice else ''}
|
||||||
|
if cfg1 and cfg1.xrechn_default:
|
||||||
|
result['edocument'] = cfg1.xrechn_default
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def generate_invoice_reports(self, data):
|
||||||
|
""" generate missing reports and store to db
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data (dict): report-data
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
Invoice = pool.get('account.invoice')
|
||||||
|
XReport = pool.get('account_invoice_xrechnung.export', type='report')
|
||||||
|
|
||||||
|
invoices = Invoice.search([
|
||||||
|
('id', '=', data['invoice']),
|
||||||
|
('type', '=', 'out')])
|
||||||
|
to_generate = [x.id for x in invoices if not x.invoice_report_cache]
|
||||||
|
|
||||||
|
if to_generate:
|
||||||
|
report_action = XReport.get_used_report()
|
||||||
|
|
||||||
|
# run selected report on invoices w/o stored report-data
|
||||||
|
data2 = {}
|
||||||
|
data2.update(data)
|
||||||
|
data2['action_id'] = report_action.id
|
||||||
|
data2['model'] = report_action.model
|
||||||
|
data2['id'] = to_generate[0]
|
||||||
|
data2['ids'] = to_generate
|
||||||
|
|
||||||
|
RepInvoice = pool.get(report_action.report_name, type='report')
|
||||||
|
with Transaction().set_context({'with_rec_name': False}):
|
||||||
|
RepInvoice.execute(to_generate, data2)
|
||||||
|
|
||||||
def do_export(self, action):
|
def do_export(self, action):
|
||||||
""" run export
|
""" run export
|
||||||
"""
|
"""
|
||||||
|
@ -93,9 +127,17 @@ class RunXRechnungReport(Wizard):
|
||||||
raise UserError(gettext(
|
raise UserError(gettext(
|
||||||
'account_invoice_xrechnung.msg_invoice_must_posted',
|
'account_invoice_xrechnung.msg_invoice_must_posted',
|
||||||
invname=self.start.invoice.rec_name))
|
invname=self.start.invoice.rec_name))
|
||||||
return action, {
|
|
||||||
|
data = {
|
||||||
'invoice': self.start.invoice.id,
|
'invoice': self.start.invoice.id,
|
||||||
'edocument': self.start.edocument,
|
'edocument': self.start.edocument,
|
||||||
'as_zip': self.start.as_zip}
|
'as_zip': self.start.as_zip}
|
||||||
|
|
||||||
|
# if zugferd - generate missing report-cache-items
|
||||||
|
if data['edocument'] == 'edocument.facturxext.invoice-ferd':
|
||||||
|
# pdf is stored to db
|
||||||
|
self.generate_invoice_reports(data)
|
||||||
|
|
||||||
|
return action, data
|
||||||
|
|
||||||
# end RunXRechnungReport
|
# end RunXRechnungReport
|
||||||
|
|
122
xreport.py
122
xreport.py
|
@ -6,9 +6,11 @@
|
||||||
import zipfile
|
import zipfile
|
||||||
from facturx import generate_from_binary
|
from facturx import generate_from_binary
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
from slugify import slugify
|
||||||
from trytond.report import Report
|
from trytond.report import Report
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from slugify import slugify
|
from trytond.exceptions import UserError
|
||||||
|
from trytond.i18n import gettext
|
||||||
from .wizard_runreport import edoc_versions
|
from .wizard_runreport import edoc_versions
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,12 +31,37 @@ class XReport(Report):
|
||||||
def execute(cls, ids, data):
|
def execute(cls, ids, data):
|
||||||
""" skip export-engine, run edocument-xml-convert
|
""" skip export-engine, run edocument-xml-convert
|
||||||
"""
|
"""
|
||||||
|
def export_data(exp_content, fname, ext, data2):
|
||||||
|
""" get tuple to return from report.execute,
|
||||||
|
|
||||||
|
|
||||||
|
Args:
|
||||||
|
exp_content (bytes or str): result data of report
|
||||||
|
fname (str): file name
|
||||||
|
ext (str): extension
|
||||||
|
data2 (dict): data
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: return value of report
|
||||||
|
"""
|
||||||
|
if data2['as_zip'] is True:
|
||||||
|
return (
|
||||||
|
'zip',
|
||||||
|
cls.compress_as_zip(
|
||||||
|
'%(fname)s.%(ext)s' % {
|
||||||
|
'fname': fname, 'ext': ext},
|
||||||
|
exp_content),
|
||||||
|
False,
|
||||||
|
file_name)
|
||||||
|
else:
|
||||||
|
return (ext, exp_content, False, fname)
|
||||||
|
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
IrDate = pool.get('ir.date')
|
IrDate = pool.get('ir.date')
|
||||||
Invoice = pool.get('account.invoice')
|
Invoice = pool.get('account.invoice')
|
||||||
document_para = pool.get(data['edocument'].split('-')[0])
|
|
||||||
|
|
||||||
EDocument = document_para[0]
|
document_para = data['edocument'].split('-')
|
||||||
|
EDocument = pool.get(document_para[0])
|
||||||
document_var = document_para[1] if len(document_para) > 1 else None
|
document_var = document_para[1] if len(document_para) > 1 else None
|
||||||
|
|
||||||
invoice, = Invoice.browse([data['invoice']])
|
invoice, = Invoice.browse([data['invoice']])
|
||||||
|
@ -46,31 +73,70 @@ class XReport(Report):
|
||||||
'descr': invoice.rec_name},
|
'descr': invoice.rec_name},
|
||||||
max_length=100, word_boundary=True, save_order=True)
|
max_length=100, word_boundary=True, save_order=True)
|
||||||
|
|
||||||
# if document_var and (
|
if document_var and (
|
||||||
# document_var == 'ferd') and (
|
document_var == 'ferd') and (
|
||||||
# EDocument.__name__ == 'edocument.facturxext.invoice'):
|
EDocument.__name__ == 'edocument.facturxext.invoice'):
|
||||||
# # convert to zugferd
|
# convert to zugferd
|
||||||
# pdf_data = generate_from_binary(
|
invoice_pdf = cls.get_zugferd_pdf(invoice, invoice_xml)
|
||||||
# pdf_file='pdf_content',
|
return export_data(invoice_pdf, file_name, 'pdf', data)
|
||||||
# xml=invoice_xml,
|
|
||||||
# check_xsd=True,
|
|
||||||
# pdf_metadata={
|
|
||||||
# 'author': invoice.company.rec_name,
|
|
||||||
# 'keywords': 'Factur-X, Invoice',
|
|
||||||
# 'title': invoice.number,
|
|
||||||
# 'subject': invoice.description},
|
|
||||||
# lang='de-DE')
|
|
||||||
|
|
||||||
if data['as_zip'] is True:
|
|
||||||
return (
|
|
||||||
'zip',
|
|
||||||
cls.compress_as_zip('%(fname)s.%(ext)s' % {
|
|
||||||
'fname': file_name,
|
|
||||||
'ext': 'xml',
|
|
||||||
}, invoice_xml),
|
|
||||||
False,
|
|
||||||
file_name)
|
|
||||||
else:
|
else:
|
||||||
return ('xml', invoice_xml, False, file_name)
|
return export_data(invoice_xml, file_name, 'xml', data)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_used_report(cls):
|
||||||
|
""" get report to use from config
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
UserError: if not report was found
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
record: ir.action.report
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
Configuration = pool.get('account.configuration')
|
||||||
|
ActionReport = pool.get('ir.action.report')
|
||||||
|
|
||||||
|
cfg1 = Configuration.get_singleton()
|
||||||
|
act_report = None
|
||||||
|
if cfg1 and cfg1.xrechn_zugferd_report:
|
||||||
|
act_report = cfg1.xrechn_zugferd_report
|
||||||
|
else:
|
||||||
|
# no report defined, use 1st found
|
||||||
|
act_report = ActionReport.search([
|
||||||
|
('model', '=', 'account.invoice'),
|
||||||
|
('extension', '=', 'pdf')], count=1)
|
||||||
|
if act_report:
|
||||||
|
act_report = act_report[0]
|
||||||
|
if not act_report:
|
||||||
|
raise UserError(gettext(
|
||||||
|
'account_invoice_xrechnung.msg_no_report_found'))
|
||||||
|
return act_report
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_zugferd_pdf(cls, invoice, invoice_xml):
|
||||||
|
""" generate ZugFeRD-PDF
|
||||||
|
|
||||||
|
Args:
|
||||||
|
invoice (record): model account.invoice
|
||||||
|
invoice_xml (str): xml-data
|
||||||
|
"""
|
||||||
|
# pdf was already stored to db
|
||||||
|
if not (invoice.invoice_report_cache and (
|
||||||
|
invoice.invoice_report_format == 'pdf')):
|
||||||
|
raise UserError(gettext(
|
||||||
|
'account_invoice_xrechnung.msg_invalid_cachecontent',
|
||||||
|
invoice_name=invoice.rec_name))
|
||||||
|
|
||||||
|
zugferd_pdf = generate_from_binary(
|
||||||
|
pdf_file=invoice.invoice_report_cache,
|
||||||
|
xml=invoice_xml,
|
||||||
|
check_xsd=True,
|
||||||
|
pdf_metadata={
|
||||||
|
'author': invoice.company.rec_name,
|
||||||
|
'keywords': 'Factur-X, Invoice, Tryton',
|
||||||
|
'title': invoice.number,
|
||||||
|
'subject': invoice.description},
|
||||||
|
lang='de-DE')
|
||||||
|
return zugferd_pdf
|
||||||
|
|
||||||
# end XReport
|
# end XReport
|
||||||
|
|
Loading…
Reference in a new issue