Add tariff_dkk + total_dkk to elprice
Each hourly row now carries the N1 time-of-use tariff (øre/kWh × 10 to match the DKK/MWh unit of price_dkk) and the combined consumer price (spot + tariff). Existing rows are backfilled in the migration with a CASE expression mirroring tariffs/tariff-for-hour; new writes compute it in the controller. API response exposes both fields. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE elprice DROP COLUMN total_dkk;
|
||||||
|
--;;
|
||||||
|
ALTER TABLE elprice DROP COLUMN tariff_dkk;
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
ALTER TABLE elprice ADD COLUMN tariff_dkk NUMERIC(10,2);
|
||||||
|
--;;
|
||||||
|
ALTER TABLE elprice ADD COLUMN total_dkk NUMERIC(10,2);
|
||||||
|
--;;
|
||||||
|
UPDATE elprice
|
||||||
|
SET tariff_dkk = CASE
|
||||||
|
WHEN EXTRACT(MONTH FROM time_dk) BETWEEN 4 AND 9 THEN
|
||||||
|
CASE
|
||||||
|
WHEN EXTRACT(HOUR FROM time_dk) < 6 THEN 109.80
|
||||||
|
WHEN EXTRACT(HOUR FROM time_dk) >= 17 AND EXTRACT(HOUR FROM time_dk) < 21 THEN 428.30
|
||||||
|
ELSE 164.70
|
||||||
|
END
|
||||||
|
ELSE
|
||||||
|
CASE
|
||||||
|
WHEN EXTRACT(HOUR FROM time_dk) < 6 THEN 109.80
|
||||||
|
WHEN EXTRACT(HOUR FROM time_dk) >= 17 AND EXTRACT(HOUR FROM time_dk) < 21 THEN 988.40
|
||||||
|
ELSE 329.50
|
||||||
|
END
|
||||||
|
END;
|
||||||
|
--;;
|
||||||
|
UPDATE elprice SET total_dkk = price_dkk + tariff_dkk WHERE tariff_dkk IS NOT NULL;
|
||||||
@@ -67,14 +67,16 @@ VALUES (:time-start, :hour, :kwh)
|
|||||||
ON CONFLICT (time_start, hour) DO NOTHING;
|
ON CONFLICT (time_start, hour) DO NOTHING;
|
||||||
|
|
||||||
-- :name insert-elprice! :! :n
|
-- :name insert-elprice! :! :n
|
||||||
-- :doc Insert an hourly el-price row; keep first value on conflict
|
-- :doc Upsert an hourly el-price row; refresh tariff/total on conflict
|
||||||
INSERT INTO elprice (time_dk, price_area, price_dkk)
|
INSERT INTO elprice (time_dk, price_area, price_dkk, tariff_dkk, total_dkk)
|
||||||
VALUES (:time-dk, :price-area, :price-dkk)
|
VALUES (:time-dk, :price-area, :price-dkk, :tariff-dkk, :total-dkk)
|
||||||
ON CONFLICT (time_dk, price_area) DO NOTHING;
|
ON CONFLICT (time_dk, price_area) DO UPDATE SET
|
||||||
|
tariff_dkk = EXCLUDED.tariff_dkk,
|
||||||
|
total_dkk = EXCLUDED.total_dkk;
|
||||||
|
|
||||||
-- :name get-elprice-for-date :? :*
|
-- :name get-elprice-for-date :? :*
|
||||||
-- :doc Hourly prices for a DK local date, both areas
|
-- :doc Hourly prices for a DK local date, both areas
|
||||||
SELECT time_dk, price_area, price_dkk
|
SELECT time_dk, price_area, price_dkk, tariff_dkk, total_dkk
|
||||||
FROM elprice
|
FROM elprice
|
||||||
WHERE time_dk::date = :date
|
WHERE time_dk::date = :date
|
||||||
ORDER BY time_dk, price_area;
|
ORDER BY time_dk, price_area;
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
(ns pmagnus.elprice.web.controllers.elprice
|
(ns pmagnus.elprice.web.controllers.elprice
|
||||||
(:require
|
(:require
|
||||||
[clojure.data.json :as json]
|
[clojure.data.json :as json]
|
||||||
[clojure.tools.logging :as log])
|
[clojure.tools.logging :as log]
|
||||||
|
[pmagnus.elprice.web.controllers.tariffs :as tariffs])
|
||||||
(:import
|
(:import
|
||||||
(java.net
|
(java.net
|
||||||
URI
|
URI
|
||||||
@@ -14,6 +15,7 @@
|
|||||||
Timestamp)
|
Timestamp)
|
||||||
(java.time
|
(java.time
|
||||||
LocalDate
|
LocalDate
|
||||||
|
LocalDateTime
|
||||||
ZoneId)
|
ZoneId)
|
||||||
(java.time.format
|
(java.time.format
|
||||||
DateTimeFormatter)))
|
DateTimeFormatter)))
|
||||||
@@ -68,14 +70,25 @@
|
|||||||
(:records (fetch-json url))))
|
(:records (fetch-json url))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn- tariff-dkk-mwh
|
||||||
|
"N1 time-of-use tariff converted from øre/kWh to DKK/MWh (×10)."
|
||||||
|
[^LocalDateTime dt]
|
||||||
|
(* 10.0 (tariffs/tariff-for-hour (.getMonthValue dt) (.getHour dt))))
|
||||||
|
|
||||||
|
|
||||||
(defn- save-records!
|
(defn- save-records!
|
||||||
[query-fn records]
|
[query-fn records]
|
||||||
(doseq [rec records]
|
(doseq [rec records]
|
||||||
(when-let [dkk (dkk-price (:DayAheadPriceDKK rec) (:DayAheadPriceEUR rec))]
|
(when-let [dkk (dkk-price (:DayAheadPriceDKK rec) (:DayAheadPriceEUR rec))]
|
||||||
(query-fn :insert-elprice!
|
(let [ts (parse-timestamp (:TimeDK rec))
|
||||||
{:time-dk (parse-timestamp (:TimeDK rec))
|
tariff (tariff-dkk-mwh (.toLocalDateTime ^Timestamp ts))
|
||||||
:price-area (:PriceArea rec)
|
total (+ (double dkk) tariff)]
|
||||||
:price-dkk dkk}))))
|
(query-fn :insert-elprice!
|
||||||
|
{:time-dk ts
|
||||||
|
:price-area (:PriceArea rec)
|
||||||
|
:price-dkk dkk
|
||||||
|
:tariff-dkk tariff
|
||||||
|
:total-dkk total})))))
|
||||||
|
|
||||||
|
|
||||||
(defn get-or-fetch!
|
(defn get-or-fetch!
|
||||||
|
|||||||
@@ -49,7 +49,9 @@
|
|||||||
{:date date
|
{:date date
|
||||||
:prices (mapv (fn [r] {:time_dk (str (:time_dk r))
|
:prices (mapv (fn [r] {:time_dk (str (:time_dk r))
|
||||||
:price_area (:price_area r)
|
:price_area (:price_area r)
|
||||||
:price_dkk (:price_dkk r)})
|
:price_dkk (:price_dkk r)
|
||||||
|
:tariff_dkk (:tariff_dkk r)
|
||||||
|
:total_dkk (:total_dkk r)})
|
||||||
rows)}))
|
rows)}))
|
||||||
(catch DateTimeParseException _
|
(catch DateTimeParseException _
|
||||||
(http-response/bad-request {:error "date must be YYYY-MM-DD"}))))
|
(http-response/bad-request {:error "date must be YYYY-MM-DD"}))))
|
||||||
|
|||||||
Reference in New Issue
Block a user