Skip to content

Commit 2979354

Browse files
committed
Merge pull request OCA#142 from acsone/8.0-new-api-purchase-partial-invoicing
[8.0] Use new api on purchase partial invoicing
2 parents 139ef4f + b9f5cf4 commit 2979354

File tree

8 files changed

+363
-168
lines changed

8 files changed

+363
-168
lines changed

purchase_partial_invoicing/README.rst

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,25 @@ This module allows to partially invoice purchase order lines.
55
The 'Create invoices' from PO lines wizard allows to specify,
66
for each line, the quantity to invoice.
77

8+
Installation
9+
============
10+
11+
To install this module, you need to:
12+
13+
* Click on install button
14+
15+
Usage
16+
=====
17+
18+
To use this module, you need to:
19+
20+
* In order to create invoice from purchase order line, you have to set invoice
21+
method on purchas order to based on purchase order line.
22+
23+
For further information, please visit:
24+
25+
* https://www.odoo.com/forum/help-1
26+
827

928
Bug Tracker
1029
===========
@@ -14,14 +33,15 @@ In case of trouble, please check there if your issue has already been reported.
1433
If you spotted it first, help us smashing it by providing a detailed and welcomed feedback
1534
`here <https://github.com/OCA/purchase-workflow/issues/new?body=module:%20purchase_partial_invoicing%0Aversion:%208.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
1635

17-
1836
Credits
1937
=======
2038

2139
Contributors
2240
------------
2341

2442
* Lorenzo Battistini <[email protected]>
43+
* Stéphane Bidoul <[email protected]>
44+
* Adrien Peiffer <[email protected]>
2545

2646
Maintainer
2747
----------
@@ -34,4 +54,4 @@ This module is maintained by the OCA.
3454

3555
OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.
3656

37-
To contribute to this module, please visit http://odoo-community.org.
57+
To contribute to this module, please visit http://odoo-community.org.

purchase_partial_invoicing/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# -*- coding: utf-8 -*-
22
##############################################################################
33
#
4-
# Copyright (C) 2013 Agile Business Group sagl
5-
# (<http://www.agilebg.com>)
4+
# Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>)
5+
# Copyright (c) 2015 ACSONE SA/NV (<http://acsone.eu>)
66
#
77
# This program is free software: you can redistribute it and/or modify
88
# it under the terms of the GNU Affero General Public License as published

purchase_partial_invoicing/__openerp__.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# -*- coding: utf-8 -*-
22
##############################################################################
33
#
4-
# Copyright (C) 2013 Agile Business Group sagl
5-
# (<http://www.agilebg.com>)
4+
# Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>)
5+
# Copyright (c) 2015 ACSONE SA/NV (<http://acsone.eu>)
66
#
77
# This program is free software: you can redistribute it and/or modify
88
# it under the terms of the GNU Affero General Public License as published
@@ -23,7 +23,9 @@
2323
'name': "Purchase partial invoicing",
2424
'version': '0.1',
2525
'category': 'Purchase Management',
26-
'author': "Agile Business Group,Odoo Community Association (OCA)",
26+
'author': "Agile Business Group,"
27+
"ACSONE SA/NV,"
28+
"Odoo Community Association (OCA)",
2729
'website': 'http://www.agilebg.com',
2830
'license': 'AGPL-3',
2931
"depends": ['purchase'],
Lines changed: 56 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# -*- coding: utf-8 -*-
22
##############################################################################
33
#
4-
# Copyright (C) 2013 Agile Business Group sagl
5-
# (<http://www.agilebg.com>)
4+
# Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>)
5+
# Copyright (c) 2015 ACSONE SA/NV (<http://acsone.eu>)
66
#
77
# This program is free software: you can redistribute it and/or modify
88
# it under the terms of the GNU Affero General Public License as published
@@ -19,122 +19,81 @@
1919
#
2020
##############################################################################
2121

22-
from openerp.osv import fields, orm
22+
from openerp import models, fields, api
2323
import openerp.addons.decimal_precision as dp
2424

2525

26-
class purchase_order_line(orm.Model):
26+
class PurchaseOrderLine(models.Model):
2727

28-
def _invoiced_qty(self, cursor, user, ids, name, arg, context=None):
29-
res = {}
30-
for line in self.browse(cursor, user, ids, context=context):
31-
invoiced_qty = 0.0
32-
for invoice_line in line.invoice_lines:
33-
invoiced_qty += invoice_line.quantity
34-
res[line.id] = invoiced_qty
35-
return res
28+
@api.one
29+
@api.depends('invoice_lines', 'invoice_lines.invoice_id',
30+
'invoice_lines.quantity')
31+
def _compute_invoiced_qty(self):
32+
self.invoiced_qty = sum(self.invoice_lines.mapped('quantity'))
3633

37-
def _fully_invoiced(self, cursor, user, ids, name, arg, context=None):
38-
res = {}
39-
for line in self.browse(cursor, user, ids, context=context):
40-
res[line.id] = line.invoiced_qty == line.product_qty
41-
return res
34+
@api.one
35+
@api.depends('invoice_lines', 'invoice_lines.invoice_id',
36+
'invoice_lines.quantity')
37+
def _compute_fully_invoiced(self):
38+
self.fully_invoiced = (self.invoiced_qty == self.product_qty)
4239

43-
def _all_invoices_approved(self, cursor, user, ids, name, arg,
44-
context=None):
45-
res = {}
46-
for line in self.browse(cursor, user, ids, context=context):
47-
if line.invoice_lines:
48-
res[line.id] = not any(inv_line.invoice_id.state
49-
in ['draft', 'cancel']
50-
for inv_line in line.invoice_lines)
51-
else:
52-
res[line.id] = False
53-
return res
54-
55-
def _order_lines_from_invoice_line(self, cr, uid, ids, context=None):
56-
result = set()
57-
for invoice in self.pool['account.invoice'].browse(cr, uid, ids,
58-
context=context):
59-
for line in invoice.invoice_line:
60-
result.add(line.purchase_line_id.id)
61-
return list(result)
40+
@api.one
41+
def _compute_all_invoices_approved(self):
42+
if self.invoice_lines:
43+
self.all_invoices_approved = \
44+
not any(inv_line.invoice_id.state in ['draft', 'cancel']
45+
for inv_line in self.invoice_lines)
46+
else:
47+
self.all_invoices_approved = False
6248

6349
_inherit = 'purchase.order.line'
6450

65-
_columns = {
66-
'invoiced_qty': fields.function(
67-
_invoiced_qty,
68-
string='Invoiced quantity',
69-
type='float',
70-
digits_compute=dp.get_precision('Product Unit of Measure'),
71-
copy=False,
72-
store={
73-
'account.invoice': (_order_lines_from_invoice_line, [], 5),
74-
'purchase.order.line': (lambda self, cr, uid, ids,
75-
context=None: ids,
76-
['invoice_lines'], 5)}),
77-
'fully_invoiced': fields.function(
78-
_fully_invoiced,
79-
string='Fully invoiced',
80-
type='boolean',
81-
copy=False,
82-
store={
83-
'account.invoice': (_order_lines_from_invoice_line, [], 10),
84-
'purchase.order.line': (lambda self, cr, uid, ids,
85-
context=None: ids,
86-
['invoice_lines'], 10)}),
87-
'all_invoices_approved': fields.function(
88-
_all_invoices_approved,
89-
string='All invoices approved',
90-
type='boolean'),
91-
}
92-
93-
94-
class purchase_order(orm.Model):
51+
invoiced_qty = fields.Float(
52+
compute='_compute_invoiced_qty',
53+
digits_compute=dp.get_precision('Product Unit of Measure'),
54+
copy=False, store=True)
55+
56+
fully_invoiced = fields.Boolean(
57+
compute='_compute_fully_invoiced', copy=False, store=True)
58+
59+
all_invoices_approved = fields.Boolean(
60+
compute='_compute_all_invoices_approved')
61+
62+
63+
class PurchaseOrder(models.Model):
9564

9665
_inherit = 'purchase.order'
9766

98-
def _invoiced(self, cursor, user, ids, name, arg, context=None):
99-
res = {}
100-
for purchase in self.browse(cursor, user, ids, context=context):
101-
res[purchase.id] = all(line.all_invoices_approved and
102-
line.fully_invoiced
103-
for line in purchase.order_line)
104-
return res
67+
@api.one
68+
def _compute_invoiced(self):
69+
self.invoiced = all(line.all_invoices_approved and line.fully_invoiced
70+
for line in self.order_line)
71+
72+
invoiced = fields.Boolean(compute='_compute_invoiced')
10573

106-
_columns = {
107-
'invoiced': fields.function(_invoiced, string='Invoice Received',
108-
type='boolean',
109-
help="It indicates that an invoice has "
110-
"been validated"),
111-
}
112-
113-
def _prepare_inv_line(self, cr, uid, account_id, order_line, context=None):
114-
if context is None:
115-
context = {}
116-
res = super(purchase_order, self).\
117-
_prepare_inv_line(cr, uid, account_id, order_line, context=context)
118-
if context.get('partial_quantity_lines'):
119-
partial_quantity_lines = context.get('partial_quantity_lines')
74+
@api.model
75+
def _prepare_inv_line(self, account_id, order_line):
76+
res = super(PurchaseOrder, self).\
77+
_prepare_inv_line(account_id, order_line)
78+
ctx = self.env.context.copy()
79+
if ctx.get('partial_quantity_lines'):
80+
partial_quantity_lines = ctx.get('partial_quantity_lines')
12081
if partial_quantity_lines.get(order_line.id):
12182
res.update({'quantity':
12283
partial_quantity_lines.get(order_line.id)})
12384
return res
12485

12586

126-
class account_invoice(orm.Model):
87+
class AccountInvoice(models.Model):
12788
_inherit = 'account.invoice'
12889

129-
def invoice_validate(self, cr, uid, ids, context=None):
130-
res = super(account_invoice, self).invoice_validate(cr, uid, ids,
131-
context=context)
132-
purchase_order_obj = self.pool.get('purchase.order')
133-
po_ids = purchase_order_obj.search(
134-
cr, uid, [('invoice_ids', 'in', ids)], context=context)
135-
for purchase_order in purchase_order_obj.browse(cr, uid, po_ids,
136-
context=context):
90+
@api.multi
91+
def invoice_validate(self):
92+
res = super(AccountInvoice, self).invoice_validate()
93+
purchase_order_obj = self.env['purchase.order']
94+
po_ids = purchase_order_obj.search([('invoice_ids', 'in', self.ids)])
95+
for purchase_order in po_ids:
13796
for po_line in purchase_order.order_line:
13897
if po_line.invoiced_qty != po_line.product_qty:
139-
po_line.write({'invoiced': False})
98+
po_line.invoiced = False
14099
return res
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
##############################################################################
4+
#
5+
# Authors: Adrien Peiffer
6+
# Copyright (c) 2015 Acsone SA/NV (http://www.acsone.eu)
7+
#
8+
# This program is free software: you can redistribute it and/or modify
9+
# it under the terms of the GNU Affero General Public License as
10+
# published by the Free Software Foundation, either version 3 of the
11+
# License, or (at your option) any later version.
12+
#
13+
# This program is distributed in the hope that it will be useful,
14+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
# GNU Affero General Public License for more details.
17+
#
18+
# You should have received a copy of the GNU Affero General Public License
19+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
20+
#
21+
##############################################################################
22+
23+
from . import test_purchase_partial_invoicing

0 commit comments

Comments
 (0)