From 7769f5f14aaf36b4b32078f20ab96feebc0e2263 Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Mon, 5 Jun 2023 20:22:53 +0200 Subject: [PATCH 01/62] Version 6.8.28 --- README.rst | 4 ++-- setup.py | 3 ++- tryton.cfg | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 83d5baa..c3b7389 100644 --- a/README.rst +++ b/README.rst @@ -9,7 +9,7 @@ pip install mds-cashbook Requires ======== -- Tryton 6.0 +- Tryton 6.8 How to ====== @@ -153,6 +153,6 @@ currency are converted into the display currency of the parent cash book. Changes ======= -*6.0.0 - 05.08.2022* +*6.8.28 - 05.06.2023* - init diff --git a/setup.py b/setup.py index ff59617..0552dca 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,7 @@ with open(path.join(here, 'versiondep.txt'), encoding='utf-8') as f: # tryton-version major_version = 6 -minor_version = 0 +minor_version = 8 requires = ['python-slugify'] for dep in info.get('depends', []): @@ -89,6 +89,7 @@ setup(name='%s_%s' % (PREFIX, MODULE), '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', diff --git a/tryton.cfg b/tryton.cfg index ea57ba7..2df358a 100644 --- a/tryton.cfg +++ b/tryton.cfg @@ -1,5 +1,5 @@ [tryton] -version=6.0.0 +version=6.8.28 depends: res currency From 3a0df50d524e3f40725c7b194d3827d9c09f2f3e Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Thu, 8 Jun 2023 17:08:47 +0200 Subject: [PATCH 03/62] line, type: fix index --- line.py | 2 +- types.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/line.py b/line.py index 18cbb3e..6a202f5 100644 --- a/line.py +++ b/line.py @@ -245,7 +245,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): (t.state, Index.Equality())), Index( t, - (t.reference, Index.Range())), + (t.reference, Index.Equality())), }) cls._sql_constraints.extend([ ('state_val2', diff --git a/types.py b/types.py index 1217adf..42bb54d 100644 --- a/types.py +++ b/types.py @@ -3,7 +3,7 @@ # The COPYRIGHT file at the top level of this repository contains the # full copyright notices and license terms. -from trytond.model import ModelView, ModelSQL, fields, Unique +from trytond.model import ModelView, ModelSQL, fields, Unique, Index from trytond.transaction import Transaction from trytond.i18n import gettext @@ -30,6 +30,11 @@ class Type(ModelSQL, ModelView): cls._sql_constraints.extend([ ('code_uniq', Unique(t, t.short), 'cashbook.msg_type_short_unique'), ]) + cls._sql_indexes.update({ + Index( + t, + (t.feature, Index.Equality())), + }) @classmethod def default_feature(cls): From e605d5f0d379a25859d5c4691e1e1382c8c52b9b Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Thu, 8 Jun 2023 17:08:47 +0200 Subject: [PATCH 04/62] line, type: fix index --- line.py | 2 +- types.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/line.py b/line.py index 18cbb3e..6a202f5 100644 --- a/line.py +++ b/line.py @@ -245,7 +245,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): (t.state, Index.Equality())), Index( t, - (t.reference, Index.Range())), + (t.reference, Index.Equality())), }) cls._sql_constraints.extend([ ('state_val2', diff --git a/types.py b/types.py index 1217adf..42bb54d 100644 --- a/types.py +++ b/types.py @@ -3,7 +3,7 @@ # The COPYRIGHT file at the top level of this repository contains the # full copyright notices and license terms. -from trytond.model import ModelView, ModelSQL, fields, Unique +from trytond.model import ModelView, ModelSQL, fields, Unique, Index from trytond.transaction import Transaction from trytond.i18n import gettext @@ -30,6 +30,11 @@ class Type(ModelSQL, ModelView): cls._sql_constraints.extend([ ('code_uniq', Unique(t, t.short), 'cashbook.msg_type_short_unique'), ]) + cls._sql_indexes.update({ + Index( + t, + (t.feature, Index.Equality())), + }) @classmethod def default_feature(cls): From e017f20df4acc947da9273cc395eff8c84251103 Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Mon, 24 Jul 2023 16:35:19 +0200 Subject: [PATCH 05/62] Version 6.8.29 --- README.rst | 4 ++++ tryton.cfg | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index c3b7389..53341d7 100644 --- a/README.rst +++ b/README.rst @@ -153,6 +153,10 @@ currency are converted into the display currency of the parent cash book. Changes ======= +*6.8.29 - 24.07.2023* + +- fix: type of indexes + *6.8.28 - 05.06.2023* - init diff --git a/tryton.cfg b/tryton.cfg index 2df358a..f020b81 100644 --- a/tryton.cfg +++ b/tryton.cfg @@ -1,5 +1,5 @@ [tryton] -version=6.8.28 +version=6.8.29 depends: res currency From 7a4fd94981910e89810b9a75443dd256f41556a0 Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Mon, 24 Jul 2023 17:31:34 +0200 Subject: [PATCH 07/62] optimize search-queries, line: fix state-selection --- book.py | 2 +- line.py | 16 ++++++++-------- reconciliation.py | 12 ++++++------ splitline.py | 4 ++-- wizard_booking.py | 2 +- wizard_runreport.py | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/book.py b/book.py index 3e3fa0f..a4fd5a7 100644 --- a/book.py +++ b/book.py @@ -574,7 +574,7 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): 'defbook', 'book1', 'book2', 'book3', 'book4', 'book5']: cfg1 = ConfigUser.search([ - ('iduser.id', '=', book.owner.id), + ('iduser', '=', book.owner.id), ('%s.id' % x, '=', book.id)]) if len(cfg1) > 0: to_write_config.extend([cfg1, {x: None}]) diff --git a/line.py b/line.py index 6a202f5..41c6c9a 100644 --- a/line.py +++ b/line.py @@ -23,7 +23,7 @@ sel_payee = [ ('party.party', 'Party') ] -sel_linetype = [ +sel_linestate = [ ('edit', 'Edit'), ('check', 'Checked'), ('recon', 'Reconciled'), @@ -197,7 +197,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): state = fields.Selection( string='State', required=True, readonly=True, - selection=sel_linetype) + selection=sel_linestate) state_string = state.translated('state') state_cashbook = fields.Function(fields.Selection( string='State of Cashbook', @@ -375,7 +375,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): # allow cashbook-line at range-limits if Recon.search_count([ ('state', 'in', ['check', 'done']), - ('cashbook.id', '=', line.cashbook.id), + ('cashbook', '=', line.cashbook.id), ('date_from', '<', line.date), ('date_to', '>', line.date)]) > 0: raise UserError(gettext( @@ -386,7 +386,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): # reconciliations exist if Recon.search_count([ ('state', 'in', ['check', 'done']), - ('cashbook.id', '=', line.cashbook.id), + ('cashbook', '=', line.cashbook.id), ['OR', ('date_from', '=', line.date), ('date_to', '=', line.date)]]) > 1: @@ -751,7 +751,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): end_value = None recons = Reconciliation.search([ - ('cashbook.id', '=', line.cashbook.id), + ('cashbook', '=', line.cashbook.id), ('date_to', '<=', line2.date), ('state', '=', 'done'), ], order=[('date_from', 'DESC')], limit=1) @@ -761,14 +761,14 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): ('date', '<=', line2.date), ['OR', ('reconciliation', '=', None), - ('reconciliation.id', '!=', recons[0])], + ('reconciliation', '!=', recons[0])], ]) end_value = getattr(recons[0], 'end_%s' % field_name) return (query2, end_value) if line.cashbook: query = [ - ('cashbook.id', '=', line.cashbook.id), + ('cashbook', '=', line.cashbook.id), ] balance = Decimal('0.0') @@ -778,7 +778,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): if line.reconciliation: if line.reconciliation.state == 'done': query.append( - ('reconciliation.id', '=', line.reconciliation.id), + ('reconciliation', '=', line.reconciliation.id), ) balance = getattr( line.reconciliation, 'start_%s' % field_name) diff --git a/reconciliation.py b/reconciliation.py index 044f85c..e27e0c9 100644 --- a/reconciliation.py +++ b/reconciliation.py @@ -183,7 +183,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView): if Line.search_count([ ('date', '>', reconciliation.date_from), ('date', '<', reconciliation.date_to), - ('cashbook.id', '=', reconciliation.cashbook.id), + ('cashbook', '=', reconciliation.cashbook.id), ('state', 'not in', ['check', 'recon']), ]) > 0: raise UserError(gettext( @@ -224,7 +224,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView): lines = Line.search([ ('date', '>=', reconciliation.date_from), ('date', '<=', reconciliation.date_to), - ('cashbook.id', '=', reconciliation.cashbook.id), + ('cashbook', '=', reconciliation.cashbook.id), ('reconciliation', '=', None), ('state', 'in', ['check', 'recon']), ]) @@ -315,7 +315,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView): # deny if there are lines not linked to reconciliation if Line.search_count([ - ('cashbook.id', '=', reconciliation.cashbook.id), + ('cashbook', '=', reconciliation.cashbook.id), ('reconciliation', '=', None), ['OR', [ # lines inside of date-range @@ -405,7 +405,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView): if self.cashbook: if self.date_from is not None: reconciliations = Recon.search([ - ('cashbook.id', '=', self.cashbook.id), + ('cashbook', '=', self.cashbook.id), ('date_from', '<', self.date_from), ], order=[('date_from', 'DESC')], limit=1) if len(reconciliations) > 0: @@ -457,7 +457,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView): # set date_from to date_to of predecessor recons = Recon.search([ - ('cashbook.id', '=', id_cashbook), + ('cashbook', '=', id_cashbook), ], order=[('date_to', 'DESC')], limit=1) if len(recons) > 0: values['date_from'] = recons[0].date_to @@ -466,7 +466,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView): # set date_to to day of last 'checked'-booking in selected cashbook lines = Line.search([ - ('cashbook.id', '=', id_cashbook), + ('cashbook', '=', id_cashbook), ('state', '=', 'check'), ('reconciliation', '=', None), ], order=[('date', 'DESC')], limit=1) diff --git a/splitline.py b/splitline.py index a09bd77..79e78df 100644 --- a/splitline.py +++ b/splitline.py @@ -9,7 +9,7 @@ from trytond.pool import Pool from trytond.pyson import Eval, If from trytond.report import Report from trytond.i18n import gettext -from .line import sel_bookingtype, STATES, DEPENDS +from .line import sel_bookingtype, sel_linestate, STATES, DEPENDS from .book import sel_state_book from .mixin import SecondCurrencyMixin, MemCacheIndexMx @@ -90,7 +90,7 @@ class SplitLine(SecondCurrencyMixin, MemCacheIndexMx, ModelSQL, ModelView): selection=sel_bookingtype), 'on_change_with_bookingtype') state = fields.Function(fields.Selection( string='State', readonly=True, - selection=sel_linetype), 'on_change_with_state') + selection=sel_linestate), 'on_change_with_state') cashbook = fields.Function(fields.Many2One( string='Cashbook', readonly=True, states={'invisible': True}, model_name='cashbook.book'), diff --git a/wizard_booking.py b/wizard_booking.py index ef27f32..429deae 100644 --- a/wizard_booking.py +++ b/wizard_booking.py @@ -152,7 +152,7 @@ class EnterBookingWizard(Wizard): 'cashbooks': [x.id for x in Cashbook.search([ ('state', '=', 'open'), ('btype', '!=', None), - ('owner.id', '=', Transaction().user), + ('owner', '=', Transaction().user), ('id', 'in', book_ids), ])], 'bookingtype': getattr(self.start, 'bookingtype', 'out'), diff --git a/wizard_runreport.py b/wizard_runreport.py index 534f521..d2b4fc2 100644 --- a/wizard_runreport.py +++ b/wizard_runreport.py @@ -55,7 +55,7 @@ class RunCbReportStart(ModelView): if self.cashbook: recons = Recon2.search([ - ('cashbook.id', '=', self.cashbook.id), + ('cashbook', '=', self.cashbook.id), ], order=[('date_from', 'DESC')]) return [x.id for x in recons] @@ -103,7 +103,7 @@ class RunCbReport(Wizard): result['cashbook'] = result['cashbooks'][0] recons = Recon2.search([ - ('cashbook.id', '=', result['cashbook']), + ('cashbook', '=', result['cashbook']), ], order=[('date_from', 'DESC')]) if len(recons) > 0: result['reconciliations'] = [x.id for x in recons] From 90298d3eb862a5a3dc5946a4c9b820626081f359 Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Mon, 24 Jul 2023 17:31:34 +0200 Subject: [PATCH 08/62] optimize search-queries, line: fix state-selection --- book.py | 2 +- line.py | 16 ++++++++-------- reconciliation.py | 12 ++++++------ splitline.py | 4 ++-- wizard_booking.py | 2 +- wizard_runreport.py | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/book.py b/book.py index 3e3fa0f..a4fd5a7 100644 --- a/book.py +++ b/book.py @@ -574,7 +574,7 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): 'defbook', 'book1', 'book2', 'book3', 'book4', 'book5']: cfg1 = ConfigUser.search([ - ('iduser.id', '=', book.owner.id), + ('iduser', '=', book.owner.id), ('%s.id' % x, '=', book.id)]) if len(cfg1) > 0: to_write_config.extend([cfg1, {x: None}]) diff --git a/line.py b/line.py index 6a202f5..41c6c9a 100644 --- a/line.py +++ b/line.py @@ -23,7 +23,7 @@ sel_payee = [ ('party.party', 'Party') ] -sel_linetype = [ +sel_linestate = [ ('edit', 'Edit'), ('check', 'Checked'), ('recon', 'Reconciled'), @@ -197,7 +197,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): state = fields.Selection( string='State', required=True, readonly=True, - selection=sel_linetype) + selection=sel_linestate) state_string = state.translated('state') state_cashbook = fields.Function(fields.Selection( string='State of Cashbook', @@ -375,7 +375,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): # allow cashbook-line at range-limits if Recon.search_count([ ('state', 'in', ['check', 'done']), - ('cashbook.id', '=', line.cashbook.id), + ('cashbook', '=', line.cashbook.id), ('date_from', '<', line.date), ('date_to', '>', line.date)]) > 0: raise UserError(gettext( @@ -386,7 +386,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): # reconciliations exist if Recon.search_count([ ('state', 'in', ['check', 'done']), - ('cashbook.id', '=', line.cashbook.id), + ('cashbook', '=', line.cashbook.id), ['OR', ('date_from', '=', line.date), ('date_to', '=', line.date)]]) > 1: @@ -751,7 +751,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): end_value = None recons = Reconciliation.search([ - ('cashbook.id', '=', line.cashbook.id), + ('cashbook', '=', line.cashbook.id), ('date_to', '<=', line2.date), ('state', '=', 'done'), ], order=[('date_from', 'DESC')], limit=1) @@ -761,14 +761,14 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): ('date', '<=', line2.date), ['OR', ('reconciliation', '=', None), - ('reconciliation.id', '!=', recons[0])], + ('reconciliation', '!=', recons[0])], ]) end_value = getattr(recons[0], 'end_%s' % field_name) return (query2, end_value) if line.cashbook: query = [ - ('cashbook.id', '=', line.cashbook.id), + ('cashbook', '=', line.cashbook.id), ] balance = Decimal('0.0') @@ -778,7 +778,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): if line.reconciliation: if line.reconciliation.state == 'done': query.append( - ('reconciliation.id', '=', line.reconciliation.id), + ('reconciliation', '=', line.reconciliation.id), ) balance = getattr( line.reconciliation, 'start_%s' % field_name) diff --git a/reconciliation.py b/reconciliation.py index 044f85c..e27e0c9 100644 --- a/reconciliation.py +++ b/reconciliation.py @@ -183,7 +183,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView): if Line.search_count([ ('date', '>', reconciliation.date_from), ('date', '<', reconciliation.date_to), - ('cashbook.id', '=', reconciliation.cashbook.id), + ('cashbook', '=', reconciliation.cashbook.id), ('state', 'not in', ['check', 'recon']), ]) > 0: raise UserError(gettext( @@ -224,7 +224,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView): lines = Line.search([ ('date', '>=', reconciliation.date_from), ('date', '<=', reconciliation.date_to), - ('cashbook.id', '=', reconciliation.cashbook.id), + ('cashbook', '=', reconciliation.cashbook.id), ('reconciliation', '=', None), ('state', 'in', ['check', 'recon']), ]) @@ -315,7 +315,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView): # deny if there are lines not linked to reconciliation if Line.search_count([ - ('cashbook.id', '=', reconciliation.cashbook.id), + ('cashbook', '=', reconciliation.cashbook.id), ('reconciliation', '=', None), ['OR', [ # lines inside of date-range @@ -405,7 +405,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView): if self.cashbook: if self.date_from is not None: reconciliations = Recon.search([ - ('cashbook.id', '=', self.cashbook.id), + ('cashbook', '=', self.cashbook.id), ('date_from', '<', self.date_from), ], order=[('date_from', 'DESC')], limit=1) if len(reconciliations) > 0: @@ -457,7 +457,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView): # set date_from to date_to of predecessor recons = Recon.search([ - ('cashbook.id', '=', id_cashbook), + ('cashbook', '=', id_cashbook), ], order=[('date_to', 'DESC')], limit=1) if len(recons) > 0: values['date_from'] = recons[0].date_to @@ -466,7 +466,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView): # set date_to to day of last 'checked'-booking in selected cashbook lines = Line.search([ - ('cashbook.id', '=', id_cashbook), + ('cashbook', '=', id_cashbook), ('state', '=', 'check'), ('reconciliation', '=', None), ], order=[('date', 'DESC')], limit=1) diff --git a/splitline.py b/splitline.py index a09bd77..79e78df 100644 --- a/splitline.py +++ b/splitline.py @@ -9,7 +9,7 @@ from trytond.pool import Pool from trytond.pyson import Eval, If from trytond.report import Report from trytond.i18n import gettext -from .line import sel_bookingtype, STATES, DEPENDS +from .line import sel_bookingtype, sel_linestate, STATES, DEPENDS from .book import sel_state_book from .mixin import SecondCurrencyMixin, MemCacheIndexMx @@ -90,7 +90,7 @@ class SplitLine(SecondCurrencyMixin, MemCacheIndexMx, ModelSQL, ModelView): selection=sel_bookingtype), 'on_change_with_bookingtype') state = fields.Function(fields.Selection( string='State', readonly=True, - selection=sel_linetype), 'on_change_with_state') + selection=sel_linestate), 'on_change_with_state') cashbook = fields.Function(fields.Many2One( string='Cashbook', readonly=True, states={'invisible': True}, model_name='cashbook.book'), diff --git a/wizard_booking.py b/wizard_booking.py index ef27f32..429deae 100644 --- a/wizard_booking.py +++ b/wizard_booking.py @@ -152,7 +152,7 @@ class EnterBookingWizard(Wizard): 'cashbooks': [x.id for x in Cashbook.search([ ('state', '=', 'open'), ('btype', '!=', None), - ('owner.id', '=', Transaction().user), + ('owner', '=', Transaction().user), ('id', 'in', book_ids), ])], 'bookingtype': getattr(self.start, 'bookingtype', 'out'), diff --git a/wizard_runreport.py b/wizard_runreport.py index 534f521..d2b4fc2 100644 --- a/wizard_runreport.py +++ b/wizard_runreport.py @@ -55,7 +55,7 @@ class RunCbReportStart(ModelView): if self.cashbook: recons = Recon2.search([ - ('cashbook.id', '=', self.cashbook.id), + ('cashbook', '=', self.cashbook.id), ], order=[('date_from', 'DESC')]) return [x.id for x in recons] @@ -103,7 +103,7 @@ class RunCbReport(Wizard): result['cashbook'] = result['cashbooks'][0] recons = Recon2.search([ - ('cashbook.id', '=', result['cashbook']), + ('cashbook', '=', result['cashbook']), ], order=[('date_from', 'DESC')]) if len(recons) > 0: result['reconciliations'] = [x.id for x in recons] From aac69309996599af4ac8b6a48843c283849c0086 Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Tue, 25 Jul 2023 21:11:32 +0200 Subject: [PATCH 09/62] splitline: add tests --- tests/splitline.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/splitline.py b/tests/splitline.py index 629b7e9..477e23b 100644 --- a/tests/splitline.py +++ b/tests/splitline.py @@ -73,6 +73,26 @@ class SplitLineTestCase(object): book.lines[0].splitlines[1].rec_name, 'Rev/Sp|6.00 usd|from cashbook [Cat1]') + # check function fields + self.assertEqual( + book.lines[0].splitlines[0].category_view, + 'Cat1') + self.assertEqual(book.lines[0].splitlines[0].date, date(2022, 5, 1)) + self.assertEqual(book.lines[0].splitlines[0].target.rec_name, 'Cat1') + self.assertEqual(book.lines[0].splitlines[0].currency.rec_name, 'usd') + self.assertEqual(book.lines[0].splitlines[0].currency_digits, 2) + self.assertEqual(book.lines[0].splitlines[0].bookingtype, 'spin') + self.assertEqual(book.lines[0].splitlines[0].state, 'edit') + self.assertEqual( + book.lines[0].splitlines[0].cashbook.rec_name, + 'Book 1 | 11.00 usd | Open') + self.assertEqual(book.lines[0].splitlines[0].feature, 'gen') + self.assertEqual(book.lines[0].splitlines[0].booktransf_feature, None) + self.assertEqual(book.lines[0].splitlines[0].state_cashbook, 'open') + self.assertEqual( + book.lines[0].splitlines[0].owner_cashbook.rec_name, + 'Administrator') + @with_transaction() def test_splitline_category_and_transfer(self): """ add book, line, two split-lines, From 77ee7d15b7ee71fac3d8bcf2aff2255b8de64b6f Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Tue, 25 Jul 2023 21:11:32 +0200 Subject: [PATCH 10/62] splitline: add tests --- tests/splitline.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/splitline.py b/tests/splitline.py index 629b7e9..477e23b 100644 --- a/tests/splitline.py +++ b/tests/splitline.py @@ -73,6 +73,26 @@ class SplitLineTestCase(object): book.lines[0].splitlines[1].rec_name, 'Rev/Sp|6.00 usd|from cashbook [Cat1]') + # check function fields + self.assertEqual( + book.lines[0].splitlines[0].category_view, + 'Cat1') + self.assertEqual(book.lines[0].splitlines[0].date, date(2022, 5, 1)) + self.assertEqual(book.lines[0].splitlines[0].target.rec_name, 'Cat1') + self.assertEqual(book.lines[0].splitlines[0].currency.rec_name, 'usd') + self.assertEqual(book.lines[0].splitlines[0].currency_digits, 2) + self.assertEqual(book.lines[0].splitlines[0].bookingtype, 'spin') + self.assertEqual(book.lines[0].splitlines[0].state, 'edit') + self.assertEqual( + book.lines[0].splitlines[0].cashbook.rec_name, + 'Book 1 | 11.00 usd | Open') + self.assertEqual(book.lines[0].splitlines[0].feature, 'gen') + self.assertEqual(book.lines[0].splitlines[0].booktransf_feature, None) + self.assertEqual(book.lines[0].splitlines[0].state_cashbook, 'open') + self.assertEqual( + book.lines[0].splitlines[0].owner_cashbook.rec_name, + 'Administrator') + @with_transaction() def test_splitline_category_and_transfer(self): """ add book, line, two split-lines, From b237981a9be1d762f5f11e7c582d43709d14cae0 Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Tue, 25 Jul 2023 21:14:31 +0200 Subject: [PATCH 11/62] Version 6.8.30 --- README.rst | 4 ++++ tryton.cfg | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 53341d7..aa1c840 100644 --- a/README.rst +++ b/README.rst @@ -153,6 +153,10 @@ currency are converted into the display currency of the parent cash book. Changes ======= +*6.8.30 - 25.07.2023* + +- updt: optimize code, add tests + *6.8.29 - 24.07.2023* - fix: type of indexes diff --git a/tryton.cfg b/tryton.cfg index f020b81..2c2d189 100644 --- a/tryton.cfg +++ b/tryton.cfg @@ -1,5 +1,5 @@ [tryton] -version=6.8.29 +version=6.8.30 depends: res currency From 7220cff5acc3d81db808d321e99a0c192d18e493 Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Wed, 29 Nov 2023 15:19:38 +0100 Subject: [PATCH 13/62] formatting, indexes optimized --- book.py | 15 +++-------- category.py | 3 ++- configuration.py | 45 ++++++++++++-------------------- const.py | 8 ++++++ currency.py | 3 ++- line.py | 51 ++++++++++++++++++------------------ mixin.py | 15 +++++------ model.py | 4 ++- reconciliation.py | 25 +++++++++++------- setup.py | 66 ++++++++++++++++++++++++----------------------- types.py | 10 +++---- wizard_booking.py | 5 ++-- 12 files changed, 124 insertions(+), 126 deletions(-) create mode 100644 const.py diff --git a/book.py b/book.py index a4fd5a7..872f54a 100644 --- a/book.py +++ b/book.py @@ -74,8 +74,7 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): states={ 'readonly': Or( STATES['readonly'], - Len(Eval('lines')) > 0, - ), + Len(Eval('lines')) > 0), }, depends=DEPENDS+['lines']) feature = fields.Function(fields.Char( string='Feature', readonly=True, @@ -124,8 +123,7 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): states={ 'readonly': Or( STATES2['readonly'], - Len(Eval('lines')) > 0, - ), + Len(Eval('lines')) > 0), 'invisible': STATES2['invisible'], 'required': ~STATES2['invisible'], }, depends=DEPENDS2+['lines']) @@ -165,8 +163,7 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): states={ 'readonly': Or( STATES2['readonly'], - Len(Eval('lines', [])) > 0, - ), + Len(Eval('lines', [])) > 0), }, depends=DEPENDS2+['lines']) currency_digits = fields.Function(fields.Integer( string='Currency Digits', @@ -202,9 +199,6 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): Index( t, (t.btype, Index.Equality())), - Index( - t, - (t.parent, Index.Equality())), Index( t, (t.company, Index.Equality())), @@ -396,8 +390,7 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): query = tab_line.select( tab_line.cashbook, where=Operator( - getattr(tab_line, name), clause[2]), - ) + getattr(tab_line, name), clause[2])) return [('id', 'in', query)] @classmethod diff --git a/category.py b/category.py index 888697a..a10b3d1 100644 --- a/category.py +++ b/category.py @@ -11,6 +11,7 @@ from trytond.exceptions import UserError from trytond.i18n import gettext from sql.operators import Equal from .model import order_name_hierarchical +from .const import DEF_NONE sel_categorytype = [ @@ -70,7 +71,7 @@ class Category(tree(separator='/'), ModelSQL, ModelView): t, (t.name, Equal), (t.cattype, Equal), - where=(t.parent == None)), + where=(t.parent == DEF_NONE)), 'cashbook.msg_category_name_unique'), ]) diff --git a/configuration.py b/configuration.py index 2da84ee..2f2f5db 100644 --- a/configuration.py +++ b/configuration.py @@ -17,7 +17,8 @@ field_done = fields.Boolean( help='Show cashbook lines in Done-state.') field_catnamelong = fields.Boolean( string='Category: Show long name', - help='Shows the long name of the category in the Category field of a cash book line.') + help='Shows the long name of the category in the Category ' + + 'field of a cash book line.') class Configuration(ModelSingleton, ModelSQL, ModelView, UserMultiValueMixin): @@ -29,60 +30,47 @@ class Configuration(ModelSingleton, ModelSQL, ModelView, UserMultiValueMixin): domain=[ If(Eval('date_to') & Eval('date_from'), ('date_from', '<=', Eval('date_to')), - ()), - ])) + ())])) date_to = fields.MultiValue(fields.Date( string='End Date', depends=['date_from'], domain=[ If(Eval('date_to') & Eval('date_from'), ('date_from', '<=', Eval('date_to')), - ()), - ])) + ())])) checked = fields.MultiValue(field_checked) done = fields.MultiValue(field_done) catnamelong = fields.MultiValue(field_catnamelong) defbook = fields.MultiValue(fields.Many2One( string='Default Cashbook', - help='The default cashbook is selected when you open the booking wizard.', + help='The default cashbook is selected when you open ' + + 'the booking wizard.', model_name='cashbook.book', ondelete='SET NULL', - domain=[ - ('btype', '!=', None), ('state', '=', 'open'), - ])) + domain=[('btype', '!=', None), ('state', '=', 'open')])) book1 = fields.MultiValue(fields.Many2One( string='Cashbook 1', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', - domain=[ - ('btype', '!=', None), ('state', '=', 'open'), - ])) + domain=[('btype', '!=', None), ('state', '=', 'open')])) book2 = fields.MultiValue(fields.Many2One( string='Cashbook 2', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', - domain=[ - ('btype', '!=', None), ('state', '=', 'open'), - ])) + domain=[('btype', '!=', None), ('state', '=', 'open')])) book3 = fields.MultiValue(fields.Many2One( string='Cashbook 3', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', - domain=[ - ('btype', '!=', None), ('state', '=', 'open'), - ])) + domain=[('btype', '!=', None), ('state', '=', 'open')])) book4 = fields.MultiValue(fields.Many2One( string='Cashbook 4', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', - domain=[ - ('btype', '!=', None), ('state', '=', 'open'), - ])) + domain=[('btype', '!=', None), ('state', '=', 'open')])) book5 = fields.MultiValue(fields.Many2One( string='Cashbook 5', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', - domain=[ - ('btype', '!=', None), ('state', '=', 'open'), - ])) + domain=[('btype', '!=', None), ('state', '=', 'open')])) @classmethod def multivalue_model(cls, field): @@ -121,21 +109,20 @@ class UserConfiguration(ModelSQL, UserValueMixin): domain=[ If(Eval('date_to') & Eval('date_from'), ('date_from', '<=', Eval('date_to')), - ()), - ]) + ())]) date_to = fields.Date( string='End Date', depends=['date_from'], domain=[ If(Eval('date_to') & Eval('date_from'), ('date_from', '<=', Eval('date_to')), - ()), - ]) + ())]) checked = field_checked done = field_done catnamelong = field_catnamelong defbook = fields.Many2One( string='Default Cashbook', - help='The default cashbook is selected when you open the booking wizard.', + help='The default cashbook is selected when you open ' + + 'the booking wizard.', model_name='cashbook.book', ondelete='SET NULL', domain=[ ('btype', '!=', None), diff --git a/const.py b/const.py new file mode 100644 index 0000000..6eaa075 --- /dev/null +++ b/const.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# This file is part of the cashbook-module from m-ds.de for Tryton. +# The COPYRIGHT file at the top level of this repository contains the +# full copyright notices and license terms. + + +DEF_NONE = None + diff --git a/currency.py b/currency.py index 9d406c6..817812f 100644 --- a/currency.py +++ b/currency.py @@ -42,7 +42,8 @@ class CurrencyRate(metaclass=PoolMeta): MemCache = Pool().get('cashbook.memcache') for record in records: - MemCache.record_update(CACHEKEY_CURRENCY % record.currency.id, None) + MemCache.record_update( + CACHEKEY_CURRENCY % record.currency.id, None) super(CurrencyRate, cls).delete(records) # end diff --git a/line.py b/line.py index 41c6c9a..45dae05 100644 --- a/line.py +++ b/line.py @@ -16,6 +16,7 @@ from sql.functions import DatePart from sql.conditionals import Case from .book import sel_state_book from .mixin import SecondCurrencyMixin, MemCacheIndexMx +from .const import DEF_NONE sel_payee = [ @@ -48,7 +49,9 @@ STATES = { DEPENDS = ['state', 'state_cashbook'] -class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): +class Line( + SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, + ModelView): 'Cashbook Line' __name__ = 'cashbook.line' @@ -75,8 +78,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): states={ 'readonly': Or( STATES['readonly'], - Bool(Eval('bookingtype')) == False, - ), + ~Bool(Eval('bookingtype'))), 'required': Eval('bookingtype', '').in_(['in', 'out']), 'invisible': ~Eval('bookingtype', '').in_(['in', 'out']), }, depends=DEPENDS+['bookingtype'], @@ -161,7 +163,8 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): splitlines = fields.One2Many( string='Split booking lines', model_name='cashbook.split', - help='Rows with different categories form the total sum of the booking', + help='Rows with different categories form the total ' + + 'sum of the booking', states={ 'invisible': ~Eval('bookingtype' '').in_(['spin', 'spout']), 'readonly': Or( @@ -225,9 +228,6 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): t = cls.__table__() cls._sql_indexes.update({ - Index( - t, - (t.cashbook, Index.Equality())), Index( t, (t.date, Index.Range(order='ASC'))), @@ -308,7 +308,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): ).select( tab_line.id, where=tab_line.bookingtype.in_(['mvin', 'mvout']) & - (tab_line.amount_2nd_currency == None) & + (tab_line.amount_2nd_currency == DEF_NONE) & (tab_book.currency != tab_book2.currency) ) lines = Line2.search([('id', 'in', query)]) @@ -344,7 +344,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): for line in lines: if line.reference: if Transaction().context.get( - 'line.allow.wfedit', False) == False: + 'line.allow.wfedit', False) is False: raise UserError(gettext( 'cashbook.msg_line_denywf_by_reference', recname=line.reference.rec_name, @@ -508,19 +508,20 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): """ credit = self.credit if self.credit is not None else Decimal('0.0') debit = self.debit if self.debit is not None else Decimal('0.0') - return '%(date)s|%(type)s|%(amount)s %(symbol)s|%(desc)s [%(category)s]' % { - 'date': Report.format_date(self.date), - 'desc': (self.description or '-')[:40], - 'amount': Report.format_number( - credit - debit, None, - digits=getattr(self.currency, 'digits', 2)), - 'symbol': getattr(self.currency, 'symbol', '-'), - 'category': self.category_view - if self.bookingtype in ['in', 'out'] - else getattr(self.booktransf, 'rec_name', '-'), - 'type': gettext( - 'cashbook.msg_line_bookingtype_%s' % - self.bookingtype)} + return '|'.join([ + Report.format_date(self.date), + gettext('cashbook.msg_line_bookingtype_%s' % self.bookingtype), + '%(amount)s %(symbol)s' % { + 'amount': Report.format_number( + credit - debit, None, + digits=getattr(self.currency, 'digits', 2)), + 'symbol': getattr(self.currency, 'symbol', '-')}, + '%(desc)s [%(category)s]' % { + 'desc': (self.description or '-')[:40], + 'category': self.category_view + if self.bookingtype in ['in', 'out'] + else getattr(self.booktransf, 'rec_name', '-')}, + ]) @staticmethod def order_state(tables): @@ -535,8 +536,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): (tab_line.state == 'edit', 1), (tab_line.state.in_(['check', 'recon', 'done']), 0), else_=2), - where=tab_line.id == table.id - ) + where=tab_line.id == table.id) return [query] @staticmethod @@ -626,7 +626,8 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): if self.bookingtype: if self.category: - if self.bookingtype not in types.get(self.category.cattype, ''): + if self.bookingtype not in types.get( + self.category.cattype, ''): self.category = None if self.bookingtype.startswith('sp'): # split booking diff --git a/mixin.py b/mixin.py index 5b4f054..363bed5 100644 --- a/mixin.py +++ b/mixin.py @@ -31,20 +31,19 @@ class SecondCurrencyMixin: states={ 'readonly': Or( STATES['readonly'], - ~Bool(Eval('currency2nd')) - ), + ~Bool(Eval('currency2nd'))), 'required': Bool(Eval('currency2nd')), 'invisible': ~Bool(Eval('currency2nd')), }, depends=DEPENDS+['currency2nd_digits', 'currency2nd']) rate_2nd_currency = fields.Function(fields.Numeric( string='Rate', - help='Exchange rate between the currencies of the participating cashbooks.', + help='Exchange rate between the currencies of the ' + + 'participating cashbooks.', digits=(rate_decimal * 2, rate_decimal), states={ 'readonly': Or( STATES['readonly'], - ~Bool(Eval('currency2nd')) - ), + ~Bool(Eval('currency2nd'))), 'required': Bool(Eval('currency2nd')), 'invisible': ~Bool(Eval('currency2nd')), }, depends=DEPENDS+['currency2nd_digits', 'currency2nd']), @@ -124,15 +123,13 @@ class SecondCurrencyMixin: self.amount_2nd_currency = Currency.compute( self.currency, self.amount, - self.booktransf.currency - ) + self.booktransf.currency) if self.amount != Decimal('0.0'): self.rate_2nd_currency = \ self.amount_2nd_currency / self.amount else: self.amount_2nd_currency = self.booktransf.currency.round( - self.amount * self.rate_2nd_currency - ) + self.amount * self.rate_2nd_currency) @classmethod def set_rate_2nd_currency(cls, lines, name, value): diff --git a/model.py b/model.py index 0d5598c..e7b4ebc 100644 --- a/model.py +++ b/model.py @@ -15,6 +15,8 @@ from sql import With from sql.functions import Function from sql.conditionals import Coalesce import copy +from .const import DEF_NONE + if config.get('cashbook', 'memcache', default='yes').lower() \ in ['yes', '1', 'true']: @@ -269,7 +271,7 @@ def order_name_hierarchical(model_name, tables): lines = With('id', 'name', 'name_path', recursive=True) lines.query = tab_mod.select( tab_mod.id, tab_mod.name, Array(tab_mod.name), - where=tab_mod.parent == None, + where=tab_mod.parent == DEF_NONE, ) lines.query |= tab_mod2.join( lines, diff --git a/reconciliation.py b/reconciliation.py index e27e0c9..d0d5196 100644 --- a/reconciliation.py +++ b/reconciliation.py @@ -204,7 +204,8 @@ class Reconciliation(Workflow, ModelSQL, ModelView): # unlink lines from reconciliation if len(reconciliation.lines) > 0: - values['lines'] = [('remove', [x.id for x in reconciliation.lines])] + values['lines'] = [ + ('remove', [x.id for x in reconciliation.lines])] return values @classmethod @@ -339,20 +340,24 @@ class Reconciliation(Workflow, ModelSQL, ModelView): def get_rec_name(self, name): """ short + name """ - return '%(from)s - %(to)s | %(start_amount)s %(symbol)s - %(end_amount)s %(symbol)s [%(num)s]' % { - 'from': Report.format_date(self.date_from, None) + return ' '.join([ + Report.format_date(self.date_from, None) if self.date_from is not None else '-', - 'to': Report.format_date(self.date_to, None) - if self.date_to is not None else '-', - 'start_amount': Report.format_number( + '-', + Report.format_date(self.date_to, None) + if self.date_to is not None else '-', + '|', + Report.format_number( self.start_amount or 0.0, None, digits=getattr(self.currency, 'digits', 2)), - 'end_amount': Report.format_number( + getattr(self.currency, 'symbol', '-'), + '-', + Report.format_number( self.end_amount or 0.0, None, digits=getattr(self.currency, 'digits', 2)), - 'symbol': getattr(self.currency, 'symbol', '-'), - 'num': len(self.lines), - } + getattr(self.currency, 'symbol', '-'), + '[%(num)s]' % {'num': len(self.lines)}, + ]) @classmethod def default_date_from(cls): diff --git a/setup.py b/setup.py index ff59617..0a3a2ba 100644 --- a/setup.py +++ b/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,7 +36,7 @@ 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 @@ -51,19 +51,21 @@ 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 a cashbook.', long_description=long_description, @@ -74,21 +76,21 @@ setup(name='%s_%s' % (PREFIX, MODULE), 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', ], keywords='tryton cashbook', @@ -97,10 +99,10 @@ setup(name='%s_%s' % (PREFIX, MODULE), 'trytond.modules.%s' % MODULE, ], package_data={ - 'trytond.modules.%s' % MODULE: (info.get('xml', []) - + ['tryton.cfg', 'locale/*.po', 'tests/*.py', - 'view/*.xml', 'icon/*.svg', 'docs/*.txt', - 'report/*.fods', 'versiondep.txt', 'README.rst']), + 'trytond.modules.%s' % MODULE: (info.get('xml', []) + [ + 'tryton.cfg', 'locale/*.po', 'tests/*.py', + 'view/*.xml', 'icon/*.svg', 'docs/*.txt', + 'report/*.fods', 'versiondep.txt', 'README.rst']), }, install_requires=requires, diff --git a/types.py b/types.py index 42bb54d..11bcaf5 100644 --- a/types.py +++ b/types.py @@ -28,7 +28,9 @@ class Type(ModelSQL, ModelView): cls._order.insert(0, ('name', 'ASC')) t = cls.__table__() cls._sql_constraints.extend([ - ('code_uniq', Unique(t, t.short), 'cashbook.msg_type_short_unique'), + ('code_uniq', + Unique(t, t.short), + 'cashbook.msg_type_short_unique'), ]) cls._sql_indexes.update({ Index( @@ -53,8 +55,7 @@ class Type(ModelSQL, ModelView): """ return '%(short)s - %(name)s' % { 'short': self.short or '-', - 'name': self.name or '-', - } + 'name': self.name or '-'} @classmethod def search_rec_name(cls, name, clause): @@ -63,8 +64,7 @@ class Type(ModelSQL, ModelView): return [ 'OR', ('name',) + tuple(clause[1:]), - ('short',) + tuple(clause[1:]), - ] + ('short',) + tuple(clause[1:])] @staticmethod def default_company(): diff --git a/wizard_booking.py b/wizard_booking.py index 429deae..9530a35 100644 --- a/wizard_booking.py +++ b/wizard_booking.py @@ -50,7 +50,7 @@ class EnterBookingStart(ModelView): string='Category', model_name='cashbook.category', depends=['bookingtype'], states={ - 'readonly': Bool(Eval('bookingtype')) == False, + 'readonly': ~Bool(Eval('bookingtype')), 'required': Eval('bookingtype', '').in_(['in', 'out']), 'invisible': ~Eval('bookingtype', '').in_(['in', 'out']), }, @@ -90,7 +90,8 @@ class EnterBookingStart(ModelView): if self.bookingtype: if self.category: - if self.bookingtype not in types.get(self.category.cattype, ''): + if self.bookingtype not in types.get( + self.category.cattype, ''): self.category = None @fields.depends('cashbook', '_parent_cashbook.owner') From 9ee924f0d8694bcfe3b8dc56f6ea6cfb84f08333 Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Wed, 29 Nov 2023 15:19:38 +0100 Subject: [PATCH 14/62] formatting, indexes optimized --- book.py | 15 ++++---------- category.py | 3 ++- configuration.py | 45 +++++++++++++++-------------------------- const.py | 8 ++++++++ currency.py | 3 ++- line.py | 51 ++++++++++++++++++++++++----------------------- mixin.py | 15 ++++++-------- model.py | 4 +++- reconciliation.py | 25 +++++++++++++---------- types.py | 10 +++++----- wizard_booking.py | 5 +++-- 11 files changed, 90 insertions(+), 94 deletions(-) create mode 100644 const.py diff --git a/book.py b/book.py index a4fd5a7..872f54a 100644 --- a/book.py +++ b/book.py @@ -74,8 +74,7 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): states={ 'readonly': Or( STATES['readonly'], - Len(Eval('lines')) > 0, - ), + Len(Eval('lines')) > 0), }, depends=DEPENDS+['lines']) feature = fields.Function(fields.Char( string='Feature', readonly=True, @@ -124,8 +123,7 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): states={ 'readonly': Or( STATES2['readonly'], - Len(Eval('lines')) > 0, - ), + Len(Eval('lines')) > 0), 'invisible': STATES2['invisible'], 'required': ~STATES2['invisible'], }, depends=DEPENDS2+['lines']) @@ -165,8 +163,7 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): states={ 'readonly': Or( STATES2['readonly'], - Len(Eval('lines', [])) > 0, - ), + Len(Eval('lines', [])) > 0), }, depends=DEPENDS2+['lines']) currency_digits = fields.Function(fields.Integer( string='Currency Digits', @@ -202,9 +199,6 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): Index( t, (t.btype, Index.Equality())), - Index( - t, - (t.parent, Index.Equality())), Index( t, (t.company, Index.Equality())), @@ -396,8 +390,7 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): query = tab_line.select( tab_line.cashbook, where=Operator( - getattr(tab_line, name), clause[2]), - ) + getattr(tab_line, name), clause[2])) return [('id', 'in', query)] @classmethod diff --git a/category.py b/category.py index 888697a..a10b3d1 100644 --- a/category.py +++ b/category.py @@ -11,6 +11,7 @@ from trytond.exceptions import UserError from trytond.i18n import gettext from sql.operators import Equal from .model import order_name_hierarchical +from .const import DEF_NONE sel_categorytype = [ @@ -70,7 +71,7 @@ class Category(tree(separator='/'), ModelSQL, ModelView): t, (t.name, Equal), (t.cattype, Equal), - where=(t.parent == None)), + where=(t.parent == DEF_NONE)), 'cashbook.msg_category_name_unique'), ]) diff --git a/configuration.py b/configuration.py index 2da84ee..2f2f5db 100644 --- a/configuration.py +++ b/configuration.py @@ -17,7 +17,8 @@ field_done = fields.Boolean( help='Show cashbook lines in Done-state.') field_catnamelong = fields.Boolean( string='Category: Show long name', - help='Shows the long name of the category in the Category field of a cash book line.') + help='Shows the long name of the category in the Category ' + + 'field of a cash book line.') class Configuration(ModelSingleton, ModelSQL, ModelView, UserMultiValueMixin): @@ -29,60 +30,47 @@ class Configuration(ModelSingleton, ModelSQL, ModelView, UserMultiValueMixin): domain=[ If(Eval('date_to') & Eval('date_from'), ('date_from', '<=', Eval('date_to')), - ()), - ])) + ())])) date_to = fields.MultiValue(fields.Date( string='End Date', depends=['date_from'], domain=[ If(Eval('date_to') & Eval('date_from'), ('date_from', '<=', Eval('date_to')), - ()), - ])) + ())])) checked = fields.MultiValue(field_checked) done = fields.MultiValue(field_done) catnamelong = fields.MultiValue(field_catnamelong) defbook = fields.MultiValue(fields.Many2One( string='Default Cashbook', - help='The default cashbook is selected when you open the booking wizard.', + help='The default cashbook is selected when you open ' + + 'the booking wizard.', model_name='cashbook.book', ondelete='SET NULL', - domain=[ - ('btype', '!=', None), ('state', '=', 'open'), - ])) + domain=[('btype', '!=', None), ('state', '=', 'open')])) book1 = fields.MultiValue(fields.Many2One( string='Cashbook 1', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', - domain=[ - ('btype', '!=', None), ('state', '=', 'open'), - ])) + domain=[('btype', '!=', None), ('state', '=', 'open')])) book2 = fields.MultiValue(fields.Many2One( string='Cashbook 2', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', - domain=[ - ('btype', '!=', None), ('state', '=', 'open'), - ])) + domain=[('btype', '!=', None), ('state', '=', 'open')])) book3 = fields.MultiValue(fields.Many2One( string='Cashbook 3', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', - domain=[ - ('btype', '!=', None), ('state', '=', 'open'), - ])) + domain=[('btype', '!=', None), ('state', '=', 'open')])) book4 = fields.MultiValue(fields.Many2One( string='Cashbook 4', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', - domain=[ - ('btype', '!=', None), ('state', '=', 'open'), - ])) + domain=[('btype', '!=', None), ('state', '=', 'open')])) book5 = fields.MultiValue(fields.Many2One( string='Cashbook 5', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', - domain=[ - ('btype', '!=', None), ('state', '=', 'open'), - ])) + domain=[('btype', '!=', None), ('state', '=', 'open')])) @classmethod def multivalue_model(cls, field): @@ -121,21 +109,20 @@ class UserConfiguration(ModelSQL, UserValueMixin): domain=[ If(Eval('date_to') & Eval('date_from'), ('date_from', '<=', Eval('date_to')), - ()), - ]) + ())]) date_to = fields.Date( string='End Date', depends=['date_from'], domain=[ If(Eval('date_to') & Eval('date_from'), ('date_from', '<=', Eval('date_to')), - ()), - ]) + ())]) checked = field_checked done = field_done catnamelong = field_catnamelong defbook = fields.Many2One( string='Default Cashbook', - help='The default cashbook is selected when you open the booking wizard.', + help='The default cashbook is selected when you open ' + + 'the booking wizard.', model_name='cashbook.book', ondelete='SET NULL', domain=[ ('btype', '!=', None), diff --git a/const.py b/const.py new file mode 100644 index 0000000..6eaa075 --- /dev/null +++ b/const.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# This file is part of the cashbook-module from m-ds.de for Tryton. +# The COPYRIGHT file at the top level of this repository contains the +# full copyright notices and license terms. + + +DEF_NONE = None + diff --git a/currency.py b/currency.py index 9d406c6..817812f 100644 --- a/currency.py +++ b/currency.py @@ -42,7 +42,8 @@ class CurrencyRate(metaclass=PoolMeta): MemCache = Pool().get('cashbook.memcache') for record in records: - MemCache.record_update(CACHEKEY_CURRENCY % record.currency.id, None) + MemCache.record_update( + CACHEKEY_CURRENCY % record.currency.id, None) super(CurrencyRate, cls).delete(records) # end diff --git a/line.py b/line.py index 41c6c9a..45dae05 100644 --- a/line.py +++ b/line.py @@ -16,6 +16,7 @@ from sql.functions import DatePart from sql.conditionals import Case from .book import sel_state_book from .mixin import SecondCurrencyMixin, MemCacheIndexMx +from .const import DEF_NONE sel_payee = [ @@ -48,7 +49,9 @@ STATES = { DEPENDS = ['state', 'state_cashbook'] -class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): +class Line( + SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, + ModelView): 'Cashbook Line' __name__ = 'cashbook.line' @@ -75,8 +78,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): states={ 'readonly': Or( STATES['readonly'], - Bool(Eval('bookingtype')) == False, - ), + ~Bool(Eval('bookingtype'))), 'required': Eval('bookingtype', '').in_(['in', 'out']), 'invisible': ~Eval('bookingtype', '').in_(['in', 'out']), }, depends=DEPENDS+['bookingtype'], @@ -161,7 +163,8 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): splitlines = fields.One2Many( string='Split booking lines', model_name='cashbook.split', - help='Rows with different categories form the total sum of the booking', + help='Rows with different categories form the total ' + + 'sum of the booking', states={ 'invisible': ~Eval('bookingtype' '').in_(['spin', 'spout']), 'readonly': Or( @@ -225,9 +228,6 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): t = cls.__table__() cls._sql_indexes.update({ - Index( - t, - (t.cashbook, Index.Equality())), Index( t, (t.date, Index.Range(order='ASC'))), @@ -308,7 +308,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): ).select( tab_line.id, where=tab_line.bookingtype.in_(['mvin', 'mvout']) & - (tab_line.amount_2nd_currency == None) & + (tab_line.amount_2nd_currency == DEF_NONE) & (tab_book.currency != tab_book2.currency) ) lines = Line2.search([('id', 'in', query)]) @@ -344,7 +344,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): for line in lines: if line.reference: if Transaction().context.get( - 'line.allow.wfedit', False) == False: + 'line.allow.wfedit', False) is False: raise UserError(gettext( 'cashbook.msg_line_denywf_by_reference', recname=line.reference.rec_name, @@ -508,19 +508,20 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): """ credit = self.credit if self.credit is not None else Decimal('0.0') debit = self.debit if self.debit is not None else Decimal('0.0') - return '%(date)s|%(type)s|%(amount)s %(symbol)s|%(desc)s [%(category)s]' % { - 'date': Report.format_date(self.date), - 'desc': (self.description or '-')[:40], - 'amount': Report.format_number( - credit - debit, None, - digits=getattr(self.currency, 'digits', 2)), - 'symbol': getattr(self.currency, 'symbol', '-'), - 'category': self.category_view - if self.bookingtype in ['in', 'out'] - else getattr(self.booktransf, 'rec_name', '-'), - 'type': gettext( - 'cashbook.msg_line_bookingtype_%s' % - self.bookingtype)} + return '|'.join([ + Report.format_date(self.date), + gettext('cashbook.msg_line_bookingtype_%s' % self.bookingtype), + '%(amount)s %(symbol)s' % { + 'amount': Report.format_number( + credit - debit, None, + digits=getattr(self.currency, 'digits', 2)), + 'symbol': getattr(self.currency, 'symbol', '-')}, + '%(desc)s [%(category)s]' % { + 'desc': (self.description or '-')[:40], + 'category': self.category_view + if self.bookingtype in ['in', 'out'] + else getattr(self.booktransf, 'rec_name', '-')}, + ]) @staticmethod def order_state(tables): @@ -535,8 +536,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): (tab_line.state == 'edit', 1), (tab_line.state.in_(['check', 'recon', 'done']), 0), else_=2), - where=tab_line.id == table.id - ) + where=tab_line.id == table.id) return [query] @staticmethod @@ -626,7 +626,8 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): if self.bookingtype: if self.category: - if self.bookingtype not in types.get(self.category.cattype, ''): + if self.bookingtype not in types.get( + self.category.cattype, ''): self.category = None if self.bookingtype.startswith('sp'): # split booking diff --git a/mixin.py b/mixin.py index 5b4f054..363bed5 100644 --- a/mixin.py +++ b/mixin.py @@ -31,20 +31,19 @@ class SecondCurrencyMixin: states={ 'readonly': Or( STATES['readonly'], - ~Bool(Eval('currency2nd')) - ), + ~Bool(Eval('currency2nd'))), 'required': Bool(Eval('currency2nd')), 'invisible': ~Bool(Eval('currency2nd')), }, depends=DEPENDS+['currency2nd_digits', 'currency2nd']) rate_2nd_currency = fields.Function(fields.Numeric( string='Rate', - help='Exchange rate between the currencies of the participating cashbooks.', + help='Exchange rate between the currencies of the ' + + 'participating cashbooks.', digits=(rate_decimal * 2, rate_decimal), states={ 'readonly': Or( STATES['readonly'], - ~Bool(Eval('currency2nd')) - ), + ~Bool(Eval('currency2nd'))), 'required': Bool(Eval('currency2nd')), 'invisible': ~Bool(Eval('currency2nd')), }, depends=DEPENDS+['currency2nd_digits', 'currency2nd']), @@ -124,15 +123,13 @@ class SecondCurrencyMixin: self.amount_2nd_currency = Currency.compute( self.currency, self.amount, - self.booktransf.currency - ) + self.booktransf.currency) if self.amount != Decimal('0.0'): self.rate_2nd_currency = \ self.amount_2nd_currency / self.amount else: self.amount_2nd_currency = self.booktransf.currency.round( - self.amount * self.rate_2nd_currency - ) + self.amount * self.rate_2nd_currency) @classmethod def set_rate_2nd_currency(cls, lines, name, value): diff --git a/model.py b/model.py index 0d5598c..e7b4ebc 100644 --- a/model.py +++ b/model.py @@ -15,6 +15,8 @@ from sql import With from sql.functions import Function from sql.conditionals import Coalesce import copy +from .const import DEF_NONE + if config.get('cashbook', 'memcache', default='yes').lower() \ in ['yes', '1', 'true']: @@ -269,7 +271,7 @@ def order_name_hierarchical(model_name, tables): lines = With('id', 'name', 'name_path', recursive=True) lines.query = tab_mod.select( tab_mod.id, tab_mod.name, Array(tab_mod.name), - where=tab_mod.parent == None, + where=tab_mod.parent == DEF_NONE, ) lines.query |= tab_mod2.join( lines, diff --git a/reconciliation.py b/reconciliation.py index e27e0c9..d0d5196 100644 --- a/reconciliation.py +++ b/reconciliation.py @@ -204,7 +204,8 @@ class Reconciliation(Workflow, ModelSQL, ModelView): # unlink lines from reconciliation if len(reconciliation.lines) > 0: - values['lines'] = [('remove', [x.id for x in reconciliation.lines])] + values['lines'] = [ + ('remove', [x.id for x in reconciliation.lines])] return values @classmethod @@ -339,20 +340,24 @@ class Reconciliation(Workflow, ModelSQL, ModelView): def get_rec_name(self, name): """ short + name """ - return '%(from)s - %(to)s | %(start_amount)s %(symbol)s - %(end_amount)s %(symbol)s [%(num)s]' % { - 'from': Report.format_date(self.date_from, None) + return ' '.join([ + Report.format_date(self.date_from, None) if self.date_from is not None else '-', - 'to': Report.format_date(self.date_to, None) - if self.date_to is not None else '-', - 'start_amount': Report.format_number( + '-', + Report.format_date(self.date_to, None) + if self.date_to is not None else '-', + '|', + Report.format_number( self.start_amount or 0.0, None, digits=getattr(self.currency, 'digits', 2)), - 'end_amount': Report.format_number( + getattr(self.currency, 'symbol', '-'), + '-', + Report.format_number( self.end_amount or 0.0, None, digits=getattr(self.currency, 'digits', 2)), - 'symbol': getattr(self.currency, 'symbol', '-'), - 'num': len(self.lines), - } + getattr(self.currency, 'symbol', '-'), + '[%(num)s]' % {'num': len(self.lines)}, + ]) @classmethod def default_date_from(cls): diff --git a/types.py b/types.py index 42bb54d..11bcaf5 100644 --- a/types.py +++ b/types.py @@ -28,7 +28,9 @@ class Type(ModelSQL, ModelView): cls._order.insert(0, ('name', 'ASC')) t = cls.__table__() cls._sql_constraints.extend([ - ('code_uniq', Unique(t, t.short), 'cashbook.msg_type_short_unique'), + ('code_uniq', + Unique(t, t.short), + 'cashbook.msg_type_short_unique'), ]) cls._sql_indexes.update({ Index( @@ -53,8 +55,7 @@ class Type(ModelSQL, ModelView): """ return '%(short)s - %(name)s' % { 'short': self.short or '-', - 'name': self.name or '-', - } + 'name': self.name or '-'} @classmethod def search_rec_name(cls, name, clause): @@ -63,8 +64,7 @@ class Type(ModelSQL, ModelView): return [ 'OR', ('name',) + tuple(clause[1:]), - ('short',) + tuple(clause[1:]), - ] + ('short',) + tuple(clause[1:])] @staticmethod def default_company(): diff --git a/wizard_booking.py b/wizard_booking.py index 429deae..9530a35 100644 --- a/wizard_booking.py +++ b/wizard_booking.py @@ -50,7 +50,7 @@ class EnterBookingStart(ModelView): string='Category', model_name='cashbook.category', depends=['bookingtype'], states={ - 'readonly': Bool(Eval('bookingtype')) == False, + 'readonly': ~Bool(Eval('bookingtype')), 'required': Eval('bookingtype', '').in_(['in', 'out']), 'invisible': ~Eval('bookingtype', '').in_(['in', 'out']), }, @@ -90,7 +90,8 @@ class EnterBookingStart(ModelView): if self.bookingtype: if self.category: - if self.bookingtype not in types.get(self.category.cattype, ''): + if self.bookingtype not in types.get( + self.category.cattype, ''): self.category = None @fields.depends('cashbook', '_parent_cashbook.owner') From fbdc68c64256d4d185669c964863a73ad7621881 Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Thu, 30 Nov 2023 13:14:54 +0100 Subject: [PATCH 15/62] ir.rule: Eval('user').get('groups') --> Eval('groups') --- book.xml | 4 ++-- line.xml | 4 ++-- reconciliation.xml | 4 ++-- splitline.xml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/book.xml b/book.xml index 9b113ee..4520409 100644 --- a/book.xml +++ b/book.xml @@ -143,8 +143,8 @@ full copyright notices and license terms. --> diff --git a/line.xml b/line.xml index b26fb1a..e618696 100644 --- a/line.xml +++ b/line.xml @@ -146,7 +146,7 @@ full copyright notices and license terms. --> @@ -168,7 +168,7 @@ full copyright notices and license terms. --> diff --git a/reconciliation.xml b/reconciliation.xml index 6e6576d..ca2f603 100644 --- a/reconciliation.xml +++ b/reconciliation.xml @@ -97,7 +97,7 @@ full copyright notices and license terms. --> @@ -119,7 +119,7 @@ full copyright notices and license terms. --> diff --git a/splitline.xml b/splitline.xml index d2d3f87..4ab74c0 100644 --- a/splitline.xml +++ b/splitline.xml @@ -81,7 +81,7 @@ full copyright notices and license terms. --> @@ -103,7 +103,7 @@ full copyright notices and license terms. --> From 018e265cfff6c0db23f4868e13c274cce3e3f724 Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Thu, 30 Nov 2023 13:33:46 +0100 Subject: [PATCH 16/62] merge... --- setup.py | 67 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/setup.py b/setup.py index 0552dca..d7a3bc9 100644 --- a/setup.py +++ b/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,7 +36,7 @@ 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 @@ -51,19 +51,21 @@ 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 a cashbook.', long_description=long_description, @@ -74,22 +76,21 @@ setup(name='%s_%s' % (PREFIX, MODULE), 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', - 'Programming Language :: Python :: 3.9', + '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', ], keywords='tryton cashbook', @@ -98,10 +99,10 @@ setup(name='%s_%s' % (PREFIX, MODULE), 'trytond.modules.%s' % MODULE, ], package_data={ - 'trytond.modules.%s' % MODULE: (info.get('xml', []) - + ['tryton.cfg', 'locale/*.po', 'tests/*.py', - 'view/*.xml', 'icon/*.svg', 'docs/*.txt', - 'report/*.fods', 'versiondep.txt', 'README.rst']), + 'trytond.modules.%s' % MODULE: (info.get('xml', []) + [ + 'tryton.cfg', 'locale/*.po', 'tests/*.py', + 'view/*.xml', 'icon/*.svg', 'docs/*.txt', + 'report/*.fods', 'versiondep.txt', 'README.rst']), }, install_requires=requires, From aa7af9844bbb4161e9a9e9de8ab4d583bde6d852 Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Thu, 30 Nov 2023 13:14:54 +0100 Subject: [PATCH 17/62] ir.rule: Eval('user').get('groups') --> Eval('groups') --- book.xml | 4 ++-- line.xml | 4 ++-- reconciliation.xml | 4 ++-- splitline.xml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/book.xml b/book.xml index 9b113ee..4520409 100644 --- a/book.xml +++ b/book.xml @@ -143,8 +143,8 @@ full copyright notices and license terms. --> diff --git a/line.xml b/line.xml index b26fb1a..e618696 100644 --- a/line.xml +++ b/line.xml @@ -146,7 +146,7 @@ full copyright notices and license terms. --> @@ -168,7 +168,7 @@ full copyright notices and license terms. --> diff --git a/reconciliation.xml b/reconciliation.xml index 6e6576d..ca2f603 100644 --- a/reconciliation.xml +++ b/reconciliation.xml @@ -97,7 +97,7 @@ full copyright notices and license terms. --> @@ -119,7 +119,7 @@ full copyright notices and license terms. --> diff --git a/splitline.xml b/splitline.xml index d2d3f87..4ab74c0 100644 --- a/splitline.xml +++ b/splitline.xml @@ -81,7 +81,7 @@ full copyright notices and license terms. --> @@ -103,7 +103,7 @@ full copyright notices and license terms. --> From 70623993190c4971e953ff7d83171fcd2cb89e18 Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Thu, 30 Nov 2023 13:18:14 +0100 Subject: [PATCH 18/62] Tryton 7.0: ir.rule: Eval('user', ...) --> Eval('user_id', -1) --- __init__.py | 2 ++ book.xml | 2 +- ir.py | 27 +++++++++++++++++++++++++++ line.xml | 2 +- reconciliation.xml | 2 +- splitline.xml | 2 +- 6 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 ir.py diff --git a/__init__.py b/__init__.py index 5439e0e..80f7161 100644 --- a/__init__.py +++ b/__init__.py @@ -17,6 +17,7 @@ from .reconciliation import Reconciliation from .cbreport import ReconciliationReport from .currency import CurrencyRate from .model import MemCache +from .ir import Rule def register(): @@ -35,6 +36,7 @@ def register(): OpenCashBookStart, RunCbReportStart, EnterBookingStart, + Rule, module='cashbook', type_='model') Pool.register( ReconciliationReport, diff --git a/book.xml b/book.xml index 4520409..b455f14 100644 --- a/book.xml +++ b/book.xml @@ -121,7 +121,7 @@ full copyright notices and license terms. --> diff --git a/ir.py b/ir.py new file mode 100644 index 0000000..7aa9aca --- /dev/null +++ b/ir.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# This file is part of the cashbook-module from m-ds.de for Tryton. +# The COPYRIGHT file at the top level of this repository contains the +# full copyright notices and license terms. + +from trytond.transaction import Transaction +from trytond.pool import PoolMeta + + +class Rule(metaclass=PoolMeta): + __name__ = 'ir.rule' + + @classmethod + def _get_context(cls, model_name): + context = super()._get_context(model_name) + if model_name in {'cashbook.book', 'cashbook.line', 'cashbook.recon'}: + context['user_id'] = Transaction().user + return context + + @classmethod + def _get_cache_key(cls, model_name): + key = super()._get_cache_key(model_name) + if model_name in {'cashbook.book', 'cashbook.line', 'cashbook.recon'}: + key = (*key, Transaction().user) + return key + +# end Rule diff --git a/line.xml b/line.xml index e618696..624fbfd 100644 --- a/line.xml +++ b/line.xml @@ -145,7 +145,7 @@ full copyright notices and license terms. --> diff --git a/reconciliation.xml b/reconciliation.xml index ca2f603..530a1ca 100644 --- a/reconciliation.xml +++ b/reconciliation.xml @@ -96,7 +96,7 @@ full copyright notices and license terms. --> diff --git a/splitline.xml b/splitline.xml index 4ab74c0..fefec00 100644 --- a/splitline.xml +++ b/splitline.xml @@ -80,7 +80,7 @@ full copyright notices and license terms. --> From cf92b2d7b5f200404b63be98c51a71066f68b999 Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Thu, 30 Nov 2023 13:19:09 +0100 Subject: [PATCH 19/62] Tryton 7.0: list-views - sum="1" --- locale/de.po | 12 ------------ locale/en.po | 12 ------------ view/book_list.xml | 2 +- view/line_list.xml | 4 ++-- view/line_recon_list.xml | 4 ++-- view/split_list.xml | 2 +- 6 files changed, 6 insertions(+), 30 deletions(-) diff --git a/locale/de.po b/locale/de.po index 5bf26cc..5d951db 100644 --- a/locale/de.po +++ b/locale/de.po @@ -450,10 +450,6 @@ msgctxt "view:cashbook.book:" msgid "Amount and Numbering" msgstr "Betrag und Nummerierung" -msgctxt "view:cashbook.book:" -msgid "Balance" -msgstr "Saldo" - msgctxt "view:cashbook.book:" msgid "Reconciliations" msgstr "Abstimmungen" @@ -774,14 +770,6 @@ msgctxt "model:cashbook.line,name:" msgid "Cashbook Line" msgstr "Kassenbuchzeile" -msgctxt "view:cashbook.line:" -msgid "Credit" -msgstr "Einnahme" - -msgctxt "view:cashbook.line:" -msgid "Debit" -msgstr "Ausgabe" - msgctxt "view:cashbook.line:" msgid "Cashbook Line" msgstr "Kassenbuchzeile" diff --git a/locale/en.po b/locale/en.po index 8c5b79e..f3e6784 100644 --- a/locale/en.po +++ b/locale/en.po @@ -414,10 +414,6 @@ msgctxt "view:cashbook.book:" msgid "Amount and Numbering" msgstr "Amount and Numbering" -msgctxt "view:cashbook.book:" -msgid "Balance" -msgstr "Balance" - msgctxt "view:cashbook.book:" msgid "Reconciliations" msgstr "Reconciliations" @@ -730,14 +726,6 @@ msgctxt "model:cashbook.line,name:" msgid "Cashbook Line" msgstr "Cashbook Line" -msgctxt "view:cashbook.line:" -msgid "Credit" -msgstr "Credit" - -msgctxt "view:cashbook.line:" -msgid "Debit" -msgstr "Debit" - msgctxt "view:cashbook.line:" msgid "Cashbook Line" msgstr "Cashbook Line" diff --git a/view/book_list.xml b/view/book_list.xml index 3ac0a86..31479c1 100644 --- a/view/book_list.xml +++ b/view/book_list.xml @@ -4,6 +4,6 @@ The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. --> - + diff --git a/view/line_list.xml b/view/line_list.xml index fffc0ac..4264a57 100644 --- a/view/line_list.xml +++ b/view/line_list.xml @@ -9,8 +9,8 @@ full copyright notices and license terms. --> - - + +