mirror of
https://github.com/bringout/oca-ocb-project.git
synced 2026-04-22 15:02:11 +02:00
19.0 vanilla
This commit is contained in:
parent
a2f74aefd8
commit
4a4d12c333
844 changed files with 212348 additions and 270090 deletions
|
|
@ -1,3 +1,2 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import project
|
||||
from . import hr_expense
|
||||
from . import project_project
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
from odoo import api, models
|
||||
|
||||
|
||||
class HrExpense(models.Model):
|
||||
_inherit = 'hr.expense'
|
||||
|
||||
def _compute_analytic_distribution(self):
|
||||
project_id = self.env.context.get('project_id')
|
||||
if not project_id:
|
||||
super()._compute_analytic_distribution()
|
||||
else:
|
||||
analytic_distribution = self.env['project.project'].browse(project_id)._get_analytic_distribution()
|
||||
for expense in self:
|
||||
expense.analytic_distribution = expense.analytic_distribution or analytic_distribution
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
project_id = self.env.context.get('project_id')
|
||||
if project_id:
|
||||
analytic_distribution = self.env['project.project'].browse(project_id)._get_analytic_distribution()
|
||||
if analytic_distribution:
|
||||
for vals in vals_list:
|
||||
vals['analytic_distribution'] = vals.get('analytic_distribution', analytic_distribution)
|
||||
return super().create(vals_list)
|
||||
|
|
@ -1,35 +1,14 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import json
|
||||
|
||||
from odoo import api, fields, models, _, _lt
|
||||
from odoo.osv import expression
|
||||
from odoo import models
|
||||
from odoo.fields import Domain
|
||||
|
||||
class Project(models.Model):
|
||||
|
||||
class ProjectProject(models.Model):
|
||||
_inherit = 'project.project'
|
||||
|
||||
expenses_count = fields.Integer('# Expenses', compute='_compute_expenses_count', groups='hr_expense.group_hr_expense_team_approver')
|
||||
|
||||
@api.depends('analytic_account_id')
|
||||
def _compute_expenses_count(self):
|
||||
if not self.analytic_account_id:
|
||||
self.expenses_count = 0
|
||||
return
|
||||
query = self.env['hr.expense']._search([])
|
||||
query.add_where('hr_expense.analytic_distribution ?| %s', [[str(account_id) for account_id in self.analytic_account_id.ids]])
|
||||
|
||||
query.order = None
|
||||
query_string, query_param = query.select(
|
||||
'jsonb_object_keys(hr_expense.analytic_distribution) as account_id',
|
||||
'COUNT(DISTINCT(id)) as expense_count',
|
||||
)
|
||||
query_string = f'{query_string} GROUP BY jsonb_object_keys(hr_expense.analytic_distribution)'
|
||||
self._cr.execute(query_string, query_param)
|
||||
data = {int(record.get('account_id')): record.get('expense_count') for record in self._cr.dictfetchall()}
|
||||
for project in self:
|
||||
project.expenses_count = data.get(project.analytic_account_id.id, 0)
|
||||
|
||||
# ----------------------------
|
||||
# Actions
|
||||
# ----------------------------
|
||||
|
|
@ -39,33 +18,43 @@ class Project(models.Model):
|
|||
return {}
|
||||
action = self.env["ir.actions.actions"]._for_xml_id("hr_expense.hr_expense_actions_all")
|
||||
action.update({
|
||||
'display_name': _('Expenses'),
|
||||
'views': [[False, 'tree'], [False, 'form'], [False, 'kanban'], [False, 'graph'], [False, 'pivot']],
|
||||
'context': {'default_analytic_distribution': {self.analytic_account_id.id: 100}},
|
||||
'display_name': self.env._('Expenses'),
|
||||
'views': [[False, 'list'], [False, 'form'], [False, 'kanban'], [False, 'graph'], [False, 'pivot']],
|
||||
'context': {'project_id': self.id},
|
||||
'domain': domain or [('id', 'in', expense_ids)],
|
||||
})
|
||||
if len(expense_ids) == 1:
|
||||
if not self.env.context.get('from_embedded_action') and len(expense_ids) == 1:
|
||||
action["views"] = [[False, 'form']]
|
||||
action["res_id"] = expense_ids[0]
|
||||
return action
|
||||
|
||||
def _get_add_purchase_items_domain(self):
|
||||
return Domain.AND([
|
||||
super()._get_add_purchase_items_domain(),
|
||||
Domain('expense_id', '=', False),
|
||||
])
|
||||
|
||||
def action_profitability_items(self, section_name, domain=None, res_id=False):
|
||||
if section_name == 'expenses':
|
||||
return self._get_expense_action(domain, [res_id] if res_id else [])
|
||||
return super().action_profitability_items(section_name, domain, res_id)
|
||||
|
||||
def action_open_project_expenses(self):
|
||||
self.ensure_one()
|
||||
return self._get_expense_action(domain=[('analytic_distribution', 'in', self.account_id.ids)])
|
||||
|
||||
# ----------------------------
|
||||
# Project Update
|
||||
# ----------------------------
|
||||
|
||||
def _get_profitability_labels(self):
|
||||
labels = super()._get_profitability_labels()
|
||||
labels['expenses'] = _lt('Expenses')
|
||||
labels['expenses'] = self.env._('Expenses')
|
||||
return labels
|
||||
|
||||
def _get_profitability_sequence_per_invoice_type(self):
|
||||
sequence_per_invoice_type = super()._get_profitability_sequence_per_invoice_type()
|
||||
sequence_per_invoice_type['expenses'] = 11
|
||||
sequence_per_invoice_type['expenses'] = 13
|
||||
return sequence_per_invoice_type
|
||||
|
||||
def _get_already_included_profitability_invoice_line_ids(self):
|
||||
|
|
@ -73,38 +62,51 @@ class Project(models.Model):
|
|||
# we need to make sure they are exclusive in the profitability report.
|
||||
move_line_ids = super()._get_already_included_profitability_invoice_line_ids()
|
||||
query = self.env['account.move.line'].sudo()._search([
|
||||
('move_id.expense_sheet_id', '!=', False),
|
||||
('expense_id', '!=', False),
|
||||
('id', 'not in', move_line_ids),
|
||||
])
|
||||
return move_line_ids + list(query)
|
||||
|
||||
def _get_expenses_profitability_items(self, with_action=True):
|
||||
if not self.analytic_account_id:
|
||||
if not self.account_id:
|
||||
return {}
|
||||
can_see_expense = with_action and self.user_has_groups('hr_expense.group_hr_expense_team_approver')
|
||||
query = self.env['hr.expense']._search([('is_refused', '=', False), ('state', 'in', ['approved', 'done'])])
|
||||
query.order = None
|
||||
query.add_where('hr_expense.analytic_distribution ? %s', [str(self.analytic_account_id.id)])
|
||||
query_string, query_param = query.select('array_agg(id) as ids', 'SUM(untaxed_amount) as untaxed_amount')
|
||||
self._cr.execute(query_string, query_param)
|
||||
expenses_read_group = [expense for expense in self._cr.dictfetchall()]
|
||||
if not expenses_read_group or not expenses_read_group[0].get('ids'):
|
||||
can_see_expense = with_action and self.env.user.has_group('hr_expense.group_hr_expense_team_approver')
|
||||
|
||||
expenses_read_group = self.env['hr.expense']._read_group(
|
||||
[
|
||||
('state', 'in', ['posted', 'in_payment', 'paid']),
|
||||
('analytic_distribution', 'in', self.account_id.ids),
|
||||
],
|
||||
groupby=['currency_id'],
|
||||
aggregates=['id:array_agg', 'untaxed_amount_currency:sum'],
|
||||
)
|
||||
if not expenses_read_group:
|
||||
return {}
|
||||
expense_data = expenses_read_group[0]
|
||||
expense_ids = []
|
||||
amount_billed = 0.0
|
||||
for currency, ids, untaxed_amount_currency_sum in expenses_read_group:
|
||||
if can_see_expense:
|
||||
expense_ids.extend(ids)
|
||||
amount_billed += currency._convert(
|
||||
from_amount=untaxed_amount_currency_sum,
|
||||
to_currency=self.currency_id,
|
||||
company=self.company_id,
|
||||
)
|
||||
|
||||
section_id = 'expenses'
|
||||
expense_profitability_items = {
|
||||
'costs': {'id': section_id, 'sequence': self._get_profitability_sequence_per_invoice_type()[section_id], 'billed': -expense_data['untaxed_amount'], 'to_bill': 0.0},
|
||||
'costs': {'id': section_id, 'sequence': self._get_profitability_sequence_per_invoice_type()[section_id], 'billed': -amount_billed, 'to_bill': 0.0},
|
||||
}
|
||||
if can_see_expense:
|
||||
args = [section_id, [('id', 'in', expense_data['ids'])]]
|
||||
if len(expense_data['ids']) == 1:
|
||||
args.append(expense_data['ids'][0])
|
||||
args = [section_id, [('id', 'in', expense_ids)]]
|
||||
if len(expense_ids) == 1:
|
||||
args.append(expense_ids[0])
|
||||
action = {'name': 'action_profitability_items', 'type': 'object', 'args': json.dumps(args)}
|
||||
expense_profitability_items['costs']['action'] = action
|
||||
return expense_profitability_items
|
||||
|
||||
def _get_profitability_aal_domain(self):
|
||||
return expression.AND([
|
||||
return Domain.AND([
|
||||
super()._get_profitability_aal_domain(),
|
||||
['|', ('move_line_id', '=', False), ('move_line_id.expense_id', '=', False)],
|
||||
])
|
||||
Loading…
Add table
Add a link
Reference in a new issue