Initial commit: Odoo 18.0-20251222 extra-addons
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

This commit is contained in:
tocmo0nlord
2026-03-13 20:43:25 +00:00
parent 36e847a7df
commit adbe430761
9472 changed files with 1265727 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
from . import account_asset_line
from . import account_move
from . import account_asset_compute_batch

View 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
"""

View 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

View 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,
)