Create Move by grouped lines

Create one move per lines having the same number, date and party.
Use the statement as origin of the move instead of the line.

issue4386
review7771002
This commit is contained in:
Cédric Krier committed 2015-01-02 15:43:29 +01:00
1 parent a8f37a27ab
commit 3ade6fb133
4 files changed
+181 -84

No files matched your search

+2
View File
@@ -1,3 +1,5 @@
* Create Move by grouped lines (number, date, party)
Version 3.4.0 - 2014-10-20
* Bug fixes (see mercurial logs for details)
* Add different validation type on journal
+37 -2
View File
@@ -1,6 +1,13 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.pool import PoolMeta
from itertools import groupby
from operator import itemgetter
from sql.operators import Concat
from trytond.pool import PoolMeta, Pool
from trytond.transaction import Transaction
from trytond.tools import grouped_slice, reduce_ids
__all__ = ['Move']
__metaclass__ = PoolMeta
@@ -9,6 +16,34 @@ __metaclass__ = PoolMeta
class Move:
__name__ = 'account.move'
@classmethod
def __register__(cls, module_name):
pool = Pool()
StatementLine = pool.get('account.statement.line')
cursor = Transaction().cursor
sql_table = cls.__table__()
super(Move, cls).__register__(module_name)
# Migration from 3.4:
# account.statement.line origin changed to account.statement
statement_line = StatementLine.__table__()
cursor.execute(*sql_table.join(statement_line,
condition=(
Concat(StatementLine.__name__ + ',', statement_line.id)
== sql_table.origin
)
).select(sql_table.id, statement_line.statement,
order_by=(sql_table.id, statement_line.statement)))
for statement_id, values in groupby(cursor.fetchall(), itemgetter(1)):
ids = [x[0] for x in values]
for sub_ids in grouped_slice(ids):
red_sql = reduce_ids(sql_table.id, sub_ids)
cursor.execute(*sql_table.update(
columns=[sql_table.origin],
values=['account.statement,%s' % statement_id],
where=red_sql))
@classmethod
def _get_origin(cls):
return super(Move, cls)._get_origin() + ['account.statement.line']
return super(Move, cls)._get_origin() + ['account.statement']
+119 -81
View File
@@ -119,6 +119,8 @@ class Statement(Workflow, ModelSQL, ModelView):
'deletion.'),
'paid_invoice_draft_statement': ('There are paid invoices on '
'draft statements.'),
'debit_credit_account_statement_journal': ('Please provide '
'debit and credit account on statement journal "%s".'),
})
cls._transitions |= set((
('draft', 'validated'),
@@ -383,8 +385,9 @@ class Statement(Workflow, ModelSQL, ModelView):
for statement in statements:
getattr(statement, 'validate_%s' % statement.validation)()
for line in statement.lines:
line.create_move()
cls.create_move(statements)
cls.write(statements, {
'state': 'validated',
})
@@ -399,6 +402,99 @@ class Statement(Workflow, ModelSQL, ModelView):
'invoice': None,
})
@classmethod
def create_move(cls, statements):
'Create move for the statements and try to reconcile the lines'
pool = Pool()
Line = pool.get('account.statement.line')
Move = pool.get('account.move')
MoveLine = pool.get('account.move.line')
moves = []
for statement in statements:
for key, lines in groupby(
statement.lines, key=statement._group_key):
lines = list(lines)
key = dict(key)
move = statement._get_move(key)
moves.append((move, statement, lines))
Move.save([m for m, _, _ in moves])
to_write = []
for move, _, lines in moves:
to_write.append(lines)
to_write.append({
'move': move.id,
})
Line.write(*to_write)
move_lines = []
for move, statement, lines in moves:
amount = 0
amount_second_currency = 0
for line in lines:
move_line = line.get_move_line()
move_line.move = move
amount += move_line.debit - move_line.credit
if move_line.amount_second_currency:
amount_second_currency += move_line.amount_second_currency
move_lines.append((move_line, line))
move_line = statement._get_move_line(
amount, amount_second_currency)
move_line.move = move
move_lines.append((move_line, None))
MoveLine.save([l for l, _ in move_lines])
for move_line, line in move_lines:
if line:
line.reconcile(move_line)
def _get_move(self, key):
'Return Move for the grouping key'
pool = Pool()
Move = pool.get('account.move')
Period = pool.get('account.period')
period_id = Period.find(self.company.id, date=key['date'])
return Move(
period=period_id,
journal=self.journal.journal,
date=key['date'],
origin=self,
company=self.company,
)
def _get_move_line(self, amount, amount_second_currency):
'Return counterpart Move Line for the amount'
pool = Pool()
MoveLine = pool.get('account.move.line')
if amount < 0:
account = self.journal.journal.debit_account
else:
account = self.journal.journal.credit_account
if not account:
self.raise_user_error('debit_credit_account_statement_journal',
(self.journal.rec_name,))
if self.journal.currency != self.company.currency:
second_currency = self.journal.currency
else:
second_currency = None
amount_second_currency = None
return MoveLine(
debit=abs(amount) if amount < 0 else 0,
credit=abs(amount) if amount > 0 else 0,
account=account,
second_currency=second_currency,
amount_second_currency=amount_second_currency,
)
@classmethod
@ModelView.button
@Workflow.transition('posted')
@@ -454,11 +550,6 @@ class Line(ModelSQL, ModelView):
super(Line, cls).__setup__()
cls._order.insert(0, ('sequence', 'ASC'))
cls._error_messages.update({
'debit_credit_account_statement_journal': ('Please provide '
'debit and credit account on statement journal "%s".'),
'same_debit_credit_account': ('Account "%(account)s" in '
'statement line "%(line)s" is the same as the one '
'configured as credit or debit on journal "%(journal)s".'),
'amount_greater_invoice_amount_to_pay': ('Amount "%s" is '
'greater than the amount to pay of invoice.'),
})
@@ -551,37 +642,12 @@ class Line(ModelSQL, ModelView):
default.setdefault('invoice', None)
return super(Line, cls).copy(lines, default=default)
def create_move(self):
'''
Create move for the statement line and return move if created.
'''
def reconcile(self, move_line):
pool = Pool()
Move = pool.get('account.move')
Period = pool.get('account.period')
Invoice = pool.get('account.invoice')
Currency = pool.get('currency.currency')
MoveLine = pool.get('account.move.line')
Lang = pool.get('ir.lang')
if self.move:
return
period_id = Period.find(self.statement.company.id, date=self.date)
move_lines = self._get_move_lines()
move = Move(
period=period_id,
journal=self.statement.journal.journal,
date=self.date,
origin=self,
company=self.statement.company,
lines=move_lines,
)
move.save()
self.write([self], {
'move': move.id,
})
Invoice = pool.get('account.invoice')
MoveLine = pool.get('account.move.line')
if self.invoice:
with Transaction().set_context(date=self.invoice.currency_date):
@@ -606,30 +672,28 @@ class Line(ModelSQL, ModelView):
reconcile_lines = self.invoice.get_reconcile_lines_for_amount(
amount)
for move_line in move.lines:
if move_line.account == self.invoice.account:
Invoice.write([self.invoice], {
'payment_lines': [('add', [move_line.id])],
})
break
assert move_line.account == self.invoice.account
Invoice.write([self.invoice], {
'payment_lines': [('add', [move_line.id])],
})
if reconcile_lines[1] == Decimal('0.0'):
lines = reconcile_lines[0] + [move_line]
MoveLine.reconcile(lines)
return move
@classmethod
def post_move(cls, lines):
Move = Pool().get('account.move')
Move.post([l.move for l in lines if l.move])
Move.post(list({l.move for l in lines if l.move}))
@classmethod
def delete_move(cls, lines):
Move = Pool().get('account.move')
Move.delete([l.move for l in lines if l.move])
Move.delete(list({l.move for l in lines if l.move}))
def _get_move_lines(self):
def get_move_line(self):
'''
Return the move lines for the statement line
Return the move line for the statement line
'''
pool = Pool()
MoveLine = pool.get('account.move.line')
@@ -645,41 +709,15 @@ class Line(ModelSQL, ModelView):
amount_second_currency = None
second_currency = None
move_lines = []
move_lines.append(MoveLine(
description=self.description,
debit=amount < zero and -amount or zero,
credit=amount >= zero and amount or zero,
account=self.account,
party=self.party if self.account.party_required else None,
second_currency=second_currency,
amount_second_currency=amount_second_currency,
))
journal = self.statement.journal.journal
if self.amount >= zero:
account = journal.debit_account
else:
account = journal.credit_account
if not account:
self.raise_user_error('debit_credit_account_statement_journal',
(journal.rec_name,))
if self.account == account:
self.raise_user_error('same_debit_credit_account', {
'account': self.account.rec_name,
'line': self.rec_name,
'journal': journal,
})
move_lines.append(MoveLine(
description=self.description,
debit=amount >= zero and amount or zero,
credit=amount < zero and -amount or zero,
account=account,
party=self.party if account.party_required else None,
second_currency=second_currency,
amount_second_currency=amount_second_currency,
))
return move_lines
return MoveLine(
description=self.description,
debit=amount < zero and -amount or zero,
credit=amount >= zero and amount or zero,
account=self.account,
party=self.party if self.account.party_required else None,
second_currency=second_currency,
amount_second_currency=amount_second_currency,
)
class StatementReport(CompanyReport):
+23 -1
View File
@@ -116,6 +116,28 @@ this repository contains the full copyright notices and license terms. -->
<field name="name">statement_line_tree_editable</field>
</record>
<record model="ir.action.act_window" id="act_statement_line_move">
<field name="name">Statement Lines</field>
<field name="res_model">account.statement.line</field>
<field name="domain">[('move', 'in', Eval('active_ids'))]</field>
</record>
<record model="ir.action.keyword" id="act_statement_line_move_keyword1">
<field name="keyword">form_relate</field>
<field name="model">account.move,-1</field>
<field name="action" ref="act_statement_line_move"/>
</record>
<record model="ir.action.act_window" id="act_statement_line_move_line">
<field name="name">Statement Lines</field>
<field name="res_model">account.statement.line</field>
<field name="domain">[('move.lines', 'in', Eval('active_ids'))]</field>
</record>
<record model="ir.action.keyword" id="act_statement_line_move_line_keyword1">
<field name="keyword">form_relate</field>
<field name="model">account.move.line,-1</field>
<field name="action" ref="act_statement_line_move_line"/>
</record>
<record model="ir.model.access" id="access_statement_account_admin">
<field name="model" search="[('model', '=', 'account.statement')]"/>
<field name="group" ref="account.group_account_admin"/>
@@ -218,7 +240,7 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.action.act_window" id="act_move_lines_form">
<field name="name">Move Lines</field>
<field name="res_model">account.move.line</field>
<field name="domain">[('origin.statement.id', 'in', Eval('active_ids'), 'account.statement.line')]</field>
<field name="domain">[('origin.id', 'in', Eval('active_ids'), 'account.statement')]</field>
</record>
<record model="ir.action.keyword" id="act_move_lines_form_keyword1">
<field name="keyword">form_relate</field>