diff --git a/fleet_vehicle_log_fuel/models/__init__.py b/fleet_vehicle_log_fuel/models/__init__.py index a21fd93b..ce6bad7e 100644 --- a/fleet_vehicle_log_fuel/models/__init__.py +++ b/fleet_vehicle_log_fuel/models/__init__.py @@ -1 +1,2 @@ -from . import fleet_vehicle_cost, fleet_vehicle +from . import fleet_vehicle_log_fuel +from . import fleet_vehicle diff --git a/fleet_vehicle_log_fuel/models/fleet_vehicle_cost.py b/fleet_vehicle_log_fuel/models/fleet_vehicle_log_fuel.py similarity index 100% rename from fleet_vehicle_log_fuel/models/fleet_vehicle_cost.py rename to fleet_vehicle_log_fuel/models/fleet_vehicle_log_fuel.py diff --git a/fleet_vehicle_log_fuel/report/fleet_report.py b/fleet_vehicle_log_fuel/report/fleet_report.py index 46e9d394..96d25e1a 100644 --- a/fleet_vehicle_log_fuel/report/fleet_report.py +++ b/fleet_vehicle_log_fuel/report/fleet_report.py @@ -1,177 +1,79 @@ # Copyright 2022 ForgeFlow S.L. +# Copyright 2024 Tecnativa - Pedro M. Baeza # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from psycopg2 import sql -from odoo import models, tools +from odoo import fields, models, tools class FleetReport(models.Model): _inherit = "fleet.vehicle.cost.report" + cost_type = fields.Selection(selection_add=[("fuel", "Fuel")]) + def init(self): - query = """ -WITH service_costs AS ( - SELECT - ve.id AS vehicle_id, - ve.company_id AS company_id, - ve.name AS name, - ve.driver_id AS driver_id, - ve.fuel_type AS fuel_type, - date(date_trunc('month', d)) AS date_start, - COALESCE(sum(se.amount), 0) AS - COST, - 'service' AS cost_type - FROM - fleet_vehicle ve - CROSS JOIN generate_series( - ( - SELECT min(date) - FROM fleet_vehicle_log_services), - CURRENT_DATE + '1 month'::interval, '1 month') d - LEFT JOIN fleet_vehicle_log_services se ON se.vehicle_id = ve.id - AND date_trunc('month', se.date) = date_trunc('month', d) - WHERE - ve.active AND se.active AND se.state != 'cancelled' - GROUP BY - ve.id, - ve.company_id, - ve.name, - date_start, - d - ORDER BY - ve.id, - date_start -), -fuel_costs AS ( - SELECT - ve.id AS vehicle_id, - ve.company_id AS company_id, - ve.name AS name, - ve.driver_id AS driver_id, - ve.fuel_type AS fuel_type, - date(date_trunc('month', d)) AS date_start, - COALESCE(sum(se.amount), 0) AS - COST, - 'fuel' AS cost_type - FROM - fleet_vehicle ve - CROSS JOIN generate_series( - ( - SELECT min(date) - FROM fleet_vehicle_log_fuel), - CURRENT_DATE + '1 month'::interval, '1 month') d - LEFT JOIN fleet_vehicle_log_fuel se ON se.vehicle_id = ve.id - AND date_trunc('month', se.date) = date_trunc('month', d) - WHERE - ve.active AND se.active AND se.state != 'cancelled' - GROUP BY - ve.id, - ve.company_id, - ve.name, - date_start, - d - ORDER BY - ve.id, - date_start -), -contract_costs AS ( - SELECT - ve.id AS vehicle_id, - ve.company_id AS company_id, - ve.name AS name, - ve.driver_id AS driver_id, - ve.fuel_type AS fuel_type, - date(date_trunc('month', d)) AS date_start, - ( - COALESCE( - sum(co.amount), 0 - ) + COALESCE( - sum(cod.cost_generated * extract(day FROM - least (date_trunc('month', d) + interval '1 month', cod.expiration_date - ) - greatest (date_trunc('month', d), cod.start_date) - )), 0 - ) + COALESCE( - sum(com.cost_generated), 0 - ) + COALESCE( - sum(coy.cost_generated), 0 - ) - ) AS COST, - 'contract' AS cost_type - FROM - fleet_vehicle ve - CROSS JOIN generate_series(( - SELECT - min(acquisition_date) - FROM fleet_vehicle), CURRENT_DATE + '1 month'::interval, '1 month') d - LEFT JOIN fleet_vehicle_log_contract co ON co.vehicle_id = ve.id - AND date_trunc('month', co.date) = date_trunc('month', d) - LEFT JOIN fleet_vehicle_log_contract cod ON cod.vehicle_id = ve.id - AND date_trunc('month', cod.start_date) <= date_trunc('month', d) - AND date_trunc('month', cod.expiration_date) >= date_trunc('month', d) - AND cod.cost_frequency = 'daily' - LEFT JOIN fleet_vehicle_log_contract com ON com.vehicle_id = ve.id - AND date_trunc('month', com.start_date) <= date_trunc('month', d) - AND date_trunc('month', com.expiration_date) >= date_trunc('month', d) - AND com.cost_frequency = 'monthly' - LEFT JOIN fleet_vehicle_log_contract coy ON coy.vehicle_id = ve.id - AND date_trunc('month', coy.date) = date_trunc('month', d) - AND date_trunc('month', coy.start_date) <= date_trunc('month', d) - AND date_trunc('month', coy.expiration_date) >= date_trunc('month', d) - AND coy.cost_frequency = 'yearly' -WHERE - ve.active -GROUP BY - ve.id, - ve.company_id, - ve.name, - date_start, - d -ORDER BY - ve.id, - date_start -) -SELECT - vehicle_id AS id, - company_id, - vehicle_id, - name, - driver_id, - fuel_type, - date_start, - COST, - 'service' as cost_type -FROM - service_costs sc -UNION ALL ( - SELECT - vehicle_id AS id, - company_id, - vehicle_id, - name, - driver_id, - fuel_type, - date_start, - COST, - 'fuel' as cost_type - FROM - fuel_costs cc) -UNION ALL ( - SELECT - vehicle_id AS id, - company_id, - vehicle_id, - name, - driver_id, - fuel_type, - date_start, - COST, - 'contract' as cost_type - FROM - contract_costs cc) -""" + """Inject parts in the query with this hack, fetching the query and + recreating it. Query is returned all in upper case and with final ';'. + """ + super().init() + self.env.cr.execute(f"SELECT pg_get_viewdef('{self._table}', true)") + view_def = self.env.cr.fetchone()[0] + if view_def[-1] == ";": # Remove trailing semicolon + view_def = view_def[:-1] + # Subquery + view_def = view_def.replace( + "contract_costs AS (", + """ + fuel_costs AS ( + SELECT + ve.id AS vehicle_id, + ve.company_id AS company_id, + ve.name AS name, + ve.driver_id AS driver_id, + ve.fuel_type AS fuel_type, + date(date_trunc('month', d)) AS date_start, + COALESCE(sum(fvlf.amount), 0) AS COST, + 'fuel' AS cost_type + FROM + fleet_vehicle ve + CROSS JOIN generate_series( + ( + SELECT min(date) + FROM fleet_vehicle_log_fuel), + CURRENT_DATE + '1 month'::interval, '1 month') d + LEFT JOIN fleet_vehicle_log_fuel fvlf ON fvlf.vehicle_id = ve.id + AND date_trunc('month', fvlf.date) = date_trunc('month', d) + WHERE + ve.active AND fvlf.active AND fvlf.state <> 'cancelled' + GROUP BY ve.id, ve.company_id, ve.name, date_start, d + ORDER BY ve.id, date_start + ), + contract_costs AS (""", + ) + # Union + view_def = view_def.replace( + "UNION ALL", + """ + UNION ALL + SELECT + fc.vehicle_id AS id, + fc.company_id, + fc.vehicle_id, + fc.name, + fc.driver_id, + fc.fuel_type, + fc.date_start, + fc.COST, + 'fuel' as cost_type + FROM + fuel_costs fc + UNION ALL""", + ) + # Re-create view tools.drop_view_if_exists(self.env.cr, self._table) self.env.cr.execute( sql.SQL("""CREATE or REPLACE VIEW {} as ({})""").format( - sql.Identifier(self._table), sql.SQL(query) + sql.Identifier(self._table), sql.SQL(view_def) ) ) + return True