Merge pull request #34 from acsone/8.0-account_default_draft_move

8.0 Migration of account_constraints and account_default_draft_move
This commit is contained in:
Guewen Baconnier
2014-11-24 16:14:48 +01:00
29 changed files with 697 additions and 380 deletions

View File

@@ -1,258 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author Joel Grand-Guillaume. Copyright 2012 Camptocamp SA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import fields, orm, osv
from openerp.tools.translate import _
class AccountJournal(orm.Model):
_inherit = 'account.journal'
_columns = {
'allow_date_fy': fields.boolean('Check Date in Fiscal Year',
help='If set to True then do not '
'accept the entry if '
'the entry date is not into '
'the fiscal year dates'),
}
_defaults = {
'allow_date_fy': True,
}
class AccountMove(orm.Model):
_inherit = "account.move"
def _check_fiscal_year(self, cr, uid, ids):
for move in self.browse(cr, uid, ids):
if move.journal_id.allow_date_fy:
date_start = move.period_id.fiscalyear_id.date_start
date_stop = move.period_id.fiscalyear_id.date_stop
if not date_start <= move.date <= date_stop:
return False
return True
_constraints = [
(_check_fiscal_year,
'You cannot create entries with date not in the '
'fiscal year of the chosen period',
['line_id']),
]
class AccountMoveLine(orm.Model):
_inherit = 'account.move.line'
def _authorized_reconcile(self, vals):
""" Check if only reconcile_id and/or reconcile_partial_id are altered.
We cannot change other vals, but we should be able to write or unlink
those field.
e.g. when you want to manually unreconcile an entry
generated by an invoice
"""
if not vals:
return False
rec_keys = set(["reconcile_id", "reconcile_partial_id"])
write_keys = set(vals)
return rec_keys.issuperset(write_keys)
def _check_invoice_related_move(self, cr, uid, ids, vals=None,
context=None):
for line in self.browse(cr, uid, ids, context=context):
if line.invoice:
if self._authorized_reconcile(vals):
return True
err_msg = (_('Invoice name (id): %s (%s)') %
(line.invoice.name, line.invoice.id))
raise osv.except_osv(
_('Error'),
_('You cannot do this on an entry generated '
'by an invoice. You must change the related '
'invoice directly.\n%s.') % err_msg
)
return True
def _check_statement_related_move(self, cr, uid, ids, vals=None,
context=None):
for line in self.browse(cr, uid, ids, context=context):
if line.statement_id:
if self._authorized_reconcile(vals):
return True
err_msg = (_('Bank statement name (id): %s (%s)') %
(line.statement_id.name, line.statement_id.id))
raise osv.except_osv(
_('Error'),
_('You cannot do this on an entry generated '
'by a bank statement. You must change the related'
'bank statement directly.\n%s.') % err_msg
)
return True
def unlink(self, cr, uid, ids, context=None, check=True):
""" Add the following checks:
- Is the move related to an invoice
- Is the move related to a bank statement
- Is other values than reconcile_partial_id and/or
reconcile_id modified
In that case, we forbid the move to be deleted even if draft. We
should never delete directly a move line related or generated by
another object. This is mandatory if you use the module setting
all moves in draft (module: account_default_draft_move)
"""
if context is None:
context = {}
if not context.get('from_parent_object', False):
self._check_invoice_related_move(cr, uid, ids, context=context)
self._check_statement_related_move(cr, uid, ids, context=context)
return super(AccountMoveLine, self).unlink(cr, uid, ids,
context=context,
check=check)
def write(self, cr, uid, ids, vals, context=None, check=True,
update_check=True):
""" Add the following checks:
- Is the move related to an invoice
- Is the move related to a bank statement
- Is other values than reconcile_partial_id and/or
reconcile_id modified
In that case, we forbid the move to be modified even if draft.
We should never update directly a move line related or generated
by another object. This is mandatory if you use the module
setting all moves in draft (module: account_default_draft_move)
"""
if context is None:
context = {}
if not context.get('from_parent_object', False):
self._check_invoice_related_move(cr, uid, ids, vals,
context=context)
self._check_statement_related_move(cr, uid, ids, vals,
context=context)
return super(AccountMoveLine, self).write(
cr, uid, ids, vals,
context=context, check=check, update_check=update_check
)
def _check_currency_and_amount(self, cr, uid, ids, context=None):
for l in self.browse(cr, uid, ids, context=context):
# we check zero amount line
if not (l.debit and l.credit):
continue
if bool(l.currency_id) != bool(l.amount_currency):
return False
return True
def _check_currency_amount(self, cr, uid, ids, context=None):
for l in self.browse(cr, uid, ids, context=context):
if l.amount_currency:
if ((l.amount_currency > 0.0 and l.credit > 0.0) or
(l.amount_currency < 0.0 and l.debit > 0.0)):
return False
return True
def _check_currency_company(self, cr, uid, ids, context=None):
for l in self.browse(cr, uid, ids, context=context):
if l.currency_id.id == l.company_id.currency_id.id:
return False
return True
_constraints = [
(_check_currency_and_amount,
"You cannot create journal items with a secondary currency "
"without recording both 'currency' and 'amount currency' field.",
['currency_id', 'amount_currency']),
(_check_currency_amount,
"The amount expressed in the secondary currency must be positive "
"when journal item are debit and negatif when journal item are "
"credit.",
['amount_currency']),
(_check_currency_company,
"You can't provide a secondary currency if "
"the same than the company one.",
['currency_id']),
]
class AccountInvoice(orm.Model):
_inherit = "account.invoice"
def action_cancel(self, cr, uid, ids, context=None):
"""Override the method to add the key 'from_parent_object' in
the context. This is to allow to delete move line related to
invoice through the cancel button.
"""
if context is None:
context = {}
else:
context = context.copy()
context['from_parent_object'] = True
return super(AccountInvoice, self).action_cancel(cr, uid, ids,
context=context)
def action_move_create(self, cr, uid, ids, context=None):
"""Override the method to add the key 'from_parent_object' in
the context."""
if context is None:
context = {}
else:
context = context.copy()
context['from_parent_object'] = True
return super(AccountInvoice, self).action_move_create(cr, uid, ids,
context=context)
class AccountBankStatement(orm.Model):
_inherit = "account.bank.statement"
def button_cancel(self, cr, uid, ids, context=None):
"""Override the method to add the key 'from_parent_object' in
the context. This is to allow to delete move line related to
bank statement through the cancel button.
"""
if context is None:
context = {}
else:
context = context.copy()
context['from_parent_object'] = True
return super(AccountBankStatement, self).button_cancel(cr, uid, ids,
context=context)
def create_move_from_st_line(self, cr, uid, st_line_id,
company_currency_id,
st_line_number, context=None):
"""Add the from_parent_object key in context in order to be able
to post the move.
"""
if context is None:
context = {}
else:
context = context.copy()
context['from_parent_object'] = True
return super(AccountBankStatement, self).create_move_from_st_line(
cr, uid, st_line_id, company_currency_id,
st_line_number, context=context
)

