diff --git a/addons/sale_timesheet/data/sale_timesheet_filters.xml b/addons/sale_timesheet/data/sale_timesheet_filters.xml
index 71aa9f43d3d..2894ad05c76 100644
--- a/addons/sale_timesheet/data/sale_timesheet_filters.xml
+++ b/addons/sale_timesheet/data/sale_timesheet_filters.xml
@@ -7,9 +7,8 @@
{
- 'group_by': ['project_id', 'sale_line_id'],
- 'pivot_measures': ['amount_untaxed_to_invoice', 'amount_untaxed_invoiced', 'timesheet_cost', 'timesheet_unit_amount'],
- 'pivot_column_groupby': [], 'pivot_row_groupby': []
+ 'group_by': ['project_id', 'sale_line_id'],
+ 'pivot_measures': ['amount_untaxed_to_invoice', 'amount_untaxed_invoiced', 'timesheet_cost', 'timesheet_unit_amount']
}
diff --git a/addons/sale_timesheet/models/project_overview.py b/addons/sale_timesheet/models/project_overview.py
index 17327779f36..bd02f092307 100644
--- a/addons/sale_timesheet/models/project_overview.py
+++ b/addons/sale_timesheet/models/project_overview.py
@@ -243,9 +243,11 @@ class Project(models.Model):
timesheet_forecast_table_rows.append(sale_order_row)
for sale_line_row_key, sale_line_row in rows_sale_line.items():
if sale_order_id == sale_line_row_key[0]:
+ sale_order_row[0]['has_children'] = True
timesheet_forecast_table_rows.append(sale_line_row)
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 employee_row_key[2] in employees.ids:
+ sale_line_row[0]['has_children'] = True
timesheet_forecast_table_rows.append(employee_row)
# complete table data
diff --git a/addons/sale_timesheet/report/project_profitability_report_analysis.py b/addons/sale_timesheet/report/project_profitability_report_analysis.py
index 865ce757695..3b58635abbc 100644
--- a/addons/sale_timesheet/report/project_profitability_report_analysis.py
+++ b/addons/sale_timesheet/report/project_profitability_report_analysis.py
@@ -17,6 +17,7 @@ class ProfitabilityAnalysis(models.Model):
company_id = fields.Many2one('res.company', string='Project Company', readonly=True)
user_id = fields.Many2one('res.users', string='Project Manager', readonly=True)
partner_id = fields.Many2one('res.partner', string='Customer', readonly=True)
+ line_date = fields.Date("Date", readonly=True)
# cost
timesheet_unit_amount = fields.Float("Timesheet Duration", digits=(16, 2), readonly=True, group_operator="sum")
timesheet_cost = fields.Float("Timesheet Cost", digits=(16, 2), readonly=True, group_operator="sum")
@@ -27,7 +28,7 @@ class ProfitabilityAnalysis(models.Model):
sale_order_id = fields.Many2one('sale.order', string='Sale Order', readonly=True)
product_id = fields.Many2one('product.product', string='Product', readonly=True)
- amount_untaxed_to_invoice = fields.Float("Untaxed Amount To Invoice", digits=(16, 2), readonly=True, group_operator="sum")
+ amount_untaxed_to_invoice = fields.Float("Untaxed Amount to Invoice", digits=(16, 2), readonly=True, group_operator="sum")
amount_untaxed_invoiced = fields.Float("Untaxed Amount Invoiced", digits=(16, 2), readonly=True, group_operator="sum")
expense_amount_untaxed_to_invoice = fields.Float("Untaxed Amount to Re-invoice", digits=(16, 2), readonly=True, group_operator="sum")
expense_amount_untaxed_invoiced = fields.Float("Untaxed Amount Re-invoiced", digits=(16, 2), readonly=True, group_operator="sum")
@@ -60,6 +61,7 @@ class ProfitabilityAnalysis(models.Model):
sub.timesheet_cost as timesheet_cost,
sub.expense_cost as expense_cost,
sub.other_revenues as other_revenues,
+ sub.line_date as line_date,
(sub.expense_amount_untaxed_to_invoice + sub.expense_amount_untaxed_invoiced + sub.amount_untaxed_to_invoice +
sub.amount_untaxed_invoiced + sub.other_revenues + sub.timesheet_cost + sub.expense_cost)
as margin
@@ -77,35 +79,20 @@ class ProfitabilityAnalysis(models.Model):
S.date_order AS order_confirmation_date,
SOL.product_id AS product_id,
SOL.qty_delivered_method AS sale_qty_delivered_method,
- CASE
- WHEN SOL.qty_delivered_method = 'analytic' THEN (SOL.untaxed_amount_to_invoice / CASE COALESCE(S.currency_rate, 0) WHEN 0 THEN 1.0 ELSE S.currency_rate END)
- ELSE 0.0
- END AS expense_amount_untaxed_to_invoice,
- CASE
- WHEN SOL.qty_delivered_method = 'analytic' AND SOL.invoice_status != 'no'
- THEN
- CASE
- WHEN T.expense_policy = 'sales_price'
- THEN (SOL.price_reduce / CASE COALESCE(S.currency_rate, 0) WHEN 0 THEN 1.0 ELSE S.currency_rate END) * SOL.qty_invoiced
- ELSE -COST_SUMMARY.expense_cost
- END
- ELSE 0.0
- END AS expense_amount_untaxed_invoiced,
- CASE
- WHEN SOL.qty_delivered_method IN ('timesheet', 'manual') THEN (SOL.untaxed_amount_to_invoice / CASE COALESCE(S.currency_rate, 0) WHEN 0 THEN 1.0 ELSE S.currency_rate END)
- ELSE 0.0
- END AS amount_untaxed_to_invoice,
- CASE
- WHEN SOL.qty_delivered_method IN ('timesheet', 'manual') THEN (COALESCE(SOL.untaxed_amount_invoiced, COST_SUMMARY.downpayment_invoiced) / CASE COALESCE(S.currency_rate, 0) WHEN 0 THEN 1.0 ELSE S.currency_rate END)
- ELSE 0.0
- END AS amount_untaxed_invoiced,
+ COST_SUMMARY.expense_amount_untaxed_to_invoice AS expense_amount_untaxed_to_invoice,
+ COST_SUMMARY.expense_amount_untaxed_invoiced AS expense_amount_untaxed_invoiced,
+ COST_SUMMARY.amount_untaxed_to_invoice AS amount_untaxed_to_invoice,
+ COST_SUMMARY.amount_untaxed_invoiced AS amount_untaxed_invoiced,
COST_SUMMARY.timesheet_unit_amount AS timesheet_unit_amount,
COST_SUMMARY.timesheet_cost AS timesheet_cost,
COST_SUMMARY.expense_cost AS expense_cost,
- COST_SUMMARY.other_revenues AS other_revenues
+ COST_SUMMARY.other_revenues AS other_revenues,
+ COST_SUMMARY.line_date::date AS line_date
FROM project_project P
JOIN res_company C ON C.id = P.company_id
LEFT JOIN (
+ -- Each costs and revenues will be retrieved individually by sub-requests
+ -- This is required to able to get the date
SELECT
project_id,
analytic_account_id,
@@ -114,40 +101,56 @@ class ProfitabilityAnalysis(models.Model):
SUM(timesheet_cost) AS timesheet_cost,
SUM(expense_cost) AS expense_cost,
SUM(other_revenues) AS other_revenues,
- SUM(downpayment_invoiced) AS downpayment_invoiced
+ SUM(downpayment_invoiced) AS downpayment_invoiced,
+ SUM(expense_amount_untaxed_to_invoice) AS expense_amount_untaxed_to_invoice,
+ SUM(expense_amount_untaxed_invoiced) AS expense_amount_untaxed_invoiced,
+ SUM(amount_untaxed_to_invoice) AS amount_untaxed_to_invoice,
+ SUM(amount_untaxed_invoiced) AS amount_untaxed_invoiced,
+ line_date AS line_date
FROM (
+ -- Get the timesheet costs
SELECT
P.id AS project_id,
P.analytic_account_id AS analytic_account_id,
TS.so_line AS sale_line_id,
- SUM(TS.unit_amount) AS timesheet_unit_amount,
- SUM(TS.amount) AS timesheet_cost,
+ TS.unit_amount AS timesheet_unit_amount,
+ TS.amount AS timesheet_cost,
0.0 AS other_revenues,
0.0 AS expense_cost,
- 0.0 AS downpayment_invoiced
+ 0.0 AS downpayment_invoiced,
+ 0.0 AS expense_amount_untaxed_to_invoice,
+ 0.0 AS expense_amount_untaxed_invoiced,
+ 0.0 AS amount_untaxed_to_invoice,
+ 0.0 AS amount_untaxed_invoiced,
+ TS.date AS line_date
FROM account_analytic_line TS, project_project P
WHERE TS.project_id IS NOT NULL AND P.id = TS.project_id AND P.active = 't' AND P.allow_timesheets = 't'
- GROUP BY P.id, TS.so_line
- UNION
+ UNION ALL
+ -- Get the other revenues
SELECT
P.id AS project_id,
P.analytic_account_id AS analytic_account_id,
AAL.so_line AS sale_line_id,
0.0 AS timesheet_unit_amount,
0.0 AS timesheet_cost,
- SUM(AAL.amount) AS other_revenues,
+ AAL.amount AS other_revenues,
0.0 AS expense_cost,
- 0.0 AS downpayment_invoiced
+ 0.0 AS downpayment_invoiced,
+ 0.0 AS expense_amount_untaxed_to_invoice,
+ 0.0 AS expense_amount_untaxed_invoiced,
+ 0.0 AS amount_untaxed_to_invoice,
+ 0.0 AS amount_untaxed_invoiced,
+ AAL.date AS line_date
FROM project_project P
LEFT JOIN account_analytic_account AA ON P.analytic_account_id = AA.id
LEFT JOIN account_analytic_line AAL ON AAL.account_id = AA.id
WHERE AAL.amount > 0.0 AND AAL.project_id IS NULL AND P.active = 't' AND P.allow_timesheets = 't'
- GROUP BY P.id, AA.id, AAL.so_line
- UNION
+ UNION ALL
+ -- Get the expense costs from account analytic line
SELECT
P.id AS project_id,
P.analytic_account_id AS analytic_account_id,
@@ -155,16 +158,21 @@ class ProfitabilityAnalysis(models.Model):
0.0 AS timesheet_unit_amount,
0.0 AS timesheet_cost,
0.0 AS other_revenues,
- SUM(AAL.amount) AS expense_cost,
- 0.0 AS downpayment_invoiced
+ AAL.amount AS expense_cost,
+ 0.0 AS downpayment_invoiced,
+ 0.0 AS expense_amount_untaxed_to_invoice,
+ 0.0 AS expense_amount_untaxed_invoiced,
+ 0.0 AS amount_untaxed_to_invoice,
+ 0.0 AS amount_untaxed_invoiced,
+ AAL.date AS line_date
FROM project_project P
LEFT JOIN account_analytic_account AA ON P.analytic_account_id = AA.id
LEFT JOIN account_analytic_line AAL ON AAL.account_id = AA.id
WHERE AAL.amount < 0.0 AND AAL.project_id IS NULL AND P.active = 't' AND P.allow_timesheets = 't'
- GROUP BY P.id, AA.id, AAL.so_line
- UNION
+ UNION ALL
+ -- Get the invoiced downpayments
SELECT
P.id AS project_id,
P.analytic_account_id AS analytic_account_id,
@@ -173,16 +181,21 @@ class ProfitabilityAnalysis(models.Model):
0.0 AS timesheet_cost,
0.0 AS other_revenues,
0.0 AS expense_cost,
- CASE WHEN MY_SOLS.invoice_status = 'invoiced' THEN MY_SOLS.price_reduce ELSE 0.0 END AS downpayment_invoiced
+ CASE WHEN MY_SOLS.invoice_status = 'invoiced' THEN MY_SOLS.price_reduce ELSE 0.0 END AS downpayment_invoiced,
+ 0.0 AS expense_amount_untaxed_to_invoice,
+ 0.0 AS expense_amount_untaxed_invoiced,
+ 0.0 AS amount_untaxed_to_invoice,
+ 0.0 AS amount_untaxed_invoiced,
+ MY_S.date_order AS line_date
FROM project_project P
LEFT JOIN sale_order_line MY_SOL ON P.sale_line_id = MY_SOL.id
LEFT JOIN sale_order MY_S ON MY_SOL.order_id = MY_S.id
LEFT JOIN sale_order_line MY_SOLS ON MY_SOLS.order_id = MY_S.id
WHERE MY_SOLS.is_downpayment = 't'
- GROUP BY P.id, MY_SOLS.id
- UNION
+ UNION ALL
+ -- Get the expense costs from sale order line
SELECT
P.id AS project_id,
P.analytic_account_id AS analytic_account_id,
@@ -191,7 +204,12 @@ class ProfitabilityAnalysis(models.Model):
0.0 AS timesheet_cost,
0.0 AS other_revenues,
OLIS.price_reduce AS expense_cost,
- 0.0 AS downpayment_invoiced
+ 0.0 AS downpayment_invoiced,
+ 0.0 AS expense_amount_untaxed_to_invoice,
+ 0.0 AS expense_amount_untaxed_invoiced,
+ 0.0 AS amount_untaxed_to_invoice,
+ 0.0 AS amount_untaxed_invoiced,
+ ANLI.date AS line_date
FROM project_project P
LEFT JOIN account_analytic_account ANAC ON P.analytic_account_id = ANAC.id
LEFT JOIN account_analytic_line ANLI ON ANAC.id = ANLI.account_id
@@ -199,45 +217,141 @@ class ProfitabilityAnalysis(models.Model):
LEFT JOIN sale_order ORD ON OLI.order_id = ORD.id
LEFT JOIN sale_order_line OLIS ON ORD.id = OLIS.order_id
WHERE OLIS.product_id = ANLI.product_id AND OLIS.is_downpayment = 't' AND ANLI.amount < 0.0 AND ANLI.project_id IS NULL AND P.active = 't' AND P.allow_timesheets = 't'
- GROUP BY P.id, OLIS.id
- UNION
+ UNION ALL
+ -- Get the following values: expense amount untaxed to invoice/invoiced, amount untaxed to invoice/invoiced
+ -- These values have to be computed from all the records retrieved just above but grouped by project and sale order line
SELECT
- P.id AS project_id,
- P.analytic_account_id AS analytic_account_id,
- SOL.id AS sale_line_id,
+ AMOUNT_UNTAXED.project_id AS project_id,
+ AMOUNT_UNTAXED.analytic_account_id AS analytic_account_id,
+ AMOUNT_UNTAXED.sale_line_id AS sale_line_id,
0.0 AS timesheet_unit_amount,
0.0 AS timesheet_cost,
0.0 AS other_revenues,
0.0 AS expense_cost,
- 0.0 AS downpayment_invoiced
- FROM sale_order_line SOL
- INNER JOIN project_project P ON SOL.project_id = P.id
- WHERE P.active = 't' AND P.allow_timesheets = 't'
+ 0.0 AS downpayment_invoiced,
+ CASE
+ WHEN SOL.qty_delivered_method = 'analytic' THEN (SOL.untaxed_amount_to_invoice / CASE COALESCE(S.currency_rate, 0) WHEN 0 THEN 1.0 ELSE S.currency_rate END)
+ ELSE 0.0
+ END AS expense_amount_untaxed_to_invoice,
+ CASE
+ WHEN SOL.qty_delivered_method = 'analytic' AND SOL.invoice_status != 'no'
+ THEN
+ CASE
+ WHEN T.expense_policy = 'sales_price'
+ THEN (SOL.price_reduce / CASE COALESCE(S.currency_rate, 0) WHEN 0 THEN 1.0 ELSE S.currency_rate END) * SOL.qty_invoiced
+ ELSE -AMOUNT_UNTAXED.expense_cost
+ END
+ ELSE 0.0
+ END AS expense_amount_untaxed_invoiced,
+ CASE
+ WHEN SOL.qty_delivered_method IN ('timesheet', 'manual') THEN (SOL.untaxed_amount_to_invoice / CASE COALESCE(S.currency_rate, 0) WHEN 0 THEN 1.0 ELSE S.currency_rate END)
+ ELSE 0.0
+ END AS amount_untaxed_to_invoice,
+ CASE
+ WHEN SOL.qty_delivered_method IN ('timesheet', 'manual') THEN (COALESCE(SOL.untaxed_amount_invoiced, AMOUNT_UNTAXED.downpayment_invoiced) / CASE COALESCE(S.currency_rate, 0) WHEN 0 THEN 1.0 ELSE S.currency_rate END)
+ ELSE 0.0
+ END AS amount_untaxed_invoiced,
+ S.date_order AS line_date
+ FROM project_project P
+ JOIN res_company C ON C.id = P.company_id
+ LEFT JOIN (
+ SELECT
+ P.id AS project_id,
+ P.analytic_account_id AS analytic_account_id,
+ AAL.so_line AS sale_line_id,
+ 0.0 AS expense_cost,
+ 0.0 AS downpayment_invoiced
+ FROM account_analytic_line AAL, project_project P
+ WHERE AAL.project_id IS NOT NULL AND P.id = AAL.project_id AND P.active = 't'
+ GROUP BY P.id, AAL.so_line
- UNION
+ UNION
- SELECT
- P.id AS project_id,
- P.analytic_account_id AS analytic_account_id,
- SOL.id AS sale_line_id,
- 0.0 AS timesheet_unit_amount,
- 0.0 AS timesheet_cost,
- 0.0 AS other_revenues,
- 0.0 AS expense_cost,
- 0.0 AS downpayment_invoiced
- FROM sale_order_line SOL
- INNER JOIN project_task T ON SOL.task_id = T.id
- INNER JOIN project_project P ON P.id = T.project_id
- WHERE P.active = 't' AND P.allow_timesheets = 't'
+ SELECT
+ P.id AS project_id,
+ P.analytic_account_id AS analytic_account_id,
+ AAL.so_line AS sale_line_id,
+ 0.0 AS expense_cost,
+ 0.0 AS downpayment_invoiced
+ FROM project_project P
+ LEFT JOIN account_analytic_account AA ON P.analytic_account_id = AA.id
+ LEFT JOIN account_analytic_line AAL ON AAL.account_id = AA.id
+ WHERE AAL.amount > 0.0 AND AAL.project_id IS NULL AND P.active = 't' AND P.allow_timesheets = 't'
+ GROUP BY P.id, AA.id, AAL.so_line
+ UNION
+ SELECT
+ P.id AS project_id,
+ P.analytic_account_id AS analytic_account_id,
+ AAL.so_line AS sale_line_id,
+ SUM(AAL.amount) AS expense_cost,
+ 0.0 AS downpayment_invoiced
+ FROM project_project P
+ LEFT JOIN account_analytic_account AA ON P.analytic_account_id = AA.id
+ LEFT JOIN account_analytic_line AAL ON AAL.account_id = AA.id
+ WHERE AAL.amount < 0.0 AND AAL.project_id IS NULL AND P.active = 't' AND P.allow_timesheets = 't'
+ GROUP BY P.id, AA.id, AAL.so_line
+ UNION
+ SELECT
+ P.id AS project_id,
+ P.analytic_account_id AS analytic_account_id,
+ MY_SOLS.id AS sale_line_id,
+ 0.0 AS expense_cost,
+ CASE WHEN MY_SOLS.invoice_status = 'invoiced' THEN MY_SOLS.price_reduce ELSE 0.0 END AS downpayment_invoiced
+ FROM project_project P
+ LEFT JOIN sale_order_line MY_SOL ON P.sale_line_id = MY_SOL.id
+ LEFT JOIN sale_order MY_S ON MY_SOL.order_id = MY_S.id
+ LEFT JOIN sale_order_line MY_SOLS ON MY_SOLS.order_id = MY_S.id
+ WHERE MY_SOLS.is_downpayment = 't'
+ GROUP BY P.id, MY_SOLS.id
+ UNION
+ SELECT
+ P.id AS project_id,
+ P.analytic_account_id AS analytic_account_id,
+ OLIS.id AS sale_line_id,
+ OLIS.price_reduce AS expense_cost,
+ 0.0 AS downpayment_invoiced
+ FROM project_project P
+ LEFT JOIN account_analytic_account ANAC ON P.analytic_account_id = ANAC.id
+ LEFT JOIN account_analytic_line ANLI ON ANAC.id = ANLI.account_id
+ LEFT JOIN sale_order_line OLI ON P.sale_line_id = OLI.id
+ LEFT JOIN sale_order ORD ON OLI.order_id = ORD.id
+ LEFT JOIN sale_order_line OLIS ON ORD.id = OLIS.order_id
+ WHERE OLIS.product_id = ANLI.product_id AND OLIS.is_downpayment = 't' AND ANLI.amount < 0.0 AND ANLI.project_id IS NULL AND P.active = 't' AND P.allow_timesheets = 't'
+ GROUP BY P.id, OLIS.id
+ UNION
+ SELECT
+ P.id AS project_id,
+ P.analytic_account_id AS analytic_account_id,
+ SOL.id AS sale_line_id,
+ 0.0 AS expense_cost,
+ 0.0 AS downpayment_invoiced
+ FROM sale_order_line SOL
+ INNER JOIN project_project P ON SOL.project_id = P.id
+ WHERE P.active = 't' AND P.allow_timesheets = 't'
+ UNION
+ SELECT
+ P.id AS project_id,
+ P.analytic_account_id AS analytic_account_id,
+ SOL.id AS sale_line_id,
+ 0.0 AS expense_cost,
+ 0.0 AS downpayment_invoiced
+ FROM sale_order_line SOL
+ INNER JOIN project_task T ON SOL.task_id = T.id
+ INNER JOIN project_project P ON P.id = T.project_id
+ WHERE P.active = 't' AND P.allow_timesheets = 't'
+ ) AMOUNT_UNTAXED ON AMOUNT_UNTAXED.project_id = P.id
+ LEFT JOIN sale_order_line SOL ON AMOUNT_UNTAXED.sale_line_id = SOL.id
+ LEFT JOIN sale_order S ON SOL.order_id = S.id
+ LEFT JOIN product_product PP on (SOL.product_id = PP.id)
+ LEFT JOIN product_template T on (PP.product_tmpl_id = T.id)
+ WHERE P.active = 't' AND P.analytic_account_id IS NOT NULL
) SUB_COST_SUMMARY
- GROUP BY project_id, analytic_account_id, sale_line_id
+ GROUP BY project_id, analytic_account_id, sale_line_id, line_date
) COST_SUMMARY ON COST_SUMMARY.project_id = P.id
LEFT JOIN sale_order_line SOL ON COST_SUMMARY.sale_line_id = SOL.id
LEFT JOIN sale_order S ON SOL.order_id = S.id
- LEFT JOIN product_product PP on (SOL.product_id=PP.id)
- LEFT JOIN product_template T on (PP.product_tmpl_id=T.id)
WHERE P.active = 't' AND P.analytic_account_id IS NOT NULL
) AS sub
)
diff --git a/addons/sale_timesheet/report/project_profitability_report_analysis_views.xml b/addons/sale_timesheet/report/project_profitability_report_analysis_views.xml
index 1f60f4d7944..2af77617453 100644
--- a/addons/sale_timesheet/report/project_profitability_report_analysis_views.xml
+++ b/addons/sale_timesheet/report/project_profitability_report_analysis_views.xml
@@ -45,6 +45,7 @@
+
diff --git a/addons/sale_timesheet/views/hr_timesheet_templates.xml b/addons/sale_timesheet/views/hr_timesheet_templates.xml
index 540ee5c7c27..c0437ab0a18 100644
--- a/addons/sale_timesheet/views/hr_timesheet_templates.xml
+++ b/addons/sale_timesheet/views/hr_timesheet_templates.xml
@@ -339,14 +339,14 @@
-
+
+ t-att-style="'display: none;' if row_type not in ('sale_order', 'sale_order_line') else ''">
|
-
+
|