Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
@@ -1,7 +1,12 @@
from datetime import datetime
from typing import NamedTuple
from typing import NamedTuple, Self

from models_library.licensed_items import LicensedItemID, LicensedResourceType
from common_library.dict_tools import remap_keys
from models_library.licensed_items import (
LicensedItemDB,
LicensedItemID,
LicensedResourceType,
)
from models_library.resource_tracker import PricingPlanId
from pydantic import ConfigDict, PositiveInt

Expand All @@ -10,12 +15,16 @@

class LicensedItemGet(OutputSchema):
licensed_item_id: LicensedItemID

name: str
license_key: str | None
licensed_resource_type: LicensedResourceType

pricing_plan_id: PricingPlanId

created_at: datetime
modified_at: datetime

model_config = ConfigDict(
json_schema_extra={
"examples": [
Expand All @@ -32,6 +41,29 @@ class LicensedItemGet(OutputSchema):
}
)

@classmethod
def from_domain_model(cls, licensed_item_db: LicensedItemDB) -> Self:
return cls.model_validate(
remap_keys(
licensed_item_db.model_dump(
include={
"licensed_item_id",
"licensed_resource_name",
"licensed_resource_type",
"license_key",
"pricing_plan_id",
"created",
"modified",
}
),
{
"licensed_resource_name": "name",
"created": "created_at",
"modified": "modified_at",
},
)
)


class LicensedItemGetPage(NamedTuple):
items: list[LicensedItemGet]
Expand Down
32 changes: 17 additions & 15 deletions packages/models-library/src/models_library/licensed_items.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from datetime import datetime
from enum import auto
from typing import TypeAlias
from typing import Any, TypeAlias
from uuid import UUID

from pydantic import BaseModel, ConfigDict, Field
from pydantic import BaseModel, ConfigDict

from .products import ProductName
from .resource_tracker import PricingPlanId
Expand All @@ -23,23 +23,25 @@ class LicensedResourceType(StrAutoEnum):

class LicensedItemDB(BaseModel):
licensed_item_id: LicensedItemID
name: str
license_key: str | None

licensed_resource_name: str
licensed_resource_type: LicensedResourceType
pricing_plan_id: PricingPlanId
product_name: ProductName
created: datetime = Field(
...,
description="Timestamp on creation",
)
modified: datetime = Field(
...,
description="Timestamp of last modification",
)
# ----
licensed_resource_data: dict[str, Any] | None

pricing_plan_id: PricingPlanId | None
product_name: ProductName | None

# states
created: datetime
modified: datetime
trashed: datetime | None

model_config = ConfigDict(from_attributes=True)


class LicensedItemUpdateDB(BaseModel):
name: str | None = None
licensed_resource_name: str | None = None
pricing_plan_id: PricingPlanId | None = None

trash: bool | None = None
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
"""add data to licensed_items

Revision ID: 4f31760a63ba
Revises: 1bc517536e0a
Create Date: 2025-01-29 16:51:16.453069+00:00

"""
import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = "4f31760a63ba"
down_revision = "1bc517536e0a"
branch_labels = None
depends_on = None


def upgrade():

with op.batch_alter_table("licensed_items") as batch_op:
batch_op.alter_column(
"name",
new_column_name="licensed_resource_name",
existing_type=sa.String(),
nullable=False,
)
batch_op.alter_column(
"pricing_plan_id",
existing_type=sa.Integer(),
nullable=True,
)
batch_op.alter_column(
"product_name",
existing_type=sa.String(),
nullable=True,
)

# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"licensed_items",
sa.Column(
"licensed_resource_data",
postgresql.JSONB(astext_type=sa.Text()),
nullable=True,
),
)
op.add_column(
"licensed_items",
sa.Column(
"trashed",
sa.DateTime(timezone=True),
nullable=True,
comment="The date and time when the licensed_item was marked as trashed. Null if the licensed_item has not been trashed [default].",
),
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("licensed_items", "trashed")
op.drop_column("licensed_items", "licensed_resource_data")
# ### end Alembic commands ###

# Delete rows with null values in pricing_plan_id and product_name
op.execute(
sa.DDL(
"""
DELETE FROM licensed_items
WHERE pricing_plan_id IS NULL OR product_name IS NULL;
"""
)
)
print(
"Warning: Rows with null values in pricing_plan_id or product_name have been deleted."
)

with op.batch_alter_table("licensed_items") as batch_op:

batch_op.alter_column(
"product_name",
existing_type=sa.String(),
nullable=False,
)
batch_op.alter_column(
"pricing_plan_id",
existing_type=sa.Integer(),
nullable=False,
)
batch_op.alter_column(
"licensed_resource_name",
new_column_name="name",
existing_type=sa.String(),
nullable=False,
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@
import enum

import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.dialects import postgresql

from ._common import RefActions, column_created_datetime, column_modified_datetime
from ._common import (
RefActions,
column_created_datetime,
column_modified_datetime,
column_trashed_datetime,
)
from .base import metadata


Expand All @@ -19,21 +24,28 @@ class LicensedResourceType(str, enum.Enum):
metadata,
sa.Column(
"licensed_item_id",
UUID(as_uuid=True),
postgresql.UUID(as_uuid=True),
nullable=False,
primary_key=True,
server_default=sa.text("gen_random_uuid()"),
),
sa.Column(
"name",
"licensed_resource_name",
sa.String,
nullable=False,
doc="Resource name identifier",
),
sa.Column(
"licensed_resource_type",
sa.Enum(LicensedResourceType),
nullable=False,
doc="Item type, ex. VIP_MODEL",
doc="Resource type, ex. VIP_MODEL",
),
sa.Column(
"licensed_resource_data",
postgresql.JSONB,
nullable=True,
doc="Resource metadata. Used for read-only purposes",
),
sa.Column(
"pricing_plan_id",
Expand All @@ -44,7 +56,7 @@ class LicensedResourceType(str, enum.Enum):
onupdate=RefActions.CASCADE,
ondelete=RefActions.RESTRICT,
),
nullable=False,
nullable=True,
),
sa.Column(
"product_name",
Expand All @@ -55,15 +67,17 @@ class LicensedResourceType(str, enum.Enum):
ondelete=RefActions.CASCADE,
name="fk_resource_tracker_license_packages_product_name",
),
nullable=False,
doc="Product name",
nullable=True,
doc="Product name identifier. If None, then the item is not exposed",
),
sa.Column(
"license_key",
sa.String,
nullable=True,
doc="Purpose: Acts as a mapping key to the internal license server. Usage: The Sim4Life base applications use this key to check out a seat from the internal license server.",
doc="Purpose: Acts as a mapping key to the internal license server."
"Usage: The Sim4Life base applications use this key to check out a seat from the internal license server.",
),
column_created_datetime(timezone=True),
column_modified_datetime(timezone=True),
column_trashed_datetime("licensed_item"),
)
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ def _enable_only_if_dev_features_allowed(cls, v, info: ValidationInfo):

return (
None
if info.field_name and is_nullable(cls.model_fields[info.field_name])
if info.field_name and is_nullable(dict(cls.model_fields)[info.field_name])
else False
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def convert_to_environ_vars( # noqa: C901, PLR0915, PLR0912
def _set_if_disabled(field_name, section):
# Assumes that by default is enabled
enabled = section.get("enabled", True)
field = ApplicationSettings.model_fields[field_name]
field = dict(ApplicationSettings.model_fields)[field_name]
if not enabled:
envs[field_name] = "null" if is_nullable(field) else "0"
elif get_type(field) == bool:
Expand Down
Loading
Loading