33
44from fastapi import APIRouter , HTTPException , Request , status
55from fastapi .datastructures import URL
6+ from fastapi .responses import Response
67from returns .maybe import Maybe , Some
78from returns .result import Failure , Success
89
910from stapi_fastapi .backends .root_backend import RootBackend
1011from stapi_fastapi .constants import TYPE_GEOJSON , TYPE_JSON
1112from stapi_fastapi .exceptions import NotFoundException
1213from stapi_fastapi .models .conformance import CORE , Conformance
13- from stapi_fastapi .models .order import Order , OrderCollection
14+ from stapi_fastapi .models .order import (
15+ Order ,
16+ OrderCollection ,
17+ OrderStatuses ,
18+ OrderStatusPayload ,
19+ )
1420from stapi_fastapi .models .product import Product , ProductsCollection
1521from stapi_fastapi .models .root import RootResponse
1622from stapi_fastapi .models .shared import Link
@@ -84,6 +90,22 @@ def __init__(
8490 tags = ["Orders" ],
8591 )
8692
93+ self .add_api_route (
94+ "/orders/{order_id}/statuses" ,
95+ self .get_order_statuses ,
96+ methods = ["GET" ],
97+ name = f"{ self .name } :list-order-statuses" ,
98+ tags = ["Orders" ],
99+ )
100+
101+ self .add_api_route (
102+ "/orders/{order_id}/statuses" ,
103+ self .set_order_status ,
104+ methods = ["POST" ],
105+ name = f"{ self .name } :set-order-status" ,
106+ tags = ["Orders" ],
107+ )
108+
87109 def get_root (self , request : Request ) -> RootResponse :
88110 return RootResponse (
89111 id = "STAPI API" ,
@@ -168,9 +190,7 @@ async def get_order(self: Self, order_id: str, request: Request) -> Order:
168190 """
169191 match await self .backend .get_order (order_id , request ):
170192 case Success (Some (order )):
171- order .links .append (
172- Link (href = str (request .url ), rel = "self" , type = TYPE_GEOJSON )
173- )
193+ self .add_order_links (order , request )
174194 return order
175195 case Success (Maybe .empty ):
176196 raise NotFoundException ("Order not found" )
@@ -185,11 +205,78 @@ async def get_order(self: Self, order_id: str, request: Request) -> Order:
185205 case _:
186206 raise AssertionError ("Expected code to be unreachable" )
187207
208+ async def get_order_statuses (
209+ self : Self , order_id : str , request : Request
210+ ) -> OrderStatuses :
211+ match await self .backend .get_order_statuses (order_id , request ):
212+ case Success (statuses ):
213+ return OrderStatuses (
214+ statuses = statuses ,
215+ links = [
216+ Link (
217+ href = str (
218+ request .url_for (
219+ f"{ self .name } :list-order-statuses" ,
220+ order_id = order_id ,
221+ )
222+ ),
223+ rel = "self" ,
224+ type = TYPE_JSON ,
225+ )
226+ ],
227+ )
228+ case Failure (e ):
229+ logging .exception (
230+ "An error occurred while retrieving order statuses" , e
231+ )
232+ raise HTTPException (
233+ status_code = status .HTTP_500_INTERNAL_SERVER_ERROR ,
234+ detail = "Error finding Order Statuses" ,
235+ )
236+ case _:
237+ raise AssertionError ("Expected code to be unreachable" )
238+
239+ async def set_order_status (
240+ self , order_id : str , payload : OrderStatusPayload , request : Request
241+ ) -> Response :
242+ match await self .backend .set_order_status (order_id , payload , request ):
243+ case Success (_):
244+ return Response (status_code = status .HTTP_202_ACCEPTED )
245+ case Failure (e ):
246+ logging .exception ("An error occurred while setting order status" , e )
247+ raise HTTPException (
248+ status_code = status .HTTP_500_INTERNAL_SERVER_ERROR ,
249+ detail = "Error setting Order Status" ,
250+ )
251+ case x :
252+ raise AssertionError (f"Expected code to be unreachable { x } " )
253+
188254 def add_product (self : Self , product : Product ) -> None :
189255 # Give the include a prefix from the product router
190256 product_router = ProductRouter (product , self )
191257 self .include_router (product_router , prefix = f"/products/{ product .id } " )
192258 self .product_routers [product .id ] = product_router
193259
194- def generate_order_href (self : Self , request : Request , order_id : int | str ) -> URL :
260+ def generate_order_href (self : Self , request : Request , order_id : str ) -> URL :
195261 return request .url_for (f"{ self .name } :get-order" , order_id = order_id )
262+
263+ def generate_order_statuses_href (
264+ self : Self , request : Request , order_id : str
265+ ) -> URL :
266+ return request .url_for (f"{ self .name } :list-order-statuses" , order_id = order_id )
267+
268+ def add_order_links (self , order : Order , request : Request ):
269+ order .links .append (
270+ Link (
271+ href = str (self .generate_order_href (request , order .id )),
272+ rel = "self" ,
273+ type = TYPE_GEOJSON ,
274+ )
275+ )
276+ order .links .append (
277+ Link (
278+ href = str (self .generate_order_statuses_href (request , order .id )),
279+ rel = "monitor" ,
280+ type = TYPE_JSON ,
281+ ),
282+ )
0 commit comments