mirror of
https://github.com/bringout/oca-technical.git
synced 2026-04-23 07:12:08 +02:00
77 lines
3 KiB
Python
77 lines
3 KiB
Python
# Copyright 2019 Ecosoft <saranl@ecosoft.co.th>
|
|
# Copyright 2021 Tecnativa - Víctor Martínez
|
|
# Copyright 2024 Tecnativa - Pedro M. Baeza
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
from odoo import _, api, fields, models
|
|
from odoo.exceptions import ValidationError
|
|
from odoo.tools import float_compare
|
|
|
|
|
|
class AccountMove(models.Model):
|
|
_inherit = "account.move"
|
|
|
|
expense_ids = fields.One2many(
|
|
comodel_name="hr.expense", inverse_name="invoice_id", string="Expenses"
|
|
)
|
|
source_invoice_expense_id = fields.Many2one(
|
|
comodel_name="hr.expense",
|
|
help="Reference to the expense with a linked invoice that generated this"
|
|
"transfer journal entry",
|
|
)
|
|
|
|
def write(self, vals):
|
|
# Check if the amount of the invoice linked to an invoice is different
|
|
# Done here in the write instead of a Python constraint as the computed field
|
|
# amount_total is not yet updated on that moment
|
|
res = super().write(vals)
|
|
# Only need to check expenses amount when the invoice amount changes
|
|
if not ("amount_total" in vals or "tax_totals" in vals):
|
|
return res
|
|
DecimalPrecision = self.env["decimal.precision"]
|
|
precision = DecimalPrecision.precision_get("Product Price")
|
|
for move in self.filtered("expense_ids"):
|
|
expense_amount = sum(move.expense_ids.mapped("total_amount"))
|
|
if float_compare(expense_amount, move.amount_total, precision) != 0:
|
|
raise ValidationError(
|
|
_(
|
|
"You can't change the total amount, as there's an expense "
|
|
"linked to this invoice."
|
|
)
|
|
)
|
|
return res
|
|
|
|
def action_view_expense(self):
|
|
self.ensure_one()
|
|
return {
|
|
"type": "ir.actions.act_window",
|
|
"view_mode": "form",
|
|
"res_model": "hr.expense",
|
|
"res_id": self.expense_ids[:1].id,
|
|
}
|
|
|
|
|
|
class AccountMoveLine(models.Model):
|
|
_inherit = "account.move.line"
|
|
|
|
@api.constrains("account_id", "display_type")
|
|
def _check_payable_receivable(self):
|
|
_self = self.filtered("expense_id")
|
|
return super(AccountMoveLine, (self - _self))._check_payable_receivable()
|
|
|
|
def reconcile(self):
|
|
"""Mark expenses paid by employee having invoice when reconciling them."""
|
|
expenses = self.move_id.source_invoice_expense_id
|
|
not_paid_expenses = expenses.filtered(lambda x: x.state != "done")
|
|
res = super().reconcile()
|
|
not_paid_expense_sheets = not_paid_expenses.sheet_id.filtered(
|
|
lambda x: x.state != "done"
|
|
)
|
|
paid_expenses = not_paid_expenses.filtered(
|
|
lambda expense: expense.currency_id.is_zero(expense.amount_residual)
|
|
)
|
|
paid_expenses.write({"state": "done"})
|
|
paid_sheets = not_paid_expense_sheets.filtered(
|
|
lambda x: all(expense.state == "done" for expense in x.expense_line_ids)
|
|
)
|
|
paid_sheets.set_to_paid()
|
|
return res
|