181 lines
6.3 KiB
Python
181 lines
6.3 KiB
Python
# Copyright 2023 Ecosoft Co., Ltd. (http://ecosoft.co.th)
|
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
|
|
|
from lxml import etree
|
|
|
|
from odoo import api, fields, models
|
|
from odoo.exceptions import ValidationError
|
|
|
|
|
|
class AccountMove(models.Model):
|
|
_inherit = "account.move"
|
|
|
|
manual_currency = fields.Boolean()
|
|
is_manual = fields.Boolean(compute="_compute_currency")
|
|
type_currency = fields.Selection(
|
|
selection=lambda self: self._get_label_currency_name(),
|
|
default=lambda self: self._get_label_currency_name()[0][0],
|
|
)
|
|
manual_currency_rate = fields.Float(
|
|
digits="Manual Currency",
|
|
tracking=True,
|
|
help="Set new currency rate to apply on the invoice\n."
|
|
"This rate will be taken in order to convert amounts between the "
|
|
"currency on the purchase order and last currency",
|
|
)
|
|
total_company_currency = fields.Monetary(
|
|
compute="_compute_total_company_currency", currency_field="company_currency_id"
|
|
)
|
|
currency_diff = fields.Boolean(
|
|
compute="_compute_currency_diff",
|
|
store=True,
|
|
)
|
|
|
|
@api.depends("currency_id")
|
|
def _compute_currency_diff(self):
|
|
for rec in self:
|
|
rec.currency_diff = rec.company_currency_id != rec.currency_id
|
|
|
|
@api.depends("line_ids.balance")
|
|
def _compute_total_company_currency(self):
|
|
"""Convert total currency to company currency"""
|
|
for rec in self:
|
|
# check manual currency
|
|
if rec.manual_currency:
|
|
rate = (
|
|
rec.manual_currency_rate
|
|
if rec.type_currency == "inverse_company_rate"
|
|
else (1.0 / rec.manual_currency_rate)
|
|
)
|
|
rec.total_company_currency = rec.amount_total * rate
|
|
# default rate currency
|
|
else:
|
|
rec.total_company_currency = rec.currency_id._convert(
|
|
rec.amount_total,
|
|
rec.company_currency_id,
|
|
rec.company_id,
|
|
fields.Date.today(),
|
|
)
|
|
|
|
def _get_label_currency_name(self):
|
|
"""Get label related currency"""
|
|
names = {
|
|
"company_currency_name": (
|
|
self.env["res.company"].browse(self._context.get("company_id"))
|
|
or self.env.company
|
|
).currency_id.name,
|
|
"rate_currency_name": "Currency",
|
|
}
|
|
return [
|
|
[
|
|
"company_rate",
|
|
self.env._(
|
|
"%(rate_currency_name)s per 1 %(company_currency_name)s", **names
|
|
),
|
|
],
|
|
[
|
|
"inverse_company_rate",
|
|
self.env._(
|
|
"%(company_currency_name)s per 1 %(rate_currency_name)s", **names
|
|
),
|
|
],
|
|
]
|
|
|
|
@api.onchange("manual_currency", "type_currency", "currency_id", "date")
|
|
def _onchange_currency_change_rate(self):
|
|
today = fields.Date.today()
|
|
company_currency = self.env.company.currency_id
|
|
amount_currency = company_currency._get_conversion_rate(
|
|
company_currency,
|
|
self.currency_id,
|
|
self.company_id,
|
|
self.date or today,
|
|
)
|
|
if self.type_currency == "inverse_company_rate":
|
|
amount_currency = 1.0 / amount_currency
|
|
self.manual_currency_rate = amount_currency
|
|
|
|
@api.depends("currency_id")
|
|
def _compute_currency(self):
|
|
for rec in self:
|
|
rec.is_manual = rec.currency_id != rec.company_id.currency_id
|
|
|
|
def action_refresh_currency(self):
|
|
self.ensure_one()
|
|
if self.state != "draft":
|
|
raise ValidationError(
|
|
self.env._("Rate currency can refresh state draft only.")
|
|
)
|
|
self.with_context(check_move_validity=False)._onchange_currency_change_rate()
|
|
return True
|
|
|
|
@api.depends(
|
|
"currency_id",
|
|
"company_currency_id",
|
|
"company_id",
|
|
"invoice_date",
|
|
"manual_currency_rate",
|
|
)
|
|
def _compute_invoice_currency_rate(self):
|
|
res = super()._compute_invoice_currency_rate()
|
|
for move in self:
|
|
if not move.manual_currency:
|
|
continue
|
|
# Currency Rate on move use 'company_rate'
|
|
rate = (
|
|
move.manual_currency_rate
|
|
if move.type_currency == "company_rate"
|
|
else (1.0 / move.manual_currency_rate)
|
|
)
|
|
move.invoice_currency_rate = rate
|
|
return res
|
|
|
|
@api.model
|
|
def get_view(self, view_id=None, view_type="form", **options):
|
|
"""Change string name to company currency"""
|
|
result = super().get_view(view_id=view_id, view_type=view_type, **options)
|
|
if view_type == "form":
|
|
company_currency_name = (
|
|
self.env["res.company"].browse(self._context.get("company_id"))
|
|
or self.env.company
|
|
).currency_id.name
|
|
doc = etree.XML(result["arch"])
|
|
# Total company currency
|
|
node = doc.xpath("//field[@name='total_company_currency']")
|
|
if node:
|
|
node[0].set("string", f"Total ({company_currency_name})")
|
|
result["arch"] = etree.tostring(doc, encoding="unicode")
|
|
return result
|
|
|
|
@api.onchange("manual_currency_rate")
|
|
def _onchange_manual_currency_rate(self):
|
|
"""Refresh currency rate if manual currency rate is 0"""
|
|
for move in self:
|
|
if move.manual_currency and not move.manual_currency_rate:
|
|
move.action_refresh_currency()
|
|
|
|
|
|
class AccountMoveLine(models.Model):
|
|
_inherit = "account.move.line"
|
|
|
|
@api.depends(
|
|
"currency_id",
|
|
"company_id",
|
|
"move_id.invoice_currency_rate",
|
|
"move_id.date",
|
|
"move_id.manual_currency_rate",
|
|
)
|
|
def _compute_currency_rate(self):
|
|
res = super()._compute_currency_rate()
|
|
for line in self:
|
|
if not line.move_id.manual_currency:
|
|
continue
|
|
# Currency Rate on move line use 'company_rate'
|
|
rate = (
|
|
line.move_id._origin.manual_currency_rate
|
|
if line.move_id.type_currency == "company_rate"
|
|
else (1.0 / line.move_id._origin.manual_currency_rate)
|
|
)
|
|
line.currency_rate = rate
|
|
return res
|