diff --git a/book.py b/book.py index 4c44c74..c1c9036 100644 --- a/book.py +++ b/book.py @@ -32,6 +32,7 @@ class Book(metaclass=PoolMeta): return None (to_create, msg_list, fail_cnt) = QifTool.convert_transactions_to_create( + book, QifTool.qif_read_transactions(qif_content['Bank']) ) if fail_cnt == 0: diff --git a/locale/de.po b/locale/de.po index fa4d8f9..27cc0d6 100644 --- a/locale/de.po +++ b/locale/de.po @@ -27,8 +27,8 @@ msgid "No transactions were found in the file." msgstr "In der Datei wurden keine Transaktionen gefunden." msgctxt "model:ir.message,text: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." +msgid "The category '%(catname)s' was not found." +msgstr "Die Kategorie '%(catname)s' wurde nicht gefunden." msgctxt "model:ir.message,text:mds_import_party_notfound" msgid "The party '%(pname)s' was not found." @@ -39,8 +39,12 @@ msgid "For the party '%(pname)s' of the import, several parties were found in th msgstr "Für die Partei '%(pname)s' des Imports wurden mehrere Parteien im System gefunden. Verwende: '%(pname2)s'" msgctxt "model:ir.message,text: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'" +msgid "For the category '%(catname1)s' of the import, several categories were found in the system. Use: '%(catname2)s'" +msgstr "Für die Kategorie '%(catname1)s' des Imports wurden mehrere Kategorien im System gefunden. Verwende: '%(catname2)s'" + +msgctxt "model:ir.message,text:mds_import_many_books_found" +msgid "For the cashbook '%(bookname1)s' of the import, several cashbooks were found in the system. Use: '%(bookname2)s'" +msgstr "Für das Kassenbuch '%(bookname1)s' des Imports wurden mehrere Kassenbücher im System gefunden. Verwende: '%(bookname2)s'" msgctxt "model:ir.message,text:mds_import_checknumber" msgid "Cheque No." @@ -58,6 +62,14 @@ msgctxt "model:ir.message,text:mds_import_no_category" msgid "No category has been assigned for transaction '%(trdata)s'." msgstr "Für die Transaktion '%(trdata)s' wurde keine Kategorie zugeordnet." +msgctxt "model:ir.message,text:mds_import_no_account" +msgid "No cashbook has been assigned for transaction '%(trdata)s'." +msgstr "Für die Transaktion '%(trdata)s' wurde kein Kassenbuch zugeordnet." + +msgctxt "model:ir.message,text:mds_import_book_notfound" +msgid "The cashbook '%(bookname)s' was not found." +msgstr "Das Kassenbuch '%(bookname)s' wurde nicht gefunden." + ############# # ir.action # diff --git a/locale/en.po b/locale/en.po index d409b6e..e5e7d31 100644 --- a/locale/en.po +++ b/locale/en.po @@ -23,8 +23,8 @@ msgid "No transactions were found in the file." msgstr "No transactions were found in the file." msgctxt "model:ir.message,text: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." +msgid "The category '%(catname)s' was not found." +msgstr "The category '%(catname)s' was not found." msgctxt "model:ir.message,text:mds_import_party_notfound" msgid "The party '%(pname)s' was not found." @@ -35,8 +35,12 @@ msgid "For the party '%(pname)s' of the import, several parties were found in th msgstr "For the party '%(pname)s' of the import, several parties were found in the system. Use: '%(pname2)s'" msgctxt "model:ir.message,text: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'" +msgid "For the category '%(catname1)s' of the import, several categories were found in the system. Use: '%(catname2)s'" +msgstr "For the category '%(catname1)s' of the import, several categories were found in the system. Use: '%(catname2)s'" + +msgctxt "model:ir.message,text:mds_import_many_books_found" +msgid "For the cashbook '%(bookname1)s' of the import, several cashbooks were found in the system. Use: '%(bookname2)s'" +msgstr "For the cashbook '%(bookname1)s' of the import, several cashbooks were found in the system. Use: '%(bookname2)s'" msgctxt "model:ir.message,text:mds_import_checknumber" msgid "Cheque No." @@ -54,6 +58,14 @@ msgctxt "model:ir.message,text:mds_import_no_category" msgid "No category has been assigned for transaction '%(trdata)s'." msgstr "No category has been assigned for transaction '%(trdata)s'." +msgctxt "model:ir.message,text:mds_import_no_account" +msgid "No cashbook has been assigned for transaction '%(trdata)s'." +msgstr "No cashbook has been assigned for transaction '%(trdata)s'." + +msgctxt "model:ir.message,text:mds_import_book_notfound" +msgid "The cashbook '%(bookname)s' was not found." +msgstr "The cashbook '%(bookname)s' was not found." + msgctxt "model:ir.action,name:act_import_qif_wizard" msgid "Import QIF-File" msgstr "Import QIF-File" diff --git a/message.xml b/message.xml index 18111aa..d2d7b3f 100644 --- a/message.xml +++ b/message.xml @@ -23,8 +23,11 @@ full copyright notices and license terms. --> When reading the QIF file, there were the following problems: + + The cashbook '%(bookname)s' was not found. + - The category '%(catname)s' (Type: %(cattype)s) was not found. + The category '%(catname)s' was not found. The party '%(pname)s' was not found. @@ -33,7 +36,10 @@ full copyright notices and license terms. --> For the party '%(pname)s' of the import, several parties were found in the system. Use: '%(pname2)s' - For the category '%(catname1)s' (type: '%(cattype)s') of the import, several categories were found in the system. Use: '%(catname2)s' + For the category '%(catname1)s' of the import, several categories were found in the system. Use: '%(catname2)s' + + + For the cashbook '%(bookname1)s' of the import, several cashbooks were found in the system. Use: '%(bookname2)s' Cheque No. @@ -44,6 +50,9 @@ full copyright notices and license terms. --> No category has been assigned for transaction '%(trdata)s'. + + No cashbook has been assigned for transaction '%(trdata)s'. + diff --git a/qif_import_wiz.py b/qif_import_wiz.py index d6a41ba..2fe8c03 100644 --- a/qif_import_wiz.py +++ b/qif_import_wiz.py @@ -188,6 +188,7 @@ class ImportQifWizard(Wizard): qif_content = QifTool.split_by_type(file_content) if 'Bank' in qif_content.keys(): (to_create, msg_list, fail_cnt) = QifTool.convert_transactions_to_create( + self.start.book, QifTool.qif_read_transactions(qif_content['Bank']) ) if len(msg_list) > 0: @@ -203,8 +204,8 @@ class ImportQifWizard(Wizard): # count if fail_cnt == 0: - debit = sum([x['amount'] for x in to_create if x['bookingtype']=='out']) - credit = sum([x['amount'] for x in to_create if x['bookingtype']=='in']) + debit = sum([x['amount'] for x in to_create if x['bookingtype'] in ['out', 'mvout', 'spout']]) + credit = sum([x['amount'] for x in to_create if x['bookingtype'] in ['in', 'mvin', 'spin']]) balance = credit - debit if len(msg_list) > 0: diff --git a/qiftool.py b/qiftool.py index 4ab937d..af26f75 100644 --- a/qiftool.py +++ b/qiftool.py @@ -219,34 +219,64 @@ class QifTool(Model): return (party_id, msg_txt) @classmethod - def get_category_by_name(cls, catname, cattype): + def get_account_by_name(cls, book, account_name): + """ find cashbook + """ + Book = Pool().get('cashbook.book') + + book_obj = None + msg_txt = None + books = Book.search([ + ('name', '=', account_name), + ('owner.id', '=', book.owner.id), + ('id', '!=', book.id), + ]) + if len(books) == 1: + book_obj = books[0] + elif len(books) == 0: + msg_txt = gettext( + 'cashbook_dataexchange.mds_import_book_notfound', + bookname = account_name, + ) + else : + msg_txt = gettext( + 'cashbook_dataexchange.mds_import_many_books_found', + bookname1 = account_name, + bookname2 = books[0].rec_name, + ) + book_obj = books[0] + return (book_obj, msg_txt) + + @classmethod + def get_category_by_name(cls, company, catname): """ find category """ Category = Pool().get('cashbook.category') - cat_id = None + cat_obj = None msg_txt = None categories = Category.search([ - ('cattype', '=', cattype), ('rec_name', '=', catname.replace(':', '/')), + ('company.id', '=', company.id), ]) if len(categories) == 1: - cat_id = categories[0].id + cat_obj = categories[0] 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, + catname2 = '%(name)s [%(type)s]' % { + 'name': categories[0].rec_name, + 'type': categories[0].cattype, + }, ) - cat_id = categories[0].id - return (cat_id, msg_txt) + cat_obj = categories[0] + return (cat_obj, msg_txt) @classmethod def convert_categories_to_create(cls, cat_tree): @@ -319,10 +349,36 @@ class QifTool(Model): return to_create @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 + def check_counter_transaction(cls, transaction, line): + """ check if planned transaction was already inserted by + import to target-cashbook """ + Line = Pool().get('cashbook.line') + + if Line.search_count([ + ('cashbook.id', '=', line['booktransf']), + ('date', '=', line['date']), + ('description', 'ilike', '%(trinfo)s%%' % { + 'trinfo': transaction.get('party', '-'), + }), + ('amount', '=', line['amount']), + ]): + return True + else : + return False + + @classmethod + def convert_transactions_to_create(cls, book, transactions, split2edit=True): + """ convert read transactions to create-command + split2edit: True = split-bookings are 'edit', False = dont change + """ + def updt_description(descr_txt): + """ repair line breaks + """ + if descr_txt is None: + return None + return descr_txt.replace('\\n', '\n') + to_create = [] msg_list = [] fail_cnt = 0 @@ -331,18 +387,60 @@ class QifTool(Model): 'date', 'amount', 'description', 'state', ] if x in transaction.keys()} - if len(transaction['split']) > 0: - if line['amount'] >= Decimal('0.0'): - line['bookingtype'] = 'spin' + if 'description' in line.keys(): + line['description'] = updt_description(line['description']) + + cat_name = transaction.get('category', None) + account_name = transaction.get('account', None) + if cat_name is not None: + (category, msg_txt) = cls.get_category_by_name(book.company, cat_name) + if category is None: + msg_list.append(msg_txt) + fail_cnt += 1 + continue else : - line['bookingtype'] = 'spout' - line['amount'] = line['amount'].copy_sign(Decimal('1.0')) - else : - if line['amount'] >= Decimal('0.0'): - line['bookingtype'] = 'in' + cat_type = category.cattype + line['category'] = category.id + if msg_txt is not None: + msg_list.append(msg_txt) + + if cat_type == 'out': + # amount of usually out-transaction are negative in QIF, + # if its a return-transaction it should be positive + line['amount'] = line['amount'].copy_negate() + + line['bookingtype'] = cat_type + if len(transaction['split']) > 0: + line['bookingtype'] = { + 'in': 'spin', + 'out': 'spout', + }[cat_type] + elif account_name is not None: + (account, msg_txt) = cls.get_account_by_name(book, account_name) + if account is None: + msg_list.append(msg_txt) + fail_cnt += 1 + continue else : - line['bookingtype'] = 'out' - line['amount'] = line['amount'].copy_sign(Decimal('1.0')) + if msg_txt is not None: + msg_list.append(msg_txt) + if line['amount'] < Decimal('0.0'): + line['bookingtype'] = 'mvout' + line['amount'] = line['amount'].copy_negate() + else : + line['bookingtype'] = 'mvin' + + line['booktransf'] = account.id + descr_lst = [transaction.get('party', '-')] + if 'description' in line.keys(): + descr_lst.append(line['description']) + if 'party' in transaction.keys(): + del transaction['party'] + line['description'] = '; '.join(descr_lst) + line['state'] = 'edit' + if cls.check_counter_transaction(transaction, line) == True: + # counter-transaction already exists + continue # party if 'party' in transaction.keys(): @@ -354,20 +452,6 @@ class QifTool(Model): if msg_txt is not None: msg_list.append(msg_txt) - # 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) - fail_cnt += 1 - 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([ @@ -380,16 +464,17 @@ class QifTool(Model): split_lines = [] for sp_line in transaction['split']: - (cat_id, msg_txt) = cls.get_category_by_name(sp_line['category'], cat_type) + (cat_obj, msg_txt) = cls.get_category_by_name(book.company, sp_line['category']) if msg_txt is not None: msg_list.append(msg_txt) - if cat_id is not None: + if cat_obj is not None: split_lines.append({ - 'amount': sp_line['amount'].copy_sign(Decimal('1.0')), - 'description': sp_line.get('description', None), - 'category': cat_id, + 'amount': sp_line['amount'] \ + if line['bookingtype'] in ['in', 'spin'] else sp_line['amount'].copy_negate(), + 'description': updt_description(sp_line.get('description', None)), + 'category': cat_obj.id, }) else : fail_cnt += 1 @@ -407,6 +492,12 @@ class QifTool(Model): 'cashbook_dataexchange.mds_import_no_category', trdata = str(transaction))) fail_cnt += 1 + elif line['bookingtype'] in ['mvin', 'mvout']: + if line.get('booktransf', None) is None: + msg_list.append(gettext( + 'cashbook_dataexchange.mds_import_no_account', + trdata = str(transaction))) + fail_cnt += 1 to_create.append(line) return (to_create, msg_list, fail_cnt) diff --git a/tests/qifdata.py b/tests/qifdata.py index 9f749cc..1fb99ba 100644 --- a/tests/qifdata.py +++ b/tests/qifdata.py @@ -54,7 +54,7 @@ L[Bargeld] D05.12.2013 CX M05.12/06.42UHR TT TELTOW -T290,00 +T-29,00 PGA NR00002168 BLZ10000000 0 L[S-Giro] ^ @@ -65,6 +65,13 @@ T-56,37 PFoodshop Zehlendorf LLebensmittel ^ +D06.12.2013 +CX +Mreturn of bottles +T1,45 +PFoodshop Zehlendorf +LLebensmittel +^ """ qif_category = """!Type:Cat diff --git a/tests/test_category.py b/tests/test_category.py index 206f3b1..56ae211 100644 --- a/tests/test_category.py +++ b/tests/test_category.py @@ -236,9 +236,10 @@ I 'NTelekommunikation:Fernsehen\nE\n^\nNFernsehen:TV-Company\nE\n'+ '^\nNFernsehen:GEZ\nE\n^\nNLebensmittel\nE\n^') self.assertEqual(result['Bank'], 'D04.12.2013\nT7,12\nCX\nPOpening Balance\n'+ - 'L[Bargeld]\n^\nD05.12.2013\nCX\nM05.12/06.42UHR TT TELTOW\nT290,00\n'+ + 'L[Bargeld]\n^\nD05.12.2013\nCX\nM05.12/06.42UHR TT TELTOW\nT-29,00\n'+ 'PGA NR00002168 BLZ10000000 0\nL[S-Giro]\n^\nD05.12.2013\nCX\nMsome food\n'+ - 'T-56,37\nPFoodshop Zehlendorf\nLLebensmittel\n^\n') + 'T-56,37\nPFoodshop Zehlendorf\nLLebensmittel\n^\nD06.12.2013\nCX\n'+ + 'Mreturn of bottles\nT1,45\nPFoodshop Zehlendorf\nLLebensmittel\n^\n') @with_transaction() def test_qiftool_convert_transactions(self): @@ -255,7 +256,7 @@ I 'company': company.id, }): types = self.prep_type() - book, = Book.create([{ + books = Book.create([{ 'name': 'Cash Book', 'btype': types.id, 'company': company.id, @@ -263,9 +264,29 @@ I 'number_sequ': self.prep_sequence().id, 'start_date': date(2010, 1, 1), 'start_balance': Decimal('0.0'), + }, { + 'name': 'S-Giro', + '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'), + }, { + 'name': 'Bargeld', + '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') + self.assertEqual(books[0].name, 'Cash Book') + self.assertEqual(books[1].name, 'S-Giro') + self.assertEqual(books[2].name, 'Bargeld') + self.assertEqual(books[0].btype.rec_name, 'CAS - Cash') + self.assertEqual(books[1].btype.rec_name, 'CAS - Cash') + self.assertEqual(books[2].btype.rec_name, 'CAS - Cash') parties = Party.create([{ 'name': 'Opening Balance', @@ -293,42 +314,34 @@ I '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'+ + 'M05.12/06.42UHR TT TELTOW\nT-29,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, fail_cnt) = QifTool.convert_transactions_to_create(tr_list) + (to_create, msg_txt, fail_cnt) = QifTool.convert_transactions_to_create(books[0], tr_list) self.assertEqual(msg_txt, []) self.assertEqual(to_create, [{ 'date': date(2013, 12, 4), 'amount': Decimal('7.12'), - 'state': 'check', - 'bookingtype': 'in', - 'party': parties[0].id, - 'category': categories[4].id, + 'state': 'edit', + 'bookingtype': 'mvin', + 'booktransf': books[2].id, + 'description': 'Opening Balance', }, { 'date': date(2013, 12, 5), - 'amount': Decimal('290.00'), + 'amount': Decimal('29.00'), 'description': '05.12/06.42UHR TT TELTOW', - 'state': 'check', - 'bookingtype': 'in', - 'party': parties[1].id, - 'category': categories[3].id, + 'state': 'edit', + 'bookingtype': 'mvout', + 'booktransf': books[1].id, + 'description': 'GA NR00002168 BLZ10000000 0; 05.12/06.42UHR TT TELTOW', }, { 'date': date(2013, 12, 5), 'amount': Decimal('56.37'), @@ -362,12 +375,12 @@ I )], }]) Book.write(*[ - [book], + [books[0]], { 'lines': [('create', to_create)], }]) - self.assertEqual(len(book.lines), 4) - self.assertEqual(book.balance, Decimal('184.91')) + self.assertEqual(len(books[0].lines), 4) + self.assertEqual(books[0].balance, Decimal('-134.09')) @with_transaction() def test_qiftool_read_transactions(self): diff --git a/tests/test_transaction.py b/tests/test_transaction.py index 49b6c0a..45e75d1 100644 --- a/tests/test_transaction.py +++ b/tests/test_transaction.py @@ -31,7 +31,7 @@ class TransactionTestCase(ModuleTestCase): 'active_model': 'cashbook.book', }): types = self.prep_type() - book, = Book.create([{ + books = Book.create([{ 'name': 'Cash Book', 'btype': types.id, 'company': company.id, @@ -39,6 +39,22 @@ class TransactionTestCase(ModuleTestCase): 'number_sequ': self.prep_sequence().id, 'start_date': date(2010, 1, 1), 'start_balance': Decimal('0.0'), + }, { + 'name': 'S-Giro', + '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'), + }, { + 'name': 'Bargeld', + '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'), }]) Party.create([{ @@ -53,12 +69,6 @@ class TransactionTestCase(ModuleTestCase): }]) Category.create([{ - 'name':'Bargeld', - 'cattype': 'in', - }, { - 'name': 'S-Giro', - 'cattype': 'in', - }, { 'name': 'Lebensmittel', 'cattype': 'out', }]) @@ -76,10 +86,10 @@ class TransactionTestCase(ModuleTestCase): r1 = {} r1['file_'] = qif_types.encode('utf8') r1['company'] = company.id - r1['book'] = book.id + r1['book'] = books[0].id w_obj.start.file_ = r1['file_'] w_obj.start.company = company.id - w_obj.start.book = book.id + w_obj.start.book = books[0].id result = ImportWiz.execute(sess_id, {'start': r1}, 'readf') @@ -87,46 +97,53 @@ class TransactionTestCase(ModuleTestCase): self.assertEqual(result['view']['defaults']['company'], company.id) self.assertEqual(result['view']['defaults']['info'], """The following transactionen are now imported: -Credit: usd297.12 -Debit: usd56.37 -Balance: usd240.75 -Number of transactions: 3""") +Credit: usd7.12 +Debit: usd83.92 +Balance: -usd76.80 +Number of transactions: 4""") r1 = { 'company': company.id, - 'book': book.id, + 'book': books[0].id, } result = ImportWiz.execute(sess_id, {'showinfo': r1}, 'importf') self.assertEqual(list(result.keys()), []) ImportWiz.delete(sess_id) - self.assertEqual(len(book.lines), 3) + self.assertEqual(len(books[0].lines), 4) - self.assertEqual(book.lines[0].rec_name, '12/04/2013|Rev|7.12 usd|- [Bargeld]') - self.assertEqual(book.lines[1].rec_name, '12/05/2013|Rev|290.00 usd|05.12/06.42UHR TT TELTOW [S-Giro]') - self.assertEqual(book.lines[2].rec_name, '12/05/2013|Exp|-56.37 usd|some food [Lebensmittel]') + self.assertEqual(books[0].lines[0].rec_name, '12/05/2013|Exp|-56.37 usd|some food [Lebensmittel]') + self.assertEqual(books[0].lines[1].rec_name, '12/06/2013|Exp|1.45 usd|return of bottles [Lebensmittel]') + self.assertEqual(books[0].lines[2].rec_name, '12/04/2013|from|7.12 usd|Opening Balance [Bargeld | 0.00 usd | Open]') + self.assertEqual(books[0].lines[3].rec_name, '12/05/2013|to|-29.00 usd|GA NR00002168 BLZ10000000 0; 05.12/06.42 [S-Giro | 0.00 usd | Open]') - self.assertEqual(Book.export_as_qif(book), """!Type:Bank -D12/04/2013 -T7.12 -CX -POpening Balance -LBargeld -^ -D12/05/2013 -T290.00 -CX -PGA NR00002168 BLZ10000000 0 -LS-Giro -M05.12/06.42UHR TT TELTOW -^ + self.assertEqual(Book.export_as_qif(books[0]), """!Type:Bank D12/05/2013 T-56.37 CX PFoodshop Zehlendorf LLebensmittel Msome food +^ +D12/06/2013 +T1.45 +CX +PFoodshop Zehlendorf +LLebensmittel +Mreturn of bottles +^ +D12/04/2013 +T7.12 +C* +L[Bargeld] +MOpening Balance +^ +D12/05/2013 +T-29.00 +C* +L[S-Giro] +MGA NR00002168 BLZ10000000 0; 05.12/06.42UHR TT TELTOW ^""") # end PartyTestCase