Skip to content

Commit 0be918f

Browse files
authored
Merge pull request #3780 from bcgov/release-v1.2.4
Release v1.2.4
2 parents 4b2bf93 + 83fd90a commit 0be918f

File tree

78 files changed

+2468
-1774
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+2468
-1774
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Push Images to Artifactory
2+
3+
on:
4+
workflow_dispatch:
5+
6+
env:
7+
ARTIFACTORY_REGISTRY: ${{ secrets.ARTIFACTORY_REGISTRY }}
8+
ARTIFACTORY_REPO: ${{ secrets.ARTIFACTORY_REPO }}
9+
ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
10+
ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
11+
METABASE_IMAGE_TAG: v0.52.6.x
12+
13+
jobs:
14+
push-metabase-to-artifactory:
15+
name: Push Metabase image to Artifactory
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Install skopeo
19+
run: |
20+
sudo apt-get update
21+
sudo apt-get install -y skopeo
22+
23+
- name: Login to Artifactory
24+
run: |
25+
set -euo pipefail
26+
skopeo login --authfile /tmp/artifactory-auth.json \
27+
--username "${ARTIFACTORY_USERNAME}" \
28+
--password "${ARTIFACTORY_PASSWORD}" \
29+
"${ARTIFACTORY_REGISTRY}"
30+
31+
- name: Copy Metabase image from Docker Hub
32+
run: |
33+
set -euo pipefail
34+
skopeo copy --src-tls-verify=true --dest-tls-verify=true \
35+
--dest-authfile /tmp/artifactory-auth.json \
36+
"docker://metabase/metabase:${METABASE_IMAGE_TAG}" \
37+
"docker://${ARTIFACTORY_REGISTRY}/${ARTIFACTORY_REPO}/lcfs/prod/metabase:${METABASE_IMAGE_TAG}"

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Generated geocoding output files
2+
org_snapshot_coordinates.sql
3+
14
### Python template
25

