@@ -1,3 +1,4 @@
|
||||
* Add reversal option when cancelling move
|
||||
* Add cumulative balance to payable/receivable lines
|
||||
* Rename reconciliation name to number
|
||||
* Accrue and allocate rounding errors when there are multiple taxes
|
||||
|
||||
+18
-6
@@ -369,7 +369,7 @@ class Move(ModelSQL, ModelView):
|
||||
cache_cls = cache[MoveLine.__name__]
|
||||
cache_cls.clear()
|
||||
|
||||
def _cancel_default(self):
|
||||
def _cancel_default(self, reversal=False):
|
||||
'Return default dictionary to cancel move'
|
||||
pool = Pool()
|
||||
Date = pool.get('ir.date')
|
||||
@@ -392,8 +392,12 @@ class Move(ModelSQL, ModelView):
|
||||
'date': date,
|
||||
'period': period_id,
|
||||
})
|
||||
default['lines.debit'] = lambda data: data['debit'] * -1
|
||||
default['lines.credit'] = lambda data: data['credit'] * -1
|
||||
if reversal:
|
||||
default['lines.debit'] = lambda data: data['credit']
|
||||
default['lines.credit'] = lambda data: data['debit']
|
||||
else:
|
||||
default['lines.debit'] = lambda data: data['debit'] * -1
|
||||
default['lines.credit'] = lambda data: data['credit'] * -1
|
||||
default['lines.amount_second_currency'] = (
|
||||
lambda data: data['amount_second_currency'] * -1
|
||||
if data['amount_second_currency']
|
||||
@@ -403,13 +407,13 @@ class Move(ModelSQL, ModelView):
|
||||
lambda data: 'account.move.line,%s' % data['id'])
|
||||
return default
|
||||
|
||||
def cancel(self, default=None):
|
||||
def cancel(self, default=None, reversal=False):
|
||||
'Return a cancel move'
|
||||
if default is None:
|
||||
default = {}
|
||||
else:
|
||||
default = default.copy()
|
||||
default.update(self._cancel_default())
|
||||
default.update(self._cancel_default(reversal=reversal))
|
||||
cancel_move, = self.copy([self], default=default)
|
||||
return cancel_move
|
||||
|
||||
@@ -2215,7 +2219,8 @@ class CancelMoves(Wizard):
|
||||
with Transaction().set_user(0):
|
||||
Unreconcile.make_unreconciliation(moves_w_delegation[move])
|
||||
default = self.default_cancel(move)
|
||||
cancel_move = move.cancel(default=default)
|
||||
cancel_move = move.cancel(
|
||||
default=default, reversal=self.default.reversal)
|
||||
to_reconcile = defaultdict(list)
|
||||
for line in move.lines + cancel_move.lines:
|
||||
if line.account.reconcile:
|
||||
@@ -2229,6 +2234,13 @@ class CancelMovesDefault(ModelView):
|
||||
'Cancel Moves'
|
||||
__name__ = 'account.move.cancel.default'
|
||||
description = fields.Char('Description')
|
||||
reversal = fields.Boolean(
|
||||
"Reversal",
|
||||
help="Reverse debit and credit.")
|
||||
|
||||
@classmethod
|
||||
def default_reversal(cls):
|
||||
return True
|
||||
|
||||
|
||||
class GroupLines(Wizard):
|
||||
|
||||
@@ -17,6 +17,8 @@ Activate modules::
|
||||
|
||||
>>> config = activate_modules('account')
|
||||
|
||||
>>> Reconciliation = Model.get('account.move.reconciliation')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
@@ -78,10 +80,49 @@ Create Move to cancel::
|
||||
>>> receivable.debit
|
||||
Decimal('42.00')
|
||||
|
||||
Cancel reversal Move::
|
||||
|
||||
>>> cancel_move = Wizard('account.move.cancel', [move])
|
||||
>>> cancel_move.form.description = "Reversal"
|
||||
>>> cancel_move.form.reversal = True
|
||||
>>> cancel_move.execute('cancel')
|
||||
>>> cancel_move.state
|
||||
'end'
|
||||
>>> move.reload()
|
||||
>>> [bool(l.reconciliation) for l in move.lines if l.account == receivable]
|
||||
[True, True]
|
||||
>>> line, _ = [l for l in move.lines if l.account == receivable]
|
||||
>>> cancel_move, = [l.move for l in line.reconciliation.lines
|
||||
... if l.move != move]
|
||||
>>> cancel_move.origin == move
|
||||
True
|
||||
>>> cancel_move.description
|
||||
'Reversal'
|
||||
>>> sorted([l.origin.id for l in cancel_move.lines]) == \
|
||||
... sorted(map(int, move.lines))
|
||||
True
|
||||
>>> revenue.reload()
|
||||
>>> revenue.credit
|
||||
Decimal('42.00')
|
||||
>>> revenue.debit
|
||||
Decimal('42.00')
|
||||
>>> receivable.reload()
|
||||
>>> receivable.credit
|
||||
Decimal('42.00')
|
||||
>>> receivable.debit
|
||||
Decimal('42.00')
|
||||
|
||||
>>> reconciliations = {
|
||||
... l.reconciliation for l in cancel_move.lines if l.reconciliation}
|
||||
>>> Reconciliation.delete(list(reconciliations))
|
||||
>>> cancel_move.reload()
|
||||
>>> cancel_move.delete()
|
||||
|
||||
Cancel Move::
|
||||
|
||||
>>> cancel_move = Wizard('account.move.cancel', [move])
|
||||
>>> cancel_move.form.description = 'Cancel'
|
||||
>>> cancel_move.form.reversal = False
|
||||
>>> cancel_move.execute('cancel')
|
||||
>>> cancel_move.state
|
||||
'end'
|
||||
|
||||
@@ -79,6 +79,7 @@ Create some moves::
|
||||
>>> _ = move.duplicate()
|
||||
|
||||
>>> cancel_move = Wizard('account.move.cancel', [move])
|
||||
>>> cancel_move.form.reversal = False
|
||||
>>> cancel_move.execute('cancel')
|
||||
|
||||
Check tax code::
|
||||
|
||||
@@ -4,4 +4,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<form>
|
||||
<label name="description"/>
|
||||
<field name="description" colspan="3"/>
|
||||
|
||||
<label name="reversal"/>
|
||||
<field name="reversal"/>
|
||||
</form>
|
||||
|
||||
@@ -158,19 +158,19 @@ class Move(metaclass=PoolMeta):
|
||||
MoveLine.set_analytic_state(lines)
|
||||
MoveLine.save(lines)
|
||||
|
||||
def cancel(self, default=None):
|
||||
'Reverse credit/debit of analytic lines'
|
||||
pool = Pool()
|
||||
AnalyticLine = pool.get('analytic_account.line')
|
||||
cancel_move = super(Move, self).cancel(default)
|
||||
analytic_lines = []
|
||||
for line in cancel_move.lines:
|
||||
for analytic_line in line.analytic_lines:
|
||||
analytic_line.debit, analytic_line.credit = (
|
||||
analytic_line.credit, analytic_line.debit)
|
||||
analytic_lines.append(analytic_line)
|
||||
AnalyticLine.save(analytic_lines)
|
||||
return cancel_move
|
||||
def _cancel_default(self, reversal=False):
|
||||
default = super()._cancel_default(reversal=reversal)
|
||||
if reversal:
|
||||
default['lines.analytic_lines.debit'] = (
|
||||
lambda data: data['credit'])
|
||||
default['lines.analytic_lines.credit'] = (
|
||||
lambda data: data['debit'])
|
||||
else:
|
||||
default['lines.analytic_lines.debit'] = (
|
||||
lambda data: data['debit'] * -1)
|
||||
default['lines.analytic_lines.credit'] = (
|
||||
lambda data: data['credit'] * -1)
|
||||
return default
|
||||
|
||||
|
||||
class MoveLine(metaclass=PoolMeta):
|
||||
|
||||
@@ -16,6 +16,8 @@ Activate modules::
|
||||
|
||||
>>> config = activate_modules('analytic_account')
|
||||
|
||||
>>> Reconciliation = Model.get('account.move.reconciliation')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
@@ -93,7 +95,7 @@ Create Move analytic accounts::
|
||||
>>> analytic_account.debit
|
||||
Decimal('0.00')
|
||||
|
||||
Cancel Move::
|
||||
Cancel reversal move::
|
||||
|
||||
>>> cancel_move = Wizard('account.move.cancel', [move])
|
||||
>>> cancel_move.form.description = 'Cancel'
|
||||
@@ -112,6 +114,32 @@ Cancel Move::
|
||||
>>> analytic_account.debit
|
||||
Decimal('42.00')
|
||||
|
||||
>>> reconciliations = {
|
||||
... l.reconciliation for l in cancel_move.lines if l.reconciliation}
|
||||
>>> Reconciliation.delete(list(reconciliations))
|
||||
>>> cancel_move.reload()
|
||||
>>> cancel_move.delete()
|
||||
|
||||
Cancel move::
|
||||
|
||||
>>> cancel_move = Wizard('account.move.cancel', [move])
|
||||
>>> cancel_move.form.description = 'Cancel'
|
||||
>>> cancel_move.form.reversal = False
|
||||
>>> cancel_move.execute('cancel')
|
||||
>>> move.reload()
|
||||
>>> line, = [l for l in move.lines if l.account == receivable]
|
||||
>>> bool(line.reconciliation)
|
||||
True
|
||||
>>> cancel_move, = [l.move for l in line.reconciliation.lines
|
||||
... if l.move != move]
|
||||
>>> cancel_move.origin == move
|
||||
True
|
||||
>>> analytic_account.reload()
|
||||
>>> analytic_account.credit
|
||||
Decimal('0.00')
|
||||
>>> analytic_account.debit
|
||||
Decimal('0.00')
|
||||
|
||||
Create Move without analytic accounts::
|
||||
|
||||
>>> move = Move()
|
||||
|
||||
Reference in New Issue
Block a user