Before this commit, when the user is in the project update kanban view and click on Purchase Order row shown in Project Profitability section in the right side panel, the user cannot create or edit a purchase order because the AA on each purchase order line is used to link those purchase orders to the project. This commit adds the project and also `project_update` key in the context to use them keys to set the AA on new Purchase Order Line by default. task-2861207 closes odoo/odoo#95721 Related: odoo/enterprise#29304 Signed-off-by: Laurent Stukkens (ltu) <ltu@odoo.com>
143 lines
6.5 KiB
Python
143 lines
6.5 KiB
Python
# -*- 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
|
|
|
|
|
|
class Project(models.Model):
|
|
_inherit = "project.project"
|
|
|
|
purchase_orders_count = fields.Integer('# Purchase Orders', compute='_compute_purchase_orders_count', groups='purchase.group_purchase_user')
|
|
|
|
@api.depends('analytic_account_id')
|
|
def _compute_purchase_orders_count(self):
|
|
if not self.analytic_account_id:
|
|
self.purchase_orders_count = 0
|
|
return
|
|
purchase_orders_data = self.env['purchase.order.line']._read_group([
|
|
('account_analytic_id', 'in', self.analytic_account_id.ids)
|
|
], ['account_analytic_id', 'order_id:count_distinct'], ['account_analytic_id'])
|
|
mapped_data = dict([(data['account_analytic_id'][0], data['order_id']) for data in purchase_orders_data])
|
|
for project in self:
|
|
project.purchase_orders_count = mapped_data.get(project.analytic_account_id.id, 0)
|
|
|
|
# ----------------------------
|
|
# Actions
|
|
# ----------------------------
|
|
|
|
def action_open_project_purchase_orders(self):
|
|
purchase_orders = self.env['purchase.order'].search([
|
|
('order_line.account_analytic_id', '!=', False),
|
|
('order_line.account_analytic_id', 'in', self.analytic_account_id.ids)
|
|
])
|
|
action_window = {
|
|
'name': _('Purchase Orders'),
|
|
'type': 'ir.actions.act_window',
|
|
'res_model': 'purchase.order',
|
|
'views': [[False, 'tree'], [False, 'form']],
|
|
'domain': [('id', 'in', purchase_orders.ids)],
|
|
'context': {
|
|
'project_id': self.id,
|
|
}
|
|
}
|
|
if len(purchase_orders) == 1:
|
|
action_window['views'] = [[False, 'form']]
|
|
action_window['res_id'] = purchase_orders.id
|
|
return action_window
|
|
|
|
def action_profitability_items(self, section_name, domain=None, res_id=False):
|
|
if section_name == 'purchase_order':
|
|
action = {
|
|
'name': _('Purchase Order Items'),
|
|
'type': 'ir.actions.act_window',
|
|
'res_model': 'purchase.order.line',
|
|
'views': [[False, 'tree'], [False, 'form']],
|
|
'domain': domain,
|
|
'context': {
|
|
'create': False,
|
|
'edit': False,
|
|
},
|
|
}
|
|
if res_id:
|
|
action['res_id'] = res_id
|
|
if 'views' in action:
|
|
action['views'] = [
|
|
(view_id, view_type)
|
|
for view_id, view_type in action['views']
|
|
if view_type == 'form'
|
|
] or [False, 'form']
|
|
action['view_mode'] = 'form'
|
|
return action
|
|
return super().action_profitability_items(section_name, domain, res_id)
|
|
|
|
# ----------------------------
|
|
# Project Updates
|
|
# ----------------------------
|
|
|
|
def _get_stat_buttons(self):
|
|
buttons = super(Project, self)._get_stat_buttons()
|
|
if self.user_has_groups('purchase.group_purchase_user'):
|
|
buttons.append({
|
|
'icon': 'credit-card',
|
|
'text': _lt('Purchase Orders'),
|
|
'number': self.purchase_orders_count,
|
|
'action_type': 'object',
|
|
'action': 'action_open_project_purchase_orders',
|
|
'show': self.purchase_orders_count > 0,
|
|
'sequence': 36,
|
|
})
|
|
return buttons
|
|
|
|
def _get_profitability_aal_domain(self):
|
|
return expression.AND([
|
|
super()._get_profitability_aal_domain(),
|
|
['|', ('move_id', '=', False), ('move_id.purchase_line_id', '=', False)],
|
|
])
|
|
|
|
def _get_profitability_labels(self):
|
|
labels = super()._get_profitability_labels()
|
|
labels['purchase_order'] = _lt('Purchase Orders')
|
|
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['purchase_order'] = 9
|
|
return sequence_per_invoice_type
|
|
|
|
def _get_profitability_items(self, with_action=True):
|
|
profitability_items = super()._get_profitability_items(with_action)
|
|
if self.analytic_account_id:
|
|
purchase_order_line_read = self.env['purchase.order.line'].sudo().search_read([
|
|
('account_analytic_id', 'in', self.analytic_account_id.ids),
|
|
('state', 'in', ['purchase', 'done']),
|
|
'|',
|
|
('qty_invoiced', '>', 0),
|
|
'|', ('qty_to_invoice', '>', 0), ('product_uom_qty', '>', 0),
|
|
], ['qty_invoiced', 'qty_to_invoice', 'product_uom_qty', 'price_unit'])
|
|
if purchase_order_line_read:
|
|
amount_invoiced = amount_to_invoice = 0.0
|
|
purchase_order_line_ids = []
|
|
for pol_read in purchase_order_line_read:
|
|
price_unit = pol_read['price_unit']
|
|
amount_invoiced -= price_unit * pol_read['qty_invoiced'] if pol_read['qty_invoiced'] > 0 else 0.0
|
|
if pol_read['qty_to_invoice'] > 0:
|
|
amount_to_invoice -= price_unit * pol_read['qty_to_invoice']
|
|
else:
|
|
amount_to_invoice -= price_unit * (pol_read['product_uom_qty'] - pol_read['qty_invoiced'])
|
|
purchase_order_line_ids.append(pol_read['id'])
|
|
costs = profitability_items['costs']
|
|
section_id = 'purchase_order'
|
|
purchase_order_costs = {'id': section_id, 'sequence': self._get_profitability_sequence_per_invoice_type()[section_id], 'billed': amount_invoiced, 'to_bill': amount_to_invoice}
|
|
if with_action and purchase_order_line_ids and self.user_has_groups('purchase.group_purchase_user'):
|
|
action = {'name': 'action_profitability_items', 'type': 'object', 'section': section_id, 'domain': json.dumps([('id', 'in', purchase_order_line_ids)])}
|
|
if len(purchase_order_line_ids) == 1:
|
|
action['res_id'] = purchase_order_line_ids[0]
|
|
purchase_order_costs['action'] = action
|
|
costs['data'].append(purchase_order_costs)
|
|
costs['total']['billed'] += amount_invoiced
|
|
costs['total']['to_bill'] += amount_to_invoice
|
|
return profitability_items
|