36
.idea/
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""Add latitude and longitude to organization snapshot for fuel supply mapping
2+
3+
Revision ID: a1b2c3d4e5f8
4+
Revises: 5897848af3c9
5+
Create Date: 2025-01-05 12:00:00.000000
6+
7+
This migration adds latitude/longitude columns to compliance_report_organization_snapshot
8+
for the Fuel Supply Map feature in Metabase.
9+
10+
To populate existing records with coordinates:
11+
1. Run: poetry run python -m lcfs.scripts.geocode_org_snapshots
12+
2. Execute the generated org_snapshot_coordinates.sql against the database
13+
"""
14+
15+
import sqlalchemy as sa
16+
from alembic import op
17+
18+
# revision identifiers, used by Alembic.
19+
revision = "a1b2c3d4e5f8"
20+
down_revision = "5897848af3c9"
21+
branch_labels = None
22+
depends_on = None
23+
24+
25+
def upgrade() -> None:
26+
# Add latitude column for mapping organization locations
27+
op.add_column(
28+
"compliance_report_organization_snapshot",
29+
sa.Column(
30+
"latitude",
31+
sa.Float(),
32+
nullable=True,
33+
comment="Latitude coordinate for mapping (from records_address, service_address, or head_office_address)",
34+
),
35+
)
36+
# Add longitude column for mapping organization locations
37+
op.add_column(
38+
"compliance_report_organization_snapshot",
39+
sa.Column(
40+
"longitude",
41+
sa.Float(),
42+
nullable=True,
43+
comment="Longitude coordinate for mapping (from records_address, service_address, or head_office_address)",
44+
),
45+
)
46+
47+
48+
def downgrade() -> None:
49+
op.drop_column("compliance_report_organization_snapshot", "longitude")
50+
op.drop_column("compliance_report_organization_snapshot", "latitude")
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
"""Fix Energy density for fuel types
2+
3+
Revision ID: 46948662543b
4+
Revises: a1b2c3d4e5f8
5+
Create Date: 2026-01-15 06:40:38.311142
6+
7+
"""
8+
9+
import sqlalchemy as sa
10+
from alembic import op
11+
12+
# revision identifiers, used by Alembic.
13+
revision = "46948662543b"
14+
down_revision = "a1b2c3d4e5f8"
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade() -> None:
20+
# CNG
21+
op.execute(
22+
"""
23+
UPDATE energy_density
24+
SET density = 38.27
25+
WHERE fuel_type_id = 2 and compliance_period_id > 15
26+
"""
27+
)
28+
# HDRD
29+
op.execute(
30+
"""
31+
UPDATE energy_density
32+
SET density = 37.89
33+
WHERE fuel_type_id = 5 and compliance_period_id > 15
34+
"""
35+
)
36+
# Hydrogen
37+
op.execute(
38+
"""
39+
UPDATE energy_density
40+
SET density = 141.76
41+
WHERE fuel_type_id = 6 and compliance_period_id > 15
42+
"""
43+
)
44+
# LNG
45+
op.execute(
46+
"""
47+
UPDATE energy_density
48+
SET density = 53.54
49+
WHERE fuel_type_id = 7 and compliance_period_id > 15
50+
"""
51+
)
52+
# Alternative Jet Fuel
53+
op.execute(
54+
"""
55+
INSERT INTO energy_density (fuel_type_id, compliance_period_id, uom_id, density)
56+
VALUES (11, 16, 1, 36), (11, 17, 1, 36), (11, 18, 1, 36), (11, 19, 1, 36), (11, 20, 1, 36), (11, 21, 1, 36)
57+
"""
58+
)
59+
# Propane
60+
op.execute(
61+
"""
62+
UPDATE energy_density
63+
SET density = 25.62
64+
WHERE fuel_type_id = 13 and compliance_period_id > 15
65+
"""
66+
)
67+
# Renewable gasoline
68+
op.execute(
69+
"""
70+
INSERT INTO energy_density (fuel_type_id, compliance_period_id, uom_id, density)
71+
VALUES (14, 16, 1, 34.69), (14, 17, 1, 34.69), (14, 18, 1, 34.69), (14, 19, 1, 34.69), (14, 20, 1, 34.69), (14, 21, 1, 34.69)
72+
"""
73+
)
74+
# Renewable naptha
75+
op.execute(
76+
"""
77+
INSERT INTO energy_density (fuel_type_id, compliance_period_id, uom_id, density)
78+
VALUES (15, 16, 1, 34.51), (15, 17, 1, 34.51), (15, 18, 1, 34.51), (15, 19, 1, 34.51), (15, 20, 1, 34.51), (15, 21, 1, 34.51)
79+
"""
80+
)
81+
# Fossil derived jet fuel
82+
op.execute(
83+
"""
84+
INSERT INTO energy_density (fuel_type_id, compliance_period_id, uom_id, density)
85+
VALUES (18, 16, 1, 37.40), (18, 17, 1, 37.40), (18, 18, 1, 37.40), (18, 19, 1, 37.40), (18, 20, 1, 37.40), (18, 21, 1, 37.40)
86+
"""
87+
)
88+
# Other diesel
89+
op.execute(
90+
"""
91+
INSERT INTO energy_density (fuel_type_id, compliance_period_id, uom_id, density)
92+
VALUES (20, 16, 1, 36.51), (20, 17, 1, 36.51), (20, 18, 1, 36.51), (20, 19, 1, 36.51), (20, 20, 1, 36.51), (20, 21, 1, 36.51)
93+
"""
94+
)
95+
# Natural gas-based gasoline
96+
op.execute(
97+
"""
98+
INSERT INTO energy_density (fuel_type_id, compliance_period_id, uom_id, density)
99+
VALUES (21, 16, 1, 34.69), (21, 17, 1, 34.69), (21, 18, 1, 34.69), (21, 19, 1, 34.69), (21, 20, 1, 34.69), (21, 21, 1, 34.69)
100+
"""
101+
)
102+
103+
104+
def downgrade() -> None:
105+
pass

backend/lcfs/db/models/compliance/ComplianceReportOrganizationSnapshot.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from sqlalchemy import Column, Integer, String, ForeignKey, Boolean
1+
from sqlalchemy import Column, Integer, String, ForeignKey, Boolean, Float
22
from sqlalchemy.orm import relationship
33

44
from lcfs.db.base import BaseModel, Auditable
@@ -36,6 +36,12 @@ class ComplianceReportOrganizationSnapshot(BaseModel, Auditable):
3636
records_address = Column(
3737
String(500), nullable=True, comment="Organization's address in BC where records are maintained."
3838
)
39+
latitude = Column(
40+
Float, nullable=True, comment="Latitude coordinate for mapping (priority: records_address > service_address > head_office_address)"
41+
)
42+
longitude = Column(
43+
Float, nullable=True, comment="Longitude coordinate for mapping (priority: records_address > service_address > head_office_address)"
44+
)
3945

4046
is_edited = Column(
4147
Boolean,

backend/lcfs/db/sql/views/metabase.sql

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1874,6 +1874,98 @@ ORDER BY
18741874
vf.fuel_category,
18751875
vf.version_rank;
18761876
GRANT SELECT ON vw_compliance_report_fuel_volume_history, vw_compliance_report_fuel_volume_visualisation TO basic_lcfs_reporting_role;
1877+
1878+
-- ==========================================
1879+
-- Fuel Supply Map View
1880+
-- ==========================================
1881+
-- Provides location data for fuel suppliers based on organization snapshot
1882+
-- Combines fuel supply data with organization lat/long for Metabase mapping
1883+
DROP VIEW IF EXISTS vw_fuel_supply_map CASCADE;
1884+
CREATE OR REPLACE VIEW vw_fuel_supply_map AS
1885+
WITH
1886+
latest_fs AS (
1887+
SELECT
1888+
fs.group_uuid,
1889+
MAX(fs.version) AS max_version
1890+
FROM fuel_supply fs
1891+
WHERE action_type <> 'DELETE'
1892+
GROUP BY fs.group_uuid
1893+
),
1894+
selected_fs AS (
1895+
SELECT fs.*
1896+
FROM fuel_supply fs
1897+
JOIN latest_fs lfs ON fs.group_uuid = lfs.group_uuid AND fs.version = lfs.max_version
1898+
WHERE fs.action_type != 'DELETE'
1899+
),
1900+
fuel_supply_aggregated AS (
1901+
SELECT
1902+
cr.compliance_report_id,
1903+
cr.compliance_report_group_uuid,
1904+
cr.compliance_period_id,
1905+
cr.organization_id,
1906+
fs.fuel_type_id,
1907+
fs.fuel_category_id,
1908+
SUM(
1909+
CASE
1910+
WHEN fs.quantity > 0 THEN fs.quantity
1911+
ELSE COALESCE(fs.q1_quantity, 0) + COALESCE(fs.q2_quantity, 0) +
1912+
COALESCE(fs.q3_quantity, 0) + COALESCE(fs.q4_quantity, 0)
1913+
END
1914+
) AS total_quantity,
1915+
SUM(COALESCE(fs.compliance_units, 0)) AS total_compliance_units,
1916+
fs.units AS quantity_units
1917+
FROM selected_fs fs
1918+
JOIN compliance_report cr ON fs.compliance_report_id = cr.compliance_report_id
1919+
JOIN compliance_report_status crs ON cr.current_status_id = crs.compliance_report_status_id
1920+
WHERE crs.status NOT IN ('Draft'::compliancereportstatusenum)
1921+
GROUP BY
1922+
cr.compliance_report_id,
1923+
cr.compliance_report_group_uuid,
1924+
cr.compliance_period_id,
1925+
cr.organization_id,
1926+
fs.fuel_type_id,
1927+
fs.fuel_category_id,
1928+
fs.units
1929+
)
1930+
SELECT DISTINCT
1931+
fsa.compliance_report_group_uuid,
1932+
fsa.compliance_report_id,
1933+
cp.description AS compliance_period,
1934+
org.organization_id,
1935+
org.name AS organization_name,
1936+
-- Organization snapshot location data (priority: records > service > head_office)
1937+
COALESCE(os.records_address, os.service_address, os.head_office_address) AS primary_address,
1938+
os.records_address,
1939+
os.service_address,
1940+
os.head_office_address,
1941+
os.latitude,
1942+
os.longitude,
1943+
-- Fuel details
1944+
ft.fuel_type,
1945+
fc.category AS fuel_category,
1946+
fsa.total_quantity,
1947+
fsa.quantity_units,
1948+
fsa.total_compliance_units,
1949+
-- Report status
1950+
crs.status::text AS report_status
1951+
FROM fuel_supply_aggregated fsa
1952+
JOIN compliance_report cr ON fsa.compliance_report_id = cr.compliance_report_id
1953+
JOIN compliance_period cp ON fsa.compliance_period_id = cp.compliance_period_id
1954+
JOIN organization org ON fsa.organization_id = org.organization_id
1955+
JOIN compliance_report_status crs ON cr.current_status_id = crs.compliance_report_status_id
1956+
LEFT JOIN compliance_report_organization_snapshot os ON cr.compliance_report_id = os.compliance_report_id
1957+
LEFT JOIN fuel_type ft ON fsa.fuel_type_id = ft.fuel_type_id
1958+
LEFT JOIN fuel_category fc ON fsa.fuel_category_id = fc.fuel_category_id
1959+
-- Only include reports that have been submitted (exclude drafts)
1960+
WHERE crs.status NOT IN ('Draft'::compliancereportstatusenum)
1961+
ORDER BY
1962+
cp.description DESC,
1963+
org.name,
1964+
ft.fuel_type,
1965+
fc.category;
1966+
1967+
GRANT SELECT ON vw_fuel_supply_map TO basic_lcfs_reporting_role;
1968+
18771969
-- ==========================================
18781970
-- Additional permissions for base tables
18791971
-- ==========================================

0 commit comments

Comments
 (0)