Merge lp:~akretion-team/openobject-addons/trunk-extensible-sale-action-invoice-create into lp:openobject-addons

Proposed by Alexis de Lattre
Status: Merged
Merged at revision: 6597
Proposed branch: lp:~akretion-team/openobject-addons/trunk-extensible-sale-action-invoice-create
Merge into: lp:openobject-addons
Diff against target: 126 lines (+35/-37)
2 files modified
sale/sale.py (+34/-36)
sale/stock.py (+1/-1)
To merge this branch: bzr merge lp:~akretion-team/openobject-addons/trunk-extensible-sale-action-invoice-create
Reviewer Review Type Date Requested Status
Olivier Dony (Odoo) Approve
Raphaël Valyi - http://www.akretion.com (community) Approve
qdp (OpenERP) Pending
Review via email: mp+91147@code.launchpad.net

Description of the change

This merge proposal adds a function _prepare_invoice() to the sale_order object, that builds the dict that will be used to create the invoice. It allows developers to easily change the values of the account.invoice object before it is created. It is the same kind of development as these other merge proposals by Akretion that were merged in trunk :
https://code.launchpad.net/~akretion-team/openobject-addons/addons-sale-extensible-action-ship-create/+merge/76609
https://code.launchpad.net/~alexis-via/openobject-addons/extensible-stock-action_invoice_create/+merge/87689

This merge proposal removes the function _inv_get() ; developers should now inherit the function _prepare_invoice().
This function _inv_get() is not used anywhere in the addons. It is used by 3 modules in extra-trunk :
- cci_sales : they made a near-hard copy of the function _make_invoice... they were waiting for the function _prepare_invoice() ! So they can now inherit _prepare_invoice() (or just remove the line that calls _inv_get() in _make_invoice())
- purchase_tax_include -> this functionnality is now part of the addons
- sale_tax_include -> this functionnality is now part of the addons
If you think it is a problem to remove the function _inv_get(), we can keep it in the code with a warning "depracated, inherit _prepare_invoice() instead".

To post a comment you must log in.
Revision history for this message
Raphaël Valyi - http://www.akretion.com (rvalyi) wrote :

Hello,

I approve Alexis's change: yet one of those last occasion to improve our daily accounting throughput once the base modules have been overridden, even by a simple localization.

Also Alexis cleaned up the _prepare_order_line_invoice_line methods I introduced in a previous merge and removed the order ids arg as it is totally useless (we may retrieve current order id by doing line.order_id.id).

So please can this go to 6.1 too?
I feel that's cool we have been somewhat consistent with all picking and standard invoice modularization with that last change.

review: Approve
Revision history for this message
Raphaël Valyi - http://www.akretion.com (rvalyi) wrote :

up (as it changes and fixes the API, better have it before 6.1...)

Revision history for this message
Olivier Dony (Odoo) (odo-openerp) wrote :

Hello,

It looks good to me, the only few things we will change while merging are the following:

- restore _inv_get() method for compatibility (to be removed after 6.1 for example)
- add missing context guard in _prepare_invoice (our convention is that all methods that access the context should care for the None case, even if they are currently always called with a context)
- some docstrings improvements to follow our current docstring conventions (but I understand that you copied an existing one ;-))

Thanks for the clean refactoring!

review: Approve
Revision history for this message
Raphaël Valyi - http://www.akretion.com (rvalyi) wrote :

Ok, perfect! Thanks.

On Wed, Feb 15, 2012 at 3:15 PM, Olivier Dony (OpenERP) <email address hidden>wrote:

