Compare commits
20 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c2987eb3e1 | ||
![]() |
900c2b975c | ||
![]() |
40d3a9e825 | ||
![]() |
1163a8125d | ||
![]() |
d0e2c8bc52 | ||
![]() |
6cf6584f92 | ||
![]() |
ea282daa05 | ||
![]() |
ef84ca3ada | ||
![]() |
c09644e660 | ||
![]() |
197f35d3bb | ||
![]() |
1a4ed7a1df | ||
![]() |
2db020f5d8 | ||
![]() |
9e6cfb210f | ||
![]() |
18093219a8 | ||
![]() |
79620f8cbb | ||
![]() |
35a31cff69 | ||
![]() |
833f49c9a6 | ||
![]() |
50cbb2cc37 | ||
![]() |
0287452fe8 | ||
![]() |
b50927753b |
20 changed files with 1075 additions and 477 deletions
15
README.rst
15
README.rst
|
@ -9,20 +9,11 @@ pip install mds-cashbook-dataexchange
|
|||
|
||||
Requires
|
||||
========
|
||||
- Tryton 6.0
|
||||
- Tryton 7.0
|
||||
|
||||
Changes
|
||||
=======
|
||||
|
||||
*6.0.2 - 05.09.2022*
|
||||
*7.0.0 - 01.12.2023*
|
||||
|
||||
- category: qif-export
|
||||
- party, transactions: qif-import/export
|
||||
|
||||
*6.0.1 - 31.08.2022*
|
||||
|
||||
- add: qif - category - import
|
||||
|
||||
*6.0.0 - 28.08.2022*
|
||||
|
||||
- init
|
||||
- compatibility to Tryton 7.0
|
||||
|
|
|
@ -7,9 +7,11 @@ 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_import_wiz import (
|
||||
ImportQifWizard, ImportQifWizardStart, ImportQifWizardInfo)
|
||||
from .qif_export import QifCategoryExport, QifBookExport
|
||||
|
||||
|
||||
def register():
|
||||
Pool.register(
|
||||
QifTool,
|
||||
|
|
10
book.py
10
book.py
|
@ -3,7 +3,6 @@
|
|||
# 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
|
||||
|
||||
|
||||
|
@ -28,12 +27,13 @@ class Book(metaclass=PoolMeta):
|
|||
Book2 = pool.get('cashbook.book')
|
||||
|
||||
qif_content = QifTool.split_by_type(qifdata)
|
||||
if not 'Bank' in qif_content.keys():
|
||||
if 'Bank' not in qif_content.keys():
|
||||
return None
|
||||
|
||||
(to_create, msg_list, fail_cnt) = QifTool.convert_transactions_to_create(
|
||||
QifTool.qif_read_transactions(qif_content['Bank'])
|
||||
)
|
||||
(to_create, msg_list, fail_cnt) = \
|
||||
QifTool.convert_transactions_to_create(
|
||||
book,
|
||||
QifTool.qif_read_transactions(qif_content['Bank']))
|
||||
if fail_cnt == 0:
|
||||
Book2.write(*[
|
||||
[book],
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
# 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
|
||||
|
||||
|
||||
|
@ -18,8 +17,9 @@ class Category(metaclass=PoolMeta):
|
|||
Category2 = pool.get('cashbook.category')
|
||||
QifTool = pool.get('cashbook_dataexchange.qiftool')
|
||||
|
||||
categories = Category2.search([],
|
||||
order=[('cattype', 'ASC'), ('rec_name', 'ASC')])
|
||||
categories = Category2.search(
|
||||
[],
|
||||
order=[('cattype', 'ASC'), ('rec_name', 'ASC')])
|
||||
|
||||
export = ['!Type:Cat']
|
||||
export.extend([QifTool.qif_export_category(x) for x in categories])
|
||||
|
@ -34,7 +34,7 @@ class Category(metaclass=PoolMeta):
|
|||
Category2 = pool.get('cashbook.category')
|
||||
|
||||
type_data = QifTool.split_by_type(qifdata)
|
||||
if not 'Cat' in type_data.keys():
|
||||
if 'Cat' not in type_data.keys():
|
||||
return None
|
||||
|
||||
to_create = QifTool.convert_categories_to_create(
|
||||
|
|
34
locale/de.po
34
locale/de.po
|
@ -12,7 +12,7 @@ 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:\nCredit: %(credit)s\nDebit: %(debit)s\nBalance: %(balance)s\nNumber of transactions: %(quantity)s"
|
||||
msgstr "Die folgenden Transaktionen werden nun importiert:\nEinnahmen: %(credit)s\Ausgaben: %(debit)s\nSaldo: %(balance)s\nAnzahl Transactionen: %(quantity)s"
|
||||
msgstr "Die folgenden Transaktionen werden nun importiert:\nEinnahmen: %(credit)s\nAusgaben: %(debit)s\nSaldo: %(balance)s\nAnzahl Transactionen: %(quantity)s"
|
||||
|
||||
msgctxt "model:ir.message,text:msg_wiz_parties_found"
|
||||
msgid "The following %(numparties)s parties are now imported:"
|
||||
|
@ -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."
|
||||
|
@ -54,6 +58,26 @@ msgctxt "model:ir.message,text: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:"
|
||||
|
||||
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."
|
||||
|
||||
msgctxt "model:ir.message,text:mds_import_category_not_match"
|
||||
msgid "The category '%(catname)s' of the split booking does not match the bookingtype '%(bktype)s' (data: '%(data)s')"
|
||||
msgstr "Die Kategorie '%(catname)s' der Splitbuchung paßt nicht zum Buchungstyp '%(bktype)s' (Daten: '%(data)s')"
|
||||
|
||||
msgctxt "model:ir.message,text:msg_ignore_null_booking"
|
||||
msgid "Ignore empty booking, no category, amount zero: %(trinfo)s"
|
||||
msgstr "Ignoriere leere Buchung, keine Kategorie, Betrag Null: %(trinfo)s"
|
||||
|
||||
|
||||
#############
|
||||
# ir.action #
|
||||
|
|
24
locale/en.po
24
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."
|
||||
|
@ -50,6 +54,18 @@ msgctxt "model:ir.message,text: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.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"
|
||||
|
|
23
message.xml
23
message.xml
|
@ -23,8 +23,11 @@ full copyright notices and license terms. -->
|
|||
<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_book_notfound">
|
||||
<field name="text">The cashbook '%(bookname)s' was not found.</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>
|
||||
<field name="text">The category '%(catname)s' was not found.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="mds_import_party_notfound">
|
||||
<field name="text">The party '%(pname)s' was not found.</field>
|
||||
|
@ -33,7 +36,10 @@ full copyright notices and license terms. -->
|
|||
<field name="text">For the party '%(pname)s' of the import, several parties were found in the system. Use: '%(pname2)s'</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>
|
||||
<field name="text">For the category '%(catname1)s' of the import, several categories were found in the system. Use: '%(catname2)s'</field>
|
||||
</record>
|
||||
<record model="ir.message" id="mds_import_many_books_found">
|
||||
<field name="text">For the cashbook '%(bookname1)s' of the import, several cashbooks were found in the system. Use: '%(bookname2)s'</field>
|
||||
</record>
|
||||
<record model="ir.message" id="mds_import_checknumber">
|
||||
<field name="text">Cheque No.</field>
|
||||
|
@ -41,6 +47,19 @@ full copyright notices and license terms. -->
|
|||
<record model="ir.message" id="mds_import_address">
|
||||
<field name="text">Address</field>
|
||||
</record>
|
||||
<record model="ir.message" id="mds_import_no_category">
|
||||
<field name="text">No category has been assigned for transaction '%(trdata)s'.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="mds_import_no_account">
|
||||
<field name="text">No cashbook has been assigned for transaction '%(trdata)s'.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="mds_import_category_not_match">
|
||||
<field name="text">The category '%(catname)s' of the split booking does not match the bookingtype '%(bktype)s' (data: '%(data)s')</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_ignore_null_booking">
|
||||
<field name="text">Ignore empty booking, no category, amount zero: %(trinfo)s</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</tryton>
|
||||
|
|
|
@ -8,7 +8,6 @@ from trytond.pool import Pool
|
|||
from slugify import slugify
|
||||
|
||||
|
||||
|
||||
class QifCategoryExport(Report):
|
||||
__name__ = 'cashbook_dataexchange.rep_category'
|
||||
|
||||
|
@ -40,7 +39,7 @@ class QifBookExport(Report):
|
|||
IrDate = pool.get('ir.date')
|
||||
Book = pool.get('cashbook.book')
|
||||
|
||||
books = Book.search([('id', '=', data.get('id', -1))])
|
||||
books = Book.search([('id', '=', data.get('id', -1))])
|
||||
if len(books) == 1:
|
||||
return (
|
||||
'qif',
|
||||
|
@ -51,7 +50,7 @@ class QifBookExport(Report):
|
|||
'book': books[0].name,
|
||||
}, max_length=100, word_boundary=True, save_order=True),
|
||||
)
|
||||
else :
|
||||
else:
|
||||
return (
|
||||
'txt',
|
||||
'not cashbook found',
|
||||
|
|
|
@ -7,26 +7,26 @@ from trytond.transaction import Transaction
|
|||
from trytond.pool import Pool
|
||||
from trytond.model import ModelView, fields
|
||||
from trytond.wizard import Wizard, StateTransition, StateView, Button
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.i18n import gettext
|
||||
from trytond.pyson import Eval, Bool
|
||||
from trytond.report import Report
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
class ImportQifWizardStart(ModelView):
|
||||
'Import QIF-File'
|
||||
__name__ = 'cashbook_dataexchange.qif_imp_wiz.start'
|
||||
|
||||
company = fields.Many2One(model_name='company.company',
|
||||
company = fields.Many2One(
|
||||
model_name='company.company',
|
||||
string="Company", required=True,
|
||||
states={'invisible': True})
|
||||
book = fields.Many2One(string='Cashbook', readonly=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,
|
||||
'invisible': ~Bool(Eval('book'))})
|
||||
file_ = fields.Binary(
|
||||
string="QIF-File", required=True,
|
||||
help='Quicken Interchange Format')
|
||||
|
||||
@classmethod
|
||||
|
@ -40,15 +40,15 @@ class ImportQifWizardInfo(ModelView):
|
|||
'Import QIF-File'
|
||||
__name__ = 'cashbook_dataexchange.qif_imp_wiz.info'
|
||||
|
||||
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',
|
||||
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',
|
||||
'invisible': ~Bool(Eval('book'))})
|
||||
allowimport = fields.Boolean(
|
||||
string='Import Enabled',
|
||||
states={'invisible': True})
|
||||
info = fields.Text(string='Information', readonly=True)
|
||||
|
||||
|
@ -60,21 +60,23 @@ class ImportQifWizard(Wizard):
|
|||
__name__ = 'cashbook_dataexchange.qif_imp_wiz'
|
||||
|
||||
start_state = 'start'
|
||||
start = StateView(model_name='cashbook_dataexchange.qif_imp_wiz.start', \
|
||||
view='cashbook_dataexchange.qif_imp_wiz_start_form', \
|
||||
start = StateView(
|
||||
model_name='cashbook_dataexchange.qif_imp_wiz.start',
|
||||
view='cashbook_dataexchange.qif_imp_wiz_start_form',
|
||||
buttons=[
|
||||
Button(string='Cancel', state='end', icon='tryton-cancel'),
|
||||
Button(string='Read File', state='readf', icon='tryton-forward', default=True),
|
||||
])
|
||||
showinfo = StateView(model_name='cashbook_dataexchange.qif_imp_wiz.info', \
|
||||
view='cashbook_dataexchange.qif_imp_wiz_info_form', \
|
||||
Button(
|
||||
string='Read File', state='readf',
|
||||
icon='tryton-forward', default=True)])
|
||||
showinfo = StateView(
|
||||
model_name='cashbook_dataexchange.qif_imp_wiz.info',
|
||||
view='cashbook_dataexchange.qif_imp_wiz_info_form',
|
||||
buttons=[
|
||||
Button(string='Cancel', state='end', icon='tryton-cancel'),
|
||||
Button(string='Import Data', state='importf', icon='tryton-import', default=True,
|
||||
states={
|
||||
'readonly': Eval('allowimport', False) == False,
|
||||
}),
|
||||
])
|
||||
Button(
|
||||
string='Import Data', state='importf',
|
||||
icon='tryton-import', default=True,
|
||||
states={'readonly': ~Eval('allowimport', False)})])
|
||||
|
||||
readf = StateTransition()
|
||||
importf = StateTransition()
|
||||
|
@ -86,8 +88,7 @@ class ImportQifWizard(Wizard):
|
|||
|
||||
values = {
|
||||
'company': Transaction().context.get('company'),
|
||||
'book': None,
|
||||
}
|
||||
'book': None}
|
||||
|
||||
model = context.get('active_model', '')
|
||||
if model == 'cashbook.book':
|
||||
|
@ -146,7 +147,8 @@ class ImportQifWizard(Wizard):
|
|||
# read file content, extract categories
|
||||
qif_content = QifTool.split_by_type(file_content)
|
||||
if 'Cat' in qif_content.keys():
|
||||
to_create = QifTool.convert_categories_to_create(QifTool.qif_read_categories(qif_content['Cat']))
|
||||
to_create = QifTool.convert_categories_to_create(
|
||||
QifTool.qif_read_categories(qif_content['Cat']))
|
||||
|
||||
in_categories = []
|
||||
out_categories = []
|
||||
|
@ -156,42 +158,44 @@ class ImportQifWizard(Wizard):
|
|||
|
||||
self.showinfo.info = gettext(
|
||||
'cashbook_dataexchange.msg_wiz_categories_found',
|
||||
categories = '\n'.join(
|
||||
categories='\n'.join(
|
||||
[''] +
|
||||
['%s (in)' % x for x in in_categories]+
|
||||
['%s (in)' % x for x in in_categories] +
|
||||
[''] +
|
||||
['%s (out)' % x for x in out_categories]
|
||||
)
|
||||
)
|
||||
))
|
||||
if len(to_create) > 0:
|
||||
self.showinfo.allowimport = True
|
||||
else :
|
||||
self.showinfo.info = gettext('cashbook_dataexchange.msg_wiz_no_categories')
|
||||
else:
|
||||
self.showinfo.info = gettext(
|
||||
'cashbook_dataexchange.msg_wiz_no_categories')
|
||||
elif model == 'party.party':
|
||||
# read file content, extract parties
|
||||
qif_content = QifTool.split_by_type(file_content)
|
||||
if 'Bank' in qif_content.keys():
|
||||
to_create = QifTool.convert_parties_to_create(
|
||||
QifTool.qif_read_transactions(qif_content['Bank'])
|
||||
)
|
||||
QifTool.qif_read_transactions(qif_content['Bank']))
|
||||
self.showinfo.info = gettext(
|
||||
'cashbook_dataexchange.msg_wiz_parties_found',
|
||||
numparties = len(to_create),
|
||||
numparties=len(to_create),
|
||||
) + '\n\n' + '\n'.join([x['name'] for x in to_create])
|
||||
if len(to_create) > 0:
|
||||
self.showinfo.allowimport = True
|
||||
else :
|
||||
self.showinfo.info = gettext('cashbook_dataexchange.msg_wiz_no_bank')
|
||||
else:
|
||||
self.showinfo.info = gettext(
|
||||
'cashbook_dataexchange.msg_wiz_no_bank')
|
||||
elif model == 'cashbook.book':
|
||||
info_lst = []
|
||||
# read file content, extract categories
|
||||
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(
|
||||
QifTool.qif_read_transactions(qif_content['Bank'])
|
||||
)
|
||||
(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:
|
||||
info_lst.append(gettext('cashbook_dataexchange.msg_wiz_transactions_error'))
|
||||
info_lst.append(gettext(
|
||||
'cashbook_dataexchange.msg_wiz_transactions_error'))
|
||||
info_lst.append('')
|
||||
|
||||
short_lst = []
|
||||
|
@ -203,22 +207,29 @@ 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:
|
||||
msg_list.append('')
|
||||
info_lst.append(gettext(
|
||||
'cashbook_dataexchange.msg_wiz_transactions_found',
|
||||
quantity = len(to_create),
|
||||
balance = Report.format_currency(balance, None, self.start.book.currency),
|
||||
credit = Report.format_currency(credit, None, self.start.book.currency),
|
||||
debit = Report.format_currency(debit, None, self.start.book.currency),
|
||||
))
|
||||
quantity=len(to_create),
|
||||
balance=Report.format_currency(
|
||||
balance, None, self.start.book.currency),
|
||||
credit=Report.format_currency(
|
||||
credit, None, self.start.book.currency),
|
||||
debit=Report.format_currency(
|
||||
debit, None, self.start.book.currency)))
|
||||
self.showinfo.allowimport = True
|
||||
else :
|
||||
info_lst.append(gettext('cashbook_dataexchange.msg_wiz_no_bank'))
|
||||
else:
|
||||
info_lst.append(gettext(
|
||||
'cashbook_dataexchange.msg_wiz_no_bank'))
|
||||
self.showinfo.info = '\n'.join(info_lst)
|
||||
|
||||
return 'showinfo'
|
||||
|
@ -229,6 +240,7 @@ class ImportQifWizard(Wizard):
|
|||
pool = Pool()
|
||||
Category = pool.get('cashbook.category')
|
||||
Book = pool.get('cashbook.book')
|
||||
Line = pool.get('cashbook.line')
|
||||
Party = pool.get('party.party')
|
||||
QifTool = pool.get('cashbook_dataexchange.qiftool')
|
||||
|
||||
|
@ -239,10 +251,15 @@ class ImportQifWizard(Wizard):
|
|||
|
||||
if model == 'cashbook.category':
|
||||
if file_content:
|
||||
records = Category.create_from_qif(file_content)
|
||||
Category.create_from_qif(file_content)
|
||||
elif model == 'cashbook.book':
|
||||
if file_content:
|
||||
Book.create_from_qif(self.showinfo.book, file_content)
|
||||
lines = Line.search([
|
||||
('cashbook.id', '=', self.showinfo.book.id),
|
||||
('state', '=', 'edit')])
|
||||
if len(lines) > 0:
|
||||
Line.wfcheck(lines)
|
||||
elif model == 'party.party':
|
||||
qif_content = QifTool.split_by_type(file_content)
|
||||
if 'Bank' in qif_content.keys():
|
||||
|
@ -253,4 +270,3 @@ class ImportQifWizard(Wizard):
|
|||
return 'end'
|
||||
|
||||
# end ImportQifWizard
|
||||
|
||||
|
|
358
qiftool.py
358
qiftool.py
|
@ -26,11 +26,11 @@ class QifTool(Model):
|
|||
for line in lines:
|
||||
if line.startswith('!Type:'):
|
||||
current_type = line[len('!Type:'):].strip()
|
||||
else :
|
||||
else:
|
||||
if current_type is None:
|
||||
continue
|
||||
|
||||
if not current_type in blocks.keys():
|
||||
if current_type not in blocks.keys():
|
||||
blocks[current_type] = []
|
||||
blocks[current_type].append(line.strip())
|
||||
|
||||
|
@ -82,7 +82,8 @@ class QifTool(Model):
|
|||
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()
|
||||
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
|
||||
|
@ -103,19 +104,26 @@ class QifTool(Model):
|
|||
elif line.startswith('L'): # category, account
|
||||
if line_txt.startswith('[') and line_txt.endswith(']'):
|
||||
booking['account'] = line_txt[1:-1]
|
||||
else :
|
||||
else:
|
||||
booking['category'] = line_txt
|
||||
elif line.startswith('S'): # split: category
|
||||
booking['split'].append({
|
||||
'category': line_txt,
|
||||
})
|
||||
elif line.startswith('S'): # split: category, account
|
||||
if line_txt.startswith('[') and line_txt.endswith(']'):
|
||||
booking['split'].append({
|
||||
'account': line_txt[1:-1],
|
||||
})
|
||||
else:
|
||||
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)
|
||||
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 :
|
||||
booking['split'][-1]['amount'] = \
|
||||
cls.get_amount_from_txt(line_txt)
|
||||
else:
|
||||
raise ValueError('unknown line-code: %s' % (line))
|
||||
result.append(booking)
|
||||
return result
|
||||
|
@ -133,7 +141,7 @@ class QifTool(Model):
|
|||
return amount
|
||||
elif line.bookingtype in ['out', 'spout', 'mvout']:
|
||||
return amount * Decimal('-1.0')
|
||||
else :
|
||||
else:
|
||||
raise ValueError('invalid bookingtype: %s' % line.bookingtype)
|
||||
|
||||
for line in book.lines:
|
||||
|
@ -143,7 +151,10 @@ class QifTool(Model):
|
|||
})
|
||||
# total
|
||||
result.append('T%(total)s' % {
|
||||
'total': Report.format_number(get_amount_by_bookingstate(line.amount, line), None),
|
||||
'total': Report.format_number(
|
||||
get_amount_by_bookingstate(line.amount, line),
|
||||
None,
|
||||
digits=book.currency.digits),
|
||||
})
|
||||
# state
|
||||
result.append('C%(state)s' % {
|
||||
|
@ -159,8 +170,8 @@ class QifTool(Model):
|
|||
if p_address:
|
||||
if len(p_address.full_address.strip()) > 0:
|
||||
result.append('A%(address)s' % {
|
||||
'address': p_address.full_address.replace('\n', ', ').strip(),
|
||||
})
|
||||
'address': p_address.full_address.replace(
|
||||
'\n', ', ').strip()})
|
||||
# category
|
||||
if line.category:
|
||||
result.append('L%(category)s' % {
|
||||
|
@ -187,7 +198,10 @@ class QifTool(Model):
|
|||
'memo': splitline.description.replace('\n', '; ')
|
||||
})
|
||||
result.append('$%(total)s' % {
|
||||
'total': Report.format_number(get_amount_by_bookingstate(splitline.amount, line), None),
|
||||
'total': Report.format_number(
|
||||
get_amount_by_bookingstate(splitline.amount, line),
|
||||
None,
|
||||
digits=book.currency.digits),
|
||||
})
|
||||
result.append('^')
|
||||
return '\n'.join(result)
|
||||
|
@ -205,48 +219,76 @@ class QifTool(Model):
|
|||
if len(parties) == 0:
|
||||
msg_txt = gettext(
|
||||
'cashbook_dataexchange.mds_import_party_notfound',
|
||||
pname = partyname,
|
||||
)
|
||||
pname=partyname)
|
||||
elif len(parties) == 1:
|
||||
party_id = parties[0].id
|
||||
else :
|
||||
else:
|
||||
party_id = parties[0].id
|
||||
msg_txt = gettext(
|
||||
'cashbook_dataexchange.mds_import_many_parties_found',
|
||||
pname = partyname,
|
||||
pname2 = parties[0].rec_name,
|
||||
)
|
||||
pname=partyname,
|
||||
pname2=parties[0].rec_name)
|
||||
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,
|
||||
catname=catname,
|
||||
)
|
||||
else :
|
||||
else:
|
||||
msg_txt = gettext(
|
||||
'cashbook_dataexchange.mds_import_many_categories_found',
|
||||
catname1 = catname,
|
||||
catname2 = categories[0].rec_name,
|
||||
cattype = cattype,
|
||||
catname1=catname,
|
||||
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):
|
||||
|
@ -259,13 +301,13 @@ class QifTool(Model):
|
|||
"""
|
||||
result = []
|
||||
for catname in catdict.keys():
|
||||
if do_search == True:
|
||||
if do_search is True:
|
||||
c_lst = Category.search([
|
||||
('cattype', '=', ctype),
|
||||
('name', '=', catname),
|
||||
('parent', '=', None) if parent is None else ('parent.id', '=', parent.id),
|
||||
])
|
||||
else :
|
||||
('cattype', '=', ctype),
|
||||
('name', '=', catname),
|
||||
('parent', '=', None)
|
||||
if parent is None else ('parent.id', '=', parent.id)])
|
||||
else:
|
||||
c_lst = []
|
||||
|
||||
if len(c_lst) == 0:
|
||||
|
@ -277,13 +319,15 @@ class QifTool(Model):
|
|||
cat1['parent'] = parent.id
|
||||
|
||||
if len(catdict[catname]['childs']) > 0:
|
||||
childs = get_create(ctype, catdict[catname]['childs'], None, False)
|
||||
childs = get_create(
|
||||
ctype, catdict[catname]['childs'], None, False)
|
||||
if len(childs) > 0:
|
||||
cat1['childs'] = [('create', childs)]
|
||||
result.append(cat1)
|
||||
else :
|
||||
else:
|
||||
if len(catdict[catname]['childs']) > 0:
|
||||
result.extend(get_create(ctype, catdict[catname]['childs'], c_lst[0], True))
|
||||
result.extend(get_create(
|
||||
ctype, catdict[catname]['childs'], c_lst[0], True))
|
||||
return result
|
||||
to_create = []
|
||||
for typ1 in ['in', 'out']:
|
||||
|
@ -308,8 +352,7 @@ class QifTool(Model):
|
|||
if Party.search_count([
|
||||
('rec_name', 'ilike', '%%%(pname)s%%' % {
|
||||
'pname': transaction['party'],
|
||||
})
|
||||
]) == 0:
|
||||
})]) == 0:
|
||||
to_create.append({
|
||||
'name': transaction['party'],
|
||||
'addresses': [('create', [{
|
||||
|
@ -319,55 +362,142 @@ 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, book, line):
|
||||
""" check if planned transaction was already inserted by
|
||||
import to target-cashbook
|
||||
"""
|
||||
Line = Pool().get('cashbook.line')
|
||||
|
||||
if Line.search_count([
|
||||
('cashbook.id', '=', book.id),
|
||||
('booktransf.id', '=', line['booktransf']),
|
||||
('date', '=', line['date']),
|
||||
# ('description', '=', line['description']),
|
||||
('amount', '=', line['amount']),
|
||||
('bookingtype', '=', line['bookingtype']),
|
||||
]) > 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def get_category_account(cls, book, transaction):
|
||||
""" get category or account
|
||||
"""
|
||||
cat_name = transaction.get('category', None)
|
||||
account_name = transaction.get('account', None)
|
||||
msg_list = []
|
||||
fail_cnt = 0
|
||||
category = 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
|
||||
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
|
||||
return (category, account, msg_list, fail_cnt)
|
||||
|
||||
@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
|
||||
for transaction in transactions:
|
||||
line = {x:transaction[x] for x in [
|
||||
'date', 'amount', 'description', 'state',
|
||||
] if x in transaction.keys()}
|
||||
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'))
|
||||
if 'description' in line.keys():
|
||||
line['description'] = updt_description(line['description'])
|
||||
|
||||
(category, account, msg_lst2, fail_cnt2) = \
|
||||
cls.get_category_account(book, transaction)
|
||||
msg_list.extend(msg_lst2)
|
||||
if fail_cnt2 > 0:
|
||||
fail_cnt += fail_cnt2
|
||||
continue
|
||||
|
||||
if category:
|
||||
cat_type = category.cattype
|
||||
line['category'] = category.id
|
||||
|
||||
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:
|
||||
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(book, line) is True:
|
||||
# counter-transaction already exists
|
||||
continue
|
||||
else:
|
||||
# transaction: no category, no account - ignore?
|
||||
if line.get('amount', Decimal('0.0')) == Decimal('0.0'):
|
||||
# no amount --> ignore!
|
||||
tr_info = {'trdate': '-', 'amount': '-'}
|
||||
if 'date' in transaction.keys():
|
||||
tr_info['trdate'] = Report.format_date(
|
||||
transaction['date'], None)
|
||||
if 'amount' in transaction.keys():
|
||||
tr_info['amount'] = Report.format_currency(
|
||||
transaction['amount'],
|
||||
None,
|
||||
book.currency)
|
||||
tr_info['descr'] = transaction.get('description', '-')
|
||||
msg_list.append(gettext(
|
||||
'cashbook_dataexchange.msg_ignore_null_booking',
|
||||
trinfo='%(trdate)s, %(amount)s, %(descr)s' % tr_info,
|
||||
))
|
||||
continue
|
||||
|
||||
# party
|
||||
if 'party' in transaction.keys():
|
||||
(party_id, msg_txt) = cls.get_party_by_name(transaction['party'])
|
||||
(party_id, msg_txt) = cls.get_party_by_name(
|
||||
transaction['party'])
|
||||
if party_id is not None:
|
||||
line['party'] = party_id
|
||||
else :
|
||||
else:
|
||||
fail_cnt += 1
|
||||
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,26 +510,67 @@ 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)
|
||||
(category, account, msg_lst2, fail_cnt2) = \
|
||||
cls.get_category_account(book, sp_line)
|
||||
msg_list.extend(msg_lst2)
|
||||
if fail_cnt2 > 0:
|
||||
fail_cnt += fail_cnt2
|
||||
continue
|
||||
|
||||
if msg_txt is not None:
|
||||
msg_list.append(msg_txt)
|
||||
split_line = {
|
||||
'amount': sp_line['amount']
|
||||
if line['bookingtype'].endswith('in')
|
||||
else sp_line['amount'].copy_negate(),
|
||||
'description': updt_description(
|
||||
sp_line.get('description', None)),
|
||||
}
|
||||
|
||||
if category:
|
||||
# category match to bookingtype?
|
||||
if ((category.cattype == 'in') and
|
||||
line['bookingtype'].endswith('out')) or \
|
||||
((category.cattype == 'out') and
|
||||
line['bookingtype'].endswith('in')):
|
||||
msg_list.append(gettext(
|
||||
'cashbook_dataexchange.' +
|
||||
'mds_import_category_not_match',
|
||||
catname='%s [%s]' % (
|
||||
category.rec_name, category.cattype),
|
||||
bktype=line['bookingtype'],
|
||||
data=str(transaction)))
|
||||
fail_cnt += 1
|
||||
continue
|
||||
split_line['splittype'] = 'cat'
|
||||
split_line['category'] = category.id
|
||||
elif account:
|
||||
split_line['splittype'] = 'tr'
|
||||
split_line['booktransf'] = account.id
|
||||
else:
|
||||
continue
|
||||
|
||||
split_lines.append(split_line)
|
||||
|
||||
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,
|
||||
})
|
||||
else :
|
||||
fail_cnt += 1
|
||||
if len(split_lines) > 0:
|
||||
line['splitlines'] = [('create', split_lines)]
|
||||
|
||||
if split2edit == True:
|
||||
if split2edit is True:
|
||||
if 'splitlines' in line.keys():
|
||||
line['state'] = 'edit'
|
||||
|
||||
# check data
|
||||
if line['bookingtype'] in ['in', 'out']:
|
||||
if line.get('category', None) is None:
|
||||
msg_list.append(gettext(
|
||||
'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)
|
||||
|
||||
|
@ -442,9 +613,10 @@ class QifTool(Model):
|
|||
cattype = 'out'
|
||||
elif line.startswith('I'):
|
||||
cattype = 'in'
|
||||
else :
|
||||
else:
|
||||
raise ValueError('invalid line: %s (%s)' % (line, cattxt))
|
||||
categories[cattype] = add_category(categories[cattype], catname, cattype)
|
||||
categories[cattype] = add_category(
|
||||
categories[cattype], catname, cattype)
|
||||
return categories
|
||||
|
||||
@classmethod
|
||||
|
|
73
setup.py
73
setup.py
|
@ -2,7 +2,7 @@
|
|||
"""
|
||||
|
||||
# Always prefer setuptools over distutils
|
||||
from setuptools import setup, find_packages
|
||||
from setuptools import setup
|
||||
# To use a consistent encoding
|
||||
from codecs import open
|
||||
from os import path
|
||||
|
@ -36,10 +36,10 @@ with open(path.join(here, 'versiondep.txt'), encoding='utf-8') as f:
|
|||
l2 = i.strip().split(';')
|
||||
if len(l2) < 4:
|
||||
continue
|
||||
modversion[l2[0]] = {'min':l2[1], 'max':l2[2], 'prefix':l2[3]}
|
||||
modversion[l2[0]] = {'min': l2[1], 'max': l2[2], 'prefix': l2[3]}
|
||||
|
||||
# tryton-version
|
||||
major_version = 6
|
||||
major_version = 7
|
||||
minor_version = 0
|
||||
|
||||
requires = ['python-slugify']
|
||||
|
@ -51,56 +51,59 @@ for dep in info.get('depends', []):
|
|||
prefix = modversion[dep]['prefix']
|
||||
|
||||
if len(modversion[dep]['max']) > 0:
|
||||
requires.append('%s_%s >= %s, <= %s' %
|
||||
(prefix, dep, modversion[dep]['min'], modversion[dep]['max']))
|
||||
else :
|
||||
requires.append('%s_%s >= %s' %
|
||||
(prefix, dep, modversion[dep]['min']))
|
||||
else :
|
||||
requires.append('%s_%s >= %s.%s, < %s.%s' %
|
||||
('trytond', dep, major_version, minor_version,
|
||||
requires.append('%s_%s >= %s, <= %s' % (
|
||||
prefix, dep, modversion[dep]['min'],
|
||||
modversion[dep]['max']))
|
||||
else:
|
||||
requires.append('%s_%s >= %s' % (
|
||||
prefix, dep, modversion[dep]['min']))
|
||||
else:
|
||||
requires.append('%s_%s >= %s.%s, < %s.%s' % (
|
||||
'trytond', dep, major_version, minor_version,
|
||||
major_version, minor_version + 1))
|
||||
requires.append('trytond >= %s.%s, < %s.%s' %
|
||||
(major_version, minor_version, major_version, minor_version + 1))
|
||||
requires.append('trytond >= %s.%s, < %s.%s' % (
|
||||
major_version, minor_version, major_version, minor_version + 1))
|
||||
|
||||
setup(name='%s_%s' % (PREFIX, MODULE),
|
||||
setup(
|
||||
name='%s_%s' % (PREFIX, MODULE),
|
||||
version=info.get('version', '0.0.1'),
|
||||
description='Tryton module to add import/export to cashbook.',
|
||||
long_description=long_description,
|
||||
long_description_content_type='text/x-rst',
|
||||
url='https://www.m-ds.de/',
|
||||
download_url='https://scmdev.m-ds.de/Tryton/Extra/cashbook_dataexchange',
|
||||
author='martin-data services',
|
||||
author_email='service@m-ds.de',
|
||||
license='GPL-3',
|
||||
classifiers=[
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Environment :: Plugins',
|
||||
'Framework :: Tryton',
|
||||
'Intended Audience :: Developers',
|
||||
'Intended Audience :: Customer Service',
|
||||
'Intended Audience :: Information Technology',
|
||||
'Intended Audience :: Financial and Insurance Industry',
|
||||
'Topic :: Office/Business',
|
||||
'Topic :: Office/Business :: Financial :: Accounting',
|
||||
'Natural Language :: German',
|
||||
'Natural Language :: English',
|
||||
'Operating System :: OS Independent',
|
||||
'License :: OSI Approved :: GNU General Public License (GPL)',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
'Programming Language :: Python :: 3.8',
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Environment :: Plugins',
|
||||
'Framework :: Tryton',
|
||||
'Intended Audience :: Developers',
|
||||
'Intended Audience :: Customer Service',
|
||||
'Intended Audience :: Information Technology',
|
||||
'Intended Audience :: Financial and Insurance Industry',
|
||||
'Topic :: Office/Business',
|
||||
'Topic :: Office/Business :: Financial :: Accounting',
|
||||
'Natural Language :: German',
|
||||
'Natural Language :: English',
|
||||
'Operating System :: OS Independent',
|
||||
'License :: OSI Approved :: GNU General Public License (GPL)',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
'Programming Language :: Python :: 3.8',
|
||||
'Programming Language :: Python :: 3.9',
|
||||
],
|
||||
|
||||
keywords='tryton cashbook import export',
|
||||
package_dir={'trytond.modules.%s' % MODULE: '.'},
|
||||
packages=[
|
||||
'trytond.modules.%s' % MODULE,
|
||||
],
|
||||
package_data={
|
||||
'trytond.modules.%s' % MODULE: (info.get('xml', [])
|
||||
+ ['tryton.cfg', 'locale/*.po', 'tests/*.py',
|
||||
'report/*.fods', 'view/*.xml',
|
||||
'versiondep.txt', 'README.rst']),
|
||||
'trytond.modules.%s' % MODULE: (info.get('xml', []) + [
|
||||
'tryton.cfg', 'locale/*.po', 'tests/*.py',
|
||||
'report/*.fods', 'view/*.xml',
|
||||
'versiondep.txt', 'README.rst']),
|
||||
},
|
||||
|
||||
install_requires=requires,
|
||||
zip_safe=False,
|
||||
entry_points="""
|
||||
|
|
|
@ -1,27 +1,4 @@
|
|||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
import trytond.tests.test_tryton
|
||||
import unittest
|
||||
|
||||
from trytond.modules.cashbook_dataexchange.tests.test_category import CategoryTestCase
|
||||
from trytond.modules.cashbook_dataexchange.tests.test_party import PartyTestCase
|
||||
from trytond.modules.cashbook_dataexchange.tests.test_transaction import TransactionTestCase
|
||||
|
||||
__all__ = ['suite']
|
||||
|
||||
|
||||
class CashbookExchangeTestCase(\
|
||||
CategoryTestCase,\
|
||||
PartyTestCase,\
|
||||
TransactionTestCase,\
|
||||
):
|
||||
'Test cashbook exchange module'
|
||||
module = 'cashbook_dataexchange'
|
||||
|
||||
# end CashbookExchangeTestCase
|
||||
|
||||
def suite():
|
||||
suite = trytond.tests.test_tryton.suite()
|
||||
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(CashbookExchangeTestCase))
|
||||
return suite
|
||||
# -*- 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.
|
||||
|
|
|
@ -5,14 +5,13 @@
|
|||
|
||||
from datetime import date
|
||||
from decimal import Decimal
|
||||
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
||||
from trytond.tests.test_tryton import with_transaction
|
||||
from trytond.pool import Pool
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.modules.cashbook.tests import CashbookTestCase
|
||||
from .qifdata import qif_category, qif_types
|
||||
from .qifdata import qif_types
|
||||
|
||||
|
||||
class CategoryTestCase(CashbookTestCase):
|
||||
class CategoryTestCase(object):
|
||||
'Test cashbook categoy module'
|
||||
module = 'cashbook_dataexchange'
|
||||
|
||||
|
@ -22,13 +21,13 @@ class CategoryTestCase(CashbookTestCase):
|
|||
"""
|
||||
pool = Pool()
|
||||
Category = pool.get('cashbook.category')
|
||||
ImportWiz = pool.get('cashbook_dataexchange.qif_imp_wiz', type='wizard')
|
||||
ImportWiz = pool.get(
|
||||
'cashbook_dataexchange.qif_imp_wiz', type='wizard')
|
||||
|
||||
company = self.prep_company()
|
||||
with Transaction().set_context({
|
||||
'company': company.id,
|
||||
'active_model': 'cashbook.category',
|
||||
}):
|
||||
'company': company.id,
|
||||
'active_model': 'cashbook.category'}):
|
||||
(sess_id, start_state, end_state) = ImportWiz.create()
|
||||
w_obj = ImportWiz(sess_id)
|
||||
self.assertEqual(start_state, 'start')
|
||||
|
@ -49,8 +48,9 @@ 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
|
||||
self.assertEqual(
|
||||
result['view']['defaults']['info'],
|
||||
"""The following categories are now imported:\n
|
||||
Gehalt (in)
|
||||
Gehalt/Zulagen (in)
|
||||
|
||||
|
@ -88,10 +88,14 @@ Lebensmittel (out)""")
|
|||
self.assertEqual(records[8].rec_name, 'Telefon/Telco2-Handy')
|
||||
self.assertEqual(records[9].rec_name, 'Telefon/Telco3')
|
||||
self.assertEqual(records[10].rec_name, 'Telekommunikation')
|
||||
self.assertEqual(records[11].rec_name, 'Telekommunikation/Fernsehen')
|
||||
self.assertEqual(records[12].rec_name, 'Telekommunikation/Online-Dienste')
|
||||
self.assertEqual(records[13].rec_name, 'Telekommunikation/Telefon')
|
||||
self.assertEqual(records[14].rec_name, 'Telekommunikation/Telefon/Test1')
|
||||
self.assertEqual(
|
||||
records[11].rec_name, 'Telekommunikation/Fernsehen')
|
||||
self.assertEqual(
|
||||
records[12].rec_name, 'Telekommunikation/Online-Dienste')
|
||||
self.assertEqual(
|
||||
records[13].rec_name, 'Telekommunikation/Telefon')
|
||||
self.assertEqual(
|
||||
records[14].rec_name, 'Telekommunikation/Telefon/Test1')
|
||||
|
||||
@with_transaction()
|
||||
def test_category_create_by_qif_emptydb(self):
|
||||
|
@ -102,8 +106,7 @@ Lebensmittel (out)""")
|
|||
|
||||
company = self.prep_company()
|
||||
with Transaction().set_context({
|
||||
'company': company.id,
|
||||
}):
|
||||
'company': company.id}):
|
||||
records = Category.create_from_qif(qif_types)
|
||||
|
||||
records = Category.search([], order=[('rec_name', 'ASC')])
|
||||
|
@ -120,10 +123,14 @@ Lebensmittel (out)""")
|
|||
self.assertEqual(records[8].rec_name, 'Telefon/Telco2-Handy')
|
||||
self.assertEqual(records[9].rec_name, 'Telefon/Telco3')
|
||||
self.assertEqual(records[10].rec_name, 'Telekommunikation')
|
||||
self.assertEqual(records[11].rec_name, 'Telekommunikation/Fernsehen')
|
||||
self.assertEqual(records[12].rec_name, 'Telekommunikation/Online-Dienste')
|
||||
self.assertEqual(records[13].rec_name, 'Telekommunikation/Telefon')
|
||||
self.assertEqual(records[14].rec_name, 'Telekommunikation/Telefon/Test1')
|
||||
self.assertEqual(
|
||||
records[11].rec_name, 'Telekommunikation/Fernsehen')
|
||||
self.assertEqual(
|
||||
records[12].rec_name, 'Telekommunikation/Online-Dienste')
|
||||
self.assertEqual(
|
||||
records[13].rec_name, 'Telekommunikation/Telefon')
|
||||
self.assertEqual(
|
||||
records[14].rec_name, 'Telekommunikation/Telefon/Test1')
|
||||
|
||||
result = Category.export_as_qif()
|
||||
self.assertEqual(result, """!Type:Cat
|
||||
|
@ -183,8 +190,7 @@ I
|
|||
|
||||
company = self.prep_company()
|
||||
with Transaction().set_context({
|
||||
'company': company.id,
|
||||
}):
|
||||
'company': company.id}):
|
||||
cat1, = Category.create([{
|
||||
'name': 'Telekommunikation',
|
||||
'cattype': 'out',
|
||||
|
@ -199,7 +205,7 @@ I
|
|||
self.assertEqual(records[0].rec_name, 'Telekommunikation')
|
||||
self.assertEqual(records[1].rec_name, 'Telekommunikation/Telefon')
|
||||
|
||||
records1 = Category.create_from_qif(qif_types)
|
||||
Category.create_from_qif(qif_types)
|
||||
|
||||
records = Category.search([], order=[('rec_name', 'ASC')])
|
||||
self.assertEqual(len(records), 15)
|
||||
|
@ -215,10 +221,14 @@ I
|
|||
self.assertEqual(records[8].rec_name, 'Telefon/Telco2-Handy')
|
||||
self.assertEqual(records[9].rec_name, 'Telefon/Telco3')
|
||||
self.assertEqual(records[10].rec_name, 'Telekommunikation')
|
||||
self.assertEqual(records[11].rec_name, 'Telekommunikation/Fernsehen')
|
||||
self.assertEqual(records[12].rec_name, 'Telekommunikation/Online-Dienste')
|
||||
self.assertEqual(records[13].rec_name, 'Telekommunikation/Telefon')
|
||||
self.assertEqual(records[14].rec_name, 'Telekommunikation/Telefon/Test1')
|
||||
self.assertEqual(
|
||||
records[11].rec_name, 'Telekommunikation/Fernsehen')
|
||||
self.assertEqual(
|
||||
records[12].rec_name, 'Telekommunikation/Online-Dienste')
|
||||
self.assertEqual(
|
||||
records[13].rec_name, 'Telekommunikation/Telefon')
|
||||
self.assertEqual(
|
||||
records[14].rec_name, 'Telekommunikation/Telefon/Test1')
|
||||
|
||||
@with_transaction()
|
||||
def test_qiftool_split_types(self):
|
||||
|
@ -228,17 +238,25 @@ I
|
|||
|
||||
result = QifTool.split_by_type(qif_types)
|
||||
self.assertEqual(len(result.keys()), 2)
|
||||
self.assertEqual(result['Cat'], 'NGehalt\nI\n^\nNGehalt:Zulagen\n'+
|
||||
'I\n^\nNTelekommunikation\nE\n^\nNTelekommunikation:Online-Dienste\n'+
|
||||
'E\n^\nNTelekommunikation:Telefon\nE\n^\nNTelekommunikation:Telefon:Test1\n'+
|
||||
'E\n^\nNTelefon:Telco1-Tablett\n'+
|
||||
'E\n^\nNTelefon:Telco2-Handy\nE\n^\nNTelefon:Telco3\nE\n^\n'+
|
||||
'NTelekommunikation:Fernsehen\nE\n^\nNFernsehen:TV-Company\nE\n'+
|
||||
self.assertEqual(
|
||||
result['Cat'],
|
||||
'NGehalt\nI\n^\nNGehalt:Zulagen\nI\n^\nNTelekommunikation' +
|
||||
'\nE\n^\nNTelekommunikation:Online-Dienste\n' +
|
||||
'E\n^\nNTelekommunikation:Telefon\nE\n^\nN' +
|
||||
'Telekommunikation:Telefon:Test1\n' +
|
||||
'E\n^\nNTelefon:Telco1-Tablett\n' +
|
||||
'E\n^\nNTelefon:Telco2-Handy\nE\n^\nNTelefon:Telco3\nE\n^\n' +
|
||||
'NTelekommunikation:Fernsehen\nE\n^\nNFernsehen:TV-Company\nE\n' +
|
||||
'^\nNFernsehen:GEZ\nE\n^\nNLebensmittel\nE\n^')
|
||||
self.assertEqual(result['Bank'], 'D04.12.2013\nT7,12\nCX\nPOpening Balance\n'+
|
||||
'L[Bargeld]\n^\nD05.12.2013\nCX\nM05.12/06.42UHR TT TELTOW\nT290,00\n'+
|
||||
'PGA NR00002168 BLZ10000000 0\nL[S-Giro]\n^\nD05.12.2013\nCX\nMsome food\n'+
|
||||
'T-56,37\nPFoodshop Zehlendorf\nLLebensmittel\n^\n')
|
||||
self.assertEqual(
|
||||
result['Bank'],
|
||||
'D04.12.2013\nT7,12\nCX\n' +
|
||||
'POpening Balance\nL[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\nT-56,37\nPFoodshop Zehlendorf\n' +
|
||||
'LLebensmittel\n^\nD06.12.2013\nCX\nMreturn of bottles\n' +
|
||||
'T1,45\nPFoodshop Zehlendorf\nLLebensmittel\n^\n')
|
||||
|
||||
@with_transaction()
|
||||
def test_qiftool_convert_transactions(self):
|
||||
|
@ -252,20 +270,36 @@ I
|
|||
|
||||
company = self.prep_company()
|
||||
with Transaction().set_context({
|
||||
'company': company.id,
|
||||
}):
|
||||
'company': company.id}):
|
||||
types = self.prep_type()
|
||||
book, = Book.create([{
|
||||
books = 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'),
|
||||
}, {
|
||||
'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),
|
||||
}, {
|
||||
'name': 'Bargeld',
|
||||
'btype': types.id,
|
||||
'company': company.id,
|
||||
'currency': company.currency.id,
|
||||
'number_sequ': self.prep_sequence().id,
|
||||
'start_date': date(2010, 1, 1),
|
||||
}])
|
||||
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 +327,40 @@ 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'+
|
||||
'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')
|
||||
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\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\n' +
|
||||
'EKlopapier\n' +
|
||||
'$-2,99\nSHaushaltschemie\nESagrotan\n$-3,49\n' +
|
||||
'S[S-Giro]\nEtransfer out\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'),
|
||||
'description': '05.12/06.42UHR TT TELTOW',
|
||||
'state': 'check',
|
||||
'bookingtype': 'in',
|
||||
'party': parties[1].id,
|
||||
'category': categories[3].id,
|
||||
'amount': Decimal('29.00'),
|
||||
'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'),
|
||||
|
@ -347,27 +379,34 @@ I
|
|||
'party': parties[3].id,
|
||||
'splitlines': [
|
||||
('create', [{
|
||||
'splittype': 'cat',
|
||||
'amount': Decimal('49.36'),
|
||||
'description': 'Lebensmittel',
|
||||
'category': categories[0].id,
|
||||
}, {
|
||||
'splittype': 'cat',
|
||||
'amount': Decimal('2.99'),
|
||||
'description': 'Klopapier',
|
||||
'category': categories[2].id,
|
||||
}, {
|
||||
'splittype': 'cat',
|
||||
'amount': Decimal('3.49'),
|
||||
'description': 'Sagrotan',
|
||||
'category': categories[1].id,
|
||||
}],
|
||||
)],
|
||||
}, {
|
||||
'splittype': 'tr',
|
||||
'amount': Decimal('3.49'),
|
||||
'description': 'transfer out',
|
||||
'booktransf': books[1].id,
|
||||
}])],
|
||||
}])
|
||||
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('-137.58'))
|
||||
|
||||
@with_transaction()
|
||||
def test_qiftool_read_transactions(self):
|
||||
|
@ -375,13 +414,15 @@ I
|
|||
"""
|
||||
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'+
|
||||
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': [],
|
||||
|
@ -434,8 +475,10 @@ I
|
|||
"""
|
||||
QifTool = Pool().get('cashbook_dataexchange.qiftool')
|
||||
|
||||
result = QifTool.qif_read_categories('NGehalt\nI\n^\nNGehalt:Zulagen\nI\n^'+
|
||||
'NTelekommunikation\nE\n^\nNTelekommunikation:Online-Dienste\nE\n^')
|
||||
result = QifTool.qif_read_categories(
|
||||
'NGehalt\nI\n^\nNGehalt:Zulagen\nI\n^' +
|
||||
'NTelekommunikation\nE\n^\nNTelekommunikation:' +
|
||||
'Online-Dienste\nE\n^')
|
||||
self.assertEqual(result, {
|
||||
'in': {
|
||||
'Gehalt': {
|
|
@ -3,15 +3,13 @@
|
|||
# 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.tests.test_tryton import with_transaction
|
||||
from trytond.pool import Pool
|
||||
from trytond.transaction import Transaction
|
||||
from .qifdata import qif_types
|
||||
|
||||
|
||||
class PartyTestCase(ModuleTestCase):
|
||||
class PartyTestCase(object):
|
||||
'Test cashbook party module'
|
||||
module = 'cashbook_dataexchange'
|
||||
|
||||
|
@ -21,13 +19,13 @@ class PartyTestCase(ModuleTestCase):
|
|||
"""
|
||||
pool = Pool()
|
||||
Party = pool.get('party.party')
|
||||
ImportWiz = pool.get('cashbook_dataexchange.qif_imp_wiz', type='wizard')
|
||||
ImportWiz = pool.get(
|
||||
'cashbook_dataexchange.qif_imp_wiz', type='wizard')
|
||||
|
||||
company = self.prep_company()
|
||||
with Transaction().set_context({
|
||||
'company': company.id,
|
||||
'active_model': 'party.party',
|
||||
}):
|
||||
'company': company.id,
|
||||
'active_model': 'party.party'}):
|
||||
(sess_id, start_state, end_state) = ImportWiz.create()
|
||||
w_obj = ImportWiz(sess_id)
|
||||
self.assertEqual(start_state, 'start')
|
||||
|
@ -48,8 +46,9 @@ class PartyTestCase(ModuleTestCase):
|
|||
|
||||
self.assertEqual(list(result.keys()), ['view'])
|
||||
self.assertEqual(result['view']['defaults']['company'], company.id)
|
||||
self.assertEqual(result['view']['defaults']['info'],
|
||||
"""The following 3 parties are now imported:\n
|
||||
self.assertEqual(
|
||||
result['view']['defaults']['info'],
|
||||
"""The following 3 parties are now imported:\n
|
||||
Opening Balance
|
||||
GA NR00002168 BLZ10000000 0
|
||||
Foodshop Zehlendorf""")
|
||||
|
@ -64,7 +63,8 @@ Foodshop Zehlendorf""")
|
|||
self.assertEqual(len(records), 4)
|
||||
|
||||
self.assertEqual(records[0].rec_name, 'Foodshop Zehlendorf')
|
||||
self.assertEqual(records[1].rec_name, 'GA NR00002168 BLZ10000000 0')
|
||||
self.assertEqual(
|
||||
records[1].rec_name, 'GA NR00002168 BLZ10000000 0')
|
||||
self.assertEqual(records[2].rec_name, 'm-ds')
|
||||
self.assertEqual(records[3].rec_name, 'Opening Balance')
|
||||
|
|
@ -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
|
||||
|
|
24
tests/test_module.py
Normal file
24
tests/test_module.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
# -*- 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.modules.cashbook.tests.test_module import CashbookTestCase
|
||||
from .category import CategoryTestCase
|
||||
from .party import PartyTestCase
|
||||
from .transaction import TransactionTestCase
|
||||
|
||||
|
||||
class CashbookExchangeTestCase(
|
||||
CashbookTestCase,
|
||||
CategoryTestCase,
|
||||
PartyTestCase,
|
||||
TransactionTestCase):
|
||||
'Test cashbook exchange module'
|
||||
module = 'cashbook_dataexchange'
|
||||
|
||||
# end CashbookExchangeTestCase
|
||||
|
||||
|
||||
del CashbookTestCase
|
|
@ -1,132 +0,0 @@
|
|||
# -*- 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 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
|
||||
from .qifdata import qif_types
|
||||
|
||||
|
||||
class TransactionTestCase(ModuleTestCase):
|
||||
'Test cashbook transaction module'
|
||||
module = 'cashbook_dataexchange'
|
||||
|
||||
@with_transaction()
|
||||
def test_wiz_import_transactions(self):
|
||||
""" create transactions by run wizard
|
||||
"""
|
||||
pool = Pool()
|
||||
Party = pool.get('party.party')
|
||||
Category = pool.get('cashbook.category')
|
||||
Book = pool.get('cashbook.book')
|
||||
ImportWiz = pool.get('cashbook_dataexchange.qif_imp_wiz', type='wizard')
|
||||
|
||||
company = self.prep_company()
|
||||
with Transaction().set_context({
|
||||
'company': company.id,
|
||||
'active_model': 'cashbook.book',
|
||||
}):
|
||||
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'),
|
||||
}])
|
||||
|
||||
Party.create([{
|
||||
'name': 'GA NR00002168 BLZ10000000 0',
|
||||
'addresses':[('create', [{}])],
|
||||
}, {
|
||||
'name': 'Foodshop Zehlendorf',
|
||||
'addresses':[('create', [{}])],
|
||||
}, {
|
||||
'name': 'Opening Balance',
|
||||
'addresses':[('create', [{}])],
|
||||
}])
|
||||
|
||||
Category.create([{
|
||||
'name':'Bargeld',
|
||||
'cattype': 'in',
|
||||
}, {
|
||||
'name': 'S-Giro',
|
||||
'cattype': 'in',
|
||||
}, {
|
||||
'name': 'Lebensmittel',
|
||||
'cattype': 'out',
|
||||
}])
|
||||
|
||||
(sess_id, start_state, end_state) = ImportWiz.create()
|
||||
w_obj = ImportWiz(sess_id)
|
||||
self.assertEqual(start_state, 'start')
|
||||
self.assertEqual(end_state, 'end')
|
||||
|
||||
# run start
|
||||
result = ImportWiz.execute(sess_id, {}, start_state)
|
||||
self.assertEqual(list(result.keys()), ['view'])
|
||||
self.assertEqual(result['view']['defaults']['company'], company.id)
|
||||
|
||||
r1 = {}
|
||||
r1['file_'] = qif_types.encode('utf8')
|
||||
r1['company'] = company.id
|
||||
r1['book'] = book.id
|
||||
w_obj.start.file_ = r1['file_']
|
||||
w_obj.start.company = company.id
|
||||
w_obj.start.book = book.id
|
||||
|
||||
result = ImportWiz.execute(sess_id, {'start': r1}, 'readf')
|
||||
|
||||
self.assertEqual(list(result.keys()), ['view'])
|
||||
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""")
|
||||
|
||||
r1 = {
|
||||
'company': company.id,
|
||||
'book': book.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(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(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
|
||||
^
|
||||
D12/05/2013
|
||||
T-56.37
|
||||
CX
|
||||
PFoodshop Zehlendorf
|
||||
LLebensmittel
|
||||
Msome food
|
||||
^""")
|
||||
|
||||
# end PartyTestCase
|
437
tests/transaction.py
Normal file
437
tests/transaction.py
Normal file
|
@ -0,0 +1,437 @@
|
|||
# -*- 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 datetime import date
|
||||
from decimal import Decimal
|
||||
from trytond.tests.test_tryton import with_transaction
|
||||
from trytond.pool import Pool
|
||||
from trytond.transaction import Transaction
|
||||
from .qifdata import qif_types
|
||||
|
||||
|
||||
class TransactionTestCase(object):
|
||||
'Test cashbook transaction module'
|
||||
module = 'cashbook_dataexchange'
|
||||
|
||||
@with_transaction()
|
||||
def test_func_check_counter_transaction(self):
|
||||
""" check function 'check_counter_transaction'
|
||||
"""
|
||||
pool = Pool()
|
||||
Book = pool.get('cashbook.book')
|
||||
Line = pool.get('cashbook.line')
|
||||
QifTool = pool.get('cashbook_dataexchange.qiftool')
|
||||
|
||||
company = self.prep_company()
|
||||
with Transaction().set_context({
|
||||
'company': company.id}):
|
||||
types = self.prep_type()
|
||||
books = 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),
|
||||
}, {
|
||||
'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),
|
||||
}])
|
||||
|
||||
Book.write(*[
|
||||
[books[0]],
|
||||
{
|
||||
'lines': [('create', [{
|
||||
'date': date(2022, 6, 1),
|
||||
'bookingtype': 'mvout',
|
||||
'amount': Decimal('10.0'),
|
||||
'booktransf': books[1].id,
|
||||
'description': 'transfer',
|
||||
}])],
|
||||
}])
|
||||
self.assertEqual(len(books[0].lines), 1)
|
||||
self.assertEqual(
|
||||
books[0].lines[0].rec_name,
|
||||
'06/01/2022|to|-10.00 usd|transfer [S-Giro | 0.00 usd | Open]')
|
||||
self.assertEqual(len(books[1].lines), 0)
|
||||
|
||||
Line.wfcheck(books[0].lines)
|
||||
self.assertEqual(len(books[1].lines), 1)
|
||||
self.assertEqual(
|
||||
books[1].lines[0].rec_name,
|
||||
'06/01/2022|from|10.00 usd|transfer [Cash Book ' +
|
||||
'| -10.00 usd | Open]')
|
||||
|
||||
self.assertEqual(QifTool.check_counter_transaction(books[1], {
|
||||
'booktransf': books[0].id,
|
||||
'date': date(2022, 6, 1),
|
||||
'amount': Decimal('10.0'),
|
||||
'description': 'transfer',
|
||||
'bookingtype': 'mvin',
|
||||
}), True)
|
||||
|
||||
@with_transaction()
|
||||
def test_wiz_import_transactions(self):
|
||||
""" create transactions by run wizard
|
||||
"""
|
||||
pool = Pool()
|
||||
Party = pool.get('party.party')
|
||||
Category = pool.get('cashbook.category')
|
||||
Book = pool.get('cashbook.book')
|
||||
ImportWiz = pool.get(
|
||||
'cashbook_dataexchange.qif_imp_wiz', type='wizard')
|
||||
|
||||
company = self.prep_company()
|
||||
with Transaction().set_context({
|
||||
'company': company.id,
|
||||
'active_model': 'cashbook.book'}):
|
||||
types = self.prep_type()
|
||||
books = 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),
|
||||
}, {
|
||||
'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),
|
||||
}, {
|
||||
'name': 'Bargeld',
|
||||
'btype': types.id,
|
||||
'company': company.id,
|
||||
'currency': company.currency.id,
|
||||
'number_sequ': self.prep_sequence().id,
|
||||
'start_date': date(2010, 1, 1),
|
||||
}])
|
||||
|
||||
Party.create([{
|
||||
'name': 'GA NR00002168 BLZ10000000 0',
|
||||
'addresses': [('create', [{}])],
|
||||
}, {
|
||||
'name': 'Foodshop Zehlendorf',
|
||||
'addresses': [('create', [{}])],
|
||||
}, {
|
||||
'name': 'Opening Balance',
|
||||
'addresses': [('create', [{}])],
|
||||
}])
|
||||
|
||||
Category.create([{
|
||||
'name': 'Lebensmittel',
|
||||
'cattype': 'out',
|
||||
}])
|
||||
|
||||
(sess_id, start_state, end_state) = ImportWiz.create()
|
||||
w_obj = ImportWiz(sess_id)
|
||||
self.assertEqual(start_state, 'start')
|
||||
self.assertEqual(end_state, 'end')
|
||||
|
||||
# run start
|
||||
result = ImportWiz.execute(sess_id, {}, start_state)
|
||||
self.assertEqual(list(result.keys()), ['view'])
|
||||
self.assertEqual(result['view']['defaults']['company'], company.id)
|
||||
|
||||
r1 = {}
|
||||
r1['file_'] = qif_types.encode('utf8')
|
||||
r1['company'] = company.id
|
||||
r1['book'] = books[0].id
|
||||
w_obj.start.file_ = r1['file_']
|
||||
w_obj.start.company = company.id
|
||||
w_obj.start.book = books[0].id
|
||||
|
||||
result = ImportWiz.execute(sess_id, {'start': r1}, 'readf')
|
||||
|
||||
self.assertEqual(list(result.keys()), ['view'])
|
||||
self.assertEqual(result['view']['defaults']['company'], company.id)
|
||||
self.assertEqual(
|
||||
result['view']['defaults']['info'],
|
||||
"""The following transactionen are now imported:
|
||||
Credit: usd7.12
|
||||
Debit: usd83.92
|
||||
Balance: -usd76.80
|
||||
Number of transactions: 4""")
|
||||
|
||||
r1 = {
|
||||
'company': company.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(books[0].lines), 4)
|
||||
|
||||
self.assertEqual(
|
||||
books[0].lines[0].rec_name,
|
||||
'12/04/2013|from|7.12 usd|Opening Balance ' +
|
||||
'[Bargeld | -7.12 usd | Open]')
|
||||
self.assertEqual(
|
||||
books[0].lines[1].rec_name,
|
||||
'12/05/2013|to|-29.00 usd|GA NR00002168 BLZ10000000 ' +
|
||||
'0; 05.12/06.42 [S-Giro | 29.00 usd | Open]')
|
||||
self.assertEqual(
|
||||
books[0].lines[2].rec_name,
|
||||
'12/05/2013|Exp|-56.37 usd|some food [Lebensmittel]')
|
||||
self.assertEqual(
|
||||
books[0].lines[3].rec_name,
|
||||
'12/06/2013|Exp|1.45 usd|return of bottles [Lebensmittel]')
|
||||
|
||||
self.assertEqual(Book.export_as_qif(books[0]), """!Type:Bank
|
||||
D12/04/2013
|
||||
T7.12
|
||||
CX
|
||||
L[Bargeld]
|
||||
MOpening Balance
|
||||
^
|
||||
D12/05/2013
|
||||
T-29.00
|
||||
CX
|
||||
L[S-Giro]
|
||||
MGA NR00002168 BLZ10000000 0; 05.12/06.42UHR TT TELTOW
|
||||
^
|
||||
D12/05/2013
|
||||
T-56.37
|
||||
CX
|
||||
PFoodshop Zehlendorf
|
||||
LLebensmittel
|
||||
Msome food
|
||||
^
|
||||
D12/06/2013
|
||||
T1.45
|
||||
CX
|
||||
PFoodshop Zehlendorf
|
||||
LLebensmittel
|
||||
Mreturn of bottles
|
||||
^""")
|
||||
|
||||
@with_transaction()
|
||||
def test_wiz_import_transactions_transfer(self):
|
||||
""" create transactions by run wizard,
|
||||
handle transfers
|
||||
"""
|
||||
pool = Pool()
|
||||
Party = pool.get('party.party')
|
||||
Category = pool.get('cashbook.category')
|
||||
Book = pool.get('cashbook.book')
|
||||
ImportWiz = pool.get(
|
||||
'cashbook_dataexchange.qif_imp_wiz', type='wizard')
|
||||
|
||||
company = self.prep_company()
|
||||
with Transaction().set_context({
|
||||
'company': company.id,
|
||||
'active_model': 'cashbook.book'}):
|
||||
types = self.prep_type()
|
||||
books = Book.create([{
|
||||
'name': 'From Book',
|
||||
'btype': types.id,
|
||||
'company': company.id,
|
||||
'currency': company.currency.id,
|
||||
'number_sequ': self.prep_sequence().id,
|
||||
'start_date': date(2010, 1, 1),
|
||||
}, {
|
||||
'name': 'To Book',
|
||||
'btype': types.id,
|
||||
'company': company.id,
|
||||
'currency': company.currency.id,
|
||||
'number_sequ': self.prep_sequence().id,
|
||||
'start_date': date(2010, 1, 1),
|
||||
}])
|
||||
|
||||
Party.create([{
|
||||
'name': 'Foodshop Zehlendorf',
|
||||
'addresses': [('create', [{}])],
|
||||
}])
|
||||
|
||||
Category.create([{
|
||||
'name': 'Lebensmittel',
|
||||
'cattype': 'out',
|
||||
}, {
|
||||
'name': 'Fee',
|
||||
'cattype': 'out',
|
||||
}])
|
||||
|
||||
(sess_id, start_state, end_state) = ImportWiz.create()
|
||||
w_obj = ImportWiz(sess_id)
|
||||
self.assertEqual(start_state, 'start')
|
||||
self.assertEqual(end_state, 'end')
|
||||
|
||||
# run start
|
||||
result = ImportWiz.execute(sess_id, {}, start_state)
|
||||
self.assertEqual(list(result.keys()), ['view'])
|
||||
self.assertEqual(result['view']['defaults']['company'], company.id)
|
||||
|
||||
r1 = {}
|
||||
r1['file_'] = """!Type:Bank
|
||||
D05.12.2013
|
||||
CX
|
||||
Msome food
|
||||
T-50,25
|
||||
PFoodshop Zehlendorf
|
||||
LLebensmittel
|
||||
^
|
||||
D04.12.2013
|
||||
T-7,30
|
||||
CX
|
||||
PTransfer to book
|
||||
L[To Book]
|
||||
^""".encode('utf8')
|
||||
r1['company'] = company.id
|
||||
r1['book'] = books[0].id
|
||||
w_obj.start.file_ = r1['file_']
|
||||
w_obj.start.company = company.id
|
||||
w_obj.start.book = books[0].id
|
||||
|
||||
result = ImportWiz.execute(sess_id, {'start': r1}, 'readf')
|
||||
|
||||
self.assertEqual(list(result.keys()), ['view'])
|
||||
self.assertEqual(result['view']['defaults']['company'], company.id)
|
||||
self.assertEqual(
|
||||
result['view']['defaults']['info'],
|
||||
"""The following transactionen are now imported:
|
||||
Credit: usd0.00
|
||||
Debit: usd57.55
|
||||
Balance: -usd57.55
|
||||
Number of transactions: 2""")
|
||||
|
||||
r1 = {
|
||||
'company': company.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(books[0].lines), 2)
|
||||
self.assertEqual(len(books[1].lines), 1)
|
||||
|
||||
self.assertEqual(
|
||||
books[0].lines[0].rec_name,
|
||||
'12/04/2013|to|-7.30 usd|Transfer to book ' +
|
||||
'[To Book | 7.30 usd | Open]')
|
||||
self.assertEqual(books[0].lines[0].state, 'check')
|
||||
self.assertEqual(
|
||||
books[0].lines[1].rec_name,
|
||||
'12/05/2013|Exp|-50.25 usd|some food [Lebensmittel]')
|
||||
self.assertEqual(books[0].lines[1].state, 'check')
|
||||
self.assertEqual(
|
||||
books[1].lines[0].rec_name,
|
||||
'12/04/2013|from|7.30 usd|Transfer to book ' +
|
||||
'[From Book | -57.55 usd | Open]')
|
||||
self.assertEqual(books[1].lines[0].state, 'check')
|
||||
|
||||
# run wizard again - import to 'To Book'
|
||||
(sess_id, start_state, end_state) = ImportWiz.create()
|
||||
w_obj = ImportWiz(sess_id)
|
||||
self.assertEqual(start_state, 'start')
|
||||
self.assertEqual(end_state, 'end')
|
||||
|
||||
# run start
|
||||
result = ImportWiz.execute(sess_id, {}, start_state)
|
||||
self.assertEqual(list(result.keys()), ['view'])
|
||||
self.assertEqual(result['view']['defaults']['company'], company.id)
|
||||
|
||||
r1 = {}
|
||||
r1['file_'] = """!Type:Bank
|
||||
D10.12.2013
|
||||
CX
|
||||
Msome food
|
||||
T-10,00
|
||||
PFoodshop Zehlendorf
|
||||
LLebensmittel
|
||||
^
|
||||
D04.12.2013
|
||||
T7,30
|
||||
CX
|
||||
PTransfer to book
|
||||
L[From Book]
|
||||
^
|
||||
D06.12.2013
|
||||
T-10,00
|
||||
CX
|
||||
PFoodshop Zehlendorf
|
||||
MSplitbooking with category and account
|
||||
LFee
|
||||
SFee
|
||||
EFee for transfer
|
||||
$-3,00
|
||||
S[From Book]
|
||||
ETransfer to From-Book
|
||||
$-7,00
|
||||
^
|
||||
""".encode('utf8')
|
||||
r1['company'] = company.id
|
||||
r1['book'] = books[1].id
|
||||
w_obj.start.file_ = r1['file_']
|
||||
w_obj.start.company = company.id
|
||||
w_obj.start.book = books[1].id
|
||||
|
||||
result = ImportWiz.execute(sess_id, {'start': r1}, 'readf')
|
||||
|
||||
self.assertEqual(list(result.keys()), ['view'])
|
||||
self.assertEqual(result['view']['defaults']['company'], company.id)
|
||||
self.assertEqual(
|
||||
result['view']['defaults']['info'],
|
||||
"""The following transactionen are now imported:
|
||||
Credit: usd0.00
|
||||
Debit: usd20.00
|
||||
Balance: -usd20.00
|
||||
Number of transactions: 2""")
|
||||
|
||||
r1 = {
|
||||
'company': company.id,
|
||||
'book': books[1].id,
|
||||
}
|
||||
result = ImportWiz.execute(sess_id, {'showinfo': r1}, 'importf')
|
||||
self.assertEqual(list(result.keys()), [])
|
||||
|
||||
ImportWiz.delete(sess_id)
|
||||
|
||||
self.assertEqual(len(books[0].lines), 3)
|
||||
self.assertEqual(len(books[1].lines), 3)
|
||||
|
||||
self.assertEqual(
|
||||
books[0].lines[0].rec_name,
|
||||
'12/04/2013|to|-7.30 usd|Transfer to book ' +
|
||||
'[To Book | -12.70 usd | Open]')
|
||||
self.assertEqual(
|
||||
books[0].lines[0].state, 'check')
|
||||
self.assertEqual(
|
||||
books[0].lines[1].rec_name,
|
||||
'12/05/2013|Exp|-50.25 usd|some food [Lebensmittel]')
|
||||
self.assertEqual(
|
||||
books[0].lines[1].state, 'check')
|
||||
self.assertEqual(
|
||||
books[0].lines[2].rec_name,
|
||||
'12/06/2013|from|7.00 usd|Transfer to From-Book ' +
|
||||
'[To Book | -12.70 usd | Open]')
|
||||
self.assertEqual(
|
||||
books[0].lines[2].state, 'check')
|
||||
|
||||
self.assertEqual(
|
||||
books[1].lines[0].rec_name,
|
||||
'12/04/2013|from|7.30 usd|Transfer to book [From Book ' +
|
||||
'| -50.55 usd | Open]')
|
||||
self.assertEqual(books[1].lines[0].state, 'check')
|
||||
self.assertEqual(
|
||||
books[1].lines[1].rec_name,
|
||||
'12/06/2013|Exp/Sp|-10.00 usd|Splitbooking with category' +
|
||||
' and account [-]')
|
||||
self.assertEqual(books[1].lines[1].state, 'check')
|
||||
self.assertEqual(
|
||||
books[1].lines[2].rec_name,
|
||||
'12/10/2013|Exp|-10.00 usd|some food [Lebensmittel]')
|
||||
self.assertEqual(books[1].lines[2].state, 'check')
|
||||
|
||||
# end PartyTestCase
|
|
@ -1,5 +1,5 @@
|
|||
[tryton]
|
||||
version=6.0.2
|
||||
version=7.0.0
|
||||
depends:
|
||||
cashbook
|
||||
xml:
|
||||
|
|
|
@ -1 +1 @@
|
|||
cashbook;6.0.4;6.0.999;mds
|
||||
cashbook;7.0.31;7.0.999;mds
|
||||
|
|
Loading…
Reference in a new issue