Files
odoo_source/addons/purchase/models/account_invoice.py
T
IEL 41471bb0ab [FIX] purchase: always switch to vendor's currency on creating a bill
Before this commit vendor's currency wasn't used on creating an invoice if there
is default journal in context. As I understand, the idea was to let onchange("journal_id")
handler to update the currency. It works well, if journal has the same currency
as specified in vendor record (res.partner). But it confuse users in following
scenario:
* there is just one vendor journal
* vendor is configured to invoice in another currency
* then, if you create invoice via "Accounting >> Overview >> Vendor Bills", it
would have journal's currency
* while, if you create invoice via "Accounting >> Vendor >> Bills", it
would have vendor's currency

This commit force to switch to vendor's currency on changing vendor field, even
if it differs from journal's currency. If after changing vendor, you set another
journal, then journal's currency is used (thanks to onchange("journal_id") handler)

opw-2339966

closes odoo/odoo#59162

X-original-commit: 513cc1abe121cd05623be1a6519239f8f4b3fb48
Signed-off-by: agr-odoo <agr-odoo@users.noreply.github.com>
Signed-off-by: Nicolas Martinelli (nim) <nim@odoo.com>
2020-10-05 18:07:49 +00:00

141 lines
6.4 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
class AccountMove(models.Model):
_inherit = 'account.move'
purchase_vendor_bill_id = fields.Many2one('purchase.bill.union', store=False, readonly=True,
states={'draft': [('readonly', False)]},
string='Auto-complete',
help="Auto-complete from a past bill / purchase order.")
purchase_id = fields.Many2one('purchase.order', store=False, readonly=True,
states={'draft': [('readonly', False)]},
string='Purchase Order',
help="Auto-complete from a past purchase order.")
def _get_invoice_reference(self):
self.ensure_one()
vendor_refs = [ref for ref in set(self.line_ids.mapped('purchase_line_id.order_id.partner_ref')) if ref]
if self.ref:
return [ref for ref in self.ref.split(', ') if ref and ref not in vendor_refs] + vendor_refs
return vendor_refs
@api.onchange('purchase_vendor_bill_id', 'purchase_id')
def _onchange_purchase_auto_complete(self):
''' Load from either an old purchase order, either an old vendor bill.
When setting a 'purchase.bill.union' in 'purchase_vendor_bill_id':
* If it's a vendor bill, 'invoice_vendor_bill_id' is set and the loading is done by '_onchange_invoice_vendor_bill'.
* If it's a purchase order, 'purchase_id' is set and this method will load lines.
/!\ All this not-stored fields must be empty at the end of this function.
'''
if self.purchase_vendor_bill_id.vendor_bill_id:
self.invoice_vendor_bill_id = self.purchase_vendor_bill_id.vendor_bill_id
self._onchange_invoice_vendor_bill()
elif self.purchase_vendor_bill_id.purchase_order_id:
self.purchase_id = self.purchase_vendor_bill_id.purchase_order_id
self.purchase_vendor_bill_id = False
if not self.purchase_id:
return
# Copy data from PO
invoice_vals = self.purchase_id.with_company(self.purchase_id.company_id)._prepare_invoice()
del invoice_vals['ref']
self.update(invoice_vals)
# Copy purchase lines.
po_lines = self.purchase_id.order_line - self.line_ids.mapped('purchase_line_id')
new_lines = self.env['account.move.line']
for line in po_lines.filtered(lambda l: not l.display_type):
new_line = new_lines.new(line._prepare_account_move_line(self))
new_line.account_id = new_line._get_computed_account()
new_line._onchange_price_subtotal()
new_lines += new_line
new_lines._onchange_mark_recompute_taxes()
# Compute invoice_origin.
origins = set(self.line_ids.mapped('purchase_line_id.order_id.name'))
self.invoice_origin = ','.join(list(origins))
# Compute ref.
refs = self._get_invoice_reference()
self.ref = ', '.join(refs)
# Compute payment_reference.
if len(refs) == 1:
self.payment_reference = refs[0]
self.purchase_id = False
self._onchange_currency()
self.partner_bank_id = self.bank_partner_id.bank_ids and self.bank_partner_id.bank_ids[0]
@api.onchange('partner_id', 'company_id')
def _onchange_partner_id(self):
res = super(AccountMove, self)._onchange_partner_id()
if self.partner_id and\
self.move_type in ['in_invoice', 'in_refund'] and\
self.currency_id != self.partner_id.property_purchase_currency_id and\
self.partner_id.property_purchase_currency_id.id:
if not self.env.context.get('default_journal_id'):
journal_domain = [
('type', '=', 'purchase'),
('company_id', '=', self.company_id.id),
('currency_id', '=', self.partner_id.property_purchase_currency_id.id),
]
default_journal_id = self.env['account.journal'].search(journal_domain, limit=1)
if default_journal_id:
self.journal_id = default_journal_id
if self.env.context.get('default_currency_id'):
self.currency_id = self.env.context['default_currency_id']
if self.partner_id.property_purchase_currency_id:
self.currency_id = self.partner_id.property_purchase_currency_id
return res
@api.model_create_multi
def create(self, vals_list):
# OVERRIDE
moves = super(AccountMove, self).create(vals_list)
for move in moves:
if move.reversed_entry_id:
continue
purchase = move.line_ids.mapped('purchase_line_id.order_id')
if not purchase:
continue
refs = ["<a href=# data-oe-model=purchase.order data-oe-id=%s>%s</a>" % tuple(name_get) for name_get in purchase.name_get()]
message = _("This vendor bill has been created from: %s") % ','.join(refs)
move.message_post(body=message)
return moves
def write(self, vals):
# OVERRIDE
old_purchases = [move.mapped('line_ids.purchase_line_id.order_id') for move in self]
res = super(AccountMove, self).write(vals)
for i, move in enumerate(self):
new_purchases = move.mapped('line_ids.purchase_line_id.order_id')
if not new_purchases:
continue
diff_purchases = new_purchases - old_purchases[i]
if diff_purchases:
refs = ["<a href=# data-oe-model=purchase.order data-oe-id=%s>%s</a>" % tuple(name_get) for name_get in diff_purchases.name_get()]
message = _("This vendor bill has been modified from: %s") % ','.join(refs)
move.message_post(body=message)
return res
class AccountMoveLine(models.Model):
""" Override AccountInvoice_line to add the link to the purchase order line it is related to"""
_inherit = 'account.move.line'
purchase_line_id = fields.Many2one('purchase.order.line', 'Purchase Order Line', ondelete='set null', index=True)
purchase_order_id = fields.Many2one('purchase.order', 'Purchase Order', related='purchase_line_id.order_id', readonly=True)
def _copy_data_extend_business_fields(self, values):
# OVERRIDE to copy the 'purchase_line_id' field as well.
super(AccountMoveLine, self)._copy_data_extend_business_fields(values)
values['purchase_line_id'] = self.purchase_line_id.id