formatting, line: test for delete of party

This commit is contained in:
Frederik Jaeckel 2023-05-18 12:15:53 +02:00
parent 78f160bf0b
commit 619a17bcd6
16 changed files with 701 additions and 516 deletions

209
book.py
View file

@ -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