diff --git a/enrollments-events/app/events/emails/__init__.py b/enrollments-events/app/events/emails/__init__.py index e69de29..fc0d6f3 100644 --- a/enrollments-events/app/events/emails/__init__.py +++ b/enrollments-events/app/events/emails/__init__.py @@ -0,0 +1,102 @@ +from typing import TYPE_CHECKING, TypedDict + +from aws_lambda_powertools import Logger +from layercake.dateutils import now +from layercake.dynamodb import DynamoDBPersistenceLayer +from layercake.email_ import Message +from layercake.strutils import first_word, truncate_str + +from . import ( + reminder_access_period_before_30_days, + reminder_cert_expiration_before_30_days, + reminder_no_access_after_3_days, + reminder_no_activity_after_7_days, +) + +if TYPE_CHECKING: + from mypy_boto3_sesv2 import SESV2Client +else: + SESV2Client = object + +Event = TypedDict('Event', {'id': str, 'sk': str}) + +TEMPLATES = { + 'reminder_access_period_before_30_days': { + 'subject': reminder_access_period_before_30_days.SUBJECT, + 'message': reminder_access_period_before_30_days.MESSAGE, + }, + 'reminder_cert_expiration_before_30_days': { + 'subject': reminder_cert_expiration_before_30_days.SUBJECT, + 'message': reminder_cert_expiration_before_30_days.MESSAGE, + }, + 'reminder_no_access_after_3_days': { + 'subject': reminder_no_access_after_3_days.SUBJECT, + 'message': reminder_no_access_after_3_days.MESSAGE, + }, + 'reminder_no_activity_after_7_days': { + 'subject': reminder_no_activity_after_7_days.SUBJECT, + 'message': reminder_no_activity_after_7_days.MESSAGE, + }, +} + +logger = Logger(__name__) + + +def send_email( + to: tuple[str, str], + subject: str, + message: str, + context: dict = {}, + *, + sender: tuple[str, str], + event: Event, + sesv2_client: SESV2Client, + dynamodb_persistence_layer: DynamoDBPersistenceLayer, +) -> bool: + now_ = now() + name, _ = to + event_name = event['sk'] + emailmsg = Message( + from_=sender, + to=to, + subject=subject.format( + course=truncate_str(context['course']), + ), + ) + emailmsg.add_alternative( + message.format( + first_name=first_word(name), + course=context['course'], + ) + ) + + try: + sesv2_client.send_email( + Content={ + 'Raw': { + 'Data': emailmsg.as_bytes(), + }, + } + ) + dynamodb_persistence_layer.put_item( + item={ + 'id': event['id'], + 'sk': f'{event_name}#EXECUTED', + 'created_at': now_, + } + ) + logger.info('Email sent') + except Exception as exc: + logger.exception(exc) + + dynamodb_persistence_layer.put_item( + item={ + 'id': event['id'], + 'sk': f'{event_name}#FAILED', + 'created_at': now_, + } + ) + + return False + else: + return True diff --git a/enrollments-events/app/events/emails/email_.py b/enrollments-events/app/events/emails/email_.py deleted file mode 100644 index 17f980f..0000000 --- a/enrollments-events/app/events/emails/email_.py +++ /dev/null @@ -1,76 +0,0 @@ -from typing import TYPE_CHECKING, TypedDict - -from aws_lambda_powertools import Logger -from layercake.dateutils import now -from layercake.dynamodb import DynamoDBPersistenceLayer -from layercake.email_ import Message -from layercake.strutils import first_word, truncate_str - -logger = Logger(__name__) - -if TYPE_CHECKING: - from mypy_boto3_sesv2 import SESV2Client -else: - SESV2Client = object - -Event = TypedDict('Event', {'id': str, 'sk': str}) - - -def send_email( - to: tuple[str, str], - subject: str, - message: str, - context: dict = {}, - *, - sender: tuple[str, str], - event: Event, - sesv2_client: SESV2Client, - dynamodb_persistence_layer: DynamoDBPersistenceLayer, -) -> bool: - now_ = now() - name, _ = to - event_name = event['sk'] - emailmsg = Message( - from_=sender, - to=to, - subject=subject.format( - course=truncate_str(context['course']), - ), - ) - emailmsg.add_alternative( - message.format( - first_name=first_word(name), - course=context['course'], - ) - ) - - try: - sesv2_client.send_email( - Content={ - 'Raw': { - 'Data': emailmsg.as_bytes(), - }, - } - ) - dynamodb_persistence_layer.put_item( - item={ - 'id': event['id'], - 'sk': f'{event_name}#EXECUTED', - 'created_at': now_, - } - ) - logger.info('Email sent') - except Exception as exc: - logger.exception(exc) - - dynamodb_persistence_layer.put_item( - item={ - 'id': event['id'], - 'sk': f'{event_name}#FAILED', - 'created_at': now_, - } - ) - - return False - else: - return True diff --git a/enrollments-events/app/events/emails/reminder_access_period_before_30_days.py b/enrollments-events/app/events/emails/reminder_access_period_before_30_days.py index 121b30e..f6c80ef 100644 --- a/enrollments-events/app/events/emails/reminder_access_period_before_30_days.py +++ b/enrollments-events/app/events/emails/reminder_access_period_before_30_days.py @@ -1,22 +1,4 @@ -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.dynamodb import DynamoDBPersistenceLayer, KeyPair - -from boto3clients import dynamodb_client, sesv2_client -from config import ( - EMAIL_SENDER, - ENROLLMENT_TABLE, -) - -from .email_ import send_email - -logger = Logger(__name__) -enrollment_layer = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client) - +# 30 days before the course access period ends SUBJECT = 'Seu acesso ao curso {course} termina em 30 dias' MESSAGE = """ @@ -27,34 +9,3 @@ Conclua dentro desse prazo para garantir sua certificação.

