Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[14.0][FIX] fleet_vehicle_log_fuel: Don't replace whole SQL view + make it work + renaming (backport) #139

Merged
merged 1 commit into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion fleet_vehicle_log_fuel/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from . import fleet_vehicle_cost, fleet_vehicle
from . import fleet_vehicle_log_fuel
from . import fleet_vehicle
226 changes: 64 additions & 162 deletions fleet_vehicle_log_fuel/report/fleet_report.py
Original file line number Diff line number Diff line change
@@ -1,177 +1,79 @@
# Copyright 2022 ForgeFlow S.L. <https://www.forgeflow.com>
# 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
Loading