Add cancel to Account Move

issue3875
review10261002
This commit is contained in:
Cédric Krier committed 2014-05-09 23:32:17 +02:00
1 parent 6a2149e5bc
commit 0ef36b0ec8
6 files changed
+250 -2

No files matched your search

+2
View File
@@ -1,3 +1,5 @@
* Add cancel to Account Move
Version 3.2.0 - 2014-04-21
* Bug fixes (see mercurial logs for details)
* Add start/end date to tax
+1
View File
@@ -89,6 +89,7 @@ def register():
ReconcileLines,
UnreconcileLines,
OpenReconcileLines,
CancelMoves,
PrintGeneralJournal,
OpenChartTaxCode,
OpenTaxCode,
+75 -2
View File
@@ -4,6 +4,8 @@ from decimal import Decimal
import datetime
from itertools import groupby
from operator import itemgetter
from collections import defaultdict
from sql.aggregate import Sum
from sql.conditionals import Coalesce
@@ -21,7 +23,8 @@ from trytond.tools import reduce_ids
__all__ = ['Move', 'Reconciliation', 'Line', 'OpenJournalAsk',
'OpenJournal', 'OpenAccount', 'ReconcileLinesWriteOff', 'ReconcileLines',
'UnreconcileLines', 'OpenReconcileLinesStart',
'OpenReconcileLines', 'FiscalYearLine', 'FiscalYear2',
'OpenReconcileLines', 'CancelMoves',
'FiscalYearLine', 'FiscalYear2',
'PrintGeneralJournalStart', 'PrintGeneralJournal', 'GeneralJournal']
__metaclass__ = PoolMeta
@@ -86,6 +89,9 @@ class Move(ModelSQL, ModelView):
'because it\'s date is outside its period.'),
'draft_closed_period': ('You can not set to draft move '
'"%(move)s" because period "%(period)s" is closed.'),
'period_cancel': (
'The period of move "%s" is closed.\n'
'Use the current period?'),
})
cls._buttons.update({
'post': {
@@ -156,7 +162,7 @@ class Move(ModelSQL, ModelView):
@classmethod
def _get_origin(cls):
'Return list of Model names for origin Reference'
return ['account.fiscalyear']
return ['account.fiscalyear', 'account.move']
@classmethod
def get_origin(cls):
@@ -334,6 +340,50 @@ class Move(ModelSQL, ModelView):
values=[state],
where=red_sql))
def _cancel_default(self):
'Return default dictionary to cancel move'
pool = Pool()
Date = pool.get('ir.date')
Period = pool.get('account.period')
default = {
'origin': str(self),
}
if self.period.state == 'close':
self.raise_user_warning('%s.cancel' % self,
'period_cancel', self.rec_name)
date = Date.today()
period_id = Period.find(self.company.id, date=date)
default.update({
'date': date,
'period': period_id,
})
return default
def cancel(self):
'Return a cancel move'
pool = Pool()
Line = pool.get('account.move.line')
TaxLine = pool.get('account.tax.line')
default = self._cancel_default()
cancel_move, = Move.copy([self], default=default)
lines = []
tax_lines = []
for line in cancel_move.lines:
line.debit *= -1
line.credit *= -1
lines.extend(([line], line._save_values))
line._values = None
for tax_line in line.tax_lines:
tax_line.amount *= -1
tax_lines.extend(([tax_line], tax_line._save_values))
tax_line._values = None
if lines:
Line.write(*lines)
if tax_lines:
TaxLine.write(*tax_lines)
return cancel_move
@classmethod
@ModelView.button
def post(cls, moves):
@@ -1670,6 +1720,29 @@ class OpenReconcileLines(Wizard):
return action, {}
class CancelMoves(Wizard):
'Cancel Moves'
__name__ = 'account.move.cancel'
start_state = 'cancel'
cancel = StateTransition()
def transition_cancel(self):
pool = Pool()
Move = pool.get('account.move')
Line = pool.get('account.move.line')
moves = Move.browse(Transaction().context['active_ids'])
for move in moves:
cancel_move = move.cancel()
to_reconcile = defaultdict(list)
for line in move.lines + cancel_move.lines:
if line.account.reconcile:
to_reconcile[line.account].append(line)
for lines in to_reconcile.itervalues():
Line.reconcile(lines)
return 'end'
class FiscalYearLine(ModelSQL):
'Fiscal Year - Move Line'
__name__ = 'account.fiscalyear-account.move.line'
+10
View File
@@ -294,6 +294,16 @@ this repository contains the full copyright notices and license terms. -->
action="act_open_reconcile_lines"
id="menu_open_reconcile_lines"/>
<record model="ir.action.wizard" id="act_cancel_moves">
<field name="name">Cancel Moves</field>
<field name="wiz_name">account.move.cancel</field>
</record>
<record model="ir.action.keyword" id="act_cancel_moves_keyword1">
<field name="keyword">form_action</field>
<field name="model">account.move,-1</field>
<field name="action" ref="act_cancel_moves"/>
</record>
<record model="ir.ui.view" id="print_general_journal_start_view_form">
<field name="model">account.move.print_general_journal.start</field>
<field name="type">form</field>
+158
View File
@@ -0,0 +1,158 @@
====================
Move Cancel Scenario
====================
=============
General Setup
=============
Imports::
>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> from decimal import Decimal
>>> from proteus import config, Model, Wizard
>>> today = datetime.date.today()
Create database::
>>> config = config.set_trytond()
>>> config.pool.test = True
Install account::
>>> Module = Model.get('ir.module.module')
>>> modules = Module.find([
... ('name', '=', 'account'),
... ])
>>> Module.install([x.id for x in modules], config.context)
>>> Wizard('ir.module.module.install_upgrade').execute('upgrade')
Create company::
>>> Currency = Model.get('currency.currency')
>>> CurrencyRate = Model.get('currency.currency.rate')
>>> Company = Model.get('company.company')
>>> Party = Model.get('party.party')
>>> company_config = Wizard('company.company.config')
>>> company_config.execute('company')
>>> company = company_config.form
>>> party = Party(name='Dunder Mifflin')
>>> party.save()
>>> company.party = party
>>> currencies = Currency.find([('code', '=', 'USD')])
>>> if not currencies:
... currency = Currency(name='U.S. Dollar', symbol='$', code='USD',
... rounding=Decimal('0.01'), mon_grouping='[3, 3, 0]',
... mon_decimal_point='.', mon_thousands_sep=',')
... currency.save()
... CurrencyRate(date=today + relativedelta(month=1, day=1),
... rate=Decimal('1.0'), currency=currency).save()
... else:
... currency, = currencies
>>> company.currency = currency
>>> company_config.execute('add')
>>> company, = Company.find()
Reload the context::
>>> User = Model.get('res.user')
>>> config._context = User.get_preferences(True, config.context)
Create fiscal year::
>>> FiscalYear = Model.get('account.fiscalyear')
>>> Sequence = Model.get('ir.sequence')
>>> SequenceStrict = Model.get('ir.sequence.strict')
>>> fiscalyear = FiscalYear(name='%s' % today.year)
>>> fiscalyear.start_date = today + relativedelta(month=1, day=1)
>>> fiscalyear.end_date = today + relativedelta(month=12, day=31)
>>> fiscalyear.company = company
>>> post_move_sequence = Sequence(name='%s' % today.year,
... code='account.move', company=company)
>>> post_move_sequence.save()
>>> fiscalyear.post_move_sequence = post_move_sequence
>>> fiscalyear.save()
>>> FiscalYear.create_period([fiscalyear.id], config.context)
>>> period = fiscalyear.periods[0]
Create chart of accounts::
>>> AccountTemplate = Model.get('account.account.template')
>>> Account = Model.get('account.account')
>>> account_template, = AccountTemplate.find([('parent', '=', None)])
>>> create_chart = Wizard('account.create_chart')
>>> create_chart.execute('account')
>>> create_chart.form.account_template = account_template
>>> create_chart.form.company = company
>>> create_chart.execute('create_account')
>>> receivable, = Account.find([
... ('kind', '=', 'receivable'),
... ('company', '=', company.id),
... ])
>>> payable, = Account.find([
... ('kind', '=', 'payable'),
... ('company', '=', company.id),
... ])
>>> revenue, = Account.find([
... ('kind', '=', 'revenue'),
... ('company', '=', company.id),
... ])
>>> create_chart.form.account_receivable = receivable
>>> create_chart.form.account_payable = payable
>>> create_chart.execute('create_properties')
Create parties::
>>> Party = Model.get('party.party')
>>> customer = Party(name='Customer')
>>> customer.save()
Create Move to cancel::
>>> Journal = Model.get('account.journal')
>>> Move = Model.get('account.move')
>>> journal_revenue, = Journal.find([
... ('code', '=', 'REV'),
... ])
>>> journal_cash, = Journal.find([
... ('code', '=', 'CASH'),
... ])
>>> move = Move()
>>> move.period = period
>>> move.journal = journal_revenue
>>> move.date = period.start_date
>>> line = move.lines.new()
>>> line.account = revenue
>>> line.credit = Decimal(42)
>>> line = move.lines.new()
>>> line.account = receivable
>>> line.debit = Decimal(42)
>>> line.party = customer
>>> move.save()
>>> revenue.reload()
>>> revenue.credit
Decimal('42.00')
>>> receivable.reload()
>>> receivable.debit
Decimal('42.00')
Cancel Move::
>>> cancel_move = Wizard('account.move.cancel', [move])
>>> cancel_move.state
'end'
>>> 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
>>> revenue.reload()
>>> revenue.credit
Decimal('0.00')
>>> receivable.reload()
>>> receivable.debit
Decimal('0.00')
+4
View File
@@ -436,4 +436,8 @@ def suite():
'scenario_account_reconciliation.rst',
setUp=doctest_dropdb, tearDown=doctest_dropdb, encoding='utf-8',
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
suite.addTests(doctest.DocFileSuite(
'scenario_move_cancel.rst',
setUp=doctest_dropdb, tearDown=doctest_dropdb, encoding='utf-8',
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
return suite