From f27d5839f5565a1020e7e5a10c5604fe61e06daa Mon Sep 17 00:00:00 2001 From: Pawan Kumar Date: Fri, 18 Dec 2020 10:27:37 +0530 Subject: [PATCH] override project profitibility report --- cor_custom/__init__.py | 3 +- cor_custom/__manifest__.py | 1 + .../__pycache__/__init__.cpython-36.pyc | Bin 210 -> 239 bytes cor_custom/report/__init__.py | 4 + .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 214 bytes ...ofitability_report_analysis.cpython-36.pyc | Bin 0 -> 24835 bytes .../project_profitability_report_analysis.py | 360 ++++++++++++++++++ ...ct_profitability_report_analysis_views.xml | 76 ++++ 8 files changed, 443 insertions(+), 1 deletion(-) create mode 100755 cor_custom/report/__init__.py create mode 100644 cor_custom/report/__pycache__/__init__.cpython-36.pyc create mode 100644 cor_custom/report/__pycache__/project_profitability_report_analysis.cpython-36.pyc create mode 100755 cor_custom/report/project_profitability_report_analysis.py create mode 100755 cor_custom/report/project_profitability_report_analysis_views.xml diff --git a/cor_custom/__init__.py b/cor_custom/__init__.py index 511a0ca..8628669 100755 --- a/cor_custom/__init__.py +++ b/cor_custom/__init__.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- from . import controllers -from . import models \ No newline at end of file +from . import models +from . import report \ No newline at end of file diff --git a/cor_custom/__manifest__.py b/cor_custom/__manifest__.py index 1c81d5a..a118da9 100755 --- a/cor_custom/__manifest__.py +++ b/cor_custom/__manifest__.py @@ -30,6 +30,7 @@ 'views/project_view.xml', 'views/hr_timesheet_templates.xml', 'views/analytic_view.xml', + 'report/project_profitability_report_analysis_views.xml', 'views/views.xml', 'views/templates.xml', ], diff --git a/cor_custom/__pycache__/__init__.cpython-36.pyc b/cor_custom/__pycache__/__init__.cpython-36.pyc index a2ca7f5dad7e0aa4741977cd979df0d8af3279e3..638c9eeee6ca180eae2d5b074c1412ce15d39de7 100644 GIT binary patch delta 167 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 0.0 AND AAL.project_id IS NULL AND P.active = 't' AND P.allow_timesheets = 't' + + UNION ALL + + -- Get the expense costs from account analytic line + 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, + 0.0 AS other_revenues, + 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' + + UNION ALL + + -- Get the invoiced downpayments + SELECT + P.id AS project_id, + P.analytic_account_id AS analytic_account_id, + MY_SOLS.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, + 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' + + UNION ALL + + -- Get the expense costs from sale order line + SELECT + P.id AS project_id, + P.analytic_account_id AS analytic_account_id, + OLIS.id AS sale_line_id, + 0.0 AS timesheet_unit_amount, + 0.0 AS timesheet_cost, + 0.0 AS other_revenues, + OLIS.price_reduce 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, + 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 + 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' + + 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 + 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, + 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 + + 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, 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 + WHERE P.active = 't' AND P.analytic_account_id IS NOT NULL + ) AS sub + ) + """ % self._table + self._cr.execute(query) diff --git a/cor_custom/report/project_profitability_report_analysis_views.xml b/cor_custom/report/project_profitability_report_analysis_views.xml new file mode 100755 index 0000000..5cbab96 --- /dev/null +++ b/cor_custom/report/project_profitability_report_analysis_views.xml @@ -0,0 +1,76 @@ + + + + + project.profitability.report.pivot + project.profitability.report + + + + + + + + + + + + + project.profitability.report.graph + project.profitability.report + + + + + + + + + + + + + + + + project.profitability.report.search + project.profitability.report + + + + + + + + + + + + + + + + + + + + + Project Costs and Revenues + project.profitability.report + pivot,graph + + { + 'group_by_no_leaf':1, + 'group_by':[], + 'sale_show_order_product_name': 1, + } + This report allows you to analyse the profitability of your projects: compare the amount to invoice, the ones already invoiced and the project cost (via timesheet cost of your employees). + + + + +