add enroll to subscribed

This commit is contained in:
2025-12-08 16:48:31 -03:00
parent 1ff2634bc0
commit 93d96486ff
11 changed files with 148 additions and 108 deletions

View File

@@ -1,37 +1,74 @@
from abc import ABC
from dataclasses import dataclass
from datetime import timedelta
from datetime import datetime, timedelta
from enum import Enum
from typing import TypedDict
from typing import Any, Literal, TypedDict
from uuid import uuid4
from layercake.dateutils import now, ttl
from layercake.dynamodb import DynamoDBPersistenceLayer
from layercake.extra_types import CpfStr, NameStr
from layercake.strutils import md5_hash
from pydantic import (
UUID4,
BaseModel,
ConfigDict,
EmailStr,
Field,
)
from typing_extensions import NotRequired
from config import DEDUP_WINDOW_OFFSET_DAYS
from schemas import Enrollment
Org = TypedDict(
'Org',
{
'org_id': str,
'name': str,
},
)
DeduplicationWindow = TypedDict(
'DeduplicationWindow',
{
'offset_days': int,
},
)
class User(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
id: UUID4 | str
name: NameStr
email: EmailStr
email_verified: bool = False
cpf: CpfStr | None = None
class Course(BaseModel):
id: UUID4 | str
name: str
access_period: int = 90 # 3 months
class Enrollment(BaseModel):
id: UUID4 | str = Field(default_factory=uuid4)
user: User
course: Course
progress: int = Field(default=0, ge=0, le=100)
status: Literal['PENDING'] = 'PENDING'
def model_dump(
self,
exclude=None,
*args,
**kwargs,
) -> dict[str, Any]:
return super().model_dump(
exclude={'user': {'email_verified'}},
*args,
**kwargs,
)
Org = TypedDict('Org', {'org_id': str, 'name': str})
CreatedBy = TypedDict('CreatedBy', {'id': str, 'name': str})
DeduplicationWindow = TypedDict('DeduplicationWindow', {'offset_days': int})
Subscription = TypedDict(
'Subscription',
{
'org_id': str,
'billing_day': int,
'billing_period': str,
'billing_period': NotRequired[str],
},
)
@@ -58,6 +95,8 @@ def enroll(
*,
org: Org | None = None,
subscription: Subscription | None = None,
created_by: CreatedBy | None = None,
scheduled_at: datetime | None = None,
linked_entities: frozenset[LinkedEntity] = frozenset(),
deduplication_window: DeduplicationWindow | None = None,
persistence_layer: DynamoDBPersistenceLayer,
@@ -65,7 +104,7 @@ def enroll(
now_ = now()
user = enrollment.user
course = enrollment.course
lock_hash = md5_hash('%s%s' % (user.id, course.id))
lock_hash = md5_hash(f'{user.id}{course.id}')
access_expires_at = now_ + timedelta(days=course.access_period)
with persistence_layer.transact_writer() as transact:
@@ -76,8 +115,9 @@ def enroll(
'access_expires_at': access_expires_at,
**enrollment.model_dump(),
}
| ({'org_id': org['org_id']} if org else {})
| ({'subscription_covered': True} if subscription else {})
| ({'org_id': org['org_id']} if org else {}),
| ({'scheduled_at': scheduled_at} if scheduled_at else {})
)
# Relationships between this enrollment and its related entities
@@ -123,6 +163,16 @@ def enroll(
| subscription,
)
if created_by:
transact.put(
item={
'id': enrollment.id,
'sk': 'CREATED_BY',
'created_by': created_by,
'created_at': now_,
}
)
# Prevents the user from enrolling in the same course again until
# the deduplication window expires or is removed.
offset_days = (