add tests to canceled enrollment or scheduled with seat
This commit is contained in:
@@ -343,6 +343,7 @@ def _enroll_later(enrollment: Enrollment, context: Context):
|
||||
'user': user.model_dump(),
|
||||
'course': course.model_dump(),
|
||||
'org_name': org.name,
|
||||
'enrollment_id': enrollment.id,
|
||||
'created_by': {
|
||||
'id': created_by.id,
|
||||
'name': created_by.name,
|
||||
|
||||
@@ -162,9 +162,9 @@ const statuses: Record<string, { icon: LucideIcon; color?: string }> = {
|
||||
|
||||
const labels: Record<string, string> = {
|
||||
PENDING: 'Aguardando',
|
||||
EXECUTED: 'Executado',
|
||||
SCHEDULED: 'Agendado',
|
||||
ROLLBACK: 'Revogado'
|
||||
EXECUTED: 'Executada',
|
||||
SCHEDULED: 'Agendada',
|
||||
ROLLBACK: 'Revogada'
|
||||
}
|
||||
|
||||
function Status({ status: s }: { status: string }) {
|
||||
|
||||
@@ -38,7 +38,7 @@ class Course(BaseModel):
|
||||
|
||||
|
||||
class Enrollment(BaseModel):
|
||||
id: UUID4 | str = Field(default_factory=uuid4)
|
||||
id: UUID4 | str
|
||||
user: User
|
||||
course: Course
|
||||
progress: int = Field(default=0, ge=0, le=100)
|
||||
@@ -61,7 +61,7 @@ Org = TypedDict('Org', {'org_id': str, 'name': str})
|
||||
|
||||
CreatedBy = TypedDict('CreatedBy', {'id': str, 'name': str})
|
||||
|
||||
Seat = TypedDict('Seat', {'order_id': str})
|
||||
Seat = TypedDict('Seat', {'order_id': str, 'enrollment_id': NotRequired[str]})
|
||||
|
||||
DeduplicationWindow = TypedDict('DeduplicationWindow', {'offset_days': int})
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from uuid import uuid4
|
||||
|
||||
from aws_lambda_powertools import Logger
|
||||
from aws_lambda_powertools.utilities.data_classes import (
|
||||
EventBridgeEvent,
|
||||
@@ -84,6 +86,7 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
||||
|
||||
def _handler(course: Course, context: dict) -> Enrollment:
|
||||
enrollment = Enrollment(
|
||||
id=uuid4(),
|
||||
user=context['user'],
|
||||
course=course,
|
||||
)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from datetime import datetime
|
||||
from uuid import uuid4
|
||||
|
||||
from aws_lambda_powertools import Logger
|
||||
from aws_lambda_powertools.utilities.data_classes import (
|
||||
@@ -37,8 +38,9 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
||||
offset_days = old_image.get('dedup_window_offset_days')
|
||||
billing_day = old_image.get('subscription_billing_day')
|
||||
created_by = old_image.get('created_by')
|
||||
seat: Seat | None = old_image.get('seat')
|
||||
seat: Seat = old_image.get('seat', {})
|
||||
enrollment = Enrollment(
|
||||
id=old_image['enrollment_id'],
|
||||
course=old_image['course'],
|
||||
user=old_image['user'],
|
||||
)
|
||||
|
||||
@@ -37,7 +37,6 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
||||
rollback_at = :now, \
|
||||
reason = :reason',
|
||||
cond_expr='attribute_exists(sk) AND #status = :executed',
|
||||
table_name=ORDER_TABLE,
|
||||
expr_attr_names={
|
||||
'#status': 'status',
|
||||
},
|
||||
@@ -47,6 +46,7 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
||||
':reason': 'CANCELLATION',
|
||||
':now': now_,
|
||||
},
|
||||
table_name=ORDER_TABLE,
|
||||
)
|
||||
transact.put(
|
||||
item={
|
||||
@@ -0,0 +1,59 @@
|
||||
from uuid import uuid4
|
||||
|
||||
from aws_lambda_powertools import Logger
|
||||
from aws_lambda_powertools.utilities.data_classes import (
|
||||
EventBridgeEvent,
|
||||
event_source,
|
||||
)
|
||||
from aws_lambda_powertools.utilities.typing import LambdaContext
|
||||
from layercake.dateutils import now
|
||||
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair
|
||||
|
||||
from boto3clients import dynamodb_client
|
||||
from config import ENROLLMENT_TABLE, ORDER_TABLE
|
||||
|
||||
logger = Logger(__name__)
|
||||
dyn = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client)
|
||||
|
||||
|
||||
@event_source(data_class=EventBridgeEvent)
|
||||
@logger.inject_lambda_context
|
||||
def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
||||
old_image = event.detail['old_image']
|
||||
order_id = old_image['seat']['order_id']
|
||||
enrollment_id = old_image['enrollment_id']
|
||||
*_, org_id = old_image['id'].split('#')
|
||||
now_ = now()
|
||||
|
||||
with dyn.transact_writer() as transact:
|
||||
transact.update(
|
||||
key=KeyPair(
|
||||
pk=order_id,
|
||||
sk=f'ENROLLMENT#{enrollment_id}',
|
||||
table_name=ORDER_TABLE,
|
||||
),
|
||||
cond_expr='attribute_exists(sk) AND #status = :scheduled',
|
||||
update_expr='SET #status = :rollback, \
|
||||
rollback_at = :now, \
|
||||
reason = :reason',
|
||||
expr_attr_names={
|
||||
'#status': 'status',
|
||||
},
|
||||
expr_attr_values={
|
||||
':rollback': 'ROLLBACK',
|
||||
':scheduled': 'SCHEDULED',
|
||||
':reason': 'CANCELLATION',
|
||||
':now': now_,
|
||||
},
|
||||
table_name=ORDER_TABLE,
|
||||
)
|
||||
transact.put(
|
||||
item={
|
||||
'id': f'SEAT#ORG#{org_id}',
|
||||
'sk': f'ORDER#{order_id}#ENROLLMENT#{uuid4()}',
|
||||
'course': old_image['course'],
|
||||
'created_at': now_,
|
||||
}
|
||||
)
|
||||
|
||||
return True
|
||||
@@ -211,11 +211,14 @@ Resources:
|
||||
keys:
|
||||
id:
|
||||
- prefix: SCHEDULED#ORG#
|
||||
old_image:
|
||||
enrollment_id:
|
||||
- exists: true
|
||||
|
||||
EventReenrollIfFailedFunction:
|
||||
EventReenrollOnFailedFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
Handler: events.reenroll_if_failed.lambda_handler
|
||||
Handler: events.reenroll_on_failed.lambda_handler
|
||||
LoggingConfig:
|
||||
LogGroup: !Ref EventLog
|
||||
Policies:
|
||||
@@ -240,10 +243,10 @@ Resources:
|
||||
old_image:
|
||||
status: [IN_PROGRESS]
|
||||
|
||||
EventRestoreSeatFunction:
|
||||
EventRestoreSeatOnCanceledFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
Handler: events.restore_seat.lambda_handler
|
||||
Handler: events.restore_seat_on_canceled.lambda_handler
|
||||
LoggingConfig:
|
||||
LogGroup: !Ref EventLog
|
||||
Policies:
|
||||
@@ -265,6 +268,32 @@ Resources:
|
||||
order_id:
|
||||
- exists: true
|
||||
|
||||
EventRestoreSeatOnScheduledCanceledFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
Handler: events.restore_seat_on_scheduled_canceled.lambda_handler
|
||||
LoggingConfig:
|
||||
LogGroup: !Ref EventLog
|
||||
Policies:
|
||||
- DynamoDBCrudPolicy:
|
||||
TableName: !Ref EnrollmentTable
|
||||
- DynamoDBCrudPolicy:
|
||||
TableName: !Ref OrderTable
|
||||
Events:
|
||||
DynamoDBEvent:
|
||||
Type: EventBridgeRule
|
||||
Properties:
|
||||
Pattern:
|
||||
resources: [!Ref EnrollmentTable]
|
||||
detail-type: [REMOVE]
|
||||
detail:
|
||||
old_image:
|
||||
id:
|
||||
- prefix: SCHEDULED#ORG#
|
||||
seat:
|
||||
order_id:
|
||||
- exists: true
|
||||
|
||||
# DEPRECATED
|
||||
EventAllocateSlotsFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from aws_lambda_powertools.utilities.typing import LambdaContext
|
||||
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair
|
||||
|
||||
import events.reenroll_if_failed as app
|
||||
import events.reenroll_on_failed as app
|
||||
|
||||
|
||||
def test_reenroll_custom_dedup_window(
|
||||
@@ -0,0 +1,20 @@
|
||||
from aws_lambda_powertools.utilities.typing import LambdaContext
|
||||
from layercake.dynamodb import DynamoDBPersistenceLayer
|
||||
|
||||
import events.restore_seat_on_canceled as app
|
||||
|
||||
|
||||
def test_restore_seat_on_canceled(
|
||||
dynamodb_seeds,
|
||||
dynamodb_persistence_layer: DynamoDBPersistenceLayer,
|
||||
lambda_context: LambdaContext,
|
||||
):
|
||||
event = {
|
||||
'detail': {
|
||||
'old_image': {
|
||||
'id': '',
|
||||
'seat': {'order_id': ''},
|
||||
},
|
||||
}
|
||||
}
|
||||
assert app.lambda_handler(event, lambda_context) # type: ignore
|
||||
@@ -0,0 +1,45 @@
|
||||
from aws_lambda_powertools.utilities.typing import LambdaContext
|
||||
from layercake.dynamodb import DynamoDBPersistenceLayer, PartitionKey
|
||||
|
||||
import events.restore_seat_on_scheduled_canceled as app
|
||||
|
||||
|
||||
def test_restore_seat_on_scheduled_canceled(
|
||||
dynamodb_seeds,
|
||||
dynamodb_persistence_layer: DynamoDBPersistenceLayer,
|
||||
lambda_context: LambdaContext,
|
||||
):
|
||||
org_id = 'cJtK9SsnJhKPyxESe7g3DG'
|
||||
event = {
|
||||
'detail': {
|
||||
'old_image': {
|
||||
'seat': {
|
||||
'order_id': 'f1ecaa69-8054-4cdc-ba13-a6680e18df21',
|
||||
},
|
||||
'enrollment_id': '19c0aa75-473e-4d4c-822d-2d42d46d2167',
|
||||
'course': {
|
||||
'name': 'Gestão da Cultura de Segurança',
|
||||
'id': 'c19cd7ee-3cc8-4f9c-95ff-dad7993f49b1',
|
||||
'access_period': 365,
|
||||
},
|
||||
'org_name': 'Beta Educação',
|
||||
'user': {
|
||||
'name': 'Sérgio Rafael de Siqueira',
|
||||
'cpf': '07879819908',
|
||||
'id': '5OxmMjL-ujoR5IMGegQz',
|
||||
'email': 'sergio@somosbeta.com.br',
|
||||
},
|
||||
'ttl': 1769828760,
|
||||
'sk': '2026-01-31T00:00:00-03:06#addf2b5f2cbf30080df8582e6a95eb96',
|
||||
'id': f'SCHEDULED#ORG#{org_id}',
|
||||
'scheduled_at': '2026-01-25T14:58:09.772660-03:00',
|
||||
'created_by': {
|
||||
'name': 'Sérgio Rafael de Siqueira',
|
||||
'id': '5OxmMjL-ujoR5IMGegQz',
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
assert app.lambda_handler(event, lambda_context) # type: ignore
|
||||
r = dynamodb_persistence_layer.collection.query(PartitionKey(f'SEAT#ORG#{org_id}'))
|
||||
assert len(r['items'])
|
||||
@@ -47,4 +47,7 @@
|
||||
{"id": "00237409-9384-4692-9be5-b4443a41e1c4", "sk": "admins#1234", "email": "sergio@somosbeta.com.br", "name": "Sérgio R Siqueira"}
|
||||
|
||||
// file: tests/events/test_reenroll_if_failed.py::test_reenroll_custom_dedup_window
|
||||
{"id": "SUBSCRIPTION", "sk": "ORG#123"}
|
||||
{"id": "SUBSCRIPTION", "sk": "ORG#123"}
|
||||
|
||||
// file: tests/events/test_restore_seat_on_scheduled_canceled.py
|
||||
{"id": "f1ecaa69-8054-4cdc-ba13-a6680e18df21", "sk": "ENROLLMENT#19c0aa75-473e-4d4c-822d-2d42d46d2167", "status": "SCHEDULED"}
|
||||
@@ -352,6 +352,7 @@ def _enroll_later(enrollment: Enrollment, context: Context) -> None:
|
||||
'user': user.model_dump(),
|
||||
'course': course.model_dump(),
|
||||
'org_name': org.name,
|
||||
'enrollment_id': enrollment.id,
|
||||
'created_by': {
|
||||
'id': created_by['user_id'],
|
||||
'name': created_by['name'],
|
||||
|
||||
Reference in New Issue
Block a user