diff --git a/.hgignore b/.hgignore
index de14f8e..0a1c9bc 100644
--- a/.hgignore
+++ b/.hgignore
@@ -3,3 +3,4 @@ locale/convert_de2en.py
build/*
mds_cashbook_dataexchange.egg-info/*
dist/*
+__pycache__/*
diff --git a/__init__.py b/__init__.py
index 4214b77..d01f22e 100644
--- a/__init__.py
+++ b/__init__.py
@@ -5,8 +5,15 @@
from trytond.pool import Pool
from .category import Category
+from .qiftool import QifTool
+from .qif_import_wiz import ImportQifWizard, ImportQifWizardStart
def register():
Pool.register(
+ QifTool,
Category,
+ ImportQifWizardStart,
module='cashbook_dataexchange', type_='model')
+ Pool.register(
+ ImportQifWizard,
+ module='cashbook_dataexchange', type_='wizard')
diff --git a/category.py b/category.py
index 60d1732..05f31de 100644
--- a/category.py
+++ b/category.py
@@ -7,8 +7,57 @@ from trytond.transaction import Transaction
from trytond.pool import Pool, PoolMeta
-class Category(PoolMeta):
+class Category(metaclass=PoolMeta):
__name__ = 'cashbook.category'
+ @classmethod
+ def create_from_qif(cls, qifdata):
+ """ add categories from QIF-File-content
+ """
+ pool = Pool()
+ QifTool = pool.get('cashbook_dataexchange.qiftool')
+ Category2 = pool.get('cashbook.category')
+
+ def get_create(ctype, catdict, parent, do_search):
+ """ check if category exists, generate create-data
+ """
+ result = []
+ for catname in catdict.keys():
+ if do_search == True:
+ c_lst = Category2.search([
+ ('cattype', '=', ctype),
+ ('name', '=', catname),
+ ('parent', '=', None) if parent is None else ('parent.id', '=', parent.id),
+ ])
+ else :
+ c_lst = []
+
+ if len(c_lst) == 0:
+ cat1 = {
+ 'cattype': ctype,
+ 'name': catname,
+ }
+ if parent is not None:
+ cat1['parent'] = parent.id
+
+ if len(catdict[catname]['childs']) > 0:
+ childs = get_create(ctype, catdict[catname]['childs'], None, False)
+ if len(childs) > 0:
+ cat1['childs'] = [('create', childs)]
+ result.append(cat1)
+ else :
+ if len(catdict[catname]['childs']) > 0:
+ result.extend(get_create(ctype, catdict[catname]['childs'], c_lst[0], True))
+ return result
+
+ type_data = QifTool.split_by_type(qifdata)
+ if not 'Cat' in type_data.keys():
+ return None
+
+ cat_tree = QifTool.qif_read_categories(type_data['Cat'])
+ to_create = []
+ for typ1 in ['in', 'out']:
+ to_create.extend(get_create(typ1, cat_tree[typ1], None, True))
+ return Category2.create(to_create)
# end Category
diff --git a/locale/de.po b/locale/de.po
index 9f86134..2245828 100644
--- a/locale/de.po
+++ b/locale/de.po
@@ -2,3 +2,46 @@
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#############
+# ir.action #
+#############
+msgctxt "model:ir.action,name:act_import_qif_wizard"
+msgid "Import QIF-File"
+msgstr "QIF-Datei importieren"
+
+
+#####################################
+# cashbook_dataexchange.qif_imp_wiz #
+#####################################
+msgctxt "model:cashbook_dataexchange.qif_imp_wiz,name:"
+msgid "Import QIF-File"
+msgstr "QIF-Datei importieren"
+
+msgctxt "wizard_button:cashbook_dataexchange.qif_imp_wiz,start,end:"
+msgid "Cancel"
+msgstr "Abbruch"
+
+msgctxt "wizard_button:cashbook_dataexchange.qif_imp_wiz,start,readf:"
+msgid "Read File"
+msgstr "Datei lesen"
+
+
+###########################################
+# cashbook_dataexchange.qif_imp_wiz.start #
+###########################################
+msgctxt "model:cashbook_dataexchange.qif_imp_wiz.start,name:"
+msgid "Import QIF-File"
+msgstr "QIF-Datei importieren"
+
+msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,file_:"
+msgid "QIF-File"
+msgstr "QIF-Datei"
+
+msgctxt "help:cashbook_dataexchange.qif_imp_wiz.start,file_:"
+msgid "Quicken Interchange Format"
+msgstr "Quicken Interchange Format"
diff --git a/locale/en.po b/locale/en.po
new file mode 100644
index 0000000..df5fa3e
--- /dev/null
+++ b/locale/en.po
@@ -0,0 +1,32 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.action,name:act_import_qif_wizard"
+msgid "Import QIF-File"
+msgstr "Import QIF-File"
+
+msgctxt "model:cashbook_dataexchange.qif_imp_wiz,name:"
+msgid "Import QIF-File"
+msgstr "Import QIF-File"
+
+msgctxt "wizard_button:cashbook_dataexchange.qif_imp_wiz,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "wizard_button:cashbook_dataexchange.qif_imp_wiz,start,readf:"
+msgid "Read File"
+msgstr "Read File"
+
+msgctxt "model:cashbook_dataexchange.qif_imp_wiz.start,name:"
+msgid "Import QIF-File"
+msgstr "Import QIF-File"
+
+msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,company:"
+msgid "Company"
+msgstr "Company"
+
+msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,file_:"
+msgid "QIF-File"
+msgstr "QIF-File"
+
diff --git a/qif_import_wiz.py b/qif_import_wiz.py
new file mode 100644
index 0000000..e2578df
--- /dev/null
+++ b/qif_import_wiz.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+# This file is part of the cashbook-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.transaction import Transaction
+from trytond.pool import Pool
+from trytond.model import ModelView, fields
+from trytond.wizard import Wizard, StateTransition, StateView, Button
+from trytond.transaction import Transaction
+
+
+class ImportQifWizardStart(ModelView):
+ 'Import QIF-File'
+ __name__ = 'cashbook_dataexchange.qif_imp_wiz.start'
+
+ company = fields.Many2One(model_name='company.company',
+ string="Company", required=True,
+ states={'invisible': True})
+ file_ = fields.Binary(string="QIF-File", required=True,
+ help='Quicken Interchange Format')
+
+ @classmethod
+ def default_company(cls):
+ return Transaction().context.get('company')
+
+# end ImportQifWizardStart
+
+
+class ImportQifWizard(Wizard):
+ 'Import QIF-File'
+ __name__ = 'cashbook_dataexchange.qif_imp_wiz'
+
+ start_state = 'start'
+ start = StateView(model_name='cashbook_dataexchange.qif_imp_wiz.start', \
+ view='cashbook_dataexchange.qif_imp_wiz_start_form', \
+ buttons=[
+ Button(string='Cancel', state='end', icon='tryton-cancel'),
+ Button(string='Read File', state='readf', icon='tryton-forward', default=True),
+ ])
+
+# end ImportQifWizard
+
diff --git a/qif_import_wiz.xml b/qif_import_wiz.xml
new file mode 100644
index 0000000..022f445
--- /dev/null
+++ b/qif_import_wiz.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+ cashbook_dataexchange.qif_imp_wiz.start
+ form
+ wiz_qifimport_start_form
+
+
+
+
+ Import QIF-File
+ cashbook_dataexchange.qif_imp_wiz
+
+
+
+
+ form_action
+ cashbook.category,-1
+
+
+
+
+
diff --git a/qiftool.py b/qiftool.py
new file mode 100644
index 0000000..0743f3b
--- /dev/null
+++ b/qiftool.py
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+# This file is part of the cashbook-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.pool import Pool
+from trytond.model import Model
+
+
+class QifTool(Model):
+ 'QIF Tool'
+ __name__ = 'cashbook_dataexchange.qiftool'
+
+ @classmethod
+ def split_by_type(cls, qifdata):
+ """ split file-content by type
+ """
+ lines = qifdata.split('\n')
+
+ blocks = {}
+ current_type = None
+ for line in lines:
+ if line.startswith('!Type:'):
+ current_type = line[len('!Type:'):].strip()
+ else :
+ if current_type is None:
+ continue
+
+ if not current_type in blocks.keys():
+ blocks[current_type] = []
+ blocks[current_type].append(line.strip())
+
+ for block in blocks.keys():
+ blocks[block] = '\n'.join(blocks[block])
+ return blocks
+
+ @classmethod
+ def qif_read_categories(cls, catdata):
+ """ read categories from text
+ result: {
+ 'in': [{
+ '': {
+ 'type': 'in|out',
+ 'childs': [...],
+ },
+ },...],
+ 'out': [{},...],
+ }
+ """
+ def add_category(catdict, namelst, ctype):
+ """ add category to dict
+ """
+ if not namelst[0] in catdict.keys():
+ catdict[namelst[0]] = {'type': ctype, 'childs': {}}
+
+ if len(namelst) > 1:
+ catdict[namelst[0]]['childs'] = add_category(
+ catdict[namelst[0]]['childs'],
+ namelst[1:],
+ ctype)
+ return catdict
+
+ categories = {'in': {}, 'out': {}}
+ for cattxt in catdata.split('^'):
+ if len(cattxt.strip()) == 0:
+ continue
+ catname = None
+ cattype = None
+ for line in cattxt.strip().split('\n'):
+ if line.startswith('N'):
+ catname = line[1:].strip().split(':')
+ elif line.startswith('E'):
+ cattype = 'out'
+ elif line.startswith('I'):
+ cattype = 'in'
+ else :
+ raise ValueError('invalid line: %s (%s)' % (line, cattxt))
+ categories[cattype] = add_category(categories[cattype], catname, cattype)
+ return categories
+
+# end QifTool
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..19ff9ad
--- /dev/null
+++ b/tests/__init__.py
@@ -0,0 +1,23 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import trytond.tests.test_tryton
+import unittest
+
+from trytond.modules.cashbook_dataexchange.tests.test_category import CategoryTestCase
+
+__all__ = ['suite']
+
+
+class CashbookExchangeTestCase(\
+ CategoryTestCase,\
+ ):
+ 'Test cashbook exchange module'
+ module = 'cashbook_dataexchange'
+
+# end CashbookExchangeTestCase
+
+def suite():
+ suite = trytond.tests.test_tryton.suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(CashbookExchangeTestCase))
+ return suite
diff --git a/tests/qifdata.py b/tests/qifdata.py
new file mode 100644
index 0000000..9f749cc
--- /dev/null
+++ b/tests/qifdata.py
@@ -0,0 +1,386 @@
+# -*- coding: utf-8 -*-
+# This file is part of the cashbook-module from m-ds for Tryton.
+# The COPYRIGHT file at the top level of this repository contains the
+# full copyright notices and license terms.
+
+qif_types = """
+!Type:Cat
+NGehalt
+I
+^
+NGehalt:Zulagen
+I
+^
+NTelekommunikation
+E
+^
+NTelekommunikation:Online-Dienste
+E
+^
+NTelekommunikation:Telefon
+E
+^
+NTelekommunikation:Telefon:Test1
+E
+^
+NTelefon:Telco1-Tablett
+E
+^
+NTelefon:Telco2-Handy
+E
+^
+NTelefon:Telco3
+E
+^
+NTelekommunikation:Fernsehen
+E
+^
+NFernsehen:TV-Company
+E
+^
+NFernsehen:GEZ
+E
+^
+NLebensmittel
+E
+^
+!Type:Bank
+D04.12.2013
+T7,12
+CX
+POpening Balance
+L[Bargeld]
+^
+D05.12.2013
+CX
+M05.12/06.42UHR TT TELTOW
+T290,00
+PGA NR00002168 BLZ10000000 0
+L[S-Giro]
+^
+D05.12.2013
+CX
+Msome food
+T-56,37
+PFoodshop Zehlendorf
+LLebensmittel
+^
+"""
+
+qif_category = """!Type:Cat
+NGehalt
+I
+^
+NGehalt:Zulagen
+I
+^
+NGehalt:Gehalt
+I
+^
+NSonstiges
+I
+^
+NSonstiges:Prämie
+I
+^
+NSonstiges:Auslagen
+I
+^
+NSonstiges:Gebühren
+I
+^
+NZinsen
+I
+^
+NZinsen:Girokonto
+I
+^
+NZinsen:Sparkonto
+I
+^
+NZinsen:Sonstige
+I
+^
+NGeschenke
+I
+^
+NDividende
+I
+^
+NVerkauf
+I
+^
+NSteuern
+I
+^
+NSteuern:Kapitalertragssteuer
+I
+^
+NTelekommunikation
+E
+^
+NTelekommunikation:Online-Dienste
+E
+^
+NTelekommunikation:Telefon
+E
+^
+NTelefon:Telco1-Tablett
+E
+^
+NTelefon:Telco2-Handy
+E
+^
+NTelefon:Telco3
+E
+^
+NTelekommunikation:Fernsehen
+E
+^
+NFernsehen:TV-Company
+E
+^
+NFernsehen:GEZ
+E
+^
+NLebensmittel
+E
+^
+NVersicherungen
+E
+^
+NVersicherungen:Krankenversicherung
+E
+^
+NVersicherungen:Haftpflicht
+E
+^
+NVersicherungen:Haushalt
+E
+^
+NVersicherungen:KFZ
+E
+^
+NHobbies
+E
+^
+NHobbies:Werkzeug
+E
+^
+NHobbies:Sport
+E
+^
+NHobbies:Fahrrad
+E
+^
+NHobbies:Foto
+E
+^
+NComputer
+E
+^
+NComputer:Software
+E
+^
+NComputer:Hardware
+E
+^
+NGeschenke
+E
+^
+NFahrtkosten
+E
+^
+NFahrtkosten:Fahrkarten
+E
+^
+NFahrtkosten:Fahrrad
+E
+^
+NFahrtkosten:Parken
+E
+^
+NFahrtkosten:Tanken
+E
+^
+NFahrtkosten:Maut
+E
+^
+NFahrtkosten:Verwarngeld
+E
+^
+NFahrtkosten:Auto
+E
+^
+NWohnen
+E
+^
+NWohnen:Miete
+E
+^
+NWohnen:Nebenkosten
+E
+^
+NNebenkosten:Strom
+E
+^
+NNebenkosten:Abfall
+E
+^
+NNebenkosten:Gas
+E
+^
+NNebenkosten:Wasser
+E
+^
+NWohnen:Garten
+E
+^
+NWohnen:Garage
+E
+^
+NSteuern
+E
+^
+NSteuern:Sozialabgaben
+E
+^
+NSteuern:Solidarzuschlag
+E
+^
+NSteuern:Pflegeversicherung
+E
+^
+NSteuern:Einkommenssteuer
+E
+^
+NSteuern:Rentenversicherung
+E
+^
+NSteuern:Sonstige
+E
+^
+NSteuern:KFZ-Steuer
+E
+^
+NMedikamente
+E
+^
+NKleidung
+E
+^
+NSonstiges
+E
+^
+NSonstiges:Bankgebühren
+E
+^
+NSonstiges:Sonstiges
+E
+^
+NSonstiges:Versandkosten
+E
+^
+NSonstiges:Sehhilfe
+E
+^
+NSonstiges:Gebühr
+E
+^
+NSonstiges:Auslage
+E
+^
+NSonstiges:Gutschein
+E
+^
+NSpenden
+E
+^
+NUnterhaltung
+E
+^
+NUnterhaltung:Musik, Kino
+E
+^
+NUnterhaltung:Reisen
+E
+^
+NUnterhaltung:Ausgehen
+E
+^
+NUnterhaltung:Sport
+E
+^
+NUnterhaltung:Urlaub
+E
+^
+NUnterhaltung:Video
+E
+^
+NUnterhaltung:Museum
+E
+^
+NUnterhaltung:Spiele
+E
+^
+NBüroartikel
+E
+^
+NAbonnements
+E
+^
+NZeitungen
+E
+^
+NZeitungen:Newspaper1
+E
+^
+NZeitungen:Newspaper2
+E
+^
+NZeitungen:Newspaper3
+E
+^
+NBücher
+E
+^
+NKosmetik
+E
+^
+NRentenfonds
+E
+^
+NEinrichtung
+E
+^
+NEinrichtung:Technik
+E
+^
+NEinrichtung:Möbel
+E
+^
+NEinrichtung:Haushalt
+E
+^
+NZinsen
+E
+^
+NZinsen:Sollzinsen
+E
+^
+NHaushaltschemie
+E
+^
+NGesundheit
+E
+^
+NGesundheit:Zahnarzt
+E
+^
+NLuxusgüter
+E
+^
+NLuxusgüter:Uhr
+E
+^
+"""
diff --git a/tests/test_category.py b/tests/test_category.py
new file mode 100644
index 0000000..82bface
--- /dev/null
+++ b/tests/test_category.py
@@ -0,0 +1,150 @@
+# -*- coding: utf-8 -*-
+# This file is part of the cashbook-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.tests.test_tryton import ModuleTestCase, with_transaction
+from trytond.pool import Pool
+from trytond.transaction import Transaction
+from trytond.modules.cashbook.tests import CashbookTestCase
+from .qifdata import qif_category, qif_types
+
+
+class CategoryTestCase(CashbookTestCase):
+ 'Test cashbook categoy module'
+ module = 'CashbookExchangeTestCase'
+
+ @with_transaction()
+ def test_category_create_by_qif_emptydb(self):
+ """ create categories by import a qif-file
+ """
+ pool = Pool()
+ Category = pool.get('cashbook.category')
+
+ company = self.prep_company()
+ with Transaction().set_context({
+ 'company': company.id,
+ }):
+ records = Category.create_from_qif(qif_types)
+
+ records = Category.search([], order=[('name', 'ASC')])
+ self.assertEqual(len(records), 15)
+ self.assertEqual(records[0].rec_name, 'Fernsehen')
+ self.assertEqual(records[1].rec_name, 'Telekommunikation/Fernsehen')
+ self.assertEqual(records[2].rec_name, 'Gehalt')
+ self.assertEqual(records[3].rec_name, 'Fernsehen/GEZ')
+ self.assertEqual(records[4].rec_name, 'Lebensmittel')
+ self.assertEqual(records[5].rec_name, 'Telekommunikation/Online-Dienste')
+ self.assertEqual(records[6].rec_name, 'Telefon/Telco1-Tablett')
+ self.assertEqual(records[7].rec_name, 'Telefon/Telco2-Handy')
+ self.assertEqual(records[8].rec_name, 'Telefon/Telco3')
+ self.assertEqual(records[9].rec_name, 'Telekommunikation/Telefon')
+ self.assertEqual(records[10].rec_name, 'Telefon')
+ self.assertEqual(records[11].rec_name, 'Telekommunikation')
+ self.assertEqual(records[12].rec_name, 'Telekommunikation/Telefon/Test1')
+ self.assertEqual(records[13].rec_name, 'Fernsehen/TV-Company')
+ self.assertEqual(records[14].rec_name, 'Gehalt/Zulagen')
+
+ @with_transaction()
+ def test_category_create_by_qif_existing_categories(self):
+ """ create categories by import a qif-file,
+ some categories exists already
+ """
+ pool = Pool()
+ Category = pool.get('cashbook.category')
+
+ company = self.prep_company()
+ with Transaction().set_context({
+ 'company': company.id,
+ }):
+ cat1, = Category.create([{
+ 'name': 'Telekommunikation',
+ 'cattype': 'out',
+ 'childs': [('create', [{
+ 'cattype': 'out',
+ 'name': 'Telefon',
+ }])],
+ }])
+
+ records = Category.search([])
+ self.assertEqual(len(records), 2)
+ self.assertEqual(records[0].rec_name, 'Telekommunikation/Telefon')
+ self.assertEqual(records[1].rec_name, 'Telekommunikation')
+
+ records1 = Category.create_from_qif(qif_types)
+
+ records = Category.search([], order=[('name', 'ASC')])
+ self.assertEqual(len(records), 15)
+
+ for rec in records:
+ print('-rec:', rec.rec_name)
+ self.assertEqual(records[0].rec_name, 'Telekommunikation/Fernsehen')
+ self.assertEqual(records[1].rec_name, 'Fernsehen')
+ self.assertEqual(records[2].rec_name, 'Gehalt')
+ self.assertEqual(records[3].rec_name, 'Fernsehen/GEZ')
+ self.assertEqual(records[4].rec_name, 'Lebensmittel')
+ self.assertEqual(records[5].rec_name, 'Telekommunikation/Online-Dienste')
+ self.assertEqual(records[6].rec_name, 'Telefon/Telco1-Tablett')
+ self.assertEqual(records[7].rec_name, 'Telefon/Telco2-Handy')
+ self.assertEqual(records[8].rec_name, 'Telefon/Telco3')
+ self.assertEqual(records[9].rec_name, 'Telefon')
+ self.assertEqual(records[10].rec_name, 'Telekommunikation/Telefon')
+ self.assertEqual(records[11].rec_name, 'Telekommunikation')
+ self.assertEqual(records[12].rec_name, 'Telekommunikation/Telefon/Test1')
+ self.assertEqual(records[13].rec_name, 'Fernsehen/TV-Company')
+ self.assertEqual(records[14].rec_name, 'Gehalt/Zulagen')
+
+ @with_transaction()
+ def test_qiftool_split_types(self):
+ """ split file-content by types
+ """
+ QifTool = Pool().get('cashbook_dataexchange.qiftool')
+
+ result = QifTool.split_by_type(qif_types)
+ self.assertEqual(len(result.keys()), 2)
+ self.assertEqual(result['Cat'], 'NGehalt\nI\n^\nNGehalt:Zulagen\n'+
+ 'I\n^\nNTelekommunikation\nE\n^\nNTelekommunikation:Online-Dienste\n'+
+ 'E\n^\nNTelekommunikation:Telefon\nE\n^\nNTelekommunikation:Telefon:Test1\n'+
+ 'E\n^\nNTelefon:Telco1-Tablett\n'+
+ 'E\n^\nNTelefon:Telco2-Handy\nE\n^\nNTelefon:Telco3\nE\n^\n'+
+ 'NTelekommunikation:Fernsehen\nE\n^\nNFernsehen:TV-Company\nE\n'+
+ '^\nNFernsehen:GEZ\nE\n^\nNLebensmittel\nE\n^')
+ self.assertEqual(result['Bank'], 'D04.12.2013\nT7,12\nCX\nPOpening Balance\n'+
+ 'L[Bargeld]\n^\nD05.12.2013\nCX\nM05.12/06.42UHR TT TELTOW\nT290,00\n'+
+ 'PGA NR00002168 BLZ10000000 0\nL[S-Giro]\n^\nD05.12.2013\nCX\nMsome food\n'+
+ 'T-56,37\nPFoodshop Zehlendorf\nLLebensmittel\n^\n')
+
+ @with_transaction()
+ def test_qiftool_read_categories(self):
+ """ read category-data from text
+ """
+ QifTool = Pool().get('cashbook_dataexchange.qiftool')
+
+ result = QifTool.qif_read_categories('NGehalt\nI\n^\nNGehalt:Zulagen\nI\n^'+
+ 'NTelekommunikation\nE\n^\nNTelekommunikation:Online-Dienste\nE\n^')
+ self.assertEqual(result, {
+ 'in': {
+ 'Gehalt': {
+ 'type': 'in',
+ 'childs': {
+ 'Zulagen': {
+ 'type': 'in',
+ 'childs': {},
+ },
+ },
+ },
+ },
+ 'out': {
+ 'Telekommunikation': {
+ 'type': 'out',
+ 'childs': {
+ 'Online-Dienste': {
+ 'type': 'out',
+ 'childs': {},
+ },
+ },
+ },
+ },
+ })
+
+# end CategoryTestCase
diff --git a/tryton.cfg b/tryton.cfg
index 80e4d6d..a10f4f1 100644
--- a/tryton.cfg
+++ b/tryton.cfg
@@ -3,3 +3,4 @@ version=6.0.1
depends:
cashbook
xml:
+ qif_import_wiz.xml
diff --git a/view/wiz_qifimport_start_form.xml b/view/wiz_qifimport_start_form.xml
new file mode 100644
index 0000000..7c80dd1
--- /dev/null
+++ b/view/wiz_qifimport_start_form.xml
@@ -0,0 +1,11 @@
+
+
+