Files
tryton/move.py
T

1635 lines
62 KiB
Python
Raw Normal View History

2008-10-22 20:07:57 +02:00
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
2008-03-17 18:32:06 +01:00
from decimal import Decimal
import datetime
import time
2010-08-19 22:02:00 +02:00
from trytond.model import ModelView, ModelSQL, fields
2012-01-02 17:54:33 +01:00
from trytond.wizard import Wizard, StateTransition, StateView, StateAction, \
Button
2010-08-19 22:02:00 +02:00
from trytond.report import Report
from trytond.backend import TableHandler, FIELDS
2011-08-21 11:20:29 +02:00
from trytond.pyson import Eval, PYSONEncoder
2010-08-19 22:02:00 +02:00
from trytond.transaction import Transaction
2012-09-24 22:17:29 +02:00
from trytond.pool import Pool, PoolMeta
from trytond.rpc import RPC
__all__ = ['Move', 'Reconciliation', 'Line', 'Move2', 'OpenJournalAsk',
'OpenJournal', 'OpenAccount', 'ReconcileLinesWriteOff', 'ReconcileLines',
'UnreconcileLinesStart', 'UnreconcileLines', 'OpenReconcileLinesStart',
'OpenReconcileLines', 'FiscalYearLine', 'FiscalYear2',
'PrintGeneralJournalStart', 'PrintGeneralJournal', 'GeneralJournal']
__metaclass__ = PoolMeta
2008-03-17 18:32:06 +01:00
_MOVE_STATES = {
2011-08-21 11:20:29 +02:00
'readonly': Eval('state') == 'posted',
}
_MOVE_DEPENDS = ['state']
2008-03-17 18:32:06 +01:00
_LINE_STATES = {
2011-08-21 11:20:29 +02:00
'readonly': Eval('state') == 'valid',
}
_LINE_DEPENDS = ['state']
2008-03-17 18:32:06 +01:00
2009-02-28 16:57:10 +01:00
class Move(ModelSQL, ModelView):
2008-03-17 18:32:06 +01:00
'Account Move'
2012-09-24 22:17:29 +02:00
__name__ = 'account.move'
2012-09-29 15:33:21 +02:00
_rec_name = 'number'
number = fields.Char('Number', required=True, readonly=True)
post_number = fields.Char('Post Number', readonly=True,
help='Also known as Folio Number')
2008-03-17 18:32:06 +01:00
period = fields.Many2One('account.period', 'Period', required=True,
2012-03-05 10:52:56 +01:00
states=_MOVE_STATES, depends=_MOVE_DEPENDS, select=True)
2008-03-17 18:32:06 +01:00
journal = fields.Many2One('account.journal', 'Journal', required=True,
states=_MOVE_STATES, depends=_MOVE_DEPENDS)
date = fields.Date('Effective Date', required=True, states=_MOVE_STATES,
2012-04-03 20:06:15 +02:00
depends=_MOVE_DEPENDS, on_change_with=['period', 'journal', 'date'])
2008-03-28 19:49:16 +01:00
post_date = fields.Date('Post Date', readonly=True)
2012-09-29 15:33:21 +02:00
description = fields.Char('Description', states=_MOVE_STATES,
depends=_MOVE_DEPENDS)
origin = fields.Reference('Origin', selection='get_origin',
states=_MOVE_STATES, depends=_MOVE_DEPENDS)
2008-03-17 18:32:06 +01:00
state = fields.Selection([
('draft', 'Draft'),
('posted', 'Posted'),
2012-03-05 10:52:56 +01:00
], 'State', required=True, readonly=True, select=True)
2008-03-17 18:32:06 +01:00
lines = fields.One2Many('account.move.line', 'move', 'Lines',
2009-10-10 13:31:39 +02:00
states=_MOVE_STATES, depends=_MOVE_DEPENDS,
2010-01-20 10:56:33 +01:00
context={
'journal': Eval('journal'),
'period': Eval('period'),
'date': Eval('date'),
})
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def __setup__(cls):
super(Move, cls).__setup__()
cls._check_modify_exclude = ['state']
cls._constraints += [
2008-08-05 11:35:03 +02:00
('check_centralisation', 'period_centralized_journal'),
('check_company', 'company_in_move'),
('check_date', 'date_outside_period'),
2008-03-17 18:32:06 +01:00
]
2012-09-24 22:17:29 +02:00
cls._order.insert(0, ('date', 'DESC'))
2012-09-29 15:33:21 +02:00
cls._order.insert(1, ('number', 'DESC'))
2012-09-24 22:17:29 +02:00
cls._error_messages.update({
2009-03-20 13:49:25 +01:00
'del_posted_move': 'You can not delete posted moves!',
2008-07-17 19:35:43 +02:00
'post_empty_move': 'You can not post an empty move!',
2009-03-20 13:49:25 +01:00
'post_unbalanced_move': 'You can not post an unbalanced move!',
2012-03-02 07:46:19 +00:00
'draft_posted_move_journal': 'You can not set a posted move ' \
'to draft in this journal!',
'modify_posted_move': 'Move "%s" is already posted!\n'
'You can not modify a posted move.',
2008-08-05 11:35:03 +02:00
'period_centralized_journal': 'You can not create more than ' \
'one move per period\n' \
2009-03-20 13:49:25 +01:00
'in a centralized journal!',
'company_in_move': 'You can not create lines on accounts\n' \
'of different companies in the same move!',
2008-08-05 11:35:03 +02:00
'date_outside_period': 'You can not create move ' \
2009-03-20 13:49:25 +01:00
'with a date outside the period!',
'draft_closed_period': 'You can not set to draft a move ' \
'from a closed period',
2008-07-17 19:35:43 +02:00
})
2012-09-24 22:17:29 +02:00
cls._buttons.update({
2012-03-25 00:17:23 +01:00
'post': {
'invisible': Eval('state') == 'posted',
},
'draft': {
'invisible': Eval('state') == 'draft',
},
})
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def __register__(cls, module_name):
2012-09-29 15:33:21 +02:00
cursor = Transaction().cursor
table = TableHandler(cursor, cls, module_name)
# Migration from 2.4:
# - name renamed into number
# - reference renamed into post_number
if table.column_exist('name'):
table.column_rename('name', 'number')
if table.column_exist('reference'):
table.column_rename('reference', 'post_number')
2012-09-24 22:17:29 +02:00
super(Move, cls).__register__(module_name)
2009-02-02 13:09:08 +01:00
2012-09-24 22:17:29 +02:00
table = TableHandler(cursor, cls, module_name)
2009-03-06 00:45:18 +01:00
table.index_action(['journal', 'period'], 'add')
2008-03-17 18:32:06 +01:00
2010-01-23 11:40:35 +01:00
# Add index on create_date
table.index_action('create_date', action='add')
2012-09-24 22:17:29 +02:00
@staticmethod
def default_period():
Period = Pool().get('account.period')
return Period.find(Transaction().context.get('company'),
exception=False)
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@staticmethod
def default_state():
2008-03-17 18:32:06 +01:00
return 'draft'
2012-09-24 22:17:29 +02:00
@classmethod
def default_date(cls):
pool = Pool()
Period = pool.get('account.period')
Date = pool.get('ir.date')
period_id = cls.default_period()
2009-10-10 13:31:39 +02:00
if period_id:
2012-09-24 22:17:29 +02:00
period = Period(period_id)
2009-10-10 13:31:39 +02:00
return period.start_date
2012-09-24 22:17:29 +02:00
return Date.today()
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
def on_change_with_date(self):
Line = Pool().get('account.move.line')
date = self.date
lines = Line.search([
('journal', '=', self.journal),
('period', '=', self.period),
], order=[('id', 'DESC')], limit=1)
if lines:
date = lines[0].date
elif self.period:
date = self.period.start_date
return date
2009-10-10 13:31:39 +02:00
2012-09-29 15:33:21 +02:00
@classmethod
def _get_origin(cls):
'Return list of Model names for origin Reference'
return []
@classmethod
def get_origin(cls):
Model = Pool().get('ir.model')
models = cls._get_origin()
models = Model.search([
('model', 'in', models),
])
return [('', '')] + [(m.model, m.name) for m in models]
2012-09-24 22:17:29 +02:00
def check_centralisation(self):
if self.journal.centralised:
moves = self.search([
('period', '=', self.period.id),
('journal', '=', self.journal.id),
('state', '!=', 'posted'),
2008-03-17 18:32:06 +01:00
], limit=2)
2012-09-24 22:17:29 +02:00
if len(moves) > 1:
2008-03-31 14:03:17 +02:00
return False
return True
2012-09-24 22:17:29 +02:00
def check_company(self):
company_id = -1
for line in self.lines:
if company_id < 0:
company_id = line.account.company.id
if line.account.company.id != company_id:
return False
return True
def check_date(self):
return self.period.start_date <= self.date <= self.period.end_date
@classmethod
def check_modify(cls, moves):
2012-03-02 07:46:19 +00:00
'Check posted moves for modifications.'
2012-09-24 22:17:29 +02:00
for move in moves:
2012-03-02 07:46:19 +00:00
if move.state == 'posted':
2012-09-24 22:17:29 +02:00
cls.raise_user_error('modify_posted_move',
2012-03-02 07:46:19 +00:00
error_args=(move.name,))
2012-09-24 22:17:29 +02:00
@classmethod
def search_rec_name(cls, name, clause):
moves = cls.search(['OR',
2012-09-29 15:33:21 +02:00
('post_number',) + tuple(clause[1:]),
2012-09-24 22:17:29 +02:00
(cls._rec_name,) + tuple(clause[1:]),
])
return [('id', 'in', [m.id for m in moves])]
2012-09-24 22:17:29 +02:00
@classmethod
def write(cls, moves, vals):
2012-03-02 07:46:19 +00:00
keys = vals.keys()
2012-09-24 22:17:29 +02:00
for key in cls._check_modify_exclude:
2012-03-02 07:46:19 +00:00
if key in keys:
keys.remove(key)
if len(keys):
2012-09-24 22:17:29 +02:00
cls.check_modify(moves)
super(Move, cls).write(moves, vals)
cls.validate(moves)
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def create(cls, vals):
2011-07-03 13:18:40 +02:00
pool = Pool()
2012-09-24 22:17:29 +02:00
MoveLine = pool.get('account.move.line')
Sequence = pool.get('ir.sequence')
Journal = pool.get('account.journal')
2012-09-29 15:33:21 +02:00
if not vals.get('number'):
2010-08-19 22:02:00 +02:00
journal_id = (vals.get('journal')
or Transaction().context.get('journal'))
if journal_id:
vals = vals.copy()
2012-09-24 22:17:29 +02:00
journal = Journal(journal_id)
2012-09-29 15:33:21 +02:00
vals['number'] = Sequence.get_id(journal.sequence.id)
2012-09-24 22:17:29 +02:00
move = super(Move, cls).create(vals)
if move.journal.centralised:
2012-09-24 22:17:29 +02:00
line = MoveLine.create({
'account': move.journal.credit_account.id,
'move': move.id,
})
cls.write([move], {
'centralised_line': line.id,
})
2008-03-17 18:32:06 +01:00
if 'lines' in vals:
2012-09-24 22:17:29 +02:00
cls.validate([move])
return move
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def delete(cls, moves):
MoveLine = Pool().get('account.move.line')
cls.check_modify(moves)
MoveLine.delete([l for m in moves for l in m.lines])
super(Move, cls).delete(moves)
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def copy(cls, moves, default=None):
Line = Pool().get('account.move.line')
2008-12-05 13:25:33 +01:00
if default is None:
default = {}
2008-12-05 13:25:33 +01:00
default = default.copy()
2012-09-29 15:33:21 +02:00
default['number'] = None
default['post_number'] = None
2012-09-24 22:17:29 +02:00
default['state'] = cls.default_state()
2012-03-27 10:43:03 +02:00
default['post_date'] = None
default['lines'] = None
2012-09-24 22:17:29 +02:00
new_moves = []
for move in moves:
new_move, = super(Move, cls).copy([move], default=default)
Line.copy(move.lines, default={
'move': new_move.id,
})
new_moves.append(new_move)
return new_moves
2008-12-05 13:25:33 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def validate(cls, moves):
2008-03-17 18:32:06 +01:00
'''
Validate balanced move and centralise it if in centralised journal
'''
2012-09-24 22:17:29 +02:00
pool = Pool()
MoveLine = pool.get('account.move.line')
for move in moves:
2008-03-17 18:32:06 +01:00
if not move.lines:
continue
amount = Decimal('0.0')
company = None
draft_lines = []
for line in move.lines:
amount += line.debit - line.credit
if not company:
company = line.account.company
if line.state == 'draft':
draft_lines.append(line)
2012-09-24 22:17:29 +02:00
if not company.currency.is_zero(amount):
if not move.journal.centralised:
2012-09-24 22:17:29 +02:00
MoveLine.write(
[x for x in move.lines if x.state != 'draft'], {
2008-03-17 18:32:06 +01:00
'state': 'draft',
2010-08-19 22:02:00 +02:00
})
else:
if not move.centralised_line:
centralised_amount = - amount
else:
centralised_amount = move.centralised_line.debit \
- move.centralised_line.credit \
- amount
if centralised_amount >= Decimal('0.0'):
debit = centralised_amount
credit = Decimal('0.0')
account_id = move.journal.debit_account.id
else:
debit = Decimal('0.0')
credit = - centralised_amount
account_id = move.journal.credit_account.id
if not move.centralised_line:
2012-09-24 22:17:29 +02:00
centralised_line = MoveLine.create({
2010-08-19 22:02:00 +02:00
'debit': debit,
'credit': credit,
'account': account_id,
'move': move.id,
})
2012-09-24 22:17:29 +02:00
cls.write([move], {
'centralised_line': centralised_line.id,
2010-08-19 22:02:00 +02:00
})
else:
2012-09-24 22:17:29 +02:00
MoveLine.write([move.centralised_line], {
2012-04-03 20:06:15 +02:00
'debit': debit,
'credit': credit,
'account': account_id,
})
2008-03-17 18:32:06 +01:00
continue
if not draft_lines:
continue
2012-09-24 22:17:29 +02:00
MoveLine.write(draft_lines, {
2012-04-03 20:06:15 +02:00
'state': 'valid',
})
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
2012-03-25 00:17:23 +01:00
@ModelView.button
2012-09-24 22:17:29 +02:00
def post(cls, moves):
2011-07-03 13:18:40 +02:00
pool = Pool()
2012-09-24 22:17:29 +02:00
Sequence = pool.get('ir.sequence')
Date = pool.get('ir.date')
2008-04-10 11:22:16 +02:00
2008-03-17 18:32:06 +01:00
for move in moves:
amount = Decimal('0.0')
2008-03-28 19:49:16 +01:00
if not move.lines:
2012-09-24 22:17:29 +02:00
cls.raise_user_error('post_empty_move')
2008-03-17 18:32:06 +01:00
company = None
for line in move.lines:
amount += line.debit - line.credit
if not company:
company = line.account.company
2012-09-24 22:17:29 +02:00
if not company.currency.is_zero(amount):
cls.raise_user_error('post_unbalanced_move')
2008-03-17 18:32:06 +01:00
for move in moves:
values = {
2008-03-17 18:32:06 +01:00
'state': 'posted',
}
if not move.post_number:
values['post_date'] = Date.today()
values['post_number'] = Sequence.get_id(
move.period.post_move_sequence.id)
cls.write([move], values)
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
2012-03-25 00:17:23 +01:00
@ModelView.button
2012-09-24 22:17:29 +02:00
def draft(cls, moves):
for move in moves:
2008-03-17 18:32:06 +01:00
if not move.journal.update_posted:
2012-09-24 22:17:29 +02:00
cls.raise_user_error('draft_posted_move_journal')
if move.period.state == 'close':
2012-09-24 22:17:29 +02:00
cls.raise_user_error('draft_closed_period')
return cls.write(moves, {
2008-03-17 18:32:06 +01:00
'state': 'draft',
2010-08-19 22:02:00 +02:00
})
2008-03-17 18:32:06 +01:00
2009-02-28 16:57:10 +01:00
class Reconciliation(ModelSQL, ModelView):
2008-03-19 22:13:51 +01:00
'Account Move Reconciliation Lines'
2012-09-24 22:17:29 +02:00
__name__ = 'account.move.reconciliation'
2008-03-19 22:13:51 +01:00
name = fields.Char('Name', size=None, required=True)
lines = fields.One2Many('account.move.line', 'reconciliation',
'Lines')
2012-09-24 22:17:29 +02:00
@classmethod
def __setup__(cls):
super(Reconciliation, cls).__setup__()
cls._constraints += [
2008-08-05 11:35:03 +02:00
('check_lines', 'invalid_reconciliation'),
2012-09-24 22:17:29 +02:00
]
cls._error_messages.update({
2008-07-17 19:35:43 +02:00
'modify': 'You can not modify a reconciliation!',
2008-08-05 11:35:03 +02:00
'invalid_reconciliation': 'You can not create reconciliation ' \
'where lines are not balanced, nor valid, ' \
'nor in the same account, nor in account to reconcile, ' \
'nor from the same party!',
2008-07-17 19:35:43 +02:00
})
2008-03-19 22:13:51 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def create(cls, vals):
Sequence = Pool().get('ir.sequence')
if 'name' not in vals:
vals = vals.copy()
2012-09-24 22:17:29 +02:00
vals['name'] = Sequence.get('account.move.reconciliation')
2012-09-24 22:17:29 +02:00
return super(Reconciliation, cls).create(vals)
2008-03-19 22:13:51 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def write(cls, moves, vals):
cls.raise_user_error('modify')
2012-09-24 22:17:29 +02:00
@classmethod
def check_lines(cls, reconciliations):
for reconciliation in reconciliations:
2008-03-19 22:13:51 +01:00
amount = Decimal('0.0')
account = None
party = None
2008-03-19 22:13:51 +01:00
for line in reconciliation.lines:
if line.state != 'valid':
return False
amount += line.debit - line.credit
if not account:
account = line.account
elif account.id != line.account.id:
return False
if not account.reconcile:
return False
if not party:
party = line.party
elif line.party and party.id != line.party.id:
return False
2012-09-24 22:17:29 +02:00
if not account.company.currency.is_zero(amount):
2008-03-19 22:13:51 +01:00
return False
return True
2009-02-28 16:57:10 +01:00
class Line(ModelSQL, ModelView):
2008-03-17 18:32:06 +01:00
'Account Move Line'
2012-09-24 22:17:29 +02:00
__name__ = 'account.move.line'
2012-09-29 15:33:21 +02:00
_rec_name = 'id'
2010-01-20 10:56:33 +01:00
debit = fields.Numeric('Debit', digits=(16, Eval('currency_digits', 2)),
required=True,
on_change=['account', 'debit', 'credit', 'tax_lines', 'journal',
'move'],
depends=['currency_digits', 'credit', 'tax_lines', 'journal'])
2010-01-20 10:56:33 +01:00
credit = fields.Numeric('Credit', digits=(16, Eval('currency_digits', 2)),
required=True,
on_change=['account', 'debit', 'credit', 'tax_lines', 'journal',
'move'],
depends=['currency_digits', 'debit', 'tax_lines', 'journal'])
2008-03-17 18:32:06 +01:00
account = fields.Many2One('account.account', 'Account', required=True,
domain=[('kind', '!=', 'view')],
2012-03-05 10:52:56 +01:00
select=True,
on_change=['account', 'debit', 'credit', 'tax_lines',
2009-10-12 22:51:19 +02:00
'journal', 'move'])
2012-03-05 10:52:56 +01:00
move = fields.Many2One('account.move', 'Move', select=True, required=True,
2011-08-04 16:57:14 +02:00
states={
'required': False,
2011-08-21 11:20:29 +02:00
'readonly': Eval('state') == 'valid',
2011-08-04 16:57:14 +02:00
},
depends=['state'])
2010-03-11 16:45:27 +01:00
journal = fields.Function(fields.Many2One('account.journal', 'Journal'),
'get_move_field', setter='set_move_field',
searcher='search_move_field')
period = fields.Function(fields.Many2One('account.period', 'Period'),
'get_move_field', setter='set_move_field',
searcher='search_move_field')
date = fields.Function(fields.Date('Effective Date', required=True),
'get_move_field', setter='set_move_field',
searcher='search_move_field')
2012-09-29 15:33:21 +02:00
origin = fields.Function(fields.Reference('Origin',
selection='get_origin'),
'get_move_field', searcher='search_move_field')
description = fields.Char('Description')
2008-03-17 18:32:06 +01:00
amount_second_currency = fields.Numeric('Amount Second Currency',
2010-01-20 10:56:33 +01:00
digits=(16, Eval('second_currency_digits', 2)),
help='The amount expressed in a second currency',
depends=['second_currency_digits'])
2008-05-09 17:24:55 +02:00
second_currency = fields.Many2One('currency.currency', 'Second Currency',
2008-03-17 18:32:06 +01:00
help='The second currency')
2008-10-22 20:07:57 +02:00
party = fields.Many2One('party.party', 'Party',
2008-05-21 18:13:49 +02:00
on_change=['move', 'party', 'account', 'debit', 'credit',
2012-03-05 10:52:56 +01:00
'journal'], select=True, depends=['debit', 'credit', 'account',
'journal'])
maturity_date = fields.Date('Maturity Date',
2008-06-09 10:38:31 +02:00
help='This field is used for payable and receivable lines. \n' \
2008-03-17 18:32:06 +01:00
'You can put the limit date for the payment.')
state = fields.Selection([
('draft', 'Draft'),
('valid', 'Valid'),
2012-03-05 10:52:56 +01:00
], 'State', readonly=True, required=True, select=True)
2008-03-19 22:13:51 +01:00
reconciliation = fields.Many2One('account.move.reconciliation',
2012-03-05 10:52:56 +01:00
'Reconciliation', readonly=True, ondelete='SET NULL', select=True)
2008-03-23 23:05:12 +01:00
tax_lines = fields.One2Many('account.tax.line', 'move_line', 'Tax Lines')
2010-03-11 16:45:27 +01:00
move_state = fields.Function(fields.Selection([
('draft', 'Draft'),
('posted', 'Posted'),
], 'Move State'), 'get_move_field', searcher='search_move_field')
currency_digits = fields.Function(fields.Integer('Currency Digits'),
'get_currency_digits')
second_currency_digits = fields.Function(fields.Integer(
'Second Currency Digits'), 'get_currency_digits')
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def __setup__(cls):
super(Line, cls).__setup__()
cls._sql_constraints += [
2008-03-17 18:32:06 +01:00
('credit_debit',
'CHECK(credit * debit = 0.0)',
'Wrong credit/debit values!'),
2012-09-24 22:17:29 +02:00
]
cls._constraints += [
2008-08-05 11:35:03 +02:00
('check_account', 'move_view_inactive_account'),
2012-09-24 22:17:29 +02:00
]
cls.__rpc__.update({
'on_write': RPC(instantiate=0),
2012-09-29 15:33:21 +02:00
'get_origin': RPC(),
2012-09-24 22:17:29 +02:00
})
cls._order[0] = ('id', 'DESC')
cls._error_messages.update({
2008-07-17 19:35:43 +02:00
'add_modify_closed_journal_period': 'You can not ' \
'add/modify lines in a closed journal period!',
2009-03-20 13:49:25 +01:00
'modify_posted_move': 'You can not modify lines of a posted move!',
'modify_reconciled': 'You can not modify reconciled lines!',
2008-07-17 19:35:43 +02:00
'no_journal': 'No journal defined!',
2009-03-20 12:22:00 +01:00
'move_view_inactive_account': 'You can not create move lines\n' \
'on view/inactive accounts!',
2008-11-13 10:48:40 +01:00
'already_reconciled': 'Line "%s" (%d) already reconciled!',
2008-07-17 19:35:43 +02:00
})
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def __register__(cls, module_name):
2012-09-29 15:33:21 +02:00
cursor = Transaction().cursor
table = TableHandler(cursor, cls, module_name)
# Migration from 2.4: reference renamed into description
if table.column_exist('reference'):
table.column_rename('reference', 'description')
2012-09-24 22:17:29 +02:00
super(Line, cls).__register__(module_name)
2012-09-24 22:17:29 +02:00
table = TableHandler(cursor, cls, module_name)
2010-03-12 14:14:53 +01:00
# Index for General Ledger
table.index_action(['move', 'account'], 'add')
# Migration from 1.2
table.not_null_action('blocked', action='remove')
2012-09-29 15:33:21 +02:00
# Migration from 2.4: remove name
table.not_null_action('name', action='remove')
2012-09-24 22:17:29 +02:00
@classmethod
def default_date(cls):
2008-03-17 18:32:06 +01:00
'''
Return the date of the last line for journal, period
or the starting date of the period
or today
'''
2012-09-24 22:17:29 +02:00
pool = Pool()
Period = pool.get('account.period')
Date = pool.get('ir.date')
2008-10-08 12:17:47 +02:00
2012-09-24 22:17:29 +02:00
date = Date.today()
lines = cls.search([
('journal', '=', Transaction().context.get('journal')),
('period', '=', Transaction().context.get('period')),
], order=[('id', 'DESC')], limit=1)
if lines:
date = lines[0].date
2010-08-19 22:02:00 +02:00
elif Transaction().context.get('period'):
2012-09-24 22:17:29 +02:00
period = Period(Transaction().context['period'])
date = period.start_date
2010-08-19 22:02:00 +02:00
if Transaction().context.get('date'):
2012-09-24 22:17:29 +02:00
date = Transaction().context['date']
return date
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@staticmethod
def default_state():
2008-03-17 18:32:06 +01:00
return 'draft'
2012-09-24 22:17:29 +02:00
@staticmethod
def default_currency_digits():
2009-04-02 13:31:32 +02:00
return 2
2012-09-24 22:17:29 +02:00
@staticmethod
def default_debit():
return Decimal(0)
2012-09-24 22:17:29 +02:00
@staticmethod
def default_credit():
return Decimal(0)
2012-09-24 22:17:29 +02:00
@classmethod
def default_get(cls, fields, with_rec_name=True):
2011-07-03 13:18:40 +02:00
pool = Pool()
2012-09-24 22:17:29 +02:00
Move = pool.get('account.move')
Tax = pool.get('account.tax')
Account = pool.get('account.account')
TaxCode = pool.get('account.tax.code')
values = super(Line, cls).default_get(fields,
2010-08-19 22:02:00 +02:00
with_rec_name=with_rec_name)
2008-03-17 18:32:06 +01:00
if 'move' not in fields:
#Not manual entry
2008-06-06 11:22:06 +02:00
if 'date' in values:
values = values.copy()
del values['date']
2008-03-17 18:32:06 +01:00
return values
2010-08-19 22:02:00 +02:00
if (Transaction().context.get('journal')
and Transaction().context.get('period')):
2012-09-24 22:17:29 +02:00
lines = cls.search([
2010-08-19 22:02:00 +02:00
('move.journal', '=', Transaction().context['journal']),
('move.period', '=', Transaction().context['period']),
('create_uid', '=', Transaction().user),
2008-03-17 18:32:06 +01:00
('state', '=', 'draft'),
2010-08-19 22:02:00 +02:00
], order=[('id', 'DESC')], limit=1)
2012-09-24 22:17:29 +02:00
if not lines:
2008-03-17 18:32:06 +01:00
return values
2012-09-24 22:17:29 +02:00
values['move'] = lines[0].move.id
2008-03-17 18:32:06 +01:00
if 'move' not in values:
return values
2012-09-24 22:17:29 +02:00
move = Move(values['move'])
2008-03-17 18:32:06 +01:00
total = Decimal('0.0')
taxes = {}
no_code_taxes = []
2008-03-17 18:32:06 +01:00
for line in move.lines:
total += line.debit - line.credit
2008-05-21 18:13:49 +02:00
if line.party and 'party' in fields:
values.setdefault('party', line.party.id)
if move.journal.type in ('expense', 'revenue'):
line_code_taxes = [x.code.id for x in line.tax_lines]
for tax in line.account.taxes:
if move.journal.type == 'revenue':
if line.debit:
2008-10-03 17:11:53 +02:00
base_id = tax.credit_note_base_code.id
code_id = tax.credit_note_tax_code.id
account_id = tax.credit_note_account.id
else:
base_id = tax.invoice_base_code.id
code_id = tax.invoice_tax_code.id
account_id = tax.invoice_account.id
else:
if line.debit:
base_id = tax.invoice_base_code.id
code_id = tax.invoice_tax_code.id
account_id = tax.invoice_account.id
else:
2008-10-03 17:11:53 +02:00
base_id = tax.credit_note_base_code.id
code_id = tax.credit_note_tax_code.id
account_id = tax.credit_note_account.id
if base_id in line_code_taxes or not base_id:
2012-03-27 10:43:03 +02:00
taxes.setdefault((account_id, code_id, tax.id), None)
for tax_line in line.tax_lines:
taxes[(line.account.id, tax_line.code.id,
tax_line.tax.id)] = True
if not line.tax_lines:
no_code_taxes.append(line.account.id)
for no_code_account_id in no_code_taxes:
for (account_id, code_id, tax_id), test in \
taxes.iteritems():
if (not test
and not code_id
and no_code_account_id == account_id):
taxes[(account_id, code_id, tax_id)] = True
2008-03-17 18:32:06 +01:00
if 'account' in fields:
if total >= Decimal('0.0'):
values['account'] = (move.journal.credit_account \
2012-03-27 10:43:03 +02:00
and move.journal.credit_account.id or None)
2008-03-17 18:32:06 +01:00
else:
values['account'] = (move.journal.debit_account \
2012-03-27 10:43:03 +02:00
and move.journal.debit_account.id or None)
2008-03-17 18:32:06 +01:00
if ('debit' in fields) or ('credit' in fields):
values['debit'] = total < 0 and - total or Decimal(0)
values['credit'] = total > 0 and total or Decimal(0)
if move.journal.type in ('expense', 'revenue'):
for account_id, code_id, tax_id in taxes:
if taxes[(account_id, code_id, tax_id)]:
continue
for line in move.lines:
if move.journal.type == 'revenue':
if line.debit:
2008-10-03 17:11:53 +02:00
key = 'credit_note'
else:
key = 'invoice'
else:
if line.debit:
key = 'invoice'
else:
2008-10-03 17:11:53 +02:00
key = 'credit_note'
line_amount = Decimal('0.0')
tax_amount = Decimal('0.0')
2012-09-24 22:17:29 +02:00
for tax_line in Tax.compute(line.account.taxes,
2010-08-19 22:02:00 +02:00
line.debit or line.credit, 1):
if (tax_line['tax'][key + '_account'].id \
or line.account.id) == account_id \
and tax_line['tax'][key + '_tax_code'].id \
== code_id \
and tax_line['tax'].id == tax_id:
if line.debit:
line_amount += tax_line['amount']
else:
line_amount -= tax_line['amount']
tax_amount += tax_line['amount'] * \
tax_line['tax'][key + '_tax_sign']
2012-09-24 22:17:29 +02:00
line_amount = line.account.company.currency.round(
line_amount)
tax_amount = line.account.company.currency.round(
tax_amount)
if ('debit' in fields):
values['debit'] = line_amount > Decimal('0.0') \
and line_amount or Decimal('0.0')
if ('credit' in fields):
values['credit'] = line_amount < Decimal('0.0') \
and - line_amount or Decimal('0.0')
if 'account' in fields:
values['account'] = account_id
2012-09-24 22:17:29 +02:00
values['account.rec_name'] = Account(
account_id).rec_name
if 'tax_lines' in fields and code_id:
values['tax_lines'] = [
{
'amount': tax_amount,
'currency_digits': line.currency_digits,
'code': code_id,
2012-09-24 22:17:29 +02:00
'code.rec_name': TaxCode(code_id).rec_name,
'tax': tax_id,
2012-09-24 22:17:29 +02:00
'tax.rec_name': Tax(tax_id).rec_name,
},
]
2008-03-17 18:32:06 +01:00
return values
2012-09-24 22:17:29 +02:00
@classmethod
def get_currency_digits(cls, lines, names):
digits = {}
for line in lines:
2008-09-22 18:23:05 +02:00
for name in names:
2012-09-24 22:17:29 +02:00
digits.setdefault(name, {})
digits[name].setdefault(line.id, 2)
2008-09-22 18:23:05 +02:00
if name == 'currency_digits':
2012-09-24 22:17:29 +02:00
digits[name][line.id] = line.account.currency_digits
2008-09-22 18:23:05 +02:00
elif name == 'second_currency_digits':
2012-04-03 20:06:15 +02:00
second_currency = line.account.second_currency
if second_currency:
2012-09-24 22:17:29 +02:00
digits[name][line.id] = second_currency.digits
return digits
2008-09-22 18:23:05 +02:00
2012-09-29 15:33:21 +02:00
@classmethod
def get_origin(cls):
Move = Pool().get('account.move')
return Move.get_origin()
2012-09-24 22:17:29 +02:00
def on_change_debit(self):
changes = {}
Journal = Pool().get('account.journal')
if self.journal or Transaction().context.get('journal'):
journal = self.journal or Journal(Transaction().context['journal'])
if journal.type in ('expense', 'revenue'):
2012-09-24 22:17:29 +02:00
changes['tax_lines'] = self._compute_tax_lines(journal.type)
if not changes['tax_lines']:
del changes['tax_lines']
if self.debit:
changes['credit'] = Decimal('0.0')
return changes
2012-09-24 22:17:29 +02:00
def on_change_credit(self):
changes = {}
Journal = Pool().get('account.journal')
if self.journal or Transaction().context.get('journal'):
journal = self.journal or Journal(Transaction().context['journal'])
if journal.type in ('expense', 'revenue'):
2012-09-24 22:17:29 +02:00
changes['tax_lines'] = self._compute_tax_lines(journal.type)
if not changes['tax_lines']:
del changes['tax_lines']
if self.credit:
changes['debit'] = Decimal('0.0')
return changes
2012-09-24 22:17:29 +02:00
def on_change_account(self):
Journal = Pool().get('account.journal')
2008-09-22 18:23:05 +02:00
2012-09-24 22:17:29 +02:00
changes = {}
2010-08-19 22:02:00 +02:00
if Transaction().context.get('journal'):
2012-09-24 22:17:29 +02:00
journal = Journal(Transaction().context['journal'])
if journal.type in ('expense', 'revenue'):
2012-09-24 22:17:29 +02:00
changes['tax_lines'] = self._compute_tax_lines(journal.type)
if not changes['tax_lines']:
del changes['tax_lines']
2012-09-24 22:17:29 +02:00
if self.account:
changes['currency_digits'] = self.account.currency_digits
if self.account.second_currency:
changes['second_currency_digits'] = \
self.account.second_currency.digits
return changes
2012-09-24 22:17:29 +02:00
def _compute_tax_lines(self, journal_type):
res = {}
2011-07-03 13:18:40 +02:00
pool = Pool()
2012-09-24 22:17:29 +02:00
TaxCode = pool.get('account.tax.code')
Tax = pool.get('account.tax')
TaxLine = pool.get('account.tax.line')
2012-09-24 22:17:29 +02:00
if self.move:
#Only for first line
return res
2012-09-24 22:17:29 +02:00
if self.tax_lines:
res['remove'] = [x['id'] for x in self.tax_lines]
if self.account:
debit = self.debit or Decimal('0.0')
credit = self.credit or Decimal('0.0')
for tax in self.account.taxes:
if journal_type == 'revenue':
if debit:
2008-10-03 17:11:53 +02:00
key = 'credit_note'
else:
key = 'invoice'
else:
if debit:
key = 'invoice'
else:
2008-10-03 17:11:53 +02:00
key = 'credit_note'
base_amounts = {}
2012-09-24 22:17:29 +02:00
for tax_line in Tax.compute(self.account.taxes,
2010-08-19 22:02:00 +02:00
debit or credit, 1):
code_id = tax_line['tax'][key + '_base_code'].id
if not code_id:
continue
tax_id = tax_line['tax'].id
base_amounts.setdefault((code_id, tax_id), Decimal('0.0'))
base_amounts[code_id, tax_id] += tax_line['base'] * \
tax_line['tax'][key + '_tax_sign']
for code_id, tax_id in base_amounts:
if not base_amounts[code_id, tax_id]:
continue
2012-09-24 22:17:29 +02:00
value = TaxLine.default_get(TaxLine._fields.keys())
value.update({
'amount': base_amounts[code_id, tax_id],
2012-09-24 22:17:29 +02:00
'currency_digits': self.account.currency_digits,
'code': code_id,
2012-09-24 22:17:29 +02:00
'code.rec_name': TaxCode(code_id).rec_name,
'tax': tax_id,
2012-09-24 22:17:29 +02:00
'tax.rec_name': Tax(tax_id).rec_name,
})
res.setdefault('add', []).append(value)
return res
2012-09-24 22:17:29 +02:00
def on_change_party(self):
Journal = Pool().get('account.journal')
2010-08-19 22:02:00 +02:00
cursor = Transaction().cursor
res = {}
2012-09-24 22:17:29 +02:00
if (not self.party) or self.account:
return res
2012-09-24 22:17:29 +02:00
if not self.party.account_receivable \
or not self.party.account_payable:
return res
if self.party and (not self.debit) and (not self.credit):
type_name = FIELDS[self.__class__.debit._type].sql_type(
self.__class__.debit)[0]
2008-03-19 22:13:51 +01:00
query = 'SELECT ' \
'CAST(COALESCE(SUM(' \
2008-03-19 22:13:51 +01:00
'(COALESCE(debit, 0) - COALESCE(credit, 0))' \
'), 0) AS ' + type_name + ') ' \
2008-03-19 22:13:51 +01:00
'FROM account_move_line ' \
'WHERE reconciliation IS NULL ' \
2008-05-21 18:13:49 +02:00
'AND party = %s ' \
2008-03-19 22:13:51 +01:00
'AND account = %s'
2012-09-24 22:17:29 +02:00
cursor.execute(query,
(self.party.id, self.party.account_receivable.id))
2008-03-19 22:13:51 +01:00
amount = cursor.fetchone()[0]
2009-09-22 16:08:11 +02:00
# SQLite uses float for SUM
if not isinstance(amount, Decimal):
2011-10-28 10:28:26 +02:00
amount = Decimal(str(amount))
2012-09-24 22:17:29 +02:00
if not self.party.account_receivable.currency.is_zero(amount):
if amount > Decimal('0.0'):
2012-09-24 22:17:29 +02:00
res['credit'] = \
self.party.account_receivable.currency.round(amount)
2008-03-19 22:13:51 +01:00
res['debit'] = Decimal('0.0')
else:
res['credit'] = Decimal('0.0')
2012-09-24 22:17:29 +02:00
res['debit'] = \
- self.party.account_receivable.currency.round(amount)
res['account'] = self.party.account_receivable.id
res['account.rec_name'] = \
self.party.account_receivable.rec_name
2008-03-19 22:13:51 +01:00
else:
2012-09-24 22:17:29 +02:00
cursor.execute(query,
(self.party.id, self.party.account_payable.id))
2008-03-19 22:13:51 +01:00
amount = cursor.fetchone()[0]
2012-09-24 22:17:29 +02:00
if not self.party.account_payable.currency.is_zero(amount):
if amount > Decimal('0.0'):
2012-09-24 22:17:29 +02:00
res['credit'] = \
self.party.account_payable.currency.round(amount)
2008-03-19 22:13:51 +01:00
res['debit'] = Decimal('0.0')
else:
res['credit'] = Decimal('0.0')
2012-09-24 22:17:29 +02:00
res['debit'] = \
- self.party.account_payable.currency.round(amount)
res['account'] = self.party.account_payable.id
res['account.rec_name'] = \
self.party.account_payable.rec_name
2008-03-19 22:13:51 +01:00
2012-09-24 22:17:29 +02:00
if self.party and self.debit:
if self.debit > Decimal('0.0'):
if 'account' not in res:
2012-09-24 22:17:29 +02:00
res['account'] = self.party.account_receivable.id
res['account.rec_name'] = \
self.party.account_receivable.rec_name
2008-03-19 22:13:51 +01:00
else:
if 'account' not in res:
2012-09-24 22:17:29 +02:00
res['account'] = self.party.account_payable.id
res['account.rec_name'] = \
self.party.account_payable.rec_name
2008-03-19 22:13:51 +01:00
2012-09-24 22:17:29 +02:00
if self.party and self.credit:
if self.credit > Decimal('0.0'):
if 'account' not in res:
2012-09-24 22:17:29 +02:00
res['account'] = self.party.account_payable.id
res['account.rec_name'] = \
self.party.account_payable.rec_name
2008-03-19 22:13:51 +01:00
else:
if 'account' not in res:
2012-09-24 22:17:29 +02:00
res['account'] = self.party.account_receivable.id
res['account.rec_name'] = \
self.party.account_receivable.rec_name
2008-03-19 22:13:51 +01:00
2012-09-24 22:17:29 +02:00
journal = (self.journal
or Journal(Transaction().context.get('journal')))
if journal and self.party:
if journal.type == 'revenue':
if 'account' not in res:
2012-09-24 22:17:29 +02:00
res['account'] = self.party.account_receivable.id
res['account.rec_name'] = \
self.party.account_receivable.rec_name
elif journal.type == 'expense':
if 'account' not in res:
2012-09-24 22:17:29 +02:00
res['account'] = self.party.account_payable.id
res['account.rec_name'] = \
self.party.account_payable.rec_name
return res
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
def get_move_field(self, name):
if name == 'move_state':
name = 'state'
if name in ('date', 'state'):
2012-09-24 22:17:29 +02:00
return getattr(self.move, name)
elif name == 'origin':
2012-10-16 16:29:47 +02:00
origin = getattr(self.move, name)
if origin:
return str(origin)
return None
2012-09-24 22:17:29 +02:00
else:
return getattr(self.move, name).id
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def set_move_field(cls, lines, name, value):
if name == 'move_state':
name = 'state'
if not value:
return
2012-09-24 22:17:29 +02:00
Move = Pool().get('account.move')
Move.write([line.move for line in lines], {
name: value,
})
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def search_move_field(cls, name, clause):
if name == 'move_state':
name = 'state'
return [('move.' + name,) + tuple(clause[1:])]
2012-09-24 22:17:29 +02:00
@classmethod
def query_get(cls, obj='l'):
2008-03-17 18:32:06 +01:00
'''
2008-09-19 15:00:26 +02:00
Return SQL clause and fiscal years for account move line
depending of the context.
2012-09-24 22:17:29 +02:00
obj is the SQL alias of account_move_line in the query
2008-03-17 18:32:06 +01:00
'''
2012-09-24 22:17:29 +02:00
FiscalYear = Pool().get('account.fiscalyear')
2010-08-19 22:02:00 +02:00
if Transaction().context.get('date'):
time.strptime(str(Transaction().context['date']), '%Y-%m-%d')
2012-09-24 22:17:29 +02:00
fiscalyears = FiscalYear.search([
('start_date', '<=', Transaction().context['date']),
('end_date', '>=', Transaction().context['date']),
], limit=1)
2012-09-24 22:17:29 +02:00
fiscalyear_id = fiscalyears and fiscalyears[0].id or 0
2010-08-19 22:02:00 +02:00
if Transaction().context.get('posted'):
2012-09-29 15:33:21 +02:00
return (obj + '.state != \'draft\' ' \
'AND ' + obj + '.move IN (' \
'SELECT m.id FROM account_move AS m, ' \
'account_period AS p ' \
'WHERE m.period = p.id ' \
'AND p.fiscalyear = ' + \
str(fiscalyear_id) + ' ' \
2009-04-14 19:49:56 +02:00
'AND m.date <= date(\'' + \
2010-08-19 22:02:00 +02:00
str(Transaction().context['date']) + \
'\') ' \
'AND m.state = \'posted\' ' \
2012-09-24 22:17:29 +02:00
')', [f.id for f in fiscalyears])
else:
2012-09-29 15:33:21 +02:00
return (obj + '.state != \'draft\' ' \
'AND ' + obj + '.move IN (' \
'SELECT m.id FROM account_move AS m, ' \
'account_period AS p ' \
'WHERE m.period = p.id ' \
'AND p.fiscalyear = ' + \
str(fiscalyear_id) + ' ' \
2009-04-14 19:49:56 +02:00
'AND m.date <= date(\'' + \
2010-08-19 22:02:00 +02:00
str(Transaction().context['date']) + \
'\')' \
2012-09-24 22:17:29 +02:00
')', [f.id for f in fiscalyears])
2010-08-19 22:02:00 +02:00
if Transaction().context.get('periods'):
if Transaction().context.get('fiscalyear'):
fiscalyear_ids = [int(Transaction().context['fiscalyear'])]
else:
fiscalyear_ids = []
2010-08-19 22:02:00 +02:00
ids = ','.join(
str(int(x)) for x in Transaction().context['periods'])
if Transaction().context.get('posted'):
2012-09-29 15:33:21 +02:00
return (obj + '.state != \'draft\' '
2012-04-03 20:06:15 +02:00
'AND ' + obj + '.move IN ('
'SELECT id FROM account_move '
'WHERE period IN (' + ids + ') '
'AND state = \'posted\' '
')', fiscalyear_ids)
2008-03-28 17:25:14 +01:00
else:
2012-09-29 15:33:21 +02:00
return (obj + '.state != \'draft\' '
2012-04-03 20:06:15 +02:00
'AND ' + obj + '.move IN ('
'SELECT id FROM account_move '
'WHERE period IN (' + ids + ')'
')', fiscalyear_ids)
2008-03-17 18:32:06 +01:00
else:
if not Transaction().context.get('fiscalyear'):
2012-09-24 22:17:29 +02:00
fiscalyears = FiscalYear.search([
('state', '=', 'open'),
])
2012-09-24 22:17:29 +02:00
fiscalyear_ids = [f.id for f in fiscalyears]
fiscalyear_clause = (','.join(
str(f.id) for f in fiscalyears)) or '0'
else:
fiscalyear_ids = [int(Transaction().context.get('fiscalyear'))]
fiscalyear_clause = '%s' % int(
Transaction().context.get('fiscalyear'))
2010-08-19 22:02:00 +02:00
if Transaction().context.get('posted'):
2012-09-29 15:33:21 +02:00
return (obj + '.state != \'draft\' '
2012-04-03 20:06:15 +02:00
'AND ' + obj + '.move IN ('
'SELECT id FROM account_move '
'WHERE period IN ('
'SELECT id FROM account_period '
'WHERE fiscalyear IN (' + fiscalyear_clause + ')'
') '
'AND state = \'posted\' '
')', fiscalyear_ids)
2008-03-28 17:25:14 +01:00
else:
2012-09-29 15:33:21 +02:00
return (obj + '.state != \'draft\' '
2012-04-03 20:06:15 +02:00
'AND ' + obj + '.move IN ('
'SELECT id FROM account_move '
'WHERE period IN ('
'SELECT id FROM account_period '
'WHERE fiscalyear IN (' + fiscalyear_clause + ')'
')'
')', fiscalyear_ids)
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def on_write(cls, lines):
return list(set(l.id for line in lines for l in line.move.lines))
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
def check_account(self):
if self.account.kind in ('view',):
return False
if not self.account.active:
return False
2008-03-17 18:32:06 +01:00
return True
2012-09-24 22:17:29 +02:00
@classmethod
def check_journal_period_modify(cls, period, journal):
2008-03-17 18:32:06 +01:00
'''
Check if the lines can be modified or created for the journal - period
and if there is no journal - period, create it
'''
2012-09-24 22:17:29 +02:00
JournalPeriod = Pool().get('account.journal.period')
journal_periods = JournalPeriod.search([
('journal', '=', journal.id),
('period', '=', period.id),
], limit=1)
if journal_periods:
journal_period, = journal_periods
2008-03-17 18:32:06 +01:00
if journal_period.state == 'close':
2012-09-24 22:17:29 +02:00
cls.raise_user_error('add_modify_closed_journal_period')
2008-03-17 18:32:06 +01:00
else:
2012-09-24 22:17:29 +02:00
JournalPeriod.create({
'name': journal.name + ' - ' + period.name,
'journal': journal.id,
'period': period.id,
})
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def check_modify(cls, lines):
2008-03-17 18:32:06 +01:00
'''
Check if the lines can be modified
'''
journal_period_done = []
2012-09-24 22:17:29 +02:00
for line in lines:
2008-03-17 18:32:06 +01:00
if line.move.state == 'posted':
2012-09-24 22:17:29 +02:00
cls.raise_user_error('modify_posted_move')
2008-03-19 22:13:51 +01:00
if line.reconciliation:
2012-09-24 22:17:29 +02:00
cls.raise_user_error('modify_reconciled')
2008-03-17 18:32:06 +01:00
journal_period = (line.journal.id, line.period.id)
if journal_period not in journal_period_done:
2012-09-24 22:17:29 +02:00
cls.check_journal_period_modify(line.period,
line.journal)
2008-03-17 18:32:06 +01:00
journal_period_done.append(journal_period)
2012-09-24 22:17:29 +02:00
@classmethod
def delete(cls, lines):
Move = Pool().get('account.move')
cls.check_modify(lines)
moves = [x.move for x in lines]
super(Line, cls).delete(lines)
Move.validate(moves)
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def write(cls, lines, vals):
Move = Pool().get('account.move')
if len(vals) > 1 or 'reconciliation' not in vals:
2012-09-24 22:17:29 +02:00
cls.check_modify(lines)
moves = [x.move for x in lines]
super(Line, cls).write(lines, vals)
2010-08-19 22:02:00 +02:00
Transaction().timestamp = {}
2008-03-17 18:32:06 +01:00
for line in lines:
2012-09-24 22:17:29 +02:00
if line.move not in moves:
moves.append(line.move)
Move.validate(moves)
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def create(cls, vals):
pool = Pool()
Journal = pool.get('account.journal')
Move = pool.get('account.move')
2008-03-17 18:32:06 +01:00
vals = vals.copy()
if not vals.get('move'):
2010-08-19 22:02:00 +02:00
journal_id = (vals.get('journal')
or Transaction().context.get('journal'))
2008-03-17 18:32:06 +01:00
if not journal_id:
2012-09-24 22:17:29 +02:00
cls.raise_user_error('no_journal')
journal = Journal(journal_id)
2008-03-17 18:32:06 +01:00
if journal.centralised:
2012-09-24 22:17:29 +02:00
moves = Move.search([
('period', '=', vals.get('period')
or Transaction().context.get('period')),
('journal', '=', journal_id),
('state', '!=', 'posted'),
], limit=1)
if moves:
vals['move'] = moves[0].id
if not vals.get('move'):
2012-09-24 22:17:29 +02:00
vals['move'] = Move.create({
'period': (vals.get('period')
or Transaction().context.get('period')),
'journal': journal_id,
'date': vals.get('date'),
}).id
line = super(Line, cls).create(vals)
cls.check_journal_period_modify(line.period, line.journal)
Move.validate([line.move])
return line
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def copy(cls, lines, default=None):
if default is None:
default = {}
if 'move' not in default:
2012-03-27 10:43:03 +02:00
default['move'] = None
if 'reconciliation' not in default:
2012-03-27 10:43:03 +02:00
default['reconciliation'] = None
2012-09-24 22:17:29 +02:00
return super(Line, cls).copy(lines, default=default)
2012-09-24 22:17:29 +02:00
@classmethod
def view_header_get(cls, value, view_type='form'):
JournalPeriod = Pool().get('account.journal.period')
2010-08-19 22:02:00 +02:00
if (not Transaction().context.get('journal')
or not Transaction().context.get('period')):
2009-02-02 13:09:08 +01:00
return value
2012-09-24 22:17:29 +02:00
journal_periods = JournalPeriod.search([
('journal', '=', Transaction().context['journal']),
('period', '=', Transaction().context['period']),
], limit=1)
if not journal_periods:
return value
2012-09-24 22:17:29 +02:00
journal_period, = journal_periods
return value + ': ' + journal_period.rec_name
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def fields_view_get(cls, view_id=None, view_type='form'):
Journal = Pool().get('account.journal')
result = super(Line, cls).fields_view_get(view_id=view_id,
view_type=view_type)
2010-08-19 22:02:00 +02:00
if view_type == 'tree' and 'journal' in Transaction().context:
2012-09-24 22:17:29 +02:00
title = cls.view_header_get('', view_type=view_type)
journal = Journal(Transaction().context['journal'])
2008-03-17 18:32:06 +01:00
if not journal.view:
return result
xml = '<?xml version="1.0"?>\n' \
'<tree string="%s" editable="top" on_write="on_write" ' \
2009-02-02 13:09:08 +01:00
'colors="red:state==\'draft\'">\n' % title
fields = set()
2008-03-17 18:32:06 +01:00
for column in journal.view.columns:
fields.add(column.field.name)
2008-03-17 18:32:06 +01:00
attrs = []
if column.field.name == 'debit':
2008-03-18 17:30:54 +01:00
attrs.append('sum="Debit"')
2008-03-17 18:32:06 +01:00
elif column.field.name == 'credit':
2008-03-18 17:30:54 +01:00
attrs.append('sum="Credit"')
2008-03-17 18:32:06 +01:00
if column.readonly:
attrs.append('readonly="1"')
if column.required:
attrs.append('required="1"')
else:
attrs.append('required="0"')
2012-04-03 20:06:15 +02:00
xml += ('<field name="%s" %s/>\n'
% (column.field.name, ' '.join(attrs)))
2012-09-24 22:17:29 +02:00
for depend in getattr(cls, column.field.name).depends:
fields.add(depend)
fields.add('state')
2008-03-17 18:32:06 +01:00
xml += '</tree>'
result['arch'] = xml
2012-09-24 22:17:29 +02:00
result['fields'] = cls.fields_get(fields_names=list(fields))
2008-03-17 18:32:06 +01:00
return result
2012-09-24 22:17:29 +02:00
@classmethod
def reconcile(cls, lines, journal=None, date=None, account=None):
2011-07-03 13:18:40 +02:00
pool = Pool()
2012-09-24 22:17:29 +02:00
Move = pool.get('account.move')
Reconciliation = pool.get('account.move.reconciliation')
Period = pool.get('account.period')
Date = pool.get('ir.date')
2012-09-24 22:17:29 +02:00
for line in lines:
2008-11-13 10:48:40 +01:00
if line.reconciliation:
2012-09-24 22:17:29 +02:00
cls.raise_user_error('already_reconciled',
2010-08-19 22:02:00 +02:00
error_args=(line.name, line.id,))
2008-11-13 10:48:40 +01:00
2012-09-24 22:17:29 +02:00
lines = lines[:]
if journal and account:
if not date:
2012-09-24 22:17:29 +02:00
date = Date.today()
2008-03-19 22:13:51 +01:00
account = None
amount = Decimal('0.0')
2012-09-24 22:17:29 +02:00
for line in lines:
2008-03-19 22:13:51 +01:00
amount += line.debit - line.credit
if not account:
account = line.account
2012-09-24 22:17:29 +02:00
amount = account.currency.round(amount)
period_id = Period.find(account.company.id, date=date)
move = Move.create({
'journal': journal.id,
2008-03-19 22:13:51 +01:00
'period': period_id,
'date': date,
2008-03-19 22:13:51 +01:00
'lines': [
2008-03-25 11:30:13 +01:00
('create', {
2008-03-19 22:13:51 +01:00
'account': account.id,
'debit': amount < Decimal('0.0') and - amount \
or Decimal('0.0'),
'credit': amount > Decimal('0.0') and amount \
or Decimal('0.0'),
2008-03-19 22:13:51 +01:00
}),
2008-03-25 11:30:13 +01:00
('create', {
2012-09-24 22:17:29 +02:00
'account': account.id,
'debit': amount > Decimal('0.0') and amount \
or Decimal('0.0'),
'credit': amount < Decimal('0.0') and - amount \
or Decimal('0.0'),
2008-03-19 22:13:51 +01:00
}),
],
2010-08-19 22:02:00 +02:00
})
2012-09-24 22:17:29 +02:00
lines += cls.search([
('move', '=', move.id),
2008-03-19 22:13:51 +01:00
('account', '=', account.id),
('debit', '=', amount < Decimal('0.0') and - amount \
or Decimal('0.0')),
('credit', '=', amount > Decimal('0.0') and amount \
or Decimal('0.0')),
2010-08-19 22:02:00 +02:00
], limit=1)
2012-09-24 22:17:29 +02:00
return Reconciliation.create({
'lines': [('add', [x.id for x in lines])],
})
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
class Move2:
__name__ = 'account.move'
2008-03-28 12:44:45 +01:00
centralised_line = fields.Many2One('account.move.line', 'Centralised Line',
readonly=True)
2009-02-28 16:57:10 +01:00
class OpenJournalAsk(ModelView):
'Open Journal Ask'
2012-09-24 22:17:29 +02:00
__name__ = 'account.move.open_journal.ask'
2008-03-17 18:32:06 +01:00
journal = fields.Many2One('account.journal', 'Journal', required=True)
period = fields.Many2One('account.period', 'Period', required=True,
2011-08-21 11:20:29 +02:00
domain=[
('state', '!=', 'close'),
('fiscalyear.company.id', '=',
Eval('context', {}).get('company', 0)),
2010-01-20 10:56:33 +01:00
])
2008-03-17 18:32:06 +01:00
2012-09-24 22:17:29 +02:00
@staticmethod
def default_period():
Period = Pool().get('account.period')
return Period.find(Transaction().context.get('company'),
2010-08-19 22:02:00 +02:00
exception=False)
2008-03-17 18:32:06 +01:00
class OpenJournal(Wizard):
'Open Journal'
2012-09-24 22:17:29 +02:00
__name__ = 'account.move.open_journal'
2012-01-02 17:54:33 +01:00
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')
2012-09-24 22:17:29 +02:00
def transition_start(self):
2012-04-03 20:06:15 +02:00
if (Transaction().context.get('active_model', '')
== 'account.journal.period'
2012-01-02 17:54:33 +01:00
and Transaction().context.get('active_id')):
return 'open_'
return 'ask'
2012-09-24 22:17:29 +02:00
def default_ask(self, fields):
JournalPeriod = Pool().get('account.journal.period')
2012-01-02 17:54:33 +01:00
if (Transaction().context.get('active_model', '') ==
'account.journal.period'
and Transaction().context.get('active_id')):
2012-09-24 22:17:29 +02:00
journal_period = JournalPeriod(Transaction().context['active_id'])
return {
'journal': journal_period.journal.id,
'period': journal_period.period.id,
2012-09-24 22:17:29 +02:00
}
return {}
2012-09-24 22:17:29 +02:00
def do_open_(self, action):
JournalPeriod = Pool().get('account.journal.period')
2012-01-02 17:54:33 +01:00
if (Transaction().context.get('active_model', '') ==
'account.journal.period'
and Transaction().context.get('active_id')):
2012-09-24 22:17:29 +02:00
journal_period = JournalPeriod(Transaction().context['active_id'])
journal = journal_period.journal
period = journal_period.period
else:
2012-09-24 22:17:29 +02:00
journal = self.ask.journal
period = self.ask.period
journal_periods = JournalPeriod.search([
('journal', '=', journal.id),
('period', '=', period.id),
], limit=1)
if not journal_periods:
journal_period = JournalPeriod.create({
2012-01-02 17:54:33 +01:00
'name': journal.name + ' - ' + period.name,
'journal': journal.id,
'period': period.id,
})
else:
2012-09-24 22:17:29 +02:00
journal_period, = journal_periods
2012-01-02 17:54:33 +01:00
action['name'] += ' - %s' % journal_period.rec_name
action['pyson_domain'] = PYSONEncoder().encode([
2012-09-24 22:17:29 +02:00
('journal', '=', journal.id),
('period', '=', period.id),
2012-01-02 17:54:33 +01:00
])
action['pyson_context'] = PYSONEncoder().encode({
2012-09-24 22:17:29 +02:00
'journal': journal.id,
'period': period.id,
2008-07-29 12:14:16 +02:00
})
2012-01-02 17:54:33 +01:00
return action, {}
2012-09-24 22:17:29 +02:00
def transition_open_(self):
2012-01-02 17:54:33 +01:00
return 'end'
2008-03-17 18:32:06 +01:00
2008-03-18 13:20:12 +01:00
class OpenAccount(Wizard):
'Open Account'
2012-09-24 22:17:29 +02:00
__name__ = 'account.move.open_account'
2012-01-02 17:54:33 +01:00
start_state = 'open_'
open_ = StateAction('account.act_move_line_form')
2008-03-18 13:20:12 +01:00
2012-09-24 22:17:29 +02:00
def do_open_(self, action):
FiscalYear = Pool().get('account.fiscalyear')
2008-03-18 13:20:12 +01:00
2010-08-19 22:02:00 +02:00
if not Transaction().context.get('fiscalyear'):
2012-09-24 22:17:29 +02:00
fiscalyears = FiscalYear.search([
('state', '=', 'open'),
])
2008-03-18 13:20:12 +01:00
else:
2012-09-24 22:17:29 +02:00
fiscalyears = [FiscalYear(Transaction().context['fiscalyear'])]
2008-03-18 13:20:12 +01:00
2012-09-24 22:17:29 +02:00
periods = [p for f in fiscalyears for p in f.periods]
2008-03-18 13:20:12 +01:00
2012-01-02 17:54:33 +01:00
action['pyson_domain'] = [
2012-09-24 22:17:29 +02:00
('period', 'in', [p.id for p in periods]),
2012-01-02 17:54:33 +01:00
('account', '=', Transaction().context['active_id']),
2008-03-28 17:39:54 +01:00
]
2010-08-19 22:02:00 +02:00
if Transaction().context.get('posted'):
2012-01-02 17:54:33 +01:00
action['pyson_domain'].append(('move.state', '=', 'posted'))
2012-08-16 15:55:45 +02:00
if Transaction().context.get('date'):
action['pyson_domain'].append(('move.date', '<=',
Transaction().context['date']))
2012-01-02 17:54:33 +01:00
action['pyson_domain'] = PYSONEncoder().encode(action['pyson_domain'])
action['pyson_context'] = PYSONEncoder().encode({
2010-08-19 22:02:00 +02:00
'fiscalyear': Transaction().context.get('fiscalyear'),
2010-01-20 10:56:33 +01:00
})
2012-01-02 17:54:33 +01:00
return action, {}
2008-03-18 13:20:12 +01:00
2008-03-18 23:40:57 +01:00
2009-02-28 16:57:10 +01:00
class ReconcileLinesWriteOff(ModelView):
2008-03-19 22:13:51 +01:00
'Reconcile Lines Write-Off'
2012-09-24 22:17:29 +02:00
__name__ = 'account.move.reconcile_lines.writeoff'
2008-03-19 22:13:51 +01:00
journal = fields.Many2One('account.journal', 'Journal', required=True)
date = fields.Date('Date', required=True)
2008-03-19 22:13:51 +01:00
account = fields.Many2One('account.account', 'Account', required=True,
domain=[('kind', '!=', 'view')])
2008-03-19 22:13:51 +01:00
2012-09-24 22:17:29 +02:00
@staticmethod
def default_date():
Date = Pool().get('ir.date')
return Date.today()
2008-03-19 22:13:51 +01:00
class ReconcileLines(Wizard):
'Reconcile Lines'
2012-09-24 22:17:29 +02:00
__name__ = 'account.move.reconcile_lines'
2012-01-02 17:54:33 +01:00
start = StateTransition()
writeoff = StateView('account.move.reconcile_lines.writeoff',
'account.reconcile_lines_writeoff_view_form', [
Button('Cancel', 'end', 'tryton-cancel'),
Button('Reconcile', 'reconcile', 'tryton-ok', default=True),
])
reconcile = StateTransition()
2012-09-24 22:17:29 +02:00
def transition_start(self):
Line = Pool().get('account.move.line')
2008-03-19 22:13:51 +01:00
company = None
amount = Decimal('0.0')
2012-09-24 22:17:29 +02:00
for line in Line.browse(Transaction().context['active_ids']):
2008-03-19 22:13:51 +01:00
amount += line.debit - line.credit
if not company:
company = line.account.company
if not company:
return 'end'
2012-09-24 22:17:29 +02:00
if company.currency.is_zero(amount):
2008-03-19 22:13:51 +01:00
return 'reconcile'
return 'writeoff'
2012-09-24 22:17:29 +02:00
def transition_reconcile(self):
Line = Pool().get('account.move.line')
2008-03-19 22:13:51 +01:00
2012-09-24 22:17:29 +02:00
journal = None
2012-03-27 10:43:03 +02:00
date = None
2012-09-24 22:17:29 +02:00
account = None
if self.writeoff.journal:
journal = self.writeoff.journal
if self.writeoff.date:
date = self.writeoff.date
if self.writeoff.account:
account = self.writeoff.account
Line.reconcile(Line.browse(Transaction().context['active_ids']),
journal, date, account)
2012-01-02 17:54:33 +01:00
return 'end'
2008-03-19 22:13:51 +01:00
2012-01-02 17:54:33 +01:00
class UnreconcileLinesStart(ModelView):
'Unreconcile Lines'
2012-09-24 22:17:29 +02:00
__name__ = 'account.move.unreconcile_lines.start'
class UnreconcileLines(Wizard):
'Unreconcile Lines'
2012-09-24 22:17:29 +02:00
__name__ = 'account.move.unreconcile_lines'
2012-03-25 00:17:23 +01:00
start_state = 'unreconcile'
2012-01-02 17:54:33 +01:00
unreconcile = StateTransition()
2012-09-24 22:17:29 +02:00
def transition_unreconcile(self):
pool = Pool()
Line = pool.get('account.move.line')
Reconciliation = pool.get('account.move.reconciliation')
2012-09-24 22:17:29 +02:00
lines = Line.browse(Transaction().context['active_ids'])
reconciliations = [x.reconciliation for x in lines if x.reconciliation]
if reconciliations:
Reconciliation.delete(reconciliations)
2012-01-02 17:54:33 +01:00
return 'end'
2012-01-02 17:54:33 +01:00
class OpenReconcileLinesStart(ModelView):
'Open Reconcile Lines'
2012-09-24 22:17:29 +02:00
__name__ = 'account.move.open_reconcile_lines.start'
2008-03-19 22:13:51 +01:00
account = fields.Many2One('account.account', 'Account', required=True,
domain=[('kind', '!=', 'view'), ('reconcile', '=', True)])
2008-03-19 22:13:51 +01:00
class OpenReconcileLines(Wizard):
'Open Reconcile Lines'
2012-09-24 22:17:29 +02:00
__name__ = 'account.move.open_reconcile_lines'
2012-01-02 17:54:33 +01:00
start = StateView('account.move.open_reconcile_lines.start',
'account.open_reconcile_lines_start_view_form', [
Button('Cancel', 'end', 'tryton-cancel'),
Button('Open', 'open_', 'tryton-ok', default=True),
])
open_ = StateAction('account.act_move_line_form')
2012-09-24 22:17:29 +02:00
def do_open_(self, action):
2012-01-02 17:54:33 +01:00
action['pyson_domain'] = PYSONEncoder().encode([
2012-09-24 22:17:29 +02:00
('account', '=', self.start.account.id),
2012-03-27 10:43:03 +02:00
('reconciliation', '=', None),
2008-03-19 22:13:51 +01:00
])
2012-01-02 17:54:33 +01:00
return action, {}
2008-03-19 22:13:51 +01:00
2009-03-05 14:51:19 +01:00
class FiscalYearLine(ModelSQL):
2009-03-17 13:09:06 +01:00
'Fiscal Year - Move Line'
2012-09-24 22:17:29 +02:00
__name__ = 'account.fiscalyear-account.move.line'
2009-03-05 14:51:19 +01:00
_table = 'account_fiscalyear_line_rel'
2009-03-17 13:09:06 +01:00
fiscalyear = fields.Many2One('account.fiscalyear', 'Fiscal Year',
2012-03-05 10:52:56 +01:00
ondelete='CASCADE', select=True)
2009-03-05 14:51:19 +01:00
line = fields.Many2One('account.move.line', 'Line', ondelete='RESTRICT',
2012-03-05 10:52:56 +01:00
select=True, required=True)
2009-03-05 14:51:19 +01:00
2012-09-24 22:17:29 +02:00
class FiscalYear2:
__name__ = 'account.fiscalyear'
2009-03-05 14:51:19 +01:00
close_lines = fields.Many2Many('account.fiscalyear-account.move.line',
'fiscalyear', 'line', 'Close Lines')
2012-01-02 17:54:33 +01:00
class PrintGeneralJournalStart(ModelView):
'Print General Journal'
2012-09-24 22:17:29 +02:00
__name__ = 'account.move.print_general_journal.start'
2008-03-30 17:03:45 +02:00
from_date = fields.Date('From Date', required=True)
to_date = fields.Date('To Date', required=True)
company = fields.Many2One('company.company', 'Company', required=True)
2009-03-20 13:49:25 +01:00
posted = fields.Boolean('Posted Move', help='Show only posted move')
2008-03-30 17:03:45 +02:00
2012-09-24 22:17:29 +02:00
@staticmethod
def default_from_date():
Date = Pool().get('ir.date')
return datetime.date(Date.today().year, 1, 1)
2008-03-30 17:03:45 +02:00
2012-09-24 22:17:29 +02:00
@staticmethod
def default_to_date():
Date = Pool().get('ir.date')
return Date.today()
2008-03-30 17:03:45 +02:00
2012-09-24 22:17:29 +02:00
@staticmethod
def default_company():
2012-03-27 10:43:03 +02:00
return Transaction().context.get('company')
2008-03-30 17:03:45 +02:00
2012-09-24 22:17:29 +02:00
@staticmethod
def default_posted():
2008-03-30 17:03:45 +02:00
return False
class PrintGeneralJournal(Wizard):
'Print General Journal'
2012-09-24 22:17:29 +02:00
__name__ = 'account.move.print_general_journal'
2012-01-02 17:54:33 +01:00
start = StateView('account.move.print_general_journal.start',
'account.print_general_journal_start_view_form', [
Button('Cancel', 'end', 'tryton-cancel'),
Button('Print', 'print_', 'tryton-print', default=True),
])
print_ = StateAction('account.report_general_journal')
2012-09-24 22:17:29 +02:00
def do_print_(self, action):
2012-01-02 17:54:33 +01:00
data = {
2012-09-24 22:17:29 +02:00
'company': self.start.company.id,
'from_date': self.start.from_date,
'to_date': self.start.to_date,
'posted': self.start.posted,
2012-01-02 17:54:33 +01:00
}
return action, data
2008-03-30 17:03:45 +02:00
class GeneralJournal(Report):
2012-09-24 22:17:29 +02:00
__name__ = 'account.move.general_journal'
2008-03-30 17:03:45 +02:00
2012-09-24 22:17:29 +02:00
@classmethod
def _get_records(cls, ids, model, data):
Move = Pool().get('account.move')
2008-03-30 17:03:45 +02:00
clause = [
2012-01-02 17:54:33 +01:00
('date', '>=', data['from_date']),
('date', '<=', data['to_date']),
]
2012-01-02 17:54:33 +01:00
if data['posted']:
clause.append(('state', '=', 'posted'))
2012-09-24 22:17:29 +02:00
return Move.search(clause,
2012-09-29 15:33:21 +02:00
order=[('date', 'ASC'), ('id', 'ASC')])
2008-03-30 17:03:45 +02:00
2012-09-24 22:17:29 +02:00
@classmethod
def parse(cls, report, moves, data, localcontext):
Company = Pool().get('company.company')
2008-03-30 17:03:45 +02:00
2012-09-24 22:17:29 +02:00
company = Company(data['company'])
2008-03-30 17:03:45 +02:00
2010-08-19 22:02:00 +02:00
localcontext['company'] = company
localcontext['digits'] = company.currency.digits
2012-01-02 17:54:33 +01:00
localcontext['from_date'] = data['from_date']
localcontext['to_date'] = data['to_date']
2008-03-30 17:03:45 +02:00
2012-09-24 22:17:29 +02:00
return super(GeneralJournal, cls).parse(report, moves, data,
2012-01-02 17:54:33 +01:00
localcontext)