This question has been flagged
1 Reply
5118 Views

good afternoon,
I have created a column in the account_invoice_line, how can I do so that when creating the invoice from the sales order (sale.order), the new field is also copied to the invoice.
steps taken:
1-create the same change in the (sale.order.line)  How to send the field of sale.order.line to account_invoice_line ?? 
release: odoo12
Thank you.

Avatar
Discard
Best Answer

Hi,

While you clicking the Create Invoice button in sale order, it prepares invoice and invoice line details by action. After that invoice will be created. So you nee to add a new field and its value to _prepare_invoice_line() function in sale.py. This is a core file. So you just copy that function and paste it under sale model class in your module.

@api.multi
def _prepare_invoice_line(self, qty):
"""
Prepare the dict of values to create the new invoice line for a sales order line.

:param qty: float quantity to invoice
"""
self.ensure_one()
res = {}
account = self.product_id.property_account_income_id or self.product_id.categ_id.property_account_income_categ_id

if not account and self.product_id:
raise UserError(_('Please define income account for this product: "%s" (id:%d) - or for its category: "%s".') %
(self.product_id.name, self.product_id.id, self.product_id.categ_id.name))

fpos = self.order_id.fiscal_position_id or self.order_id.partner_id.property_account_position_id
if fpos and account:
account = fpos.map_account(account)

res = {
'name': self.name,
'sequence': self.sequence,
'origin': self.order_id.name,
'account_id': account.id,
'price_unit': self.price_unit,
'quantity': qty,
'discount': self.discount,
'uom_id': self.product_uom.id,
'product_id': self.product_id.id or False,
'invoice_line_tax_ids': [(6, 0, self.tax_id.ids)],
'account_analytic_id': self.order_id.analytic_account_id.id,
'analytic_tag_ids': [(6, 0, self.analytic_tag_ids.ids)],
'display_type': self.display_type,

'new_field_name': value of new field,

}
return res



Avatar
Discard
Author

Hi,

Perform the steps as commented, but the value is not on the invoice. I see that the action is done through the wizard (sale.advance.payment.inv), method: create_invoices, I inherited it also as evidence but neither does it update my new column in invoice_line.

@api.multi

def create_invoices(self):

sale_orders = self.env['sale.order'].browse(self._context.get('active_ids', []))

if self.advance_payment_method == 'delivered':

sale_orders.action_invoice_create()

elif self.advance_payment_method == 'all':

sale_orders.action_invoice_create(final=True)

else:

# Create deposit product if necessary

if not self.product_id:

vals = self._prepare_deposit_product()

self.product_id = self.env['product.product'].create(vals)

self.env['ir.config_parameter'].sudo().set_param('sale.default_deposit_product_id', self.product_id.id)

sale_line_obj = self.env['sale.order.line']

for order in sale_orders:

if self.advance_payment_method == 'percentage':

amount = order.amount_untaxed * self.amount / 100

else:

amount = self.amount

if self.product_id.invoice_policy != 'order':

raise UserError(_('The product used to invoice a down payment should have an invoice policy set to "Ordered quantities". Please update your deposit product to be able to create a deposit invoice.'))

if self.product_id.type != 'service':

raise UserError(_("The product used to invoice a down payment should be of type 'Service'. Please use another product or update this product."))

taxes = self.product_id.taxes_id.filtered(lambda r: not order.company_id or r.company_id == order.company_id)

if order.fiscal_position_id and taxes:

tax_ids = order.fiscal_position_id.map_tax(taxes, self.product_id, order.partner_shipping_id).ids

else:

tax_ids = taxes.ids

context = {'lang': order.partner_id.lang}

analytic_tag_ids = []

for line in order.order_line:

analytic_tag_ids = [(4, analytic_tag.id, None) for analytic_tag in line.analytic_tag_ids]

so_line = sale_line_obj.create({

'name': _('Advance: %s') % (time.strftime('%m %Y'),),

'price_unit': amount,

'product_uom_qty': 0.0,

'order_id': order.id,

'discount': 0.0,

'product_uom': self.product_id.uom_id.id,

'product_id': self.product_id.id,

'analytic_tag_ids': analytic_tag_ids,

'tax_id': [(6, 0, tax_ids)],

'is_downpayment': True,

'price_unit2':100,

})

del context

self._create_invoice(order, so_line, amount)

if self._context.get('open_invoices', False):

return sale_orders.action_view_invoice()

return {'type': 'ir.actions.act_window_close'}

Hi,

Overwrite the _prepare_invoice_values() of salesadvancepayment in your module. In that function add your new field and its value.

def _prepare_invoice_values(self, order, name, amount, so_line):

invoice_vals = {

'type': 'out_invoice',

'invoice_origin': order.name,

'invoice_user_id': order.user_id.id,

'narration': order.note,

'partner_id': order.partner_invoice_id.id,

'fiscal_position_id': order.fiscal_position_id.id or order.partner_id.property_account_position_id.id,

'partner_shipping_id': order.partner_shipping_id.id,

'currency_id': order.pricelist_id.currency_id.id,

'invoice_payment_ref': order.client_order_ref,

'invoice_payment_term_id': order.payment_term_id.id,

'invoice_partner_bank_id': order.company_id.partner_id.bank_ids[:1].id,

'team_id': order.team_id.id,

'campaign_id': order.campaign_id.id,

'medium_id': order.medium_id.id,

'source_id': order.source_id.id,

'invoice_line_ids': [(0, 0, {

'name': name,

'price_unit': amount,

'quantity': 1.0,

'product_id': self.product_id.id,

'product_uom_id': so_line.product_uom.id,

'tax_ids': [(6, 0, so_line.tax_id.ids)],

'sale_line_ids': [(6, 0, [so_line.id])],

'analytic_tag_ids': [(6, 0, so_line.analytic_tag_ids.ids)],

'analytic_account_id': order.analytic_account_id.id or False,

'new_field' : value,

})],

}

Author

hi, It is not working for me. The code I have is. where price_unit2 is the new column. I'm passing a fixed value for testing.

from odoo import models, fields, api

from odoo.exceptions import UserError,ValidationError

class sale_send_value(models.TransientModel):

_inherit = "sale.advance.payment.inv"

def _prepare_invoice_values(self, order, name, amount, so_line):

invoice_vals = {

'type': 'out_invoice',

......

'analytic_account_id': order.analytic_account_id.id or False,

'price_unit2' : 100.01,

})],

}

return invoice_vals

Author

Sorry, copy error,should say (not work): def _prepare_invoice_values(self, order, name, amount, so_line):

Sorry I did't understand. It's working or not?

Author

hello it is solved, with your first comment: _prepare_invoice_line, only not with the code you put. you must do a res.update ({}), thank you very much, it helped me a lot.