Replace account move number by post number

Closes #13864
This commit is contained in:
Cédric Krier
2025-02-11 12:50:48 +01:00
parent 9bd8739978
commit 93b3d27117
22 changed files with 50 additions and 195 deletions
+1 -11
View File
@@ -14,24 +14,14 @@ def setup(config, modules, company):
Statement = Model.get('account.statement')
AccountJournal = Model.get('account.journal')
Account = Model.get('account.account')
Sequence = Model.get('ir.sequence')
SequenceType = Model.get('ir.sequence.type')
Invoice = Model.get('account.invoice')
sequence_type, = SequenceType.find([('name', '=', "Account Journal")])
sequence = Sequence(name='Statement',
sequence_type=sequence_type,
company=company)
sequence.save()
cash, = Account.find([
('company', '=', company.id),
('code', '=', '1.1.1'),
])
account_journal = AccountJournal(name='Bank',
type='statement',
sequence=sequence)
account_journal = AccountJournal(name='Bank', type='statement')
account_journal.save()
journal = Journal(name='Bank',
+2
View File
@@ -1,3 +1,5 @@
* Rename post number to number
* Remove number on move and its sequence on journal
Version 7.4.0 - 2024-11-04
--------------------------
-1
View File
@@ -47,7 +47,6 @@ def register():
configuration.Journal,
period.Period,
journal.Journal,
journal.JournalSequence,
journal.JournalCashContext,
journal.JournalPeriod,
move.Move,
+1 -2
View File
@@ -7,8 +7,7 @@ A *Journal* represents a book of original entry from traditional manual
accounting.
In Tryton it allows `Account Moves <model-account.move>` of the same class
to be grouped together.
Every account move gets associated with a journal, and the journal defines
what sequence is then used to number the account move.
Every account move gets associated with a journal.
Among the journal's properties is a type.
This limits where the journal can be used.
+2 -2
View File
@@ -515,7 +515,7 @@
<table:table-header-rows>
<table:table-row table:style-name="Table4.1">
<table:table-cell table:style-name="Table4.A1" office:value-type="string">
<text:p text:style-name="Table_20_Heading">Journal Entry:<text:line-break/><text:placeholder text:placeholder-type="text">&lt;move.number&gt;</text:placeholder></text:p>
<text:p text:style-name="Table_20_Heading">Journal Entry:<text:line-break/><text:placeholder text:placeholder-type="text">&lt;move.rec_name&gt;</text:placeholder></text:p>
</table:table-cell>
<table:table-cell table:style-name="Table4.C1" office:value-type="string">
<text:p text:style-name="Table_20_Heading">Date:<text:line-break/> <text:placeholder text:placeholder-type="text">&lt;format_date(move.date, user.language)&gt;</text:placeholder></text:p>
@@ -527,7 +527,7 @@
</table:table-cell>
<table:table-cell table:style-name="Table4.D1" table:number-columns-spanned="2" office:value-type="string">
<text:p text:style-name="Table_20_Heading"><text:placeholder text:placeholder-type="text">&lt;if test=&quot;move.state == &apos;posted&apos;&quot;&gt;</text:placeholder></text:p>
<text:p text:style-name="Table_20_Heading">Posted <text:placeholder text:placeholder-type="text">&lt;move.post_number&gt;</text:placeholder><text:line-break/><text:placeholder text:placeholder-type="text">&lt;format_date(move.post_date, user.language)&gt;</text:placeholder></text:p>
<text:p text:style-name="Table_20_Heading">Posted<text:line-break/><text:placeholder text:placeholder-type="text">&lt;format_date(move.post_date, user.language)&gt;</text:placeholder></text:p>
<text:p text:style-name="Table_20_Heading"><text:placeholder text:placeholder-type="text">&lt;/if&gt;</text:placeholder></text:p>
<text:p text:style-name="Table_20_Heading"><text:placeholder text:placeholder-type="text">&lt;if test=&quot;move.state == &apos;draft&apos;&quot;&gt;</text:placeholder></text:p>
<text:p text:style-name="Table_20_Heading">Draft</text:p>
+2 -48
View File
@@ -9,11 +9,9 @@ from trytond.model import (
DeactivableMixin, MatchMixin, ModelSQL, ModelView, Unique, Workflow,
fields, sequence_ordered)
from trytond.model.exceptions import AccessError
from trytond.modules.company.model import (
CompanyMultiValueMixin, CompanyValueMixin)
from trytond.modules.currency.fields import Monetary
from trytond.pool import Pool
from trytond.pyson import Bool, Eval, Id
from trytond.pyson import Eval
from trytond.tools import (
grouped_slice, is_full_text, lstrip_wildcard, reduce_ids,
sqlite_apply_types)
@@ -27,7 +25,7 @@ STATES = {
class Journal(
DeactivableMixin, MatchMixin,
sequence_ordered('matching_sequence', "Matching Sequence"),
ModelSQL, ModelView, CompanyMultiValueMixin):
ModelSQL, ModelView):
__name__ = 'account.journal'
name = fields.Char('Name', size=None, required=True, translate=True)
code = fields.Char('Code', size=None)
@@ -39,19 +37,6 @@ class Journal(
('situation', "Situation"),
('write-off', "Write-Off"),
], 'Type', required=True)
sequence = fields.MultiValue(fields.Many2One(
'ir.sequence', "Sequence",
domain=[
('sequence_type', '=',
Id('account', 'sequence_type_account_journal')),
('company', 'in', [
Eval('context', {}).get('company', -1), None]),
],
states={
'required': Bool(Eval('context', {}).get('company', -1)),
}))
sequences = fields.One2Many(
'account.journal.sequence', 'journal', "Sequences")
debit = fields.Function(Monetary(
"Debit", currency='currency', digits='currency'),
'get_debit_credit_balance')
@@ -70,10 +55,6 @@ class Journal(
super(Journal, cls).__setup__()
cls._order.insert(0, ('name', 'ASC'))
@classmethod
def default_sequence(cls, **pattern):
return cls.multivalue_model('sequence').default_sequence()
@classmethod
def search_rec_name(cls, name, clause):
_, operator, operand, *extra = clause
@@ -185,33 +166,6 @@ class Journal(
super().write(*args)
class JournalSequence(ModelSQL, CompanyValueMixin):
__name__ = 'account.journal.sequence'
journal = fields.Many2One(
'account.journal', "Journal", ondelete='CASCADE',
context={
'company': Eval('company', -1),
},
depends={'company'})
sequence = fields.Many2One(
'ir.sequence', "Sequence",
domain=[
('sequence_type', '=',
Id('account', 'sequence_type_account_journal')),
('company', 'in', [Eval('company', -1), None]),
],
depends={'company'})
@classmethod
def default_sequence(cls):
pool = Pool()
ModelData = pool.get('ir.model.data')
try:
return ModelData.get_id('account', 'sequence_account_journal')
except KeyError:
return None
class JournalCashContext(ModelView):
__name__ = 'account.journal.open_cash.context'
start_date = fields.Date('Start Date', required=True)
-19
View File
@@ -95,25 +95,6 @@ this repository contains the full copyright notices and license terms. -->
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<record model="ir.sequence.type" id="sequence_type_account_journal">
<field name="name">Account Journal</field>
</record>
<record model="ir.sequence.type-res.group"
id="sequence_type_account_journal_group_admin">
<field name="sequence_type" ref="sequence_type_account_journal"/>
<field name="group" ref="res.group_admin"/>
</record>
<record model="ir.sequence.type-res.group"
id="sequence_type_account_journal_group_account_admin">
<field name="sequence_type" ref="sequence_type_account_journal"/>
<field name="group" ref="group_account_admin"/>
</record>
<record model="ir.sequence" id="sequence_account_journal">
<field name="name">Default Account Journal</field>
<field name="sequence_type" ref="sequence_type_account_journal"/>
<field name="company" eval="None"/>
</record>
<record model="ir.ui.view" id="journal_period_view_form">
<field name="model">account.journal.period</field>
+19 -48
View File
@@ -85,8 +85,8 @@ class DescriptionOriginMixin:
class Move(DescriptionOriginMixin, ModelSQL, ModelView):
__name__ = 'account.move'
_rec_name = 'number'
number = fields.Char('Number', required=True, readonly=True)
post_number = fields.Char('Post Number', readonly=True,
number = fields.Char(
"Number", readonly=True,
help='Also known as Folio Number.')
company = fields.Many2One('company.company', 'Company', required=True,
states=_MOVE_STATES)
@@ -103,10 +103,8 @@ class Move(DescriptionOriginMixin, ModelSQL, ModelView):
[]),
],
states=_MOVE_STATES)
journal = fields.Many2One('account.journal', 'Journal', required=True,
states={
'readonly': Eval('number') & Eval('journal', None),
},
journal = fields.Many2One(
'account.journal', "Journal", required=True, states=_MOVE_STATES,
context={
'company': Eval('company', -1),
},
@@ -131,7 +129,6 @@ class Move(DescriptionOriginMixin, ModelSQL, ModelView):
@classmethod
def __setup__(cls):
cls.number.search_unaccented = False
cls.post_number.search_unaccented = False
super(Move, cls).__setup__()
t = cls.__table__()
cls.create_date.select = True
@@ -157,16 +154,20 @@ class Move(DescriptionOriginMixin, ModelSQL, ModelView):
(t.period, Index.Range())),
})
@classmethod
def __register__(cls, module):
table_h = cls.__table_handler__(module)
if (table_h.column_exist('number')
and table_h.column_exist('post_number')):
table_h.drop_column('number')
table_h.column_rename('post_number', 'number')
super().__register__(module)
@classmethod
def order_number(cls, tables):
table, _ = tables[None]
return [CharLength(table.number), table.number]
@classmethod
def order_post_number(cls, tables):
table, _ = tables[None]
return [CharLength(table.post_number), table.post_number]
@staticmethod
def default_company():
return Transaction().context.get('company')
@@ -276,16 +277,11 @@ class Move(DescriptionOriginMixin, ModelSQL, ModelView):
gettext('account.msg_modify_posted_moved',
move=move.rec_name))
@classmethod
def search_rec_name(cls, name, clause):
if clause[1].startswith('!') or clause[1].startswith('not '):
bool_op = 'AND'
def get_rec_name(self, name):
if self.number:
return self.number
else:
bool_op = 'OR'
return [bool_op,
('post_number',) + tuple(clause[1:]),
(cls._rec_name,) + tuple(clause[1:]),
]
return f'({self.id})'
@classmethod
def write(cls, *args):
@@ -301,30 +297,6 @@ class Move(DescriptionOriginMixin, ModelSQL, ModelView):
args.extend((moves, values))
super(Move, cls).write(*args)
@classmethod
def create(cls, vlist):
pool = Pool()
Journal = pool.get('account.journal')
context = Transaction().context
default_company = cls.default_company()
vlist = [x.copy() for x in vlist]
missing_number = defaultdict(list)
for vals in vlist:
if not vals.get('number'):
journal_id = vals.get('journal', context.get('journal'))
company_id = vals.get('company', default_company)
if journal_id:
missing_number[(journal_id, company_id)].append(vals)
for (journal_id, company_id), values in missing_number.items():
journal = Journal(journal_id)
sequence = journal.get_multivalue('sequence', company=company_id)
with Transaction().set_context(company=company_id):
for vals, number in zip(
values, sequence.get_many(len(values))):
vals['number'] = number
return super().create(vlist)
@classmethod
def delete(cls, moves):
MoveLine = Pool().get('account.move.line')
@@ -374,7 +346,6 @@ class Move(DescriptionOriginMixin, ModelSQL, ModelView):
return origin['date']
default.setdefault('number', None)
default.setdefault('post_number', None)
default.setdefault('state', cls.default_state())
default.setdefault('post_date', None)
default.setdefault('period', default_period)
@@ -539,7 +510,7 @@ class Move(DescriptionOriginMixin, ModelSQL, ModelView):
missing_number = defaultdict(list)
for move in c_moves:
move.state = 'posted'
if not move.post_number:
if not move.number:
move.post_date = today
missing_number[move.period.post_move_sequence_used].append(
move)
@@ -547,7 +518,7 @@ class Move(DescriptionOriginMixin, ModelSQL, ModelView):
for sequence, m_moves in missing_number.items():
for move, number in zip(
m_moves, sequence.get_many(len(m_moves))):
move.post_number = number
move.number = number
cls.save(moves)
@@ -84,11 +84,7 @@ Create Moves to reconcile::
Create a write off method::
>>> Sequence = Model.get('ir.sequence')
>>> sequence_journal, = Sequence.find(
... [('sequence_type.name', '=', "Account Journal")], limit=1)
>>> journal_writeoff = Journal(name='Write-Off', type='write-off',
... sequence=sequence_journal)
>>> journal_writeoff = Journal(name='Write-Off', type='write-off')
>>> journal_writeoff.save()
>>> WriteOff = Model.get('account.move.reconcile.write_off')
>>> writeoff_method = WriteOff()
@@ -154,11 +154,7 @@ Create Moves for writeoff reconciliation::
Create a write-off payment method::
>>> Sequence = Model.get('ir.sequence')
>>> sequence_journal, = Sequence.find(
... [('sequence_type.name', '=', "Account Journal")], limit=1)
>>> journal_writeoff = Journal(name='Write-Off', type='write-off',
... sequence=sequence_journal)
>>> journal_writeoff = Journal(name='Write-Off', type='write-off')
>>> journal_writeoff.save()
>>> WriteOff = Model.get('account.move.reconcile.write_off')
>>> writeoff_method = WriteOff()
@@ -43,14 +43,10 @@ Get accounts::
Prepare the closing settings for fiscalyear close::
>>> journal_sequence, = Sequence.find([
... ('sequence_type.name', '=', "Account Journal"),
... ], limit=1)
>>> journal_closing = Journal()
>>> journal_closing.name = 'Closing'
>>> journal_closing.code = 'CLO'
>>> journal_closing.type = 'situation'
>>> journal_closing.sequence = journal_sequence
>>> journal_closing.save()
>>> period_closing = Period()
>>> period_closing.name = 'Closing'
+3 -6
View File
@@ -10,8 +10,7 @@ Imports::
>>> from trytond.modules.account.tests.tools import (
... create_chart, create_fiscalyear, get_accounts)
>>> from trytond.modules.company.tests.tools import create_company
>>> from trytond.tests.tools import (
... activate_modules, assertEqual, assertNotEqual, assertTrue)
>>> from trytond.tests.tools import activate_modules, assertEqual, assertNotEqual
Activate modules::
@@ -57,8 +56,7 @@ Create a posted move::
Copy move on open period::
>>> copy_move, = move.duplicate()
>>> assertTrue(copy_move.number)
>>> copy_move.post_number
>>> copy_move.number
>>> copy_move.state
'draft'
>>> copy_move.post_date
@@ -79,8 +77,7 @@ Copy move on closed period::
>>> config.skip_warning = True
>>> copy_move, = move.duplicate()
>>> assertTrue(copy_move.number)
>>> copy_move.post_number
>>> copy_move.number
>>> copy_move.state
'draft'
>>> copy_move.post_date
-5
View File
@@ -120,7 +120,6 @@ def get_fiscalyear(company, today=None, start_date=None, end_date=None):
def close_fiscalyear(fiscalyear):
pool = Pool()
Sequence = pool.get('ir.sequence')
Journal = pool.get('account.journal')
Period = pool.get('account.period')
Account = pool.get('account.account')
@@ -130,14 +129,10 @@ def close_fiscalyear(fiscalyear):
'account.fiscalyear.balance_non_deferral', type='wizard')
# Balance non-deferral
journal_sequence, = Sequence.search([
('sequence_type.name', '=', "Account Journal"),
], limit=1)
journal_closing, = Journal.create([{
'name': 'Closing',
'code': 'CLO',
'type': 'situation',
'sequence': journal_sequence.id,
}])
period_closing, = Period.create([{
'name': 'Closing',
+7 -8
View File
@@ -4,16 +4,15 @@ this repository contains the full copyright notices and license terms. -->
<form>
<label name="name"/>
<field name="name"/>
<label name="active"/>
<field name="active" xexpand="0" width="100"/>
<label name="code"/>
<field name="code"/>
<label name="matching_sequence"/>
<field name="matching_sequence"/>
<group col="-1" id="code_active">
<field name="code"/>
<label name="active"/>
<field name="active" xexpand="0" width="25"/>
</group>
<label name="type"/>
<field name="type"/>
<label name="sequence"/>
<field name="sequence"/>
<label name="matching_sequence"/>
<field name="matching_sequence"/>
</form>
+1 -3
View File
@@ -4,11 +4,9 @@ this repository contains the full copyright notices and license terms. -->
<form cursor="journal">
<label name="company"/>
<field name="company"/>
<newline/>
<label name="number"/>
<field name="number"/>
<label name="post_number"/>
<field name="post_number"/>
<label name="journal"/>
<field name="journal" widget="selection"/>
<label name="period"/>
-1
View File
@@ -4,7 +4,6 @@ this repository contains the full copyright notices and license terms. -->
<tree>
<field name="company" optional="1"/>
<field name="number" optional="0"/>
<field name="post_number" optional="1"/>
<field name="journal" optional="0"/>
<field name="period" optional="1"/>
<field name="date"/>
+1 -1
View File
@@ -132,7 +132,7 @@ class Move(metaclass=PoolMeta):
if isinstance(self.origin, Invoice):
number = self.origin.number
else:
number = self.post_number
number = self.number
return re.sub(r'[^0-9]', '', number)
+2 -2
View File
@@ -250,7 +250,7 @@ class FrFEC(Wizard):
domain,
order=[
('move.post_date', 'ASC'),
('move.post_number', 'ASC'),
('move.number', 'ASC'),
('id', 'ASC'),
])
@@ -269,7 +269,7 @@ class FrFEC(Wizard):
return [
line.move.journal.code or line.move.journal.name,
line.move.journal.name,
line.move.post_number,
line.move.number,
format_date(line.move.date),
line.account.code,
line.account.name,
+4 -8
View File
@@ -79,7 +79,7 @@ Create some moves::
>>> move.save()
>>> Move.write([move.id], {
... 'post_date': period_previous.start_date,
... 'post_number': '1',
... 'number': '1',
... }, config.context)
>>> move.click('post')
@@ -102,7 +102,7 @@ With an empty line::
>>> move.save()
>>> Move.write([move.id], {
... 'post_date': period.start_date,
... 'post_number': '1',
... 'number': '1',
... }, config.context)
>>> move.click('post')
@@ -123,7 +123,7 @@ With reconciliation::
>>> reconcile1, = [l for l in move.lines if l.account == receivable]
>>> Move.write([move.id], {
... 'post_date': period.start_date,
... 'post_number': '2',
... 'number': '2',
... }, config.context)
>>> move.click('post')
>>> move = Move()
@@ -140,7 +140,7 @@ With reconciliation::
>>> move.save()
>>> Move.write([move.id], {
... 'post_date': period.start_date,
... 'post_number': '3',
... 'number': '3',
... }, config.context)
>>> move.click('post')
>>> reconcile2, = [l for l in move.lines if l.account == receivable]
@@ -152,14 +152,10 @@ With reconciliation::
Balance non-deferral::
>>> Sequence = Model.get('ir.sequence')
>>> Period = Model.get('account.period')
>>> Account = Model.get('account.account')
>>> journal_closing = Journal(name="Closing", code="CLO", type='situation')
>>> journal_closing.sequence, = Sequence.find([
... ('name', '=', "Default Account Journal"),
... ])
>>> journal_closing.save()
>>> period_closing = Period(name="Closing")
@@ -64,7 +64,6 @@ Create payment method::
>>> Journal = Model.get('account.journal')
>>> PaymentMethod = Model.get('account.invoice.payment.method')
>>> Sequence = Model.get('ir.sequence')
>>> journal_cash, = Journal.find([('type', '=', 'cash')])
>>> payment_method = PaymentMethod()
>>> payment_method.name = 'Cash'
@@ -76,10 +75,7 @@ Create payment method::
Create writeoff method::
>>> WriteOff = Model.get('account.move.reconcile.write_off')
>>> sequence_journal, = Sequence.find(
... [('sequence_type.name', '=', "Account Journal")])
>>> journal_writeoff = Journal(name='Write-Off', type='write-off',
... sequence=sequence_journal)
>>> journal_writeoff = Journal(name='Write-Off', type='write-off')
>>> journal_writeoff.save()
>>> writeoff = WriteOff()
>>> writeoff.name = 'Rate loss'
@@ -32,7 +32,6 @@ Create payment method::
>>> Journal = Model.get('account.journal')
>>> PaymentMethod = Model.get('account.invoice.payment.method')
>>> Sequence = Model.get('ir.sequence')
>>> journal_cash, = Journal.find([('type', '=', 'cash')])
>>> payment_method = PaymentMethod()
>>> payment_method.name = 'Cash'
@@ -44,10 +43,7 @@ Create payment method::
Create write-off method::
>>> WriteOff = Model.get('account.move.reconcile.write_off')
>>> sequence_journal, = Sequence.find(
... [('sequence_type.name', '=', "Account Journal")], limit=1)
>>> journal_writeoff = Journal(
... name='Write-Off', type='write-off', sequence=sequence_journal)
>>> journal_writeoff = Journal(name='Write-Off', type='write-off')
>>> journal_writeoff.save()
>>> writeoff = WriteOff()
>>> writeoff.name = 'Write-off'
@@ -164,18 +164,13 @@ Check analytic lines are created on posting::
Prepare to balance non-deferral accounts::
>>> Sequence = Model.get('ir.sequence')
>>> Period = Model.get('account.period')
>>> AccountType = Model.get('account.account.type')
>>> Account = Model.get('account.account')
>>> journal_sequence, = Sequence.find([
... ('name', '=', "Default Account Journal"),
... ])
>>> journal_closing = Journal()
>>> journal_closing.code = 'CLO'
>>> journal_closing.type = 'situation'
>>> journal_closing.name = "Closing"
>>> journal_closing.sequence = journal_sequence
>>> journal_closing.save()
>>> period_closing = Period()
>>> period_closing.name = "Closing"