import der transaktionen begonnen

This commit is contained in:
Frederik Jaeckel 2022-09-01 14:48:04 +02:00
parent b50927753b
commit 0287452fe8
11 changed files with 637 additions and 15 deletions

View file

@ -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')

52
book.py Normal file
View 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

View file

@ -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"

View file

@ -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"

View file

@ -8,10 +8,30 @@ full copyright notices and license terms. -->
<record model="ir.message" id="msg_wiz_categories_found">
<field name="text">The following categories are now imported:\n%(categories)s</field>
</record>
<record model="ir.message" id="msg_wiz_no_categories">
<field name="text">No categories were found in the file.</field>
</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>
</tryton>

View file

@ -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

View file

@ -29,5 +29,12 @@ full copyright notices and license terms. -->
<field name="action" ref="act_import_qif_wizard"/>
</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>
</tryton>

View file

@ -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': <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
def qif_read_categories(cls, catdata):
""" read categories from text

View file

@ -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

View file

@ -5,9 +5,12 @@ full copyright notices and license terms. -->
<form col="2">
<label name="company"/>
<field name="company"/>
<label name="book"/>
<field name="book"/>
<group col="1" name="info" colspan="2" string="Information" yexpand="1">
<field name="info"/>
</group>
<field name="allowimport"/>
</form>

View file

@ -5,6 +5,8 @@ full copyright notices and license terms. -->
<form col="2">
<label name="company"/>
<field name="company"/>
<label name="book"/>
<field name="book"/>
<label name="file_"/>
<field name="file_"/>