Merge pull request #52 from guewen/account_invoice_reference

Migration of account_invoice_reference
This commit is contained in:
Pedro M. Baeza
2014-12-15 09:33:33 +01:00
18 changed files with 186 additions and 106 deletions

View File

@@ -1,101 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier
# Copyright 2014 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 AccountMove(orm.Model):
_inherit = 'account.move'
def create(self, cr, uid, vals, context=None):
if context is None:
context = {}
# invoice from which the move is generated
invoice = context.get('invoice')
if invoice:
assert isinstance(invoice, orm.browse_record)
invoice_obj = self.pool['account.invoice']
ref = invoice_obj._ref_from_invoice(
cr, uid, invoice, context=context)
vals = vals.copy()
vals['ref'] = ref
move_id = super(AccountMove, self).create(cr, uid, vals,
context=context)
return move_id
class AccountInvoice(orm.Model):
_inherit = 'account.invoice'
def _ref_from_invoice(self, cr, uid, invoice, context=None):
if invoice.type in ('out_invoice', 'out_refund'):
return invoice.origin
elif invoice.type in ('in_invoice', 'in_refund'):
return invoice.supplier_invoice_number
def action_number(self, cr, uid, ids, context=None):
# force the number of the invoice to be updated for the
# subsequent browse
self.write(cr, uid, ids, {})
for invoice in self.browse(cr, uid, ids, context=context):
ref = self._ref_from_invoice(cr, uid, invoice, context=context)
if not ref:
ref = invoice.number
move_id = invoice.move_id.id if invoice.move_id else False
self.write(cr, uid, ids, {'internal_number': invoice.number},
context=context)
cr.execute('UPDATE account_move SET ref=%s '
'WHERE id=%s AND (ref is null OR ref = \'\')',
(ref, move_id))
cr.execute('UPDATE account_move_line SET ref=%s '
'WHERE move_id=%s AND (ref is null OR ref = \'\')',
(ref, move_id))
cr.execute(
'UPDATE account_analytic_line SET ref=%s '
'FROM account_move_line '
'WHERE account_move_line.move_id = %s '
'AND account_analytic_line.move_id = account_move_line.id',
(ref, move_id))
return True
def create(self, cr, uid, vals, context=None):
if (vals.get('supplier_invoice_reference') and not
vals.get('reference')):
vals['reference'] = vals['supplier_invoice_reference']
return super(AccountInvoice, self).create(cr, uid, vals,
context=context)
def write(self, cr, uid, ids, vals, context=None):
if vals.get('supplier_invoice_reference'):
if isinstance(ids, (int, long)):
ids = [ids]
for invoice in self.browse(cr, uid, ids, context=context):
if not invoice.reference:
locvals = vals.copy()
locvals['reference'] = vals['supplier_invoice_reference']
super(AccountInvoice, self).write(cr, uid, [invoice.id],
locvals, context=context)
return True
else:
return super(AccountInvoice, self).write(cr, uid, ids, vals,
context=context)

View File

@@ -20,3 +20,4 @@
##############################################################################
from . import account_move
from . import account_invoice

View File

@@ -39,10 +39,10 @@ origin, free reference) and above all, to understand which field will be
copied in the reference field of the move and move lines.
The approach here is to state simple rules with one concern: consistency.
The reference of the move lines must be the number of the document at their very
origin (number of a sales order, of an external document like a supplier
invoice, ...). The goal is for the accountant to be able to trace to the
source document from a ledger).
The reference of the move lines must be the number of the document at
their very origin (number of a sales order, of an external document
like a supplier invoice, ...). The goal is for the accountant to be
able to trace to the source document from a ledger).
The description of a line should always be... well, a description. Not a number
or a cryptic reference.
@@ -141,8 +141,9 @@ Information propagated to the move lines:
'test/out_refund_without_origin.yml',
'test/in_refund_with_supplier_number.yml',
'test/in_refund_without_supplier_number.yml',
'test/supplier_invoice_number.yml',
],
'installable': False,
'installable': True,
'auto_install': False,
}

View File

