diff --git a/__init__.py b/__init__.py
index ed4330c..ca56a2a 100644
--- a/__init__.py
+++ b/__init__.py
@@ -8,7 +8,7 @@ from .category import Category
from .book import Book
from .qiftool import QifTool
from .qif_import_wiz import ImportQifWizard, ImportQifWizardStart, ImportQifWizardInfo
-from .qif_export import QifCategoryExport
+from .qif_export import QifCategoryExport, QifBookExport
def register():
Pool.register(
@@ -20,6 +20,7 @@ def register():
module='cashbook_dataexchange', type_='model')
Pool.register(
QifCategoryExport,
+ QifBookExport,
module='cashbook_dataexchange', type_='report')
Pool.register(
ImportQifWizard,
diff --git a/book.py b/book.py
index 56c728b..4c44c74 100644
--- a/book.py
+++ b/book.py
@@ -10,20 +10,14 @@ from trytond.pool import Pool, PoolMeta
class Book(metaclass=PoolMeta):
__name__ = 'cashbook.book'
- # ~ @classmethod
- # ~ def export_as_qif(cls):
- # ~ """ export all transactions as QIF
- # ~ """
- # ~ pool = Pool()
- # ~ Category2 = pool.get('cashbook.category')
- # ~ QifTool = pool.get('cashbook_dataexchange.qiftool')
+ @classmethod
+ def export_as_qif(cls, book):
+ """ export all transactions as QIF
+ """
+ pool = Pool()
+ QifTool = pool.get('cashbook_dataexchange.qiftool')
- # ~ categories = Category2.search([],
- # ~ order=[('cattype', 'ASC'), ('rec_name', 'ASC')])
-
- # ~ export = ['!Type:Cat']
- # ~ export.extend([QifTool.qif_export_category(x) for x in categories])
- # ~ return '\n'.join(export)
+ return QifTool.qif_export_book(book)
@classmethod
def create_from_qif(cls, book, qifdata):
diff --git a/locale/de.po b/locale/de.po
index b452c61..3aace03 100644
--- a/locale/de.po
+++ b/locale/de.po
@@ -66,6 +66,10 @@ msgctxt "model:ir.action,name:qif_category_report"
msgid "Export QIF-File"
msgstr "QIF-Datei exportieren"
+msgctxt "model:ir.action,name:qif_transaction_report"
+msgid "Export QIF-File"
+msgstr "QIF-Datei exportieren"
+
#####################################
# cashbook_dataexchange.qif_imp_wiz #
diff --git a/locale/en.po b/locale/en.po
index 455bf50..4afb36c 100644
--- a/locale/en.po
+++ b/locale/en.po
@@ -7,8 +7,8 @@ msgid "The following categories are now imported:\n%(categories)s"
msgstr "The following categories are now imported:\n%(categories)s"
msgctxt "model:ir.message,text:msg_wiz_transactions_found"
-msgid "The following transactionen are now imported:\nBalance: %(balance)s\nNumber of transactions: %(quantity)s"
-msgstr "The following transactionen are now imported:\nBalance: %(balance)s\nNumber of transactions: %(quantity)s"
+msgid "The following transactionen are now imported:\nCredit: %(credit)s\nDebit: %(debit)s\nBalance: %(balance)s\nNumber of transactions: %(quantity)s"
+msgstr "The following transactionen are now imported:\nCredit: %(credit)s\nDebit: %(debit)s\nBalance: %(balance)s\nNumber of transactions: %(quantity)s"
msgctxt "model:ir.message,text:msg_wiz_parties_found"
msgid "The following %(numparties)s parties are now imported:"
@@ -58,6 +58,10 @@ msgctxt "model:ir.action,name:qif_category_report"
msgid "Export QIF-File"
msgstr "Export QIF-File"
+msgctxt "model:ir.action,name:qif_transaction_report"
+msgid "Export QIF-File"
+msgstr "Export QIF-File"
+
msgctxt "model:cashbook_dataexchange.qif_imp_wiz,name:"
msgid "Import QIF-File"
msgstr "Import QIF-File"
diff --git a/qif_export.py b/qif_export.py
index d54d9c4..b764cd7 100644
--- a/qif_export.py
+++ b/qif_export.py
@@ -5,6 +5,8 @@
from trytond.report import Report
from trytond.pool import Pool
+from slugify import slugify
+
class QifCategoryExport(Report):
@@ -25,3 +27,38 @@ class QifCategoryExport(Report):
'%s-categories' % IrDate.today().isoformat().replace('-', ''))
# end QifCategoryExport
+
+
+class QifBookExport(Report):
+ __name__ = 'cashbook_dataexchange.rep_book'
+
+ @classmethod
+ def execute(cls, ids, data):
+ """ filename for export
+ """
+ pool = Pool()
+ IrDate = pool.get('ir.date')
+ Book = pool.get('cashbook.book')
+
+ books = Book.search([('id', '=', data.get('id', -1))])
+ if len(books) == 1:
+ return (
+ 'qif',
+ Book.export_as_qif(books[0]),
+ False,
+ slugify('%(date)s-transactions-%(book)s' % {
+ 'date': IrDate.today().isoformat().replace('-', ''),
+ 'book': books[0].name,
+ }, max_length=100, word_boundary=True, save_order=True),
+ )
+ else :
+ return (
+ 'txt',
+ 'not cashbook found',
+ False,
+ '%(date)s-transactions-%(book)s' % {
+ 'date': IrDate.today().isoformat().replace('-', ''),
+ 'book': 'not-found',
+ })
+
+# end QifBookExport
diff --git a/qif_export.xml b/qif_export.xml
index 26507a9..b9b32f6 100644
--- a/qif_export.xml
+++ b/qif_export.xml
@@ -19,5 +19,19 @@ full copyright notices and license terms. -->
+
+ Export QIF-File
+ cashbook.book
+ cashbook_dataexchange.rep_book
+ cashbook_dataexchange/report/export.fods
+ ods
+
+
+
+ form_action
+ cashbook.book,-1
+
+
+
diff --git a/qiftool.py b/qiftool.py
index 2625775..1f9e48c 100644
--- a/qiftool.py
+++ b/qiftool.py
@@ -6,6 +6,7 @@
from trytond.pool import Pool
from trytond.model import Model
from trytond.i18n import gettext
+from trytond.report import Report
from decimal import Decimal
from datetime import datetime
@@ -119,6 +120,78 @@ class QifTool(Model):
result.append(booking)
return result
+ @classmethod
+ def qif_export_book(cls, book):
+ """ export book
+ """
+ result = ['!Type:Bank']
+
+ def get_amount_by_bookingstate(amount, line):
+ """ get amount with sign
+ """
+ if line.bookingtype in ['in', 'spin', 'mvin']:
+ return amount
+ elif line.bookingtype in ['out', 'spout', 'mvout']:
+ return amount * Decimal('-1.0')
+ else :
+ raise ValueError('invalid bookingtype: %s' % line.bookingtype)
+
+ for line in book.lines:
+ # date
+ result.append('D%(date)s' % {
+ 'date': Report.format_date(line.date, None),
+ })
+ # total
+ result.append('T%(total)s' % {
+ 'total': Report.format_number(get_amount_by_bookingstate(line.amount, line), None),
+ })
+ # state
+ result.append('C%(state)s' % {
+ 'state': 'X' if line.state in ['check', 'done'] else '*',
+ })
+ # party
+ if line.party:
+ result.append('P%(party)s' % {
+ 'party': line.party.rec_name,
+ })
+ # address
+ p_address = line.party.address_get()
+ if p_address:
+ if len(p_address.full_address.strip()) > 0:
+ result.append('A%(address)s' % {
+ 'address': p_address.full_address.replace('\n', ', ').strip(),
+ })
+ # category
+ if line.category:
+ result.append('L%(category)s' % {
+ 'category': line.category.rec_name.replace('/', ':'),
+ })
+ # account
+ if line.booktransf:
+ result.append('L[%(account)s]' % {
+ 'account': line.booktransf.name,
+ })
+ # description
+ if line.description:
+ result.append('M%(memo)s' % {
+ 'memo': line.description.replace('\n', '; ')
+ })
+
+ # split-booking
+ for splitline in line.splitlines:
+ result.append('S%(category)s' % {
+ 'category': splitline.category.rec_name.replace('/', ':'),
+ })
+ if splitline.description:
+ result.append('E%(memo)s' % {
+ 'memo': splitline.description.replace('\n', '; ')
+ })
+ result.append('$%(total)s' % {
+ 'total': Report.format_number(get_amount_by_bookingstate(splitline.amount, line), None),
+ })
+ result.append('^')
+ return '\n'.join(result)
+
@classmethod
def get_party_by_name(cls, partyname):
""" find party
diff --git a/setup.py b/setup.py
index 61227b6..acb487d 100644
--- a/setup.py
+++ b/setup.py
@@ -42,7 +42,7 @@ with open(path.join(here, 'versiondep.txt'), encoding='utf-8') as f:
major_version = 6
minor_version = 0
-requires = []
+requires = ['python-slugify']
for dep in info.get('depends', []):
if not re.match(r'(ir|res|webdav)(\W|$)', dep):
if dep in modversion.keys():
diff --git a/tests/test_transaction.py b/tests/test_transaction.py
index b400b73..49b6c0a 100644
--- a/tests/test_transaction.py
+++ b/tests/test_transaction.py
@@ -87,6 +87,8 @@ 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""")
@@ -105,4 +107,26 @@ Number of transactions: 3""")
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