View File

@@ -1,64 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author Vincent Renaville/Joel Grand-Guillaume.
# Copyright 2012 Camptocamp SA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
##############################################################################
from openerp.osv import orm, osv
from tools.translate import _
class AccountInvoice(orm.Model):
_inherit = 'account.invoice'
def action_move_create(self, cr, uid, ids, context=None):
"""Set move line in draft state after creating them."""
res = super(AccountInvoice, self).action_move_create(cr, uid, ids,
context=context)
move_obj = self.pool.get('account.move')
for inv in self.browse(cr, uid, ids, context=context):
if inv.move_id:
move_obj.write(cr, uid, [inv.move_id.id], {'state': 'draft'},
context=context)
return res
class AccountMove(orm.Model):
_inherit = 'account.move'
def button_cancel(self, cr, uid, ids, context=None):
""" We rewrite function button_cancel, to allow invoice or bank
statement with linked draft moved
to be canceled
"""
for line in self.browse(cr, uid, ids, context=context):
if line.state == 'draft':
continue
else:
if not line.journal_id.update_posted:
raise osv.except_osv(
_('Error!'),
_('You cannot modify a posted entry of this journal.'
'First you should set the journal '
'to allow cancelling entries.')
)
if ids:
cr.execute('UPDATE account_move '
'SET state=%s '
'WHERE id IN %s', ('draft', tuple(ids),))
return True

