Skip to content
Extraits de code Groupes Projets
Valider 7dbfabc6 rédigé par Julien - Le Filament's avatar Julien - Le Filament
Parcourir les fichiers

Merge branch '14.0-sale-overview' into '14.0'

[UPD] do not check is projet milestone in sale timesheet overview

See merge request !2
parents 60d04deb 4b8a115a
Aucune branche associée trouvée
Aucune étiquette associée trouvée
1 requête de fusion!2[UPD] do not check is projet milestone in sale timesheet overview
...@@ -7,7 +7,7 @@ from odoo.addons.sale_timesheet.models.project_overview import _to_action_data ...@@ -7,7 +7,7 @@ from odoo.addons.sale_timesheet.models.project_overview import _to_action_data
class Project(models.Model): class Project(models.Model):
_inherit = 'project.project' _inherit = "project.project"
# ------------------------------------------------------ # ------------------------------------------------------
# Fields declaration # Fields declaration
...@@ -37,9 +37,9 @@ class Project(models.Model): ...@@ -37,9 +37,9 @@ class Project(models.Model):
if not self: if not self:
return False return False
uom_hour = self.env.ref('uom.product_uom_hour') uom_hour = self.env.ref("uom.product_uom_hour")
company_uom = self.env.company.timesheet_encode_uom_id company_uom = self.env.company.timesheet_encode_uom_id
is_uom_day = company_uom and company_uom == self.env.ref('uom.product_uom_day') is_uom_day = company_uom and company_uom == self.env.ref("uom.product_uom_day")
# build SQL query and fetch raw data # build SQL query and fetch raw data
query, query_params = self._table_rows_sql_query() query, query_params = self._table_rows_sql_query()
...@@ -54,53 +54,98 @@ class Project(models.Model): ...@@ -54,53 +54,98 @@ class Project(models.Model):
sale_line_ids = set() sale_line_ids = set()
sale_order_ids = set() sale_order_ids = set()
for key_tuple, row in rows_employee.items(): for key_tuple, row in rows_employee.items():
if row[0]['sale_line_id']: if row[0]["sale_line_id"]:
sale_line_ids.add(row[0]['sale_line_id']) sale_line_ids.add(row[0]["sale_line_id"])
if row[0]['sale_order_id']: if row[0]["sale_order_id"]:
sale_order_ids.add(row[0]['sale_order_id']) sale_order_ids.add(row[0]["sale_order_id"])
sale_orders = self.env['sale.order'].sudo().browse(sale_order_ids | empty_order_ids) sale_orders = (
sale_order_lines = self.env['sale.order.line'].sudo().browse(sale_line_ids | empty_line_ids) self.env["sale.order"].sudo().browse(sale_order_ids | empty_order_ids)
)
sale_order_lines = (
self.env["sale.order.line"].sudo().browse(sale_line_ids | empty_line_ids)
)
map_so_names = {so.id: so.name for so in sale_orders} map_so_names = {so.id: so.name for so in sale_orders}
map_so_cancel = {so.id: so.state == 'cancel' for so in sale_orders} map_so_cancel = {so.id: so.state == "cancel" for so in sale_orders}
map_sol = {sol.id: sol for sol in sale_order_lines} map_sol = {sol.id: sol for sol in sale_order_lines}
map_sol_names = {sol.id: sol.name.split('\n')[0] if sol.name else _('No Sales Order Line') for sol in map_sol_names = {
sale_order_lines} sol.id: sol.name.split("\n")[0] if sol.name else _("No Sales Order Line")
for sol in sale_order_lines
}
map_sol_so = {sol.id: sol.order_id.id for sol in sale_order_lines} map_sol_so = {sol.id: sol.order_id.id for sol in sale_order_lines}
rows_sale_line = {} # (so, sol) -> [INFO, before, M1, M2, M3, Done, M3, M4, M5, After, Forecasted] rows_sale_line = (
{}
) # (so, sol) -> [INFO, before, M1, M2, M3, Done, M3, M4, M5, After, Forecasted]
for sale_line_id in empty_line_ids: # add service SO line having no timesheet for sale_line_id in empty_line_ids: # add service SO line having no timesheet
sale_line_row_key = (map_sol_so.get(sale_line_id), sale_line_id) sale_line_row_key = (map_sol_so.get(sale_line_id), sale_line_id)
sale_line = map_sol.get(sale_line_id) sale_line = map_sol.get(sale_line_id)
is_milestone = sale_line.product_id.invoice_policy == 'delivery' and sale_line.product_id.service_type == 'manual' if sale_line else False is_milestone = (
rows_sale_line[sale_line_row_key] = [{'label': map_sol_names.get(sale_line_id, _('No Sales Order Line')), sale_line.product_id.invoice_policy == "delivery"
'res_id': sale_line_id, 'res_model': 'sale.order.line', and sale_line.product_id.service_type == "manual"
'type': 'sale_order_line', if sale_line
'is_milestone': is_milestone}] + default_row_vals[:] else False
if not is_milestone: )
rows_sale_line[sale_line_row_key] = [
{
"label": map_sol_names.get(sale_line_id, _("No Sales Order Line")),
"res_id": sale_line_id,
"res_model": "sale.order.line",
"type": "sale_order_line",
"is_milestone": is_milestone,
}
] + default_row_vals[:]
# ***** Modif Filament ***** # ***** Modif Filament *****
rows_sale_line[sale_line_row_key][ rows_sale_line[sale_line_row_key][-2] = (
-2] = sale_line.product_uom_qty * sale_line.price_unit / sale_line.taux_horaire if sale_line else 0.0 sale_line.product_uom_qty
* sale_line.price_unit
/ sale_line.taux_horaire
if sale_line
else 0.0
)
rows_sale_line_all_data = {} rows_sale_line_all_data = {}
if not employees: if not employees:
employees = self.env['hr.employee'].sudo().search(self.env['account.analytic.line']._domain_employee_id()) employees = (
self.env["hr.employee"]
.sudo()
.search(self.env["account.analytic.line"]._domain_employee_id())
)
for row_key, row_employee in rows_employee.items(): for row_key, row_employee in rows_employee.items():
sale_order_id, sale_line_id, employee_id = row_key sale_order_id, sale_line_id, employee_id = row_key
# sale line row # sale line row
sale_line_row_key = (sale_order_id, sale_line_id) sale_line_row_key = (sale_order_id, sale_line_id)
if sale_line_row_key not in rows_sale_line: if sale_line_row_key not in rows_sale_line:
sale_line = map_sol.get(sale_line_id, self.env['sale.order.line']) sale_line = map_sol.get(sale_line_id, self.env["sale.order.line"])
is_milestone = sale_line.product_id.invoice_policy == 'delivery' and sale_line.product_id.service_type == 'manual' if sale_line else False is_milestone = (
rows_sale_line[sale_line_row_key] = [{'label': map_sol_names.get(sale_line.id) if sale_line else _( sale_line.product_id.invoice_policy == "delivery"
'No Sales Order Line'), 'res_id': sale_line_id, 'res_model': 'sale.order.line', and sale_line.product_id.service_type == "manual"
'type': 'sale_order_line', if sale_line
'is_milestone': is_milestone}] + default_row_vals[ else False
:] # INFO, before, M1, M2, M3, Done, M3, M4, M5, After, Forecasted )
if not is_milestone: rows_sale_line[sale_line_row_key] = [
{
"label": (
map_sol_names.get(sale_line.id)
if sale_line
else _("No Sales Order Line")
),
"res_id": sale_line_id,
"res_model": "sale.order.line",
"type": "sale_order_line",
"is_milestone": is_milestone,
}
] + default_row_vals[
:
] # INFO, before, M1, M2, M3, Done, M3, M4, M5, After, Forecasted
# ***** Modif Filament ***** # ***** Modif Filament *****
rows_sale_line[sale_line_row_key][ rows_sale_line[sale_line_row_key][-2] = (
-2] = sale_line.product_uom_qty * sale_line.price_unit / sale_line.taux_horaire if sale_line else 0.0 sale_line.product_uom_qty
* sale_line.price_unit
/ sale_line.taux_horaire
if sale_line
else 0.0
)
if sale_line_row_key not in rows_sale_line_all_data: if sale_line_row_key not in rows_sale_line_all_data:
rows_sale_line_all_data[sale_line_row_key] = [0] * len(row_employee) rows_sale_line_all_data[sale_line_row_key] = [0] * len(row_employee)
...@@ -108,22 +153,31 @@ class Project(models.Model): ...@@ -108,22 +153,31 @@ class Project(models.Model):
if employee_id in employees.ids: if employee_id in employees.ids:
rows_sale_line[sale_line_row_key][index] += row_employee[index] rows_sale_line[sale_line_row_key][index] += row_employee[index]
rows_sale_line_all_data[sale_line_row_key][index] += row_employee[index] rows_sale_line_all_data[sale_line_row_key][index] += row_employee[index]
if not rows_sale_line[sale_line_row_key][0].get('is_milestone'):
rows_sale_line[sale_line_row_key][-1] = rows_sale_line[sale_line_row_key][-2] - \
rows_sale_line_all_data[sale_line_row_key][5]
else:
rows_sale_line[sale_line_row_key][-1] = 0
rows_sale_order = {} # so -> [INFO, before, M1, M2, M3, Done, M3, M4, M5, After, Forecasted] # ***** Modif Filament *****
rows_sale_line[sale_line_row_key][-1] = (
rows_sale_line[sale_line_row_key][-2]
- rows_sale_line_all_data[sale_line_row_key][5]
)
rows_sale_order = (
{}
) # so -> [INFO, before, M1, M2, M3, Done, M3, M4, M5, After, Forecasted]
for row_key, row_sale_line in rows_sale_line.items(): for row_key, row_sale_line in rows_sale_line.items():
sale_order_id = row_key[0] sale_order_id = row_key[0]
# sale order row # sale order row
if sale_order_id not in rows_sale_order: if sale_order_id not in rows_sale_order:
rows_sale_order[sale_order_id] = [{'label': map_so_names.get(sale_order_id, _('No Sales Order')), rows_sale_order[sale_order_id] = [
'canceled': map_so_cancel.get(sale_order_id, False), {
'res_id': sale_order_id, 'res_model': 'sale.order', "label": map_so_names.get(sale_order_id, _("No Sales Order")),
'type': 'sale_order'}] + default_row_vals[ "canceled": map_so_cancel.get(sale_order_id, False),
:] # INFO, before, M1, M2, M3, Done, M3, M4, M5, After, Forecasted "res_id": sale_order_id,
"res_model": "sale.order",
"type": "sale_order",
}
] + default_row_vals[
:
] # INFO, before, M1, M2, M3, Done, M3, M4, M5, After, Forecasted
for index in range(1, len(row_sale_line)): for index in range(1, len(row_sale_line)):
rows_sale_order[sale_order_id][index] += row_sale_line[index] rows_sale_order[sale_order_id][index] += row_sale_line[index]
...@@ -134,143 +188,199 @@ class Project(models.Model): ...@@ -134,143 +188,199 @@ class Project(models.Model):
timesheet_forecast_table_rows.append(sale_order_row) timesheet_forecast_table_rows.append(sale_order_row)
for sale_line_row_key, sale_line_row in rows_sale_line.items(): for sale_line_row_key, sale_line_row in rows_sale_line.items():
if sale_order_id == sale_line_row_key[0]: if sale_order_id == sale_line_row_key[0]:
sale_order_row[0]['has_children'] = True sale_order_row[0]["has_children"] = True
timesheet_forecast_table_rows.append(sale_line_row) timesheet_forecast_table_rows.append(sale_line_row)
for employee_row_key, employee_row in rows_employee.items(): for employee_row_key, employee_row in rows_employee.items():
if sale_order_id == employee_row_key[0] and sale_line_row_key[1] == employee_row_key[1] and \ if (
employee_row_key[2] in employees.ids: sale_order_id == employee_row_key[0]
sale_line_row[0]['has_children'] = True and sale_line_row_key[1] == employee_row_key[1]
and employee_row_key[2] in employees.ids
):
sale_line_row[0]["has_children"] = True
timesheet_forecast_table_rows.append(employee_row) timesheet_forecast_table_rows.append(employee_row)
if is_uom_day: if is_uom_day:
# convert all values from hours to days # convert all values from hours to days
for row in timesheet_forecast_table_rows: for row in timesheet_forecast_table_rows:
for index in range(1, len(row)): for index in range(1, len(row)):
row[index] = round(uom_hour._compute_quantity(row[index], company_uom, raise_if_failure=False), 2) row[index] = round(
uom_hour._compute_quantity(
row[index], company_uom, raise_if_failure=False
),
2,
)
# complete table data # complete table data
return { return {"header": self._table_header(), "rows": timesheet_forecast_table_rows}
'header': self._table_header(),
'rows': timesheet_forecast_table_rows
}
def _plan_get_stat_button(self): def _plan_get_stat_button(self):
stat_buttons = [] stat_buttons = []
num_projects = len(self) num_projects = len(self)
if num_projects == 1: if num_projects == 1:
action_data = _to_action_data('project.project', res_id=self.id, action_data = _to_action_data(
views=[[self.env.ref('project.edit_project').id, 'form']]) "project.project",
res_id=self.id,
views=[[self.env.ref("project.edit_project").id, "form"]],
)
else: else:
action_data = _to_action_data(action=self.env.ref('project.open_view_project_all_config').sudo(), action_data = _to_action_data(
domain=[('id', 'in', self.ids)]) action=self.env.ref("project.open_view_project_all_config").sudo(),
domain=[("id", "in", self.ids)],
)
stat_buttons.append({ stat_buttons.append(
'name': _('Project') if num_projects == 1 else _('Projects'), {
'count': num_projects, "name": _("Project") if num_projects == 1 else _("Projects"),
'icon': 'fa fa-puzzle-piece', "count": num_projects,
'action': action_data "icon": "fa fa-puzzle-piece",
}) "action": action_data,
}
)
# if only one project, add it in the context as default value # if only one project, add it in the context as default value
tasks_domain = [('project_id', 'in', self.ids)] tasks_domain = [("project_id", "in", self.ids)]
tasks_context = self.env.context.copy() tasks_context = self.env.context.copy()
tasks_context.pop('search_default_name', False) tasks_context.pop("search_default_name", False)
late_tasks_domain = [('project_id', 'in', self.ids), ('date_deadline', '<', fields.Date.to_string(fields.Date.today())), ('date_end', '=', False)] late_tasks_domain = [
overtime_tasks_domain = [('project_id', 'in', self.ids), ('overtime', '>', 0), ('planned_hours', '>', 0)] ("project_id", "in", self.ids),
("date_deadline", "<", fields.Date.to_string(fields.Date.today())),
("date_end", "=", False),
]
overtime_tasks_domain = [
("project_id", "in", self.ids),
("overtime", ">", 0),
("planned_hours", ">", 0),
]
if len(self) == 1: if len(self) == 1:
tasks_context = {**tasks_context, 'default_project_id': self.id} tasks_context = {**tasks_context, "default_project_id": self.id}
elif len(self): elif len(self):
task_projects_ids = self.env['project.task'].read_group([('project_id', 'in', self.ids)], ['project_id'], ['project_id']) task_projects_ids = self.env["project.task"].read_group(
task_projects_ids = [p['project_id'][0] for p in task_projects_ids] [("project_id", "in", self.ids)], ["project_id"], ["project_id"]
)
task_projects_ids = [p["project_id"][0] for p in task_projects_ids]
if len(task_projects_ids) == 1: if len(task_projects_ids) == 1:
tasks_context = {**tasks_context, 'default_project_id': task_projects_ids[0]} tasks_context = {
**tasks_context,
stat_buttons.append({ "default_project_id": task_projects_ids[0],
'name': _('Tasks'), }
'count': sum(self.mapped('task_count')),
'icon': 'fa fa-tasks', stat_buttons.append(
'action': _to_action_data( {
action=self.env.ref('project.action_view_task').sudo(), "name": _("Tasks"),
"count": sum(self.mapped("task_count")),
"icon": "fa fa-tasks",
"action": _to_action_data(
action=self.env.ref("project.action_view_task").sudo(),
domain=tasks_domain, domain=tasks_domain,
context=tasks_context context=tasks_context,
),
}
) )
}) stat_buttons.append(
stat_buttons.append({ {
'name': [_("Tasks"), _("Late")], "name": [_("Tasks"), _("Late")],
'count': self.env['project.task'].search_count(late_tasks_domain), "count": self.env["project.task"].search_count(late_tasks_domain),
'icon': 'fa fa-tasks', "icon": "fa fa-tasks",
'action': _to_action_data( "action": _to_action_data(
action=self.env.ref('project.action_view_task').sudo(), action=self.env.ref("project.action_view_task").sudo(),
domain=late_tasks_domain, domain=late_tasks_domain,
context=tasks_context, context=tasks_context,
), ),
}) }
stat_buttons.append({ )
'name': [_("Tasks"), _("in Overtime")], stat_buttons.append(
'count': self.env['project.task'].search_count(overtime_tasks_domain), {
'icon': 'fa fa-tasks', "name": [_("Tasks"), _("in Overtime")],
'action': _to_action_data( "count": self.env["project.task"].search_count(overtime_tasks_domain),
action=self.env.ref('project.action_view_task').sudo(), "icon": "fa fa-tasks",
"action": _to_action_data(
action=self.env.ref("project.action_view_task").sudo(),
domain=overtime_tasks_domain, domain=overtime_tasks_domain,
context=tasks_context, context=tasks_context,
), ),
}) }
)
if self.env.user.has_group('sales_team.group_sale_salesman_all_leads'): if self.env.user.has_group("sales_team.group_sale_salesman_all_leads"):
# read all the sale orders linked to the projects' tasks # read all the sale orders linked to the projects' tasks
task_so_ids = self.env['project.task'].search_read([ task_so_ids = self.env["project.task"].search_read(
('project_id', 'in', self.ids), ('sale_order_id', '!=', False) [("project_id", "in", self.ids), ("sale_order_id", "!=", False)],
], ['sale_order_id']) ["sale_order_id"],
task_so_ids = [o['sale_order_id'][0] for o in task_so_ids] )
task_so_ids = [o["sale_order_id"][0] for o in task_so_ids]
sale_ids = self.env['sale.order'].search([('project_id', 'in', self.ids)]) sale_ids = self.env["sale.order"].search([("project_id", "in", self.ids)])
sale_orders = self.mapped('sale_line_id.order_id') | self.env['sale.order'].browse(task_so_ids) | sale_ids sale_orders = (
self.mapped("sale_line_id.order_id")
| self.env["sale.order"].browse(task_so_ids)
| sale_ids
)
if sale_orders: if sale_orders:
stat_buttons.append({ stat_buttons.append(
'name': _('Sales Orders'), {
'count': len(sale_orders), "name": _("Sales Orders"),
'icon': 'fa fa-dollar', "count": len(sale_orders),
'action': _to_action_data( "icon": "fa fa-dollar",
action=self.env.ref('sale.action_orders').sudo(), "action": _to_action_data(
domain=[('id', 'in', sale_orders.ids)], action=self.env.ref("sale.action_orders").sudo(),
context={'create': False, 'edit': False, 'delete': False} domain=[("id", "in", sale_orders.ids)],
context={"create": False, "edit": False, "delete": False},
),
}
) )
})
invoice_ids = self.env['sale.order'].search_read([('id', 'in', sale_orders.ids)], ['invoice_ids']) invoice_ids = self.env["sale.order"].search_read(
invoice_ids = list(itertools.chain(*[i['invoice_ids'] for i in invoice_ids])) [("id", "in", sale_orders.ids)], ["invoice_ids"]
invoice_ids = self.env['account.move'].search_read([('id', 'in', invoice_ids), ('move_type', '=', 'out_invoice')], ['id']) )
invoice_ids = list(map(lambda x: x['id'], invoice_ids)) invoice_ids = list(
itertools.chain(*[i["invoice_ids"] for i in invoice_ids])
)
invoice_ids = self.env["account.move"].search_read(
[("id", "in", invoice_ids), ("move_type", "=", "out_invoice")],
["id"],
)
invoice_ids = list(map(lambda x: x["id"], invoice_ids))
if invoice_ids: if invoice_ids:
stat_buttons.append({ stat_buttons.append(
'name': _('Invoices'), {
'count': len(invoice_ids), "name": _("Invoices"),
'icon': 'fa fa-pencil-square-o', "count": len(invoice_ids),
'action': _to_action_data( "icon": "fa fa-pencil-square-o",
action=self.env.ref('account.action_move_out_invoice_type').sudo(), "action": _to_action_data(
domain=[('id', 'in', invoice_ids), ('move_type', '=', 'out_invoice')], action=self.env.ref(
context={'create': False, 'delete': False} "account.action_move_out_invoice_type"
).sudo(),
domain=[
("id", "in", invoice_ids),
("move_type", "=", "out_invoice"),
],
context={"create": False, "delete": False},
),
}
) )
})
ts_tree = self.env.ref('hr_timesheet.hr_timesheet_line_tree') ts_tree = self.env.ref("hr_timesheet.hr_timesheet_line_tree")
ts_form = self.env.ref('hr_timesheet.hr_timesheet_line_form') ts_form = self.env.ref("hr_timesheet.hr_timesheet_line_form")
if self.env.company.timesheet_encode_uom_id == self.env.ref('uom.product_uom_day'): if self.env.company.timesheet_encode_uom_id == self.env.ref(
timesheet_label = [_('Days'), _('Recorded')] "uom.product_uom_day"
):
timesheet_label = [_("Days"), _("Recorded")]
else: else:
timesheet_label = [_('Hours'), _('Recorded')] timesheet_label = [_("Hours"), _("Recorded")]
stat_buttons.append({ stat_buttons.append(
'name': timesheet_label, {
'count': sum(self.mapped('total_timesheet_time')), "name": timesheet_label,
'icon': 'fa fa-calendar', "count": sum(self.mapped("total_timesheet_time")),
'action': _to_action_data( "icon": "fa fa-calendar",
'account.analytic.line', "action": _to_action_data(
domain=[('project_id', 'in', self.ids)], "account.analytic.line",
views=[(ts_tree.id, 'list'), (ts_form.id, 'form')], domain=[("project_id", "in", self.ids)],
views=[(ts_tree.id, "list"), (ts_form.id, "form")],
),
}
) )
})
return stat_buttons return stat_buttons
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter