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

feat: search filter on sensor API #1191

Merged
merged 30 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4dc4e04
feat: search filter on sensor API
joshuaunity Sep 20, 2024
4ab4263
Merge branch 'main' into feat-sensors-filters
joshuaunity Sep 24, 2024
92c58a0
feat: sensor API pagintion and search
joshuaunity Sep 24, 2024
658b525
refactor: reduce code repitition and code size
joshuaunity Sep 24, 2024
2114eca
refactor: request changes
joshuaunity Sep 25, 2024
1930365
feat: api to fetch all sensors under an asset
joshuaunity Sep 25, 2024
ecd3966
feat: added filter feature for sensor table, both name and unit filte…
joshuaunity Sep 25, 2024
2a37dde
feat: unit filter features on get sensors API
joshuaunity Sep 25, 2024
f8ebe9b
refactor: asset sensor and sensors API changes
joshuaunity Sep 25, 2024
5d9b547
feat: test case for asset_sensors API
joshuaunity Sep 25, 2024
e93b1fb
chore: few changes variable namings and import arrangement
joshuaunity Sep 26, 2024
d80f1ba
refactor: updated testcase with more checks and removed redundant code
joshuaunity Sep 26, 2024
461f1d2
chore: little changes on test(waiting for comment resolution)
joshuaunity Sep 26, 2024
dc3e8df
chore: moved formatResolution func to base.html
joshuaunity Sep 27, 2024
807f0d0
refactor: changes to asset sensors API and ISO formatter logic on for…
joshuaunity Sep 27, 2024
e92a8dd
chore: removed hard coded asset ID in asset sensors test case
joshuaunity Sep 27, 2024
8652c23
feat: test to get all sensors
joshuaunity Sep 30, 2024
ec4938a
Merge branch 'main' into feat-sensors-filters
nhoening Sep 30, 2024
dbd300b
fix: fix wrong imports
joshuaunity Sep 30, 2024
b08901d
refactor: expandd test cases for get sensors
joshuaunity Sep 30, 2024
651006a
refactor: expanded test case
joshuaunity Oct 1, 2024
5c7f797
chore: added to changelog
joshuaunity Oct 2, 2024
e420fa1
chore: updated change log
joshuaunity Oct 3, 2024
646de9c
refactor: dynamic expected results for test case
joshuaunity Oct 3, 2024
f4f5bf6
refactor: dynamic sensor name for test case
joshuaunity Oct 3, 2024
c5fedaf
Merge branch 'main' into feat-sensors-filters
joshuaunity Oct 4, 2024
4f987b2
chore: simplified testcase
joshuaunity Oct 8, 2024
289e78b
Merge branch 'main' into feat-sensors-filters
joshuaunity Oct 8, 2024
e8d4ad8
Merge branch 'main' into feat-sensors-filters
joshuaunity Oct 11, 2024
fe5b6fa
Merge branch 'main' into feat-sensors-filters
nhoening Oct 11, 2024
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
18 changes: 15 additions & 3 deletions flexmeasures/api/v3_0/sensors.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@
from flexmeasures.data.queries.utils import simplify_index
from flexmeasures.data.schemas.sensors import SensorSchema, SensorIdField
from flexmeasures.data.schemas.times import AwareDateTimeField, PlanningDurationField
from flexmeasures.data.services.sensors import get_sensors, get_sensor_stats
from flexmeasures.data.services.sensors import (
get_sensors,
get_sensor_stats,
get_all_accessible_sensors,
)
from flexmeasures.data.services.scheduling import (
create_scheduling_job,
get_data_source_for_job,
Expand All @@ -65,12 +69,16 @@ class SensorAPI(FlaskView):
"account": AccountIdField(
data_key="account_id", load_default=AccountIdField.load_current
),
"all_accessible": fields.Boolean(required=False, missing=False),
"filter": fields.Str(load_default=None),
},
location="query",
)
@permission_required_for_context("read", ctx_arg_name="account")
@as_json
def index(self, account: Account):
def index(
self, account: Account, all_accessible: bool = False, filter: str | None = None
):
"""API endpoint to list all sensors of an account.

.. :quickref: Sensor; Download sensor list
Expand Down Expand Up @@ -106,7 +114,11 @@ def index(self, account: Account):
:status 403: INVALID_SENDER
:status 422: UNPROCESSABLE_ENTITY
"""
sensors = get_sensors(account=account)
if all_accessible:
sensors = get_all_accessible_sensors(account, filter)
else:
sensors = get_sensors(account, filter=filter)

return sensors_schema.dump(sensors), 200

@route("/data", methods=["POST"])
Expand Down
43 changes: 43 additions & 0 deletions flexmeasures/data/services/sensors.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,47 @@
from flexmeasures.data.models.generic_assets import GenericAsset
from flexmeasures.data.schemas.reporting import StatusSchema
from flexmeasures.utils.time_utils import server_now
from flexmeasures.auth.policy import check_access


def get_all_accessible_sensors(account: Account, filter: str | None = None):
joshuaunity marked this conversation as resolved.
Show resolved Hide resolved
accounts: list = [account] if account else []
account_ids: list = [acc.id for acc in accounts]
consultancy_account_ids: list = [acc.consultancy_account_id for acc in accounts]
account_ids.extend(consultancy_account_ids)

sensor_query = (
sa.select(Sensor)
.join(GenericAsset, Sensor.generic_asset_id == GenericAsset.id)
.join(Account, GenericAsset.owner)
.filter(
sa.or_(
GenericAsset.account_id.in_(account_ids),
GenericAsset.account_id.is_(None),
)
)
)

if filter:
filter_statement = f"%{filter}%"
sensor_query = sensor_query.filter(
sa.or_(
Sensor.name.ilike(filter_statement),
Account.name.ilike(filter_statement),
)
)

sensors = db.session.scalars(sensor_query).all()

return [sensor for sensor in sensors if check_access(sensor, "read") is None]


def get_sensors(
joshuaunity marked this conversation as resolved.
Show resolved Hide resolved
account: Account | list[Account] | None,
include_public_assets: bool = False,
sensor_id_allowlist: list[int] | None = None,
sensor_name_allowlist: list[str] | None = None,
filter: str | None = None,
) -> list[Sensor]:
"""Return a list of Sensor objects that belong to the given account, and/or public sensors.

Expand Down Expand Up @@ -60,6 +94,15 @@ def get_sensors(
sensor_query = sensor_query.filter(Sensor.id.in_(sensor_id_allowlist))
if sensor_name_allowlist:
sensor_query = sensor_query.filter(Sensor.name.in_(sensor_name_allowlist))

if filter:
print("===================filter:", filter)
sensor_query = sensor_query.join(Account, GenericAsset.owner).filter(
sa.or_(
Sensor.name.ilike(filter),
Account.name.ilike(filter),
)
)
return db.session.scalars(sensor_query).all()


Expand Down
Loading