View File

@@ -1,52 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author Vincent Renaville. Copyright 2012 Camptocamp SA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
##############################################################################
from openerp.osv import orm
class AccountBankStatement(orm.Model):
_inherit = "account.bank.statement"
def create_move_from_st_line(self, cr, uid,
st_line_id, company_currency_id,
st_line_number, context=None):
move_ids = super(AccountBankStatement, self).create_move_from_st_line(
cr, uid, st_line_id, company_currency_id,
st_line_number, context
)
# If a bank statement line is already linked to a voucher
# we received boolean instead of voucher move ids in move_ids
bank_st_line_obj = self.pool.get('account.bank.statement.line')
voucher_obj = self.pool.get('account.voucher')
st_line = bank_st_line_obj.browse(cr, uid, st_line_id, context=context)
if st_line.voucher_id:
v = voucher_obj.browse(cr, uid, st_line.voucher_id.id,
context=context)
move_ids = v.move_id.id
if not isinstance(move_ids, (tuple, list)):
move_ids = [move_ids]
# We receive the move created for the bank statement, we set it
# to draft
if move_ids:
move_obj = self.pool.get('account.move')
move_obj.write(cr, uid, move_ids,
{'state': 'draft'}, context=context)
return move_ids
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@@ -17,4 +17,4 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import account_constraints
from . import model

View File

@@ -51,8 +51,8 @@ Summary of constraints are:
invoice or a bank statement, no matter what the status of the move
(draft, validated or posted). This is useful in a standard context but
even more if you're using `account_default_draft_move`. This way you ensure
that the user cannot make mistakes even in draft state, he must pass
through the parent object to make his modification.
that the user cannot make mistakes even in draft state, he must pass through
the parent object to make his modification.
Contributors
* Stéphane Bidoul <stephane.bidoul@acsone.eu>
@@ -61,6 +61,7 @@ Summary of constraints are:
'website': 'http://www.camptocamp.com',
'data': [
'view/account_journal.xml',
'view/account_bank_statement.xml',
],
'installable': False,
'installable': True,
}

View File

@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
#
#
# Authors: Adrien Peiffer
# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu)
# All Rights Reserved
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs.
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contact a Free Software
# Service Company.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#
from . import account_bank_statement
from . import account_invoice
from . import account_journal
from . import account_move_line
from . import account_move

View File

@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author Joel Grand-Guillaume. Copyright 2012 Camptocamp SA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import models, api, fields
class AccountBankStatement(models.Model):
_inherit = "account.bank.statement"
@api.multi
def button_cancel(self):
"""Override the method to add the key 'from_parent_object' in
the context. This is to allow to delete move line related to
bank statement through the cancel button.
"""
self = self.with_context(from_parent_object=True)
return super(AccountBankStatement, self).button_cancel()
@api.multi
def button_confirm_bank(self):
"""Add the from_parent_object key in context in order to be able
to post the move.
"""
self = self.with_context(from_parent_object=True)
return super(AccountBankStatement, self).button_confirm_bank()
class AccountBankStatementLine(models.Model):
_inherit = "account.bank.statement.line"
state = fields.Selection(string='Statement state',
related='statement_id.state')
@api.multi
def cancel(self):
self = self.with_context(from_parent_object=True)
return super(AccountBankStatementLine, self).cancel()
@api.multi
def process_reconciliation(self, mv_line_dicts):
"""Add the from_parent_object key in context in order to be able
to balanced the move.
"""
self = self.with_context(from_parent_object=True)
return super(AccountBankStatementLine, self)\
.process_reconciliation(mv_line_dicts)

View File

