From 58825ab0b3615ea0a3feff58a5137c37a097b49f Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Thu, 9 Oct 2014 13:37:22 +0200 Subject: [PATCH 1/7] Move account_invoice_reference from __unported__ to the root folder --- .../__init__.py | 0 .../__openerp__.py | 0 .../account_invoice_view.xml | 0 .../account_move.py | 0 .../i18n/account_invoice_reference.pot | 0 .../i18n/es.po | 0 .../i18n/fr.po | 0 .../test/in_invoice_with_supplier_number.yml | 0 .../test/in_invoice_without_supplier_number.yml | 0 .../test/in_refund_with_supplier_number.yml | 0 .../test/in_refund_without_supplier_number.yml | 0 .../test/out_invoice_with_origin.yml | 0 .../test/out_invoice_without_origin.yml | 0 .../test/out_refund_with_origin.yml | 0 .../test/out_refund_without_origin.yml | 0 15 files changed, 0 insertions(+), 0 deletions(-) rename {__unported__/account_invoice_reference => account_invoice_reference}/__init__.py (100%) rename {__unported__/account_invoice_reference => account_invoice_reference}/__openerp__.py (100%) rename {__unported__/account_invoice_reference => account_invoice_reference}/account_invoice_view.xml (100%) rename {__unported__/account_invoice_reference => account_invoice_reference}/account_move.py (100%) rename {__unported__/account_invoice_reference => account_invoice_reference}/i18n/account_invoice_reference.pot (100%) rename {__unported__/account_invoice_reference => account_invoice_reference}/i18n/es.po (100%) rename {__unported__/account_invoice_reference => account_invoice_reference}/i18n/fr.po (100%) rename {__unported__/account_invoice_reference => account_invoice_reference}/test/in_invoice_with_supplier_number.yml (100%) rename {__unported__/account_invoice_reference => account_invoice_reference}/test/in_invoice_without_supplier_number.yml (100%) rename {__unported__/account_invoice_reference => account_invoice_reference}/test/in_refund_with_supplier_number.yml (100%) rename {__unported__/account_invoice_reference => account_invoice_reference}/test/in_refund_without_supplier_number.yml (100%) rename {__unported__/account_invoice_reference => account_invoice_reference}/test/out_invoice_with_origin.yml (100%) rename {__unported__/account_invoice_reference => account_invoice_reference}/test/out_invoice_without_origin.yml (100%) rename {__unported__/account_invoice_reference => account_invoice_reference}/test/out_refund_with_origin.yml (100%) rename {__unported__/account_invoice_reference => account_invoice_reference}/test/out_refund_without_origin.yml (100%) diff --git a/__unported__/account_invoice_reference/__init__.py b/account_invoice_reference/__init__.py similarity index 100% rename from __unported__/account_invoice_reference/__init__.py rename to account_invoice_reference/__init__.py diff --git a/__unported__/account_invoice_reference/__openerp__.py b/account_invoice_reference/__openerp__.py similarity index 100% rename from __unported__/account_invoice_reference/__openerp__.py rename to account_invoice_reference/__openerp__.py diff --git a/__unported__/account_invoice_reference/account_invoice_view.xml b/account_invoice_reference/account_invoice_view.xml similarity index 100% rename from __unported__/account_invoice_reference/account_invoice_view.xml rename to account_invoice_reference/account_invoice_view.xml diff --git a/__unported__/account_invoice_reference/account_move.py b/account_invoice_reference/account_move.py similarity index 100% rename from __unported__/account_invoice_reference/account_move.py rename to account_invoice_reference/account_move.py diff --git a/__unported__/account_invoice_reference/i18n/account_invoice_reference.pot b/account_invoice_reference/i18n/account_invoice_reference.pot similarity index 100% rename from __unported__/account_invoice_reference/i18n/account_invoice_reference.pot rename to account_invoice_reference/i18n/account_invoice_reference.pot diff --git a/__unported__/account_invoice_reference/i18n/es.po b/account_invoice_reference/i18n/es.po similarity index 100% rename from __unported__/account_invoice_reference/i18n/es.po rename to account_invoice_reference/i18n/es.po diff --git a/__unported__/account_invoice_reference/i18n/fr.po b/account_invoice_reference/i18n/fr.po similarity index 100% rename from __unported__/account_invoice_reference/i18n/fr.po rename to account_invoice_reference/i18n/fr.po diff --git a/__unported__/account_invoice_reference/test/in_invoice_with_supplier_number.yml b/account_invoice_reference/test/in_invoice_with_supplier_number.yml similarity index 100% rename from __unported__/account_invoice_reference/test/in_invoice_with_supplier_number.yml rename to account_invoice_reference/test/in_invoice_with_supplier_number.yml diff --git a/__unported__/account_invoice_reference/test/in_invoice_without_supplier_number.yml b/account_invoice_reference/test/in_invoice_without_supplier_number.yml similarity index 100% rename from __unported__/account_invoice_reference/test/in_invoice_without_supplier_number.yml rename to account_invoice_reference/test/in_invoice_without_supplier_number.yml diff --git a/__unported__/account_invoice_reference/test/in_refund_with_supplier_number.yml b/account_invoice_reference/test/in_refund_with_supplier_number.yml similarity index 100% rename from __unported__/account_invoice_reference/test/in_refund_with_supplier_number.yml rename to account_invoice_reference/test/in_refund_with_supplier_number.yml diff --git a/__unported__/account_invoice_reference/test/in_refund_without_supplier_number.yml b/account_invoice_reference/test/in_refund_without_supplier_number.yml similarity index 100% rename from __unported__/account_invoice_reference/test/in_refund_without_supplier_number.yml rename to account_invoice_reference/test/in_refund_without_supplier_number.yml diff --git a/__unported__/account_invoice_reference/test/out_invoice_with_origin.yml b/account_invoice_reference/test/out_invoice_with_origin.yml similarity index 100% rename from __unported__/account_invoice_reference/test/out_invoice_with_origin.yml rename to account_invoice_reference/test/out_invoice_with_origin.yml diff --git a/__unported__/account_invoice_reference/test/out_invoice_without_origin.yml b/account_invoice_reference/test/out_invoice_without_origin.yml similarity index 100% rename from __unported__/account_invoice_reference/test/out_invoice_without_origin.yml rename to account_invoice_reference/test/out_invoice_without_origin.yml diff --git a/__unported__/account_invoice_reference/test/out_refund_with_origin.yml b/account_invoice_reference/test/out_refund_with_origin.yml similarity index 100% rename from __unported__/account_invoice_reference/test/out_refund_with_origin.yml rename to account_invoice_reference/test/out_refund_with_origin.yml diff --git a/__unported__/account_invoice_reference/test/out_refund_without_origin.yml b/account_invoice_reference/test/out_refund_without_origin.yml similarity index 100% rename from __unported__/account_invoice_reference/test/out_refund_without_origin.yml rename to account_invoice_reference/test/out_refund_without_origin.yml From c5f7ac238322d7974eb4b1a62e1598041ec7e057 Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Thu, 9 Oct 2014 13:38:35 +0200 Subject: [PATCH 2/7] Set account_invoice_reference as installable --- account_invoice_reference/__openerp__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account_invoice_reference/__openerp__.py b/account_invoice_reference/__openerp__.py index 02ad451d..fc12a9ca 100644 --- a/account_invoice_reference/__openerp__.py +++ b/account_invoice_reference/__openerp__.py @@ -143,6 +143,6 @@ Information propagated to the move lines: 'test/in_refund_without_supplier_number.yml', ], - 'installable': False, + 'installable': True, 'auto_install': False, } From b3e278d3abf53bd4272a86928748f85ecdaf5cef Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Thu, 9 Oct 2014 13:39:47 +0200 Subject: [PATCH 3/7] Move the Model account.invoice in a python module with the same name --- account_invoice_reference/__init__.py | 1 + account_invoice_reference/account_invoice.py | 81 ++++++++++++++++++++ account_invoice_reference/account_move.py | 59 -------------- 3 files changed, 82 insertions(+), 59 deletions(-) create mode 100644 account_invoice_reference/account_invoice.py diff --git a/account_invoice_reference/__init__.py b/account_invoice_reference/__init__.py index ce74e081..d9829c7f 100644 --- a/account_invoice_reference/__init__.py +++ b/account_invoice_reference/__init__.py @@ -20,3 +20,4 @@ ############################################################################## from . import account_move +from . import account_invoice diff --git a/account_invoice_reference/account_invoice.py b/account_invoice_reference/account_invoice.py new file mode 100644 index 00000000..0fc78b27 --- /dev/null +++ b/account_invoice_reference/account_invoice.py @@ -0,0 +1,81 @@ +# -*- 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 . +# +############################################################################## + +from openerp.osv import orm + + +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) diff --git a/account_invoice_reference/account_move.py b/account_invoice_reference/account_move.py index b99689b8..746ac989 100644 --- a/account_invoice_reference/account_move.py +++ b/account_invoice_reference/account_move.py @@ -40,62 +40,3 @@ class AccountMove(orm.Model): 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) From a8ad844d485eb196bca29383031627bb4be05c57 Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Fri, 10 Oct 2014 10:58:41 +0200 Subject: [PATCH 4/7] Add tests that fail to check the copy of supplier_invoice_number to reference on create and write --- account_invoice_reference/__openerp__.py | 1 + .../test/supplier_invoice_number.yml | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 account_invoice_reference/test/supplier_invoice_number.yml diff --git a/account_invoice_reference/__openerp__.py b/account_invoice_reference/__openerp__.py index fc12a9ca..0211d207 100644 --- a/account_invoice_reference/__openerp__.py +++ b/account_invoice_reference/__openerp__.py @@ -141,6 +141,7 @@ 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': True, diff --git a/account_invoice_reference/test/supplier_invoice_number.yml b/account_invoice_reference/test/supplier_invoice_number.yml new file mode 100644 index 00000000..846fc63f --- /dev/null +++ b/account_invoice_reference/test/supplier_invoice_number.yml @@ -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' From b9e8b6a8b2cf0f7dde36e27c68ffc4f56a65a8e2 Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Fri, 10 Oct 2014 11:12:20 +0200 Subject: [PATCH 5/7] Make the new test passes, the fields is named supplier_invoice_number not supplier_invoice_reference --- account_invoice_reference/account_invoice.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/account_invoice_reference/account_invoice.py b/account_invoice_reference/account_invoice.py index 0fc78b27..deee487a 100644 --- a/account_invoice_reference/account_invoice.py +++ b/account_invoice_reference/account_invoice.py @@ -59,22 +59,23 @@ class AccountInvoice(orm.Model): return True def create(self, cr, uid, vals, context=None): - if (vals.get('supplier_invoice_reference') and not + if (vals.get('supplier_invoice_number') and not vals.get('reference')): - vals['reference'] = vals['supplier_invoice_reference'] + vals = vals.copy() + vals['reference'] = vals['supplier_invoice_number'] 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] + if vals.get('supplier_invoice_number'): for invoice in self.browse(cr, uid, ids, context=context): + loc_vals = None if not invoice.reference: - locvals = vals.copy() - locvals['reference'] = vals['supplier_invoice_reference'] + loc_vals = vals.copy() + loc_vals['reference'] = vals['supplier_invoice_number'] super(AccountInvoice, self).write(cr, uid, [invoice.id], - locvals, context=context) + loc_vals or vals, + context=context) return True else: return super(AccountInvoice, self).write(cr, uid, ids, vals, From 0b84dda3ff6f58c07511928add4a9af0eba69849 Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Fri, 10 Oct 2014 11:13:14 +0200 Subject: [PATCH 6/7] Migration to the new API for account.invoice --- account_invoice_reference/account_invoice.py | 70 +++++++++++--------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/account_invoice_reference/account_invoice.py b/account_invoice_reference/account_invoice.py index deee487a..8de7a88d 100644 --- a/account_invoice_reference/account_invoice.py +++ b/account_invoice_reference/account_invoice.py @@ -19,64 +19,72 @@ # ############################################################################## -from openerp.osv import orm +from openerp import models, api -class AccountInvoice(orm.Model): +class AccountInvoice(models.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 + @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 - def action_number(self, cr, uid, ids, context=None): + @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(cr, uid, ids, {}) + self.write({}) - for invoice in self.browse(cr, uid, ids, context=context): - ref = self._ref_from_invoice(cr, uid, invoice, context=context) + 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 - 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 = \'\')', + 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 = \'\')', + 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', + "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 - def create(self, cr, uid, vals, context=None): + @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(cr, uid, vals, - context=context) + return super(AccountInvoice, self).create(vals) - def write(self, cr, uid, ids, vals, context=None): + @api.multi + def write(self, vals): if vals.get('supplier_invoice_number'): - for invoice in self.browse(cr, uid, ids, context=context): + for invoice in self: loc_vals = None if not invoice.reference: loc_vals = vals.copy() loc_vals['reference'] = vals['supplier_invoice_number'] - super(AccountInvoice, self).write(cr, uid, [invoice.id], - loc_vals or vals, - context=context) + super(AccountInvoice, invoice).write(loc_vals or vals) return True else: - return super(AccountInvoice, self).write(cr, uid, ids, vals, - context=context) + return super(AccountInvoice, self).write(vals) From 96e32d3a5c1b315b0ab064241c57bc5b933d0dfa Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Fri, 10 Oct 2014 11:43:38 +0200 Subject: [PATCH 7/7] Long line --- account_invoice_reference/__openerp__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/account_invoice_reference/__openerp__.py b/account_invoice_reference/__openerp__.py index 0211d207..a1ac6d03 100644 --- a/account_invoice_reference/__openerp__.py +++ b/account_invoice_reference/__openerp__.py @@ -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.