Creating an invoice from a sale order ; a field is not copied in the right destination

Asked by forstera

Hello all,
I received an information from my acount manager about a problem of invoice creation.
In the sale order, there's a field 'client_order_ref' . In the account_invoice, there's a field 'name' and a field 'reference'.
When an invoice is created from a sale order, the value of the field client_order_ref is copied into the field 'name' of the invoice which seems not correct to us because the field name is the one displayed in the accounting.

We'd like that the value of the field 'client_order_ref' is copied into the field 'reference' but as I'm a beginner in python developpings, I request your help. I think I have to heritate the classs sale.order but ...

Thanks for your help

Finallym, after some researchs, I' just woul'd like to overwrite the function _make_invoice() to redirect the value of the fields but doesnt know the way to do it. Do have I to inherit the whole class and rewrite the function _make_invoice() with my own changes ?
Is it enough ? will my new function take the place of the 'old' one ?

Thanks for your help and your time

Question information

Language:
English Edit question
Status:
Solved
For:
Odoo Addons (MOVED TO GITHUB) Edit question
Assignee:
No assignee Edit question
Solved by:
Vinay Rana (OpenERP)
Solved:
Last query:
Last reply:
Revision history for this message
Vinay Rana (OpenERP) (vra-openerp) said :
#1

Hello forstera ,

Simple you need to create your own module where you can inherit the class sale_order class and override the method.
If you are new in python and do not aware with tiny framework use the following document links:
http://doc.openerp.com/developer/index.html#book-develop-link
http://doc.openerp.com/developer/1_2_module_development/3_Inheritance.html

Hope this will help you.

Thanks.

Revision history for this message
forstera (arnaud-forster-deactivatedaccount) said :
#2

Hello vra,
Ok, I'm going to try to override the function _make_invoice().

Thanks for your help

Revision history for this message
forstera (arnaud-forster-deactivatedaccount) said :
#3

Hello,

I spend 3 hours trying to inherit sale.order and just 1 method but it seems this is too hard for me for the while. I read many python docs but everything fails ...

I had my filename with the same name as the inherited one (sale.py) so I changed it because I don't know if this can be a cause of error ..

I just have the following class which is working fine :

class sale_order(osv.osv):
     _inherit = "sale.order"
 _defaults = {
        'print_total' : lambda *a: 1,
     }

 _columns = {
        'print_total' : fields.boolean('Impression du total',required=False,translate=False),
        'mw_contact': fields.many2one( 'res.partner.contact', 'Contact' ),
        'validite': fields.char('Validite', size=64),
        'date_offre':fields.date('Date offre',required=False, translate=False),
        'date_livraison':fields.date('Date livraison',required=False, translate=False),
        'so_remarques_ids': fields.one2many('remarques.so', 'so_id', 'Remarques'),
        'remarque_offre': fields.text('Remarques offre', required=False, translate=False),
        'remarque_ccde': fields.text('Remarques confirmation de commande', required=False, translate=False),
        'remarque_bl': fields.text('Remarques bulletin de livraison', required=False, translate=False),
        }

sale_order()

But now, I'd like to add a method from the inherited class (sale.order) to modify it.Here's the original method :

    def _make_invoice(self, cr, uid, order, lines, context={}):
        a = order.partner_id.property_account_receivable.id
        if order.payment_term:
            pay_term = order.payment_term.id
        else:
            pay_term = False
        for preinv in order.invoice_ids:
            if preinv.state not in ('cancel',):
                for preline in preinv.invoice_line:
                    inv_line_id = self.pool.get('account.invoice.line').copy(cr, uid, preline.id, {'invoice_id': False, 'price_unit': -preline.price_unit})
                    lines.append(inv_line_id)
        inv = {
            'name': order.client_order_ref or order.name,
            'origin': order.name,
            'type': 'out_invoice',
            'reference': "P%dSO%d" % (order.partner_id.id, order.id),
            'account_id': a,
            'partner_id': order.partner_id.id,
            'address_invoice_id': order.partner_invoice_id.id,
            'address_contact_id': order.partner_order_id.id,
            'invoice_line': [(6, 0, lines)],
            'currency_id': order.pricelist_id.currency_id.id,
            'comment': order.note,
            'payment_term': pay_term,
            'fiscal_position': order.partner_id.property_account_position.id
        }
        inv_obj = self.pool.get('account.invoice')
        inv.update(self._inv_get(cr, uid, order))
        inv_id = inv_obj.create(cr, uid, inv)
        data = inv_obj.onchange_payment_term_date_invoice(cr, uid, [inv_id], pay_term, time.strftime('%Y-%m-%d'))
        if data.get('value', False):
            inv_obj.write(cr, uid, [inv_id], data['value'], context=context)
        inv_obj.button_compute(cr, uid, [inv_id])
        return inv_id

I just would like to change the field
'reference': "P%dSO%d" % (order.partner_id.id, order.id),

but impossible to inherit this function, As soon as I add it to my sub-class, system hangs when restarting ...
If someone can give me some informations on what I do false, I'd be very gratefull

Best Regards

Revision history for this message
Akshay Jain (akshay-jain-7983) said :
#4