@@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author Joel Grand-Guillaume. Copyright 2012 Camptocamp SA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import models, api
class AccountInvoice(models.Model):
_inherit = "account.invoice"
@api.multi
def action_cancel(self):
"""Override the method to add the key 'from_parent_object' in
the context. This is to allow to delete move line related to
invoice through the cancel button.
"""
self = self.with_context(from_parent_object=True)
return super(AccountInvoice, self).action_cancel()
@api.multi
def action_move_create(self):
"""Override the method to add the key 'from_parent_object' in
the context."""
self = self.with_context(from_parent_object=True)
return super(AccountInvoice, self).action_move_create()

View File

@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author Joel Grand-Guillaume. Copyright 2012 Camptocamp SA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##
from openerp import models, fields
class AccountJournal(models.Model):
_inherit = 'account.journal'
allow_date_fy = fields.Boolean(string='Check Date in Fiscal Year',
help='If set to True then do not '
'accept the entry if '
'the entry date is not into '
'the fiscal year dates',
default=True)

View File

@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author Joel Grand-Guillaume. Copyright 2012 Camptocamp SA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import models, api, exceptions, _
class AccountMove(models.Model):
_inherit = "account.move"
@api.constrains('journal_id', 'period_id', 'date')
def _check_fiscal_year(self):
for move in self:
if move.journal_id.allow_date_fy:
date_start = move.period_id.fiscalyear_id.date_start
date_stop = move.period_id.fiscalyear_id.date_stop
if not date_start <= move.date <= date_stop:
raise exceptions.Warning(
_('You cannot create entries with date not in the '
'fiscal year of the chosen period'))
return True

View File

@@ -0,0 +1,145 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author Joel Grand-Guillaume. Copyright 2012 Camptocamp SA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import models, api, exceptions, _
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
@api.multi
def _authorized_reconcile(self, vals):
""" Check if only reconcile_id and/or reconcile_partial_id are altered.
We cannot change other vals, but we should be able to write or unlink
those field (e.g. when you want to manually unreconcile an entry
generated by an invoice).
"""
if not vals:
return False
rec_keys = set(["reconcile_id", "reconcile_partial_id"])
write_keys = set(vals)
return rec_keys.issuperset(write_keys)
@api.multi
def _check_invoice_related_move(self, vals=None):
for line in self:
if line.invoice:
if self._authorized_reconcile(vals):
return True
err_msg = (_('Invoice name (id): %s (%s)') %
(line.invoice.name, line.invoice.id))
raise exceptions.Warning(
_('You cannot do this on an entry generated by an invoice.'
'You must '
'change the related invoice directly.\n%s.') % err_msg)
return True
@api.multi
def _check_statement_related_move(self, vals=None):
for line in self:
if line.statement_id:
if self._authorized_reconcile(vals):
return True
err_msg = (_('Bank statement name (id): %s (%s)') %
(line.statement_id.name, line.statement_id.id))
raise exceptions.Warning(
_('You cannot do this on an entry generated by a bank'
' statement. '
'You must change the related bank statement'
' directly.\n%s.') % err_msg)
return True
@api.cr_uid_ids_context
def unlink(self, cr, uid, ids, context=None, check=True):
""" Add the following checks:
- Is the move related to an invoice
- Is the move related to a bank statement
- Is other values than reconcile_partial_id and/or reconcile_id
modified
In that case, we forbid the move to be deleted even if draft. We
should never delete directly a move line related or generated by
another object. This is mandatory if you use the module setting
all moves in draft (module: account_default_draft_move)
"""
if not context.get('from_parent_object', False):
self._check_invoice_related_move(cr, uid, ids)
self._check_statement_related_move(cr, uid, ids)
return super(AccountMoveLine, self).unlink(cr, uid, ids,
context=context,
check=check)
@api.cr_uid_ids_context
def write(self, cr, uid, ids, vals, context=None, check=True,
update_check=True):
""" Add the following checks:
- Is the move related to an invoice
- Is the move related to a bank statement
- Is other values than reconcile_partial_id and/or reconcile_id
modified
In that case, we forbid the move to be modified even if draft.
We should never update directly a move line related or generated
by another object. This is mandatory if you use the module
setting all moves in draft (module: account_default_draft_move)
"""
if not context.get('from_parent_object', False):
self._check_invoice_related_move(cr, uid, ids, vals)
self._check_statement_related_move(cr, uid, ids, vals)
return super(AccountMoveLine, self).write(cr, uid, ids, vals,
context=context,
check=check,
update_check=update_check)
@api.constrains('currency_id', 'amount_currency')
def _check_currency_and_amount(self):
for l in self:
# we check zero amount line
if not (l.debit and l.credit):
continue
if bool(l.currency_id) != bool(l.amount_currency):
raise exceptions.Warning(
_("You cannot create journal items with a secondary "
"currency without recording both 'currency' and "
"'amount currency' field."))
return True
@api.constrains('amount_currency')
def _check_currency_amount(self):
for l in self:
if l.amount_currency:
if ((l.amount_currency > 0.0 and l.credit > 0.0) or
(l.amount_currency < 0.0 and l.debit > 0.0)):
raise exceptions.Warning(
_("The amount expressed in the secondary currency "
"must be positive when journal item are debit and "
"negatif when journal item are credit."))
return True
@api.constrains('currency_id')
def _check_currency_company(self):
for l in self:
if l.currency_id.id == l.company_id.currency_id.id:
raise exceptions.Warning(
_("You can't provide a secondary currency if the same "
"than the company one."))
return True

