Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ introduce licensed_items_purchases endpoints 🗃️ #6928

Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
829eae9
db layer licensed items purchase
matusdrobuliak66 Dec 9, 2024
a975a63
rut part
matusdrobuliak66 Dec 10, 2024
fc62c0d
merge master
matusdrobuliak66 Dec 10, 2024
78ef2cc
renaming tests
matusdrobuliak66 Dec 10, 2024
a6f49cd
rpc interface
matusdrobuliak66 Dec 10, 2024
f5de79b
RUT unit tests
matusdrobuliak66 Dec 10, 2024
acd4c88
RUT unit tests
matusdrobuliak66 Dec 10, 2024
317cf1d
RUT unit tests
matusdrobuliak66 Dec 10, 2024
932fb00
webserver part
matusdrobuliak66 Dec 10, 2024
06f5743
webserver part
matusdrobuliak66 Dec 10, 2024
dbd1ffe
open api specs
matusdrobuliak66 Dec 10, 2024
6bec5ff
webserver part tests
matusdrobuliak66 Dec 10, 2024
754cd58
Merge branch 'master' into introduce-vip-models-pricing-4-part
matusdrobuliak66 Dec 10, 2024
3755dce
open api specs
matusdrobuliak66 Dec 10, 2024
8f264b1
Merge branch 'introduce-vip-models-pricing-4-part' of github.com:matu…
matusdrobuliak66 Dec 10, 2024
4185852
fix type
matusdrobuliak66 Dec 10, 2024
4c31cd0
fix type
matusdrobuliak66 Dec 10, 2024
530fda0
fix type
matusdrobuliak66 Dec 10, 2024
00d40bd
fix type
matusdrobuliak66 Dec 10, 2024
fa3c648
Merge branch 'master' into introduce-vip-models-pricing-4-part
matusdrobuliak66 Dec 10, 2024
12ebf32
Merge branch 'master' into introduce-vip-models-pricing-4-part
matusdrobuliak66 Dec 11, 2024
969f982
review @pcrespov
matusdrobuliak66 Dec 11, 2024
138412e
adding purchase item functionality
matusdrobuliak66 Dec 11, 2024
7e9de14
open api specs
matusdrobuliak66 Dec 11, 2024
4f1c5d6
improve error handling
matusdrobuliak66 Dec 11, 2024
26f9c57
open api specs
matusdrobuliak66 Dec 11, 2024
583b2b4
fix import
matusdrobuliak66 Dec 11, 2024
4a1008f
fix import
matusdrobuliak66 Dec 11, 2024
776806b
fix typecheck
matusdrobuliak66 Dec 11, 2024
fadfa1f
fix typecheck
matusdrobuliak66 Dec 11, 2024
356b3ee
Merge branch 'master' into introduce-vip-models-pricing-4-part
matusdrobuliak66 Dec 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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(
matusdrobuliak66 marked this conversation as resolved.
Show resolved Hide resolved
"/wallets/{wallet_id}/licensed-items-purchases",
response_model=Page[LicensedItemPurchaseGet],
tags=["wallets"],
)
async def list_wallet_licensed_items_purchases(
matusdrobuliak66 marked this conversation as resolved.
Show resolved Hide resolved
_path: Annotated[WalletsPathParams, Depends()],
_query: Annotated[as_query(LicensedItemsPurchasesListQueryParams), Depends()],
):
...


@router.get(
"/licensed-items-purchases/{licensed_item_purchase_id}",
matusdrobuliak66 marked this conversation as resolved.
Show resolved Hide resolved
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
matusdrobuliak66 marked this conversation as resolved.
Show resolved Hide resolved
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]
matusdrobuliak66 marked this conversation as resolved.
Show resolved Hide resolved
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,12 +20,40 @@ 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
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)
matusdrobuliak66 marked this conversation as resolved.
Show resolved Hide resolved
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),
matusdrobuliak66 marked this conversation as resolved.
Show resolved Hide resolved
)
# ### 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
Loading