Skip to content

Commit

Permalink
✨ introduce licensed_items_purchases endpoints 🗃️ (#6928)
Browse files Browse the repository at this point in the history
On behalf of @matusdrobuliak66
  • Loading branch information
matusdrobuliak66 authored Dec 11, 2024
1 parent a35576c commit 825c22a
Show file tree
Hide file tree
Showing 54 changed files with 2,002 additions and 247 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@
from models_library.generics import Envelope
from models_library.rest_error import EnvelopedError
from simcore_service_webserver._meta import API_VTAG
from simcore_service_webserver.catalog.licenses._exceptions_handlers import (
_TO_HTTP_ERROR_MAP,
)
from simcore_service_webserver.catalog.licenses._models import (
from simcore_service_webserver.licenses._exceptions_handlers import _TO_HTTP_ERROR_MAP
from simcore_service_webserver.licenses._models import (
LicensedItemsBodyParams,
LicensedItemsListQueryParams,
LicensedItemsPathParams,
Expand Down
57 changes: 57 additions & 0 deletions api/specs/web-server/_licensed_items_purchases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
""" Helper script to generate OAS automatically
"""

# pylint: disable=redefined-outer-name
# pylint: disable=unused-argument
# pylint: disable=unused-variable
# pylint: disable=too-many-arguments

from typing import Annotated

from _common import as_query
from fastapi import APIRouter, Depends
from models_library.api_schemas_webserver.licensed_items_purchases import (
LicensedItemPurchaseGet,
)
from models_library.generics import Envelope
from models_library.rest_error import EnvelopedError
from models_library.rest_pagination import Page
from simcore_service_webserver._meta import API_VTAG
from simcore_service_webserver.licenses._exceptions_handlers import _TO_HTTP_ERROR_MAP
from simcore_service_webserver.licenses._models import (
LicensedItemsPurchasesListQueryParams,
LicensedItemsPurchasesPathParams,
)
from simcore_service_webserver.wallets._handlers import WalletsPathParams

router = APIRouter(
prefix=f"/{API_VTAG}",
tags=[
"licenses",
],
responses={
i.status_code: {"model": EnvelopedError} for i in _TO_HTTP_ERROR_MAP.values()
},
)


@router.get(
"/wallets/{wallet_id}/licensed-items-purchases",
response_model=Page[LicensedItemPurchaseGet],
tags=["wallets"],
)
async def list_wallet_licensed_items_purchases(
_path: Annotated[WalletsPathParams, Depends()],
_query: Annotated[as_query(LicensedItemsPurchasesListQueryParams), Depends()],
):
...


@router.get(
"/licensed-items-purchases/{licensed_item_purchase_id}",
response_model=Envelope[LicensedItemPurchaseGet],
)
async def get_licensed_item_purchase(
_path: Annotated[LicensedItemsPurchasesPathParams, Depends()],
):
...
3 changes: 2 additions & 1 deletion api/specs/web-server/openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@
"_announcements",
"_catalog",
"_catalog_tags", # MUST BE after _catalog
"_catalog_licensed_items",
"_computations",
"_exporter",
"_folders",
"_long_running_tasks",
"_licensed_items",
"_licensed_items_purchases",
"_metamodeling",
"_nih_sparc",
"_nih_sparc_redirections",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from datetime import datetime
from decimal import Decimal
from typing import NamedTuple

from models_library.licensed_items import LicensedItemID
from models_library.products import ProductName
from models_library.resource_tracker import PricingUnitCostId
from models_library.resource_tracker_licensed_items_purchases import (
LicensedItemPurchaseID,
)
from models_library.users import UserID
from models_library.wallets import WalletID
from pydantic import BaseModel, ConfigDict, PositiveInt


class LicensedItemPurchaseGet(BaseModel):
licensed_item_purchase_id: LicensedItemPurchaseID
product_name: ProductName
licensed_item_id: LicensedItemID
wallet_id: WalletID
wallet_name: str
pricing_unit_cost_id: PricingUnitCostId
pricing_unit_cost: Decimal
start_at: datetime
expire_at: datetime
num_of_seats: int
purchased_by_user: UserID
purchased_at: datetime
modified: datetime

model_config = ConfigDict(
json_schema_extra={
"examples": [
{
"licensed_item_purchase_id": "beb16d18-d57d-44aa-a638-9727fa4a72ef",
"product_name": "osparc",
"licensed_item_id": "303942ef-6d31-4ba8-afbe-dbb1fce2a953",
"wallet_id": 1,
"wallet_name": "My Wallet",
"pricing_unit_cost_id": 1,
"pricing_unit_cost": 10,
"start_at": "2023-01-11 13:11:47.293595",
"expire_at": "2023-01-11 13:11:47.293595",
"num_of_seats": 1,
"purchased_by_user": 1,
"purchased_at": "2023-01-11 13:11:47.293595",
"modified": "2023-01-11 13:11:47.293595",
}
]
}
)


class LicensedItemsPurchasesPage(NamedTuple):
items: list[LicensedItemPurchaseGet]
total: PositiveInt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from datetime import datetime
from decimal import Decimal
from typing import NamedTuple

from models_library.licensed_items import LicensedItemID
from models_library.products import ProductName
from models_library.resource_tracker import PricingUnitCostId
from models_library.resource_tracker_licensed_items_purchases import (
LicensedItemPurchaseID,
)
from models_library.users import UserID
from models_library.wallets import WalletID
from pydantic import PositiveInt

from ._base import OutputSchema


class LicensedItemPurchaseGet(OutputSchema):
licensed_item_purchase_id: LicensedItemPurchaseID
product_name: ProductName
licensed_item_id: LicensedItemID
wallet_id: WalletID
pricing_unit_cost_id: PricingUnitCostId
pricing_unit_cost: Decimal
start_at: datetime
expire_at: datetime
num_of_seats: int
purchased_by_user: UserID
purchased_at: datetime
modified_at: datetime


class LicensedItemPurchaseGetPage(NamedTuple):
items: list[LicensedItemPurchaseGet]
total: PositiveInt
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,59 @@ class WalletGet(OutputSchema):
created: datetime
modified: datetime

model_config = ConfigDict(from_attributes=True, frozen=False)
model_config = ConfigDict(
from_attributes=True,
frozen=False,
json_schema_extra={
"examples": [
{
"wallet_id": 1,
"name": "My wallet",
"description": "My description",
"owner": 1,
"thumbnail": "https://example.com/payment-method/form",
"status": "ACTIVE",
"created": "2024-03-25T00:00:00",
"modified": "2024-03-25T00:00:00",
}
]
},
)


class WalletGetWithAvailableCredits(WalletGet):
available_credits: Decimal

model_config = ConfigDict(
json_schema_extra={
"examples": [
{
**WalletGet.model_config["json_schema_extra"]["examples"][0], # type: ignore
"available_credits": 10.5,
}
]
}
)


class WalletGetPermissions(WalletGet):
read: bool
write: bool
delete: bool

model_config = ConfigDict(
json_schema_extra={
"examples": [
{
**WalletGet.model_config["json_schema_extra"]["examples"][0], # type: ignore
"read": True,
"write": True,
"delete": True,
}
]
}
)


class CreateWalletBodyParams(OutputSchema):
name: str
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class CreditTransactionStatus(StrAutoEnum):
class CreditClassification(StrAutoEnum):
ADD_WALLET_TOP_UP = auto() # user top up credits
DEDUCT_SERVICE_RUN = auto() # computational/dynamic service run costs)
DEDUCT_LICENSE_PURCHASE = auto()


class PricingPlanClassification(StrAutoEnum):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from datetime import datetime
from decimal import Decimal
from typing import TypeAlias
from uuid import UUID

from pydantic import BaseModel, ConfigDict

from .licensed_items import LicensedItemID
from .products import ProductName
from .resource_tracker import PricingPlanId, PricingUnitCostId, PricingUnitId
from .users import UserID
from .wallets import WalletID

LicensedItemPurchaseID: TypeAlias = UUID


class LicensedItemsPurchasesCreate(BaseModel):
product_name: ProductName
licensed_item_id: LicensedItemID
wallet_id: WalletID
wallet_name: str
pricing_plan_id: PricingPlanId
pricing_unit_id: PricingUnitId
pricing_unit_cost_id: PricingUnitCostId
pricing_unit_cost: Decimal
start_at: datetime
expire_at: datetime
num_of_seats: int
purchased_by_user: UserID
user_email: str
purchased_at: datetime

model_config = ConfigDict(from_attributes=True)
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""add cols to licensed_items_purchases table 3
Revision ID: 77ac824a77ff
Revises: d68b8128c23b
Create Date: 2024-12-10 16:42:14.041313+00:00
"""
import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = "77ac824a77ff"
down_revision = "d68b8128c23b"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"resource_tracker_credit_transactions",
sa.Column(
"licensed_item_purchase_id", postgresql.UUID(as_uuid=True), nullable=True
),
)
# ### end Alembic commands ###
op.execute(
sa.DDL(
"ALTER TYPE credittransactionclassification ADD VALUE 'DEDUCT_LICENSE_PURCHASE'"
)
)


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("resource_tracker_credit_transactions", "licensed_item_purchase_id")
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""add cols to licensed_items_purchases table
Revision ID: 8fa15c4c3977
Revises: 5e27063c3ac9
Create Date: 2024-12-10 06:42:23.319239+00:00
"""
import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "8fa15c4c3977"
down_revision = "5e27063c3ac9"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"resource_tracker_licensed_items_purchases",
sa.Column("wallet_name", sa.String(), nullable=False),
)
op.add_column(
"resource_tracker_licensed_items_purchases",
sa.Column("pricing_unit_cost_id", sa.BigInteger(), nullable=False),
)
op.add_column(
"resource_tracker_licensed_items_purchases",
sa.Column("pricing_unit_cost", sa.Numeric(scale=2), nullable=True),
)
op.add_column(
"resource_tracker_licensed_items_purchases",
sa.Column("num_of_seats", sa.SmallInteger(), nullable=False),
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("resource_tracker_licensed_items_purchases", "num_of_seats")
op.drop_column("resource_tracker_licensed_items_purchases", "pricing_unit_cost")
op.drop_column("resource_tracker_licensed_items_purchases", "pricing_unit_cost_id")
op.drop_column("resource_tracker_licensed_items_purchases", "wallet_name")
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""add cols to licensed_items_purchases table 2
Revision ID: d68b8128c23b
Revises: 8fa15c4c3977
Create Date: 2024-12-10 10:24:28.071216+00:00
"""
import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = "d68b8128c23b"
down_revision = "8fa15c4c3977"
branch_labels = None
depends_on = None


def upgrade():
op.drop_column("resource_tracker_licensed_items_purchases", "licensed_item_id")
op.add_column(
"resource_tracker_licensed_items_purchases",
sa.Column("licensed_item_id", postgresql.UUID(as_uuid=True), nullable=False),
)


def downgrade():
...
Loading

0 comments on commit 825c22a

Please sign in to comment.