import der transaktionen begonnen
This commit is contained in:
parent
b50927753b
commit
0287452fe8
11 changed files with 637 additions and 15 deletions
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from .category import Category
|
from .category import Category
|
||||||
|
from .book import Book
|
||||||
from .qiftool import QifTool
|
from .qiftool import QifTool
|
||||||
from .qif_import_wiz import ImportQifWizard, ImportQifWizardStart, ImportQifWizardInfo
|
from .qif_import_wiz import ImportQifWizard, ImportQifWizardStart, ImportQifWizardInfo
|
||||||
from .qif_export import QifCategoryExport
|
from .qif_export import QifCategoryExport
|
||||||
|
@ -13,6 +14,7 @@ def register():
|
||||||
Pool.register(
|
Pool.register(
|
||||||
QifTool,
|
QifTool,
|
||||||
Category,
|
Category,
|
||||||
|
Book,
|
||||||
ImportQifWizardStart,
|
ImportQifWizardStart,
|
||||||
ImportQifWizardInfo,
|
ImportQifWizardInfo,
|
||||||
module='cashbook_dataexchange', type_='model')
|
module='cashbook_dataexchange', type_='model')
|
||||||
|
|
52
book.py
Normal file
52
book.py
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
# -*- 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, PoolMeta
|
||||||
|
|
||||||
|
|
||||||
|
class Book(metaclass=PoolMeta):
|
||||||
|
__name__ = 'cashbook.book'
|
||||||
|
|
||||||
|
# ~ @classmethod
|
||||||
|
# ~ def export_as_qif(cls):
|
||||||
|
# ~ """ export all transactions as QIF
|
||||||
|
# ~ """
|
||||||
|
# ~ pool = Pool()
|
||||||
|
# ~ Category2 = pool.get('cashbook.category')
|
||||||
|
# ~ QifTool = pool.get('cashbook_dataexchange.qiftool')
|
||||||
|
|
||||||
|
# ~ categories = Category2.search([],
|
||||||
|
# ~ order=[('cattype', 'ASC'), ('rec_name', 'ASC')])
|
||||||
|
|
||||||
|
# ~ export = ['!Type:Cat']
|
||||||
|
# ~ export.extend([QifTool.qif_export_category(x) for x in categories])
|
||||||
|
# ~ return '\n'.join(export)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_from_qif(cls, book, qifdata):
|
||||||
|
""" add transactions from QIF-File-content
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
QifTool = pool.get('cashbook_dataexchange.qiftool')
|
||||||
|
Book2 = pool.get('cashbook.book')
|
||||||
|
|
||||||
|
qif_content = QifTool.split_by_type(qifdata)
|
||||||
|
if not 'Bank' in qif_content.keys():
|
||||||
|
return None
|
||||||
|
|
||||||
|
(to_create, msg_list) = QifTool.convert_transactions_to_create(
|
||||||
|
QifTool.qif_read_transactions(qif_content['Bank'])
|
||||||
|
)
|
||||||
|
if msg_list == []:
|
||||||
|
Book2.write(*[
|
||||||
|
[book],
|
||||||
|
{
|
||||||
|
'lines': [('create', to_create)],
|
||||||
|
}])
|
||||||
|
return [book]
|
||||||
|
return None
|
||||||
|
|
||||||
|
# end Category
|
52
locale/de.po
52
locale/de.po
|
@ -10,6 +10,38 @@ msgctxt "model:ir.message,text:msg_wiz_categories_found"
|
||||||
msgid "The following categories are now imported:\n%(categories)s"
|
msgid "The following categories are now imported:\n%(categories)s"
|
||||||
msgstr "Die folgenden Kategorien werden nun importiert:\n%(categories)s"
|
msgstr "Die folgenden Kategorien werden nun importiert:\n%(categories)s"
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,text:msg_wiz_transactions_found"
|
||||||
|
msgid "The following transactionen are now imported:\nBalance: %(balance)s\nNumber of transactions: %(quantity)s"
|
||||||
|
msgstr "Die folgenden Transaktionen werden nun importiert:\nSaldo: %(balance)s\nAnzahl Transactionen: %(quantity)s"
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,name:msg_wiz_no_categories"
|
||||||
|
msgid "No categories were found in the file."
|
||||||
|
msgstr "In der Datei wurden keine Kategorien gefunden."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,name:msg_wiz_no_bank"
|
||||||
|
msgid "No transactions were found in the file."
|
||||||
|
msgstr "In der Datei wurden keine Transaktionen gefunden."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,name:mds_import_category_notfound"
|
||||||
|
msgid "The category '%(catname)s' (Type: %(cattype)s) was not found."
|
||||||
|
msgstr "Die Kategorie '%(catname)s' (Typ: %(cattype)s) wurde nicht gefunden."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,name:mds_import_many_categories_found"
|
||||||
|
msgid "For the category '%(catname1)s' (type: '%(cattype)s') of the import, several categories were found in the system. Use: '%(catname2)s'"
|
||||||
|
msgstr "Für die Kategorie '%(catname1)s' (Typ: '%(cattype)s') des Imports wurden mehrere Kategorien im System gefunden. Verwende: '%(catname2)s'"
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,name:mds_import_checknumber"
|
||||||
|
msgid "Cheque No."
|
||||||
|
msgstr "Scheck-Nr:"
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,name:mds_import_address"
|
||||||
|
msgid "Address"
|
||||||
|
msgstr "Adresse"
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,name:msg_wiz_transactions_error"
|
||||||
|
msgid "When reading the QIF file, there were the following problems:"
|
||||||
|
msgstr "Beim Einlesen der QIF-Datei gab es folgende Probleme:"
|
||||||
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# ir.action #
|
# ir.action #
|
||||||
|
@ -22,10 +54,6 @@ msgctxt "model:ir.action,name:qif_category_report"
|
||||||
msgid "Export QIF-File"
|
msgid "Export QIF-File"
|
||||||
msgstr "QIF-Datei exportieren"
|
msgstr "QIF-Datei exportieren"
|
||||||
|
|
||||||
msgctxt "model:ir.action,name:msg_wiz_no_categories"
|
|
||||||
msgid "No categories were found in the file."
|
|
||||||
msgstr "In der Datei wurden keine Kategorien gefunden."
|
|
||||||
|
|
||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
# cashbook_dataexchange.qif_imp_wiz #
|
# cashbook_dataexchange.qif_imp_wiz #
|
||||||
|
@ -47,8 +75,8 @@ msgid "Cancel"
|
||||||
msgstr "Abbruch"
|
msgstr "Abbruch"
|
||||||
|
|
||||||
msgctxt "wizard_button:cashbook_dataexchange.qif_imp_wiz,showinfo,importf:"
|
msgctxt "wizard_button:cashbook_dataexchange.qif_imp_wiz,showinfo,importf:"
|
||||||
msgid "Import Categories"
|
msgid "Import Data"
|
||||||
msgstr "Kategorien importieren"
|
msgstr "Daten Kategorien"
|
||||||
|
|
||||||
|
|
||||||
###########################################
|
###########################################
|
||||||
|
@ -62,6 +90,10 @@ msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,company:"
|
||||||
msgid "Company"
|
msgid "Company"
|
||||||
msgstr "Unternehmen"
|
msgstr "Unternehmen"
|
||||||
|
|
||||||
|
msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,book:"
|
||||||
|
msgid "Cashbook"
|
||||||
|
msgstr "Kassenbuch"
|
||||||
|
|
||||||
msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,file_:"
|
msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,file_:"
|
||||||
msgid "QIF-File"
|
msgid "QIF-File"
|
||||||
msgstr "QIF-Datei"
|
msgstr "QIF-Datei"
|
||||||
|
@ -82,10 +114,14 @@ msgctxt "view:cashbook_dataexchange.qif_imp_wiz.info:"
|
||||||
msgid "Information"
|
msgid "Information"
|
||||||
msgstr "Information"
|
msgstr "Information"
|
||||||
|
|
||||||
msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,company:"
|
msgctxt "field:cashbook_dataexchange.qif_imp_wiz.info,book:"
|
||||||
|
msgid "Cashbook"
|
||||||
|
msgstr "Kassenbuch"
|
||||||
|
|
||||||
|
msgctxt "field:cashbook_dataexchange.qif_imp_wiz.info,company:"
|
||||||
msgid "Company"
|
msgid "Company"
|
||||||
msgstr "Unternehmen"
|
msgstr "Unternehmen"
|
||||||
|
|
||||||
msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,info:"
|
msgctxt "field:cashbook_dataexchange.qif_imp_wiz.info,info:"
|
||||||
msgid "Information"
|
msgid "Information"
|
||||||
msgstr "Information"
|
msgstr "Information"
|
||||||
|
|
72
locale/en.po
72
locale/en.po
|
@ -2,10 +2,50 @@
|
||||||
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_wiz_categories_found"
|
||||||
|
msgid "The following categories are now imported:\n%(categories)s"
|
||||||
|
msgstr "The following categories are now imported:\n%(categories)s"
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,text:msg_wiz_transactions_found"
|
||||||
|
msgid "The following transactionen are now imported:\nBalance: %(balance)s\nNumber of transactions: %(quantity)s"
|
||||||
|
msgstr "The following transactionen are now imported:\nBalance: %(balance)s\nNumber of transactions: %(quantity)s"
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,name:msg_wiz_no_categories"
|
||||||
|
msgid "No categories were found in the file."
|
||||||
|
msgstr "No categories were found in the file."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,name:msg_wiz_no_bank"
|
||||||
|
msgid "No transactions were found in the file."
|
||||||
|
msgstr "No transactions were found in the file."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,name:mds_import_category_notfound"
|
||||||
|
msgid "The category '%(catname)s' (Type: %(cattype)s) was not found."
|
||||||
|
msgstr "The category '%(catname)s' (Type: %(cattype)s) was not found."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,name:mds_import_many_categories_found"
|
||||||
|
msgid "For the category '%(catname1)s' (type: '%(cattype)s') of the import, several categories were found in the system. Use: '%(catname2)s'"
|
||||||
|
msgstr "For the category '%(catname1)s' (type: '%(cattype)s') of the import, several categories were found in the system. Use: '%(catname2)s'"
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,name:mds_import_checknumber"
|
||||||
|
msgid "Cheque No."
|
||||||
|
msgstr "Cheque No."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,name:mds_import_address"
|
||||||
|
msgid "Address"
|
||||||
|
msgstr "Address"
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,name:msg_wiz_transactions_error"
|
||||||
|
msgid "When reading the QIF file, there were the following problems:"
|
||||||
|
msgstr "When reading the QIF file, there were the following problems:"
|
||||||
|
|
||||||
msgctxt "model:ir.action,name:act_import_qif_wizard"
|
msgctxt "model:ir.action,name:act_import_qif_wizard"
|
||||||
msgid "Import QIF-File"
|
msgid "Import QIF-File"
|
||||||
msgstr "Import QIF-File"
|
msgstr "Import QIF-File"
|
||||||
|
|
||||||
|
msgctxt "model:ir.action,name:qif_category_report"
|
||||||
|
msgid "Export QIF-File"
|
||||||
|
msgstr "Export QIF-File"
|
||||||
|
|
||||||
msgctxt "model:cashbook_dataexchange.qif_imp_wiz,name:"
|
msgctxt "model:cashbook_dataexchange.qif_imp_wiz,name:"
|
||||||
msgid "Import QIF-File"
|
msgid "Import QIF-File"
|
||||||
msgstr "Import QIF-File"
|
msgstr "Import QIF-File"
|
||||||
|
@ -18,6 +58,14 @@ msgctxt "wizard_button:cashbook_dataexchange.qif_imp_wiz,start,readf:"
|
||||||
msgid "Read File"
|
msgid "Read File"
|
||||||
msgstr "Read File"
|
msgstr "Read File"
|
||||||
|
|
||||||
|
msgctxt "wizard_button:cashbook_dataexchange.qif_imp_wiz,showinfo,end:"
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "Cancel"
|
||||||
|
|
||||||
|
msgctxt "wizard_button:cashbook_dataexchange.qif_imp_wiz,showinfo,importf:"
|
||||||
|
msgid "Import Data"
|
||||||
|
msgstr "Import Data"
|
||||||
|
|
||||||
msgctxt "model:cashbook_dataexchange.qif_imp_wiz.start,name:"
|
msgctxt "model:cashbook_dataexchange.qif_imp_wiz.start,name:"
|
||||||
msgid "Import QIF-File"
|
msgid "Import QIF-File"
|
||||||
msgstr "Import QIF-File"
|
msgstr "Import QIF-File"
|
||||||
|
@ -26,7 +74,31 @@ msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,company:"
|
||||||
msgid "Company"
|
msgid "Company"
|
||||||
msgstr "Company"
|
msgstr "Company"
|
||||||
|
|
||||||
|
msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,book:"
|
||||||
|
msgid "Cashbook"
|
||||||
|
msgstr "Cashbook"
|
||||||
|
|
||||||
msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,file_:"
|
msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,file_:"
|
||||||
msgid "QIF-File"
|
msgid "QIF-File"
|
||||||
msgstr "QIF-File"
|
msgstr "QIF-File"
|
||||||
|
|
||||||
|
msgctxt "help:cashbook_dataexchange.qif_imp_wiz.start,file_:"
|
||||||
|
msgid "Quicken Interchange Format"
|
||||||
|
msgstr "Quicken Interchange Format"
|
||||||
|
|
||||||
|
msgctxt "model:cashbook_dataexchange.qif_imp_wiz.info,name:"
|
||||||
|
msgid "Import QIF-File"
|
||||||
|
msgstr "Import QIF-File"
|
||||||
|
|
||||||
|
msgctxt "view:cashbook_dataexchange.qif_imp_wiz.info:"
|
||||||
|
msgid "Information"
|
||||||
|
msgstr "Information"
|
||||||
|
|
||||||
|
msgctxt "field:cashbook_dataexchange.qif_imp_wiz.info,book:"
|
||||||
|
msgid "Cashbook"
|
||||||
|
msgstr "Cashbook"
|
||||||
|
|
||||||
|
msgctxt "field:cashbook_dataexchange.qif_imp_wiz.info,company:"
|
||||||
|
msgid "Company"
|
||||||
|
msgstr "Company"
|
||||||
|
|
||||||
|
|
22
message.xml
22
message.xml
|
@ -8,10 +8,30 @@ full copyright notices and license terms. -->
|
||||||
<record model="ir.message" id="msg_wiz_categories_found">
|
<record model="ir.message" id="msg_wiz_categories_found">
|
||||||
<field name="text">The following categories are now imported:\n%(categories)s</field>
|
<field name="text">The following categories are now imported:\n%(categories)s</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.message" id="msg_wiz_no_categories">
|
<record model="ir.message" id="msg_wiz_no_categories">
|
||||||
<field name="text">No categories were found in the file.</field>
|
<field name="text">No categories were found in the file.</field>
|
||||||
</record>
|
</record>
|
||||||
|
<record model="ir.message" id="msg_wiz_no_bank">
|
||||||
|
<field name="text">No transactions were found in the file.</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_wiz_transactions_found">
|
||||||
|
<field name="text">The following transactionen are now imported:\nBalance: %(balance)s\nNumber of transactions: %(quantity)s</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_wiz_transactions_error">
|
||||||
|
<field name="text">When reading the QIF file, there were the following problems:</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="mds_import_category_notfound">
|
||||||
|
<field name="text">The category '%(catname)s' (Type: %(cattype)s) was not found.</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="mds_import_many_categories_found">
|
||||||
|
<field name="text">For the category '%(catname1)s' (type: '%(cattype)s') of the import, several categories were found in the system. Use: '%(catname2)s'</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="mds_import_checknumber">
|
||||||
|
<field name="text">Cheque No.</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="mds_import_address">
|
||||||
|
<field name="text">Address</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</tryton>
|
</tryton>
|
||||||
|
|
|
@ -9,6 +9,9 @@ from trytond.model import ModelView, fields
|
||||||
from trytond.wizard import Wizard, StateTransition, StateView, Button
|
from trytond.wizard import Wizard, StateTransition, StateView, Button
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
from trytond.i18n import gettext
|
from trytond.i18n import gettext
|
||||||
|
from trytond.pyson import Eval, Bool
|
||||||
|
from trytond.report import Report
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
|
||||||
class ImportQifWizardStart(ModelView):
|
class ImportQifWizardStart(ModelView):
|
||||||
|
@ -18,6 +21,11 @@ class ImportQifWizardStart(ModelView):
|
||||||
company = fields.Many2One(model_name='company.company',
|
company = fields.Many2One(model_name='company.company',
|
||||||
string="Company", required=True,
|
string="Company", required=True,
|
||||||
states={'invisible': True})
|
states={'invisible': True})
|
||||||
|
book = fields.Many2One(string='Cashbook', readonly=True,
|
||||||
|
model_name='cashbook.book',
|
||||||
|
states={
|
||||||
|
'invisible': ~Bool(Eval('book')),
|
||||||
|
})
|
||||||
file_ = fields.Binary(string="QIF-File", required=True,
|
file_ = fields.Binary(string="QIF-File", required=True,
|
||||||
help='Quicken Interchange Format')
|
help='Quicken Interchange Format')
|
||||||
|
|
||||||
|
@ -35,6 +43,13 @@ class ImportQifWizardInfo(ModelView):
|
||||||
company = fields.Many2One(model_name='company.company',
|
company = fields.Many2One(model_name='company.company',
|
||||||
string="Company", required=True,
|
string="Company", required=True,
|
||||||
states={'invisible': True})
|
states={'invisible': True})
|
||||||
|
book = fields.Many2One(string='Cash Book', readonly=True,
|
||||||
|
model_name='cashbook.book',
|
||||||
|
states={
|
||||||
|
'invisible': ~Bool(Eval('book')),
|
||||||
|
})
|
||||||
|
allowimport = fields.Boolean(string='Import Enabled',
|
||||||
|
states={'invisible': True})
|
||||||
info = fields.Text(string='Information', readonly=True)
|
info = fields.Text(string='Information', readonly=True)
|
||||||
|
|
||||||
# end ImportQifWizardInfo
|
# end ImportQifWizardInfo
|
||||||
|
@ -55,18 +70,38 @@ class ImportQifWizard(Wizard):
|
||||||
view='cashbook_dataexchange.qif_imp_wiz_info_form', \
|
view='cashbook_dataexchange.qif_imp_wiz_info_form', \
|
||||||
buttons=[
|
buttons=[
|
||||||
Button(string='Cancel', state='end', icon='tryton-cancel'),
|
Button(string='Cancel', state='end', icon='tryton-cancel'),
|
||||||
Button(string='Import Categories', state='importf', icon='tryton-import', default=True),
|
Button(string='Import Data', state='importf', icon='tryton-import', default=True,
|
||||||
|
states={
|
||||||
|
'readonly': Eval('allowimport', False) == False,
|
||||||
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
readf = StateTransition()
|
readf = StateTransition()
|
||||||
importf = StateTransition()
|
importf = StateTransition()
|
||||||
|
|
||||||
|
def default_start(self, fields):
|
||||||
|
""" show book, company
|
||||||
|
"""
|
||||||
|
context = Transaction().context
|
||||||
|
|
||||||
|
values = {
|
||||||
|
'company': Transaction().context.get('company'),
|
||||||
|
'book': None,
|
||||||
|
}
|
||||||
|
|
||||||
|
model = context.get('active_model', '')
|
||||||
|
if model == 'cashbook.book':
|
||||||
|
values['book'] = context.get('active_id', None)
|
||||||
|
return values
|
||||||
|
|
||||||
def default_showinfo(self, fields):
|
def default_showinfo(self, fields):
|
||||||
""" show import-info
|
""" show import-info
|
||||||
"""
|
"""
|
||||||
values = {
|
values = {
|
||||||
'company': self.start.company.id,
|
'company': self.start.company.id,
|
||||||
'info': getattr(self.showinfo, 'info', None),
|
'info': getattr(self.showinfo, 'info', None),
|
||||||
|
'book': getattr(getattr(self.start, 'book', None), 'id', None),
|
||||||
|
'allowimport': getattr(self.showinfo, 'allowimport', False),
|
||||||
}
|
}
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
@ -74,13 +109,14 @@ class ImportQifWizard(Wizard):
|
||||||
""" read file, show number of objects
|
""" read file, show number of objects
|
||||||
"""
|
"""
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
QitTool = pool.get('cashbook_dataexchange.qiftool')
|
QifTool = pool.get('cashbook_dataexchange.qiftool')
|
||||||
|
|
||||||
model = Transaction().context.get('active_model', '')
|
model = Transaction().context.get('active_model', '')
|
||||||
file_content = None
|
file_content = None
|
||||||
if isinstance(self.start.file_, bytes):
|
if isinstance(self.start.file_, bytes):
|
||||||
file_content = self.start.file_.decode('utf8')
|
file_content = self.start.file_.decode('utf8')
|
||||||
|
|
||||||
|
self.showinfo.allowimport = False
|
||||||
if model == 'cashbook.category':
|
if model == 'cashbook.category':
|
||||||
def get_catlist(catlist, parent_name=None):
|
def get_catlist(catlist, parent_name=None):
|
||||||
""" generate list of categories
|
""" generate list of categories
|
||||||
|
@ -97,9 +133,9 @@ class ImportQifWizard(Wizard):
|
||||||
return names
|
return names
|
||||||
|
|
||||||
# read file content, extract categories
|
# read file content, extract categories
|
||||||
qif_content = QitTool.split_by_type(file_content)
|
qif_content = QifTool.split_by_type(file_content)
|
||||||
if 'Cat' in qif_content.keys():
|
if 'Cat' in qif_content.keys():
|
||||||
categories = QitTool.qif_read_categories(qif_content['Cat'])
|
categories = QifTool.qif_read_categories(qif_content['Cat'])
|
||||||
self.showinfo.info = gettext(
|
self.showinfo.info = gettext(
|
||||||
'cashbook_dataexchange.msg_wiz_categories_found',
|
'cashbook_dataexchange.msg_wiz_categories_found',
|
||||||
categories = '\n'.join(
|
categories = '\n'.join(
|
||||||
|
@ -109,8 +145,40 @@ class ImportQifWizard(Wizard):
|
||||||
['%s (out)' % x for x in get_catlist(categories['out'], None)]
|
['%s (out)' % x for x in get_catlist(categories['out'], None)]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
self.showinfo.allowimport = True
|
||||||
else :
|
else :
|
||||||
self.showinfo.info = gettext('cashbook_dataexchange.msg_wiz_no_categories')
|
self.showinfo.info = gettext('cashbook_dataexchange.msg_wiz_no_categories')
|
||||||
|
elif model == 'cashbook.book':
|
||||||
|
# read file content, extract categories
|
||||||
|
qif_content = QifTool.split_by_type(file_content)
|
||||||
|
if 'Bank' in qif_content.keys():
|
||||||
|
(to_create, msg_list) = QifTool.convert_transactions_to_create(
|
||||||
|
QifTool.qif_read_transactions(qif_content['Bank'])
|
||||||
|
)
|
||||||
|
if len(msg_list) > 0:
|
||||||
|
short_lst = []
|
||||||
|
for x in msg_list:
|
||||||
|
if x not in short_lst:
|
||||||
|
short_lst.append(x)
|
||||||
|
|
||||||
|
self.showinfo.info = '%s\n\n%s' % (
|
||||||
|
gettext('cashbook_dataexchange.msg_wiz_transactions_error'),
|
||||||
|
'\n'.join(short_lst),
|
||||||
|
)
|
||||||
|
else :
|
||||||
|
# count
|
||||||
|
balance = sum([
|
||||||
|
x['amount'] \
|
||||||
|
if x['bookingtype'] in ['in', 'spin'] else x['amount'].copy_sign(Decimal('-1.0')) \
|
||||||
|
for x in to_create])
|
||||||
|
self.showinfo.info = gettext(
|
||||||
|
'cashbook_dataexchange.msg_wiz_transactions_found',
|
||||||
|
quantity = len(to_create),
|
||||||
|
balance = Report.format_currency(balance, None, self.start.book.currency),
|
||||||
|
)
|
||||||
|
self.showinfo.allowimport = True
|
||||||
|
else :
|
||||||
|
self.showinfo.info = gettext('cashbook_dataexchange.msg_wiz_no_bank')
|
||||||
|
|
||||||
return 'showinfo'
|
return 'showinfo'
|
||||||
|
|
||||||
|
@ -119,6 +187,7 @@ class ImportQifWizard(Wizard):
|
||||||
"""
|
"""
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
Category = pool.get('cashbook.category')
|
Category = pool.get('cashbook.category')
|
||||||
|
Book = pool.get('cashbook.book')
|
||||||
|
|
||||||
model = Transaction().context.get('active_model', '')
|
model = Transaction().context.get('active_model', '')
|
||||||
file_content = None
|
file_content = None
|
||||||
|
@ -128,7 +197,9 @@ class ImportQifWizard(Wizard):
|
||||||
if model == 'cashbook.category':
|
if model == 'cashbook.category':
|
||||||
if file_content:
|
if file_content:
|
||||||
records = Category.create_from_qif(file_content)
|
records = Category.create_from_qif(file_content)
|
||||||
|
elif model == 'cashbook.book':
|
||||||
|
if file_content:
|
||||||
|
Book.create_from_qif(self.showinfo.book, file_content)
|
||||||
return 'end'
|
return 'end'
|
||||||
|
|
||||||
# end ImportQifWizard
|
# end ImportQifWizard
|
||||||
|
|
|
@ -29,5 +29,12 @@ full copyright notices and license terms. -->
|
||||||
<field name="action" ref="act_import_qif_wizard"/>
|
<field name="action" ref="act_import_qif_wizard"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<!-- import transactions -->
|
||||||
|
<record model="ir.action.keyword" id="act_import_qif_wizard-book-keyword">
|
||||||
|
<field name="keyword">form_action</field>
|
||||||
|
<field name="model">cashbook.book,-1</field>
|
||||||
|
<field name="action" ref="act_import_qif_wizard"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</tryton>
|
</tryton>
|
||||||
|
|
186
qiftool.py
186
qiftool.py
|
@ -5,6 +5,9 @@
|
||||||
|
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from trytond.model import Model
|
from trytond.model import Model
|
||||||
|
from trytond.i18n import gettext
|
||||||
|
from decimal import Decimal
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
class QifTool(Model):
|
class QifTool(Model):
|
||||||
|
@ -34,6 +37,189 @@ class QifTool(Model):
|
||||||
blocks[block] = '\n'.join(blocks[block])
|
blocks[block] = '\n'.join(blocks[block])
|
||||||
return blocks
|
return blocks
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_amount_from_txt(cls, amount_txt):
|
||||||
|
""" convert text to Decimal
|
||||||
|
"""
|
||||||
|
if (',' in amount_txt) and (amount_txt[-3] == '.'):
|
||||||
|
# '.' = decimal, ',' = tousand
|
||||||
|
amount_txt = amount_txt.replace(',', '.')
|
||||||
|
elif ('.' in amount_txt) and (amount_txt[-3] == ','):
|
||||||
|
# ',' = decimal, '.' = tousand
|
||||||
|
amount_txt = amount_txt.replace('.', '')
|
||||||
|
amount_txt = amount_txt.replace(',', '.')
|
||||||
|
elif ',' in amount_txt:
|
||||||
|
amount_txt = amount_txt.replace(',', '.')
|
||||||
|
return Decimal(amount_txt)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def qif_read_transactions(cls, transactiondata):
|
||||||
|
""" read transactions from text
|
||||||
|
result: [{
|
||||||
|
'split': [{
|
||||||
|
'amount': <Decimal>,
|
||||||
|
'description': 'purpose',
|
||||||
|
'category': 'name of categroy',
|
||||||
|
},...],
|
||||||
|
'date': <date of transaction>,
|
||||||
|
'amount': <Decimal>,
|
||||||
|
'party': 'name of party',
|
||||||
|
'address': 'address of party',
|
||||||
|
'checknumber': 'number',
|
||||||
|
'description': 'purpose',
|
||||||
|
'state': 'check|edit',
|
||||||
|
'account': 'name of cashbook',
|
||||||
|
'category': 'name of category',
|
||||||
|
}, ...]
|
||||||
|
"""
|
||||||
|
result = []
|
||||||
|
for booktxt in transactiondata.split('^'):
|
||||||
|
if len(booktxt.strip()) == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
booking = {'split': []}
|
||||||
|
for line in booktxt.strip().split('\n'):
|
||||||
|
line_txt = line[1:].strip()
|
||||||
|
if line.startswith('D'): # date
|
||||||
|
booking['date'] = datetime.strptime(line_txt, '%d.%m.%Y').date()
|
||||||
|
elif line.startswith('T'): # total
|
||||||
|
booking['amount'] = cls.get_amount_from_txt(line_txt)
|
||||||
|
elif line.startswith('U'): # total
|
||||||
|
booking['amount'] = cls.get_amount_from_txt(line_txt)
|
||||||
|
elif line.startswith('P'): # party
|
||||||
|
booking['party'] = line_txt
|
||||||
|
elif line.startswith('A'): # address
|
||||||
|
booking['address'] = line_txt
|
||||||
|
elif line.startswith('N'): # address
|
||||||
|
booking['checknumber'] = line_txt
|
||||||
|
elif line.startswith('M'): # memo
|
||||||
|
booking['description'] = line_txt
|
||||||
|
elif line.startswith('C'): # state
|
||||||
|
booking['state'] = {
|
||||||
|
'X': 'check',
|
||||||
|
'*': 'edit',
|
||||||
|
}.get(line_txt, 'edit')
|
||||||
|
elif line.startswith('L'): # category, account
|
||||||
|
if line_txt.startswith('[') and line_txt.endswith(']'):
|
||||||
|
booking['account'] = line_txt[1:-1]
|
||||||
|
else :
|
||||||
|
booking['category'] = line_txt
|
||||||
|
elif line.startswith('S'): # split: category
|
||||||
|
booking['split'].append({
|
||||||
|
'category': line_txt,
|
||||||
|
})
|
||||||
|
elif line.startswith('E'): # split: memo
|
||||||
|
booking['split'][-1]['description'] = line_txt
|
||||||
|
elif line.startswith('$'): # split: amount
|
||||||
|
booking['split'][-1]['amount'] = cls.get_amount_from_txt(line_txt)
|
||||||
|
elif line.startswith('£'): # split: amount
|
||||||
|
booking['split'][-1]['amount'] = cls.get_amount_from_txt(line_txt)
|
||||||
|
else :
|
||||||
|
raise ValueError('unknown line-code: %s' % (line))
|
||||||
|
result.append(booking)
|
||||||
|
return result
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_category_by_name(cls, catname, cattype):
|
||||||
|
""" find category
|
||||||
|
"""
|
||||||
|
Category = Pool().get('cashbook.category')
|
||||||
|
|
||||||
|
cat_id = None
|
||||||
|
msg_txt = None
|
||||||
|
categories = Category.search([
|
||||||
|
('cattype', '=', cattype),
|
||||||
|
('rec_name', '=', catname.replace(':', '/')),
|
||||||
|
])
|
||||||
|
if len(categories) == 1:
|
||||||
|
cat_id = categories[0].id
|
||||||
|
elif len(categories) == 0:
|
||||||
|
msg_txt = gettext(
|
||||||
|
'cashbook_dataexchange.mds_import_category_notfound',
|
||||||
|
catname = catname,
|
||||||
|
cattype = cattype,
|
||||||
|
)
|
||||||
|
else :
|
||||||
|
msg_txt = gettext(
|
||||||
|
'cashbook_dataexchange.mds_import_many_categories_found',
|
||||||
|
catname1 = catname,
|
||||||
|
catname2 = categories[0].rec_name,
|
||||||
|
cattype = cattype,
|
||||||
|
)
|
||||||
|
cat_id = categories[0].id
|
||||||
|
return (cat_id, msg_txt)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def convert_transactions_to_create(cls, transactions, split2edit=True):
|
||||||
|
""" convert read transactions to create-command
|
||||||
|
split2edit: True = split-bokings are 'edit', False = dont change
|
||||||
|
"""
|
||||||
|
to_create = []
|
||||||
|
msg_list = []
|
||||||
|
for transaction in transactions:
|
||||||
|
line = {x:transaction[x] for x in [
|
||||||
|
'date', 'amount', 'description', 'state',
|
||||||
|
] if x in transaction.keys()}
|
||||||
|
|
||||||
|
if len(transaction['split']) > 0:
|
||||||
|
if line['amount'] >= Decimal('0.0'):
|
||||||
|
line['bookingtype'] = 'spin'
|
||||||
|
else :
|
||||||
|
line['bookingtype'] = 'spout'
|
||||||
|
line['amount'] = line['amount'].copy_sign(Decimal('1.0'))
|
||||||
|
else :
|
||||||
|
if line['amount'] >= Decimal('0.0'):
|
||||||
|
line['bookingtype'] = 'in'
|
||||||
|
else :
|
||||||
|
line['bookingtype'] = 'out'
|
||||||
|
line['amount'] = line['amount'].copy_sign(Decimal('1.0'))
|
||||||
|
|
||||||
|
# store 'account' like 'category'
|
||||||
|
cat_name = transaction.get('category', transaction.get('account', None))
|
||||||
|
cat_type = 'in' if line['bookingtype'] in ['in', 'spin'] else 'out'
|
||||||
|
if cat_name is not None:
|
||||||
|
(cat_id, msg_txt) = cls.get_category_by_name(cat_name, cat_type)
|
||||||
|
if cat_id is None:
|
||||||
|
msg_list.append(msg_txt)
|
||||||
|
continue
|
||||||
|
else :
|
||||||
|
line['category'] = cat_id
|
||||||
|
if msg_txt is not None:
|
||||||
|
msg_list.append(msg_txt)
|
||||||
|
|
||||||
|
for x in ['address', 'checknumber']:
|
||||||
|
if x in transaction.keys():
|
||||||
|
line['description'] = ', '.join([
|
||||||
|
line.get('description', ''),
|
||||||
|
'%s %s' % (
|
||||||
|
gettext('cashbook_dataexchange.mds_import_%s' % x),
|
||||||
|
transaction[x]
|
||||||
|
),
|
||||||
|
])
|
||||||
|
|
||||||
|
split_lines = []
|
||||||
|
for sp_line in transaction['split']:
|
||||||
|
(cat_id, msg_txt) = cls.get_category_by_name(sp_line['category'], cat_type)
|
||||||
|
|
||||||
|
if msg_txt is not None:
|
||||||
|
msg_list.append(msg_txt)
|
||||||
|
|
||||||
|
if cat_id is not None:
|
||||||
|
split_lines.append({
|
||||||
|
'amount': sp_line['amount'].copy_sign(Decimal('1.0')),
|
||||||
|
'description': sp_line.get('description', None),
|
||||||
|
'category': cat_id,
|
||||||
|
})
|
||||||
|
if len(split_lines) > 0:
|
||||||
|
line['splitlines'] = [('create', split_lines)]
|
||||||
|
|
||||||
|
if split2edit == True:
|
||||||
|
if 'splitlines' in line.keys():
|
||||||
|
line['state'] = 'edit'
|
||||||
|
|
||||||
|
to_create.append(line)
|
||||||
|
return (to_create, msg_list)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def qif_read_categories(cls, catdata):
|
def qif_read_categories(cls, catdata):
|
||||||
""" read categories from text
|
""" read categories from text
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
# The COPYRIGHT file at the top level of this repository contains the
|
# The COPYRIGHT file at the top level of this repository contains the
|
||||||
# full copyright notices and license terms.
|
# full copyright notices and license terms.
|
||||||
|
|
||||||
|
from datetime import date
|
||||||
|
from decimal import Decimal
|
||||||
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
|
@ -48,7 +50,7 @@ class CategoryTestCase(CashbookTestCase):
|
||||||
self.assertEqual(list(result.keys()), ['view'])
|
self.assertEqual(list(result.keys()), ['view'])
|
||||||
self.assertEqual(result['view']['defaults']['company'], company.id)
|
self.assertEqual(result['view']['defaults']['company'], company.id)
|
||||||
self.assertEqual(result['view']['defaults']['info'],
|
self.assertEqual(result['view']['defaults']['info'],
|
||||||
"""The following categories are now imported:\\n
|
"""The following categories are now imported:\n
|
||||||
Gehalt (in)
|
Gehalt (in)
|
||||||
Gehalt/Zulagen (in)
|
Gehalt/Zulagen (in)
|
||||||
|
|
||||||
|
@ -238,6 +240,175 @@ I
|
||||||
'PGA NR00002168 BLZ10000000 0\nL[S-Giro]\n^\nD05.12.2013\nCX\nMsome food\n'+
|
'PGA NR00002168 BLZ10000000 0\nL[S-Giro]\n^\nD05.12.2013\nCX\nMsome food\n'+
|
||||||
'T-56,37\nPFoodshop Zehlendorf\nLLebensmittel\n^\n')
|
'T-56,37\nPFoodshop Zehlendorf\nLLebensmittel\n^\n')
|
||||||
|
|
||||||
|
@with_transaction()
|
||||||
|
def test_qiftool_convert_transactions(self):
|
||||||
|
""" convert_transactions_to_create
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
QifTool = pool.get('cashbook_dataexchange.qiftool')
|
||||||
|
Category = pool.get('cashbook.category')
|
||||||
|
Book = pool.get('cashbook.book')
|
||||||
|
|
||||||
|
company = self.prep_company()
|
||||||
|
with Transaction().set_context({
|
||||||
|
'company': company.id,
|
||||||
|
}):
|
||||||
|
types = self.prep_type()
|
||||||
|
book, = Book.create([{
|
||||||
|
'name': 'Cash Book',
|
||||||
|
'btype': types.id,
|
||||||
|
'company': company.id,
|
||||||
|
'currency': company.currency.id,
|
||||||
|
'number_sequ': self.prep_sequence().id,
|
||||||
|
'start_date': date(2010, 1, 1),
|
||||||
|
'start_balance': Decimal('0.0'),
|
||||||
|
}])
|
||||||
|
self.assertEqual(book.name, 'Cash Book')
|
||||||
|
self.assertEqual(book.btype.rec_name, 'CAS - Cash')
|
||||||
|
|
||||||
|
Category.create([{
|
||||||
|
'name': 'Lebensmittel',
|
||||||
|
'cattype': 'out',
|
||||||
|
'company': company.id,
|
||||||
|
}, {
|
||||||
|
'name': 'Haushaltschemie',
|
||||||
|
'cattype': 'out',
|
||||||
|
'company': company.id,
|
||||||
|
}, {
|
||||||
|
'name': 'Kosmetik',
|
||||||
|
'cattype': 'out',
|
||||||
|
'company': company.id,
|
||||||
|
}, {
|
||||||
|
'name': 'S-Giro',
|
||||||
|
'cattype': 'in',
|
||||||
|
'company': company.id,
|
||||||
|
}, {
|
||||||
|
'name': 'Bargeld',
|
||||||
|
'cattype': 'in',
|
||||||
|
'company': company.id,
|
||||||
|
}, ])
|
||||||
|
|
||||||
|
tr_list = QifTool.qif_read_transactions('D04.12.2013\nT7,12\nCX\n'+
|
||||||
|
'POpening Balance\nL[Bargeld]\n^\nD05.12.2013\nCX\n'+
|
||||||
|
'M05.12/06.42UHR TT TELTOW\nT290,00\nPGA NR00002168 BLZ10000000 0\n'+
|
||||||
|
'L[S-Giro]\n^\nD05.12.2013\nCX\nMsome food\nT-56,37\n'+
|
||||||
|
'PFoodshop Zehlendorf\nLLebensmittel\n^\nD22.10.2020\n'+
|
||||||
|
'CX\nMLebensmittel\nT-55,84\nPreal,- Teltow\nLLebensmittel\n'+
|
||||||
|
'SLebensmittel\nELebensmittel\n$-49,36\nSKosmetik\nEKlopapier\n'+
|
||||||
|
'$-2,99\nSHaushaltschemie\nESagrotan\n$-3,49\n^\n')
|
||||||
|
|
||||||
|
(to_create, msg_txt) = QifTool.convert_transactions_to_create(tr_list)
|
||||||
|
self.assertEqual(msg_txt, [])
|
||||||
|
self.assertEqual(to_create, [{
|
||||||
|
'date': date(2013, 12, 4),
|
||||||
|
'amount': Decimal('7.12'),
|
||||||
|
'state': 'check',
|
||||||
|
'bookingtype': 'in',
|
||||||
|
'category': 74,
|
||||||
|
}, {
|
||||||
|
'date': date(2013, 12, 5),
|
||||||
|
'amount': Decimal('290.00'),
|
||||||
|
'description': '05.12/06.42UHR TT TELTOW',
|
||||||
|
'state': 'check',
|
||||||
|
'bookingtype': 'in',
|
||||||
|
'category': 73,
|
||||||
|
}, {
|
||||||
|
'date': date(2013, 12, 5),
|
||||||
|
'amount': Decimal('56.37'),
|
||||||
|
'description': 'some food',
|
||||||
|
'state': 'check',
|
||||||
|
'bookingtype': 'out',
|
||||||
|
'category': 70,
|
||||||
|
}, {
|
||||||
|
'date': date(2020, 10, 22),
|
||||||
|
'amount': Decimal('55.84'),
|
||||||
|
'description': 'Lebensmittel',
|
||||||
|
'state': 'edit',
|
||||||
|
'bookingtype': 'spout',
|
||||||
|
'category': 70,
|
||||||
|
'splitlines': [
|
||||||
|
('create', [{
|
||||||
|
'amount': Decimal('49.36'),
|
||||||
|
'description': 'Lebensmittel',
|
||||||
|
'category': 70,
|
||||||
|
}, {
|
||||||
|
'amount': Decimal('2.99'),
|
||||||
|
'description': 'Klopapier',
|
||||||
|
'category': 72,
|
||||||
|
}, {
|
||||||
|
'amount': Decimal('3.49'),
|
||||||
|
'description': 'Sagrotan',
|
||||||
|
'category': 71,
|
||||||
|
}],
|
||||||
|
)],
|
||||||
|
}])
|
||||||
|
Book.write(*[
|
||||||
|
[book],
|
||||||
|
{
|
||||||
|
'lines': [('create', to_create)],
|
||||||
|
}])
|
||||||
|
self.assertEqual(len(book.lines), 4)
|
||||||
|
self.assertEqual(book.balance, Decimal('184.91'))
|
||||||
|
|
||||||
|
@with_transaction()
|
||||||
|
def test_qiftool_read_transactions(self):
|
||||||
|
""" read transaction data from text
|
||||||
|
"""
|
||||||
|
QifTool = Pool().get('cashbook_dataexchange.qiftool')
|
||||||
|
|
||||||
|
result = QifTool.qif_read_transactions('D04.12.2013\nT7,12\nCX\n'+
|
||||||
|
'POpening Balance\nL[Bargeld]\n^\nD05.12.2013\nCX\n'+
|
||||||
|
'M05.12/06.42UHR TT TELTOW\nT290,00\nPGA NR00002168 BLZ10000000 0\n'+
|
||||||
|
'L[S-Giro]\n^\nD05.12.2013\nCX\nMsome food\nT-56,37\n'+
|
||||||
|
'PFoodshop Zehlendorf\nLLebensmittel\n^\nD22.10.2020\n'+
|
||||||
|
'CX\nMLebensmittel\nT-55,84\nPreal,- Teltow\nLLebensmittel\n'+
|
||||||
|
'SLebensmittel\nELebensmittel\n$-49,36\nSKosmetik\nEKlopapier\n'+
|
||||||
|
'$-2,99\nSHaushaltschemie\nESagrotan\n$-3,49\n^\n')
|
||||||
|
self.assertEqual(result, [{
|
||||||
|
'split': [],
|
||||||
|
'date': date(2013, 12, 4),
|
||||||
|
'amount': Decimal('7.12'),
|
||||||
|
'state': 'check',
|
||||||
|
'party': 'Opening Balance',
|
||||||
|
'account': 'Bargeld',
|
||||||
|
}, {
|
||||||
|
'split': [],
|
||||||
|
'date': date(2013, 12, 5),
|
||||||
|
'state': 'check',
|
||||||
|
'description': '05.12/06.42UHR TT TELTOW',
|
||||||
|
'amount': Decimal('290.00'),
|
||||||
|
'party': 'GA NR00002168 BLZ10000000 0',
|
||||||
|
'account': 'S-Giro',
|
||||||
|
}, {
|
||||||
|
'split': [],
|
||||||
|
'date': date(2013, 12, 5),
|
||||||
|
'state': 'check',
|
||||||
|
'description': 'some food',
|
||||||
|
'amount': Decimal('-56.37'),
|
||||||
|
'party': 'Foodshop Zehlendorf',
|
||||||
|
'category': 'Lebensmittel',
|
||||||
|
}, {
|
||||||
|
'split': [{
|
||||||
|
'category': 'Lebensmittel',
|
||||||
|
'description': 'Lebensmittel',
|
||||||
|
'amount': Decimal('-49.36'),
|
||||||
|
}, {
|
||||||
|
'category': 'Kosmetik',
|
||||||
|
'description': 'Klopapier',
|
||||||
|
'amount': Decimal('-2.99'),
|
||||||
|
}, {
|
||||||
|
'category': 'Haushaltschemie',
|
||||||
|
'description': 'Sagrotan',
|
||||||
|
'amount': Decimal('-3.49'),
|
||||||
|
}],
|
||||||
|
'date': date(2020, 10, 22),
|
||||||
|
'state': 'check',
|
||||||
|
'description': 'Lebensmittel',
|
||||||
|
'amount': Decimal('-55.84'),
|
||||||
|
'party': 'real,- Teltow',
|
||||||
|
'category': 'Lebensmittel',
|
||||||
|
}])
|
||||||
|
|
||||||
@with_transaction()
|
@with_transaction()
|
||||||
def test_qiftool_read_categories(self):
|
def test_qiftool_read_categories(self):
|
||||||
""" read category-data from text
|
""" read category-data from text
|
||||||
|
|
|
@ -5,9 +5,12 @@ full copyright notices and license terms. -->
|
||||||
<form col="2">
|
<form col="2">
|
||||||
<label name="company"/>
|
<label name="company"/>
|
||||||
<field name="company"/>
|
<field name="company"/>
|
||||||
|
<label name="book"/>
|
||||||
|
<field name="book"/>
|
||||||
|
|
||||||
<group col="1" name="info" colspan="2" string="Information" yexpand="1">
|
<group col="1" name="info" colspan="2" string="Information" yexpand="1">
|
||||||
<field name="info"/>
|
<field name="info"/>
|
||||||
</group>
|
</group>
|
||||||
|
<field name="allowimport"/>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -5,6 +5,8 @@ full copyright notices and license terms. -->
|
||||||
<form col="2">
|
<form col="2">
|
||||||
<label name="company"/>
|
<label name="company"/>
|
||||||
<field name="company"/>
|
<field name="company"/>
|
||||||
|
<label name="book"/>
|
||||||
|
<field name="book"/>
|
||||||
|
|
||||||
<label name="file_"/>
|
<label name="file_"/>
|
||||||
<field name="file_"/>
|
<field name="file_"/>
|
||||||
|
|
Loading…
Reference in a new issue