'purchase_id': False,
}
- def _get_address_invoice(self, cr, uid, picking):
- """ Gets invoice address of a partner
- @return {'contact': address, 'invoice': address} for invoice
+ def _get_partner_to_invoice(self, cr, uid, picking, context=None):
- """Inherit the original function of the 'stock' module
- We select the partner of the sale order as the partner of the customer invoice
++ """ Inherit the original function of the 'stock' module
++ We select the partner of the sale order as the partner of the customer invoice
"""
- res = super(stock_picking, self)._get_address_invoice(cr, uid, picking)
if picking.purchase_id:
- partner_obj = self.pool.get('res.partner')
- partner = picking.purchase_id.partner_id or picking.address_id.partner_id
- data = partner_obj.address_get(cr, uid, [partner.id],
- ['contact', 'invoice'])
- res.update(data)
- return res
+ return picking.purchase_id.partner_id
+ return super(stock_picking, self)._get_partner_to_invoice(cr, uid, picking, context=context)
+
+ def _prepare_invoice(self, cr, uid, picking, partner, inv_type, journal_id, context=None):
- """Inherit the original function of the 'stock' module in order to override some
- values if the picking has been generated by a purchase order
++ """ Inherit the original function of the 'stock' module in order to override some
++ values if the picking has been generated by a purchase order
+ """
+ invoice_vals = super(stock_picking, self)._prepare_invoice(cr, uid, picking, partner, inv_type, journal_id, context=context)
+ if picking.purchase_id:
+ invoice_vals['address_contact_id'], invoice_vals['address_invoice_id'] = \
- self.pool.get('res.partner').address_get(cr, uid, [partner.id],
- ['contact', 'invoice']).values()
++ self.pool.get('res.partner').address_get(cr, uid, [partner.id], ['contact', 'invoice']).values()
+ invoice_vals['fiscal_position'] = picking.purchase_id.fiscal_position.id
+ return invoice_vals
def get_currency_id(self, cursor, user, picking):
if picking.purchase_id:
def _invoice_line_hook(self, cursor, user, move_line, invoice_line_id):
if move_line.purchase_line_id:
invoice_line_obj = self.pool.get('account.invoice.line')
+ purchase_line_obj = self.pool.get('purchase.order.line')
- purchase_line_obj.write(cursor, user, [move_line.purchase_line_id.id],
- {
- 'invoiced': True,
- 'invoice_lines': [(4, invoice_line_id)],
- })
++ purchase_line_obj.write(cursor, user, [move_line.purchase_line_id.id], {
++ 'invoiced': True,
++ 'invoice_lines': [(4, invoice_line_id)],
++ })
invoice_line_obj.write(cursor, user, [invoice_line_id], {'note': move_line.purchase_line_id.notes,})
return super(stock_picking, self)._invoice_line_hook(cursor, user, move_line, invoice_line_id)
'price_unit': 0.0,
}
- def invoice_line_create(self, cr, uid, ids, context=None):
- if context is None:
- context = {}
+ def _prepare_order_line_invoice_line(self, cr, uid, ids, line, account_id=False, context=None):
- """Builds the invoice line dict from a sale order line
- @param line: sale order line object
- @param account_id: the id of the account to force eventually (the method is used for picking return including service)
- @return: dict that will be used to create the invoice line"""
-
++ """ Builds the invoice line dict from a sale order line
++ @param line: sale order line object
++ @param account_id: the id of the account to force eventually (the method is used for picking return including service)
++ @return: dict that will be used to create the invoice line
++ """
+
def _get_line_qty(line):
if (line.order_id.invoice_quantity=='order') or not line.procurement_id:
if line.product_uos:
return self.pool.get('procurement.order').uom_get(cr, uid,
line.procurement_id.id, context=context)
- create_ids = []
- sales = {}
- for line in self.browse(cr, uid, ids, context=context):
- if not line.invoiced:
+ if not line.invoiced:
+ if not account_id:
if line.product_id:
- a = line.product_id.product_tmpl_id.property_account_income.id
- if not a:
- a = line.product_id.categ_id.property_account_income_categ.id
- if not a:
+ account_id = line.product_id.product_tmpl_id.property_account_income.id
+ if not account_id:
+ account_id = line.product_id.categ_id.property_account_income_categ.id
+ if not account_id:
raise osv.except_osv(_('Error !'),
-- _('There is no income account defined ' \
- 'for this product: "%s" (id:%d)') % \
- (line.product_id.name, line.product_id.id,))
- 'for this product: "%s" (id:%d)') % \
++ _('There is no income account defined for this product: "%s" (id:%d)') % \
+ (line.product_id.name, line.product_id.id,))
else:
prop = self.pool.get('ir.property').get(cr, uid,
'property_account_income_categ', 'product.category',
context=context)
- a = prop and prop.id or False
- uosqty = _get_line_qty(line)
- uos_id = _get_line_uom(line)
- pu = 0.0
- if uosqty:
- pu = round(line.price_unit * line.product_uom_qty / uosqty,
- self.pool.get('decimal.precision').precision_get(cr, uid, 'Sale Price'))
- fpos = line.order_id.fiscal_position or False
- a = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, a)
- if not a:
- raise osv.except_osv(_('Error !'),
- _('There is no income category account defined in default Properties for Product Category or Fiscal Position is not defined !'))
- inv_id = self.pool.get('account.invoice.line').create(cr, uid, {
- 'name': line.name,
- 'origin': line.order_id.name,
- 'account_id': a,
- 'price_unit': pu,
- 'quantity': uosqty,
- 'discount': line.discount,
- 'uos_id': uos_id,
- 'product_id': line.product_id.id or False,
- 'invoice_line_tax_id': [(6, 0, [x.id for x in line.tax_id])],
- 'note': line.notes,
- 'account_analytic_id': line.order_id.project_id and line.order_id.project_id.id or False,
- })
+ account_id = prop and prop.id or False
+ uosqty = _get_line_qty(line)
+ uos_id = _get_line_uom(line)
+ pu = 0.0
+ if uosqty:
+ pu = round(line.price_unit * line.product_uom_qty / uosqty,
+ self.pool.get('decimal.precision').precision_get(cr, uid, 'Sale Price'))
+ fpos = line.order_id.fiscal_position or False
+ account_id = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, account_id)
+ if not account_id:
+ raise osv.except_osv(_('Error !'),
+ _('There is no income category account defined in default Properties for Product Category or Fiscal Position is not defined !'))
+ return {
+ 'name': line.name,
+ 'origin': line.order_id.name,
+ 'account_id': account_id,
+ 'price_unit': pu,
+ 'quantity': uosqty,
+ 'discount': line.discount,
+ 'uos_id': uos_id,
+ 'product_id': line.product_id.id or False,
+ 'invoice_line_tax_id': [(6, 0, [x.id for x in line.tax_id])],
+ 'note': line.notes,
+ 'account_analytic_id': line.order_id.project_id and line.order_id.project_id.id or False,
+ }
- else:
- return False
++
++ return False
+
+ def invoice_line_create(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+
+ create_ids = []
- sales = {}
++ sales = set()
+ for line in self.browse(cr, uid, ids, context=context):
+ vals = self._prepare_order_line_invoice_line(cr, uid, ids, line, False, context)
+ if vals:
+ inv_id = self.pool.get('account.invoice.line').create(cr, uid, vals, context=context)
cr.execute('insert into sale_order_line_invoice_rel (order_line_id,invoice_id) values (%s,%s)', (line.id, inv_id))
self.write(cr, uid, [line.id], {'invoiced': True})
-- sales[line.order_id.id] = True
++ sales.add(line.order_id.id)
create_ids.append(inv_id)
# Trigger workflow events
wf_service = netsvc.LocalService("workflow")
-- for sid in sales.keys():
-- wf_service.trg_write(uid, 'sale.order', sid, cr)
++ for sale_id in sales:
++ wf_service.trg_write(uid, 'sale.order', sale_id, cr)
return create_ids
def button_cancel(self, cr, uid, ids, context=None):
else:
return super(stock_picking, self).get_currency_id(cursor, user, picking)
- def _get_payment_term(self, cursor, user, picking):
- if picking.sale_id and picking.sale_id.payment_term:
- return picking.sale_id.payment_term.id
- return super(stock_picking, self)._get_payment_term(cursor, user, picking)
-
- def _get_address_invoice(self, cursor, user, picking):
- res = {}
+ def _get_partner_to_invoice(self, cr, uid, picking, context=None):
- """Inherit the original function of the 'stock' module
- We select the partner of the sale order as the partner of the customer invoice
++ """ Inherit the original function of the 'stock' module
++ We select the partner of the sale order as the partner of the customer invoice
+ """
if picking.sale_id:
- res['contact'] = picking.sale_id.partner_order_id.id
- res['invoice'] = picking.sale_id.partner_invoice_id.id
- return res
- return super(stock_picking, self)._get_address_invoice(cursor, user, picking)
+ return picking.sale_id.partner_id
+ return super(stock_picking, self)._get_partner_to_invoice(cr, uid, picking, context=context)
def _get_comment_invoice(self, cursor, user, picking):
if picking.note or (picking.sale_id and picking.sale_id.note):
return picking.note or picking.sale_id.note
return super(stock_picking, self)._get_comment_invoice(cursor, user, picking)
+ def _prepare_invoice(self, cr, uid, picking, partner, inv_type, journal_id, context=None):
- """Inherit the original function of the 'stock' module in order to override some
- values if the picking has been generated by a sale order
++ """ Inherit the original function of the 'stock' module in order to override some
++ values if the picking has been generated by a sale order
+ """
+ invoice_vals = super(stock_picking, self)._prepare_invoice(cr, uid, picking, partner, inv_type, journal_id, context=context)
+ if picking.sale_id:
+ invoice_vals['address_contact_id'] = picking.sale_id.partner_order_id.id
+ invoice_vals['address_invoice_id'] = picking.sale_id.partner_invoice_id.id
+ invoice_vals['fiscal_position'] = picking.sale_id.fiscal_position.id
+ invoice_vals['payment_term'] = picking.sale_id.payment_term.id
+ invoice_vals['user_id'] = picking.sale_id.user_id.id
+ return invoice_vals
+
def _get_price_unit_invoice(self, cursor, user, move_line, type):
if move_line.sale_line_id and move_line.sale_line_id.product_id.id == move_line.product_id.id:
uom_id = move_line.product_id.uom_id.id
if not account_id:
account_id = sale_line.product_id.categ_id.\
property_account_expense_categ.id
- price_unit = sale_line.price_unit
- discount = sale_line.discount
- tax_ids = sale_line.tax_id
- tax_ids = map(lambda x: x.id, tax_ids)
-
- account_analytic_id = self._get_account_analytic_invoice(cursor,
- user, picking, sale_line)
-
- account_id = fiscal_position_obj.map_account(cursor, user, picking.sale_id.partner_id.property_account_position, account_id)
- invoice = invoices[result[picking.id]]
- invoice_line_id = invoice_line_obj.create(cursor, user, {
- 'name': name,
- 'invoice_id': invoice.id,
- 'uos_id': sale_line.product_uos.id or sale_line.product_uom.id,
- 'product_id': sale_line.product_id.id,
- 'account_id': account_id,
- 'price_unit': price_unit,
- 'discount': discount,
- 'quantity': sale_line.product_uos_qty,
- 'invoice_line_tax_id': [(6, 0, tax_ids)],
- 'account_analytic_id': account_analytic_id,
- 'notes':sale_line.notes
- }, context=context)
- order_line_obj.write(cursor, user, [sale_line.id], {'invoiced': True,
- 'invoice_lines': [(6, 0, [invoice_line_id])],
- })
+
+ vals = order_line_obj._prepare_order_line_invoice_line(cursor, user, ids, sale_line, account_id, context)
+ if vals: #note: in some cases we may not want to include all service lines as invoice lines
+ vals['name'] = name
+ vals['account_analytic_id'] = self._get_account_analytic_invoice(cursor, user, picking, sale_line)
+ vals['invoice_id'] = invoices[result[picking.id]].id
+ invoice_line_id = invoice_line_obj.create(cursor, user, vals, context=context)
- order_line_obj.write(cursor, user, [sale_line.id], {'invoiced': True,
- 'invoice_lines': [(6, 0, [invoice_line_id])]})
++ order_line_obj.write(cursor, user, [sale_line.id], {
++ 'invoiced': True,
++ 'invoice_lines': [(6, 0, [invoice_line_id])],
++ })
return result
- # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+ # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
def get_currency_id(self, cr, uid, picking):
return False
- def _get_payment_term(self, cr, uid, picking):
- """ Gets payment term from partner.
- @return: Payment term
+ def _get_partner_to_invoice(self, cr, uid, picking, context=None):
+ """ Gets the partner that will be invoiced
- Note that this function is inherited in the sale module
- @param picking: object of the picking for which we are selecting the partner to invoice
- @return: object of the partner to invoice
++ Note that this function is inherited in the sale module
++ @param picking: object of the picking for which we are selecting the partner to invoice
++ @return: object of the partner to invoice
"""
- partner = picking.address_id.partner_id
- return partner.property_payment_term and partner.property_payment_term.id or False
-
- def _get_address_invoice(self, cr, uid, picking):
- """ Gets invoice address of a partner
- @return {'contact': address, 'invoice': address} for invoice
- """
- partner_obj = self.pool.get('res.partner')
- partner = picking.address_id.partner_id
- return partner_obj.address_get(cr, uid, [partner.id],
- ['contact', 'invoice'])
+ return picking.address_id and picking.address_id.partner_id
def _get_comment_invoice(self, cr, uid, picking):
"""
inv_type = 'out_invoice'
return inv_type
+ def _prepare_invoice_group(self, cr, uid, picking, partner, invoice, context=None):
- """Builds the dict for grouped invoices
- @param picking: picking object
- @param partner: object of the partner to invoice (not used here, but may be usefull if this function is inherited)
- @param invoice: object of the invoice that we are updating
- @return: dict that will be used to update the invoice
++ """ Builds the dict for grouped invoices
++ @param picking: picking object
++ @param partner: object of the partner to invoice (not used here, but may be usefull if this function is inherited)
++ @param invoice: object of the invoice that we are updating
++ @return: dict that will be used to update the invoice
+ """
+ comment = self._get_comment_invoice(cr, uid, picking)
-
+ return {
+ 'name': (invoice.name or '') + ', ' + (picking.name or ''),
+ 'origin': (invoice.origin or '') + ', ' + (picking.name or '') + (picking.origin and (':' + picking.origin) or ''),
+ 'comment': (comment and (invoice.comment and invoice.comment + "\n" + comment or comment)) or (invoice.comment and invoice.comment or ''),
+ 'date_invoice': context.get('date_inv', False),
- 'user_id': uid
++ 'user_id': uid,
+ }
+
+ def _prepare_invoice(self, cr, uid, picking, partner, inv_type, journal_id, context=None):
- """Builds the dict containing the values for the invoice
- @param picking: picking object
- @param partner: object of the partner to invoice
- @param inv_type: type of the invoice ('out_invoice', 'in_invoice', ...)
- @param journal_id: ID of the accounting journal
- @return: dict that will be used to create the invoice object
++ """ Builds the dict containing the values for the invoice
++ @param picking: picking object
++ @param partner: object of the partner to invoice
++ @param inv_type: type of the invoice ('out_invoice', 'in_invoice', ...)
++ @param journal_id: ID of the accounting journal
++ @return: dict that will be used to create the invoice object
+ """
+ if inv_type in ('out_invoice', 'out_refund'):
+ account_id = partner.property_account_receivable.id
+ else:
+ account_id = partner.property_account_payable.id
+ address_contact_id, address_invoice_id = \
+ self.pool.get('res.partner').address_get(cr, uid, [partner.id],
+ ['contact', 'invoice']).values()
+ comment = self._get_comment_invoice(cr, uid, picking)
+ invoice_vals = {
+ 'name': picking.name,
+ 'origin': (picking.name or '') + (picking.origin and (':' + picking.origin) or ''),
+ 'type': inv_type,
+ 'account_id': account_id,
+ 'partner_id': partner.id,
+ 'address_invoice_id': address_invoice_id,
+ 'address_contact_id': address_contact_id,
+ 'comment': comment,
- 'payment_term': partner.property_payment_term and partner.property_payment_term.id
- or False,
++ 'payment_term': partner.property_payment_term and partner.property_payment_term.id or False,
+ 'fiscal_position': partner.property_account_position.id,
+ 'date_invoice': context.get('date_inv', False),
+ 'company_id': picking.company_id.id,
- 'user_id': uid
++ 'user_id': uid,
+ }
+ cur_id = self.get_currency_id(cr, uid, picking)
+ if cur_id:
+ invoice_vals['currency_id'] = cur_id
+ if journal_id:
+ invoice_vals['journal_id'] = journal_id
+ return invoice_vals
+
+ def _prepare_invoice_line(self, cr, uid, group, picking, move_line, invoice_id,
+ invoice_vals, context=None):
- """Builds the dict containing the values for the invoice line
- @param group: True or False
- @param picking: picking object
- @param: move_line: move_line object
- @param: invoice_id: ID of the related invoice
- @param: invoice_vals: dict used to created the invoice
- @return: dict that will be used to create the invoice line
++ """ Builds the dict containing the values for the invoice line
++ @param group: True or False
++ @param picking: picking object
++ @param: move_line: move_line object
++ @param: invoice_id: ID of the related invoice
++ @param: invoice_vals: dict used to created the invoice
++ @return: dict that will be used to create the invoice line
+ """
+ if group:
+ name = (picking.name or '') + '-' + move_line.name
+ else:
+ name = move_line.name
+ origin = move_line.picking_id.name or ''
+ if move_line.picking_id.origin:
+ origin += ':' + move_line.picking_id.origin
+
+ if invoice_vals['type'] in ('out_invoice', 'out_refund'):
+ account_id = move_line.product_id.product_tmpl_id.\
+ property_account_income.id
+ if not account_id:
+ account_id = move_line.product_id.categ_id.\
+ property_account_income_categ.id
+ else:
+ account_id = move_line.product_id.product_tmpl_id.\
+ property_account_expense.id
+ if not account_id:
+ account_id = move_line.product_id.categ_id.\
+ property_account_expense_categ.id
+ if invoice_vals['fiscal_position']:
+ fp_obj = self.pool.get('account.fiscal.position')
+ fiscal_position = fp_obj.browse(cr, uid, invoice_vals['fiscal_position'], context=context)
+ account_id = fp_obj.map_account(cr, uid, fiscal_position, account_id)
+ # set UoS if it's a sale and the picking doesn't have one
+ uos_id = move_line.product_uos and move_line.product_uos.id or False
+ if not uos_id and invoice_vals['type'] in ('out_invoice', 'out_refund'):
+ uos_id = move_line.product_uom.id
+
+ return {
+ 'name': name,
+ 'origin': origin,
+ 'invoice_id': invoice_id,
+ 'uos_id': uos_id,
+ 'product_id': move_line.product_id.id,
+ 'account_id': account_id,
+ 'price_unit': self._get_price_unit_invoice(cr, uid, move_line, invoice_vals['type']),
+ 'discount': self._get_discount_invoice(cr, uid, move_line),
+ 'quantity': move_line.product_uos_qty or move_line.product_qty,
- 'invoice_line_tax_id': [(6, 0,
- self._get_taxes_invoice(cr, uid, move_line, invoice_vals['type']))],
++ 'invoice_line_tax_id': [(6, 0, self._get_taxes_invoice(cr, uid, move_line, invoice_vals['type']))],
+ 'account_analytic_id': self._get_account_analytic_invoice(cr, uid, picking, move_line),
- }
++ }
+
def action_invoice_create(self, cr, uid, ids, journal_id=False,
group=False, type='out_invoice', context=None):
""" Creates invoice based on the invoice state selected for picking.