Skip to content

Commit

Permalink
✨ Enhancements for product-owner users and invitations (ITISFoundatio…
Browse files Browse the repository at this point in the history
  • Loading branch information
pcrespov authored Oct 16, 2023
1 parent f2e6292 commit 707d185
Show file tree
Hide file tree
Showing 35 changed files with 643 additions and 232 deletions.
2 changes: 1 addition & 1 deletion .env-devel
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ S3_SECURE=0
SCICRUNCH_API_BASE_URL=https://scicrunch.org/api/1
SCICRUNCH_API_KEY=REPLACE_ME_with_valid_api_key

SMTP_HOST=mail.speag.com
SMTP_HOST=fake.mail.server.com
SMTP_PORT=25
SMTP_USERNAME=it_doesnt_matter
SMTP_PASSWORD=it_doesnt_matter
Expand Down
18 changes: 15 additions & 3 deletions api/specs/web-server/_products.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@
# pylint: disable=unused-variable


from fastapi import APIRouter
from typing import Annotated

from fastapi import APIRouter, Depends
from models_library.api_schemas_webserver.product import (
CreditPriceGet,
GenerateInvitation,
GetCreditPrice,
GetProduct,
InvitationGenerated,
)
from models_library.generics import Envelope
from simcore_service_webserver._meta import API_VTAG
from simcore_service_webserver.products._handlers import _ProductsRequestParams

router = APIRouter(
prefix=f"/{API_VTAG}",
Expand All @@ -24,12 +28,20 @@

@router.get(
"/credits-price",
response_model=Envelope[CreditPriceGet],
response_model=Envelope[GetCreditPrice],
)
async def get_current_product_price():
...


@router.get(
"/products/{product_name}",
response_model=Envelope[GetProduct],
)
async def get_product(_params: Annotated[_ProductsRequestParams, Depends()]):
...


@router.post(
"/invitation:generate",
response_model=Envelope[InvitationGenerated],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from ._base import InputSchema, OutputSchema


class CreditPriceGet(OutputSchema):
class GetCreditPrice(OutputSchema):
product_name: str
usd_per_credit: NonNegativeDecimal | None = Field(
...,
Expand All @@ -26,18 +26,40 @@ class Config(OutputSchema.Config):
}


class GetProduct(OutputSchema):
name: ProductName
display_name: str
short_name: str | None = Field(
default=None, description="Short display name for SMS"
)

vendor: dict | None = Field(default=None, description="vendor attributes")
issues: list[dict] | None = Field(
default=None, description="Reference to issues tracker"
)
manuals: list[dict] | None = Field(default=None, description="List of manuals")
support: list[dict] | None = Field(
default=None, description="List of support resources"
)

login_settings: dict
max_open_studies_per_user: PositiveInt | None
is_payment_enabled: bool
credits_per_usd: NonNegativeDecimal | None


class GenerateInvitation(InputSchema):
guest: LowerCaseEmailStr
trial_account_days: PositiveInt | None = None
extra_credits: PositiveInt | None = None
extra_credits_in_usd: PositiveInt | None = None


class InvitationGenerated(OutputSchema):
product_name: ProductName
issuer: LowerCaseEmailStr
guest: LowerCaseEmailStr
trial_account_days: PositiveInt | None = None
extra_credits: PositiveInt | None = None
extra_credits_in_usd: PositiveInt | None = None
created: datetime
invitation_link: HttpUrl

Expand All @@ -49,7 +71,7 @@ class Config(OutputSchema.Config):
"issuer": "[email protected]",
"guest": "[email protected]",
"trialAccountDays": 7,
"extraCredits": 30,
"extraCreditsInUsd": 30,
"created": "2023-09-27T15:30:00",
"invitationLink": "https://example.com/invitation#1234",
},
Expand Down
4 changes: 2 additions & 2 deletions packages/models-library/src/models_library/invitations.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ class InvitationInputs(BaseModel):
description="If set, this invitation will activate a trial account."
"Sets the number of days from creation until the account expires",
)
extra_credits: PositiveInt | None = Field(
extra_credits_in_usd: PositiveInt | None = Field(
None,
description="If set, the account's primary wallet will add these extra credits",
description="If set, the account's primary wallet will add extra credits corresponding to this ammount in USD",
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,6 @@
"usd_per_credit >= 0", name="non_negative_usd_per_credit_constraint"
),
)


__all__: tuple[str, ...] = ("NUMERIC_KWARGS",)
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
from decimal import Decimal
from typing import Final

import sqlalchemy as sa
from aiopg.sa.connection import SAConnection
from simcore_postgres_database.models.products_prices import products_prices
from simcore_postgres_database.models.products_prices import (
NUMERIC_KWARGS,
products_prices,
)

QUANTIZE_EXP_ARG: Final = Decimal(f"1e-{NUMERIC_KWARGS['scale']}")


async def get_product_latest_credit_price_or_none(
Expand All @@ -16,7 +22,7 @@ async def get_product_latest_credit_price_or_none(
.limit(1)
)
if usd_per_credit is not None:
return Decimal(usd_per_credit)
return Decimal(usd_per_credit).quantize(QUANTIZE_EXP_ARG)
return None


Expand Down
20 changes: 9 additions & 11 deletions packages/pytest-simcore/src/pytest_simcore/helpers/utils_assert.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"""
from pprint import pformat
from typing import Optional

from aiohttp import ClientResponse
from aiohttp.web import HTTPError, HTTPException, HTTPInternalServerError, HTTPNoContent
Expand All @@ -12,10 +11,10 @@
async def assert_status(
response: ClientResponse,
expected_cls: type[HTTPException],
expected_msg: Optional[str] = None,
expected_error_code: Optional[str] = None,
include_meta: Optional[bool] = False,
include_links: Optional[bool] = False,
expected_msg: str | None = None,
expected_error_code: str | None = None,
include_meta: bool | None = False,
include_links: bool | None = False,
) -> tuple[dict, ...]:
"""
Asserts for enveloped responses
Expand All @@ -34,9 +33,8 @@ async def assert_status(
assert not data, pformat(data)
assert not error, pformat(error)
else:
# with a 200, data may still be empty see
# https://medium.com/@santhoshkumarkrishna/http-get-rest-api-no-content-404-vs-204-vs-200-6dd869e3af1d
# assert data is not None, pformat(data)
# with a 200, data may still be empty so we cannot 'assert data is not None'
# SEE https://medium.com/@santhoshkumarkrishna/http-get-rest-api-no-content-404-vs-204-vs-200-6dd869e3af1d
assert not error, pformat(error)

if expected_msg:
Expand All @@ -56,7 +54,7 @@ async def assert_status(
async def assert_error(
response: ClientResponse,
expected_cls: type[HTTPException],
expected_msg: Optional[str] = None,
expected_msg: str | None = None,
):
data, error = unwrap_envelope(await response.json())
return do_assert_error(data, error, expected_cls, expected_msg)
Expand All @@ -66,8 +64,8 @@ def do_assert_error(
data,
error,
expected_cls: type[HTTPException],
expected_msg: Optional[str] = None,
expected_error_code: Optional[str] = None,
expected_msg: str | None = None,
expected_error_code: str | None = None,
):
assert not data, pformat(data)
assert error, pformat(error)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,15 @@ def __init__(
guest_email: str | None = None,
host: dict | None = None,
trial_days: int | None = None,
extra_credits: int | None = None,
extra_credits_in_usd: int | None = None,
):
assert client.app
super().__init__(params=host, app=client.app)
self.client = client
self.tag = f"Created by {guest_email or FAKE.email()}"
self.confirmation = None
self.trial_days = trial_days
self.extra_credits = extra_credits
self.extra_credits_in_usd = extra_credits_in_usd

async def __aenter__(self) -> "NewInvitation":
# creates host user
Expand All @@ -148,7 +148,7 @@ async def __aenter__(self) -> "NewInvitation":
user_email=self.user["email"],
tag=self.tag,
trial_days=self.trial_days,
extra_credits=self.extra_credits,
extra_credits_in_usd=self.extra_credits_in_usd,
)
return self

Expand Down
18 changes: 9 additions & 9 deletions services/invitations/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,11 @@
"description": "If set, this invitation will activate a trial account.Sets the number of days from creation until the account expires",
"minimum": 0
},
"extra_credits": {
"title": "Extra Credits",
"extra_credits_in_usd": {
"title": "Extra Credits In Usd",
"exclusiveMinimum": true,
"type": "integer",
"description": "If set, the account's primary wallet will add these extra credits",
"description": "If set, the account's primary wallet will add extra credits corresponding to this ammount in USD",
"minimum": 0
},
"created": {
Expand Down Expand Up @@ -240,11 +240,11 @@
"description": "If set, this invitation will activate a trial account.Sets the number of days from creation until the account expires",
"minimum": 0
},
"extra_credits": {
"title": "Extra Credits",
"extra_credits_in_usd": {
"title": "Extra Credits In Usd",
"exclusiveMinimum": true,
"type": "integer",
"description": "If set, the account's primary wallet will add these extra credits",
"description": "If set, the account's primary wallet will add extra credits corresponding to this ammount in USD",
"minimum": 0
},
"created": {
Expand Down Expand Up @@ -299,11 +299,11 @@
"description": "If set, this invitation will activate a trial account.Sets the number of days from creation until the account expires",
"minimum": 0
},
"extra_credits": {
"title": "Extra Credits",
"extra_credits_in_usd": {
"title": "Extra Credits In Usd",
"exclusiveMinimum": true,
"type": "integer",
"description": "If set, the account's primary wallet will add these extra credits",
"description": "If set, the account's primary wallet will add extra credits corresponding to this ammount in USD",
"minimum": 0
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class Config:
"trial_account_days": {
"alias": "t",
},
"extra_credits": {
"extra_credits_in_usd": {
"alias": "e",
},
"created": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,12 @@ qx.Class.define("osparc.po.Invitations", {
});
form.add(userEmail, this.tr("User Email"));

const extraCredits = new qx.ui.form.Spinner().set({
const extraCreditsInUsd = new qx.ui.form.Spinner().set({
minimum: 0,
maximum: 1000,
value: 0
});
form.add(extraCredits, this.tr("Welcome Credits"));
form.add(extraCreditsInUsd, this.tr("Welcome Credits (US $)"));

const withExpiration = new qx.ui.form.CheckBox().set({
value: false
Expand Down Expand Up @@ -135,8 +135,8 @@ qx.Class.define("osparc.po.Invitations", {
"guest": userEmail.getValue()
}
};
if (extraCredits.getValue() > 0) {
params.data["extraCredits"] = extraCredits.getValue();
if (extraCreditsInUsd.getValue() > 0) {
params.data["extraCreditsInUsd"] = extraCreditsInUsd.getValue();
}
if (withExpiration.getValue()) {
params.data["trialAccountDays"] = trialDays.getValue();
Expand Down
2 changes: 1 addition & 1 deletion services/web/server/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.33.0
0.34.0
2 changes: 1 addition & 1 deletion services/web/server/setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.33.0
current_version = 0.34.0
commit = True
message = services/webserver api version: {current_version} → {new_version}
tag = False
Expand Down
Loading

0 comments on commit 707d185

Please sign in to comment.