Skip to content

Commit 47894e5

Browse files
committed
Support listing invalid orders
When listing, gridpool orders are filtered by validity. Valid orders require a finite price and quantity to be set unless they are cancelled. The filter can optionally be disabled when calling the endpoint. Signed-off-by: cwasicki <[email protected]>
1 parent 8adcf0a commit 47894e5

File tree

3 files changed

+28
-19
lines changed

3 files changed

+28
-19
lines changed

src/frequenz/client/electricity_trading/_client.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,7 @@ async def list_gridpool_orders(
809809
tag: str | None = None,
810810
page_size: int | None = None,
811811
timeout: timedelta | None = None,
812+
valid_only: bool = True,
812813
) -> AsyncIterator[OrderDetail]:
813814
"""
814815
List orders for a specific Gridpool with optional filters.
@@ -822,6 +823,7 @@ async def list_gridpool_orders(
822823
tag: The tag to filter by.
823824
page_size: The number of orders to return per page.
824825
timeout: Timeout duration, defaults to None.
826+
valid_only: If True, only returns orders that are valid.
825827
826828
Yields:
827829
The list of orders for the given gridpool.
@@ -856,9 +858,11 @@ async def list_gridpool_orders(
856858
timeout=timeout,
857859
),
858860
)
859-
860861
for order_detail in response.order_details:
861-
yield OrderDetail.from_pb(order_detail)
862+
od = OrderDetail.from_pb(order_detail)
863+
if valid_only and not od.is_valid:
864+
continue
865+
yield od
862866

863867
if response.pagination_info.next_page_token:
864868
request.pagination_params.CopyFrom(

src/frequenz/client/electricity_trading/_types.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,9 +1316,6 @@ def from_pb(cls, order_detail: electricity_trading_pb2.OrderDetail) -> Self:
13161316
13171317
Returns:
13181318
OrderDetail object corresponding to the protobuf message.
1319-
1320-
Raises:
1321-
ValueError: If the order price and quantity are not specified for a non-canceled order.
13221319
"""
13231320
od = cls(
13241321
order_id=order_detail.order_id,
@@ -1332,18 +1329,24 @@ def from_pb(cls, order_detail: electricity_trading_pb2.OrderDetail) -> Self:
13321329
),
13331330
)
13341331

1332+
return od
1333+
1334+
@property
1335+
def is_valid(self) -> bool:
1336+
"""Check if the order detail is valid.
1337+
1338+
Returns:
1339+
True if the order detail is valid, False otherwise.
1340+
"""
13351341
# Only cancelled orders are allowed to have missing price or quantity
1336-
missing_price_or_quantity = (
1337-
od.order.price.amount.is_nan()
1338-
or od.order.price.currency == Currency.UNSPECIFIED
1339-
or od.order.quantity.mw.is_nan()
1340-
)
1341-
if missing_price_or_quantity and od.state_detail.state != OrderState.CANCELED:
1342-
raise ValueError(
1343-
f"Price and quantity must be specified for a non-canceled order (`{od}`)."
1344-
)
1342+
if self.state_detail.state == OrderState.CANCELED:
1343+
return True
13451344

1346-
return od
1345+
return not (
1346+
self.order.price.amount.is_nan()
1347+
or self.order.price.currency == Currency.UNSPECIFIED
1348+
or self.order.quantity.mw.is_nan()
1349+
)
13471350

13481351
def to_pb(self) -> electricity_trading_pb2.OrderDetail:
13491352
"""Convert an OrderDetail object to protobuf OrderDetail.

tests/test_types.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -554,22 +554,24 @@ def test_order_detail_from_pb_missing_fields() -> None:
554554
# Missing price
555555
od_pb1 = electricity_trading_pb2.OrderDetail()
556556
od_pb1.CopyFrom(ORDER_DETAIL_PB)
557+
assert OrderDetail.from_pb(od_pb1).is_valid
557558
od_pb1.order.ClearField("price")
558559
# Not allowed for active orders
559-
with pytest.raises(ValueError):
560-
OrderDetail.from_pb(od_pb1)
560+
assert not OrderDetail.from_pb(od_pb1).is_valid
561561
# But allowed for canceled orders
562562
od_pb1.state_detail.state = electricity_trading_pb2.OrderState.ORDER_STATE_CANCELED
563563
OrderDetail.from_pb(od_pb1)
564+
assert OrderDetail.from_pb(od_pb1).is_valid
564565

565566
# Missing quantity (same logic as above)
566567
od_pb2 = electricity_trading_pb2.OrderDetail()
567568
od_pb2.CopyFrom(ORDER_DETAIL_PB)
569+
assert OrderDetail.from_pb(od_pb2).is_valid
568570
od_pb2.order.ClearField("quantity")
569-
with pytest.raises(ValueError):
570-
OrderDetail.from_pb(od_pb2)
571+
assert not OrderDetail.from_pb(od_pb2).is_valid
571572
od_pb2.state_detail.state = electricity_trading_pb2.OrderState.ORDER_STATE_CANCELED
572573
OrderDetail.from_pb(od_pb2)
574+
assert OrderDetail.from_pb(od_pb2).is_valid
573575

574576

575577
def test_order_detail_no_timezone_error() -> None:

0 commit comments

Comments
 (0)