> Review: Approve
>
> Hello,
>
> It looks good to me, the only few things we will change while merging are
> the following:
>
> - restore _inv_get() method for compatibility (to be removed after 6.1 for
> example)
> - add missing context guard in _prepare_invoice (our convention is that
> all methods that access the context should care for the None case, even if
> they are currently always called with a context)
> - some docstrings improvements to follow our current docstring conventions
> (but I understand that you copied an existing one ;-))
>
> Thanks for the clean refactoring!
> --
>
> https://code.launchpad.net/~akretion-team/openobject-addons/trunk-extensible-sale-action-invoice-create/+merge/91147
> You are reviewing the proposed merge of
> lp:~akretion-team/openobject-addons/trunk-extensible-sale-action-invoice-create
> into lp:openobject-addons.
>

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'sale/sale.py'
--- sale/sale.py 2012-01-31 13:36:57 +0000
+++ sale/sale.py 2012-02-01 18:56:22 +0000
@@ -393,43 +393,24 @@
393 def button_dummy(self, cr, uid, ids, context=None):393 def button_dummy(self, cr, uid, ids, context=None):
394 return True394 return True
395395
396 #FIXME: the method should return the list of invoices created (invoice_ids)396 def _prepare_invoice(self, cr, uid, order, lines, context=None):
397 # and not the id of the last invoice created (res). The problem is that we397 """ Builds the dict containing the values for the invoice
398 # cannot change it directly since the method is called by the sales order398 @param order: order object
399 # workflow and I suppose it expects a single id...399 @param line: list of invoice line IDs that must be attached to the invoice
400 def _inv_get(self, cr, uid, order, context=None):400 @return: dict that will be used to create the invoice object
401 return {}401 """
402402 journal_ids = self.pool.get('account.journal').search(cr, uid,
403 def _make_invoice(self, cr, uid, order, lines, context=None):403 [('type', '=', 'sale'), ('company_id', '=', order.company_id.id)],
404 journal_obj = self.pool.get('account.journal')404 limit=1)
405 inv_obj = self.pool.get('account.invoice')
406 obj_invoice_line = self.pool.get('account.invoice.line')
407 if context is None:
408 context = {}
409
410 journal_ids = journal_obj.search(cr, uid, [('type', '=', 'sale'), ('company_id', '=', order.company_id.id)], limit=1)
411 if not journal_ids:405 if not journal_ids:
412 raise osv.except_osv(_('Error !'),406 raise osv.except_osv(_('Error !'),
413 _('There is no sales journal defined for this company: "%s" (id:%d)') % (order.company_id.name, order.company_id.id))407 _('There is no sales journal defined for this company: "%s" (id:%d)') % (order.company_id.name, order.company_id.id))
414 a = order.partner_id.property_account_receivable.id408 return {
415 pay_term = order.payment_term and order.payment_term.id or False
416 invoiced_sale_line_ids = self.pool.get('sale.order.line').search(cr, uid, [('order_id', '=', order.id), ('invoiced', '=', True)], context=context)
417 from_line_invoice_ids = []
418 for invoiced_sale_line_id in self.pool.get('sale.order.line').browse(cr, uid, invoiced_sale_line_ids, context=context):
419 for invoice_line_id in invoiced_sale_line_id.invoice_lines:
420 if invoice_line_id.invoice_id.id not in from_line_invoice_ids:
421 from_line_invoice_ids.append(invoice_line_id.invoice_id.id)
422 for preinv in order.invoice_ids:
423 if preinv.state not in ('cancel',) and preinv.id not in from_line_invoice_ids:
424 for preline in preinv.invoice_line:
425 inv_line_id = obj_invoice_line.copy(cr, uid, preline.id, {'invoice_id': False, 'price_unit': -preline.price_unit})
426 lines.append(inv_line_id)
427 inv = {
428 'name': order.client_order_ref or '',409 'name': order.client_order_ref or '',
429 'origin': order.name,410 'origin': order.name,
430 'type': 'out_invoice',411 'type': 'out_invoice',
431 'reference': order.client_order_ref or order.name,412 'reference': order.client_order_ref or order.name,
432 'account_id': a,413 'account_id': order.partner_id.property_account_receivable.id,
433 'partner_id': order.partner_id.id,414 'partner_id': order.partner_id.id,
434 'journal_id': journal_ids[0],415 'journal_id': journal_ids[0],
435 'address_invoice_id': order.partner_invoice_id.id,416 'address_invoice_id': order.partner_invoice_id.id,
@@ -437,15 +418,32 @@
437 'invoice_line': [(6, 0, lines)],418 'invoice_line': [(6, 0, lines)],
438 'currency_id': order.pricelist_id.currency_id.id,419 'currency_id': order.pricelist_id.currency_id.id,
439 'comment': order.note,420 'comment': order.note,
440 'payment_term': pay_term,421 'payment_term': order.payment_term and order.payment_term.id or False,
441 'fiscal_position': order.fiscal_position.id or order.partner_id.property_account_position.id,422 'fiscal_position': order.fiscal_position.id or order.partner_id.property_account_position.id,
442 'date_invoice': context.get('date_invoice',False),423 'date_invoice': context.get('date_invoice', False),
443 'company_id': order.company_id.id,424 'company_id': order.company_id.id,
444 'user_id': order.user_id and order.user_id.id or False425 'user_id': order.user_id and order.user_id.id or False
445 }426 }
446 inv.update(self._inv_get(cr, uid, order))427
428 def _make_invoice(self, cr, uid, order, lines, context=None):
429 inv_obj = self.pool.get('account.invoice')
430 obj_invoice_line = self.pool.get('account.invoice.line')
431 if context is None:
432 context = {}
433 invoiced_sale_line_ids = self.pool.get('sale.order.line').search(cr, uid, [('order_id', '=', order.id), ('invoiced', '=', True)], context=context)
434 from_line_invoice_ids = []
435 for invoiced_sale_line_id in self.pool.get('sale.order.line').browse(cr, uid, invoiced_sale_line_ids, context=context):
436 for invoice_line_id in invoiced_sale_line_id.invoice_lines:
437 if invoice_line_id.invoice_id.id not in from_line_invoice_ids:
438 from_line_invoice_ids.append(invoice_line_id.invoice_id.id)
439 for preinv in order.invoice_ids:
440 if preinv.state not in ('cancel',) and preinv.id not in from_line_invoice_ids:
441 for preline in preinv.invoice_line:
442 inv_line_id = obj_invoice_line.copy(cr, uid, preline.id, {'invoice_id': False, 'price_unit': -preline.price_unit})
443 lines.append(inv_line_id)
444 inv = self._prepare_invoice(cr, uid, order, lines, context=context)
447 inv_id = inv_obj.create(cr, uid, inv, context=context)445 inv_id = inv_obj.create(cr, uid, inv, context=context)
448 data = inv_obj.onchange_payment_term_date_invoice(cr, uid, [inv_id], pay_term, time.strftime(DEFAULT_SERVER_DATE_FORMAT))446 data = inv_obj.onchange_payment_term_date_invoice(cr, uid, [inv_id], inv['payment_term'], time.strftime(DEFAULT_SERVER_DATE_FORMAT))
449 if data.get('value', False):447 if data.get('value', False):
450 inv_obj.write(cr, uid, [inv_id], data['value'], context=context)448 inv_obj.write(cr, uid, [inv_id], data['value'], context=context)
451 inv_obj.button_compute(cr, uid, [inv_id])449 inv_obj.button_compute(cr, uid, [inv_id])
@@ -981,7 +979,7 @@
981 'price_unit': 0.0,979 'price_unit': 0.0,
982 }980 }
983981
984 def _prepare_order_line_invoice_line(self, cr, uid, ids, line, account_id=False, context=None):982 def _prepare_order_line_invoice_line(self, cr, uid, line, account_id=False, context=None):
985 """ Builds the invoice line dict from a sale order line983 """ Builds the invoice line dict from a sale order line
986 @param line: sale order line object984 @param line: sale order line object
987 @param account_id: the id of the account to force eventually (the method is used for picking return including service)985 @param account_id: the id of the account to force eventually (the method is used for picking return including service)
@@ -1055,7 +1053,7 @@
1055 create_ids = []1053 create_ids = []
1056 sales = set()1054 sales = set()
1057 for line in self.browse(cr, uid, ids, context=context):1055 for line in self.browse(cr, uid, ids, context=context):
1058 vals = self._prepare_order_line_invoice_line(cr, uid, ids, line, False, context)1056 vals = self._prepare_order_line_invoice_line(cr, uid, line, False, context)
1059 if vals:1057 if vals:
1060 inv_id = self.pool.get('account.invoice.line').create(cr, uid, vals, context=context)1058 inv_id = self.pool.get('account.invoice.line').create(cr, uid, vals, context=context)
1061 cr.execute('insert into sale_order_line_invoice_rel (order_line_id,invoice_id) values (%s,%s)', (line.id, inv_id))1059 cr.execute('insert into sale_order_line_invoice_rel (order_line_id,invoice_id) values (%s,%s)', (line.id, inv_id))
10621060
=== modified file 'sale/stock.py'
--- sale/stock.py 2012-01-31 13:36:57 +0000
+++ sale/stock.py 2012-02-01 18:56:22 +0000
@@ -176,7 +176,7 @@
176 account_id = sale_line.product_id.categ_id.\176 account_id = sale_line.product_id.categ_id.\
177 property_account_expense_categ.id177 property_account_expense_categ.id
178178
179 vals = order_line_obj._prepare_order_line_invoice_line(cursor, user, ids, sale_line, account_id, context)179 vals = order_line_obj._prepare_order_line_invoice_line(cursor, user, sale_line, account_id, context)
180 if vals: #note: in some cases we may not want to include all service lines as invoice lines180 if vals: #note: in some cases we may not want to include all service lines as invoice lines
181 vals['name'] = name181 vals['name'] = name
182 vals['account_analytic_id'] = self._get_account_analytic_invoice(cursor, user, picking, sale_line)182 vals['account_analytic_id'] = self._get_account_analytic_invoice(cursor, user, picking, sale_line)

Subscribers

People subscribed via source and target branches

to all changes: