- {seats.map(({ course, quantity }) => {
+ {seats.map(({ course, quantity }, idx) => {
return (
- -
+
-
{quantity}x {course.name}
)
diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.payments.$id._index/route.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.payments.$id._index/route.tsx
index 7136e29..076bb22 100644
--- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.payments.$id._index/route.tsx
+++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.payments.$id._index/route.tsx
@@ -110,6 +110,7 @@ type Item = {
type User = {
id: string
name: string
+ email: string
}
type Invoice = {
@@ -137,12 +138,13 @@ type Course = {
}
export type Enrollment = {
- status: 'PENDING' | 'EXECUTED' | 'ROLLBACK'
- user: { id: string; name: string; email: string }
+ status: 'PENDING' | 'EXECUTED' | 'ROLLBACK' | 'SCHEDULED'
+ user: User
course: Course
executed_at?: string
rollback_at?: string
scheduled_at?: string
+ reason?: string
}
export type Seat = {
@@ -213,7 +215,7 @@ export default function Route({ loaderData: { order } }: Route.ComponentProps) {
useEffect(() => {
reset()
}, [])
- console.log(seats)
+
return (
diff --git a/enrollments-events/app/events/restore_seat_on_scheduled_canceled.py b/enrollments-events/app/events/restore_seat_on_scheduled_canceled.py
index ee03b5c..d780e2e 100644
--- a/enrollments-events/app/events/restore_seat_on_scheduled_canceled.py
+++ b/enrollments-events/app/events/restore_seat_on_scheduled_canceled.py
@@ -42,7 +42,7 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
expr_attr_values={
':rollback': 'ROLLBACK',
':scheduled': 'SCHEDULED',
- ':reason': 'CANCELLATION',
+ ':reason': 'UNSCHEDULED',
':now': now_,
},
table_name=ORDER_TABLE,
diff --git a/orders-events/app/events/start_fulfillment.py b/orders-events/app/events/start_fulfillment.py
index 3a4a81c..bc3b48f 100644
--- a/orders-events/app/events/start_fulfillment.py
+++ b/orders-events/app/events/start_fulfillment.py
@@ -19,7 +19,7 @@ from layercake.dynamodb import (
TransactKey,
)
from layercake.strutils import md5_hash
-from pydantic import UUID4, BaseModel, BeforeValidator, Field, FutureDate
+from pydantic import UUID4, BaseModel, BeforeValidator, Field
from boto3clients import dynamodb_client
from config import (
@@ -42,6 +42,9 @@ class DeduplicationConflictError(Exception): ...
class EnrollmentConflictError(Exception): ...
+class DeadlineExceededError(Exception): ...
+
+
class User(BaseModel):
id: str
name: str
@@ -200,9 +203,12 @@ def _get_courses(ids: set[str]) -> tuple[Course, ...]:
def _friendly_reason(reason: str) -> str:
- if reason == 'DeduplicationConflictError':
- return 'DEDUPLICATION'
- return 'CONFLICT'
+ reasons = {
+ 'DeduplicationConflictError': 'DEDUPLICATION',
+ 'DeadlineExceededError': 'DEADLINE',
+ }
+
+ return reasons.get(reason, 'CONFLICT')
CreatedBy = TypedDict('CreatedBy', {'user_id': str, 'name': str})
@@ -341,6 +347,9 @@ def _enroll_later(enrollment: Enrollment, context: Context) -> None:
scheduled_for = _date_to_midnight(enrollment.scheduled_for) # type: ignore
lock_hash = md5_hash(f'{user.id}{course.id}')
+ if now_ > scheduled_for:
+ raise DeadlineExceededError('Deadline exceeded')
+
with dyn.transact_writer(table_name=ENROLLMENT_TABLE) as transact:
pk = f'SCHEDULED#ORG#{org.id}'
sk = f'{scheduled_for.isoformat()}#{lock_hash}'