Replace open journal wizard by a context model

Closes #14937
This commit is contained in:
Cédric Krier
2026-07-07 19:06:14 +02:00
parent 138e95f7d8
commit a96cb0a84f
11 changed files with 137 additions and 178 deletions
+1
View File
@@ -1,3 +1,4 @@
* Replace open journal wizard by a context model
* Use also maturity date to calculate reconciliation date
Version 8.0.0 - 2026-04-20
+9
View File
@@ -83,6 +83,15 @@ These facts help ensure the integrity of the
`Company's <company:model-company.company>` accounts and the accounting reports
generated by Tryton.
.. seealso::
Account move lines can be found by opening the main menu item:
|Financial --> Entries --> Lines|__
.. |Financial --> Entries --> Lines| replace:: :menuselection:`Financial --> Entries --> Lines`
__ https://demo.tryton.org/model/account.move.line
Wizards
-------
+2 -2
View File
@@ -36,8 +36,8 @@ One-off entries
For entries that are only needed once, for example to set an account's
initial opening balance, you can manually create an *Account Move*.
The [:menuselection:`Financial --> Entries --> Open Journal`] main menu item
provides another way of entering the details of an account move.
The [:menuselection:`Financial --> Entries --> Lines`] main menu item provides
another way of entering the details of an account move.
It provides a list of individual
`Account Move Lines <model-account.move.line>`, which can be added to as
required.
+1 -38
View File
@@ -112,45 +112,8 @@ this repository contains the full copyright notices and license terms. -->
<field name="name">journal_period_list_close</field>
</record>
<record model="ir.action.act_window" id="act_journal_period_tree">
<field name="name">Journals - Periods</field>
<field name="res_model">account.journal.period</field>
<!-- Migration from 7.4: force empty domain for multi company -->
<field name="domain" eval="None"/>
</record>
<record model="ir.action.act_window.view" id="act_journal_period_tree_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="journal_period_view_tree"/>
<field name="act_window" ref="act_journal_period_tree"/>
</record>
<menuitem
parent="menu_reporting"
action="act_journal_period_tree"
sequence="50"
id="menu_journal_period_tree"/>
<record model="ir.action.act_window" id="act_journal_period_tree2">
<field name="name">Journals - Periods</field>
<field name="res_model">account.journal.period</field>
<!-- Migration from 7.4: force empty domain for multi company -->
<field name="domain" eval="None"/>
<field name="search_value"
eval="[('state', '=', 'open')]"
pyson="1"/>
</record>
<record model="ir.action.act_window.view" id="act_journal_period_tree2_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="journal_period_view_tree"/>
<field name="act_window" ref="act_journal_period_tree2"/>
</record>
<menuitem
parent="menu_entries"
action="act_journal_period_tree2"
sequence="20"
id="menu_journal_period_tree2"/>
<record model="ir.action.act_window" id="act_journal_period_form_close">
<field name="name">Close Journals - Periods</field>
<field name="name">Journals - Periods</field>
<field name="res_model">account.journal.period</field>
<field name="search_value"
eval="[('state', '=', 'open')]" pyson="1"/>
+60 -113
View File
@@ -1123,35 +1123,43 @@ class Line(DescriptionOriginMixin, MoveLineMixin, ModelSQL, ModelView):
where=table.reconciliation == Null),
})
@classmethod
def _last_move_line(cls):
"Last move line created by the current user"
transaction = Transaction()
context = transaction.context
domain = [
('company', '=', context.get('company')),
('create_uid', '=', transaction.user),
('state', '=', 'draft'),
]
if context.get('journal') is not None:
domain.append(('move.journal', '=', context['journal']))
if context.get('period') is not None:
domain.append(('move.period', '=', context['period']))
lines = cls.search(domain, order=[('id', 'DESC')], limit=1)
if lines:
line, = lines
return line
@classmethod
def default_date(cls):
'''
Return the date of the last line for journal, period
or the starting date of the period
or today
'''
pool = Pool()
Period = pool.get('account.period')
Date = pool.get('ir.date')
context = Transaction().context
date = Date.today()
lines = cls.search([
('company', '=', context.get('company')),
('journal', '=', context.get('journal')),
('period', '=', context.get('period')),
],
order=[('date', 'DESC')], limit=1)
if lines:
line, = lines
if (context.get('default_last_move_line')
and (line := cls._last_move_line())):
date = line.date
elif context.get('period'):
elif context.get('period') is not None:
period = Period(context['period'])
if period.start_date >= date:
date = period.start_date
else:
date = period.end_date
if context.get('date'):
elif context.get('date'):
date = context['date']
return date
@@ -1159,21 +1167,15 @@ class Line(DescriptionOriginMixin, MoveLineMixin, ModelSQL, ModelView):
def default_move(cls):
transaction = Transaction()
context = transaction.context
if context.get('journal') and context.get('period'):
lines = cls.search([
('company', '=', context.get('company')),
('move.journal', '=', context['journal']),
('move.period', '=', context['period']),
('create_uid', '=', transaction.user),
('state', '=', 'draft'),
], order=[('id', 'DESC')], limit=1)
if lines:
line, = lines
return line.move.id
if context.get('default_last_move_line'):
if line := cls._last_move_line():
return line.move
@fields.depends(
'move', 'debit', 'credit',
'_parent_move.lines', '_parent_move.company')
'company', 'period', 'journal',
'_parent_move.lines',
'_parent_move.company', '_parent_move.period', '_parent_move.journal')
def on_change_move(self):
if self.move:
if not self.debit and not self.credit:
@@ -1182,11 +1184,21 @@ class Line(DescriptionOriginMixin, MoveLineMixin, ModelSQL, ModelView):
self.debit = -total if total < 0 else Decimal(0)
self.credit = total if total > 0 else Decimal(0)
self.company = self.move.company
self.period = self.move.period
self.journal = self.move.journal
@classmethod
def default_company(cls):
return Transaction().context.get('company')
@classmethod
def default_journal(cls):
return Transaction().context.get('journal')
@classmethod
def default_period(cls):
return Transaction().context.get('period')
@staticmethod
def default_state():
return 'draft'
@@ -1502,6 +1514,10 @@ class Line(DescriptionOriginMixin, MoveLineMixin, ModelSQL, ModelView):
attributes.append(
('/tree', 'visual',
If(Bool(Eval('reconciliation')), 'muted', '')))
else:
attributes.append(
('/tree', 'visual',
If(Eval('state') != 'valid', 'muted', '')))
return attributes
@classmethod
@@ -1565,13 +1581,10 @@ class Line(DescriptionOriginMixin, MoveLineMixin, ModelSQL, ModelView):
# Add a wizard entry for each templates
context = Transaction().context
company = context.get('company')
journal = context.get('journal')
period = context.get('period')
if company and journal and period:
if context.get('default_last_move_line'):
templates = Template.search([
('company', '=', company),
('journal', '=', journal),
('company', '=', context.get('company')),
('journal', '=', context.get('journal')),
])
toolbar = dict(toolbar)
action = list(toolbar['action'])
@@ -1959,15 +1972,16 @@ class WriteOff(DeactivableMixin, ModelSQL, ModelView):
return Transaction().context.get('company')
class OpenJournalAsk(ModelView):
__name__ = 'account.move.open_journal.ask'
class LineContext(ModelView):
__name__ = 'account.move.line.context'
company = fields.Many2One('company.company', "Company", required=True)
journal = fields.Many2One(
'account.journal', 'Journal', required=True,
'account.journal', "Journal",
context={
'company': Eval('company', None),
})
period = fields.Many2One('account.period', 'Period', required=True,
period = fields.Many2One(
'account.period', "Period",
domain=[
('company', '=', Eval('company', -1)),
('state', '!=', 'closed'),
@@ -1977,88 +1991,21 @@ class OpenJournalAsk(ModelView):
def default_company(cls):
return Transaction().context.get('company')
@classmethod
def default_journal(cls):
return Transaction().context.get('journal')
@classmethod
def default_period(cls):
pool = Pool()
Period = pool.get('account.period')
if company := cls.default_company():
if period := Transaction().context.get('period'):
return period
elif company := cls.default_company():
try:
period = Period.find(company)
return Period.find(company)
except PeriodNotFoundError:
return None
return period.id
class OpenJournal(Wizard):
__name__ = 'account.move.open_journal'
_readonly = True
start = StateTransition()
ask = StateView('account.move.open_journal.ask',
'account.open_journal_ask_view_form', [
Button('Cancel', 'end', 'tryton-cancel'),
Button('Open', 'open_', 'tryton-ok', default=True),
])
open_ = StateAction('account.act_move_line_form')
def transition_start(self):
if (self.model
and self.model.__name__ == 'account.journal.period'
and self.record):
return 'open_'
return 'ask'
def default_ask(self, fields):
if (self.model
and self.model.__name__ == 'account.journal.period'
and self.record):
return {
'company': self.record.company.id,
'journal': self.record.journal.id,
'period': self.record.period.id,
}
return {}
def do_open_(self, action):
JournalPeriod = Pool().get('account.journal.period')
if (self.model
and self.model.__name__ == 'account.journal.period'
and self.record):
journal = self.record.journal
period = self.record.period
else:
journal = self.ask.journal
period = self.ask.period
journal_periods = JournalPeriod.search([
('journal', '=', journal.id),
('period', '=', period.id),
], limit=1)
if not journal_periods:
with Transaction().new_transaction():
journal_period, = JournalPeriod.create([{
'journal': journal.id,
'period': period.id,
}])
name = journal_period.rec_name
else:
journal_period, = journal_periods
name = journal_period.rec_name
action['name'] += ' (%s)' % name
action['pyson_domain'] = PYSONEncoder().encode([
('journal', '=', journal.id),
('period', '=', period.id),
('company', '=', period.company.id),
])
action['pyson_context'] = PYSONEncoder().encode({
'journal': journal.id,
'period': period.id,
'company': period.company.id,
})
return action, {}
def transition_open_(self):
return 'end'
pass
class OpenAccount(Wizard):
+35 -19
View File
@@ -191,6 +191,13 @@ this repository contains the full copyright notices and license terms. -->
<field name="name">move_line_tree</field>
</record>
<record model="ir.ui.view" id="move_line_view_list_editable">
<field name="model">account.move.line</field>
<field name="type">tree</field>
<field name="priority" eval="20"/>
<field name="name">move_line_list_editable</field>
</record>
<record model="ir.ui.view" id="move_line_view_tree_move">
<field name="model">account.move.line</field>
<field name="type">tree</field>
@@ -230,6 +237,31 @@ this repository contains the full copyright notices and license terms. -->
<field name="view" ref="move_line_view_form"/>
<field name="act_window" ref="act_move_line_form"/>
</record>
<record model="ir.action.act_window" id="act_move_line_form_editable">
<field name="name">Lines</field>
<field name="res_model">account.move.line</field>
<field name="context_model">account.move.line.context</field>
<field name="context_domain" eval="[('company', '=', Eval('company', -1)), If(Eval('journal', None) != None, ('journal', '=', Eval('journal', -1)), ()), If(Eval('period', None) != None, ('period', '=', Eval('period', -1)), ())]" pyson="1"/>
<field name="context" eval="{'default_last_move_line': True}" pyson="1"/>
</record>
<record model="ir.action.act_window.view" id="act_move_line_form_editable_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="move_line_view_list_editable"/>
<field name="act_window" ref="act_move_line_form_editable"/>
</record>
<record model="ir.action.act_window.view" id="act_move_line_form_editable_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="move_line_view_form"/>
<field name="act_window" ref="act_move_line_form_editable"/>
</record>
<menuitem
parent="menu_entries"
action="act_move_line_form_editable"
sequence="30"
id="menu_move_line_form_editable"/>
<record model="ir.action.wizard" id="act_open_account">
<field name="name">Open Move Account</field>
<field name="wiz_name">account.move.open_account</field>
@@ -282,28 +314,12 @@ this repository contains the full copyright notices and license terms. -->
<field name="name">move_line_receivable_payable_context_form</field>
</record>
<record model="ir.ui.view" id="open_journal_ask_view_form">
<field name="model">account.move.open_journal.ask</field>
<record model="ir.ui.view" id="move_line_context_view_form">
<field name="model">account.move.line.context</field>
<field name="type">form</field>
<field name="name">open_journal_ask_form</field>
<field name="name">move_line_context_form</field>
</record>
<record model="ir.action.wizard" id="act_open_journal">
<field name="name">Open Journal</field>
<field name="wiz_name">account.move.open_journal</field>
</record>
<record model="ir.action.keyword" id="act_open_journal_keyword">
<field name="keyword">tree_open</field>
<field name="model">account.journal.period,-1</field>
<field name="action" ref="act_open_journal"/>
</record>
<menuitem
parent="menu_entries"
action="act_open_journal"
sequence="20"
id="menu_open_journal"
icon="tryton-list"/>
<record model="ir.ui.view" id="reconcile_lines_writeoff_view_form">
<field name="model">account.move.reconcile_lines.writeoff</field>
<field name="type">form</field>
+1 -2
View File
@@ -69,7 +69,7 @@ model:
move.Line
move.LineReceivablePayableContext
move.WriteOff
move.OpenJournalAsk
move.LineContext
move.ReconcileLinesWriteOff
move.ReconcileStart
move.ReconcileShow
@@ -110,7 +110,6 @@ wizard:
account.CreateChart
account.UpdateChart
account.OpenGeneralLedgerAccountParty
move.OpenJournal
move.OpenAccount
move.ReconcileLines
move.UnreconcileLines
@@ -1,12 +1,11 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form cursor="journal">
<form col="6">
<label name="company"/>
<field name="company"/>
<label name="period"/>
<field name="period"/>
<label name="journal"/>
<field name="journal" widget="selection"/>
</form>
@@ -0,0 +1,24 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tree editable="1" on_write="on_written">
<field name="period" optional="1"/>
<field name="journal" optional="0"/>
<field name="date"/>
<field name="account" expand="1"/>
<field name="party" expand="1"/>
<field name="debit" sum="1"/>
<field name="credit" sum="1"/>
<field name="amount_second_currency" symbol="" optional="1"/>
<field name="second_currency" optional="1"/>
<field name="delegated_amount" optional="1"/>
<field name="tax_lines" optional="1"/>
<field name="move_description_used" expand="1" optional="1"/>
<field name="description_used" expand="1" optional="1"/>
<field name="reconciliation" optional="1"/>
<field name="origin" expand="1" optional="1"/>
<field name="move"/>
<field name="move_origin" expand="1" optional="1"/>
<field name="move_state" optional="0"/>
<field name="state" tree_invisible="1"/>
</tree>
+2 -2
View File
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tree editable="1" on_write="on_written">
<tree>
<field name="company" expand="1" optional="1"/>
<field name="move"/>
<field name="move_origin" expand="1" optional="1"/>
@@ -18,6 +18,6 @@ this repository contains the full copyright notices and license terms. -->
<field name="move_description_used" expand="1" optional="1"/>
<field name="description_used" expand="1" optional="1"/>
<field name="reconciliation" optional="1"/>
<field name="state"/>
<field name="move_state" optional="0"/>
<field name="state" tree_invisible="1"/>
</tree>
@@ -12,4 +12,5 @@ this repository contains the full copyright notices and license terms. -->
<field name="tax_lines" optional="1"/>
<field name="description_used" expand="1" optional="1"/>
<field name="reconciliation" optional="1"/>
<field name="state" tree_invisible="1"/>
</tree>