Files
Odoo-18.0-20251222/account_manual_currency/models/account_move.py
tocmo0nlord adbe430761
Some checks failed
pre-commit / pre-commit (push) Has been cancelled
tests / Detect unreleased dependencies (push) Has been cancelled
tests / test with OCB (push) Has been cancelled
tests / test with Odoo (push) Has been cancelled
Initial commit: Odoo 18.0-20251222 extra-addons
2026-03-13 20:43:25 +00:00

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