Skip to content

Commit

Permalink
[FIX] budget_control: carry forward
Browse files Browse the repository at this point in the history
  • Loading branch information
Saran440 committed Jul 25, 2024
1 parent 7f632b0 commit a1e04b1
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 115 deletions.
56 changes: 46 additions & 10 deletions budget_control/models/analytic_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,23 @@ def _find_next_analytic(self, next_date_range):

def _update_val_analytic(self, next_analytic, next_date_range):
BudgetPeriod = self.env["budget.period"]
vals_update = {}
type_id = next_analytic.budget_period_id.plan_date_range_type_id
period_id = BudgetPeriod.search(

Check warning on line 171 in budget_control/models/analytic_account.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/analytic_account.py#L168-L171

Added lines #L168 - L171 were not covered by tests
[
("bm_date_from", "=", next_date_range),
("plan_date_range_type_id", "=", type_id.id),
]
)
return {"budget_period_id": period_id.id}
if period_id:
vals_update = {"budget_period_id": period_id.id}

Check warning on line 178 in budget_control/models/analytic_account.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/analytic_account.py#L178

Added line #L178 was not covered by tests
else:
# No budget period found, update date_from and date_to
vals_update = {

Check warning on line 181 in budget_control/models/analytic_account.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/analytic_account.py#L181

Added line #L181 was not covered by tests
"bm_date_from": next_date_range,
"bm_date_to": next_analytic.bm_date_to + relativedelta(years=1),
}
return vals_update

Check warning on line 185 in budget_control/models/analytic_account.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/analytic_account.py#L185

Added line #L185 was not covered by tests

def _auto_create_next_analytic(self, next_date_range):
self.ensure_one()

Check warning on line 188 in budget_control/models/analytic_account.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/analytic_account.py#L188

Added line #L188 was not covered by tests
Expand All @@ -183,17 +192,44 @@ def _auto_create_next_analytic(self, next_date_range):
next_analytic.write(val_update)
return next_analytic

Check warning on line 193 in budget_control/models/analytic_account.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/analytic_account.py#L190-L193

Added lines #L190 - L193 were not covered by tests

def next_year_analytic(self, auto_create=True):
@api.model
def _get_analytic_date(self, analytic_account, order):
"""
Finds the minimum or maximum date of an analytic account.
:param analytic_account: Analytic account record
:param order: The order to search for the earliest or latest date
:return: The earliest or latest date found, or None if no records
"""

# Access the analytic line model
AnalyticAccount = self.env["account.analytic.account"]

Check warning on line 206 in budget_control/models/analytic_account.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/analytic_account.py#L206

Added line #L206 was not covered by tests

# Construct the domain to search for the specific analytic account
domain = [('id', 'in', [analytic_id for analytic_id, _ in analytic_account.items()])]
# Perform the search
result = AnalyticAccount.search(domain, order=order, limit=1)

Check warning on line 211 in budget_control/models/analytic_account.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/analytic_account.py#L211

Added line #L211 was not covered by tests

# Return the date if a record is found, else None
return result

Check warning on line 214 in budget_control/models/analytic_account.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/analytic_account.py#L214

Added line #L214 was not covered by tests

@api.model
def next_year_analytic(self, analytic_distribution, auto_create=True):
"""Find next analytic from analytic date_to + 1,
if bm_date_to = False, this is an open end analytic, always return False"""
self.ensure_one()
if not self.bm_date_to:
return False
next_date_range = self.bm_date_to + relativedelta(days=1)
next_analytic = self._find_next_analytic(next_date_range)
if not next_analytic and auto_create:
next_analytic = self._auto_create_next_analytic(next_date_range)
return next_analytic
next_analytic_distribution = {}

Check warning on line 220 in budget_control/models/analytic_account.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/analytic_account.py#L220

Added line #L220 was not covered by tests
for analytic_id, aa_percent in analytic_distribution.items():
analytic = self.browse(int(analytic_id))

Check warning on line 222 in budget_control/models/analytic_account.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/analytic_account.py#L222

Added line #L222 was not covered by tests
# Use same analytic
if not analytic.bm_date_to:
next_analytic_distribution[str(analytic_id)] = aa_percent
continue
next_date_range = analytic.bm_date_to + relativedelta(days=1)
next_analytic = analytic._find_next_analytic(next_date_range)

Check warning on line 228 in budget_control/models/analytic_account.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/analytic_account.py#L225-L228