I had the same problem where i wanted the client order ref in invoice. If you notice that on Sale Order form in history tab you will see a table that shows associated invoices. I suggested (Question # 99471) this to openerp team that if a relationship already exists between sale order and invoice then why not show sale order as a link on invoice form as well. Well i had done that at my end. And i am able to print the customer ref on invoices as well. Specially in India we need to print customer order ref and customer order date on invoices to show our customer for our quick turnaround times.

No need to override any method of invoice or sale order. Do this:

In Sale.py file of sale module, append the following code at the end of file:

class account_invoice(osv.osv):
    _inherit = "account.invoice"
    _columns = {
        'saleorder_ids': fields.many2many('sale.order', 'sale_order_invoice_rel', 'invoice_id', 'order_id', 'Sale Order'),
    }
account_invoice()

Now you have added link to sale order on invoice object. Next to show this on invoice form. From Administration menu you can edit the xml for view account.invoice.form and add rhe below code after the last "</page>" tag in that xml:

<page string="Origin">
<separator colspan="4" string="Sale Orders"/>
<field name="saleorder_ids" nolabel="1" colspan="4" readonly="1"/>
</page>

Hope this helps. Any questions then mail me at <email address hidden>

Revision history for this message
Akshay Jain (akshay-jain-7983) said :
#5

Oh yes restart the server after modifying the python code.

Revision history for this message
forstera (arnaud-forster-deactivatedaccount) said :
#6

Hello,
Thank you very much for the informations; I think they're very useful. But I really need to overwrite the method def _make_invoice() because I'd like to change the content of one field.
As I said, the field 'name' is the field that is used in the accounting to reference a journal entry. This field has the now the value of the customer's own sale order number. So, if we have in the Accounting a journal entry with the customer's sale.order, the account number and the value. People from the Accounting can't do anything with that. They have, for each entry, delete this valeue and replace it with the name of the customer and our own sale order's number.
That's why I'd like to modify that by overwriting this method but really have problems to solve that

I really appreciate your help
Thanks

Revision history for this message
Vinay Rana (OpenERP) (vra-openerp) said :
#7

Hello forstera ,

Change your code by following manner:
create your own module and create one py file for this code.Do not forget to put dependency of sale module in __terp__.py file in your new module.

class sale_order(osv.osv):
          _inherit = "sale.order"

         def _make_invoice(self, cr, uid, order, lines, context={}):
               inv_obj = self.pool.get('account.invoice')
               inv_id = super(sale_order, self)._make_invoice(cr, uid, order, lines,context=context)
               inv_obj.write(cr, uid, inv_id,{'reference':("P%dSO%d" % (order.partner_id.id, order.id) )=><do it your changes here>})
               return inv_id
 sale_order()

Hope this will help you.

Thanks.

Revision history for this message
forstera (arnaud-forster-deactivatedaccount) said :
#8

Hello Vra,
Great !
thanks so much for your help. I'm going to test that next week and keep informed.

Thanks again for a so great help !!

regards

Revision history for this message
forstera (arnaud-forster-deactivatedaccount) said :
#9

Hello vra,

I'm trying your solution but for the while, but for a reason I don't understand, the system hangs. I can write the name of the function and thre return value :

def _make_invoice(self, cr, uid, order, lines, context={}):
return inv_id

I can update the module in this state, no problem. But the simple fact to add a line inside this function (whatever it is) makes the system to hang when I update

Couldn't load module new_sale_order
...
debug_rpc:exception:u''
debug_rpc:service:'object'
debug_rpc:method: 'execute'

Any idea ?
thanks very very much for your help

Revision history for this message
Vinay Rana (OpenERP) (vra-openerp) said :
#10

Hello Forster,

Can you provide me your code which you did it in new module (new_sale_order)?
I will try it in my code and check.

Thanks.

Revision history for this message
forstera (arnaud-forster-deactivatedaccount) said :
#11

Here it is (this is very kind to you) :

# -*- encoding: utf-8 -*-
##############################################################################
# .. removed to make place to post
###############################################################################

import netsvc
from osv import osv, fields
import time
import pooler

class sale_order(osv.osv):
 _inherit = "sale.order"

 def _make_invoice(self, cr, uid, order, lines, context={}):
               inv_obj = self.pool.get('account.invoice')
               inv_id = super(sale_order, self)._make_invoice(cr, uid, order, lines,context=context)
               inv_obj.write(cr, uid, inv_id,{'reference': "Testing value"})
        return inv_id
sale_order()

Revision history for this message
Vinay Rana (OpenERP) (vra-openerp) said :
#12

Hello Forster,

I have successfully run this code and reference field which you did write.One more thing i want to tell you that the reference field is not exist in form view of customer invoice.
This function will only call (from action_invoice_create) when you select Shipping policy 'Shipping & Manual Invoice'.
From Picking policy, stock will create invoice (function is defined in 'stock.py' code) with the help of create invoice wizard.

I am surprised for system hang problem.Try to create new database and check.

Thanks.

Revision history for this message
forstera (arnaud-forster-deactivatedaccount) said :
#13

Hello,
I'm going to try that and keep you informed ...
Thanks very much

Revision history for this message
forstera (arnaud-forster-deactivatedaccount) said :
#14

Successfull, too great !!

Thanks for the informations you just gave, very very useful.

Before, I had more things defined with the method _make_invoice() like fields. So I completely made a new module with just the function and it's working.

So, to make such functions, do I have to write some modules just for them or can I mix functions and other things (like adding new fields) ?

Thanks very very much for your very useful help :)

Revision history for this message
Best Vinay Rana (OpenERP) (vra-openerp) said :
#15

Hello forstera,

See Why i suggest you to make separate module because the original code will remain same and when you will want to revert back from original code.It is very easy to just uninstall those module.
What type of changes you want always create new module if the object is different otherwise you can merge all the changes in new module which you did create.

Thanks.

Revision history for this message
forstera (arnaud-forster-deactivatedaccount) said :
#16

Thanks vra (openerp), that solved my question.

Revision history for this message
bondok (ahmed-samir) said :
#17

Akshay Jain,

Thank, you solution was exactly what I needed. Now I need to print the client_order_ref from the sales order on the invoice report form. Can you tell me how to do so ? I need the object name to use in the rml file.