👉 Acesse agora seu curso """ - - -@event_source(data_class=EventBridgeEvent) -@logger.inject_lambda_context -def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool: - """30 days before the course access period ends.""" - old_image = event.detail['old_image'] - - # Post-migration: Remove the following lines - if 'email' not in old_image: - # If email is missing, use enrollment email - cur_image = enrollment_layer.get_item(KeyPair(old_image['id'], '0')) - old_image['name'] = cur_image['user']['name'] - old_image['email'] = cur_image['user']['email'] - old_image['course'] = cur_image['course']['name'] - - return send_email( - to=(old_image['name'], old_image['email']), - subject=SUBJECT, - message=MESSAGE, - context={ - 'course': old_image['course'], - }, - sender=EMAIL_SENDER, - sesv2_client=sesv2_client, - event={ - 'id': old_image['id'], - 'sk': 'SCHEDULE#REMINDER_ACCESS_PERIOD_BEFORE_30_DAYS', - }, - dynamodb_persistence_layer=enrollment_layer, - ) diff --git a/enrollments-events/app/events/emails/reminder_cert_expiration_before_30_days.py b/enrollments-events/app/events/emails/reminder_cert_expiration_before_30_days.py index 57cfd58..e8f026e 100644 --- a/enrollments-events/app/events/emails/reminder_cert_expiration_before_30_days.py +++ b/enrollments-events/app/events/emails/reminder_cert_expiration_before_30_days.py @@ -1,22 +1,7 @@ -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.dynamodb import DynamoDBPersistenceLayer, KeyPair - -from boto3clients import dynamodb_client, sesv2_client -from config import ( - EMAIL_SENDER, - ENROLLMENT_TABLE, -) - -from .email_ import send_email - -logger = Logger(__name__) -enrollment_layer = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client) - +""" +If a certificate exists, remind the user 30 days before +the certificate expires +""" SUBJECT = 'Seu certificado {course} vai expirar em breve' MESSAGE = """ @@ -28,35 +13,3 @@ antes da expiração.

👉 Acesse o curso e renove sua certificação """ - - -@event_source(data_class=EventBridgeEvent) -@logger.inject_lambda_context -def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool: - """If a certificate exists, remind the user 30 days before - the certificate expires.""" - old_image = event.detail['old_image'] - - # Post-migration: Remove the following lines - if 'email' not in old_image: - # If email is missing, use enrollment email - cur_image = enrollment_layer.get_item(KeyPair(old_image['id'], '0')) - old_image['name'] = cur_image['user']['name'] - old_image['email'] = cur_image['user']['email'] - old_image['course'] = cur_image['course']['name'] - - return send_email( - to=(old_image['name'], old_image['email']), - subject=SUBJECT, - message=MESSAGE, - context={ - 'course': old_image['course'], - }, - sender=EMAIL_SENDER, - sesv2_client=sesv2_client, - event={ - 'id': old_image['id'], - 'sk': 'SCHEDULE#REMINDER_CERT_EXPIRATION_BEFORE_30_DAYS', - }, - dynamodb_persistence_layer=enrollment_layer, - ) diff --git a/enrollments-events/app/events/emails/reminder_no_access_after_3_days.py b/enrollments-events/app/events/emails/reminder_no_access_after_3_days.py index e708269..c0f0b51 100644 --- a/enrollments-events/app/events/emails/reminder_no_access_after_3_days.py +++ b/enrollments-events/app/events/emails/reminder_no_access_after_3_days.py @@ -1,22 +1,7 @@ -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.dynamodb import DynamoDBPersistenceLayer, KeyPair - -from boto3clients import dynamodb_client, sesv2_client -from config import ( - EMAIL_SENDER, - ENROLLMENT_TABLE, -) - -from .email_ import send_email - -logger = Logger(__name__) -enrollment_layer = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client) - +""" +If the user does not access the course within 3 days +after enrollment creation +""" SUBJECT = 'Seu curso {course} está esperando por você na EDUSEG®' MESSAGE = """ @@ -28,35 +13,3 @@ ao máximo seu curso!