Added lines #L225 - L228 were not covered by tests
if not next_analytic and auto_create:
next_analytic = analytic._auto_create_next_analytic(next_date_range)
next_analytic_distribution[str(next_analytic.id)] = aa_percent
return next_analytic_distribution

Check warning on line 232 in budget_control/models/analytic_account.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/analytic_account.py#L230-L232

Added lines #L230 - L232 were not covered by tests

def _check_budget_control_status(self, budget_period_id=False):
"""Warning for budget_control on budget_period, but not in controlled"""
Expand Down
126 changes: 62 additions & 64 deletions budget_control/models/budget_commit_forward.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.exceptions import UserError, ValidationError


class BudgetCommitForward(models.Model):
Expand Down Expand Up @@ -63,7 +63,7 @@ def _compute_missing_analytic(self):
for rec in self:
rec.missing_analytic = any(

Check warning on line 64 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L64

Added line #L64 was not covered by tests
rec.forward_line_ids.filtered_domain(
[("to_analytic_account_id", "=", False)]
[("to_analytic_distribution", "=", False)]
)
)

Expand Down Expand Up @@ -98,32 +98,30 @@ def _prepare_vals_forward(self, docs, res_model):
analytic_account = (

Check warning on line 98 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L98

Added line #L98 was not covered by tests
doc.fwd_analytic_distribution or doc[doc._budget_analytic_field]
)
# 1 line document can multi analytic, This function will split analytic
for analytic_id, aa_percent in analytic_account.items():
analytic = AnalyticAccount.browse(int(analytic_id))
method_type = False
to_analytic_account_id = False
if analytic.bm_date_to and analytic.bm_date_to < self.to_date_commit:
method_type = "new"
to_analytic_account_id = analytic.next_year_analytic(
auto_create=False
)
value_dict.append(
{
"forward_id": self.id,
"analytic_account_id": analytic_id,
"analytic_percent": aa_percent,
"method_type": method_type,
"res_model": res_model,
"res_id": doc.id,
"document_id": "{},{}".format(doc._name, doc.id),
"document_number": self._get_document_number(doc),
"to_analytic_account_id": to_analytic_account_id.id,
# Total amount commit from each analytic account
"amount_commit": doc.amount_commit * aa_percent / 100,
"date_commit": doc.fwd_date_commit or doc.date_commit,
}
)
# Get analytic min date
analytic_min_date = AnalyticAccount._get_analytic_date(analytic_account, "bm_date_to asc")
method_type = False
to_analytic_account_id = False

Check warning on line 104 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L102-L104

Added lines #L102 - L104 were not covered by tests
if analytic_min_date.bm_date_to and analytic_min_date.bm_date_to < self.to_date_commit:
method_type = "new"

Check warning on line 106 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L106

Added line #L106 was not covered by tests

# to_analytic_account_id = analytic.next_year_analytic(
# auto_create=False
# )
value_dict.append(

Check warning on line 111 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L111

Added line #L111 was not covered by tests
{
"forward_id": self.id,
"analytic_distribution": analytic_account,
"method_type": method_type,
"res_model": res_model,
"res_id": doc.id,
"document_id": "{},{}".format(doc._name, doc.id),
"document_number": self._get_document_number(doc),
"to_analytic_distribution": {},
"amount_commit": doc.amount_commit,
"date_commit": doc.fwd_date_commit or doc.date_commit,
}
)
return value_dict

Check warning on line 125 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L125

Added line #L125 was not covered by tests

def action_review_budget_commit(self):
Expand All @@ -142,12 +140,13 @@ def get_budget_commit_forward(self, res_model):
Line.create(vals)

Check warning on line 140 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L138-L140

Added lines #L138 - L140 were not covered by tests

def create_missing_analytic(self):
AnalyticAccount = self.env["account.analytic.account"]

Check warning on line 143 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L143

