Skip to content

Commit 436ad91

Browse files
openapi specs
1 parent 6bb88c5 commit 436ad91

File tree

5 files changed

+82
-32
lines changed

5 files changed

+82
-32
lines changed

api/specs/web-server/_licensed_items.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
from typing import Annotated
1010

1111
from _common import as_query
12-
from fastapi import APIRouter, Depends, status
12+
from fastapi import APIRouter, Depends
1313
from models_library.api_schemas_webserver.licensed_items import LicensedItemRestGet
14+
from models_library.api_schemas_webserver.licensed_items_purchases import (
15+
LicensedItemPurchaseGet,
16+
)
1417
from models_library.rest_error import EnvelopedError
1518
from models_library.rest_pagination import Page
1619
from simcore_service_webserver._meta import API_VTAG
@@ -57,7 +60,7 @@ async def list_licensed_items(
5760

5861
@router.post(
5962
"/catalog/licensed-items/{licensed_item_id}:purchase",
60-
status_code=status.HTTP_204_NO_CONTENT,
63+
response_model=LicensedItemPurchaseGet,
6164
)
6265
async def purchase_licensed_item(
6366
_path: Annotated[LicensedItemsPathParams, Depends()],

services/web/server/src/simcore_service_webserver/api/v0/openapi.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3146,8 +3146,12 @@ paths:
31463146
schema:
31473147
$ref: '#/components/schemas/LicensedItemsBodyParams'
31483148
responses:
3149-
'204':
3149+
'200':
31503150
description: Successful Response
3151+
content:
3152+
application/json:
3153+
schema:
3154+
$ref: '#/components/schemas/LicensedItemPurchaseGet'
31513155
'404':
31523156
content:
31533157
application/json:

services/web/server/src/simcore_service_webserver/licenses/_licensed_items_rest.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
from aiohttp import web
44
from models_library.api_schemas_webserver.licensed_items import LicensedItemRestGet
5+
from models_library.api_schemas_webserver.licensed_items_purchases import (
6+
LicensedItemPurchaseGet,
7+
)
58
from models_library.licenses import LicensedItemPage
69
from models_library.rest_ordering import OrderBy
710
from models_library.rest_pagination import Page
811
from models_library.rest_pagination_utils import paginate_data
9-
from servicelib.aiohttp import status
1012
from servicelib.aiohttp.requests_validation import (
1113
parse_request_body_as,
1214
parse_request_path_parameters_as,
@@ -18,6 +20,7 @@
1820
from .._meta import API_VTAG as VTAG
1921
from ..login.decorators import login_required
2022
from ..security.decorators import permission_required
23+
from ..utils_aiohttp import envelope_json_response
2124
from . import _licensed_items_service
2225
from ._common.exceptions_handlers import handle_plugin_requests_exceptions
2326
from ._common.models import (
@@ -101,11 +104,14 @@ async def purchase_licensed_item(request: web.Request):
101104
path_params = parse_request_path_parameters_as(LicensedItemsPathParams, request)
102105
body_params = await parse_request_body_as(LicensedItemsBodyParams, request)
103106

104-
await _licensed_items_service.purchase_licensed_item(
105-
app=request.app,
106-
user_id=req_ctx.user_id,
107-
licensed_item_id=path_params.licensed_item_id,
108-
product_name=req_ctx.product_name,
109-
body_params=body_params,
107+
licensed_item_purchase_get: LicensedItemPurchaseGet = (
108+
await _licensed_items_service.purchase_licensed_item(
109+
app=request.app,
110+
user_id=req_ctx.user_id,
111+
licensed_item_id=path_params.licensed_item_id,
112+
product_name=req_ctx.product_name,
113+
body_params=body_params,
114+
)
110115
)
111-
return web.json_response(status=status.HTTP_204_NO_CONTENT)
116+
117+
return envelope_json_response(licensed_item_purchase_get)

services/web/server/src/simcore_service_webserver/licenses/_licensed_items_service.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
from datetime import UTC, datetime, timedelta
55

66
from aiohttp import web
7+
from models_library.api_schemas_webserver import (
8+
licensed_items_purchases as webserver_licensed_items_purchases,
9+
)
710
from models_library.licenses import LicensedItem, LicensedItemID, LicensedItemPage
811
from models_library.products import ProductName
912
from models_library.resource_tracker_licensed_items_purchases import (
@@ -69,7 +72,7 @@ async def purchase_licensed_item(
6972
user_id: UserID,
7073
licensed_item_id: LicensedItemID,
7174
body_params: LicensedItemsBodyParams,
72-
) -> None:
75+
) -> webserver_licensed_items_purchases.LicensedItemPurchaseGet:
7376
# Check user wallet permissions
7477
wallet = await get_wallet_with_available_credits_by_user_and_wallet(
7578
app, user_id=user_id, wallet_id=body_params.wallet_id, product_name=product_name
@@ -119,10 +122,29 @@ async def purchase_licensed_item(
119122
pricing_unit_cost=pricing_unit.current_cost_per_unit,
120123
start_at=datetime.now(tz=UTC),
121124
expire_at=datetime.now(tz=UTC) + timedelta(days=365),
122-
num_of_seats=body_params.num_of_seats, # <-- TODO: MD: this needs to be taken from the Pricing UNIT !!!
125+
num_of_seats=body_params.num_of_seats, # <-- NOTE: MD: this needs to be taken from the Pricing UNIT
123126
purchased_by_user=user_id,
124127
user_email=user["email"],
125128
purchased_at=datetime.now(tz=UTC),
126129
)
127130
rpc_client = get_rabbitmq_rpc_client(app)
128-
await licensed_items_purchases.create_licensed_item_purchase(rpc_client, data=_data)
131+
purchased_item = await licensed_items_purchases.create_licensed_item_purchase(
132+
rpc_client, data=_data
133+
)
134+
return webserver_licensed_items_purchases.LicensedItemPurchaseGet(
135+
licensed_item_purchase_id=purchased_item.licensed_item_purchase_id,
136+
product_name=purchased_item.product_name,
137+
licensed_item_id=purchased_item.licensed_item_id,
138+
key=purchased_item.key,
139+
version=purchased_item.version,
140+
wallet_id=purchased_item.wallet_id,
141+
pricing_unit_cost_id=purchased_item.pricing_unit_cost_id,
142+
pricing_unit_cost=purchased_item.pricing_unit_cost,
143+
start_at=purchased_item.start_at,
144+
expire_at=purchased_item.expire_at,
145+
num_of_seats=purchased_item.num_of_seats,
146+
purchased_by_user=purchased_item.purchased_by_user,
147+
user_email=purchased_item.user_email,
148+
purchased_at=purchased_item.purchased_at,
149+
modified_at=purchased_item.modified,
150+
)

services/web/server/tests/unit/with_dbs/04/licenses/test_licensed_items_rest.py

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,21 @@
33
# pylint: disable=unused-variable
44
# pylint: disable=too-many-arguments
55
# pylint: disable=too-many-statements
6+
from decimal import Decimal
67
from http import HTTPStatus
78

89
import pytest
910
from aiohttp.test_utils import TestClient
11+
from models_library.api_schemas_resource_usage_tracker import (
12+
licensed_items_purchases as rut_licensed_items_purchases,
13+
)
1014
from models_library.api_schemas_resource_usage_tracker.pricing_plans import (
1115
PricingUnitGet,
1216
)
1317
from models_library.api_schemas_webserver.licensed_items import LicensedItemRestGet
18+
from models_library.api_schemas_webserver.licensed_items_purchases import (
19+
LicensedItemPurchaseGet,
20+
)
1421
from models_library.api_schemas_webserver.wallets import WalletGetWithAvailableCredits
1522
from models_library.licenses import VIP_DETAILS_EXAMPLE, LicensedResourceType
1623
from pytest_mock.plugin import MockerFixture
@@ -96,13 +103,29 @@ async def test_licensed_items_listing(
96103
assert "additionalField" not in source
97104
assert "additional_field" not in source
98105

99-
# # get
100-
# url = client.app.router["get_licensed_item"].url_for(
101-
# licensed_item_id=f"{_licensed_item_id}"
102-
# )
103-
# resp = await client.get(f"{url}")
104-
# data, _ = await assert_status(resp, status.HTTP_200_OK)
105-
# assert LicensedItemRestGet(**data)
106+
107+
_LICENSED_ITEM_PURCHASE_GET = (
108+
rut_licensed_items_purchases.LicensedItemPurchaseGet.model_validate(
109+
{
110+
"licensed_item_purchase_id": "beb16d18-d57d-44aa-a638-9727fa4a72ef",
111+
"product_name": "osparc",
112+
"licensed_item_id": "303942ef-6d31-4ba8-afbe-dbb1fce2a953",
113+
"key": "Duke",
114+
"version": "1.0.0",
115+
"wallet_id": 1,
116+
"wallet_name": "My Wallet",
117+
"pricing_unit_cost_id": 1,
118+
"pricing_unit_cost": Decimal(10),
119+
"start_at": "2023-01-11 13:11:47.293595",
120+
"expire_at": "2023-01-11 13:11:47.293595",
121+
"num_of_seats": 1,
122+
"purchased_by_user": 1,
123+
"user_email": "[email protected]",
124+
"purchased_at": "2023-01-11 13:11:47.293595",
125+
"modified": "2023-01-11 13:11:47.293595",
126+
}
127+
)
128+
)
106129

107130

108131
@pytest.fixture
@@ -123,7 +146,7 @@ def mock_licensed_items_purchase_functions(mocker: MockerFixture) -> tuple:
123146
)
124147
mock_create_licensed_item_purchase = mocker.patch(
125148
"simcore_service_webserver.licenses._licensed_items_service.licensed_items_purchases.create_licensed_item_purchase",
126-
spec=True,
149+
return_value=_LICENSED_ITEM_PURCHASE_GET,
127150
)
128151

129152
return (
@@ -179,14 +202,6 @@ async def test_licensed_items_purchase(
179202
)
180203
)
181204

182-
# # get
183-
# url = client.app.router["get_licensed_item"].url_for(
184-
# licensed_item_id=f"{_licensed_item_id}"
185-
# )
186-
# resp = await client.get(f"{url}")
187-
# data, _ = await assert_status(resp, status.HTTP_200_OK)
188-
# assert LicensedItemRestGet(**data)
189-
190205
# purchase
191206
url = client.app.router["purchase_licensed_item"].url_for(
192207
licensed_item_id=f"{_licensed_item_id}"
@@ -200,5 +215,5 @@ async def test_licensed_items_purchase(
200215
"pricing_unit_id": 1,
201216
},
202217
)
203-
await assert_status(resp, status.HTTP_204_NO_CONTENT)
204-
print("yes")
218+
data, _ = await assert_status(resp, status.HTTP_200_OK)
219+
assert LicensedItemPurchaseGet(**data)

0 commit comments

Comments
 (0)