👉 Acesse seu curso agora """ - - -@event_source(data_class=EventBridgeEvent) -@logger.inject_lambda_context -def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool: - """If the user does not access the course within 3 days after - enrollment creation.""" - old_image = event.detail['old_image'] - - # Post-migration: Remove the following lines - if 'email' not in old_image: - # If email is missing, use enrollment email - cur_image = enrollment_layer.get_item(KeyPair(old_image['id'], '0')) - old_image['name'] = cur_image['user']['name'] - old_image['email'] = cur_image['user']['email'] - old_image['course'] = cur_image['course']['name'] - - return send_email( - to=(old_image['name'], old_image['email']), - subject=SUBJECT, - message=MESSAGE, - context={ - 'course': old_image['course'], - }, - sender=EMAIL_SENDER, - sesv2_client=sesv2_client, - event={ - 'id': old_image['id'], - 'sk': 'SCHEDULE#REMINDER_NO_ACCESS_AFTER_3_DAYS', - }, - dynamodb_persistence_layer=enrollment_layer, - ) diff --git a/enrollments-events/app/events/emails/reminder_no_activity_after_7_days.py b/enrollments-events/app/events/emails/reminder_no_activity_after_7_days.py index f240333..e27f430 100644 --- a/enrollments-events/app/events/emails/reminder_no_activity_after_7_days.py +++ b/enrollments-events/app/events/emails/reminder_no_activity_after_7_days.py @@ -1,22 +1,4 @@ -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.dynamodb import DynamoDBPersistenceLayer, KeyPair - -from boto3clients import dynamodb_client, sesv2_client -from config import ( - EMAIL_SENDER, - ENROLLMENT_TABLE, -) - -from .email_ import send_email - -logger = Logger(__name__) -enrollment_layer = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client) - +# 7 days after the user's last activity in the course SUBJECT = 'Seu curso {course} está parado há 7 dias...' MESSAGE = """ @@ -27,34 +9,3 @@ Não deixe seu período de acesso expirar! Retome seu aprendizado agora mesmo.👉 Clique aqui para acessar seu curso """ - - -@event_source(data_class=EventBridgeEvent) -@logger.inject_lambda_context -def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool: - """7 days after the user's last activity in the course.""" - old_image = event.detail['old_image'] - - # Post-migration: Remove the following lines - if 'email' not in old_image: - # If email is missing, use enrollment email - cur_image = enrollment_layer.get_item(KeyPair(old_image['id'], '0')) - old_image['name'] = cur_image['user']['name'] - old_image['email'] = cur_image['user']['email'] - old_image['course'] = cur_image['course']['name'] - - return send_email( - to=(old_image['name'], old_image['email']), - subject=SUBJECT, - message=MESSAGE, - context={ - 'course': old_image['course'], - }, - sender=EMAIL_SENDER, - sesv2_client=sesv2_client, - event={ - 'id': old_image['id'], - 'sk': 'SCHEDULE#REMINDER_NO_ACTIVITY_AFTER_7_DAYS', - }, - dynamodb_persistence_layer=enrollment_layer, - ) diff --git a/enrollments-events/app/events/send_reminder_emails.py b/enrollments-events/app/events/send_reminder_emails.py new file mode 100644 index 0000000..0a2b127 --- /dev/null +++ b/enrollments-events/app/events/send_reminder_emails.py @@ -0,0 +1,49 @@ +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.dynamodb import DynamoDBPersistenceLayer, KeyPair + +from boto3clients import dynamodb_client, sesv2_client +from config import ( + EMAIL_SENDER, + ENROLLMENT_TABLE, +) + +from .emails import TEMPLATES, send_email + +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'] + event_name = old_image['sk'].removeprefix('SCHEDULE#').lower() + template = TEMPLATES[event_name] + + # If email is missing, use enrollment email + if 'email' not in old_image: + r = dyn.get_item(KeyPair(pk=old_image['id'], sk='0')) + old_image['name'] = r['user']['name'] + old_image['email'] = r['user']['email'] + old_image['course'] = r['course']['name'] + + return send_email( + to=(old_image['name'], old_image['email']), + subject=template['subject'], + message=template['message'], + context={ + 'course': old_image['course'], + }, + sender=EMAIL_SENDER, + sesv2_client=sesv2_client, + event={ + 'id': old_image['id'], + 'sk': old_image['sk'], + }, + dynamodb_persistence_layer=dyn, + ) diff --git a/enrollments-events/app/events/stopgap/patch_course_metadata.py b/enrollments-events/app/events/stopgap/patch_course_metadata.py index 64f55cd..21939d2 100644 --- a/enrollments-events/app/events/stopgap/patch_course_metadata.py +++ b/enrollments-events/app/events/stopgap/patch_course_metadata.py @@ -9,15 +9,12 @@ from aws_lambda_powertools.utilities.data_classes import ( ) from aws_lambda_powertools.utilities.typing import LambdaContext from layercake.dateutils import now -from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair -from sqlite_utils import Database +from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair, SortKey from boto3clients import dynamodb_client from config import ( COURSE_TABLE, ENROLLMENT_TABLE, - SQLITE_DATABASE, - SQLITE_TABLE, ) sqlite3.register_converter('json', json.loads) @@ -72,23 +69,24 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool: class CourseNotFoundError(Exception): def __init__(self, *args): - super().__init__('Course not found in SQLite') + super().__init__('Course not found') -def _get_course(course_id: str) -> dict: - course = course_layer.get_item(KeyPair(pk=course_id, sk='0')) +def _get_course(id: str) -> dict: + course = course_layer.get_item(KeyPair(pk=id, sk='0')) if course: return course - with sqlite3.connect( - database=SQLITE_DATABASE, detect_types=sqlite3.PARSE_DECLTYPES - ) as conn: - db = Database(conn) - rows = db[SQLITE_TABLE].rows_where( - "json->>'$.metadata__betaeducacao_id' = ?", [course_id] - ) - - for row in rows: - return row['json'] - - raise CourseNotFoundError + course_id = course_layer.collection.get_item( + KeyPair( + pk='MIGRATION', + sk=SortKey( + f'COURSE#{id}', + path_spec='course_id', + ), + ), + exc_cls=CourseNotFoundError, + ) + return course_layer.collection.get_item( + KeyPair(pk=course_id, sk='0'), + ) diff --git a/enrollments-events/template.yaml b/enrollments-events/template.yaml index 805f4a6..268e576 100644 --- a/enrollments-events/template.yaml +++ b/enrollments-events/template.yaml @@ -219,11 +219,10 @@ Resources: - !Sub arn:aws:ses:${AWS::Region}:${AWS::AccountId}:identity/eduseg.com.br - !Sub arn:aws:ses:${AWS::Region}:${AWS::AccountId}:configuration-set/tracking - # If the user does not access the course within 3 days after enrollment creation - EventReminderNoAccessAfter3DaysFunction: + EventSendReminderEmailsFunction: Type: AWS::Serverless::Function Properties: - Handler: events.emails.reminder_no_access_after_3_days.lambda_handler + Handler: events.emails.send_reminder_emails.lambda_handler LoggingConfig: LogGroup: !Ref EventLog Policies: @@ -239,17 +238,19 @@ Resources: detail-type: [EXPIRE] detail: keys: - sk: [SCHEDULE#REMINDER_NO_ACCESS_AFTER_3_DAYS] + sk: + - SCHEDULE#REMINDER_NO_ACCESS_AFTER_3_DAYS + - SCHEDULE#REMINDER_NO_ACTIVITY_AFTER_7_DAYS + - SCHEDULE#REMINDER_ACCESS_PERIOD_BEFORE_30_DAYS + - SCHEDULE#REMINDER_CERT_EXPIRATION_BEFORE_30_DAYS - # 7 days after the user's last activity in the course - EventReminderNoActivityAfter7DaysFunction: + EventScheduleRemindersFunction: Type: AWS::Serverless::Function Properties: - Handler: events.emails.reminder_no_activity_after_7_days.lambda_handler + Handler: events.schedule_reminders.lambda_handler LoggingConfig: LogGroup: !Ref EventLog Policies: - - !Ref SesPolicy - DynamoDBCrudPolicy: TableName: !Ref EnrollmentTable Events: @@ -258,54 +259,11 @@ Resources: Properties: Pattern: resources: [!Ref EnrollmentTable] - detail-type: [EXPIRE] + detail-type: [INSERT] detail: - keys: - sk: [SCHEDULE#REMINDER_NO_ACTIVITY_AFTER_7_DAYS] - - # 30 days before the course access period ends. - EventReminderAccessPeriodBefore30DaysFunction: - Type: AWS::Serverless::Function - Properties: - Handler: events.emails.reminder_access_period_before_30_days.lambda_handler - LoggingConfig: - LogGroup: !Ref EventLog - Policies: - - !Ref SesPolicy - - DynamoDBCrudPolicy: - TableName: !Ref EnrollmentTable - Events: - DynamoDBEvent: - Type: EventBridgeRule - Properties: - Pattern: - resources: [!Ref EnrollmentTable] - detail-type: [EXPIRE] - detail: - keys: - sk: [SCHEDULE#REMINDER_ACCESS_PERIOD_BEFORE_30_DAYS] - - # If a certificate exists, remind the user 30 days before the certificate expires - EventReminderCertExpirationBefore30DaysFunction: - Type: AWS::Serverless::Function - Properties: - Handler: events.emails.reminder_cert_expiration_before_30_days.lambda_handler - LoggingConfig: - LogGroup: !Ref EventLog - Policies: - - !Ref SesPolicy - - DynamoDBCrudPolicy: - TableName: !Ref EnrollmentTable - Events: - DynamoDBEvent: - Type: EventBridgeRule - Properties: - Pattern: - resources: [!Ref EnrollmentTable] - detail-type: [EXPIRE] - detail: - keys: - sk: [SCHEDULE#REMINDER_CERT_EXPIRATION_BEFORE_30_DAYS] + new_image: + sk: ["0"] + status: [PENDING] EventSetAccessExpiredFunction: Type: AWS::Serverless::Function @@ -347,27 +305,6 @@ Resources: keys: sk: [SCHEDULE#SET_CERT_EXPIRED, SCHEDULE#SET_AS_ARCHIVED] - 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 Properties: diff --git a/enrollments-events/tests/events/emails/test_reminder_access_period_before_30_days.py b/enrollments-events/tests/events/emails/test_reminder_access_period_before_30_days.py index bbd1d51..91f652b 100644 --- a/enrollments-events/tests/events/emails/test_reminder_access_period_before_30_days.py +++ b/enrollments-events/tests/events/emails/test_reminder_access_period_before_30_days.py @@ -1,4 +1,4 @@ -import app.events.emails.reminder_access_period_before_30_days as app +import app.events.send_reminder_emails as app from aws_lambda_powertools.utilities.typing import LambdaContext diff --git a/enrollments-events/tests/events/emails/test_reminder_cert_expiration_before_30_days.py b/enrollments-events/tests/events/emails/test_reminder_cert_expiration_before_30_days.py index 2a6fecf..8fb6595 100644 --- a/enrollments-events/tests/events/emails/test_reminder_cert_expiration_before_30_days.py +++ b/enrollments-events/tests/events/emails/test_reminder_cert_expiration_before_30_days.py @@ -1,4 +1,4 @@ -import app.events.emails.reminder_cert_expiration_before_30_days as app +import app.events.send_reminder_emails as app from aws_lambda_powertools.utilities.typing import LambdaContext diff --git a/enrollments-events/tests/events/emails/test_reminder_no_access_after_3_days.py b/enrollments-events/tests/events/emails/test_reminder_no_access_after_3_days.py index fb25c7d..1ed3faf 100644 --- a/enrollments-events/tests/events/emails/test_reminder_no_access_after_3_days.py +++ b/enrollments-events/tests/events/emails/test_reminder_no_access_after_3_days.py @@ -1,4 +1,4 @@ -import app.events.emails.reminder_no_access_after_3_days as app +import app.events.send_reminder_emails as app from aws_lambda_powertools.utilities.typing import LambdaContext diff --git a/enrollments-events/tests/events/emails/test_reminder_no_activity_after_7_days.py b/enrollments-events/tests/events/emails/test_reminder_no_activity_after_7_days.py index 5635f5e..2d70025 100644 --- a/enrollments-events/tests/events/emails/test_reminder_no_activity_after_7_days.py +++ b/enrollments-events/tests/events/emails/test_reminder_no_activity_after_7_days.py @@ -1,4 +1,4 @@ -import app.events.emails.reminder_no_activity_after_7_days as app +import app.events.send_reminder_emails as app from aws_lambda_powertools.utilities.typing import LambdaContext diff --git a/enrollments-events/tests/seeds.jsonl b/enrollments-events/tests/seeds.jsonl index a9548c3..bc29400 100644 --- a/enrollments-events/tests/seeds.jsonl +++ b/enrollments-events/tests/seeds.jsonl @@ -16,6 +16,9 @@ {"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": "*"} {"id": "e1c44881-2fe3-484e-ada2-12b6bf5b9398", "sk": "0", "name": "NR-35 Segurança nos Trabalhos em Altura (Teórico)", "updated_at": "2025-08-22T00:00:24.431267-03:00", "access_period": 360, "created_at": "2024-12-30T00:11:33.088916-03:00", "metadata__konviva_class_id": 1, "tenant_id": "*", "cert": {"exp_interval": 700}, "metadata__unit_price": 119} +// Course migration +{"id": "MIGRATION", "sk": "COURSE#57", "course_id": "e1c44881-2fe3-484e-ada2-12b6bf5b9398"} + // User data {"id": "5OxmMjL-ujoR5IMGegQz", "sk": "konviva", "konvivaId": 26943} @@ -34,4 +37,5 @@ {"id": "294e9864-8284-4287-b153-927b15d90900", "sk": "METADATA#COURSE", "access_period": 360, "created_at": "2025-09-09T09:11:29.292760-03:00", "cert": {"exp_interval": 360}} {"id": "294e9864-8284-4287-b153-927b15d90900", "sk": "konviva", "class_id": 34, "user_id": 26943, "created_at": "2025-09-09T09:11:29.315247-03:00", "enrollment_id": 244488} {"id": "294e9864-8284-4287-b153-927b15d90900", "sk": "METADATA#DEDUPLICATION_WINDOW", "offset_days": 90, "created_at": "2025-09-11T09:00:45.923035-03:00"} -{"id": "294e9864-8284-4287-b153-927b15d90900", "sk": "tenant", "org_id": "123", "name": "EDUSEG", "create_date": "2025-09-12T17:11:00.556907-03:00"} \ No newline at end of file +{"id": "294e9864-8284-4287-b153-927b15d90900", "sk": "tenant", "org_id": "123", "name": "EDUSEG", "create_date": "2025-09-12T17:11:00.556907-03:00"} +