Added line #L143 was not covered by tests
for rec in self:
for line in rec.forward_line_ids.filtered_domain(
[("to_analytic_account_id", "=", False)]
[("to_analytic_distribution", "=", False)]
):
line.to_analytic_account_id = (
line.analytic_account_id.next_year_analytic()
line.to_analytic_distribution = (

Check warning on line 148 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L148

Added line #L148 was not covered by tests
AnalyticAccount.next_year_analytic(line.analytic_distribution)
)

def preview_budget_commit_forward_info(self):
Expand Down Expand Up @@ -185,13 +184,13 @@ def _get_forward_initial_commit(self, domain):
self.ensure_one()
forwards = self.env["budget.commit.forward.line"].read_group(

Check warning on line 185 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L184-L185

Added lines #L184 - L185 were not covered by tests
domain,
["to_analytic_account_id", "amount_commit"],
["to_analytic_account_id"],
orderby="to_analytic_account_id",
)
["to_analytic_distribution", "amount_commit"],
["to_analytic_distribution"],
orderby="to_analytic_distribution",
)
res = [
{
"analytic_account_id": f["to_analytic_account_id"][0],
"analytic_distribution": f["to_analytic_distribution"],
"initial_commit": f["amount_commit"],
}
for f in forwards
Expand All @@ -201,7 +200,7 @@ def _get_forward_initial_commit(self, domain):
def _do_forward_commit(self, reverse=False):
"""Create carry forward budget move to all related documents"""
self = self.sudo()
_analytic_field = "analytic_account_id" if reverse else "to_analytic_account_id"
_analytic_field = "analytic_distribution" if reverse else "to_analytic_distribution"

Check warning on line 203 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L202-L203

Added lines #L202 - L203 were not covered by tests
for rec in self:
group_document = {}

Check warning on line 205 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L205

Added line #L205 was not covered by tests
# Group by document
Expand Down Expand Up @@ -297,6 +296,7 @@ def action_draft(self):

class BudgetCommitForwardLine(models.Model):
_name = "budget.commit.forward.line"
_inherit = "analytic.mixin"
_description = "Budget Commit Forward Line"

forward_id = fields.Many2one(
Expand All @@ -307,16 +307,6 @@ class BudgetCommitForwardLine(models.Model):
readonly=True,
ondelete="cascade",
)
analytic_account_id = fields.Many2one(
comodel_name="account.analytic.account",
index=True,
required=True,
readonly=True,
)
analytic_percent = fields.Float(
required=True,
readonly=True,
)
method_type = fields.Selection(
selection=[
("new", "New"),
Expand All @@ -326,16 +316,14 @@ class BudgetCommitForwardLine(models.Model):
help="New: if the analytic has ended, 'To Analytic Account' is required\n"
"Extended: if the analytic has ended, but want to extend to next period date end",
)
to_analytic_account_id = fields.Many2one(
comodel_name="account.analytic.account",
string="Forward to Analytic",
compute="_compute_to_analytic_account_id",
to_analytic_distribution = fields.Json(
string="To Analytic",
compute="_compute_to_analytic_distribution",
store=True,
readonly=True,
)
bm_date_to = fields.Date(
related="analytic_account_id.bm_date_to",
readonly=True,
string="Date To",
compute="_compute_bm_date_to",
)
res_model = fields.Selection(
selection=[],
Expand Down Expand Up @@ -374,30 +362,40 @@ class BudgetCommitForwardLine(models.Model):
readonly=True,
)

@api.depends("analytic_distribution")
def _compute_bm_date_to(self):
AnalyticAccount = self.env["account.analytic.account"]

Check warning on line 367 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L367

Added line #L367 was not covered by tests
for rec in self:
analytic_min_date = AnalyticAccount._get_analytic_date(rec.analytic_distribution, "bm_date_to asc")
rec.bm_date_to = analytic_min_date.bm_date_to

Check warning on line 370 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L369-L370

Added lines #L369 - L370 were not covered by tests

@api.depends("method_type")
def _compute_to_analytic_account_id(self):
def _compute_to_analytic_distribution(self):
AnalyticAccount = self.env["account.analytic.account"]

Check warning on line 374 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L374

Added line #L374 was not covered by tests
for rec in self:
if not rec.analytic_account_id:
if not rec.analytic_distribution:
continue
analytic_min_date = AnalyticAccount._get_analytic_date(rec.analytic_distribution, "bm_date_to asc")

Check warning on line 378 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L377-L378

Added lines #L377 - L378 were not covered by tests

# Case analytic has no end date, always use same analytic
if not rec.analytic_account_id.bm_date_to:
rec.to_analytic_account_id = rec.analytic_account_id
if not analytic_min_date.bm_date_to:
rec.to_analytic_distribution = rec.analytic_distribution
rec.method_type = False
continue

Check warning on line 384 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L382-L384

Added lines #L382 - L384 were not covered by tests
# Case analytic has extended end date that cover new commit date, use same analytic
if (
rec.analytic_account_id.bm_date_to
and rec.analytic_account_id.bm_date_to >= rec.forward_id.to_date_commit
analytic_min_date.bm_date_to
and analytic_min_date.bm_date_to >= rec.forward_id.to_date_commit
):
rec.to_analytic_account_id = rec.analytic_account_id
rec.to_analytic_distribution = rec.analytic_distribution
rec.method_type = "extend"
continue

Check warning on line 392 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L390-L392

Added lines #L390 - L392 were not covered by tests
# Case want to extend analytic to end of next budget period
if rec.method_type == "extend":
rec.to_analytic_account_id = rec.analytic_account_id
rec.to_analytic_distribution = rec.analytic_distribution
continue

Check warning on line 396 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L395-L396

Added lines #L395 - L396 were not covered by tests
# Case want to use next analytic, if exists
if rec.method_type == "new":
rec.to_analytic_account_id = rec.analytic_account_id.next_year_analytic(
auto_create=False
rec.to_analytic_distribution = AnalyticAccount.next_year_analytic(

Check warning on line 399 in budget_control/models/budget_commit_forward.py

View check run for this annotation

Codecov / codecov/patch

budget_control/models/budget_commit_forward.py#L399

Added line #L399 was not covered by tests
rec.analytic_distribution, auto_create=False
)
17 changes: 5 additions & 12 deletions budget_control/views/budget_commit_forward_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,15 @@
<field name="arch" type="xml">
<tree editable="bottom" create="0">
<field name="document_id" invisible="1" />
<field name="analytic_account_id" />
<field name="analytic_percent" />
<field name="bm_date_to" invisible="1" />
<field name="analytic_distribution" widget="analytic_distribution" />
<field name="bm_date_to" optional="hide" />
<field
name="method_type"
optional="show"
attrs="{'required': [('bm_date_to', '!=', False)],
'readonly': [('bm_date_to', '=', False)]}"
/>
<field
name="to_analytic_account_id"
force_save="1"
options="{'no_create': 1}"
optional="show"
readonly="1"
/>
<field name="to_analytic_distribution" widget="analytic_distribution" optional="show" />
<field name="document_number" optional="show" />
<field name="date_commit" />
<field name="currency_id" invisible="1" />
Expand All @@ -53,10 +46,10 @@
<group>
<group>
<field name="document_id" invisible="1" />
<field name="analytic_account_id" />
<field name="analytic_distribution" />
<field name="bm_date_to" invisible="1" />
<field name="method_type" />
<field name="to_analytic_account_id" />
<field name="to_analytic_distribution" />
</group>
<group>
<field name="document_number" />
Expand Down
40 changes: 18 additions & 22 deletions budget_control/wizards/budget_commit_forward_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def action_budget_commit_forward(self):

class BudgetCommitForwardInfoLine(models.TransientModel):
_name = "budget.commit.forward.info.line"
_inherit = "analytic.mixin"
_description = "Budget Commitment Forward Info Line"

forward_info_id = fields.Many2one(
Expand All @@ -41,35 +42,30 @@ class BudgetCommitForwardInfoLine(models.TransientModel):
readonly=True,
ondelete="cascade",
)
analytic_account_id = fields.Many2one(
string="Forward to Analytic",
comodel_name="account.analytic.account",
readonly=True,
)
analytic_plan = fields.Many2one(
comodel_name="account.analytic.plan",
related="analytic_account_id.plan_id",
readonly=True,
)
initial_available = fields.Monetary(
string="Initial Available",
related="analytic_account_id.initial_available",
readonly=True,
)
# analytic_plan = fields.Many2one(
# comodel_name="account.analytic.plan",
# related="analytic_account_id.plan_id",
# readonly=True,
# )
# initial_available = fields.Monetary(
# string="Initial Available",
# related="analytic_account_id.initial_available",
# readonly=True,
# )
initial_commit = fields.Monetary(
string="Initial Commitment",
readonly=True,
)
amount_balance = fields.Monetary(
string="Available",
compute="_compute_amount_balance",
)
# amount_balance = fields.Monetary(
# string="Available",
# compute="_compute_amount_balance",
# )
currency_id = fields.Many2one(
comodel_name="res.currency",
related="forward_info_id.currency_id",
readonly=True,
)

def _compute_amount_balance(self):
for rec in self:
rec.amount_balance = rec.initial_available - rec.initial_commit
# def _compute_amount_balance(self):
# for rec in self:
# rec.amount_balance = rec.initial_available - rec.initial_commit
Loading

0 comments on commit a1e04b1

Please sign in to comment.