diff --git a/__init__.py b/__init__.py
index d703d42..ed4330c 100644
--- a/__init__.py
+++ b/__init__.py
@@ -5,6 +5,7 @@
from trytond.pool import Pool
from .category import Category
+from .book import Book
from .qiftool import QifTool
from .qif_import_wiz import ImportQifWizard, ImportQifWizardStart, ImportQifWizardInfo
from .qif_export import QifCategoryExport
@@ -13,6 +14,7 @@ def register():
Pool.register(
QifTool,
Category,
+ Book,
ImportQifWizardStart,
ImportQifWizardInfo,
module='cashbook_dataexchange', type_='model')
diff --git a/book.py b/book.py
new file mode 100644
index 0000000..261cb64
--- /dev/null
+++ b/book.py
@@ -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
diff --git a/locale/de.po b/locale/de.po
index 730f94e..124fc7b 100644
--- a/locale/de.po
+++ b/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"
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 #
@@ -22,10 +54,6 @@ msgctxt "model:ir.action,name:qif_category_report"
msgid "Export QIF-File"
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 #
@@ -47,8 +75,8 @@ msgid "Cancel"
msgstr "Abbruch"
msgctxt "wizard_button:cashbook_dataexchange.qif_imp_wiz,showinfo,importf:"
-msgid "Import Categories"
-msgstr "Kategorien importieren"
+msgid "Import Data"
+msgstr "Daten Kategorien"
###########################################
@@ -62,6 +90,10 @@ msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,company:"
msgid "Company"
msgstr "Unternehmen"
+msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,book:"
+msgid "Cashbook"
+msgstr "Kassenbuch"
+
msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,file_:"
msgid "QIF-File"
msgstr "QIF-Datei"
@@ -82,10 +114,14 @@ msgctxt "view:cashbook_dataexchange.qif_imp_wiz.info:"
msgid "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"
msgstr "Unternehmen"
-msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,info:"
+msgctxt "field:cashbook_dataexchange.qif_imp_wiz.info,info:"
msgid "Information"
msgstr "Information"
diff --git a/locale/en.po b/locale/en.po
index df5fa3e..1bc2211 100644
--- a/locale/en.po
+++ b/locale/en.po
@@ -2,10 +2,50 @@
msgid ""
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"
msgid "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:"
msgid "Import QIF-File"
msgstr "Import QIF-File"
@@ -18,6 +58,14 @@ msgctxt "wizard_button:cashbook_dataexchange.qif_imp_wiz,start,readf:"
msgid "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:"
msgid "Import QIF-File"
msgstr "Import QIF-File"
@@ -26,7 +74,31 @@ msgctxt "field:cashbook_dataexchange.qif_imp_wiz.start,company:"
msgid "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_:"
msgid "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"
+
diff --git a/message.xml b/message.xml
index fe4a54e..b03a6a2 100644
--- a/message.xml
+++ b/message.xml
@@ -8,10 +8,30 @@ full copyright notices and license terms. -->
The following categories are now imported:\n%(categories)s
-
No categories were found in the file.
+
+ No transactions were found in the file.
+
+
+ The following transactionen are now imported:\nBalance: %(balance)s\nNumber of transactions: %(quantity)s
+
+
+ When reading the QIF file, there were the following problems:
+
+
+ The category '%(catname)s' (Type: %(cattype)s) was not found.
+
+
+ For the category '%(catname1)s' (type: '%(cattype)s') of the import, several categories were found in the system. Use: '%(catname2)s'
+
+
+ Cheque No.
+
+
+ Address
+
diff --git a/qif_import_wiz.py b/qif_import_wiz.py
index 0687533..ef50af0 100644
--- a/qif_import_wiz.py
+++ b/qif_import_wiz.py
@@ -9,6 +9,9 @@ from trytond.model import ModelView, fields
from trytond.wizard import Wizard, StateTransition, StateView, Button
from trytond.transaction import Transaction
from trytond.i18n import gettext
+from trytond.pyson import Eval, Bool
+from trytond.report import Report
+from decimal import Decimal
class ImportQifWizardStart(ModelView):
@@ -18,6 +21,11 @@ class ImportQifWizardStart(ModelView):
company = fields.Many2One(model_name='company.company',
string="Company", required=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,
help='Quicken Interchange Format')
@@ -35,6 +43,13 @@ class ImportQifWizardInfo(ModelView):
company = fields.Many2One(model_name='company.company',
string="Company", required=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)
# end ImportQifWizardInfo
@@ -55,18 +70,38 @@ class ImportQifWizard(Wizard):
view='cashbook_dataexchange.qif_imp_wiz_info_form', \
buttons=[
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()
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):
""" show import-info
"""
values = {
'company': self.start.company.id,
'info': getattr(self.showinfo, 'info', None),
+ 'book': getattr(getattr(self.start, 'book', None), 'id', None),
+ 'allowimport': getattr(self.showinfo, 'allowimport', False),
}
return values
@@ -74,13 +109,14 @@ class ImportQifWizard(Wizard):
""" read file, show number of objects
"""
pool = Pool()
- QitTool = pool.get('cashbook_dataexchange.qiftool')
+ QifTool = pool.get('cashbook_dataexchange.qiftool')
model = Transaction().context.get('active_model', '')
file_content = None
if isinstance(self.start.file_, bytes):
file_content = self.start.file_.decode('utf8')
+ self.showinfo.allowimport = False
if model == 'cashbook.category':
def get_catlist(catlist, parent_name=None):
""" generate list of categories
@@ -97,9 +133,9 @@ class ImportQifWizard(Wizard):
return names
# 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():
- categories = QitTool.qif_read_categories(qif_content['Cat'])
+ categories = QifTool.qif_read_categories(qif_content['Cat'])
self.showinfo.info = gettext(
'cashbook_dataexchange.msg_wiz_categories_found',
categories = '\n'.join(
@@ -109,8 +145,40 @@ class ImportQifWizard(Wizard):
['%s (out)' % x for x in get_catlist(categories['out'], None)]
)
)
+ self.showinfo.allowimport = True
else :
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'
@@ -119,6 +187,7 @@ class ImportQifWizard(Wizard):
"""
pool = Pool()
Category = pool.get('cashbook.category')
+ Book = pool.get('cashbook.book')
model = Transaction().context.get('active_model', '')
file_content = None
@@ -128,7 +197,9 @@ class ImportQifWizard(Wizard):
if model == 'cashbook.category':
if 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'
# end ImportQifWizard
diff --git a/qif_import_wiz.xml b/qif_import_wiz.xml
index f354c18..cb345e2 100644
--- a/qif_import_wiz.xml
+++ b/qif_import_wiz.xml
@@ -29,5 +29,12 @@ full copyright notices and license terms. -->
+
+
+ form_action
+ cashbook.book,-1
+
+
+
diff --git a/qiftool.py b/qiftool.py
index c00bdd2..29b454d 100644
--- a/qiftool.py
+++ b/qiftool.py
@@ -5,6 +5,9 @@
from trytond.pool import Pool
from trytond.model import Model
+from trytond.i18n import gettext
+from decimal import Decimal
+from datetime import datetime
class QifTool(Model):
@@ -34,6 +37,189 @@ class QifTool(Model):
blocks[block] = '\n'.join(blocks[block])
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': ,
+ 'description': 'purpose',
+ 'category': 'name of categroy',
+ },...],
+ 'date': ,
+ 'amount': ,
+ '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
def qif_read_categories(cls, catdata):
""" read categories from text
diff --git a/tests/test_category.py b/tests/test_category.py
index 1487cc9..7cb1b65 100644
--- a/tests/test_category.py
+++ b/tests/test_category.py
@@ -3,6 +3,8 @@
# The COPYRIGHT file at the top level of this repository contains the
# 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.pool import Pool
from trytond.transaction import Transaction
@@ -48,7 +50,7 @@ class CategoryTestCase(CashbookTestCase):
self.assertEqual(list(result.keys()), ['view'])
self.assertEqual(result['view']['defaults']['company'], company.id)
self.assertEqual(result['view']['defaults']['info'],
-"""The following categories are now imported:\\n
+"""The following categories are now imported:\n
Gehalt (in)
Gehalt/Zulagen (in)
@@ -238,6 +240,175 @@ I
'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_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()
def test_qiftool_read_categories(self):
""" read category-data from text
diff --git a/view/wiz_qifimport_info_form.xml b/view/wiz_qifimport_info_form.xml
index caff918..9b38048 100644
--- a/view/wiz_qifimport_info_form.xml
+++ b/view/wiz_qifimport_info_form.xml
@@ -5,9 +5,12 @@ full copyright notices and license terms. -->
diff --git a/view/wiz_qifimport_start_form.xml b/view/wiz_qifimport_start_form.xml
index 7c80dd1..52a4ee6 100644
--- a/view/wiz_qifimport_start_form.xml
+++ b/view/wiz_qifimport_start_form.xml
@@ -5,6 +5,8 @@ full copyright notices and license terms. -->