Initial commit: Odoo 18.0-20251222 extra-addons
This commit is contained in:
4
account_asset_management/wizard/__init__.py
Executable file
4
account_asset_management/wizard/__init__.py
Executable file
@@ -0,0 +1,4 @@
|
||||
from . import account_asset_compute
|
||||
from . import account_asset_remove
|
||||
from . import wiz_account_asset_report
|
||||
from . import wiz_asset_move_reverse
|
||||
64
account_asset_management/wizard/account_asset_compute.py
Executable file
64
account_asset_management/wizard/account_asset_compute.py
Executable file
@@ -0,0 +1,64 @@
|
||||
# Copyright 2009-2018 Noviat
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class AccountAssetCompute(models.TransientModel):
|
||||
_name = "account.asset.compute"
|
||||
_description = "Compute Assets"
|
||||
|
||||
date_end = fields.Date(
|
||||
string="Date",
|
||||
required=True,
|
||||
default=fields.Date.today,
|
||||
help="All depreciation lines prior to this date will be automatically"
|
||||
" posted",
|
||||
)
|
||||
note = fields.Text()
|
||||
|
||||
def _get_domain_asset_to_compute(self):
|
||||
self.ensure_one()
|
||||
return [("state", "=", "open")]
|
||||
|
||||
def asset_compute(self):
|
||||
assets = self.env["account.asset"].search(self._get_domain_asset_to_compute())
|
||||
created_move_ids, error_log = assets._compute_entries(
|
||||
self.date_end, check_triggers=True
|
||||
)
|
||||
|
||||
if error_log:
|
||||
module = __name__.split("addons.")[1].split(".")[0]
|
||||
result_view = self.env.ref(f"{module}.{self._table}_view_form_result")
|
||||
self.note = self.env._("Compute Assets errors") + ":\n" + error_log
|
||||
return {
|
||||
"name": self.env._("Compute Assets result"),
|
||||
"res_id": self.id,
|
||||
"view_mode": "form",
|
||||
"res_model": "account.asset.compute",
|
||||
"view_id": result_view.id,
|
||||
"target": "new",
|
||||
"type": "ir.actions.act_window",
|
||||
"context": {"asset_move_ids": created_move_ids},
|
||||
}
|
||||
|
||||
return {
|
||||
"name": self.env._("Created Asset Moves"),
|
||||
"view_mode": "list,form",
|
||||
"res_model": "account.move",
|
||||
"view_id": False,
|
||||
"domain": [("id", "in", created_move_ids)],
|
||||
"type": "ir.actions.act_window",
|
||||
}
|
||||
|
||||
def view_asset_moves(self):
|
||||
self.ensure_one()
|
||||
domain = [("id", "in", self.env.context.get("asset_move_ids", []))]
|
||||
return {
|
||||
"name": self.env._("Created Asset Moves"),
|
||||
"view_mode": "list,form",
|
||||
"res_model": "account.move",
|
||||
"view_id": False,
|
||||
"domain": domain,
|
||||
"type": "ir.actions.act_window",
|
||||
}
|
||||
53
account_asset_management/wizard/account_asset_compute.xml
Executable file
53
account_asset_management/wizard/account_asset_compute.xml
Executable file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="account_asset_compute_view_form" model="ir.ui.view">
|
||||
<field name="name">account.asset.compute</field>
|
||||
<field name="model">account.asset.compute</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<group>
|
||||
<field
|
||||
name="date_end"
|
||||
options="{'no_create': True, 'no_open': True}"
|
||||
/>
|
||||
</group>
|
||||
<footer>
|
||||
<button
|
||||
string="Compute"
|
||||
name="asset_compute"
|
||||
type="object"
|
||||
class="oe_highlight"
|
||||
/>
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_asset_compute_view_form_result" model="ir.ui.view">
|
||||
<field name="name">account.asset.compute.result</field>
|
||||
<field name="model">account.asset.compute</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<separator colspan="4" string="Results :" />
|
||||
<field name="note" colspan="4" nolabel="1" width="850" height="400" />
|
||||
<footer>
|
||||
<button
|
||||
string="View Asset Moves"
|
||||
name="view_asset_moves"
|
||||
type="object"
|
||||
class="oe_highlight"
|
||||
/>
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="account_asset_compute_action" model="ir.actions.act_window">
|
||||
<field name="name">Compute Assets</field>
|
||||
<field name="res_model">account.asset.compute</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="view_id" ref="account_asset_compute_view_form" />
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
</odoo>
|
||||
381
account_asset_management/wizard/account_asset_remove.py
Executable file
381
account_asset_management/wizard/account_asset_remove.py
Executable file
@@ -0,0 +1,381 @@
|
||||
# Copyright 2009-2018 Noviat
|
||||
# Copyright 2021 Tecnativa - João Marques
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
|
||||
|
||||
class AccountAssetRemove(models.TransientModel):
|
||||
_name = "account.asset.remove"
|
||||
_description = "Remove Asset"
|
||||
_check_company_auto = True
|
||||
_check_company_domain = models.check_company_domain_parent_of
|
||||
|
||||
company_id = fields.Many2one(
|
||||
comodel_name="res.company",
|
||||
string="Company",
|
||||
readonly=True,
|
||||
required=True,
|
||||
default=lambda self: self._default_company_id(),
|
||||
)
|
||||
currency_id = fields.Many2one(
|
||||
related="company_id.currency_id", string="Company Currency"
|
||||
)
|
||||
date_remove = fields.Date(
|
||||
string="Asset Removal Date",
|
||||
required=True,
|
||||
default=fields.Date.today,
|
||||
help="Removal date must be after the last posted entry "
|
||||
"in case of early removal",
|
||||
)
|
||||
force_date = fields.Date(string="Force accounting date")
|
||||
sale_value = fields.Monetary(
|
||||
default=lambda self: self._default_sale_value(),
|
||||
)
|
||||
account_sale_id = fields.Many2one(
|
||||
comodel_name="account.account",
|
||||
string="Asset Sale Account",
|
||||
domain=[("deprecated", "=", False)],
|
||||
check_company=True,
|
||||
default=lambda self: self._default_account_sale_id(),
|
||||
)
|
||||
account_plus_value_id = fields.Many2one(
|
||||
comodel_name="account.account",
|
||||
string="Plus-Value Account",
|
||||
domain=[("deprecated", "=", False)],
|
||||
check_company=True,
|
||||
default=lambda self: self._default_account_plus_value_id(),
|
||||
)
|
||||
account_min_value_id = fields.Many2one(
|
||||
comodel_name="account.account",
|
||||
string="Min-Value Account",
|
||||
domain=[("deprecated", "=", False)],
|
||||
check_company=True,
|
||||
default=lambda self: self._default_account_min_value_id(),
|
||||
)
|
||||
account_residual_value_id = fields.Many2one(
|
||||
comodel_name="account.account",
|
||||
string="Residual Value Account",
|
||||
domain=[("deprecated", "=", False)],
|
||||
check_company=True,
|
||||
default=lambda self: self._default_account_residual_value_id(),
|
||||
)
|
||||
posting_regime = fields.Selection(
|
||||
selection=lambda self: self._selection_posting_regime(),
|
||||
string="Removal Entry Policy",
|
||||
required=True,
|
||||
default=lambda self: self._get_posting_regime(),
|
||||
help="Removal Entry Policy \n"
|
||||
" * Residual Value: The non-depreciated value will be "
|
||||
"posted on the 'Residual Value Account' \n"
|
||||
" * Gain/Loss on Sale: The Gain or Loss will be posted on "
|
||||
"the 'Plus-Value Account' or 'Min-Value Account' ",
|
||||
)
|
||||
note = fields.Text("Notes")
|
||||
|
||||
@api.constrains("sale_value", "company_id")
|
||||
def _check_sale_value(self):
|
||||
if self.company_id.currency_id.compare_amounts(self.sale_value, 0) < 0:
|
||||
raise ValidationError(self.env._("The Sale Value must be positive!"))
|
||||
|
||||
@api.model
|
||||
def _default_company_id(self):
|
||||
asset_id = self.env.context.get("active_id")
|
||||
asset = self.env["account.asset"].browse(asset_id)
|
||||
return asset.company_id
|
||||
|
||||
@api.model
|
||||
def _default_sale_value(self):
|
||||
return self._get_sale()["sale_value"]
|
||||
|
||||
@api.model
|
||||
def _default_account_sale_id(self):
|
||||
return self._get_sale()["account_sale_id"]
|
||||
|
||||
def _get_sale(self):
|
||||
asset_id = self.env.context.get("active_id")
|
||||
sale_value = 0.0
|
||||
account_sale_id = False
|
||||
inv_lines = self.env["account.move.line"].search(
|
||||
[
|
||||
("asset_id", "=", asset_id),
|
||||
("move_id.move_type", "in", ("out_invoice", "out_refund")),
|
||||
]
|
||||
)
|
||||
for line in inv_lines:
|
||||
inv = line.move_id
|
||||
comp_curr = inv.currency_id
|
||||
inv_curr = inv.currency_id
|
||||
if line.move_id.payment_state == "paid" or line.parent_state == "draft":
|
||||
account_sale_id = line.account_id.id
|
||||
amount_inv_cur = line.price_subtotal
|
||||
amount_comp_cur = inv_curr._convert(
|
||||
amount_inv_cur, comp_curr, inv.company_id, inv.date
|
||||
)
|
||||
sale_value += amount_comp_cur
|
||||
return {"sale_value": sale_value, "account_sale_id": account_sale_id}
|
||||
|
||||
@api.model
|
||||
def _default_account_plus_value_id(self):
|
||||
asset_id = self.env.context.get("active_id")
|
||||
asset = self.env["account.asset"].browse(asset_id)
|
||||
return asset.profile_id.account_plus_value_id
|
||||
|
||||
@api.model
|
||||
def _default_account_min_value_id(self):
|
||||
asset_id = self.env.context.get("active_id")
|
||||
asset = self.env["account.asset"].browse(asset_id)
|
||||
return asset.profile_id.account_min_value_id
|
||||
|
||||
@api.model
|
||||
def _default_account_residual_value_id(self):
|
||||
asset_id = self.env.context.get("active_id")
|
||||
asset = self.env["account.asset"].browse(asset_id)
|
||||
return asset.profile_id.account_residual_value_id
|
||||
|
||||
@api.model
|
||||
def _selection_posting_regime(self):
|
||||
return [
|
||||
("residual_value", self.env._("Residual Value")),
|
||||
("gain_loss_on_sale", self.env._("Gain/Loss on Sale")),
|
||||
]
|
||||
|
||||
@api.model
|
||||
def _get_posting_regime(self):
|
||||
asset_obj = self.env["account.asset"]
|
||||
asset = asset_obj.browse(self.env.context.get("active_id"))
|
||||
country = asset and asset.company_id.country_id.code or False
|
||||
if country in self._residual_value_regime_countries():
|
||||
return "residual_value"
|
||||
else:
|
||||
return "gain_loss_on_sale"
|
||||
|
||||
def _residual_value_regime_countries(self):
|
||||
return ["FR"]
|
||||
|
||||
def remove(self):
|
||||
self.ensure_one()
|
||||
asset_line_obj = self.env["account.asset.line"]
|
||||
|
||||
asset_id = self.env.context.get("active_id")
|
||||
asset = self.env["account.asset"].browse(asset_id)
|
||||
asset_ref = asset.code and f"{asset.name} (ref: {asset.code})" or asset.name
|
||||
|
||||
if self.env.context.get("early_removal"):
|
||||
residual_value = self._prepare_early_removal(asset)
|
||||
else:
|
||||
residual_value = asset.value_residual
|
||||
|
||||
dlines = asset_line_obj.search(
|
||||
[
|
||||
("asset_id", "=", asset.id),
|
||||
("type", "=", "depreciate"),
|
||||
("move_check", "!=", False),
|
||||
],
|
||||
order="line_date desc",
|
||||
)
|
||||
if dlines:
|
||||
last_date = dlines[0].line_date
|
||||
else:
|
||||
create_dl = asset_line_obj.search(
|
||||
[("asset_id", "=", asset.id), ("type", "=", "create")]
|
||||
)[0]
|
||||
last_date = create_dl.line_date
|
||||
|
||||
if self.date_remove < last_date:
|
||||
raise UserError(
|
||||
self.env._(
|
||||
"The removal date must be after " "the last depreciation date."
|
||||
)
|
||||
)
|
||||
|
||||
line_name = asset._get_depreciation_entry_name(len(dlines) + 1)
|
||||
journal_id = asset.profile_id.journal_id.id
|
||||
if not self.force_date:
|
||||
date_remove = self.date_remove
|
||||
else:
|
||||
date_remove = self.force_date
|
||||
|
||||
# create move
|
||||
move_vals = {
|
||||
"date": date_remove,
|
||||
"ref": line_name,
|
||||
"journal_id": journal_id,
|
||||
"narration": self.note,
|
||||
}
|
||||
move = self.env["account.move"].create(move_vals)
|
||||
|
||||
# create asset line
|
||||
asset_line_vals = {
|
||||
"amount": residual_value,
|
||||
"asset_id": asset_id,
|
||||
"name": line_name,
|
||||
"line_date": self.date_remove,
|
||||
"move_id": move.id,
|
||||
"type": "remove",
|
||||
}
|
||||
asset_line_obj.create(asset_line_vals)
|
||||
asset.write({"state": "removed", "date_remove": self.date_remove})
|
||||
|
||||
# create move lines
|
||||
move_lines = self._get_removal_data(asset, residual_value)
|
||||
move.with_context(allow_asset=True).write({"line_ids": move_lines})
|
||||
|
||||
return {
|
||||
"name": self.env._("Asset '%s' Removal Journal Entry", asset_ref),
|
||||
"view_mode": "list,form",
|
||||
"res_model": "account.move",
|
||||
"view_id": False,
|
||||
"type": "ir.actions.act_window",
|
||||
"context": self.env.context,
|
||||
"domain": [("id", "=", move.id)],
|
||||
}
|
||||
|
||||
def _prepare_early_removal(self, asset):
|
||||
"""
|
||||
Generate last depreciation entry on the day before the removal date.
|
||||
"""
|
||||
date_remove = self.date_remove
|
||||
asset_line_obj = self.env["account.asset.line"]
|
||||
|
||||
currency = asset.company_id.currency_id
|
||||
|
||||
def _dlines(asset):
|
||||
lines = asset.depreciation_line_ids
|
||||
dlines = lines.filtered(
|
||||
lambda line: line.type == "depreciate"
|
||||
and not line.init_entry
|
||||
and not line.move_check
|
||||
)
|
||||
dlines = dlines.sorted(key=lambda line: line.line_date)
|
||||
return dlines
|
||||
|
||||
dlines = _dlines(asset)
|
||||
if not dlines:
|
||||
asset.compute_depreciation_board()
|
||||
dlines = _dlines(asset)
|
||||
if not dlines:
|
||||
return asset.value_residual
|
||||
first_to_depreciate_dl = dlines[0]
|
||||
|
||||
first_date = first_to_depreciate_dl.line_date
|
||||
if date_remove > first_date:
|
||||
raise UserError(
|
||||
self.env._(
|
||||
"You can't make an early removal if all the depreciation "
|
||||
"lines for previous periods are not posted."
|
||||
)
|
||||
)
|
||||
|
||||
if first_to_depreciate_dl.previous_id:
|
||||
last_depr_date = first_to_depreciate_dl.previous_id.line_date
|
||||
else:
|
||||
create_dl = asset_line_obj.search(
|
||||
[("asset_id", "=", asset.id), ("type", "=", "create")]
|
||||
)
|
||||
last_depr_date = create_dl.line_date
|
||||
|
||||
# Never create move.
|
||||
same_month = (
|
||||
last_depr_date.month == first_to_depreciate_dl.line_date.month and 1 or 0
|
||||
)
|
||||
|
||||
period_number_days = (first_date - last_depr_date).days + same_month
|
||||
new_line_date = date_remove + relativedelta(days=-1)
|
||||
to_depreciate_days = (new_line_date - last_depr_date).days + same_month
|
||||
to_depreciate_amount = currency.round(
|
||||
float(to_depreciate_days)
|
||||
/ float(period_number_days)
|
||||
* first_to_depreciate_dl.amount,
|
||||
)
|
||||
residual_value = asset.value_residual - to_depreciate_amount
|
||||
if to_depreciate_amount:
|
||||
update_vals = {
|
||||
"amount": to_depreciate_amount,
|
||||
"line_date": new_line_date,
|
||||
"line_days": to_depreciate_days,
|
||||
}
|
||||
first_to_depreciate_dl.write(update_vals)
|
||||
dlines[0].create_move()
|
||||
dlines -= dlines[0]
|
||||
dlines.unlink()
|
||||
return residual_value
|
||||
|
||||
def _get_removal_data(self, asset, residual_value):
|
||||
move_lines = []
|
||||
partner_id = asset.partner_id and asset.partner_id.id or False
|
||||
profile = asset.profile_id
|
||||
currency = asset.company_id.currency_id
|
||||
|
||||
# asset and asset depreciation account reversal
|
||||
depr_amount = asset.depreciation_base - residual_value
|
||||
depr_amount_comp = currency.compare_amounts(depr_amount, 0)
|
||||
if depr_amount:
|
||||
move_line_vals = {
|
||||
"name": asset.name,
|
||||
"account_id": profile.account_depreciation_id.id,
|
||||
"debit": depr_amount_comp > 0 and depr_amount or 0.0,
|
||||
"credit": depr_amount_comp < 0 and -depr_amount or 0.0,
|
||||
"partner_id": partner_id,
|
||||
"asset_id": asset.id,
|
||||
}
|
||||
move_lines.append((0, 0, move_line_vals))
|
||||
|
||||
depreciation_base_comp = currency.compare_amounts(asset.depreciation_base, 0)
|
||||
move_line_vals = {
|
||||
"name": asset.name,
|
||||
"account_id": profile.account_asset_id.id,
|
||||
"debit": (depreciation_base_comp < 0 and -asset.depreciation_base or 0.0),
|
||||
"credit": (depreciation_base_comp > 0 and asset.depreciation_base or 0.0),
|
||||
"partner_id": partner_id,
|
||||
"asset_id": asset.id,
|
||||
}
|
||||
move_lines.append((0, 0, move_line_vals))
|
||||
|
||||
if residual_value:
|
||||
if self.posting_regime == "residual_value":
|
||||
move_line_vals = {
|
||||
"name": asset.name,
|
||||
"account_id": self.account_residual_value_id.id,
|
||||
"analytic_distribution": asset.analytic_distribution,
|
||||
"debit": residual_value,
|
||||
"credit": 0.0,
|
||||
"partner_id": partner_id,
|
||||
"asset_id": asset.id,
|
||||
}
|
||||
move_lines.append((0, 0, move_line_vals))
|
||||
elif self.posting_regime == "gain_loss_on_sale":
|
||||
if self.sale_value:
|
||||
sale_value = self.sale_value
|
||||
move_line_vals = {
|
||||
"name": asset.name,
|
||||
"account_id": self.account_sale_id.id,
|
||||
"analytic_distribution": asset.analytic_distribution,
|
||||
"debit": sale_value,
|
||||
"credit": 0.0,
|
||||
"partner_id": partner_id,
|
||||
"asset_id": asset.id,
|
||||
}
|
||||
move_lines.append((0, 0, move_line_vals))
|
||||
balance = self.sale_value - residual_value
|
||||
balance_comp = currency.compare_amounts(balance, 0)
|
||||
account_id = (
|
||||
self.account_plus_value_id.id
|
||||
if balance_comp > 0
|
||||
else self.account_min_value_id.id
|
||||
)
|
||||
move_line_vals = {
|
||||
"name": asset.name,
|
||||
"account_id": account_id,
|
||||
"debit": balance_comp < 0 and -balance or 0.0,
|
||||
"credit": balance_comp > 0 and balance or 0.0,
|
||||
"analytic_distribution": asset.analytic_distribution,
|
||||
"partner_id": partner_id,
|
||||
"asset_id": asset.id,
|
||||
}
|
||||
move_lines.append((0, 0, move_line_vals))
|
||||
return move_lines
|
||||
58
account_asset_management/wizard/account_asset_remove.xml
Executable file
58
account_asset_management/wizard/account_asset_remove.xml
Executable file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="account_asset_remove_view_form" model="ir.ui.view">
|
||||
<field name="name">account.asset.remove.form</field>
|
||||
<field name="model">account.asset.remove</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<group>
|
||||
<group>
|
||||
<field name="company_id" invisible="1" />
|
||||
<field name="company_id" groups="base.group_multi_company" />
|
||||
<field name="date_remove" />
|
||||
<field name="force_date" />
|
||||
<field name="sale_value" />
|
||||
<field
|
||||
name="account_sale_id"
|
||||
invisible="sale_value == 0.0"
|
||||
required="sale_value > 0.0"
|
||||
/>
|
||||
</group>
|
||||
<group>
|
||||
<field
|
||||
name="account_plus_value_id"
|
||||
invisible="posting_regime == 'residual_value'"
|
||||
required="posting_regime != 'residual_value'"
|
||||
/>
|
||||
<field
|
||||
name="account_min_value_id"
|
||||
invisible="posting_regime == 'residual_value'"
|
||||
required="posting_regime != 'residual_value'"
|
||||
/>
|
||||
<field
|
||||
name="account_residual_value_id"
|
||||
invisible="posting_regime != 'residual_value'"
|
||||
required="posting_regime == 'residual_value'"
|
||||
/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="posting_regime" />
|
||||
</group>
|
||||
<separator string="Notes" colspan="4" />
|
||||
<field name="note" nolabel="1" colspan="4" />
|
||||
</group>
|
||||
<newline />
|
||||
<separator colspan="4" />
|
||||
<footer>
|
||||
<button
|
||||
string="Generate Removal entries"
|
||||
name="remove"
|
||||
type="object"
|
||||
class="oe_highlight"
|
||||
/>
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
75
account_asset_management/wizard/wiz_account_asset_report.py
Executable file
75
account_asset_management/wizard/wiz_account_asset_report.py
Executable file
@@ -0,0 +1,75 @@
|
||||
# Copyright 2009-2019 Noviat
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
import unicodedata
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class WizAccountAssetReport(models.TransientModel):
|
||||
_name = "wiz.account.asset.report"
|
||||
_description = "Financial Assets report"
|
||||
|
||||
asset_group_id = fields.Many2one(
|
||||
comodel_name="account.asset.group",
|
||||
string="Asset Group",
|
||||
default=lambda self: self._default_asset_group_id(),
|
||||
)
|
||||
date_from = fields.Date(string="Start Date", required=True)
|
||||
date_to = fields.Date(string="End Date", required=True)
|
||||
draft = fields.Boolean(string="Include draft assets")
|
||||
company_id = fields.Many2one(
|
||||
comodel_name="res.company",
|
||||
string="Company",
|
||||
required=True,
|
||||
default=lambda self: self._default_company_id(),
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _default_asset_group_id(self):
|
||||
return (
|
||||
self.env["account.asset.group"]
|
||||
.search([("parent_id", "=", False)], limit=1)
|
||||
.id
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _default_company_id(self):
|
||||
return self.env.company
|
||||
|
||||
@api.onchange("company_id")
|
||||
def _onchange_company_id(self):
|
||||
fy_dates = self.company_id.compute_fiscalyear_dates(fields.date.today())
|
||||
self.date_from = fy_dates["date_from"]
|
||||
self.date_to = fy_dates["date_to"]
|
||||
|
||||
@api.constrains("date_from", "date_to")
|
||||
def _check_dates(self):
|
||||
for wiz in self:
|
||||
if wiz.date_to <= wiz.date_from:
|
||||
raise UserError(
|
||||
self.env._("The Start Date must precede the Ending Date.")
|
||||
)
|
||||
|
||||
def xls_export(self):
|
||||
self.ensure_one()
|
||||
report_name = "account_asset_management.asset_report_xls"
|
||||
if self.asset_group_id:
|
||||
prefix = (
|
||||
unicodedata.normalize("NFKD", self.asset_group_id.name)
|
||||
.encode("ascii", "ignore")
|
||||
.decode("ascii")
|
||||
)
|
||||
prefix = "".join(x for x in prefix if x.isalnum())
|
||||
report_file = f"{prefix}_asset_report"
|
||||
else:
|
||||
report_file = "asset_report"
|
||||
report = {
|
||||
"type": "ir.actions.report",
|
||||
"report_type": "xlsx",
|
||||
"report_name": report_name,
|
||||
"context": dict(self.env.context, report_file=report_file),
|
||||
"data": {"dynamic_report": True},
|
||||
}
|
||||
return report
|
||||
51
account_asset_management/wizard/wiz_account_asset_report.xml
Executable file
51
account_asset_management/wizard/wiz_account_asset_report.xml
Executable file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="wiz_account_asset_report_view_form" model="ir.ui.view">
|
||||
<field name="name">Financial Assets report</field>
|
||||
<field name="model">wiz.account.asset.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<group col="2" colspan="4">
|
||||
<field
|
||||
name="asset_group_id"
|
||||
options="{'no_create_edit': True, 'no_create': True}"
|
||||
/>
|
||||
<field name="date_from" />
|
||||
<field name="date_to" />
|
||||
<field name="draft" />
|
||||
<field name="company_id" groups="base.group_multi_company" />
|
||||
</group>
|
||||
<footer>
|
||||
<button
|
||||
name="xls_export"
|
||||
string="Generate Report"
|
||||
type="object"
|
||||
default_focus="1"
|
||||
class="oe_highlight"
|
||||
/>
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="wiz_account_asset_report_action" model="ir.actions.act_window">
|
||||
<field name="name">Financial Assets report</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">wiz.account.asset.report</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="wiz_account_asset_report_view_form" />
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
<menuitem
|
||||
id="account_asset_report_menu"
|
||||
name="Financial Assets"
|
||||
parent="account.menu_finance_reports"
|
||||
/>
|
||||
<menuitem
|
||||
id="wiz_account_asset_report_menu"
|
||||
name="Financial Assets report"
|
||||
parent="account_asset_report_menu"
|
||||
action="wiz_account_asset_report_action"
|
||||
sequence="200"
|
||||
/>
|
||||
</odoo>
|
||||
60
account_asset_management/wizard/wiz_asset_move_reverse.py
Executable file
60
account_asset_management/wizard/wiz_asset_move_reverse.py
Executable file
@@ -0,0 +1,60 @@
|
||||
# Copyright 2021 ForgeFlow, S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class WizAssetMoveReverse(models.TransientModel):
|
||||
_name = "wiz.asset.move.reverse"
|
||||
_description = "Reverse posted journal entry on depreciation line"
|
||||
|
||||
line_id = fields.Many2one(
|
||||
comodel_name="account.asset.line",
|
||||
string="Asset Line",
|
||||
readonly=True,
|
||||
required=True,
|
||||
)
|
||||
date_reversal = fields.Date(
|
||||
string="Reversal date",
|
||||
required=True,
|
||||
default=fields.Date.context_today,
|
||||
)
|
||||
reason = fields.Char()
|
||||
journal_id = fields.Many2one(
|
||||
"account.journal",
|
||||
string="Use Specific Journal",
|
||||
help="If empty, uses the journal of the journal entry to be reversed.",
|
||||
)
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
res = super().default_get(fields)
|
||||
line_ids = (
|
||||
self.env["account.asset.line"].browse(self.env.context["active_ids"])
|
||||
if self.env.context.get("active_model") == "account.asset.line"
|
||||
else self.env["account.asset.line"]
|
||||
)
|
||||
res["line_id"] = line_ids[0].id if line_ids else False
|
||||
return res
|
||||
|
||||
def reverse_move(self):
|
||||
move = self.line_id.move_id
|
||||
move_reversal = (
|
||||
self.env["account.move.reversal"]
|
||||
.with_context(
|
||||
active_model="account.move", active_ids=move.ids, active_id=move.id
|
||||
)
|
||||
.create(
|
||||
{
|
||||
"date": self.date_reversal,
|
||||
"reason": self.reason,
|
||||
"journal_id": self.journal_id.id,
|
||||
}
|
||||
)
|
||||
)
|
||||
reversal = move_reversal.with_context(allow_asset=True).reverse_moves()
|
||||
reverse_move = self.env["account.move"].browse(reversal["res_id"])
|
||||
reverse_move.action_post()
|
||||
self.line_id.with_context(
|
||||
unlink_from_asset=True
|
||||
).update_asset_line_after_unlink_move()
|
||||
return True
|
||||
27
account_asset_management/wizard/wiz_asset_move_reverse.xml
Executable file
27
account_asset_management/wizard/wiz_asset_move_reverse.xml
Executable file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="wiz_asset_move_reverse_view_form" model="ir.ui.view">
|
||||
<field name="name">wiz.asset.move.reverse.form</field>
|
||||
<field name="model">wiz.asset.move.reverse</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Reverse Journal Entry">
|
||||
<group>
|
||||
<field name="line_id" invisible="True" />
|
||||
<field name="date_reversal" />
|
||||
<field name="journal_id" />
|
||||
<field name="reason" />
|
||||
</group>
|
||||
<newline />
|
||||
<footer>
|
||||
<button
|
||||
string="Confirm"
|
||||
name="reverse_move"
|
||||
type="object"
|
||||
class="oe_highlight"
|
||||
/>
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user