diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 17:14:58 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 17:14:58 +0700 |
| commit | 1ca3b3df3421961caec3b747a364071c80f5c7da (patch) | |
| tree | 6778a1f0f3f9b4c6e26d6d87ccde16e24da6c9d6 /base_account_budget/models | |
| parent | b57188be371d36d96caac4b8d65a40745c0e972c (diff) | |
initial commit
Diffstat (limited to 'base_account_budget/models')
| -rw-r--r-- | base_account_budget/models/__init__.py | 24 | ||||
| -rw-r--r-- | base_account_budget/models/account_analytic_account.py | 28 | ||||
| -rw-r--r-- | base_account_budget/models/account_budget.py | 188 |
3 files changed, 240 insertions, 0 deletions
diff --git a/base_account_budget/models/__init__.py b/base_account_budget/models/__init__.py new file mode 100644 index 0000000..2a08a54 --- /dev/null +++ b/base_account_budget/models/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) +# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see <http://www.gnu.org/licenses/>. +# +############################################################################# + +from . import account_budget +from . import account_analytic_account diff --git a/base_account_budget/models/account_analytic_account.py b/base_account_budget/models/account_analytic_account.py new file mode 100644 index 0000000..73625d7 --- /dev/null +++ b/base_account_budget/models/account_analytic_account.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) +# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see <http://www.gnu.org/licenses/>. +# +############################################################################# +from odoo import fields, models + + +class AccountAnalyticAccount(models.Model): + _inherit = "account.analytic.account" + + budget_line = fields.One2many('budget.lines', 'analytic_account_id', 'Budget Lines') diff --git a/base_account_budget/models/account_budget.py b/base_account_budget/models/account_budget.py new file mode 100644 index 0000000..ab9674d --- /dev/null +++ b/base_account_budget/models/account_budget.py @@ -0,0 +1,188 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) +# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see <http://www.gnu.org/licenses/>. +# +############################################################################# + +from odoo import api, fields, models, _ +from odoo.exceptions import ValidationError + + +class AccountBudgetPost(models.Model): + _name = "account.budget.post" + _order = "name" + _description = "Budgetary Position" + + name = fields.Char('Name', required=True) + account_ids = fields.Many2many('account.account', 'account_budget_rel', 'budget_id', 'account_id', 'Accounts', + domain=[('deprecated', '=', False)]) + budget_line = fields.One2many('budget.lines', 'general_budget_id', 'Budget Lines') + company_id = fields.Many2one('res.company', 'Company', required=True, + default=lambda self: self.env['res.company']._company_default_get( + 'account.budget.post')) + + def _check_account_ids(self, vals): + if 'account_ids' in vals: + account_ids = vals['account_ids'] + # account_ids = self.resolve_2many_commands('account_ids', vals['account_ids']) + else: + account_ids = self.account_ids + if not account_ids: + raise ValidationError(_('The budget must have at least one account.')) + + @api.model + def create(self, vals): + self._check_account_ids(vals) + return super(AccountBudgetPost, self).create(vals) + + def write(self, vals): + self._check_account_ids(vals) + return super(AccountBudgetPost, self).write(vals) + + +class Budget(models.Model): + _name = "budget.budget" + _description = "Budget" + _inherit = ['mail.thread'] + + name = fields.Char('Budget Name', required=True, states={'done': [('readonly', True)]}) + creating_user_id = fields.Many2one('res.users', 'Responsible', default=lambda self: self.env.user) + date_from = fields.Date('Start Date', required=True, states={'done': [('readonly', True)]}) + date_to = fields.Date('End Date', required=True, states={'done': [('readonly', True)]}) + state = fields.Selection([ + ('draft', 'Draft'), + ('cancel', 'Cancelled'), + ('confirm', 'Confirmed'), + ('validate', 'Validated'), + ('done', 'Done') + ], 'Status', default='draft', index=True, required=True, readonly=True, copy=False, track_visibility='always') + budget_line = fields.One2many('budget.lines', 'budget_id', 'Budget Lines', + states={'done': [('readonly', True)]}, copy=True) + company_id = fields.Many2one('res.company', 'Company', required=True, + default=lambda self: self.env['res.company']._company_default_get( + 'account.budget.post')) + + def action_budget_confirm(self): + self.write({'state': 'confirm'}) + + def action_budget_draft(self): + self.write({'state': 'draft'}) + + def action_budget_validate(self): + self.write({'state': 'validate'}) + + def action_budget_cancel(self): + self.write({'state': 'cancel'}) + + def action_budget_done(self): + self.write({'state': 'done'}) + + +class BudgetLines(models.Model): + _name = "budget.lines" + _rec_name = "budget_id" + _description = "Budget Line" + + budget_id = fields.Many2one('budget.budget', 'Budget', ondelete='cascade', index=True, required=True) + analytic_account_id = fields.Many2one('account.analytic.account', 'Analytic Account') + general_budget_id = fields.Many2one('account.budget.post', 'Budgetary Position', required=True) + date_from = fields.Date('Start Date', required=True) + date_to = fields.Date('End Date', required=True) + paid_date = fields.Date('Paid Date') + planned_amount = fields.Float('Planned Amount', required=True, digits=0) + practical_amount = fields.Float(compute='_compute_practical_amount', string='Practical Amount', digits=0) + theoretical_amount = fields.Float(compute='_compute_theoretical_amount', string='Theoretical Amount', digits=0) + percentage = fields.Float(compute='_compute_percentage', string='Achievement') + company_id = fields.Many2one(related='budget_id.company_id', comodel_name='res.company', + string='Company', store=True, readonly=True) + + def _compute_practical_amount(self): + for line in self: + result = 0.0 + acc_ids = line.general_budget_id.account_ids.ids + date_to = self.env.context.get('wizard_date_to') or line.date_to + date_from = self.env.context.get('wizard_date_from') or line.date_from + if line.analytic_account_id.id: + self.env.cr.execute(""" + SELECT SUM(amount) + FROM account_analytic_line + WHERE account_id=%s + AND date between %s AND %s + AND general_account_id=ANY(%s)""", + (line.analytic_account_id.id, date_from, date_to, acc_ids,)) + result = self.env.cr.fetchone()[0] or 0.0 + line.practical_amount = result + + def _compute_theoretical_amount(self): + today = fields.Datetime.now() + for line in self: + # Used for the report + + if self.env.context.get('wizard_date_from') and self.env.context.get('wizard_date_to'): + date_from = fields.Datetime.from_string(self.env.context.get('wizard_date_from')) + date_to = fields.Datetime.from_string(self.env.context.get('wizard_date_to')) + if date_from < fields.Datetime.from_string(line.date_from): + date_from = fields.Datetime.from_string(line.date_from) + elif date_from > fields.Datetime.from_string(line.date_to): + date_from = False + + if date_to > fields.Datetime.from_string(line.date_to): + date_to = fields.Datetime.from_string(line.date_to) + elif date_to < fields.Datetime.from_string(line.date_from): + date_to = False + + theo_amt = 0.00 + if date_from and date_to: + line_timedelta = fields.Datetime.from_string(line.date_to) - fields.Datetime.from_string( + line.date_from) + elapsed_timedelta = date_to - date_from + if elapsed_timedelta.days > 0: + theo_amt = ( + elapsed_timedelta.total_seconds() / line_timedelta.total_seconds()) * line.planned_amount + else: + if line.paid_date: + if fields.Datetime.from_string(line.date_to) <= fields.Datetime.from_string(line.paid_date): + theo_amt = 0.00 + else: + theo_amt = line.planned_amount + else: + line_timedelta = fields.Datetime.from_string(line.date_to) - fields.Datetime.from_string( + line.date_from) + elapsed_timedelta = fields.Datetime.from_string(today) - ( + fields.Datetime.from_string(line.date_from)) + + if elapsed_timedelta.days < 0: + # If the budget line has not started yet, theoretical amount should be zero + theo_amt = 0.00 + elif line_timedelta.days > 0 and fields.Datetime.from_string(today) < fields.Datetime.from_string( + line.date_to): + # If today is between the budget line date_from and date_to + theo_amt = ( + elapsed_timedelta.total_seconds() / line_timedelta.total_seconds()) * line.planned_amount + else: + theo_amt = line.planned_amount + + line.theoretical_amount = theo_amt + + def _compute_percentage(self): + for line in self: + if line.theoretical_amount != 0.00: + line.percentage = float((line.practical_amount or 0.0) / line.theoretical_amount) * 100 + else: + line.percentage = 0.00 |
