diff --git a/__init__.py b/__init__.py
index f5712e6..8e0f27b 100644
--- a/__init__.py
+++ b/__init__.py
@@ -8,6 +8,7 @@ from .wizard_runreport import RunXRechnungReport, RunXRechnungReportStart
from .invoice import InvoiceLine
from .xreport import XReport
from .configuration import ConfigurationXRechnungexport, Configuration
+from .wizard_import import ImportXmlStart, ImportXml, ImportXmlShowcontent
def register():
@@ -16,9 +17,12 @@ def register():
ConfigurationXRechnungexport,
InvoiceLine,
RunXRechnungReportStart,
+ ImportXmlStart,
+ ImportXmlShowcontent,
module='account_invoice_xrechnung', type_='model')
Pool.register(
RunXRechnungReport,
+ ImportXml,
module='account_invoice_xrechnung', type_='wizard')
Pool.register(
XReport,
diff --git a/locale/de.po b/locale/de.po
index c09de26..1d5dc89 100644
--- a/locale/de.po
+++ b/locale/de.po
@@ -30,6 +30,10 @@ msgctxt "model:ir.action,name:report_edocument"
msgid "eDocument Export"
msgstr "eDocument Export"
+msgctxt "model:ir.action,name:act_import_wiz"
+msgid "eDocument Import"
+msgstr "eDocument Import"
+
##########################################
# account_invoice_xrechnung.runrep.start #
@@ -193,3 +197,83 @@ msgstr "ZUGFeRD 2.3.2"
msgctxt "selection:account_invoice_xrechnung.configuration,xrechn_default:"
msgid "CII CrossIndustryInvoice D16B"
msgstr "CII CrossIndustryInvoice D16B"
+
+
+##########################################
+# account_invoice_xrechnung.import.start #
+##########################################
+msgctxt "model:account_invoice_xrechnung.import.start,name:"
+msgid "eDocument Import"
+msgstr "eDocument Import"
+
+msgctxt "field:account_invoice_xrechnung.import.start,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:account_invoice_xrechnung.import.start,invoice_type:"
+msgid "Invoice Type"
+msgstr "Rechnungstyp"
+
+msgctxt "selection:account_invoice_xrechnung.import.start,invoice_type:"
+msgid "Customer Invoice"
+msgstr "Kundenrechnung"
+
+msgctxt "selection:account_invoice_xrechnung.import.start,invoice_type:"
+msgid "Supplier Invoice"
+msgstr "Lieferantenrechnung"
+
+msgctxt "field:account_invoice_xrechnung.import.start,file_:"
+msgid "ZIP or XML-File"
+msgstr "ZIP oder XML-Datei"
+
+
+################################################
+# account_invoice_xrechnung.import.showcontent #
+################################################
+msgctxt "model:account_invoice_xrechnung.import.showcontent,name:"
+msgid "eDocument Import"
+msgstr "eDocument Import"
+
+msgctxt "field:account_invoice_xrechnung.import.showcontent,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:account_invoice_xrechnung.import.showcontent,invoice_type:"
+msgid "Invoice Type"
+msgstr "Rechnungstyp"
+
+msgctxt "selection:account_invoice_xrechnung.import.showcontent,invoice_type:"
+msgid "Customer Invoice"
+msgstr "Kundenrechnung"
+
+msgctxt "selection:account_invoice_xrechnung.import.showcontent,invoice_type:"
+msgid "Supplier Invoice"
+msgstr "Lieferantenrechnung"
+
+
+####################################
+# account_invoice_xrechnung.import #
+####################################
+msgctxt "model:account_invoice_xrechnung.import,name:"
+msgid "eDocument Import"
+msgstr "eDocument Import"
+
+msgctxt "wizard_button:account_invoice_xrechnung.import,start,end:"
+msgid "Cancel"
+msgstr "Abbruch"
+
+msgctxt "wizard_button:account_invoice_xrechnung.import,start,doupload:"
+msgid "Upload"
+msgstr "Hochladen"
+
+msgctxt "wizard_button:account_invoice_xrechnung.import,showcontent,end:"
+msgid "Cancel"
+msgstr "Abbruch"
+
+msgctxt "wizard_button:account_invoice_xrechnung.import,showcontent,start:"
+msgid "Back"
+msgstr "Zurück"
+
+msgctxt "wizard_button:account_invoice_xrechnung.import,showcontent,doimport:"
+msgid "Import"
+msgstr "Import"
diff --git a/locale/en.po b/locale/en.po
index d6ec74c..07a080d 100644
--- a/locale/en.po
+++ b/locale/en.po
@@ -22,6 +22,10 @@ msgctxt "model:ir.action,name:report_edocument"
msgid "eDocument Export"
msgstr "eDocument Export"
+msgctxt "model:ir.action,name:act_import_wiz"
+msgid "eDocument Import"
+msgstr "eDocument Import"
+
msgctxt "model:account_invoice_xrechnung.runrep.start,name:"
msgid "eDocument Export"
msgstr "eDocument Export"
@@ -165,3 +169,72 @@ msgstr "ZUGFeRD 2.3.2"
msgctxt "selection:account_invoice_xrechnung.configuration,xrechn_default:"
msgid "CII CrossIndustryInvoice D16B"
msgstr "CII CrossIndustryInvoice D16B"
+
+msgctxt "model:account_invoice_xrechnung.import.start,name:"
+msgid "eDocument Import"
+msgstr "eDocument Import"
+
+msgctxt "field:account_invoice_xrechnung.import.start,company:"
+msgid "Company"
+msgstr "Company"
+
+msgctxt "field:account_invoice_xrechnung.import.start,invoice_type:"
+msgid "Invoice Type"
+msgstr "Invoice Type"
+
+msgctxt "selection:account_invoice_xrechnung.import.start,invoice_type:"
+msgid "Customer Invoice"
+msgstr "Customer Invoice"
+
+msgctxt "selection:account_invoice_xrechnung.import.start,invoice_type:"
+msgid "Supplier Invoice"
+msgstr "Supplier Invoice"
+
+msgctxt "field:account_invoice_xrechnung.import.start,file_:"
+msgid "ZIP or XML-File"
+msgstr "ZIP or XML-File"
+
+msgctxt "model:account_invoice_xrechnung.import.showcontent,name:"
+msgid "eDocument Import"
+msgstr "eDocument Import"
+
+msgctxt "field:account_invoice_xrechnung.import.showcontent,company:"
+msgid "Company"
+msgstr "Company"
+
+msgctxt "field:account_invoice_xrechnung.import.showcontent,invoice_type:"
+msgid "Invoice Type"
+msgstr "Invoice Type"
+
+msgctxt "selection:account_invoice_xrechnung.import.showcontent,invoice_type:"
+msgid "Customer Invoice"
+msgstr "Customer Invoice"
+
+msgctxt "selection:account_invoice_xrechnung.import.showcontent,invoice_type:"
+msgid "Supplier Invoice"
+msgstr "Supplier Invoice"
+
+msgctxt "model:account_invoice_xrechnung.import,name:"
+msgid "eDocument Import"
+msgstr "eDocument Import"
+
+msgctxt "wizard_button:account_invoice_xrechnung.import,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "wizard_button:account_invoice_xrechnung.import,start,doupload:"
+msgid "Upload"
+msgstr "Upload"
+
+msgctxt "wizard_button:account_invoice_xrechnung.import,showcontent,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "wizard_button:account_invoice_xrechnung.import,showcontent,start:"
+msgid "Back"
+msgstr "Back"
+
+msgctxt "wizard_button:account_invoice_xrechnung.import,showcontent,doimport:"
+msgid "Import"
+msgstr "Import"
+
diff --git a/menu.xml b/menu.xml
new file mode 100644
index 0000000..186e980
--- /dev/null
+++ b/menu.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
diff --git a/tests/facturx-extended.xml b/tests/facturx-extended.xml
new file mode 100644
index 0000000..ce384cb
--- /dev/null
+++ b/tests/facturx-extended.xml
@@ -0,0 +1,114 @@
+
+
+
+
+ urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended
+
+
+
+ RE2024.01234
+ 380
+
+ 20240617
+
+
+ Some notes to the customer.
+
+
+
+
+
+ 1
+
+
+ Name of Product 1
+ Description of Product 1
+
+
+
+ 1350.00
+
+
+
+ 1.0
+
+
+
+ VAT
+ S
+ 19.00
+
+
+ 1350.00
+
+
+
+
+
+ Name of the Comany
+
+
+
+ 12345
+ Street of Company No 1
+ Berlin
+ DE
+ Berlin
+
+
+
+ Customer Company
+
+
+
+ 23456
+ Address Line 1
+ Address Line 2
+ Potsdam
+ DE
+ Brandenburg
+
+
+
+
+
+
+
+
+
+ RE2024.01234
+ EUR
+
+ 30
+ Wire transfer
+
+ DE02300209000106531065
+ mbs
+
+
+ WELADED1PMB
+
+
+
+ 256.5
+ VAT
+ 1350
+ S
+ 19.00
+
+
+
+ 20240701
+
+ 1606.50
+
+
+ 1350.00
+ 1350.00
+ 256.5
+ 1606.50
+ 1606.50
+
+
+
+
diff --git a/tests/test_invoice.py b/tests/test_invoice.py
index d502547..f712a5c 100644
--- a/tests/test_invoice.py
+++ b/tests/test_invoice.py
@@ -3,6 +3,7 @@
# from m-ds for Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
+import os.path
from decimal import Decimal
from datetime import date
from facturx import get_facturx_xml_from_pdf
@@ -109,6 +110,57 @@ class InvoiceTestCase(ModuleTestCase):
self.assertEqual(len(inv_lst.move.lines), 3)
return inv_lst
+ @with_transaction()
+ def test_wiz_import_single_xml(self):
+ """ run import wizard, upload a single file
+ """
+ pool = Pool()
+ ImportWiz = pool.get(
+ 'account_invoice_xrechnung.import', type='wizard')
+
+ company1 = create_company('m-ds')
+ with Transaction().set_context({
+ 'company': company1.id,
+ 'active_model': 'party.party'}):
+ (sess_id, start_state, end_state) = ImportWiz.create()
+ w_obj = ImportWiz(sess_id)
+ self.assertEqual(start_state, 'start')
+ self.assertEqual(end_state, 'end')
+
+ # run start
+ result = ImportWiz.execute(sess_id, {}, start_state)
+ self.assertEqual(list(result.keys()), ['view'])
+
+ step_values = {
+ x: result['view']['defaults'][x]
+ for x in result['view']['defaults'].keys()
+ if '.' not in x}
+
+ self.assertEqual(step_values, {
+ 'company': company1.id,
+ 'invoice_type': 'in',
+ 'file_': None})
+
+ # step 1: upload xml-file
+ with open(os.path.join(
+ os.path.split(__file__)[0],
+ 'facturx-extended.xml'), 'rb') as fhdl:
+ step_values['file_'] = fhdl.read()
+ for i in step_values.keys():
+ setattr(w_obj.start, i, step_values[i])
+
+ result = ImportWiz.execute(
+ sess_id, {start_state: step_values}, 'doupload')
+
+ step_values = {
+ x: result['view']['defaults'][x]
+ for x in result['view']['defaults'].keys()
+ if '.' not in x}
+
+ self.assertEqual(step_values, {
+ 'company': company1.id,
+ 'invoice_type': 'in'})
+
@with_transaction()
def test_xrechnung_configuration(self):
""" test configuration
diff --git a/tryton.cfg b/tryton.cfg
index 272e243..1c134fd 100644
--- a/tryton.cfg
+++ b/tryton.cfg
@@ -8,4 +8,6 @@ xml:
message.xml
configuration.xml
wizard_runreport.xml
+ wizard_import.xml
xreport.xml
+ menu.xml
diff --git a/view/import_content_form.xml b/view/import_content_form.xml
new file mode 100644
index 0000000..e4b28e7
--- /dev/null
+++ b/view/import_content_form.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/view/import_start_form.xml b/view/import_start_form.xml
new file mode 100644
index 0000000..16f22ce
--- /dev/null
+++ b/view/import_start_form.xml
@@ -0,0 +1,14 @@
+
+
+
diff --git a/wizard_import.py b/wizard_import.py
new file mode 100644
index 0000000..7ccc274
--- /dev/null
+++ b/wizard_import.py
@@ -0,0 +1,128 @@
+# -*- coding: utf-8 -*-
+# This file is part of the account-invoice-xrechnung-module
+# from m-ds for Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+
+from trytond.model import ModelView, fields
+from trytond.wizard import (
+ Wizard, StateView, StateTransition, StateAction, Button)
+from trytond.transaction import Transaction
+from trytond.pyson import Bool, Eval
+
+
+sel_invoice_type = [
+ ('out', 'Customer Invoice'),
+ ('in', 'Supplier Invoice')]
+
+
+class ImportXmlStart(ModelView):
+ 'eDocument Import'
+ __name__ = 'account_invoice_xrechnung.import.start'
+
+ company = fields.Many2One(
+ string='Company', model_name='company.company', required=True,
+ readonly=True)
+ invoice_type = fields.Selection(
+ string='Invoice Type', required=True,
+ selection=sel_invoice_type)
+ file_ = fields.Binary(
+ string="ZIP or XML-File", required=True)
+
+# end ImportStart
+
+
+class ImportXmlShowcontent(ModelView):
+ 'eDocument Import'
+ __name__ = 'account_invoice_xrechnung.import.showcontent'
+
+ company = fields.Many2One(
+ string='Company', model_name='company.company', required=True,
+ readonly=True)
+ invoice_type = fields.Selection(
+ string='Invoice Type', required=True, readonly=True,
+ selection=sel_invoice_type)
+
+# end ImportXmlShowcontent
+
+
+class ImportXml(Wizard):
+ 'eDocument Import'
+ __name__ = 'account_invoice_xrechnung.import'
+
+ start_state = 'start'
+ start = StateView(
+ model_name='account_invoice_xrechnung.import.start',
+ view='account_invoice_xrechnung.import_start_form',
+ buttons=[
+ Button(string='Cancel', state='end', icon='tryton-cancel'),
+ Button(
+ string='Upload', state='doupload', icon='tryton-open',
+ states={'readonly': ~Bool(Eval('file_'))}),
+ ])
+ doupload = StateTransition()
+ showcontent = StateView(
+ model_name='account_invoice_xrechnung.import.showcontent',
+ view='account_invoice_xrechnung.import_content_form',
+ buttons=[
+ Button(string='Cancel', state='end', icon='tryton-cancel'),
+ Button(string='Back', state='start', icon='tryton-back'),
+ Button(string='Import', state='doimport', icon='tryton-open'),
+ ])
+ doimport = StateTransition()
+ invoices_out = StateAction('account_invoice.act_invoice_out_form')
+ invoices_in = StateAction('account_invoice.act_invoice_in_form')
+
+ def default_start(self, fields):
+ """ fill fields of start-form
+ """
+ context = Transaction().context
+
+ inv_type = getattr(getattr(
+ self, 'showcontent', {}), 'invoice_type', None)
+ result = {
+ 'company': context.get('company', None),
+ 'invoice_type': inv_type if inv_type else 'in',
+ 'file_': getattr(self.start, 'file_', None)}
+ return result
+
+ def default_showcontent(self, fields):
+ """ fill fields of start-form
+ """
+ context = Transaction().context
+
+ inv_type = getattr(self.start, 'invoice_type')
+ result = {
+ 'company': context.get('company', None),
+ 'invoice_type': inv_type if inv_type else 'in'}
+ return result
+
+ def transition_doupload(self):
+ """ load file, detect content
+ """
+ self.showcontent.company = self.start.company
+ self.showcontent.invoice_type = self.start.invoice_type
+ return 'showcontent'
+
+ def transition_doimport(self):
+ """ create invoices
+ """
+ return 'end'
+
+ def do_invoices_out(self, action):
+ """ show created customer invoices
+ """
+ data = {}
+ data['res_id'] = []
+ action['views'].reverse()
+ return action, data
+
+ def do_invoices_in(self, action):
+ """ show created supplier invoices
+ """
+ data = {}
+ data['res_id'] = []
+ action['views'].reverse()
+ return action, data
+
+# end ImportXml
diff --git a/wizard_import.xml b/wizard_import.xml
new file mode 100644
index 0000000..9e367bd
--- /dev/null
+++ b/wizard_import.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+ account_invoice_xrechnung.import.start
+ form
+
+ import_start_form
+
+
+
+ account_invoice_xrechnung.import.showcontent
+ form
+
+ import_content_form
+
+
+
+ eDocument Import
+ account_invoice_xrechnung.import
+
+
+ form_action
+ account.invoice,-1
+
+
+
+
+