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>
141 lines
6.4 KiB
Python
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
|