@@ -0,0 +1,90 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier
# Copyright 2014 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.v8
def _ref_from_invoice(self):
self.ensure_one()
if self.type in ('out_invoice', 'out_refund'):
return self.origin
elif self.type in ('in_invoice', 'in_refund'):
return self.supplier_invoice_number
@api.v7
def _ref_from_invoice(self, cr, uid, invoice, context=None):
return invoice._ref_from_invoice()
@api.multi
def action_number(self):
# force the number of the invoice to be updated for the
# subsequent browse
self.write({})
for invoice in self:
ref = invoice._ref_from_invoice()
if not ref:
ref = invoice.number
move_id = invoice.move_id.id if invoice.move_id else False
invoice.write({'internal_number': invoice.number})
cr = self._cr
cr.execute("UPDATE account_move SET ref=%s "
"WHERE id=%s AND (ref is null OR ref = '')",
(ref, move_id))
cr.execute("UPDATE account_move_line SET ref=%s "
"WHERE move_id=%s AND (ref is null OR ref = '')",
(ref, move_id))
cr.execute(
"UPDATE account_analytic_line SET ref=%s "
"FROM account_move_line "
"WHERE account_move_line.move_id = %s "
"AND account_analytic_line.move_id = account_move_line.id",
(ref, move_id))
self.invalidate_cache()
return True
@api.model
@api.returns('self', lambda value: value.id)
def create(self, vals):
if (vals.get('supplier_invoice_number') and not
vals.get('reference')):
vals = vals.copy()
vals['reference'] = vals['supplier_invoice_number']
return super(AccountInvoice, self).create(vals)
@api.multi
def write(self, vals):
if vals.get('supplier_invoice_number'):
for invoice in self:
loc_vals = None
if not invoice.reference:
loc_vals = vals.copy()
loc_vals['reference'] = vals['supplier_invoice_number']
super(AccountInvoice, invoice).write(loc_vals or vals)
return True
else:
return super(AccountInvoice, self).write(vals)

View File

@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier
# Copyright 2014 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 AccountMove(orm.Model):
_inherit = 'account.move'
def create(self, cr, uid, vals, context=None):
if context is None:
context = {}
# invoice from which the move is generated
invoice = context.get('invoice')
if invoice:
assert isinstance(invoice, orm.browse_record)
invoice_obj = self.pool['account.invoice']
ref = invoice_obj._ref_from_invoice(
cr, uid, invoice, context=context)
vals = vals.copy()
vals['ref'] = ref
move_id = super(AccountMove, self).create(cr, uid, vals,
context=context)
return move_id

View File

@@ -0,0 +1,47 @@
-
In order to check if the reference is populated from the supplier_invoice_number
I create an invoice.
-
!record {model: account.invoice, id: invoice_supplier_invoice_number, view: account.invoice_supplier_form}:
account_id: account.a_pay
check_total: 3000.0
company_id: base.main_company
currency_id: base.EUR
invoice_line:
- account_id: account.a_expense
name: '[PCSC234] PC Assemble SC234'
price_unit: 300.0
product_id: product.product_product_3
quantity: 10.0
uos_id: product.product_uom_unit
journal_id: account.expenses_journal
partner_id: base.res_partner_12
reference_type: none
supplier_invoice_number: ZZZ246
type: in_invoice
-
Set again the type of the invoice (not set on the first one...)
-
!record {model: account.invoice, id: invoice_supplier_invoice_number, view: account.invoice_supplier_form}:
type: in_invoice
-
Ensure that the reference is the same than the supplier_invoice_number
-
!assert {model: account.invoice, id: invoice_supplier_invoice_number}:
- reference == 'ZZZ246'
-
In order to check if the supplier_invoice_number is copied to the supplier_invoice_number
when the reference is empty, I empty the reference
-
!record {model: account.invoice, id: invoice_supplier_invoice_number, view: account.invoice_supplier_form}:
reference:
-
And I write a new supplier_invoice_number
-
!record {model: account.invoice, id: invoice_supplier_invoice_number, view: account.invoice_supplier_form}:
supplier_invoice_number: ABC789
-
Ensure that the reference is the same than the supplier_invoice_number
-
!assert {model: account.invoice, id: invoice_supplier_invoice_number}:
- reference == 'ABC789'