View File

@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
#
#
# Authors: Adrien Peiffer
# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu)
# All Rights Reserved
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs.
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contact a Free Software
# Service Company.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#
from . import test_account_constraints

View File

@@ -0,0 +1,97 @@
# -*- coding: utf-8 -*-
#
#
# Authors: Adrien Peiffer
# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu)
# All Rights Reserved
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs.
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contact a Free Software
# Service Company.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#
import openerp.tests.common as common
from datetime import datetime
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
from openerp import workflow, exceptions
DB = common.DB
ADMIN_USER_ID = common.ADMIN_USER_ID
def create_simple_invoice(self):
partner_id = self.ref('base.res_partner_2')
product_id = self.ref('product.product_product_4')
today = datetime.now()
journal_id = self.ref('account.sales_journal')
date = today.strftime(DEFAULT_SERVER_DATE_FORMAT)
return self.env['account.invoice']\
.create({'partner_id': partner_id,
'account_id':
self.ref('account.a_recv'),
'journal_id':
journal_id,
'date_invoice': date,
'invoice_line': [(0, 0, {'name': 'test',
'account_id':
self.ref('account.a_sale'),
'price_unit': 2000.00,
'quantity': 1,
'product_id': product_id,
}
)
],
})
class TestAccountConstraints(common.TransactionCase):
def setUp(self):
super(TestAccountConstraints, self).setUp()
def test_draft_move_invoice(self):
invoice = create_simple_invoice(self)
workflow.trg_validate(self.uid, 'account.invoice', invoice.id,
'invoice_open', self.cr)
move = invoice.move_id
move_lines = move.line_id
move.with_context({'from_parent_object': True})\
.write({'state': 'draft'})
self.assertRaises(exceptions.Warning, move_lines.write,
{'credit': 0.0})
def test_post_move_invoice_ref(self):
invoice = create_simple_invoice(self)
workflow.trg_validate(self.uid, 'account.invoice', invoice.id,
'invoice_open', self.cr)
move_lines = invoice.move_id.line_id
# here, normally no exception is raised in standard code.
# It's just to verify if it's
# possible to modify ref field in a post account_move_line
move_lines.with_context({'from_parent_object': True})\
.write({'ref': 'test'})
def test_post_move_invoice(self):
invoice = create_simple_invoice(self)
workflow.trg_validate(self.uid, 'account.invoice', invoice.id,
'invoice_open', self.cr)
move_lines = invoice.move_id.line_id
self.assertRaises(exceptions.Warning, move_lines.write,
{'ref': 'test'})

View File

