diff --git a/README.rst b/README.rst index 83d5baa..668a099 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,22 @@ currency are converted into the display currency of the parent cash book. Changes ======= -*6.0.0 - 05.08.2022* +*6.8.32 - 06.12.2023* + +- columns optional + +*6.8.31 - 30.11.2023* + +- optimized ir.rule + +*6.8.30 - 25.07.2023* + +- updt: optimize code, add tests + +*6.8.29 - 24.07.2023* + +- fix: type of indexes + +*6.8.28 - 05.06.2023* - init diff --git a/book.py b/book.py index 3e3fa0f..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 @@ -574,7 +567,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/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/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 18cbb3e..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 = [ @@ -23,7 +24,7 @@ sel_payee = [ ('party.party', 'Party') ] -sel_linetype = [ +sel_linestate = [ ('edit', 'Edit'), ('check', 'Checked'), ('recon', 'Reconciled'), @@ -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( @@ -197,7 +200,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', @@ -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'))), @@ -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', @@ -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, @@ -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: @@ -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 @@ -751,7 +752,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 +762,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 +779,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/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/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 044f85c..d0d5196 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( @@ -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 @@ -224,7 +225,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 +316,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 @@ -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): @@ -405,7 +410,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 +462,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 +471,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/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/setup.py b/setup.py index ff59617..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,11 +36,11 @@ 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 -minor_version = 0 +minor_version = 8 requires = ['python-slugify'] for dep in info.get('depends', []): @@ -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/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/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. --> 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, diff --git a/tryton.cfg b/tryton.cfg index ea57ba7..f40298a 100644 --- a/tryton.cfg +++ b/tryton.cfg @@ -1,5 +1,5 @@ [tryton] -version=6.0.0 +version=6.8.32 depends: res currency diff --git a/types.py b/types.py index 1217adf..11bcaf5 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 @@ -28,8 +28,15 @@ 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( + t, + (t.feature, Index.Equality())), + }) @classmethod def default_feature(cls): @@ -48,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): @@ -58,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/view/book_list.xml b/view/book_list.xml index 3ac0a86..2f14a6e 100644 --- a/view/book_list.xml +++ b/view/book_list.xml @@ -5,5 +5,5 @@ full copyright notices and license terms. --> - + diff --git a/view/book_tree.xml b/view/book_tree.xml index f3cfcb1..1ba5c32 100644 --- a/view/book_tree.xml +++ b/view/book_tree.xml @@ -5,7 +5,7 @@ full copyright notices and license terms. --> - + diff --git a/view/line_list.xml b/view/line_list.xml index fffc0ac..4ffa594 100644 --- a/view/line_list.xml +++ b/view/line_list.xml @@ -4,14 +4,14 @@ The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. --> - + - - - - + + + +