Initial commit: Odoo 18.0-20251222 extra-addons
This commit is contained in:
3
account_asset_compute_batch/models/__init__.py
Executable file
3
account_asset_compute_batch/models/__init__.py
Executable file
@@ -0,0 +1,3 @@
|
||||
from . import account_asset_line
|
||||
from . import account_move
|
||||
from . import account_asset_compute_batch
|
||||
239
account_asset_compute_batch/models/account_asset_compute_batch.py
Executable file
239
account_asset_compute_batch/models/account_asset_compute_batch.py
Executable file
@@ -0,0 +1,239 @@
|
||||
# Copyright 2021 Ecosoft Co., Ltd. (http://ecosoft.co.th)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
import logging
|
||||
from sys import exc_info
|
||||
from traceback import format_exception
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AssetComputeBatch(models.Model):
|
||||
_name = "account.asset.compute.batch"
|
||||
_inherit = ["mail.thread", "mail.activity.mixin"]
|
||||
_description = "Compute Depreciation Batch"
|
||||
_check_company_auto = True
|
||||
|
||||
name = fields.Char()
|
||||
description = fields.Char()
|
||||
date_end = fields.Date(
|
||||
string="Date",
|
||||
default=fields.Date.today,
|
||||
help="All depreciation lines prior to this date will be computed",
|
||||
)
|
||||
note = fields.Text(string="Exception Error")
|
||||
profile_ids = fields.Many2many(
|
||||
comodel_name="account.asset.profile",
|
||||
string="Profiles",
|
||||
help="Selected asset to run depreciation. Run all profiles if left blank.",
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
comodel_name="res.company",
|
||||
default=lambda self: self.env.company,
|
||||
)
|
||||
delay_post = fields.Boolean(
|
||||
string="Delay Posting",
|
||||
help="Dalay account posting of newly created journaly entries, "
|
||||
"by setting auto_post='at_date', to be posted by cron job",
|
||||
)
|
||||
auto_compute = fields.Boolean(
|
||||
help="Auto compute draft batches with 'Date' up to today, by cron job",
|
||||
)
|
||||
move_line_ids = fields.One2many(
|
||||
comodel_name="account.move.line",
|
||||
inverse_name="compute_batch_id",
|
||||
readonly=True,
|
||||
)
|
||||
state = fields.Selection(
|
||||
selection=[
|
||||
("draft", "Draft"),
|
||||
("computed", "Computed"),
|
||||
("exception", "Exception"),
|
||||
],
|
||||
default="draft",
|
||||
tracking=True,
|
||||
index=True,
|
||||
required=True,
|
||||
readonly=True,
|
||||
)
|
||||
profile_report = fields.One2many(
|
||||
comodel_name="account.asset.compute.batch.profile.report",
|
||||
inverse_name="compute_batch_id",
|
||||
)
|
||||
currency_id = fields.Many2one(
|
||||
comodel_name="res.currency",
|
||||
default=lambda self: self.env.company.currency_id,
|
||||
)
|
||||
depre_amount = fields.Monetary(
|
||||
string="Depreciation Amount",
|
||||
compute="_compute_depre_amount",
|
||||
)
|
||||
_sql_constraints = [
|
||||
("name_uniq", "UNIQUE(name)", "Batch name must be unique!"),
|
||||
]
|
||||
|
||||
@api.depends("state")
|
||||
def _compute_depre_amount(self):
|
||||
res = self.env["account.move.line"].read_group(
|
||||
domain=[("compute_batch_id", "in", self.ids)],
|
||||
fields=["compute_batch_id", "debit"],
|
||||
groupby=["compute_batch_id"],
|
||||
)
|
||||
res = {x["compute_batch_id"][0]: x["debit"] for x in res}
|
||||
for rec in self:
|
||||
rec.depre_amount = res.get(rec.id)
|
||||
|
||||
def unlink(self):
|
||||
if self.filtered(lambda batch: batch.state != "draft"):
|
||||
raise ValidationError(self.env._("Only draft batch can be deleted!"))
|
||||
return super().unlink()
|
||||
|
||||
def action_compute(self):
|
||||
asset_model = self.env["account.asset"]
|
||||
for batch in self:
|
||||
domain = [
|
||||
("state", "=", "open"),
|
||||
("profile_id", "in", batch.profile_ids.ids),
|
||||
]
|
||||
assets = asset_model.search(domain)
|
||||
if not assets:
|
||||
continue
|
||||
|
||||
created_move_ids, error_log = assets.with_context(
|
||||
compute_batch_id=batch.id,
|
||||
delay_post=batch.delay_post,
|
||||
)._compute_entries(self.date_end, check_triggers=True)
|
||||
if error_log:
|
||||
batch.write(
|
||||
{
|
||||
"note": self.env._("Compute Assets errors") + ":\n" + error_log,
|
||||
"state": "exception",
|
||||
}
|
||||
)
|
||||
else:
|
||||
batch.write({"state": "computed"})
|
||||
|
||||
def open_move_lines(self):
|
||||
self.ensure_one()
|
||||
action = {
|
||||
"name": self.env._("Journal Items"),
|
||||
"view_mode": "list,form",
|
||||
"res_model": "account.move.line",
|
||||
"type": "ir.actions.act_window",
|
||||
"context": {"search_default_group_by_account": True},
|
||||
"domain": [("id", "in", self.move_line_ids.ids)],
|
||||
}
|
||||
return action
|
||||
|
||||
def open_moves(self):
|
||||
self.ensure_one()
|
||||
action = {
|
||||
"name": self.env._("Journal Entries"),
|
||||
"view_mode": "list,form",
|
||||
"res_model": "account.move",
|
||||
"type": "ir.actions.act_window",
|
||||
"domain": [("id", "in", self.move_line_ids.mapped("move_id").ids)],
|
||||
"search_view_id": [
|
||||
self.env.ref("account.view_account_move_filter").id,
|
||||
"search",
|
||||
],
|
||||
"views": [
|
||||
[self.env.ref("account.view_move_tree").id, "list"],
|
||||
[self.env.ref("account.view_move_form").id, "form"],
|
||||
],
|
||||
}
|
||||
return action
|
||||
|
||||
@api.model
|
||||
def _autocompute_draft_batches(self):
|
||||
"""This method is called from a cron job.
|
||||
It is used to auto compute account.asset.compute.batch with auto_compute=True
|
||||
"""
|
||||
records = self.search(
|
||||
[
|
||||
("state", "=", "draft"),
|
||||
("date_end", "<=", fields.Date.context_today(self)),
|
||||
("auto_compute", "=", True),
|
||||
]
|
||||
)
|
||||
for ids in self.env.cr.split_for_in_conditions(records.ids, size=1000):
|
||||
batches = self.browse(ids)
|
||||
try:
|
||||
with self.env.cr.savepoint():
|
||||
batches.action_compute()
|
||||
except Exception:
|
||||
exc_info()[0]
|
||||
tb = "".join(format_exception(*exc_info()))
|
||||
batch_ref = ", ".join(batches.mapped("name"))
|
||||
error_msg = self.env._(
|
||||
"Error while processing batches %(batch_ref)s: \n\n%(tb)s"
|
||||
) % {"batch_ref": batch_ref, "tb": tb}
|
||||
_logger.error("%s, %s", self._name, error_msg)
|
||||
|
||||
|
||||
class AccountAssetComputeBatchProfileReport(models.Model):
|
||||
_name = "account.asset.compute.batch.profile.report"
|
||||
_description = "Depreciation Amount by Profile"
|
||||
_auto = False
|
||||
_order = "profile_id desc"
|
||||
|
||||
compute_batch_id = fields.Many2one(
|
||||
comodel_name="account.asset.compute.batch",
|
||||
readonly=True,
|
||||
)
|
||||
profile_id = fields.Many2one(
|
||||
string="Asset Profile",
|
||||
comodel_name="account.asset.profile",
|
||||
readonly=True,
|
||||
)
|
||||
currency_id = fields.Many2one(
|
||||
comodel_name="res.currency",
|
||||
readonly=True,
|
||||
)
|
||||
amount = fields.Monetary(
|
||||
readonly=True,
|
||||
)
|
||||
|
||||
@property
|
||||
def _table_query(self):
|
||||
"""
|
||||
Build SQL query for depreciation amount by profile report.
|
||||
"""
|
||||
return f"{self._select()} {self._from()} {self._where()} {self._group_by()}"
|
||||
|
||||
@api.model
|
||||
def _select(self):
|
||||
return """
|
||||
SELECT
|
||||
min(ml.id) as id,
|
||||
ml.compute_batch_id,
|
||||
p.id as profile_id,
|
||||
ml.currency_id,
|
||||
sum(ml.debit) as amount
|
||||
"""
|
||||
|
||||
@api.model
|
||||
def _from(self):
|
||||
return """
|
||||
FROM account_move_line ml
|
||||
JOIN account_asset a on a.id = ml.asset_id
|
||||
JOIN account_asset_profile p on p.id = a.profile_id
|
||||
"""
|
||||
|
||||
@api.model
|
||||
def _where(self):
|
||||
return """
|
||||
WHERE
|
||||
ml.compute_batch_id IS NOT NULL
|
||||
"""
|
||||
|
||||
@api.model
|
||||
def _group_by(self):
|
||||
return """
|
||||
GROUP BY
|
||||
ml.compute_batch_id,
|
||||
p.id,
|
||||
ml.currency_id
|
||||
"""
|
||||
16
account_asset_compute_batch/models/account_asset_line.py
Executable file
16
account_asset_compute_batch/models/account_asset_line.py
Executable file
@@ -0,0 +1,16 @@
|
||||
# Copyright 2021 Ecosoft Co., Ltd. (http://ecosoft.co.th)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class AccountAssetLine(models.Model):
|
||||
_inherit = "account.asset.line"
|
||||
|
||||
def _setup_move_line_data(self, depreciation_date, account, ml_type, move):
|
||||
move_line_data = super()._setup_move_line_data(
|
||||
depreciation_date, account, ml_type, move
|
||||
)
|
||||
if self.env.context.get("compute_batch_id"):
|
||||
move_line_data["compute_batch_id"] = self.env.context["compute_batch_id"]
|
||||
return move_line_data
|
||||
25
account_asset_compute_batch/models/account_move.py
Executable file
25
account_asset_compute_batch/models/account_move.py
Executable file
@@ -0,0 +1,25 @@
|
||||
# Copyright 2021 Ecosoft Co., Ltd. (http://ecosoft.co.th)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class AccountMove(models.Model):
|
||||
_inherit = "account.move"
|
||||
|
||||
def action_post(self):
|
||||
if self.env.context.get("delay_post"):
|
||||
self.write({"auto_post": "at_date"})
|
||||
return False
|
||||
return super().action_post()
|
||||
|
||||
|
||||
class AccountMoveLine(models.Model):
|
||||
_inherit = "account.move.line"
|
||||
|
||||
compute_batch_id = fields.Many2one(
|
||||
comodel_name="account.asset.compute.batch",
|
||||
index=True,
|
||||
ondelete="set null",
|
||||
readonly=True,
|
||||
)
|
||||
Reference in New Issue
Block a user