@@ -0,0 +1,21 @@
<?xml version="1.0"?>
<openerp>
<data>
<!--
Since account_constraint forbids the deletion of account moves that
are linked to a bank statement, we add the possibility to delete them
from the bank statement itself, to let the user fix erroneous reconciles.
-->
<record id="bank_statement_cancel_form_inherit" model="ir.ui.view">
<field name="name">bank.statement.cancel.form.inherit</field>
<field name="model">account.bank.statement</field>
<field name="inherit_id" ref="account.view_bank_statement_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='bank_account_id']" position="after">
<field name="state" invisible="1"/>
<button name="cancel" attrs="{'invisible': ['|', ('journal_entry_id', '=', False), ('state', '=', 'confirm')]}" string="Cancel" type="object" icon="gtk-undo"/>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@@ -51,7 +51,7 @@ need to make a refund).
'website': 'http://www.camptocamp.com',
'data': ['account_view.xml',
'invoice_view.xml'],
'installable': False,
'active': False,
'installable': True,
'auto_install': False,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author Vincent Renaville/Joel Grand-Guillaume.Copyright 2012 Camptocamp SA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
##############################################################################
from openerp import models, api, exceptions, _
class AccountInvoice(models.Model):
_inherit = 'account.invoice'
@api.multi
def action_move_create(self):
"""Set move line in draft state after creating them."""
res = super(AccountInvoice, self).action_move_create()
for inv in self:
if inv.move_id:
inv.move_id.state = 'draft'
return res
class AccountMove(models.Model):
_inherit = 'account.move'
@api.multi
def button_cancel(self):
""" We rewrite function button_cancel, to allow invoice or bank
statement with linked draft moved
to be canceled """
for line in self:
if line.state == 'draft':
continue
else:
if not line.journal_id.update_posted:
raise exceptions.Warning(
_('You cannot modify a posted entry of this journal.'
'First you should set the journal to allow'
' cancelling entries.'))
if self:
self._cr.execute('UPDATE account_move '
'SET state=%s '
'WHERE id IN %s', ('draft', self.ids,))
return True
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author Vincent Renaville. Copyright 2012 Camptocamp SA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
##############################################################################
from openerp import models, api
class AccountBankStatement(models.Model):
_inherit = "account.bank.statement"
@api.multi
def button_confirm_bank(self):
res = super(AccountBankStatement, self).button_confirm_bank()
entries = self.mapped('line_ids.journal_entry_id')
entries.write({'state': 'draft'})
return res

View File

@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
#
#
# Authors: Adrien Peiffer
# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu)
# All Rights Reserved
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs.
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contact a Free Software
# Service Company.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#
from . import test_account_default_draft_move

View File

@@ -0,0 +1,73 @@
# -*- coding: utf-8 -*-
#
#
# Authors: Adrien Peiffer
# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu)
# All Rights Reserved
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs.
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contact a Free Software
# Service Company.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#
import openerp.tests.common as common
from datetime import datetime
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
from openerp import workflow
DB = common.DB
ADMIN_USER_ID = common.ADMIN_USER_ID
def create_simple_invoice(self):
partner_id = self.ref('base.res_partner_2')
product_id = self.ref('product.product_product_4')
today = datetime.now()
journal_id = self.ref('account.sales_journal')
date = today.strftime(DEFAULT_SERVER_DATE_FORMAT)
return self.env['account.invoice']\
.create({'partner_id': partner_id,
'account_id':
self.ref('account.a_recv'),
'journal_id':
journal_id,
'date_invoice': date,
'invoice_line': [(0, 0, {'name': 'test',
'account_id':
self.ref('account.a_sale'),
'price_unit': 2000.00,
'quantity': 1,
'product_id': product_id,
}
)
],
})
class TestAccountDefaultDraftMove(common.TransactionCase):
def setUp(self):
super(TestAccountDefaultDraftMove, self).setUp()
def test_draft_move_invoice(self):
invoice = create_simple_invoice(self)
workflow.trg_validate(self.uid, 'account.invoice', invoice.id,
'invoice_open', self.cr)
self.assertEqual(invoice.move_id.state, 'draft', 'State error!')