fix enroll and reenroll relationship

This commit is contained in:
2025-10-14 18:11:24 -03:00
parent 466ff824dd
commit a7e5a0a528
20 changed files with 125 additions and 89 deletions

View File

@@ -1,4 +1,7 @@
from abc import ABC
from dataclasses import dataclass
from datetime import timedelta
from enum import Enum
from typing import NotRequired, Self, TypedDict
from layercake.dateutils import now, ttl
@@ -32,15 +35,16 @@ Subscription = TypedDict(
)
class LinkedEntity(str):
def __new__(cls, id: str, type: str) -> Self:
return super().__new__(cls, '#'.join([type.lower(), id]))
class Kind(str, Enum):
ORDER = 'ORDER'
ENROLLMENT = 'ENROLLMENT'
def __init__(self, id: str, type: str) -> None:
# __init__ is used to store the parameters for later reference.
# For immutable types like str, __init__ cannot change the instance's value.
self.id = id
self.type = type
@dataclass(frozen=True)
class LinkedEntity(ABC):
id: str
kind: Kind
table_name: str | None = None
class DeduplicationConflictError(Exception):
@@ -76,29 +80,27 @@ def enroll(
)
# Relationships between this enrollment and its related entities
for parent_entity in linked_entities:
perent_id = parent_entity.id
entity_sk = f'LINKED_ENTITIES#{parent_entity.type}'
keyprefix = parent_entity.type.lower()
for entity in linked_entities:
# Parent knows the child
transact.put(
item={
'id': perent_id,
'sk': f'{entity_sk}#CHILD',
'id': entity.id,
'sk': f'LINKED_ENTITIES#{entity.kind.value}#CHILD',
'created_at': now_,
f'{keyprefix}_id': enrollment.id,
'enrollment_id': enrollment.id,
},
cond_expr='attribute_not_exists(sk)',
table_name=entity.table_name,
)
keyprefix = entity.kind.value.lower()
# Child knows the parent
transact.put(
item={
'id': enrollment.id,
'sk': f'{entity_sk}#PARENT',
'sk': f'LINKED_ENTITIES#{entity.kind.value}#PARENT',
'created_at': now_,
f'{keyprefix}_id': perent_id,
f'{keyprefix}_id': entity.id,
},
cond_expr='attribute_not_exists(sk)',
)

View File

@@ -81,6 +81,7 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
class Course:
id: str
name: str
access_period: int
def _get_courses(ids: set) -> tuple[Course, ...]:
@@ -93,6 +94,7 @@ def _get_courses(ids: set) -> tuple[Course, ...]:
Course(
id=idx,
name=obj['name'],
access_period=obj['access_period'],
)
for idx, obj in result.items()
)

View File

@@ -18,7 +18,11 @@ from layercake.dynamodb import (
from boto3clients import dynamodb_client
from config import COURSE_TABLE, ENROLLMENT_TABLE, ORDER_TABLE
from enrollment import LinkedEntity, enroll
from enrollment import (
Kind,
LinkedEntity,
enroll,
)
from schemas import Course, Enrollment, User
logger = Logger(__name__)
@@ -89,7 +93,15 @@ def _handler(record: Course, context: dict) -> Enrollment:
enrollment,
persistence_layer=enrollment_layer,
deduplication_window={'offset_days': 90},
linked_entities=frozenset({LinkedEntity(context['order_id'], 'ORDER')}),
linked_entities=frozenset(
{
LinkedEntity(
id=context['order_id'],
kind=Kind.ORDER,
table_name=ORDER_TABLE,
),
}
),
)
return enrollment

View File

@@ -56,6 +56,9 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
)
try:
if 's3_uri' not in cert:
raise ValueError('Template URI is missing')
# Send template URI and data to Paperforge API to generate a PDF
r = requests.post(
PAPERFORGE_API,
@@ -79,10 +82,11 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
),
},
),
timeout=5,
)
r.raise_for_status()
object_key = f'issuedcerts/{enrollment_id}.pdf'
object_key = f'certs/{enrollment_id}.pdf'
s3_uri = f's3://{BUCKET_NAME}/{object_key}'
s3_client.put_object(
@@ -93,10 +97,10 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
)
logger.debug(f'PDF uploaded successfully to {s3_uri}')
except KeyError:
except ValueError as exc:
# PDF generation fails if template URI is missing
s3_uri = None
logger.debug('Template URI is missing')
logger.exception(exc)
except requests.exceptions.RequestException as exc:
logger.exception(exc)
raise

View File

@@ -10,7 +10,7 @@ from layercake.dynamodb import DynamoDBPersistenceLayer, SortKey, TransactKey
from boto3clients import dynamodb_client
from config import ENROLLMENT_TABLE
from enrollment import LinkedEntity, enroll
from enrollment import Kind, LinkedEntity, enroll
from schemas import Course, Enrollment, User
logger = Logger(__name__)
@@ -52,7 +52,12 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
'offset_days': metadata['dedup_window_offset_days'],
},
linked_entities=frozenset(
{LinkedEntity(new_image['id'], 'ENROLLMENT')},
{
LinkedEntity(
id=new_image['id'],
kind=Kind.ENROLLMENT,
),
},
),
persistence_layer=dyn,
)

View File

@@ -29,8 +29,7 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
pk=old_image['id'],
sk='0',
),
update_expr='SET access_expired = :true, \
updated_at = :now',
update_expr='SET access_expired = :true, updated_at = :now',
expr_attr_values={
':true': True,
':now': now_,