2018-08-05 20:33:56 +02:00
|
|
|
# Copyright 2009-2018 Noviat
|
2021-01-14 08:53:25 +01:00
|
|
|
# Copyright 2021 Tecnativa - João Marques
|
2021-03-11 09:18:10 +01:00
|
|
|
# Copyright 2021 Tecnativa - Víctor Martínez
|
2018-08-05 20:33:56 +02:00
|
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
|
|
|
|
|
|
import logging
|
|
|
|
|
2020-01-29 18:34:31 +01:00
|
|
|
from odoo import _, api, fields, models
|
2018-08-05 20:33:56 +02:00
|
|
|
from odoo.exceptions import UserError
|
|
|
|
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
# List of move's fields that can't be modified if move is linked
|
|
|
|
# with a depreciation line
|
2020-01-29 18:34:31 +01:00
|
|
|
FIELDS_AFFECTS_ASSET_MOVE = {"journal_id", "date"}
|
2018-08-05 20:33:56 +02:00
|
|
|
# List of move line's fields that can't be modified if move is linked
|
|
|
|
# with a depreciation line
|
2020-01-29 18:34:31 +01:00
|
|
|
FIELDS_AFFECTS_ASSET_MOVE_LINE = {
|
2020-01-29 18:37:08 +01:00
|
|
|
"credit",
|
|
|
|
"debit",
|
|
|
|
"account_id",
|
|
|
|
"journal_id",
|
|
|
|
"date",
|
|
|
|
"asset_profile_id",
|
|
|
|
"asset_id",
|
2020-01-29 18:34:31 +01:00
|
|
|
}
|
2018-08-05 20:33:56 +02:00
|
|
|
|
|
|
|
|
|
|
|
class AccountMove(models.Model):
|
2020-01-29 18:34:31 +01:00
|
|
|
_inherit = "account.move"
|
2018-08-05 20:33:56 +02:00
|
|
|
|
2018-10-01 11:57:07 +02:00
|
|
|
def unlink(self):
|
|
|
|
# for move in self:
|
2020-01-29 18:34:31 +01:00
|
|
|
deprs = self.env["account.asset.line"].search(
|
|
|
|
[("move_id", "in", self.ids), ("type", "in", ["depreciate", "remove"])]
|
|
|
|
)
|
|
|
|
if deprs and not self.env.context.get("unlink_from_asset"):
|
2018-10-01 11:57:07 +02:00
|
|
|
raise UserError(
|
2020-01-29 18:34:31 +01:00
|
|
|
_(
|
|
|
|
"You are not allowed to remove an accounting entry "
|
|
|
|
"linked to an asset."
|
|
|
|
"\nYou should remove such entries from the asset."
|
|
|
|
)
|
|
|
|
)
|
2018-10-01 11:57:07 +02:00
|
|
|
# trigger store function
|
2020-01-29 18:34:31 +01:00
|
|
|
deprs.write({"move_id": False})
|
2018-10-01 11:57:07 +02:00
|
|
|
return super().unlink()
|
2018-08-05 20:33:56 +02:00
|
|
|
|
|
|
|
def write(self, vals):
|
|
|
|
if set(vals).intersection(FIELDS_AFFECTS_ASSET_MOVE):
|
2020-01-29 18:34:31 +01:00
|
|
|
deprs = self.env["account.asset.line"].search(
|
|
|
|
[("move_id", "in", self.ids), ("type", "=", "depreciate")]
|
|
|
|
)
|
2018-10-01 11:57:07 +02:00
|
|
|
if deprs:
|
|
|
|
raise UserError(
|
2020-01-29 18:34:31 +01:00
|
|
|
_(
|
|
|
|
"You cannot change an accounting entry "
|
|
|
|
"linked to an asset depreciation line."
|
|
|
|
)
|
|
|
|
)
|
2018-10-01 11:57:07 +02:00
|
|
|
return super().write(vals)
|
2018-08-05 20:33:56 +02:00
|
|
|
|
2021-01-14 08:53:25 +01:00
|
|
|
def action_post(self):
|
|
|
|
super().action_post()
|
2020-01-29 18:37:08 +01:00
|
|
|
for move in self:
|
|
|
|
for aml in move.line_ids.filtered("asset_profile_id"):
|
2021-01-14 08:53:25 +01:00
|
|
|
depreciation_base = aml.price_subtotal
|
2021-04-14 14:51:00 +02:00
|
|
|
if not aml.name:
|
|
|
|
raise UserError(
|
|
|
|
_("Asset name must be set in the label of the line.")
|
|
|
|
)
|
2020-01-29 18:37:08 +01:00
|
|
|
vals = {
|
|
|
|
"name": aml.name,
|
|
|
|
"code": move.name,
|
|
|
|
"profile_id": aml.asset_profile_id.id,
|
|
|
|
"purchase_value": depreciation_base,
|
|
|
|
"partner_id": aml.partner_id.id,
|
|
|
|
"date_start": move.date,
|
|
|
|
"account_analytic_id": aml.analytic_account_id.id,
|
|
|
|
}
|
|
|
|
if self.env.context.get("company_id"):
|
|
|
|
vals["company_id"] = self.env.context["company_id"]
|
|
|
|
asset = (
|
|
|
|
self.env["account.asset"]
|
|
|
|
.with_context(create_asset_from_move_line=True, move_id=move.id)
|
|
|
|
.create(vals)
|
|
|
|
)
|
|
|
|
aml.with_context(allow_asset=True).asset_id = asset.id
|
2020-07-03 16:11:20 +02:00
|
|
|
refs = [
|
|
|
|
"<a href=# data-oe-model=account.asset data-oe-id=%s>%s</a>"
|
|
|
|
% tuple(name_get)
|
|
|
|
for name_get in move.line_ids.filtered(
|
|
|
|
"asset_profile_id"
|
|
|
|
).asset_id.name_get()
|
|
|
|
]
|
2020-09-24 14:18:04 +02:00
|
|
|
if refs:
|
|
|
|
message = _("This invoice created the asset(s): %s") % ", ".join(refs)
|
|
|
|
move.message_post(body=message)
|
2020-01-29 18:37:08 +01:00
|
|
|
|
|
|
|
def button_draft(self):
|
2020-12-22 09:06:05 +01:00
|
|
|
invoices = self.filtered(lambda r: r.is_purchase_document())
|
2020-01-29 18:37:08 +01:00
|
|
|
if invoices:
|
|
|
|
invoices.line_ids.asset_id.unlink()
|
|
|
|
super().button_draft()
|
|
|
|
|
|
|
|
def _reverse_move_vals(self, default_values, cancel=True):
|
|
|
|
move_vals = super()._reverse_move_vals(default_values, cancel)
|
2021-01-26 15:59:48 +01:00
|
|
|
if move_vals["move_type"] not in ("out_invoice", "out_refund"):
|
2020-01-29 18:37:08 +01:00
|
|
|
for line_command in move_vals.get("line_ids", []):
|
|
|
|
line_vals = line_command[2] # (0, 0, {...})
|
|
|
|
asset = self.env["account.asset"].browse(line_vals["asset_id"])
|
|
|
|
asset.unlink()
|
|
|
|
line_vals.update(asset_profile_id=False, asset_id=False)
|
|
|
|
return move_vals
|
|
|
|
|
2018-08-05 20:33:56 +02:00
|
|
|
|
|
|
|
class AccountMoveLine(models.Model):
|
2020-01-29 18:34:31 +01:00
|
|
|
_inherit = "account.move.line"
|
2018-08-05 20:33:56 +02:00
|
|
|
|
|
|
|
asset_profile_id = fields.Many2one(
|
2020-01-29 18:34:31 +01:00
|
|
|
comodel_name="account.asset.profile", string="Asset Profile"
|
|
|
|
)
|
2018-08-05 20:33:56 +02:00
|
|
|
asset_id = fields.Many2one(
|
2020-01-29 18:34:31 +01:00
|
|
|
comodel_name="account.asset", string="Asset", ondelete="restrict"
|
|
|
|
)
|
2018-08-05 20:33:56 +02:00
|
|
|
|
2020-01-29 18:34:31 +01:00
|
|
|
@api.onchange("account_id")
|
2018-08-05 20:33:56 +02:00
|
|
|
def _onchange_account_id(self):
|
2021-03-11 09:18:10 +01:00
|
|
|
if self.account_id.asset_profile_id:
|
|
|
|
self.asset_profile_id = self.account_id.asset_profile_id
|
2020-01-29 18:37:08 +01:00
|
|
|
super()._onchange_account_id()
|
|
|
|
|
2021-03-11 09:18:10 +01:00
|
|
|
@api.onchange("asset_profile_id")
|
|
|
|
def _onchange_asset_profile_id(self):
|
|
|
|
if self.asset_profile_id.account_asset_id:
|
|
|
|
self.account_id = self.asset_profile_id.account_asset_id
|
|
|
|
|
2020-01-29 18:37:08 +01:00
|
|
|
@api.model_create_multi
|
|
|
|
def create(self, vals_list):
|
|
|
|
for vals in vals_list:
|
|
|
|
move = self.env["account.move"].browse(vals.get("move_id"))
|
|
|
|
if not move.is_sale_document():
|
|
|
|
if vals.get("asset_id") and not self.env.context.get("allow_asset"):
|
|
|
|
raise UserError(
|
|
|
|
_(
|
|
|
|
"You are not allowed to link "
|
|
|
|
"an accounting entry to an asset."
|
|
|
|
"\nYou should generate such entries from the asset."
|
|
|
|
)
|
|
|
|
)
|
|
|
|
records = super().create(vals_list)
|
|
|
|
for record in records:
|
|
|
|
record._expand_asset_line()
|
|
|
|
return records
|
2018-08-05 20:33:56 +02:00
|
|
|
|
2018-10-01 11:57:07 +02:00
|
|
|
def write(self, vals):
|
2020-01-29 18:34:31 +01:00
|
|
|
if set(vals).intersection(FIELDS_AFFECTS_ASSET_MOVE_LINE) and not (
|
|
|
|
self.env.context.get("allow_asset_removal")
|
|
|
|
and list(vals.keys()) == ["asset_id"]
|
2018-10-01 11:57:07 +02:00
|
|
|
):
|
2019-06-20 19:19:51 +02:00
|
|
|
# Check if at least one asset is linked to a move
|
|
|
|
linked_asset = False
|
2020-01-29 18:37:08 +01:00
|
|
|
for move_line in self.filtered(lambda r: not r.move_id.is_sale_document()):
|
|
|
|
linked_asset = move_line.asset_id
|
2019-06-20 19:19:51 +02:00
|
|
|
if linked_asset:
|
|
|
|
raise UserError(
|
2020-01-29 18:34:31 +01:00
|
|
|
_(
|
|
|
|
"You cannot change an accounting item "
|
|
|
|
"linked to an asset depreciation line."
|
|
|
|
)
|
|
|
|
)
|
2020-01-29 18:37:08 +01:00
|
|
|
|
|
|
|
if (
|
|
|
|
self.filtered(lambda r: not r.move_id.is_sale_document())
|
|
|
|
and vals.get("asset_id")
|
|
|
|
and not self.env.context.get("allow_asset")
|
|
|
|
):
|
2018-08-05 20:33:56 +02:00
|
|
|
raise UserError(
|
2020-01-29 18:34:31 +01:00
|
|
|
_(
|
|
|
|
"You are not allowed to link "
|
|
|
|
"an accounting entry to an asset."
|
|
|
|
"\nYou should generate such entries from the asset."
|
|
|
|
)
|
|
|
|
)
|
2020-01-29 18:37:08 +01:00
|
|
|
super().write(vals)
|
|
|
|
if "quantity" in vals or "asset_profile_id" in vals:
|
|
|
|
for record in self:
|
|
|
|
record._expand_asset_line()
|
|
|
|
return True
|
2018-08-05 20:33:56 +02:00
|
|
|
|
2020-01-29 18:37:08 +01:00
|
|
|
def _expand_asset_line(self):
|
|
|
|
self.ensure_one()
|
|
|
|
if self.asset_profile_id and self.quantity > 1.0:
|
|
|
|
profile = self.asset_profile_id
|
|
|
|
if profile.asset_product_item:
|
|
|
|
aml = self.with_context(check_move_validity=False)
|
|
|
|
qty = self.quantity
|
|
|
|
name = self.name
|
|
|
|
aml.write({"quantity": 1, "name": "{} {}".format(name, 1)})
|
|
|
|
aml._onchange_price_subtotal()
|
|
|
|
for i in range(1, int(qty)):
|
|
|
|
aml.copy({"name": "{} {}".format(name, i + 1)})
|
|
|
|
aml.move_id._onchange_invoice_line_ids()
|