diff --git a/__init__.py b/__init__.py index 20541f8..5439e0e 100644 --- a/__init__.py +++ b/__init__.py @@ -18,6 +18,7 @@ from .cbreport import ReconciliationReport from .currency import CurrencyRate from .model import MemCache + def register(): Pool.register( MemCache, diff --git a/book.py b/book.py index b0cb21f..1bfe5fd 100644 --- a/book.py +++ b/book.py @@ -20,16 +20,18 @@ from .model import order_name_hierarchical, sub_ids_hierarchical, \ # enable/disable caching of cachekey for 'currency.rate' -if config.get('cashbook', 'cache_currency', default='yes').lower() in ['yes', '1', 'true']: +if config.get( + 'cashbook', 'cache_currency', default='yes' + ).lower() in ['yes', '1', 'true']: ENA_CURRKEY = True -else : +else: ENA_CURRKEY = False STATES = { 'readonly': Eval('state', '') != 'open', } -DEPENDS=['state'] +DEPENDS = ['state'] # states in case of 'btype'!=None STATES2 = { @@ -55,14 +57,17 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): 'Cashbook' __name__ = 'cashbook.book' - company = fields.Many2One(string='Company', model_name='company.company', + company = fields.Many2One( + string='Company', model_name='company.company', required=True, select=True, ondelete="RESTRICT") - name = fields.Char(string='Name', required=True, - states=STATES, depends=DEPENDS) - description = fields.Text(string='Description', - states=STATES, depends=DEPENDS) - btype = fields.Many2One(string='Type', select=True, - help='A cash book with type can contain postings. Without type is a view.', + name = fields.Char( + string='Name', required=True, states=STATES, depends=DEPENDS) + description = fields.Text( + string='Description', states=STATES, depends=DEPENDS) + btype = fields.Many2One( + string='Type', select=True, + help='A cash book with type can contain postings. ' + + 'Without type is a view.', model_name='cashbook.type', ondelete='RESTRICT', states={ 'readonly': Or( @@ -70,40 +75,50 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): Len(Eval('lines')) > 0, ), }, depends=DEPENDS+['lines']) - feature = fields.Function(fields.Char(string='Feature', readonly=True, + feature = fields.Function(fields.Char( + string='Feature', readonly=True, states={'invisible': True}), 'on_change_with_feature') - owner = fields.Many2One(string='Owner', required=True, select=True, + owner = fields.Many2One( + string='Owner', required=True, select=True, model_name='res.user', ondelete='SET NULL', states=STATES, depends=DEPENDS) - reviewer = fields.Many2One(string='Reviewer', select=True, + reviewer = fields.Many2One( + string='Reviewer', select=True, help='Group of users who have write access to the cashbook.', model_name='res.group', ondelete='SET NULL', states=STATES, depends=DEPENDS) - observer = fields.Many2One(string='Observer', select=True, + observer = fields.Many2One( + string='Observer', select=True, help='Group of users who have read-only access to the cashbook.', model_name='res.group', ondelete='SET NULL', states=STATES, depends=DEPENDS) - lines = fields.One2Many(string='Lines', field='cashbook', + lines = fields.One2Many( + string='Lines', field='cashbook', model_name='cashbook.line', states=STATES, depends=DEPENDS) - reconciliations = fields.One2Many(string='Reconciliations', + reconciliations = fields.One2Many( + string='Reconciliations', field='cashbook', model_name='cashbook.recon', states=STATES2, depends=DEPENDS2) - number_sequ = fields.Many2One(string='Line numbering', + number_sequ = fields.Many2One( + string='Line numbering', help='Number sequence for numbering of the cash book lines.', model_name='ir.sequence', domain=[ - ('sequence_type', '=', Id('cashbook', 'sequence_type_cashbook_line')), + ('sequence_type', '=', + Id('cashbook', 'sequence_type_cashbook_line')), ['OR', ('company', '=', None), - ('company', '=', Eval('company', -1)), - ], + ('company', '=', Eval('company', -1))], ], states=STATES3, depends=DEPENDS2+['company']) - number_atcheck = fields.Boolean(string="number when 'Checking'", - help="The numbering of the lines is done in the step Check. If the check mark is inactive, this happens with Done.", + number_atcheck = fields.Boolean( + string="number when 'Checking'", + help="The numbering of the lines is done in the step Check. " + + "If the check mark is inactive, this happens with Done.", states=STATES2, depends=DEPENDS2) - start_date = fields.Date(string='Initial Date', + start_date = fields.Date( + string='Initial Date', states={ 'readonly': Or( STATES2['readonly'], @@ -112,25 +127,29 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): 'invisible': STATES2['invisible'], 'required': ~STATES2['invisible'], }, depends=DEPENDS2+['lines']) - balance = fields.Function(fields.Numeric(string='Balance', + balance = fields.Function(fields.Numeric( + string='Balance', readonly=True, depends=['currency_digits'], help='Balance of bookings to date', digits=(16, Eval('currency_digits', 2))), 'get_balance_cashbook', searcher='search_balance') - balance_all = fields.Function(fields.Numeric(string='Total balance', + balance_all = fields.Function(fields.Numeric( + string='Total balance', readonly=True, depends=['currency_digits'], help='Balance of all bookings', digits=(16, Eval('currency_digits', 2))), 'get_balance_cashbook', searcher='search_balance') - balance_ref = fields.Function(fields.Numeric(string='Balance (Ref.)', + balance_ref = fields.Function(fields.Numeric( + string='Balance (Ref.)', help='Balance in company currency', readonly=True, digits=(16, Eval('company_currency_digits', 2)), states={ 'invisible': ~Bool(Eval('company_currency')), }, depends=['company_currency_digits', 'company_currency']), 'get_balance_cashbook') - company_currency = fields.Function(fields.Many2One(readonly=True, + company_currency = fields.Function(fields.Many2One( + readonly=True, string='Company Currency', states={'invisible': True}, model_name='currency.currency'), 'on_change_with_company_currency') @@ -138,7 +157,8 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): string='Currency Digits (Ref.)', readonly=True), 'on_change_with_currency_digits') - currency = fields.Many2One(string='Currency', select=True, + currency = fields.Many2One( + string='Currency', select=True, model_name='currency.currency', states={ 'readonly': Or( @@ -146,15 +166,19 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): Len(Eval('lines', [])) > 0, ), }, depends=DEPENDS2+['lines']) - currency_digits = fields.Function(fields.Integer(string='Currency Digits', + currency_digits = fields.Function(fields.Integer( + string='Currency Digits', readonly=True), 'on_change_with_currency_digits') - state = fields.Selection(string='State', required=True, + state = fields.Selection( + string='State', required=True, readonly=True, selection=sel_state_book) state_string = state.translated('state') - parent = fields.Many2One(string="Parent", + parent = fields.Many2One( + string="Parent", model_name='cashbook.book', ondelete='RESTRICT') - childs = fields.One2Many(string='Children', field='parent', + childs = fields.One2Many( + string='Children', field='parent', model_name='cashbook.book') @classmethod @@ -245,9 +269,8 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): query = tab_book.select( Case( (tab_book.state == 'open', 0), - else_ = 1), - where=tab_book.id==table.id - ) + else_=1), + where=tab_book.id == table.id) return [query] @staticmethod @@ -286,19 +309,21 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): # deny invalid date in context if isinstance(query_date, str): - try : - dt1 = date.fromisoformat(query_date) - except : + try: + date.fromisoformat(query_date) + except Exception: query_date = IrDate.today() - query = tab_book.join(tab_line, - condition=tab_book.id==tab_line.cashbook, + query = tab_book.join( + tab_line, + condition=tab_book.id == tab_line.cashbook, ).select( tab_line.cashbook, tab_book.currency, Sum(Case( - (tab_line.date <= query_date, tab_line.credit - tab_line.debit), - else_ = Decimal('0.0'), + (tab_line.date <= query_date, + tab_line.credit - tab_line.debit), + else_=Decimal('0.0'), )).as_('balance'), Sum(tab_line.credit - tab_line.debit).as_('balance_all'), group_by=[tab_line.cashbook, tab_book.currency], @@ -313,9 +338,9 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): (tab_book, tab2) = Book2.get_balance_of_cashbook_sql() table, _ = tables[None] - query = tab_book.select(tab_book.balance, - where=tab_book.cashbook==table.id, - ) + query = tab_book.select( + tab_book.balance, + where=tab_book.cashbook == table.id) return [query] @staticmethod @@ -326,9 +351,9 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): (tab_book, tab2) = Book2.get_balance_of_cashbook_sql() table, _ = tables[None] - query = tab_book.select(tab_book.balance_all, - where=tab_book.cashbook==table.id, - ) + query = tab_book.select( + tab_book.balance_all, + where=tab_book.cashbook == table.id) return [query] @classmethod @@ -361,32 +386,32 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): context = Transaction().context result = { - x:{y.id: Decimal('0.0') for y in cashbooks} - for x in ['balance', 'balance_all', 'balance_ref']} + x: {y.id: Decimal('0.0') for y in cashbooks} + for x in ['balance', 'balance_all', 'balance_ref']} # deny invalid date in context query_date = context.get('date', IrDate.today()) if isinstance(query_date, str): - try : - dt1 = date.fromisoformat(query_date) - except : + try: + date.fromisoformat(query_date) + except Exception: query_date = IrDate.today() cache_keys = { - x.id: MemCache.get_key_by_record( - name = 'get_balance_cashbook', - record = x, - query = [{ - 'model': 'cashbook.line', - 'query': [('cashbook.parent', 'child_of', [x.id])], - }, { - 'model': 'currency.currency.rate', - 'query': [('currency.id', '=', x.currency.id)], - 'cachekey' if ENA_CURRKEY else 'disabled': CACHEKEY_CURRENCY % x.currency.id, - }, ], - addkeys = [query_date.isoformat()]) - for x in cashbooks - } + x.id: MemCache.get_key_by_record( + name='get_balance_cashbook', + record=x, + query=[{ + 'model': 'cashbook.line', + 'query': [('cashbook.parent', 'child_of', [x.id])], + }, { + 'model': 'currency.currency.rate', + 'query': [('currency.id', '=', x.currency.id)], + 'cachekey' if ENA_CURRKEY + else 'disabled': CACHEKEY_CURRENCY % x.currency.id, + }, ], + addkeys=[query_date.isoformat()]) + for x in cashbooks} # read from cache (todo_cashbook, result) = MemCache.read_from_cache( @@ -396,16 +421,19 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): # query balances of cashbooks and sub-cashbooks with Transaction().set_context({ - 'date': query_date, - }): + 'date': query_date}): (tab_line, tab2) = cls.get_balance_of_cashbook_sql() tab_subids = sub_ids_hierarchical('cashbook.book') - query = tab_book.join(tab_subids, - condition=tab_book.id==tab_subids.parent, - ).join(tab_comp, - condition=tab_book.company==tab_comp.id, - ).join(tab_line, - condition=tab_line.cashbook==AnyInArray(tab_subids.subids), + query = tab_book.join( + tab_subids, + condition=tab_book.id == tab_subids.parent, + ).join( + tab_comp, + condition=tab_book.company == tab_comp.id, + ).join( + tab_line, + condition=tab_line.cashbook == AnyInArray( + tab_subids.subids), ).select( tab_book.id, tab_book.currency.as_('to_currency'), @@ -413,7 +441,8 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): tab_comp.currency.as_('company_currency'), Sum(tab_line.balance).as_('balance'), Sum(tab_line.balance_all).as_('balance_all'), - group_by=[tab_book.id, tab_line.currency, tab_comp.currency], + group_by=[ + tab_book.id, tab_line.currency, tab_comp.currency], where=tab_book.id.in_([x.id for x in todo_cashbook]), ) cursor.execute(*query) @@ -496,30 +525,29 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): if (values['btype'] is None) and (len(book.lines) > 0): raise UserError(gettext( 'cashbook.msg_book_btype_with_lines', - cbname = book.rec_name, - numlines = len(book.lines), - )) + cbname=book.rec_name, + numlines=len(book.lines))) if book.state != 'open': # allow state-update, if its the only action - if not (('state' in values.keys()) and (len(values.keys()) == 1)): + if not (('state' in values.keys()) and + (len(values.keys()) == 1)): raise UserError(gettext( 'cashbook.msg_book_deny_write', - bookname = book.rec_name, - state_txt = book.state_string, - )) + bookname=book.rec_name, + state_txt=book.state_string)) # if owner changes, remove book from user-config if 'owner' in values.keys(): if book.owner.id != values['owner']: - for x in ['defbook', 'book1', 'book2', 'book3', - 'book4', 'book5']: + for x in [ + 'defbook', 'book1', 'book2', 'book3', + 'book4', 'book5']: cfg1 = ConfigUser.search([ ('iduser.id', '=', book.owner.id), - ('%s.id' % x, '=', book.id), - ]) + ('%s.id' % x, '=', book.id)]) if len(cfg1) > 0: - to_write_config.extend([ cfg1, {x: None} ]) + to_write_config.extend([cfg1, {x: None}]) super(Book, cls).write(*args) if len(to_write_config) > 0: @@ -533,9 +561,8 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView): if (len(book.lines) > 0) and (book.state != 'archive'): raise UserError(gettext( 'cashbook.msg_book_deny_delete', - bookname = book.rec_name, - booklines = len(book.lines), - )) + bookname=book.rec_name, + booklines=len(book.lines))) super(Book, cls).delete(books) # end Book diff --git a/category.py b/category.py index 95e9858..888697a 100644 --- a/category.py +++ b/category.py @@ -25,22 +25,27 @@ class Category(tree(separator='/'), ModelSQL, ModelView): name = fields.Char(string='Name', required=True, translate=True) description = fields.Char(string='Description', translate=True) - cattype = fields.Selection(string='Type', required=True, + cattype = fields.Selection( + string='Type', required=True, help='Type of Category', selection=sel_categorytype, states={'readonly': Bool(Eval('parent_cattype'))}, domain=[If(Bool(Eval('parent_cattype')), ('cattype', '=', Eval('parent_cattype', '')), ())], depends=['parent_cattype']) - parent_cattype = fields.Function(fields.Char(string='Parent Category Type', + parent_cattype = fields.Function(fields.Char( + string='Parent Category Type', readonly=True, states={'invisible': True}), 'on_change_with_parent_cattype') - company = fields.Many2One(string='Company', model_name='company.company', + company = fields.Many2One( + string='Company', model_name='company.company', required=True, ondelete="RESTRICT") - parent = fields.Many2One(string="Parent", + parent = fields.Many2One( + string="Parent", model_name='cashbook.category', ondelete='RESTRICT') - childs = fields.One2Many(string='Children', field='parent', + childs = fields.One2Many( + string='Children', field='parent', model_name='cashbook.category') @classmethod @@ -61,7 +66,8 @@ class Category(tree(separator='/'), ModelSQL, ModelView): Unique(t, t.name, t.company, t.parent), 'cashbook.msg_category_name_unique'), ('name2_uniq', - Exclude(t, + Exclude( + t, (t.name, Equal), (t.cattype, Equal), where=(t.parent == None)), @@ -106,9 +112,8 @@ class Category(tree(separator='/'), ModelSQL, ModelView): if category.parent.cattype != category.cattype: raise UserError(gettext( 'cashbook.msg_category_type_not_like_parent', - parentname = category.parent.rec_name, - catname = category.rec_name, - )) + parentname=category.parent.rec_name, + catname=category.rec_name,)) @classmethod def create(cls, vlist): diff --git a/cbreport.py b/cbreport.py index bde7523..fcf7975 100644 --- a/cbreport.py +++ b/cbreport.py @@ -20,7 +20,8 @@ class ReconciliationReport(Report): Company = Pool().get('company.company') context2 = Transaction().context - context = super(ReconciliationReport, cls).get_context(records, header, data) + context = super( + ReconciliationReport, cls).get_context(records, header, data) context['company'] = Company(context2['company']) return context @@ -41,14 +42,14 @@ class ReconciliationReport(Report): recon_obj = pool.get(data['model'])(data['id']) rep_name = gettext( 'cashbook.msg_rep_reconciliation_fname', - recname = recon_obj.cashbook.rec_name[:50], - date_from = recon_obj.date_from.isoformat(), - date_to = recon_obj.date_to.isoformat(), - ) - else : + recname=recon_obj.cashbook.rec_name[:50], + date_from=recon_obj.date_from.isoformat(), + date_to=recon_obj.date_to.isoformat()) + else: raise ValueError('invalid model') - (ext1, cont1, dirprint, title) = super(ReconciliationReport, cls).execute(ids, data) + (ext1, cont1, dirprint, title) = super( + ReconciliationReport, cls).execute(ids, data) return ( ext1, @@ -63,5 +64,3 @@ class ReconciliationReport(Report): ) # end ReconciliationReport - - diff --git a/configuration.py b/configuration.py index 0566a64..2da84ee 100644 --- a/configuration.py +++ b/configuration.py @@ -9,11 +9,14 @@ from trytond.pyson import Eval, If from trytond.pool import Pool -field_checked = fields.Boolean(string='Checked', +field_checked = fields.Boolean( + string='Checked', help='Show cashbook lines in Checked-state.') -field_done = fields.Boolean(string='Done', +field_done = fields.Boolean( + string='Done', help='Show cashbook lines in Done-state.') -field_catnamelong = fields.Boolean(string='Category: Show long name', +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.') @@ -21,13 +24,15 @@ class Configuration(ModelSingleton, ModelSQL, ModelView, UserMultiValueMixin): 'Configuration' __name__ = 'cashbook.configuration' - date_from = fields.MultiValue(fields.Date(string='Start Date', depends=['date_to'], + date_from = fields.MultiValue(fields.Date( + string='Start Date', depends=['date_to'], 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'], + 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')), @@ -36,37 +41,43 @@ class Configuration(ModelSingleton, ModelSQL, ModelView, UserMultiValueMixin): checked = fields.MultiValue(field_checked) done = fields.MultiValue(field_done) catnamelong = fields.MultiValue(field_catnamelong) - defbook = fields.MultiValue(fields.Many2One(string='Default Cashbook', + defbook = fields.MultiValue(fields.Many2One( + string='Default Cashbook', help='The default cashbook is selected when you open the booking wizard.', model_name='cashbook.book', ondelete='SET NULL', domain=[ ('btype', '!=', None), ('state', '=', 'open'), ])) - book1 = fields.MultiValue(fields.Many2One(string='Cashbook 1', + 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'), ])) - book2 = fields.MultiValue(fields.Many2One(string='Cashbook 2', + 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'), ])) - book3 = fields.MultiValue(fields.Many2One(string='Cashbook 3', + 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'), ])) - book4 = fields.MultiValue(fields.Many2One(string='Cashbook 4', + 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'), ])) - book5 = fields.MultiValue(fields.Many2One(string='Cashbook 5', + book5 = fields.MultiValue(fields.Many2One( + string='Cashbook 5', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', domain=[ @@ -79,9 +90,10 @@ class Configuration(ModelSingleton, ModelSQL, ModelView, UserMultiValueMixin): """ pool = Pool() - if field in ['date_from', 'date_to', 'checked', 'done', - 'catnamelong', 'defbook', 'book1', 'book2', - 'book3', 'book4', 'book5']: + if field in [ + 'date_from', 'date_to', 'checked', 'done', + 'catnamelong', 'defbook', 'book1', 'book2', + 'book3', 'book4', 'book5']: return pool.get('cashbook.configuration_user') return super(Configuration, cls).multivalue_model(field) @@ -104,13 +116,15 @@ class UserConfiguration(ModelSQL, UserValueMixin): 'User Configuration' __name__ = 'cashbook.configuration_user' - date_from = fields.Date(string='Start Date', depends=['date_to'], + date_from = fields.Date( + string='Start Date', depends=['date_to'], domain=[ If(Eval('date_to') & Eval('date_from'), ('date_from', '<=', Eval('date_to')), ()), ]) - date_to = fields.Date(string='End Date', depends=['date_from'], + date_to = fields.Date( + string='End Date', depends=['date_from'], domain=[ If(Eval('date_to') & Eval('date_from'), ('date_from', '<=', Eval('date_to')), @@ -119,7 +133,8 @@ class UserConfiguration(ModelSQL, UserValueMixin): checked = field_checked done = field_done catnamelong = field_catnamelong - defbook = fields.Many2One(string='Default Cashbook', + defbook = fields.Many2One( + string='Default Cashbook', help='The default cashbook is selected when you open the booking wizard.', model_name='cashbook.book', ondelete='SET NULL', domain=[ @@ -127,7 +142,8 @@ class UserConfiguration(ModelSQL, UserValueMixin): ('state', '=', 'open'), ('owner.id', '=', Eval('iduser', -1)) ], depends=['iduser']) - book1 = fields.Many2One(string='Cashbook 1', + book1 = fields.Many2One( + string='Cashbook 1', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', domain=[ @@ -135,7 +151,8 @@ class UserConfiguration(ModelSQL, UserValueMixin): ('state', '=', 'open'), ('owner.id', '=', Eval('iduser', -1)) ], depends=['iduser']) - book2 = fields.Many2One(string='Cashbook 2', + book2 = fields.Many2One( + string='Cashbook 2', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', domain=[ @@ -143,7 +160,8 @@ class UserConfiguration(ModelSQL, UserValueMixin): ('state', '=', 'open'), ('owner.id', '=', Eval('iduser', -1)) ], depends=['iduser']) - book3 = fields.Many2One(string='Cashbook 3', + book3 = fields.Many2One( + string='Cashbook 3', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', domain=[ @@ -151,7 +169,8 @@ class UserConfiguration(ModelSQL, UserValueMixin): ('state', '=', 'open'), ('owner.id', '=', Eval('iduser', -1)) ], depends=['iduser']) - book4 = fields.Many2One(string='Cashbook 4', + book4 = fields.Many2One( + string='Cashbook 4', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', domain=[ @@ -159,7 +178,8 @@ class UserConfiguration(ModelSQL, UserValueMixin): ('state', '=', 'open'), ('owner.id', '=', Eval('iduser', -1)) ], depends=['iduser']) - book5 = fields.Many2One(string='Cashbook 5', + book5 = fields.Many2One( + string='Cashbook 5', help='Cash book available in selection dialog.', model_name='cashbook.book', ondelete='SET NULL', domain=[ diff --git a/currency.py b/currency.py index 68b1636..9d406c6 100644 --- a/currency.py +++ b/currency.py @@ -32,7 +32,8 @@ class CurrencyRate(metaclass=PoolMeta): actions = iter(args) for rates, values in zip(actions, actions): for rate in rates: - MemCache.record_update(CACHEKEY_CURRENCY % rate.currency.id, rate) + MemCache.record_update( + CACHEKEY_CURRENCY % rate.currency.id, rate) @classmethod def delete(cls, records): diff --git a/line.py b/line.py index 9d2dddb..5ad13d4 100644 --- a/line.py +++ b/line.py @@ -45,26 +45,32 @@ STATES = { Eval('state_cashbook', '') != 'open', ), } -DEPENDS=['state', 'state_cashbook'] +DEPENDS = ['state', 'state_cashbook'] class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): 'Cashbook Line' __name__ = 'cashbook.line' - cashbook = fields.Many2One(string='Cashbook', required=True, select=True, + cashbook = fields.Many2One( + string='Cashbook', required=True, select=True, model_name='cashbook.book', ondelete='CASCADE', readonly=True, domain=[('btype', '!=', None)]) - date = fields.Date(string='Date', required=True, select=True, + date = fields.Date( + string='Date', required=True, select=True, states=STATES, depends=DEPENDS) - month = fields.Function(fields.Integer(string='Month', readonly=True), + month = fields.Function(fields.Integer( + string='Month', readonly=True), 'on_change_with_month', searcher='search_month') number = fields.Char(string='Number', readonly=True) - description = fields.Text(string='Description', select=True, + description = fields.Text( + string='Description', select=True, states=STATES, depends=DEPENDS) - descr_short = fields.Function(fields.Char(string='Description', readonly=True), + descr_short = fields.Function(fields.Char( + string='Description', readonly=True), 'on_change_with_descr_short', searcher='search_descr_short') - category = fields.Many2One(string='Category', select=True, + category = fields.Many2One( + string='Category', select=True, model_name='cashbook.category', ondelete='RESTRICT', states={ 'readonly': Or( @@ -80,18 +86,23 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): ('cattype', '=', 'in'), ('cattype', '=', 'out'), )]) - category_view = fields.Function(fields.Char(string='Category', readonly=True), + category_view = fields.Function(fields.Char( + string='Category', readonly=True), 'on_change_with_category_view', searcher='search_category_view') - feature = fields.Function(fields.Char(string='Feature', readonly=True, + feature = fields.Function(fields.Char( + string='Feature', readonly=True, states={'invisible': True}), 'on_change_with_feature') - booktransf_feature = fields.Function(fields.Char(string='Feature', readonly=True, + booktransf_feature = fields.Function(fields.Char( + string='Feature', readonly=True, states={'invisible': True}), 'on_change_with_booktransf_feature') - bookingtype = fields.Selection(string='Type', required=True, + bookingtype = fields.Selection( + string='Type', required=True, help='Type of Booking', selection=sel_bookingtype, select=True, states=STATES, depends=DEPENDS) bookingtype_string = bookingtype.translated('bookingtype') - amount = fields.Numeric(string='Amount', digits=(16, Eval('currency_digits', 2)), + amount = fields.Numeric( + string='Amount', digits=(16, Eval('currency_digits', 2)), required=True, states={ 'readonly': Or( @@ -99,13 +110,16 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): Eval('bookingtype', '').in_(['spin', 'spout']), ), }, depends=DEPENDS+['currency_digits', 'bookingtype']) - debit = fields.Numeric(string='Debit', digits=(16, Eval('currency_digits', 2)), + debit = fields.Numeric( + string='Debit', digits=(16, Eval('currency_digits', 2)), required=True, readonly=True, depends=['currency_digits']) - credit = fields.Numeric(string='Credit', digits=(16, Eval('currency_digits', 2)), + credit = fields.Numeric( + string='Credit', digits=(16, Eval('currency_digits', 2)), required=True, readonly=True, depends=['currency_digits']) # party or cashbook as counterpart - booktransf = fields.Many2One(string='Source/Dest', + booktransf = fields.Many2One( + string='Source/Dest', ondelete='RESTRICT', model_name='cashbook.book', domain=[ ('owner.id', '=', Eval('owner_cashbook', -1)), @@ -117,28 +131,35 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): 'invisible': ~Eval('bookingtype', '').in_(['mvin', 'mvout']), 'required': Eval('bookingtype', '').in_(['mvin', 'mvout']), }, depends=DEPENDS+['bookingtype', 'owner_cashbook', 'cashbook']) - party = fields.Many2One(string='Party', model_name='party.party', + party = fields.Many2One( + string='Party', model_name='party.party', ondelete='RESTRICT', states={ 'readonly': STATES['readonly'], - 'invisible': ~Eval('bookingtype', '').in_(['in', 'out', 'spin', 'spout']), + 'invisible': ~Eval('bookingtype', '').in_( + ['in', 'out', 'spin', 'spout']), }, depends=DEPENDS+['bookingtype']) - payee = fields.Function(fields.Reference(string='Payee', readonly=True, + payee = fields.Function(fields.Reference( + string='Payee', readonly=True, selection=sel_payee), 'on_change_with_payee', searcher='search_payee') # link to lines created by this record - reference = fields.Many2One(string='Reference', readonly=True, select=True, + reference = fields.Many2One( + string='Reference', readonly=True, select=True, states={ 'invisible': ~Bool(Eval('reference')), }, model_name='cashbook.line', ondelete='CASCADE', - help='The current row was created by and is controlled by the reference row.') - references = fields.One2Many(string='References', + help='The current row was created by and is controlled ' + + 'by the reference row.') + references = fields.One2Many( + string='References', model_name='cashbook.line', help='The rows are created and managed by the current record.', states={ 'invisible': ~Bool(Eval('references')), }, field='reference', readonly=True) - splitlines = fields.One2Many(string='Split booking lines', + splitlines = fields.One2Many( + string='Split booking lines', model_name='cashbook.split', help='Rows with different categories form the total sum of the booking', states={ @@ -150,7 +171,8 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): 'required': Eval('bookingtype' '').in_(['spin', 'spout']), }, field='line', depends=DEPENDS+['bookingtype']) - reconciliation = fields.Many2One(string='Reconciliation', readonly=True, + reconciliation = fields.Many2One( + string='Reconciliation', readonly=True, model_name='cashbook.recon', ondelete='SET NULL', domain=[('cashbook.id', '=', Eval('cashbook'))], depends=['cashbook'], @@ -158,24 +180,31 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): 'invisible': ~Bool(Eval('reconciliation')), }) - balance = fields.Function(fields.Numeric(string='Balance', + balance = fields.Function(fields.Numeric( + string='Balance', digits=(16, Eval('currency_digits', 2)), - help='Balance of the cash book up to the current line, if the default sorting applies.', + help='Balance of the cash book up to the current line, ' + + 'if the default sorting applies.', readonly=True, depends=['currency_digits']), 'on_change_with_balance') - currency = fields.Function(fields.Many2One(model_name='currency.currency', + currency = fields.Function(fields.Many2One( + model_name='currency.currency', string="Currency", readonly=True), 'on_change_with_currency') - currency_digits = fields.Function(fields.Integer(string='Currency Digits', + currency_digits = fields.Function(fields.Integer( + string='Currency Digits', readonly=True), 'on_change_with_currency_digits') - state = fields.Selection(string='State', required=True, readonly=True, + state = fields.Selection( + string='State', required=True, readonly=True, select=True, selection=sel_linetype) state_string = state.translated('state') - state_cashbook = fields.Function(fields.Selection(string='State of Cashbook', + state_cashbook = fields.Function(fields.Selection( + string='State of Cashbook', readonly=True, states={'invisible': True}, selection=sel_state_book), 'on_change_with_state_cashbook', searcher='search_state_cashbook') - owner_cashbook = fields.Function(fields.Many2One(string='Owner', readonly=True, + owner_cashbook = fields.Function(fields.Many2One( + string='Owner', readonly=True, states={'invisible': True}, model_name='res.user'), 'on_change_with_owner_cashbook') @@ -230,8 +259,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): return super().view_attributes() + [ ('/tree', 'visual', If(Eval('balance', 0) < 0, 'warning', - If(Eval('date', Date()) > Date(), 'muted', '') - )), + If(Eval('date', Date()) > Date(), 'muted', ''))), ] @classmethod @@ -247,13 +275,16 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): tab_book2 = Book2.__table__() # transfer-target cursor = Transaction().connection.cursor() - query = tab_line.join(tab_book, + query = tab_line.join( + tab_book, condition=tab_line.cashbook == tab_book.id, - ).join(tab_book2, - condition=tab_line.booktransf== tab_book2.id, - ).select(tab_line.id, - where=tab_line.bookingtype.in_(['mvin', 'mvout']) & \ - (tab_line.amount_2nd_currency == None) & \ + ).join( + tab_book2, + condition=tab_line.booktransf == tab_book2.id, + ).select( + tab_line.id, + where=tab_line.bookingtype.in_(['mvin', 'mvout']) & + (tab_line.amount_2nd_currency == None) & (tab_book.currency != tab_book2.currency) ) lines = Line2.search([('id', 'in', query)]) @@ -270,9 +301,9 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): for line in to_write: qu1 = tab_line.update( - columns = [tab_line.amount_2nd_currency], - values = [line['amount_2nd_currency']], - where = tab_line.id == line['id'], + columns=[tab_line.amount_2nd_currency], + values=[line['amount_2nd_currency']], + where=tab_line.id == line['id'], ) cursor.execute(*qu1) @@ -288,19 +319,18 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): to_delete_line = [] for line in lines: if line.reference: - if Transaction().context.get('line.allow.wfedit', False) == False: + if Transaction().context.get( + 'line.allow.wfedit', False) == False: raise UserError(gettext( 'cashbook.msg_line_denywf_by_reference', - recname = line.reference.rec_name, - cbook = line.reference.cashbook.rec_name, - )) + recname=line.reference.rec_name, + cbook=line.reference.cashbook.rec_name)) # delete references to_delete_line.extend(list(line.references)) if len(to_delete_line) > 0: with Transaction().set_context({ - 'line.allow.wfedit': True, - }): + 'line.allow.wfedit': True}): Line2.wfedit(to_delete_line) Line2.delete(to_delete_line) @@ -323,11 +353,10 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): ('state', 'in', ['check', 'done']), ('cashbook.id', '=', line.cashbook.id), ('date_from', '<', line.date), - ('date_to', '>', line.date), - ]) > 0: + ('date_to', '>', line.date)]) > 0: raise UserError(gettext( 'cashbook.msg_line_err_write_to_reconciled', - datetxt = Report.format_date(line.date), + datetxt=Report.format_date(line.date), )) # deny if date is at reconciliation limits and two # reconciliations exist @@ -336,12 +365,10 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): ('cashbook.id', '=', line.cashbook.id), ['OR', ('date_from', '=', line.date), - ('date_to', '=', line.date), - ] - ]) > 1: + ('date_to', '=', line.date)]]) > 1: raise UserError(gettext( 'cashbook.msg_line_err_write_to_reconciled', - datetxt = Report.format_date(line.date), + datetxt=Report.format_date(line.date), )) if line.reference is None: @@ -356,25 +383,28 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): if sp_line.splittype != 'tr': continue - values = cls.get_counterpart_values(line, - splitline = sp_line, - values = { - 'cashbook': sp_line.booktransf.id, - 'description': sp_line.description, - 'amount': sp_line.amount \ - if sp_line.currency.id == sp_line.booktransf.currency.id \ + values = cls.get_counterpart_values( + line, splitline=sp_line, + values={ + 'cashbook': sp_line.booktransf.id, + 'description': sp_line.description, + 'amount': sp_line.amount + if sp_line.currency.id == sp_line. + booktransf.currency.id else sp_line.amount_2nd_currency, - 'amount_2nd_currency': sp_line.amount \ - if sp_line.currency.id != sp_line.booktransf.currency.id \ + 'amount_2nd_currency': sp_line.amount + if sp_line.currency.id != sp_line. + booktransf.currency.id else None, - 'bookingtype': 'mvin' \ - if line.bookingtype.endswith('out') else 'mvout', + 'bookingtype': 'mvin' + if line.bookingtype.endswith('out') + else 'mvout', }) values.update(cls.get_debit_credit(values)) to_create_line.append(values) # add number to line - if line.cashbook.number_atcheck == True: + if line.cashbook.number_atcheck is True: if len(line.number or '') == 0: to_write_line.extend([ [line], @@ -459,11 +489,12 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): 'desc': (self.description or '-')[:40], 'amount': Report.format_number(credit - debit, None), '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), - } + '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)} @staticmethod def order_state(tables): @@ -477,8 +508,8 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): Case( (tab_line.state == 'edit', 1), (tab_line.state.in_(['check', 'recon', 'done']), 0), - else_ = 2), - where=tab_line.id==table.id + else_=2), + where=tab_line.id == table.id ) return [query] @@ -490,10 +521,9 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): Category = Pool().get('cashbook.category') tab_cat = Category.__table__() - tab2 = tab_cat.select(tab_cat.name, - where=tab_cat.id==table.category - ) - + tab2 = tab_cat.select( + tab_cat.name, + where=tab_cat.id == table.category) return [tab2] @staticmethod @@ -509,8 +539,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): """ return ['OR', ('party.rec_name',) + tuple(clause[1:]), - ('booktransf.rec_name',) + tuple(clause[1:]), - ] + ('booktransf.rec_name',) + tuple(clause[1:])] @classmethod def search_category_view(cls, name, clause): @@ -529,10 +558,12 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): Operator = fields.SQL_OPERATORS[clause[1]] dt1 = IrDate.today() - query = tab_line.select(tab_line.id, + query = tab_line.select( + tab_line.id, where=Operator( - Literal(12 * dt1.year + dt1.month) - \ - (Literal(12) * DatePart('year', tab_line.date) + DatePart('month', tab_line.date)), + Literal(12 * dt1.year + dt1.month) - + (Literal(12) * DatePart('year', tab_line.date) + + DatePart('month', tab_line.date)), clause[2]), ) return [('id', 'in', query)] @@ -553,9 +584,11 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): def on_change_splitlines(self): """ update amount if splitlines change """ - self.amount = sum([x.amount for x in self.splitlines if x.amount is not None]) + self.amount = sum([ + x.amount for x in self.splitlines if x.amount is not None]) - @fields.depends('bookingtype', 'category', 'splitlines', 'booktransf',\ + @fields.depends( + 'bookingtype', 'category', 'splitlines', 'booktransf', 'currency2nd') def on_change_bookingtype(self): """ clear category if not valid type @@ -567,19 +600,20 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): if self.bookingtype: if self.category: - if not self.bookingtype 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 self.category = None self.booktransf = None for spline in self.splitlines: - if not self.bookingtype in types.get(getattr(spline.category, 'cattype', '-'), ''): + if self.bookingtype not in types.get( + getattr(spline.category, 'cattype', '-'), ''): spline.category = None - elif self.bookingtype.startswith('mv'): # transfer + elif self.bookingtype.startswith('mv'): # transfer self.splitlines = [] self.category = None - else : # category + else: # category self.splitlines = [] self.booktransf = None self.currency2nd = self.on_change_with_currency2nd() @@ -627,9 +661,9 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): if self.category: cfg1 = Configuration.get_singleton() - if getattr(cfg1, 'catnamelong', True) == True: + if getattr(cfg1, 'catnamelong', True) is True: return self.category.rec_name - else : + else: return self.category.name @fields.depends('date') @@ -673,7 +707,9 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): return 2 @classmethod - def get_balance_of_line(cls, line, field_name='amount', credit_name='credit', debit_name='debit'): + def get_balance_of_line( + cls, line, field_name='amount', credit_name='credit', + debit_name='debit'): """ get balance of current line, try to speed up by usage of last reconcilitaion """ @@ -699,8 +735,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): ('date', '<=', line2.date), ['OR', ('reconciliation', '=', None), - ('reconciliation.id', '!=', recons[0]), - ], + ('reconciliation.id', '!=', recons[0])], ]) end_value = getattr(recons[0], 'end_%s' % field_name) return (query2, end_value) @@ -719,13 +754,14 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): query.append( ('reconciliation.id', '=', line.reconciliation.id), ) - balance = getattr(line.reconciliation, 'start_%s' % field_name) - else : + balance = getattr( + line.reconciliation, 'start_%s' % field_name) + else: (query2, balance2) = get_from_last_recon(line) query.extend(query2) if balance2 is not None: balance = balance2 - else : + else: (query2, balance2) = get_from_last_recon(line) query.extend(query2) if balance2 is not None: @@ -743,18 +779,16 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): break return balance - @fields.depends('id', 'date', 'cashbook', \ - '_parent_cashbook.id', 'reconciliation', \ - '_parent_reconciliation.start_amount',\ - '_parent_reconciliation.state') + @fields.depends( + 'id', 'date', 'cashbook', '_parent_cashbook.id', 'reconciliation', + '_parent_reconciliation.start_amount', '_parent_reconciliation.state') def on_change_with_balance(self, name=None): """ compute balance until current line, with current sort order, try to use a reconciliation as start to speed up calculation """ Line2 = Pool().get('cashbook.line') - return Line2.get_balance_of_line(self, - field_name='amount', - credit_name='credit', + return Line2.get_balance_of_line( + self, field_name='amount', credit_name='credit', debit_name='debit') @classmethod @@ -764,12 +798,14 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): values2 = {} values2.update(values) - bookingtype = values2.get('bookingtype', getattr(line, 'bookingtype', None)) + bookingtype = values2.get( + 'bookingtype', getattr(line, 'bookingtype', None)) if (bookingtype in ['in', 'out', 'mvin', 'mvout']) and \ ('splitlines' not in values2.keys()): if line: if len(line.splitlines) > 0: - values2['splitlines'] = [('delete', [x.id for x in line.splitlines])] + values2['splitlines'] = [ + ('delete', [x.id for x in line.splitlines])] if bookingtype in ['in', 'out']: values2['booktransf'] = None @@ -788,7 +824,8 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): transfer booking """ line_currency = getattr(line.currency, 'id', None) - booktransf_currency = getattr(getattr(line.booktransf, 'currency', {}), 'id', None) + booktransf_currency = getattr(getattr( + line.booktransf, 'currency', {}), 'id', None) result = { 'cashbook': getattr(line.booktransf, 'id', None), @@ -797,13 +834,11 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): 'description': line.description, 'booktransf': line.cashbook.id, 'reference': line.id, - 'amount': line.amount \ - if line_currency == booktransf_currency \ - else line.amount_2nd_currency, - 'amount_2nd_currency': line.amount \ - if line_currency != booktransf_currency \ - else None, - } + 'amount': line.amount + if line_currency == booktransf_currency + else line.amount_2nd_currency, + 'amount_2nd_currency': line.amount + if line_currency != booktransf_currency else None} # update values from 'values' result.update(values) return result @@ -813,10 +848,12 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): """ compute debit/credit from amount """ if isinstance(values, dict): - type_ = values.get('bookingtype', getattr(line, 'bookingtype', None)) + type_ = values.get( + 'bookingtype', getattr(line, 'bookingtype', None)) amount = values.get('amount', None) - else : - type_ = getattr(values, 'bookingtype', getattr(line, 'bookingtype', None)) + else: + type_ = getattr( + values, 'bookingtype', getattr(line, 'bookingtype', None)) amount = getattr(values, 'amount', None) result = {} @@ -824,15 +861,11 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): if amount is not None: if type_ in ['in', 'mvin', 'spin']: result.update({ - 'debit': Decimal('0.0'), - 'credit': amount, - }) + 'debit': Decimal('0.0'), 'credit': amount}) elif type_ in ['out', 'mvout', 'spout']: result.update({ - 'debit': amount, - 'credit': Decimal('0.0'), - }) - else : + 'debit': amount, 'credit': Decimal('0.0')}) + else: raise ValueError('invalid "bookingtype"') return result @@ -851,30 +884,27 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): if line.date < line.cashbook.start_date: raise UserError(gettext( 'cashbook.msg_line_date_before_book', - datebook = Report.format_date(line.cashbook.start_date), - recname = line.rec_name, - )) + datebook=Report.format_date(line.cashbook.start_date), + recname=line.rec_name)) # line: category <--> bookingtype? if line.category: - if not line.bookingtype in types[line.category.cattype]: + if line.bookingtype not in types[line.category.cattype]: raise UserError(gettext( 'cashbook.msg_line_invalid_category', - recname = line.rec_name, - booktype = line.bookingtype_string, - )) + recname=line.rec_name, + booktype=line.bookingtype_string)) # splitline: category <--> bookingtype? for spline in line.splitlines: if spline.splittype != 'cat': continue - if not line.bookingtype in types[spline.category.cattype]: + if line.bookingtype not in types[spline.category.cattype]: raise UserError(gettext( 'cashbook.msg_line_split_invalid_category', - recname = line.rec_name, - splitrecname = spline.rec_name, - booktype = line.bookingtype_string, - )) + recname=line.rec_name, + splitrecname=spline.rec_name, + booktype=line.bookingtype_string)) @classmethod def check_permission_write(cls, lines, values={}): @@ -885,29 +915,28 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): if line.cashbook.state != 'open': raise UserError(gettext( 'cashbook.msg_book_deny_write', - bookname = line.cashbook.rec_name, - state_txt = line.cashbook.state_string, - )) + bookname=line.cashbook.rec_name, + state_txt=line.cashbook.state_string)) # deny write if reconciliation is 'check' or 'done' if line.reconciliation: if line.reconciliation.state == 'done': raise UserError(gettext( 'cashbook.msg_line_deny_write_by_reconciliation', - recname = line.rec_name, - reconame = line.reconciliation.rec_name, - )) + recname=line.rec_name, + reconame=line.reconciliation.rec_name)) # deny write if line is not 'Edit' if line.state != 'edit': # allow state-update, if its the only action - if not ((len(set({'state', 'reconciliation', 'number'}).intersection(values.keys())) > 0) \ - and (len(values.keys()) == 1)): + if not ((len(set({ + 'state', 'reconciliation', 'number' + }).intersection(values.keys())) > 0) + and (len(values.keys()) == 1)): raise UserError(gettext( 'cashbook.msg_line_deny_write', - recname = line.rec_name, - state_txt = line.state_string, - )) + recname=line.rec_name, + state_txt=line.state_string)) @classmethod def check_permission_delete(cls, lines): @@ -917,16 +946,14 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): if line.cashbook.state == 'closed': raise UserError(gettext( 'cashbook.msg_line_deny_delete1', - linetxt = line.rec_name, - bookname = line.cashbook.rec_name, - bookstate = line.cashbook.state_string, - )) + linetxt=line.rec_name, + bookname=line.cashbook.rec_name, + bookstate=line.cashbook.state_string)) if line.state != 'edit': raise UserError(gettext( 'cashbook.msg_line_deny_delete2', - linetxt = line.rec_name, - linestate = line.state_string, - )) + linetxt=line.rec_name, + linestate=line.state_string)) @classmethod def update_values_by_splitlines(cls, lines): @@ -936,7 +963,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): for line in lines: amount = sum([x.amount for x in line.splitlines]) if amount != line.amount: - to_write.extend([ [line], {'amount': amount,} ]) + to_write.extend([[line], {'amount': amount}]) return to_write @classmethod @@ -946,7 +973,8 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): if ('splitlines' in values.keys()) and ('amount' not in values.keys()): for action in values['splitlines']: if action[0] == 'create': - values['amount'] = sum([x.get('amount', None) for x in action[1]]) + values['amount'] = sum([ + x.get('amount', None) for x in action[1]]) return values @classmethod @@ -956,7 +984,8 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): Cashbook = Pool().get('cashbook.book') cashbook = values.get('cashbook', None) if cashbook: - values.update(cls.add_2nd_currency(values, Cashbook(cashbook).currency)) + values.update(cls.add_2nd_currency( + values, Cashbook(cashbook).currency)) return values @classmethod @@ -975,7 +1004,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): default = default.copy() default.setdefault('number', None) default.setdefault('state', cls.default_state()) - return super(Line, cls).copy(moves, default=default) + return super(Line, cls).copy(lines, default=default) @classmethod def create(cls, vlist): @@ -988,7 +1017,8 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): values.update(cls.clear_by_bookingtype(values)) values.update(cls.add_2nd_unit_values(values)) - # deny add to reconciliation if state is not 'check', 'recon' or 'done' + # deny add to reconciliation if state is + # not 'check', 'recon' or 'done' if values.get('reconciliation', None): if not values.get('state', '-') in ['check', 'done', 'recon']: date_txt = '-' @@ -996,11 +1026,9 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): date_txt = Report.format_date(values.get('date', None)) raise UserError(gettext( 'cashbook.msg_line_deny_recon_by_state', - recname = '%(date)s|%(descr)s' % { + recname='%(date)s|%(descr)s' % { 'date': date_txt, - 'descr': values.get('description', '-'), - }, - )) + 'descr': values.get('description', '-')})) return super(Line, cls).create(vlist) @classmethod @@ -1015,21 +1043,21 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): for line in lines: if line.reconciliation: - # deny state-change to 'edit' if line is linked to reconciliation + # deny state-change to 'edit' if line is + # linked to reconciliation if values.get('state', '-') == 'edit': raise UserError(gettext( 'cashbook.msg_line_deny_stateedit_with_recon', - recname = line.rec_name, - )) + recname=line.rec_name)) - # deny add to reconciliation if state is not 'check', 'recon' or 'done' + # deny add to reconciliation if state is + # not 'check', 'recon' or 'done' if values.get('reconciliation', None): for line in lines: - if not line.state in ['check', 'done', 'recon']: + if line.state not in ['check', 'done', 'recon']: raise UserError(gettext( 'cashbook.msg_line_deny_recon_by_state', - recname = line.rec_name - )) + recname=line.rec_name)) # update debit / credit fields_update = cls.get_fields_write_update() @@ -1043,13 +1071,15 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView): updt_fields = [] updt_fields.extend(values.keys()) if 'bookingtype' in values.keys(): - updt_fields.extend([x for x in fields_update if x not in values.keys()]) + updt_fields.extend([ + x for x in fields_update + if x not in values.keys()]) values2.update(cls.get_debit_credit({ - x:values.get(x, getattr(line, x)) for x in updt_fields - }, line=line)) + x: values.get(x, getattr(line, x)) + for x in updt_fields}, line=line)) to_write.extend([lines, values2]) - else : + else: to_write.extend([lines, values]) super(Line, cls).write(*to_write) @@ -1068,23 +1098,27 @@ class LineContext(ModelView): 'Line Context' __name__ = 'cashbook.line.context' - date_from = fields.Date(string='Start Date', depends=['date_to'], + date_from = fields.Date( + string='Start Date', depends=['date_to'], help='Limits the date range for the displayed entries.', domain=[ If(Eval('date_to') & Eval('date_from'), ('date_from', '<=', Eval('date_to')), ()), ]) - date_to = fields.Date(string='End Date', depends=['date_from'], + date_to = fields.Date( + string='End Date', depends=['date_from'], help='Limits the date range for the displayed entries.', domain=[ If(Eval('date_to') & Eval('date_from'), ('date_from', '<=', Eval('date_to')), ()), ]) - checked = fields.Boolean(string='Checked', + checked = fields.Boolean( + string='Checked', help='Show account lines in Checked-state.') - done = fields.Boolean(string='Done', + done = fields.Boolean( + string='Done', help='Show account lines in Done-state.') @classmethod diff --git a/mixin.py b/mixin.py index 33e8fca..8c1318c 100644 --- a/mixin.py +++ b/mixin.py @@ -17,13 +17,14 @@ STATES = { Eval('state_cashbook', '') != 'open', ), } -DEPENDS=['state', 'state_cashbook'] +DEPENDS = ['state', 'state_cashbook'] class SecondCurrencyMixin: """ two fields for 2nd currency: amount + rate """ - amount_2nd_currency = fields.Numeric(string='Amount Second Currency', + amount_2nd_currency = fields.Numeric( + string='Amount Second Currency', digits=(16, Eval('currency2nd_digits', 2)), states={ 'readonly': Or( @@ -33,7 +34,8 @@ class SecondCurrencyMixin: 'required': Bool(Eval('currency2nd')), 'invisible': ~Bool(Eval('currency2nd')), }, depends=DEPENDS+['currency2nd_digits', 'currency2nd']) - rate_2nd_currency = fields.Function(fields.Numeric(string='Rate', + rate_2nd_currency = fields.Function(fields.Numeric( + string='Rate', help='Exchange rate between the currencies of the participating cashbooks.', digits=(rate_decimal * 2, rate_decimal), states={ @@ -46,9 +48,11 @@ class SecondCurrencyMixin: }, depends=DEPENDS+['currency2nd_digits', 'currency2nd']), 'on_change_with_rate_2nd_currency', setter='set_rate_2nd_currency') - currency2nd = fields.Function(fields.Many2One(model_name='currency.currency', + currency2nd = fields.Function(fields.Many2One( + model_name='currency.currency', string="2nd Currency", readonly=True), 'on_change_with_currency2nd') - currency2nd_digits = fields.Function(fields.Integer(string='2nd Currency Digits', + currency2nd_digits = fields.Function(fields.Integer( + string='2nd Currency Digits', readonly=True), 'on_change_with_currency2nd_digits') @classmethod @@ -69,8 +73,7 @@ class SecondCurrencyMixin: booktransf = Cashbook(booktransf) if from_currency.id != booktransf.currency.id: with Transaction().set_context({ - 'date': values.get('date', IrDate.today()), - }): + 'date': values.get('date', IrDate.today())}): values['amount_2nd_currency'] = Currency.compute( from_currency, amount, @@ -78,22 +81,28 @@ class SecondCurrencyMixin: ) return values - @fields.depends('booktransf', '_parent_booktransf.currency', \ - 'currency', 'amount', 'date', 'amount_2nd_currency', 'rate_2nd_currency') + @fields.depends( + 'booktransf', '_parent_booktransf.currency', + 'currency', 'amount', 'date', 'amount_2nd_currency', + 'rate_2nd_currency') def on_change_booktransf(self): """ update amount_2nd_currency """ self.on_change_rate_2nd_currency() - @fields.depends('booktransf', '_parent_booktransf.currency', \ - 'currency', 'amount', 'date', 'amount_2nd_currency', 'rate_2nd_currency') + @fields.depends( + 'booktransf', '_parent_booktransf.currency', + 'currency', 'amount', 'date', 'amount_2nd_currency', + 'rate_2nd_currency') def on_change_amount(self): """ update amount_2nd_currency """ self.on_change_rate_2nd_currency() - @fields.depends('booktransf', '_parent_booktransf.currency', \ - 'currency', 'amount', 'date', 'amount_2nd_currency', 'rate_2nd_currency') + @fields.depends( + 'booktransf', '_parent_booktransf.currency', + 'currency', 'amount', 'date', 'amount_2nd_currency', + 'rate_2nd_currency') def on_change_rate_2nd_currency(self): """ update amount_2nd_currency + rate_2nd_currency """ @@ -109,16 +118,16 @@ class SecondCurrencyMixin: if self.rate_2nd_currency is None: # no rate set, use current rate of target-currency with Transaction().set_context({ - 'date': self.date or IrDate.today(), - }): + 'date': self.date or IrDate.today()}): self.amount_2nd_currency = Currency.compute( self.currency, self.amount, self.booktransf.currency ) if self.amount != Decimal('0.0'): - self.rate_2nd_currency = self.amount_2nd_currency / self.amount - else : + 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 ) @@ -161,10 +170,10 @@ class SecondCurrencyMixin: def on_change_with_rate_2nd_currency(self, name=None): """ get current rate from amount """ - Rate = Pool().get('currency.currency.rate') + Rate = Pool().get('currency.currency.rate') if (self.amount is not None) and \ - (self.amount_2nd_currency is not None): + (self.amount_2nd_currency is not None): if self.amount != Decimal('0.0'): exp = Decimal(Decimal(1) / 10 ** Rate.rate.digits[1]) return (self.amount_2nd_currency / self.amount).quantize(exp) @@ -201,5 +210,3 @@ class MemCacheIndexMx: cls.create_date.select = True # end MemCacheIndexMx - - diff --git a/model.py b/model.py index 7796ced..a3cebb5 100644 --- a/model.py +++ b/model.py @@ -8,19 +8,21 @@ from trytond.transaction import Transaction from trytond.pool import Pool from trytond.cache import MemoryCache from trytond.config import config -from datetime import timedelta, datetime +from datetime import timedelta from decimal import Decimal -from sql import With, Literal +from sql import With from sql.functions import Function from sql.conditionals import Coalesce import copy -if config.get('cashbook', 'memcache', default='yes').lower() in ['yes', '1', 'true']: +if config.get('cashbook', 'memcache', default='yes').lower() \ + in ['yes', '1', 'true']: ENABLE_CACHE = True else: ENABLE_CACHE = False -if config.get('cashbook', 'sync', default='yes').lower() in ['yes', '1', 'true']: +if config.get('cashbook', 'sync', default='yes').lower() \ + in ['yes', '1', 'true']: ENABLE_CACHESYNC = True else: ENABLE_CACHESYNC = False @@ -36,6 +38,7 @@ class ArrayAgg(Function): # end ArrayAgg + class ArrayAppend(Function): """ sql: array_append """ @@ -87,14 +90,14 @@ class MemCache(Model): _cashbook_value_cache = MemoryCache( 'cashbook.book.valuecache', - context = False, - duration = timedelta(seconds=60*60*4)) + context=False, + duration=timedelta(seconds=60*60*4)) @classmethod def read_value(cls, cache_key): """ read values from cache """ - if ENABLE_CACHE == False: + if ENABLE_CACHE is False: return None return copy.deepcopy(cls._cashbook_value_cache.get(cache_key)) @@ -102,23 +105,24 @@ class MemCache(Model): def store_result(cls, records, cache_keys, values, skip_records=[]): """ store result to cache """ - if ENABLE_CACHE == False: + if ENABLE_CACHE is False: return for record in records: if record not in skip_records: continue - data = {x:values[x][record.id] - for x in values.keys() - if record.id in values[x].keys()} - cls._cashbook_value_cache.set(cache_keys[record.id], copy.deepcopy(data)) - if ENABLE_CACHESYNC == True: + data = { + x: values[x][record.id] + for x in values.keys() if record.id in values[x].keys()} + cls._cashbook_value_cache.set( + cache_keys[record.id], copy.deepcopy(data)) + if ENABLE_CACHESYNC is True: cls._cashbook_value_cache.sync(Transaction()) @classmethod def store_value(cls, cache_key, values): """ store values to cache """ - if ENABLE_CACHE == False: + if ENABLE_CACHE is False: return cls._cashbook_value_cache.set(cache_key, copy.deepcopy(values)) @@ -126,7 +130,7 @@ class MemCache(Model): def read_from_cache(cls, records, cache_keys, names, result): """ get stored values from memcache """ - if ENABLE_CACHE == False: + if ENABLE_CACHE is False: return (records, result) todo_records = [] @@ -141,7 +145,7 @@ class MemCache(Model): if result[name][record.id] is None: result[name][record.id] = Decimal('0.0') result[name][record.id] += values[name] - else : + else: todo_records.append(record) return (todo_records, result) @@ -152,7 +156,7 @@ class MemCache(Model): pool = Pool() cursor = Transaction().connection.cursor() - if ENABLE_CACHE == False: + if ENABLE_CACHE is False: return '-' fname = [name, str(record.id)] @@ -173,15 +177,17 @@ class MemCache(Model): tab_model = Model.__table__() tab_query = Model.search(line['query'], query=True) - qu1 = tab_model.join(tab_query, - condition=tab_query.id==tab_model.id, + qu1 = tab_model.join( + tab_query, + condition=tab_query.id == tab_model.id, ).select( tab_model.id, tab_model.write_date, tab_model.create_date, - limit = 1, - order_by = [ - Coalesce(tab_model.write_date, tab_model.create_date).desc, + limit=1, + order_by=[ + Coalesce( + tab_model.write_date, tab_model.create_date).desc, tab_model.id.desc, ], ) @@ -193,7 +199,7 @@ class MemCache(Model): records[0][1], records[0][2], )) - else : + else: fname.append('0') if 'cachekey' in line.keys(): @@ -216,11 +222,12 @@ class MemCache(Model): def record_update(cls, cache_key, record): """ update cache-value """ - if ENABLE_CACHE == False: + if ENABLE_CACHE is False: return - cls.store_value(cache_key, + cls.store_value( + cache_key, cls.genkey(record.id, record.write_date, record.create_date) - if record is not None else None) + if record is not None else None) # end mem_cache @@ -235,18 +242,17 @@ def sub_ids_hierarchical(model_name): lines = With('parent', 'id', recursive=True) lines.query = tab_mod.select( tab_mod.id, tab_mod.id, - ) | tab_mod2.join(lines, - condition=lines.id==tab_mod2.parent, - ).select( - lines.parent, tab_mod2.id, - ) + ) | tab_mod2.join( + lines, + condition=lines.id == tab_mod2.parent, + ).select(lines.parent, tab_mod2.id) lines.query.all_ = True query = lines.select( lines.parent, ArrayAgg(lines.id).as_('subids'), group_by=[lines.parent], - with_ = [lines]) + with_=[lines]) return query @@ -262,24 +268,28 @@ 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 == None, ) - lines.query |= tab_mod2.join(lines, - condition=lines.id==tab_mod2.parent, + lines.query |= tab_mod2.join( + lines, + condition=lines.id == tab_mod2.parent, ).select( - tab_mod2.id, tab_mod2.name, ArrayAppend(lines.name_path, tab_mod2.name), + tab_mod2.id, + tab_mod2.name, + ArrayAppend(lines.name_path, tab_mod2.name), ) lines.query.all_ = True query = lines.select( ArrayToString(lines.name_path, '/').as_('rec_name'), - where = table.id==lines.id, - with_ = [lines]) + where=table.id == lines.id, + with_=[lines]) return [query] class UserValueMixin(ValueMixin): - iduser = fields.Many2One(model_name='res.user', string="User", + iduser = fields.Many2One( + model_name='res.user', string="User", select=True, ondelete='CASCADE', required=True) @classmethod @@ -313,6 +323,7 @@ class UserMultiValueMixin(MultiValueMixin): Value = self.multivalue_model(name) if issubclass(Value, UserValueMixin): pattern = self.updt_multivalue_pattern(pattern) - return super(UserMultiValueMixin, self).set_multivalue(name, value, **pattern) + return super( + UserMultiValueMixin, self).set_multivalue(name, value, **pattern) # end UserMultiValueMixin diff --git a/reconciliation.py b/reconciliation.py index 8978e6c..c3c640d 100644 --- a/reconciliation.py +++ b/reconciliation.py @@ -4,15 +4,12 @@ # full copyright notices and license terms. from trytond.model import Workflow, ModelView, ModelSQL, fields -from trytond.transaction import Transaction -from trytond.pyson import Eval, If, Or, Bool +from trytond.pyson import Eval, If, Or from trytond.pool import Pool from trytond.report import Report from trytond.exceptions import UserError from trytond.i18n import gettext from decimal import Decimal -from sql.operators import Equal, Between -from sql import Literal, Null from datetime import timedelta from .book import sel_state_book @@ -29,21 +26,25 @@ STATES = { Eval('state_cashbook', '') != 'open', ), } -DEPENDS=['state', 'state_cashbook'] +DEPENDS = ['state', 'state_cashbook'] class Reconciliation(Workflow, ModelSQL, ModelView): 'Cashbook Reconciliation' __name__ = 'cashbook.recon' - cashbook = fields.Many2One(string='Cashbook', required=True, select=True, + cashbook = fields.Many2One( + string='Cashbook', required=True, select=True, model_name='cashbook.book', ondelete='CASCADE', readonly=True) - date = fields.Date(string='Date', required=True, select=True, + date = fields.Date( + string='Date', required=True, select=True, states=STATES, depends=DEPENDS) - feature = fields.Function(fields.Char(string='Feature', readonly=True, + feature = fields.Function(fields.Char( + string='Feature', readonly=True, states={'invisible': True}), 'on_change_with_feature') - date_from = fields.Date(string='Start Date', + date_from = fields.Date( + string='Start Date', required=True, domain=[ If(Eval('date_to') & Eval('date_from'), @@ -51,7 +52,8 @@ class Reconciliation(Workflow, ModelSQL, ModelView): ()), ], states=STATES, depends=DEPENDS+['date_to']) - date_to = fields.Date(string='End Date', + date_to = fields.Date( + string='End Date', required=True, select=True, domain=[ If(Eval('date_to') & Eval('date_from'), @@ -59,14 +61,17 @@ class Reconciliation(Workflow, ModelSQL, ModelView): ()), ], states=STATES, depends=DEPENDS+['date_from']) - start_amount = fields.Numeric(string='Start Amount', required=True, + start_amount = fields.Numeric( + string='Start Amount', required=True, readonly=True, digits=(16, Eval('currency_digits', 2)), depends=['currency_digits']) - end_amount = fields.Numeric(string='End Amount', required=True, + end_amount = fields.Numeric( + string='End Amount', required=True, readonly=True, digits=(16, Eval('currency_digits', 2)), depends=['currency_digits']) - lines = fields.One2Many(string='Lines', field='reconciliation', + lines = fields.One2Many( + string='Lines', field='reconciliation', model_name='cashbook.line', states=STATES, depends=DEPENDS+['date_from', 'date_to', 'cashbook'], add_remove=[ @@ -80,18 +85,23 @@ class Reconciliation(Workflow, ModelSQL, ModelView): ('date', '<=', Eval('date_to')), ]) - currency = fields.Function(fields.Many2One(model_name='currency.currency', + currency = fields.Function(fields.Many2One( + model_name='currency.currency', string="Currency"), 'on_change_with_currency') - currency_digits = fields.Function(fields.Integer(string='Currency Digits'), - 'on_change_with_currency_digits') - predecessor = fields.Function(fields.Many2One(string='Predecessor', readonly=True, + currency_digits = fields.Function(fields.Integer( + string='Currency Digits'), + 'on_change_with_currency_digits') + predecessor = fields.Function(fields.Many2One( + string='Predecessor', readonly=True, model_name='cashbook.recon'), 'on_change_with_predecessor') - state = fields.Selection(string='State', required=True, readonly=True, + state = fields.Selection( + string='State', required=True, readonly=True, select=True, selection=sel_reconstate) state_string = state.translated('state') - state_cashbook = fields.Function(fields.Selection(string='State of Cashbook', + state_cashbook = fields.Function(fields.Selection( + string='State of Cashbook', readonly=True, states={'invisible': True}, selection=sel_state_book), 'on_change_with_state_cashbook') @@ -140,9 +150,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView): [ # enclose other record ('date_from', '>=', self.date_from), ('date_to', '<=', self.date_to), - ], - ], - ] + ]]] if Recon.search_count(query) > 0: raise UserError(gettext('cashbook.msg_recon_err_overlap')) @@ -155,18 +163,17 @@ class Reconciliation(Workflow, ModelSQL, ModelView): for reconciliation in reconciliations: if Line.search_count([ - ('date', '>', reconciliation.date_from), - ('date', '<', reconciliation.date_to), - ('cashbook.id', '=', reconciliation.cashbook.id), - ('state', 'not in', ['check', 'recon']), - ]) > 0: + ('date', '>', reconciliation.date_from), + ('date', '<', reconciliation.date_to), + ('cashbook.id', '=', reconciliation.cashbook.id), + ('state', 'not in', ['check', 'recon']), + ]) > 0: raise UserError(gettext( 'cashbook.mds_recon_deny_line_not_check', - bookname = reconciliation.cashbook.rec_name, - reconame = reconciliation.rec_name, - datefrom = Report.format_date(reconciliation.date_from), - dateto = Report.format_date(reconciliation.date_to), - )) + bookname=reconciliation.cashbook.rec_name, + reconame=reconciliation.rec_name, + datefrom=Report.format_date(reconciliation.date_from), + dateto=Report.format_date(reconciliation.date_to))) @classmethod def get_values_wfedit(cls, reconciliation): @@ -191,7 +198,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView): values = {} if reconciliation.predecessor: values['start_amount'] = reconciliation.predecessor.end_amount - else : + else: values['start_amount'] = Decimal('0.0') values['end_amount'] = values['start_amount'] @@ -209,7 +216,8 @@ class Reconciliation(Workflow, ModelSQL, ModelView): # add amounts of new lines values['end_amount'] += sum([x.credit - x.debit for x in lines]) # add amounts of already linked lines - values['end_amount'] += sum([x.credit - x.debit for x in reconciliation.lines]) + values['end_amount'] += sum([ + x.credit - x.debit for x in reconciliation.lines]) return values @classmethod @@ -248,18 +256,18 @@ class Reconciliation(Workflow, ModelSQL, ModelView): if reconciliation.predecessor.state != 'done': raise UserError(gettext( 'cashbook.msg_recon_predecessor_not_done', - recname_p = reconciliation.predecessor.rec_name, - recname_c = reconciliation.rec_name, - )) + recname_p=reconciliation.predecessor.rec_name, + recname_c=reconciliation.rec_name)) # check if current.date_from == predecessor.date_to - if reconciliation.predecessor.date_to != reconciliation.date_from: + if reconciliation.predecessor.date_to != \ + reconciliation.date_from: raise UserError(gettext( 'cashbook.msg_recon_date_from_to_mismatch', - datefrom = Report.format_date(reconciliation.date_from), - dateto = Report.format_date(reconciliation.predecessor.date_to), - recname = reconciliation.rec_name, - )) + datefrom=Report.format_date(reconciliation.date_from), + dateto=Report.format_date( + reconciliation.predecessor.date_to), + recname=reconciliation.rec_name)) to_write.extend([ [reconciliation], @@ -281,13 +289,11 @@ class Reconciliation(Workflow, ModelSQL, ModelView): to_wfrecon_line = [] for reconciliation in reconciliations: to_wfrecon_line.extend([ - x for x in reconciliation.lines \ - if x.state == 'check' - ]) + x for x in reconciliation.lines + if x.state == 'check']) to_wfdone_line.extend([ - x for x in reconciliation.lines \ - if x.state == 'recon' - ]) + x for x in reconciliation.lines + if x.state == 'recon']) # deny if there are lines not linked to reconciliation if Line.search_count([ @@ -299,14 +305,12 @@ class Reconciliation(Workflow, ModelSQL, ModelView): ('date', '<', reconciliation.date_to), ], # lines at from-date must relate to a reconciliation - ('date', '=', reconciliation.date_from), - ], - ]) > 0: + ('date', '=', reconciliation.date_from)], + ]) > 0: raise UserError(gettext( 'cashbook.msg_recon_lines_no_linked', - date_from = Report.format_date(reconciliation.date_from), - date_to = Report.format_date(reconciliation.date_to), - )) + date_from=Report.format_date(reconciliation.date_from), + date_to=Report.format_date(reconciliation.date_to),)) if len(to_wfrecon_line) > 0: Line.wfrecon(to_wfrecon_line) @@ -318,9 +322,12 @@ class Reconciliation(Workflow, ModelSQL, ModelView): """ 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) 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(self.start_amount or 0.0, None), + 'from': 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( + self.start_amount or 0.0, None), 'end_amount': Report.format_number(self.end_amount or 0.0, None), 'symbol': getattr(self.currency, 'symbol', '-'), 'num': len(self.lines), @@ -459,9 +466,8 @@ class Reconciliation(Workflow, ModelSQL, ModelView): if reconciliation.cashbook.state != 'open': raise UserError(gettext( 'cashbook.msg_book_deny_write', - bookname = reconciliation.cashbook.rec_name, - state_txt = reconciliation.cashbook.state_string, - )) + bookname=reconciliation.cashbook.rec_name, + state_txt=reconciliation.cashbook.state_string)) super(Reconciliation, cls).write(*args) @classmethod @@ -472,16 +478,14 @@ class Reconciliation(Workflow, ModelSQL, ModelView): if reconciliation.cashbook.state == 'closed': raise UserError(gettext( 'cashbook.msg_line_deny_delete1', - linetxt = reconciliation.rec_name, - bookname = reconciliation.cashbook.rec_name, - bookstate = reconciliation.cashbook.state_string, - )) + linetxt=reconciliation.rec_name, + bookname=reconciliation.cashbook.rec_name, + bookstate=reconciliation.cashbook.state_string)) if reconciliation.state != 'edit': raise UserError(gettext( 'cashbook.msg_recon_deny_delete2', - recontxt = reconciliation.rec_name, - reconstate = reconciliation.state_string, - )) + recontxt=reconciliation.rec_name, + reconstate=reconciliation.state_string)) super(Reconciliation, cls).delete(reconciliations) diff --git a/splitline.py b/splitline.py index 0c7ad63..3aed848 100644 --- a/splitline.py +++ b/splitline.py @@ -4,13 +4,12 @@ # full copyright notices and license terms. -from trytond.model import ModelView, ModelSQL, Workflow, fields, Check +from trytond.model import ModelView, ModelSQL, fields from trytond.pool import Pool from trytond.pyson import Eval, If from trytond.report import Report from trytond.i18n import gettext -from trytond.transaction import Transaction -from .line import sel_linetype, sel_bookingtype, STATES, DEPENDS +from .line import sel_bookingtype, STATES, DEPENDS from .book import sel_state_book from .mixin import SecondCurrencyMixin, MemCacheIndexMx @@ -30,15 +29,18 @@ class SplitLine(SecondCurrencyMixin, MemCacheIndexMx, ModelSQL, ModelView): 'Split booking line' __name__ = 'cashbook.split' - line = fields.Many2One(string='Line', required=True, + line = fields.Many2One( + string='Line', required=True, select=True, ondelete='CASCADE', model_name='cashbook.line', readonly=True) - description = fields.Text(string='Description', - states=STATES, depends=DEPENDS) - splittype = fields.Selection(string='Type', required=True, + description = fields.Text( + string='Description', states=STATES, depends=DEPENDS) + splittype = fields.Selection( + string='Type', required=True, help='Type of split booking line', selection=sel_linetype, states=STATES, depends=DEPENDS, select=True) - category = fields.Many2One(string='Category', select=True, + category = fields.Many2One( + string='Category', select=True, model_name='cashbook.category', ondelete='RESTRICT', states={ 'readonly': STATES['readonly'], @@ -51,9 +53,11 @@ class SplitLine(SecondCurrencyMixin, MemCacheIndexMx, ModelSQL, ModelView): ('cattype', '=', 'in'), ('cattype', '=', 'out'), )]) - category_view = fields.Function(fields.Char(string='Category', readonly=True), + category_view = fields.Function(fields.Char( + string='Category', readonly=True), 'on_change_with_category_view') - booktransf = fields.Many2One(string='Source/Dest', + booktransf = fields.Many2One( + string='Source/Dest', ondelete='RESTRICT', model_name='cashbook.book', domain=[ ('owner.id', '=', Eval('owner_cashbook', -1)), @@ -66,32 +70,43 @@ class SplitLine(SecondCurrencyMixin, MemCacheIndexMx, ModelSQL, ModelView): 'required': Eval('splittype', '') == 'tr', }, depends=DEPENDS+['bookingtype', 'owner_cashbook', 'cashbook']) - amount = fields.Numeric(string='Amount', digits=(16, Eval('currency_digits', 2)), + amount = fields.Numeric( + string='Amount', digits=(16, Eval('currency_digits', 2)), required=True, states=STATES, depends=DEPENDS+['currency_digits']) - date = fields.Function(fields.Date(string='Date', readonly=True), - 'on_change_with_date') - target = fields.Function(fields.Reference(string='Target', readonly=True, + date = fields.Function(fields.Date( + string='Date', readonly=True), 'on_change_with_date') + target = fields.Function(fields.Reference( + string='Target', readonly=True, selection=sel_target), 'on_change_with_target') - currency = fields.Function(fields.Many2One(model_name='currency.currency', + currency = fields.Function(fields.Many2One( + model_name='currency.currency', string="Currency", readonly=True), 'on_change_with_currency') - currency_digits = fields.Function(fields.Integer(string='Currency Digits', + currency_digits = fields.Function(fields.Integer( + string='Currency Digits', readonly=True), 'on_change_with_currency_digits') - bookingtype = fields.Function(fields.Selection(string='Type', readonly=True, + bookingtype = fields.Function(fields.Selection( + string='Type', readonly=True, selection=sel_bookingtype), 'on_change_with_bookingtype') - state = fields.Function(fields.Selection(string='State', readonly=True, + state = fields.Function(fields.Selection( + string='State', readonly=True, selection=sel_linetype), 'on_change_with_state') - cashbook = fields.Function(fields.Many2One(string='Cashbook', + cashbook = fields.Function(fields.Many2One( + string='Cashbook', readonly=True, states={'invisible': True}, model_name='cashbook.book'), 'on_change_with_cashbook') - feature = fields.Function(fields.Char(string='Feature', readonly=True, + feature = fields.Function(fields.Char( + string='Feature', readonly=True, states={'invisible': True}), 'on_change_with_feature') - booktransf_feature = fields.Function(fields.Char(string='Feature', readonly=True, + booktransf_feature = fields.Function(fields.Char( + string='Feature', readonly=True, states={'invisible': True}), 'on_change_with_booktransf_feature') - state_cashbook = fields.Function(fields.Selection(string='State of Cashbook', + state_cashbook = fields.Function(fields.Selection( + string='State of Cashbook', readonly=True, states={'invisible': True}, selection=sel_state_book), 'on_change_with_state_cashbook') - owner_cashbook = fields.Function(fields.Many2One(string='Owner', readonly=True, + owner_cashbook = fields.Function(fields.Many2One( + string='Owner', readonly=True, states={'invisible': True}, model_name='res.user'), 'on_change_with_owner_cashbook') @@ -108,8 +123,10 @@ class SplitLine(SecondCurrencyMixin, MemCacheIndexMx, ModelSQL, ModelView): 'desc': (self.description or '-')[:40], 'amount': Report.format_number(self.amount, None), 'symbol': getattr(self.currency, 'symbol', '-'), - 'target': self.category_view if self.splittype == 'cat' else self.booktransf.rec_name, - 'type': gettext('cashbook.msg_line_bookingtype_%s' % self.line.bookingtype), + 'target': self.category_view + if self.splittype == 'cat' else self.booktransf.rec_name, + 'type': gettext( + 'cashbook.msg_line_bookingtype_%s' % self.line.bookingtype), } @fields.depends('splittype', 'category', 'booktransf') @@ -151,9 +168,9 @@ class SplitLine(SecondCurrencyMixin, MemCacheIndexMx, ModelSQL, ModelView): if self.category: cfg1 = Configuration.get_singleton() - if getattr(cfg1, 'catnamelong', True) == True: + if getattr(cfg1, 'catnamelong', True) is True: return self.category.rec_name - else : + else: return self.category.name @fields.depends('line', '_parent_line.state') @@ -246,7 +263,7 @@ class SplitLine(SecondCurrencyMixin, MemCacheIndexMx, ModelSQL, ModelView): to_update_line = [] for record in records: - if not record.line in to_update_line: + if record.line not in to_update_line: to_update_line.append(record.line) to_write = Line2.update_values_by_splitlines(to_update_line) @@ -268,7 +285,7 @@ class SplitLine(SecondCurrencyMixin, MemCacheIndexMx, ModelSQL, ModelView): if 'amount' in values.keys(): for record in records: - if not record.line in to_update_line: + if record.line not in to_update_line: to_update_line.append(record.line) super(SplitLine, cls).write(*args) diff --git a/tests/test_line.py b/tests/test_line.py index 0cb6608..e705526 100644 --- a/tests/test_line.py +++ b/tests/test_line.py @@ -811,6 +811,49 @@ class LineTestCase(ModuleTestCase): 'amount': Decimal('0.0'), }]) + @with_transaction() + def test_line_check_deny_delete_of_party(self): + """ create cashbook + line, delete party should fail + """ + pool = Pool() + Book = pool.get('cashbook.book') + Line = pool.get('cashbook.line') + Party = pool.get('party.party') + + types = self.prep_type() + category = self.prep_category(cattype='in') + company = self.prep_company() + party = self.prep_party() + book, = Book.create([{ + 'name': 'Book 1', + 'btype': types.id, + 'company': company.id, + 'currency': company.currency.id, + 'number_sequ': self.prep_sequence().id, + 'start_date': date(2022, 5, 1), + 'lines': [('create', [{ + 'date': date(2022, 5, 1), + 'description': 'Text 1', + 'category': category.id, + 'bookingtype': 'in', + 'amount': Decimal('1.0'), + 'party': party.id, + }])], + }]) + self.assertEqual(book.name, 'Book 1') + self.assertEqual(book.state, 'open') + self.assertEqual(len(book.lines), 1) + self.assertEqual(book.lines[0].party.rec_name, 'Party') + self.assertEqual(book.lines[0].party.id, party.id) + + self.assertEqual(Party.search_count([('name', '=', 'Party')]), 1) + + self.assertRaisesRegex( + UserError, + 'The records could not be deleted because they are used by field "Party" of "Cashbook Line".', + Party.delete, + [party]) + @with_transaction() def test_line_create_check_deny_write(self): """ create cashbook + line, 'close' book, write to line diff --git a/types.py b/types.py index c86cc02..3ae0ba7 100644 --- a/types.py +++ b/types.py @@ -14,9 +14,11 @@ class Type(ModelSQL, ModelView): name = fields.Char(string='Name', required=True, translate=True) short = fields.Char(string='Abbreviation', required=True, size=3) - company = fields.Many2One(string='Company', model_name='company.company', + company = fields.Many2One( + string='Company', model_name='company.company', required=True, ondelete="RESTRICT") - feature = fields.Selection(string='Feature', required=True, + feature = fields.Selection( + string='Feature', required=True, selection='get_sel_feature', select=True, help='Select feature set of the Cashbook.') @@ -53,7 +55,8 @@ class Type(ModelSQL, ModelView): def search_rec_name(cls, name, clause): """ search in name + short """ - return ['OR', + return [ + 'OR', ('name',) + tuple(clause[1:]), ('short',) + tuple(clause[1:]), ] diff --git a/wizard_booking.py b/wizard_booking.py index 5c58a69..ef27f32 100644 --- a/wizard_booking.py +++ b/wizard_booking.py @@ -7,7 +7,7 @@ from trytond.model import ModelView, fields from trytond.wizard import Wizard, StateView, StateTransition, Button from trytond.pool import Pool from trytond.transaction import Transaction -from trytond.pyson import Eval, Bool, If, And +from trytond.pyson import Eval, Bool, If from decimal import Decimal from .line import sel_bookingtype @@ -18,29 +18,36 @@ class EnterBookingStart(ModelView): 'Enter Booking' __name__ = 'cashbook.enterbooking.start' - cashbook = fields.Many2One(string='Cashbook', model_name='cashbook.book', + cashbook = fields.Many2One( + string='Cashbook', model_name='cashbook.book', domain=[('id', 'in', Eval('cashbooks', [])), ('btype', '!=', None)], depends=['cashbooks'], required=True) - cashbooks = fields.One2Many(string='Cashbooks', field=None, + cashbooks = fields.One2Many( + string='Cashbooks', field=None, model_name='cashbook.book', readonly=True, states={'invisible': True}) - owner_cashbook = fields.Function(fields.Many2One(string='Owner', readonly=True, + owner_cashbook = fields.Function(fields.Many2One( + string='Owner', readonly=True, states={'invisible': True}, model_name='res.user'), 'on_change_with_owner_cashbook') - currency = fields.Function(fields.Many2One(string='Currency', + currency = fields.Function(fields.Many2One( + string='Currency', model_name='currency.currency', states={'invisible': True}), 'on_change_with_currency') - currency_digits = fields.Function(fields.Integer(string='Currency Digits', + currency_digits = fields.Function(fields.Integer( + string='Currency Digits', readonly=True, states={'invisible': True}), 'on_change_with_currency_digits') - bookingtype = fields.Selection(string='Type', required=True, - selection=sel_booktypewiz) - amount = fields.Numeric(string='Amount', + bookingtype = fields.Selection( + string='Type', required=True, selection=sel_booktypewiz) + amount = fields.Numeric( + string='Amount', depends=['currency_digits', 'bookingtype'], digits=(16, Eval('currency_digits', 2)), required=True, domain=[('amount', '>=', Decimal('0.0'))]) description = fields.Text(string='Description') - category = fields.Many2One(string='Category', + category = fields.Many2One( + string='Category', model_name='cashbook.category', depends=['bookingtype'], states={ 'readonly': Bool(Eval('bookingtype')) == False, @@ -55,7 +62,8 @@ class EnterBookingStart(ModelView): )]) # party or cashbook as counterpart - booktransf = fields.Many2One(string='Source/Dest', + booktransf = fields.Many2One( + string='Source/Dest', model_name='cashbook.book', domain=[ ('owner.id', '=', Eval('owner_cashbook', -1)), @@ -65,7 +73,8 @@ class EnterBookingStart(ModelView): 'invisible': ~Eval('bookingtype', '').in_(['mvin', 'mvout']), 'required': Eval('bookingtype', '').in_(['mvin', 'mvout']), }, depends=['bookingtype', 'owner_cashbook', 'cashbook']) - party = fields.Many2One(string='Party', model_name='party.party', + party = fields.Many2One( + string='Party', model_name='party.party', states={ 'invisible': ~Eval('bookingtype', '').in_(['in', 'out']), }, depends=['bookingtype']) @@ -81,7 +90,7 @@ class EnterBookingStart(ModelView): if self.bookingtype: if self.category: - if not self.bookingtype 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') @@ -104,7 +113,7 @@ class EnterBookingStart(ModelView): """ if self.cashbook: return self.cashbook.currency.digits - else : + else: return 2 # end EnterBookingStart @@ -115,7 +124,8 @@ class EnterBookingWizard(Wizard): __name__ = 'cashbook.enterbooking' start_state = 'start' - start = StateView('cashbook.enterbooking.start', + start = StateView( + 'cashbook.enterbooking.start', 'cashbook.enterbooking_start_form', [ Button('Cancel', 'end', 'tryton-cancel'), Button('Save', 'save_', 'tryton-save', default=True), diff --git a/wizard_openline.py b/wizard_openline.py index 770c3da..6ef8cc2 100644 --- a/wizard_openline.py +++ b/wizard_openline.py @@ -5,7 +5,8 @@ from trytond.model import ModelView, fields from trytond.pyson import PYSONEncoder -from trytond.wizard import Wizard, StateView, StateTransition, StateAction, Button +from trytond.wizard import Wizard, StateView, StateTransition, \ + StateAction, Button from trytond.i18n import gettext from trytond.pool import Pool from trytond.exceptions import UserError @@ -28,7 +29,7 @@ class OLineMixin: 'checked': getattr(cfg1, 'checked', None), 'done': getattr(cfg1, 'done', None), }), - 'name' : '%(name)s: %(cashbook)s' % { + 'name': '%(name)s: %(cashbook)s' % { 'name': gettext('cashbook.msg_name_cashbook'), 'cashbook': getattr(book, 'rec_name', '-/-'), }, @@ -42,10 +43,13 @@ class OpenCashBookStart(ModelView): 'Open Cashbook' __name__ = 'cashbook.open_lines.start' - cashbook = fields.Many2One(string='Cashbook', model_name='cashbook.book', + cashbook = fields.Many2One( + string='Cashbook', model_name='cashbook.book', required=True, domain=[('btype', '!=', None)]) - checked = fields.Boolean(string='Checked', help="Show cashbook lines in Checked-state.") - done = fields.Boolean(string='Done', help="Show cashbook lines in Done-state") + checked = fields.Boolean( + string='Checked', help="Show cashbook lines in Checked-state.") + done = fields.Boolean( + string='Done', help="Show cashbook lines in Done-state") date_from = fields.Date(string='Start Date') date_to = fields.Date(string='End Date') @@ -66,7 +70,8 @@ class OpenCashBook(OLineMixin, Wizard): start_state = 'check' check = StateTransition() - askuser = StateView('cashbook.open_lines.start', + askuser = StateView( + 'cashbook.open_lines.start', 'cashbook.open_lines_view_form', [ Button('Cancel', 'end', 'tryton-cancel'), Button('Open', 'open_', 'tryton-ok', default=True), @@ -79,8 +84,7 @@ class OpenCashBook(OLineMixin, Wizard): Book = Pool().get('cashbook.book') with Transaction().set_context({ - '_check_access': True, - }): + '_check_access': True}): books = Book.search([('btype', '!=', None)]) if len(books) == 1: return 'open_' @@ -115,8 +119,7 @@ class OpenCashBook(OLineMixin, Wizard): book = getattr(self.askuser, 'cashbook', None) if book is None: with Transaction().set_context({ - '_check_access': True, - }): + '_check_access': True}): books = Book.search([('btype', '!=', None)]) if len(books) > 0: book = books[0] @@ -158,17 +161,15 @@ class OpenCashBookTree(OLineMixin, Wizard): book = self.record if book is None: with Transaction().set_context({ - '_check_access': True, - }): + '_check_access': True}): books = Book.search([('btype', '!=', None)]) if len(books) > 0: book = books[0] - else : + else: if book.btype is None: raise UserError(gettext( 'cashbook.msg_book_no_type_noopen', - bookname = book.rec_name, - )) + bookname=book.rec_name)) action.update(self.add_action_data(book)) return action, {} diff --git a/wizard_runreport.py b/wizard_runreport.py index b864e1f..534f521 100644 --- a/wizard_runreport.py +++ b/wizard_runreport.py @@ -4,7 +4,6 @@ # full copyright notices and license terms. from trytond.model import ModelView, fields -from trytond.pyson import PYSONEncoder from trytond.wizard import Wizard, StateView, StateReport, Button from trytond.pool import Pool from trytond.pyson import Eval, Bool @@ -15,17 +14,21 @@ class RunCbReportStart(ModelView): 'Cashbook Report' __name__ = 'cashbook.runrepbook.start' - cashbook = fields.Many2One(string='Cashbook', required=True, + cashbook = fields.Many2One( + string='Cashbook', required=True, model_name='cashbook.book', depends=['cashbooks'], domain=[('id', 'in', Eval('cashbooks', []))]) - cashbooks = fields.One2Many(string='Cashbooks', model_name='cashbook.book', + cashbooks = fields.One2Many( + string='Cashbooks', model_name='cashbook.book', field=None, readonly=True, states={'invisible': True}) - reconciliation = fields.Many2One(string='Reconciliation', required=True, + reconciliation = fields.Many2One( + string='Reconciliation', required=True, model_name='cashbook.recon', depends=['reconciliations'], states={ 'readonly': ~Bool(Eval('reconciliations')), }, domain=[('id', 'in', Eval('reconciliations', []))]) - reconciliations = fields.Function(fields.One2Many(string='Reconciliations', + reconciliations = fields.Function(fields.One2Many( + string='Reconciliations', model_name='cashbook.recon', field=None, readonly=True, states={'invisible': True}), 'on_change_with_reconciliations') @@ -38,9 +41,9 @@ class RunCbReportStart(ModelView): self.reconciliations = self.on_change_with_reconciliations() if len(self.reconciliations or []) > 0: self.reconciliation = self.reconciliations[0] - else : + else: self.reconciliation = None - else : + else: self.reconciliations = [] self.reconciliation = None @@ -64,14 +67,14 @@ class RunCbReport(Wizard): __name__ = 'cashbook.runrepbook' start_state = 'selrecon' - selrecon = StateView('cashbook.runrepbook.start', + selrecon = StateView( + 'cashbook.runrepbook.start', 'cashbook.runrepbook_view_form', [ Button(string='Cancel', state='end', icon='tryton-cancel'), - Button(string='Report', state='report_', icon='tryton-ok', default=True, - states={ - 'readonly': ~Bool(Eval('reconciliation')), - }), - ]) + Button( + string='Report', state='report_', icon='tryton-ok', + default=True, + states={'readonly': ~Bool(Eval('reconciliation'))})]) report_ = StateReport('cashbook.reprecon') def default_selrecon(self, fields): @@ -87,12 +90,11 @@ class RunCbReport(Wizard): result['cashbook'] = context.get('active_id', None) elif context.get('active_model', '') == 'cashbook.line': result['cashbook'] = context.get('cashbook', None) - else : + else: raise ValueError('invalid model') with Transaction().set_context({ - '_check_access': True, - }): + '_check_access': True}): books = Book.search([]) result['cashbooks'] = [x.id for x in books] @@ -118,7 +120,7 @@ class RunCbReport(Wizard): 'id': self.selrecon.reconciliation.id, 'ids': [self.selrecon.reconciliation.id], } - else : + else: r1 = {'model': '', 'id': None, 'ids': []} return action, r1