19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:32:12 +01:00
parent 79f83631d5
commit 73afc09215
6267 changed files with 1534193 additions and 1130106 deletions

View file

@ -1,14 +1,13 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.tools import SQL
class CrmTeam(models.Model):
_inherit = 'crm.team'
use_quotations = fields.Boolean(string='Quotations', help="Check this box if you send quotations to your customers rather than confirming orders straight away.")
invoiced = fields.Float(
compute='_compute_invoiced',
string='Invoiced This Month', readonly=True,
@ -17,130 +16,46 @@ class CrmTeam(models.Model):
"of the current and target revenue on the kanban view.")
invoiced_target = fields.Float(
string='Invoicing Target',
help="Revenue target for the current month (untaxed total of confirmed invoices).")
quotations_count = fields.Integer(
compute='_compute_quotations_to_invoice',
string='Number of quotations to invoice', readonly=True)
quotations_amount = fields.Float(
compute='_compute_quotations_to_invoice',
string='Amount of quotations to invoice', readonly=True)
sales_to_invoice_count = fields.Integer(
compute='_compute_sales_to_invoice',
string='Number of sales to invoice', readonly=True)
help="Revenue Target for the current month (untaxed total of paid invoices).")
sale_order_count = fields.Integer(compute='_compute_sale_order_count', string='# Sale Orders')
def _compute_quotations_to_invoice(self):
query = self.env['sale.order']._where_calc([
('team_id', 'in', self.ids),
('state', 'in', ['draft', 'sent']),
])
self.env['sale.order']._apply_ir_rules(query, 'read')
_, where_clause, where_clause_args = query.get_sql()
select_query = """
SELECT team_id, count(*), sum(amount_total /
CASE COALESCE(currency_rate, 0)
WHEN 0 THEN 1.0
ELSE currency_rate
END
) as amount_total
FROM sale_order
WHERE %s
GROUP BY team_id
""" % where_clause
self.env.cr.execute(select_query, where_clause_args)
quotation_data = self.env.cr.dictfetchall()
teams = self.browse()
for datum in quotation_data:
team = self.browse(datum['team_id'])
team.quotations_amount = datum['amount_total']
team.quotations_count = datum['count']
teams |= team
remaining = (self - teams)
remaining.quotations_amount = 0
remaining.quotations_count = 0
def _compute_sales_to_invoice(self):
sale_order_data = self.env['sale.order']._read_group([
('team_id', 'in', self.ids),
('invoice_status','=','to invoice'),
], ['team_id'], ['team_id'])
data_map = {datum['team_id'][0]: datum['team_id_count'] for datum in sale_order_data}
for team in self:
team.sales_to_invoice_count = data_map.get(team.id,0.0)
def _compute_invoiced(self):
if not self:
return
if self.ids:
today = fields.Date.today()
data_map = dict(self.env.execute_query(SQL(
''' SELECT
move.team_id AS team_id,
SUM(move.amount_untaxed_signed) AS amount_untaxed_signed
FROM account_move move
WHERE move.move_type IN ('out_invoice', 'out_refund', 'out_receipt')
AND move.payment_state IN ('in_payment', 'paid', 'reversed')
AND move.state = 'posted'
AND move.team_id IN %s
AND move.date BETWEEN %s AND %s
GROUP BY move.team_id
''',
tuple(self.ids),
fields.Date.to_string(today.replace(day=1)),
fields.Date.to_string(today),
)))
else:
data_map = {}
query = '''
SELECT
move.team_id AS team_id,
SUM(move.amount_untaxed_signed) AS amount_untaxed_signed
FROM account_move move
WHERE move.move_type IN ('out_invoice', 'out_refund', 'out_receipt')
AND move.payment_state IN ('in_payment', 'paid', 'reversed')
AND move.state = 'posted'
AND move.team_id IN %s
AND move.date BETWEEN %s AND %s
GROUP BY move.team_id
'''
today = fields.Date.today()
params = [tuple(self.ids), fields.Date.to_string(today.replace(day=1)), fields.Date.to_string(today)]
self._cr.execute(query, params)
data_map = dict((v[0], v[1]) for v in self._cr.fetchall())
for team in self:
team.invoiced = data_map.get(team.id, 0.0)
team.invoiced = data_map.get(team._origin.id, 0.0)
def _compute_sale_order_count(self):
data_map = {}
if self.ids:
sale_order_data = self.env['sale.order']._read_group([
('team_id', 'in', self.ids),
('state', '!=', 'cancel'),
], ['team_id'], ['team_id'])
data_map = {datum['team_id'][0]: datum['team_id_count'] for datum in sale_order_data}
sale_order_data = self.env['sale.order']._read_group([
('team_id', 'in', self.ids),
('state', '!=', 'cancel'),
], ['team_id'], ['__count'])
data_map = {team.id: count for team, count in sale_order_data}
for team in self:
team.sale_order_count = data_map.get(team.id, 0)
def _in_sale_scope(self):
return self.env.context.get('in_sales_app')
def _graph_get_model(self):
if self._in_sale_scope():
return 'sale.report'
return super()._graph_get_model()
def _graph_date_column(self):
if self._in_sale_scope():
return 'date'
return super()._graph_date_column()
def _graph_get_table(self, GraphModel):
if self._in_sale_scope():
# For a team not shared between company, we make sure the amounts are expressed
# in the currency of the team company and not converted to the current company currency,
# as the amounts of the sale report are converted in the currency
# of the current company (for multi-company reporting, see #83550)
GraphModel = GraphModel.with_company(self.company_id)
return f"({GraphModel._table_query}) AS {GraphModel._table}"
return super()._graph_get_table(GraphModel)
def _graph_y_query(self):
if self._in_sale_scope():
return 'SUM(price_subtotal)'
return super()._graph_y_query()
def _extra_sql_conditions(self):
if self._in_sale_scope():
return "AND state in ('sale', 'done', 'pos_done')"
return super()._extra_sql_conditions()
def _graph_title_and_key(self):
if self._in_sale_scope():
return ['', _('Sales: Untaxed Total')] # no more title
return super()._graph_title_and_key()
def _compute_dashboard_button_name(self):
super(CrmTeam,self)._compute_dashboard_button_name()
if self._in_sale_scope():
@ -163,7 +78,7 @@ class CrmTeam(models.Model):
for team in self:
if team.sale_order_count >= SO_COUNT_TRIGGER:
raise UserError(
_('Team %(team_name)s has %(sale_order_count)s active sale orders. Consider canceling them or archiving the team instead.',
_('Team %(team_name)s has %(sale_order_count)s active sale orders. Consider cancelling them or archiving the team instead.',
team_name=team.name,
sale_order_count=team.sale_order_count
))