Skip to content
Open
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
1 change: 1 addition & 0 deletions documentation/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ v1.1.0 | September XX, 2026
New features
-------------

* Hover over an organisation's plan on its page to see its effective API rate limits and trigger rate-limit scope [see `PR #2524 <https://www.github.com/FlexMeasures/flexmeasures/pull/2524>`_]
* Automations: recurring tasks defined per asset, computing forecasts or schedules, managed with new CLI commands (``flexmeasures add|edit|delete automation``), run by ``flexmeasures jobs run-automations``, and viewable in a new UI page and API endpoints (``[GET] /assets/(id)/automations``); each automation interprets its recurrence in its own timezone, and runs missed while the runner was down are caught up once, coalesced into one current forecast; a forecast automation points at a data source holding its forecaster configuration, while a schedule automation stores what the schedule trigger endpoint accepts, and schedules from each run's own time, unless the trigger message fixes a ``start``; an automation's details link to the sensors it reads from and writes to, a sensor's page lists the automations feeding it, and deleting a sensor warns about the automations that use it; jobs now also record whether they were created via the CLI, the API or an automation [see `PR #2290 <https://www.github.com/FlexMeasures/flexmeasures/pull/2290>`_, `PR #2396 <https://www.github.com/FlexMeasures/flexmeasures/pull/2396>`_ and `PR #2293 <https://www.github.com/FlexMeasures/flexmeasures/pull/2293>`_]
* A scheduler's data source now also records the flex config the scheduler computed under, so a schedule can be traced back to the configuration that produced it, and a schedule automation points at such a data source, the way a forecast automation points at its forecaster's [see `PR #2444 <https://www.github.com/FlexMeasures/flexmeasures/pull/2444>`_]
* In the UI, the full record of the data source selected on a sensor page can be inspected, backed by a new API endpoint (``[GET] /sources/(id)``) [see `PR #2290 <https://www.github.com/FlexMeasures/flexmeasures/pull/2290>`_]
Expand Down
15 changes: 12 additions & 3 deletions flexmeasures/ui/templates/accounts/account.html
Original file line number Diff line number Diff line change
Expand Up @@ -305,9 +305,18 @@ <h3>Account</h3>
<tr>
<td>Plan</td>
<td>
{% if account.plan %} {{ account.plan.name }}{% if
account.plan.legacy %} (legacy){% endif %} {% else %} No
plan (server defaults apply) {% endif %}
<span
rel="tooltip"
data-bs-toggle="tooltip"
data-bs-placement="right"
data-bs-html="true"
tabindex="0"
title="Default API rate limit: {{ effective_default_rate_limit }}<br>Trigger rate limit: {{ effective_trigger_rate_limit }}<br>Trigger rate-limit scope: {{ effective_rate_limit_key }}"
>
{% if account.plan %}{{ account.plan.name }}{% if
account.plan.legacy %} (legacy){% endif %}{% else %}No
plan (server defaults apply){% endif %}
</span>
</td>
</tr>
<tr>
Expand Down
21 changes: 20 additions & 1 deletion flexmeasures/ui/views/accounts.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from flask import request
from flask import current_app, request
from sqlalchemy import or_, select
from werkzeug.exceptions import Forbidden, Unauthorized, NotFound
from flask_classful import FlaskView, route
Expand Down Expand Up @@ -142,6 +142,22 @@ def get(self, account_id: str):
role.name: role.id for role in db.session.scalars(select(AccountRole)).all()
}
selected_account_roles = [role.name for role in account.account_roles]
plan = account.plan
effective_default_rate_limit = (
plan.default_rate_limit
if plan is not None and plan.default_rate_limit is not None
else current_app.config["FLEXMEASURES_API_DEFAULT_RATE_LIMIT"]
)
effective_trigger_rate_limit = (
plan.trigger_rate_limit
if plan is not None and plan.trigger_rate_limit is not None
else current_app.config["FLEXMEASURES_API_TRIGGER_RATE_LIMIT"]
)
effective_rate_limit_key = (
plan.rate_limit_key.value
if plan is not None and plan.rate_limit_key is not None
else current_app.config["FLEXMEASURES_API_RATE_LIMIT_KEY"]
)

return render_flexmeasures_template(
"accounts/account.html",
Expand All @@ -152,6 +168,9 @@ def get(self, account_id: str):
can_add_client_account=can_add_client_account,
account_role_options=account_role_options,
selected_account_roles=selected_account_roles,
effective_default_rate_limit=effective_default_rate_limit,
effective_trigger_rate_limit=effective_trigger_rate_limit,
effective_rate_limit_key=effective_rate_limit_key,
user_can_update_account=user_can_update_account,
user_can_create_children=user_can_create_children,
can_view_account_auditlog=user_can_view_account_auditlog,
Expand Down
Loading