add set as expired
This commit is contained in:
@@ -54,7 +54,7 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
||||
sesv2_client=sesv2_client,
|
||||
event={
|
||||
'id': old_image['id'],
|
||||
'sk': 'SCHEDULE#REMINDER_NO_ACCESS_AFTER_3_DAYS',
|
||||
'sk': 'SCHEDULE#REMINDER_ACCESS_PERIOD_BEFORE_30_DAYS',
|
||||
},
|
||||
dynamodb_persistence_layer=enrollment_layer,
|
||||
)
|
||||
|
||||
@@ -55,7 +55,7 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
||||
sesv2_client=sesv2_client,
|
||||
event={
|
||||
'id': old_image['id'],
|
||||
'sk': 'SCHEDULE#REMINDER_NO_ACCESS_AFTER_3_DAYS',
|
||||
'sk': 'SCHEDULE#REMINDER_CERT_EXPIRATION_BEFORE_30_DAYS',
|
||||
},
|
||||
dynamodb_persistence_layer=enrollment_layer,
|
||||
)
|
||||
|
||||
@@ -17,6 +17,7 @@ from .email_ import send_email
|
||||
logger = Logger(__name__)
|
||||
enrollment_layer = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client)
|
||||
|
||||
|
||||
SUBJECT = 'Seu curso de {course} está esperando por você na EDUSEG®'
|
||||
MESSAGE = """
|
||||
Oi {first_name}, tudo bem?<br/><br/>
|
||||
|
||||
@@ -4,7 +4,7 @@ from aws_lambda_powertools.utilities.data_classes import (
|
||||
event_source,
|
||||
)
|
||||
from aws_lambda_powertools.utilities.typing import LambdaContext
|
||||
from layercake.dynamodb import DynamoDBPersistenceLayer
|
||||
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair, SortKey, TransactKey
|
||||
|
||||
from boto3clients import dynamodb_client
|
||||
from config import (
|
||||
@@ -19,5 +19,10 @@ enrollment_layer = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client)
|
||||
@logger.inject_lambda_context
|
||||
def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
||||
new_image = event.detail['new_image']
|
||||
enrollment = enrollment_layer.collection.get_items(
|
||||
TransactKey(pk=new_image['id'])
|
||||
+ SortKey('METADATA#DEDUPLICATION_WINDOW', rename_key='DEDUPLICATION_WINDOW')
|
||||
+ SortKey('METADATA#COURSE', rename_key='COURSE'),
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
@@ -22,11 +22,10 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
||||
subscription = enrollment_layer.collection.get_items(
|
||||
TransactKey(new_image['id'])
|
||||
+ SortKey('METADATA#SUBSCRIPTION_COVERED')
|
||||
+ SortKey('author')
|
||||
+ SortKey('tenant')
|
||||
# Post-migration: uncommet the following lines
|
||||
# + SortKey('CREATED_BY')
|
||||
# + SortKey('ORG')
|
||||
+ SortKey('author', rename_key='CREATED_BY')
|
||||
+ SortKey('tenant', rename_key='ORG')
|
||||
+ SortKey('CREATED_BY')
|
||||
+ SortKey('ORG')
|
||||
)
|
||||
|
||||
with enrollment_layer.transact_writer() as transact_writer:
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from aws_lambda_powertools import Logger
|
||||
from aws_lambda_powertools.utilities.data_classes import (
|
||||
EventBridgeEvent,
|
||||
@@ -15,7 +13,7 @@ from config import (
|
||||
)
|
||||
|
||||
logger = Logger(__name__)
|
||||
enrollment_layer = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client)
|
||||
dyn = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client)
|
||||
|
||||
|
||||
@event_source(data_class=EventBridgeEvent)
|
||||
@@ -27,7 +25,7 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
||||
course = new_image['course']
|
||||
now_ = now()
|
||||
|
||||
with enrollment_layer.transact_writer() as transact:
|
||||
with dyn.transact_writer() as transact:
|
||||
transact.put(
|
||||
item={
|
||||
'id': enrollment_id,
|
||||
@@ -48,22 +46,19 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
||||
item={
|
||||
'id': enrollment_id,
|
||||
'sk': 'SCHEDULE#SET_AS_EXPIRED',
|
||||
'name': user.name,
|
||||
'email': user.email,
|
||||
'course': course.name,
|
||||
'created_at': now_,
|
||||
'ttl': ttl(start_dt=now_ + timedelta(days=course.access_period)),
|
||||
'ttl': ttl(start_dt=now_, days=course.access_period),
|
||||
},
|
||||
)
|
||||
transact.put(
|
||||
item={
|
||||
'id': enrollment_id,
|
||||
'sk': 'REMINDER_ACCESS_PERIOD_BEFORE_15_DAYS',
|
||||
'sk': 'SCHEDULE#REMINDER_CERT_EXPIRATION_BEFORE_30_DAYS',
|
||||
'name': user.name,
|
||||
'email': user.email,
|
||||
'course': course.name,
|
||||
'created_at': now_,
|
||||
'ttl': ttl(start_dt=now_ + timedelta(days=course.access_period - 15)),
|
||||
'ttl': ttl(start_dt=now_, days=course.access_period - 30),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -310,10 +310,10 @@ Resources:
|
||||
# Post-migration: remove the following line
|
||||
- schedules#expiration
|
||||
|
||||
EventScheduleRemindersFunction:
|
||||
EventSetAsExpiredFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
Handler: events.schedule_reminders.lambda_handler
|
||||
Handler: events.set_as_expired.lambda_handler
|
||||
LoggingConfig:
|
||||
LogGroup: !Ref EventLog
|
||||
Policies:
|
||||
@@ -325,11 +325,31 @@ Resources:
|
||||
Properties:
|
||||
Pattern:
|
||||
resources: [!Ref EnrollmentTable]
|
||||
detail-type: [INSERT]
|
||||
detail-type: [EXPIRE]
|
||||
detail:
|
||||
new_image:
|
||||
sk: ["0"]
|
||||
status: [PENDING]
|
||||
keys:
|
||||
sk: [SCHEDULE#SET_AS_EXPIRED]
|
||||
|
||||
# EventScheduleRemindersFunction:
|
||||
# Type: AWS::Serverless::Function
|
||||
# Properties:
|
||||
# Handler: events.schedule_reminders.lambda_handler
|
||||
# LoggingConfig:
|
||||
# LogGroup: !Ref EventLog
|
||||
# Policies:
|
||||
# - DynamoDBCrudPolicy:
|
||||
# TableName: !Ref EnrollmentTable
|
||||
# Events:
|
||||
# DynamoDBEvent:
|
||||
# Type: EventBridgeRule
|
||||
# Properties:
|
||||
# Pattern:
|
||||
# resources: [!Ref EnrollmentTable]
|
||||
# detail-type: [INSERT]
|
||||
# detail:
|
||||
# new_image:
|
||||
# sk: ["0"]
|
||||
# status: [PENDING]
|
||||
|
||||
EventIssueCertFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
|
||||
@@ -67,7 +67,14 @@ def dynamodb_persistence_layer(dynamodb_client):
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def dynamodb_seeds(dynamodb_client):
|
||||
with jsonlines.open('tests/seeds.jsonl') as lines:
|
||||
for line in lines:
|
||||
dynamodb_client.put_item(TableName=PYTEST_TABLE_NAME, Item=line)
|
||||
def seeds(dynamodb_client):
|
||||
from layercake.dynamodb import serialize
|
||||
|
||||
with open('tests/seeds.jsonl', 'rb') as fp:
|
||||
reader = jsonlines.Reader(fp)
|
||||
|
||||
for line in reader.iter(type=dict, skip_invalid=True):
|
||||
dynamodb_client.put_item(
|
||||
TableName=PYTEST_TABLE_NAME,
|
||||
Item=serialize(line),
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@ from aws_lambda_powertools.utilities.typing import LambdaContext
|
||||
|
||||
|
||||
def test_reminder_access_period_before_30_days(
|
||||
dynamodb_seeds,
|
||||
seeds,
|
||||
lambda_context: LambdaContext,
|
||||
):
|
||||
event = {
|
||||
|
||||
@@ -3,7 +3,7 @@ from aws_lambda_powertools.utilities.typing import LambdaContext
|
||||
|
||||
|
||||
def test_reminder_cert_expiration_before_30_days(
|
||||
dynamodb_seeds,
|
||||
seeds,
|
||||
lambda_context: LambdaContext,
|
||||
):
|
||||
event = {
|
||||
|
||||
@@ -3,7 +3,7 @@ from aws_lambda_powertools.utilities.typing import LambdaContext
|
||||
|
||||
|
||||
def test_reminder_no_access_after_3_days(
|
||||
dynamodb_seeds,
|
||||
seeds,
|
||||
lambda_context: LambdaContext,
|
||||
):
|
||||
event = {
|
||||
|
||||
@@ -3,7 +3,7 @@ from aws_lambda_powertools.utilities.typing import LambdaContext
|
||||
|
||||
|
||||
def test_reminder_no_activity_after_7_days(
|
||||
dynamodb_seeds,
|
||||
seeds,
|
||||
lambda_context: LambdaContext,
|
||||
):
|
||||
event = {
|
||||
|
||||
@@ -8,8 +8,7 @@ from layercake.dynamodb import (
|
||||
|
||||
|
||||
def test_enroll(
|
||||
dynamodb_seeds,
|
||||
dynamodb_client,
|
||||
seeds,
|
||||
dynamodb_persistence_layer: DynamoDBPersistenceLayer,
|
||||
lambda_context: LambdaContext,
|
||||
):
|
||||
|
||||
@@ -5,7 +5,7 @@ import events.stopgap.patch_konviva as app
|
||||
|
||||
|
||||
def test_patch_konviva(
|
||||
dynamodb_seeds,
|
||||
seeds,
|
||||
dynamodb_persistence_layer: DynamoDBPersistenceLayer,
|
||||
lambda_context: LambdaContext,
|
||||
):
|
||||
@@ -18,7 +18,7 @@ def test_patch_konviva(
|
||||
},
|
||||
}
|
||||
}
|
||||
assert app.lambda_handler(event, lambda_context)
|
||||
assert app.lambda_handler(event, lambda_context) # type: ignore
|
||||
|
||||
r = dynamodb_persistence_layer.collection.get_item(
|
||||
KeyPair('f321f0aa-66a3-4419-b41f-cb6b961e7e4f', 'konviva')
|
||||
|
||||
@@ -4,8 +4,7 @@ from layercake.dynamodb import DynamoDBPersistenceLayer, PartitionKey
|
||||
|
||||
|
||||
def test_allocate_slots(
|
||||
dynamodb_seeds,
|
||||
dynamodb_client,
|
||||
seeds,
|
||||
dynamodb_persistence_layer: DynamoDBPersistenceLayer,
|
||||
lambda_context: LambdaContext,
|
||||
):
|
||||
|
||||
@@ -4,8 +4,7 @@ from layercake.dynamodb import DynamoDBPersistenceLayer
|
||||
|
||||
|
||||
def test_enroll(
|
||||
dynamodb_seeds,
|
||||
dynamodb_client,
|
||||
seeds,
|
||||
dynamodb_persistence_layer: DynamoDBPersistenceLayer,
|
||||
lambda_context: LambdaContext,
|
||||
):
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
{"id": {"S": "47ZxxcVBjvhDS5TE98tpfQ"}, "sk": {"S": "0"}, "course": {"M": {"id": {"S": "42"}, "name": {"S": "NR-35 Segurança nos Trabalhos em Altura (Teórico)"},"time_in_days": {"N": "720"}}},"create_date": {"S": "2025-04-10T11:58:33.303347-03:00"},"konviva:id": {"N": "238662"},"progress": {"N": "16.67"},"score": {"NULL": true},"status": {"S": "IN_PROGRESS"}, "update_date": {"S": "2025-04-10T15:44:03.023054-03:00"}, "user": {"M": {"id": {"S": "5OxmMjL-ujoR5IMGegQz"}, "cpf": {"S": "07879819908"}, "email": {"S": "sergio@somosbeta.com.br"}, "name": {"S": "Sérgio Rafael Siqueira"}}}}
|
||||
{"id": {"S": "47ZxxcVBjvhDS5TE98tpfQ"}, "sk": {"S": "konviva"}, "create_date": {"S": "2025-04-10T11:58:35.035729-03:00"}, "konviva_id": {"N": "238662"}}
|
||||
{"id": {"S": "47ZxxcVBjvhDS5TE98tpfQ"}, "sk": {"S": "tenant"}, "create_date": {"S": "2025-04-10T11:58:33.303347-03:00"}, "name": {"S": "Beta Educação"},"org_id": {"S": "cJtK9SsnJhKPyxESe7g3DG"}}
|
||||
{"id": {"S": "JeCybf6oiv6CF3PchhBqdG"}, "sk": {"S": "0"}, "assignee": {"M": {"name": {"S": "Rodrigo Silva"}}},"cnpj": {"S": "54183587001708"},"create_date": {"S": "2025-07-16T15:54:24.304566-03:00"},"due_date": {"S": "2025-07-17T15:50:08.139000-03:00"},"email": {"S": "silva.rodrigo@manserv.com.br"},"name": {"S": "MANSERV MONTAGEM E MANUTENCAO S/A"},"payment_date": {"NULL": true},"payment_method": {"S": "MANUAL"},"status": {"S": "PAID"},"tenant_id": {"S": "PWQyjGZeVcoD5zc5eTkvpr"},"total": {"N": "0"},"updated_at": {"S": "2025-07-16T15:54:27.074086-03:00"},"update_date": {"S": "2025-07-16T15:54:26.697884-03:00"}}
|
||||
{"id": {"S": "JeCybf6oiv6CF3PchhBqdG"}, "sk": {"S": "items"},"items": {"L": [{"M": {"id": {"S": "a955518e-ebcb-4441-b914-ddc9ecef84f0"},"name": {"S": "NR-11 Operador de Munck"},"quantity": {"N": "3"},"unit_price": {"N": "99"}}}, {"M": {"id": {"S": "123"},"name": {"S": "pytest"},"quantity": {"N": "1"},"unit_price": {"N": "99"}}},{"M": {"id": {"S": "23020"},"name": {"S": "Desconto 100%"},"quantity": {"N": "1"},"unit_price": {"N": "-297"}}}]},"updated_at": {"S": "2025-07-16T15:54:27.154404-03:00"}}
|
||||
{"id": {"S": "JeCybf6oiv6CF3PchhBqdG"},"sk": {"S": "generated_items"},"create_date": {"S": "2025-07-16T15:54:30.160729-03:00"},"scope": {"S": "MULTI_USER"},"status": {"S": "SUCCESS"},"update_date": {"S": "2025-07-16T15:54:33.674670-03:00"}}
|
||||
{"id": {"S": "a955518e-ebcb-4441-b914-ddc9ecef84f0"},"sk": {"S": "0"},"access_period": {"N": "360"},"cert": {"M": {"exp_interval": {"N": "360"}}},"created_at": {"S": "2025-07-14T15:09:18.559528-03:00"},"metadata__konviva_class_id": {"N": "281"},"name": {"S": "NR-11 Operador de Munck"},"tenant_id": {"S": "*"}}
|
||||
{"id": {"S": "6a403773-aeac-4e6a-ac39-dc958e4be52a"},"sk": {"S": "0"},"access_period": {"N": "360"},"cert": {"M": {"exp_interval": {"N": "360"}}},"created_at": {"S": "2025-07-14T15:09:18.559528-03:00"},"metadata__konviva_class_id": {"N": "281"},"name": {"S": "Reciclagem em NR-11 - Operador de Empilhadeira"},"tenant_id": {"S": "*"}}
|
||||
{"id": {"S": "123"},"sk": {"S": "0"},"access_period": {"N": "360"},"cert": {"M": {"exp_interval": {"N": "360"}}},"created_at": {"S": "2025-07-14T15:09:18.559528-03:00"},"metadata__konviva_class_id": {"N": "281"},"name": {"S": "pytest"},"tenant_id": {"S": "*"}}
|
||||
{"id": {"S": "5OxmMjL-ujoR5IMGegQz"},"sk": {"S": "konviva"},"created_at": {"S": "2025-07-11T13:52:35.521154-03:00"},"konvivaId": {"N": "26943"}}
|
||||
{"id": {"S": "cpYSbBcie2NDbZhDKCxCih"}, "sk": {"S": "0"},"cpf": {"S": "02713421535"},"create_date": {"S": "2025-07-21T16:19:43.297712-03:00"},"due_date": {"S": "2025-07-22T16:13:41.056000-03:00"},"email": {"S": "sergio@somosbeta.com.br"},"name": {"S": "Sérgio Rafael Siqueira"},"payment_date": {"S": "2025-07-21T16:21:47.161889-03:00"},"payment_method": {"S": "PIX"},"phone_number": {"S": "+5574998189595"},"status": {"S": "PAID"},"total": {"N": "99"},"update_date": {"S": "2025-07-21T16:21:47.161889-03:00"}, "user_id": {"S": "5OxmMjL-ujoR5IMGegQz"}}
|
||||
{"id": {"S": "cpYSbBcie2NDbZhDKCxCih"}, "sk": {"S": "items"},"items": {"L": [{"M": {"id": {"S": "6a403773-aeac-4e6a-ac39-dc958e4be52a"},"name": {"S": "Reciclagem em NR-11 - Operador de Empilhadeira"},"quantity": {"N": "1"},"unit_price": {"N": "99"}}}]}}
|
||||
{"id": {"S": "cpYSbBcie2NDbZhDKCxCih"}, "sk": {"S": "generated_items"},"create_date": {"S": "2025-07-21T16:21:50.143551-03:00"},"scope": {"S": "SINGLE_USER"},"status": {"S": "SUCCESS"},"update_date": {"S": "2025-07-21T16:21:53.994941-03:00"}}
|
||||
{"id": "47ZxxcVBjvhDS5TE98tpfQ", "sk": "0", "course": {"id": "42", "name": "NR-35 Seguran\u00e7a nos Trabalhos em Altura (Te\u00f3rico)", "time_in_days": 720}, "create_date": "2025-04-10T11:58:33.303347-03:00", "konviva:id": 238662, "progress": "16.67", "score": null, "status": "IN_PROGRESS", "update_date": "2025-04-10T15:44:03.023054-03:00", "user": {"id": "5OxmMjL-ujoR5IMGegQz", "cpf": "07879819908", "email": "sergio@somosbeta.com.br", "name": "S\u00e9rgio Rafael Siqueira"}}
|
||||
{"id": "47ZxxcVBjvhDS5TE98tpfQ", "sk": "konviva", "create_date": "2025-04-10T11:58:35.035729-03:00", "konviva_id": "238662"}
|
||||
{"id": "47ZxxcVBjvhDS5TE98tpfQ", "sk": "tenant", "create_date": "2025-04-10T11:58:33.303347-03:00", "name": "Beta Educa\u00e7\u00e3o", "org_id": "cJtK9SsnJhKPyxESe7g3DG"}
|
||||
{"id": "JeCybf6oiv6CF3PchhBqdG", "sk": "0", "assignee": {"name": "Rodrigo Silva"}, "cnpj": "54183587001708", "create_date": "2025-07-16T15:54:24.304566-03:00", "due_date": "2025-07-17T15:50:08.139000-03:00", "email": "silva.rodrigo@manserv.com.br", "name": "MANSERV MONTAGEM E MANUTENCAO S/A", "payment_date": null, "payment_method": "MANUAL", "status": "PAID", "tenant_id": "PWQyjGZeVcoD5zc5eTkvpr", "total": "0", "updated_at": "2025-07-16T15:54:27.074086-03:00", "update_date": "2025-07-16T15:54:26.697884-03:00"}
|
||||
{"id": "JeCybf6oiv6CF3PchhBqdG", "sk": "items", "items": [{"id": "a955518e-ebcb-4441-b914-ddc9ecef84f0", "name": "NR-11 Operador de Munck", "quantity": "3", "unit_price": 99}, {"id": "123", "name": "pytest", "quantity": 1, "unit_price": 99}, {"id": "23020", "name": "Desconto 100%", "quantity": 1, "unit_price": -297}], "updated_at": "2025-07-16T15:54:27.154404-03:00"}
|
||||
{"id": "JeCybf6oiv6CF3PchhBqdG", "sk": "generated_items", "create_date": "2025-07-16T15:54:30.160729-03:00", "scope": "MULTI_USER", "status": "SUCCESS", "update_date": "2025-07-16T15:54:33.674670-03:00"}
|
||||
|
||||
// Order
|
||||
{"id": "cpYSbBcie2NDbZhDKCxCih", "sk": "0", "name": "Sérgio R Siqueira", "email": "sergio@somosbeta.com.br", "cpf": "07879819908", "user_id": "5OxmMjL-ujoR5IMGegQz"}
|
||||
{"id": "cpYSbBcie2NDbZhDKCxCih", "sk": "items", "items": [{"id": "6a403773-aeac-4e6a-ac39-dc958e4be52a", "name": "Reciclagem em NR-11 - Operador de Empilhadeira", "quantity": 1, "unit_price": 99}]}
|
||||
{"id": "cpYSbBcie2NDbZhDKCxCih", "sk": "generated_items"}
|
||||
|
||||
// Course
|
||||
{"id": "123", "sk": "0", "access_period": 360, "cert": {"exp_interval": 360}, "created_at": "2025-07-14T15:09:18.559528-03:00", "metadata__konviva_class_id": "281", "name": "pytest", "tenant_id": "*"}
|
||||
{"id": "a955518e-ebcb-4441-b914-ddc9ecef84f0", "sk": "0", "access_period": "360", "cert": {"exp_interval": 360}, "created_at": "2025-07-14T15:09:18.559528-03:00", "metadata__konviva_class_id": "281", "name": "NR-11 Operador de Munck", "tenant_id": "*"}
|
||||
{"id": "6a403773-aeac-4e6a-ac39-dc958e4be52a", "sk": "0", "access_period": "360", "cert": {"exp_interval": 360}, "created_at": "2025-07-14T15:09:18.559528-03:00", "metadata__konviva_class_id": "281", "name": "Reciclagem em NR-11 - Operador de Empilhadeira", "tenant_id": "*"}
|
||||
|
||||
// User data
|
||||
{"id": "5OxmMjL-ujoR5IMGegQz", "sk": "konviva", "konvivaId": 26943}
|
||||
|
||||
// Enrollment
|
||||
{"id": "6437a282-6fe8-4e4d-9eb0-da1007238007", "sk": "0", "status": "IN_PROGRESS", "progress": 10}
|
||||
{"id": "845fe390-e3c3-4514-97f8-c42de0566cf0", "sk": "0", "status": "COMPLETED", "progress": 100}
|
||||
Reference in New Issue
Block a user