formatting, line: test for delete of party
This commit is contained in:
parent
78f160bf0b
commit
619a17bcd6
16 changed files with 701 additions and 516 deletions
209
book.py
209
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue