Skip to content

Commit 138412e

Browse files
adding purchase item functionality
1 parent 969f982 commit 138412e

File tree

14 files changed

+181
-24
lines changed

14 files changed

+181
-24
lines changed

packages/models-library/src/models_library/resource_tracker.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class CreditTransactionStatus(StrAutoEnum):
4848
class CreditClassification(StrAutoEnum):
4949
ADD_WALLET_TOP_UP = auto() # user top up credits
5050
DEDUCT_SERVICE_RUN = auto() # computational/dynamic service run costs)
51+
DEDUCT_LICENSE_PURCHASE = auto()
5152

5253

5354
class PricingPlanClassification(StrAutoEnum):

packages/models-library/src/models_library/resource_tracker_licensed_items_purchases.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from .licensed_items import LicensedItemID
99
from .products import ProductName
10-
from .resource_tracker import PricingUnitCostId
10+
from .resource_tracker import PricingPlanId, PricingUnitCostId, PricingUnitId
1111
from .users import UserID
1212
from .wallets import WalletID
1313

@@ -19,12 +19,15 @@ class LicensedItemsPurchasesCreate(BaseModel):
1919
licensed_item_id: LicensedItemID
2020
wallet_id: WalletID
2121
wallet_name: str
22+
pricing_plan_id: PricingPlanId
23+
pricing_unit_id: PricingUnitId
2224
pricing_unit_cost_id: PricingUnitCostId
2325
pricing_unit_cost: Decimal
2426
start_at: datetime
2527
expire_at: datetime
2628
num_of_seats: int
2729
purchased_by_user: UserID
30+
user_email: str
2831
purchased_at: datetime
2932

3033
model_config = ConfigDict(from_attributes=True)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""add cols to licensed_items_purchases table 3
2+
3+
Revision ID: 77ac824a77ff
4+
Revises: d68b8128c23b
5+
Create Date: 2024-12-10 16:42:14.041313+00:00
6+
7+
"""
8+
import sqlalchemy as sa
9+
from alembic import op
10+
from sqlalchemy.dialects import postgresql
11+
12+
# revision identifiers, used by Alembic.
13+
revision = "77ac824a77ff"
14+
down_revision = "d68b8128c23b"
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade():
20+
# ### commands auto generated by Alembic - please adjust! ###
21+
op.add_column(
22+
"resource_tracker_credit_transactions",
23+
sa.Column(
24+
"licensed_item_purchase_id", postgresql.UUID(as_uuid=True), nullable=True
25+
),
26+
)
27+
# ### end Alembic commands ###
28+
op.execute(
29+
sa.DDL(
30+
"ALTER TYPE credittransactionclassification ADD VALUE 'DEDUCT_LICENSE_PURCHASE'"
31+
)
32+
)
33+
34+
35+
def downgrade():
36+
# ### commands auto generated by Alembic - please adjust! ###
37+
op.drop_column("resource_tracker_credit_transactions", "licensed_item_purchase_id")
38+
# ### end Alembic commands ###

packages/postgres-database/src/simcore_postgres_database/migration/versions/8fa15c4c3977_add_cols_to_licensed_items_purchases_.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""add cols to licensed_items_purchases table
22
33
Revision ID: 8fa15c4c3977
4-
Revises: 4d007819e61a
4+
Revises: 5e27063c3ac9
55
Create Date: 2024-12-10 06:42:23.319239+00:00
66
77
"""
@@ -10,7 +10,7 @@
1010

1111
# revision identifiers, used by Alembic.
1212
revision = "8fa15c4c3977"
13-
down_revision = "4d007819e61a"
13+
down_revision = "5e27063c3ac9"
1414
branch_labels = None
1515
depends_on = None
1616

packages/postgres-database/src/simcore_postgres_database/models/resource_tracker_credit_transactions.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import enum
55

66
import sqlalchemy as sa
7+
from sqlalchemy.dialects.postgresql import UUID
78

89
from ._common import (
910
NUMERIC_KWARGS,
@@ -26,6 +27,7 @@ class CreditTransactionClassification(str, enum.Enum):
2627
DEDUCT_SERVICE_RUN = (
2728
"DEDUCT_SERVICE_RUN" # computational/dynamic service run costs)
2829
)
30+
DEDUCT_LICENSE_PURCHASE = "DEDUCT_LICENSE_PURCHASE"
2931

3032

3133
resource_tracker_credit_transactions = sa.Table(
@@ -117,7 +119,13 @@ class CreditTransactionClassification(str, enum.Enum):
117119
"payment_transaction_id",
118120
sa.String,
119121
nullable=True,
120-
doc="Service run id connected with this transaction",
122+
doc="Payment transaction id connected with this transaction",
123+
),
124+
sa.Column(
125+
"licensed_item_purchase_id",
126+
UUID(as_uuid=True),
127+
nullable=True,
128+
doc="Licensed item purchase id connected with this transaction",
121129
),
122130
column_created_datetime(timezone=True),
123131
sa.Column(

services/resource-usage-tracker/src/simcore_service_resource_usage_tracker/api/rpc/_licensed_items_purchases.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,5 @@ async def create_licensed_item_purchase(
5757
app: FastAPI, *, data: LicensedItemsPurchasesCreate
5858
) -> LicensedItemPurchaseGet:
5959
return await licensed_items_purchases.create_licensed_item_purchase(
60-
db_engine=app.state.engine, data=data
60+
rabbitmq_client=app.state.rabbitmq_client, db_engine=app.state.engine, data=data
6161
)

services/resource-usage-tracker/src/simcore_service_resource_usage_tracker/models/credit_transactions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
PricingUnitId,
1212
ServiceRunId,
1313
)
14+
from models_library.resource_tracker_licensed_items_purchases import (
15+
LicensedItemPurchaseID,
16+
)
1417
from models_library.users import UserID
1518
from models_library.wallets import WalletID
1619
from pydantic import BaseModel, ConfigDict
@@ -32,6 +35,7 @@ class CreditTransactionCreate(BaseModel):
3235
payment_transaction_id: str | None
3336
created_at: datetime
3437
last_heartbeat_at: datetime
38+
licensed_item_purchase_id: LicensedItemPurchaseID | None
3539

3640

3741
class CreditTransactionCreditsUpdate(BaseModel):

services/resource-usage-tracker/src/simcore_service_resource_usage_tracker/services/credit_transactions.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ async def create_credit_transaction(
4343
transaction_classification=CreditClassification.ADD_WALLET_TOP_UP,
4444
service_run_id=None,
4545
payment_transaction_id=credit_transaction_create_body.payment_transaction_id,
46+
licensed_item_purchase_id=None,
4647
created_at=credit_transaction_create_body.created_at,
4748
last_heartbeat_at=credit_transaction_create_body.created_at,
4849
)

services/resource-usage-tracker/src/simcore_service_resource_usage_tracker/services/licensed_items_purchases.py

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,28 @@
66
LicensedItemsPurchasesPage,
77
)
88
from models_library.products import ProductName
9+
from models_library.resource_tracker import (
10+
CreditClassification,
11+
CreditTransactionStatus,
12+
)
913
from models_library.resource_tracker_licensed_items_purchases import (
1014
LicensedItemPurchaseID,
1115
LicensedItemsPurchasesCreate,
1216
)
1317
from models_library.rest_ordering import OrderBy
1418
from models_library.wallets import WalletID
19+
from simcore_postgres_database.utils_repos import transaction_context
1520
from sqlalchemy.ext.asyncio import AsyncEngine
1621

1722
from ..api.rest.dependencies import get_resource_tracker_db_engine
23+
from ..models.credit_transactions import CreditTransactionCreate
1824
from ..models.licensed_items_purchases import (
1925
CreateLicensedItemsPurchasesDB,
2026
LicensedItemsPurchasesDB,
2127
)
22-
from .modules.db import licensed_items_purchases_db
28+
from .modules.db import credit_transactions_db, licensed_items_purchases_db
29+
from .modules.rabbitmq import RabbitMQClient, get_rabbitmq_client
30+
from .utils import make_negative, sum_credit_transactions_and_publish_to_rabbitmq
2331

2432

2533
async def list_licensed_items_purchases(
@@ -94,27 +102,59 @@ async def get_licensed_item_purchase(
94102

95103

96104
async def create_licensed_item_purchase(
105+
rabbitmq_client: Annotated[RabbitMQClient, Depends(get_rabbitmq_client)],
97106
db_engine: Annotated[AsyncEngine, Depends(get_resource_tracker_db_engine)],
98107
*,
99108
data: LicensedItemsPurchasesCreate,
100109
) -> LicensedItemPurchaseGet:
101110

102-
_create_db_data = CreateLicensedItemsPurchasesDB(
103-
product_name=data.product_name,
104-
licensed_item_id=data.licensed_item_id,
105-
wallet_id=data.wallet_id,
106-
wallet_name=data.wallet_name,
107-
pricing_unit_cost_id=data.pricing_unit_cost_id,
108-
pricing_unit_cost=data.pricing_unit_cost,
109-
start_at=data.start_at,
110-
expire_at=data.expire_at,
111-
num_of_seats=data.num_of_seats,
112-
purchased_by_user=data.purchased_by_user,
113-
purchased_at=data.purchased_at,
114-
)
111+
async with transaction_context(db_engine) as conn:
112+
item_purchase_create = CreateLicensedItemsPurchasesDB(
113+
product_name=data.product_name,
114+
licensed_item_id=data.licensed_item_id,
115+
wallet_id=data.wallet_id,
116+
wallet_name=data.wallet_name,
117+
pricing_unit_cost_id=data.pricing_unit_cost_id,
118+
pricing_unit_cost=data.pricing_unit_cost,
119+
start_at=data.start_at,
120+
expire_at=data.expire_at,
121+
num_of_seats=data.num_of_seats,
122+
purchased_by_user=data.purchased_by_user,
123+
purchased_at=data.purchased_at,
124+
)
115125

116-
licensed_item_purchase_db: LicensedItemsPurchasesDB = (
117-
await licensed_items_purchases_db.create(db_engine, data=_create_db_data)
126+
licensed_item_purchase_db: LicensedItemsPurchasesDB = (
127+
await licensed_items_purchases_db.create(
128+
db_engine, connection=conn, data=item_purchase_create
129+
)
130+
)
131+
132+
# Deduct credits from credit_transactions table
133+
transaction_create = CreditTransactionCreate(
134+
product_name=data.product_name,
135+
wallet_id=data.wallet_id,
136+
wallet_name=data.wallet_name,
137+
pricing_plan_id=data.pricing_plan_id,
138+
pricing_unit_id=data.pricing_unit_id,
139+
pricing_unit_cost_id=data.pricing_unit_cost_id,
140+
user_id=data.purchased_by_user,
141+
user_email=data.user_email,
142+
osparc_credits=make_negative(data.pricing_unit_cost),
143+
transaction_status=CreditTransactionStatus.BILLED,
144+
transaction_classification=CreditClassification.DEDUCT_LICENSE_PURCHASE,
145+
service_run_id=None,
146+
payment_transaction_id=None,
147+
licensed_item_purchase_id=licensed_item_purchase_db.licensed_item_purchase_id,
148+
created_at=data.start_at,
149+
last_heartbeat_at=data.start_at,
150+
)
151+
await credit_transactions_db.create_credit_transaction(
152+
db_engine, connection=conn, data=transaction_create
153+
)
154+
155+
# Publish wallet total credits to RabbitMQ
156+
await sum_credit_transactions_and_publish_to_rabbitmq(
157+
db_engine, rabbitmq_client, data.product_name, data.wallet_id
118158
)
119159

120160
return LicensedItemPurchaseGet(

services/resource-usage-tracker/src/simcore_service_resource_usage_tracker/services/modules/db/credit_transactions_db.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ async def create_credit_transaction(
4848
transaction_classification=data.transaction_classification,
4949
service_run_id=data.service_run_id,
5050
payment_transaction_id=data.payment_transaction_id,
51+
licensed_item_purchase_id=data.licensed_item_purchase_id,
5152
created=data.created_at,
5253
last_heartbeat_at=data.last_heartbeat_at,
5354
modified=sa.func.now(),

0 commit comments

Comments
 (0)