wip reenroll

This commit is contained in:
2025-09-11 21:53:08 -03:00
parent ac07ee0101
commit e51964bc8b
13 changed files with 106 additions and 567 deletions

View File

@@ -1,5 +1,4 @@
from dataclasses import asdict, dataclass
from typing import Self, TypedDict
from typing import NotRequired, Self, TypedDict
from layercake.dateutils import now, ttl
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair
@@ -8,8 +7,16 @@ from layercake.strutils import md5_hash
from schemas import Enrollment
Tenant = TypedDict('Tenant', {'id': str, 'name': str})
Author = TypedDict('Author', {'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': NotRequired[str],
},
)
class LinkedEntity(str):
@@ -23,32 +30,16 @@ class LinkedEntity(str):
self.type = type
@dataclass(frozen=True)
class Slot:
id: str
sk: str
@property
def order_id(self) -> LinkedEntity:
idx, _ = self.sk.split('#')
return LinkedEntity(idx, 'ORDER')
class DeduplicationConflictError(Exception):
def __init__(self, *args):
super().__init__('Enrollment already exists')
class SlotDoesNotExistError(Exception):
def __init__(self, *args):
super().__init__('Slot does not exist')
def enroll(
enrollment: Enrollment,
*,
slot: Slot | None = None,
author: Author | None = None,
created_by: CreatedBy | None = None,
subscription: Subscription | None = None,
linked_entities: frozenset[LinkedEntity] = frozenset(),
deduplication_window: DeduplicationWindow | None = None,
persistence_layer: DynamoDBPersistenceLayer,
@@ -60,9 +51,6 @@ def enroll(
lock_hash = md5_hash('%s%s' % (user.id, course.id))
with persistence_layer.transact_writer() as transact:
if slot:
linked_entities = frozenset({slot.order_id}) | linked_entities
transact.put(
item={
'sk': '0',
@@ -90,46 +78,33 @@ def enroll(
}
)
if slot:
transact.put(
item={
'id': enrollment.id,
# Post-migration: uncomment the following line
# 'sk': 'METADATA#SOURCE_SLOT',
'sk': 'parent_vacancy',
'vacancy': asdict(slot),
'created_at': now_,
}
)
transact.delete(
key=KeyPair(slot.id, slot.sk),
cond_expr='attribute_exists(sk)',
exc_cls=SlotDoesNotExistError,
)
transact.put(
item={
'id': enrollment.id,
'sk': 'CANCEL_POLICY',
'created_at': now_,
}
)
if author:
if created_by:
transact.put(
item={
'id': enrollment.id,
'sk': 'author',
'user_id': author['id'],
'name': author['name'],
# Post-migration: uncomment the following line
# 'sk': 'created_by',
'user_id': created_by['id'],
'name': created_by['name'],
'created_at': now_,
},
)
if subscription:
transact.put(
item={
'id': enrollment.id,
'sk': 'METADATA#SUBSCRIPTION_COVERED',
'created_at': now_,
}
| subscription,
)
# Prevents the user from enrolling in the same course again until
# the deduplication window expires or is removed.
if deduplication_window:
offset_days = deduplication_window['offset_days']
offset_days = int(deduplication_window['offset_days'])
ttl_ = ttl(
start_dt=now_,
days=course.access_period - offset_days,