From 18674d883133884760a09c11a37a8c8da7fe4ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Rafael=20Siqueira?= Date: Mon, 22 Sep 2025 10:42:13 -0300 Subject: [PATCH] fix issued cert --- .../events/emails/reminder_cert_expired.py | 13 ++++++++ enrollments-events/app/events/issue_cert.py | 30 +++++++++---------- .../tests/events/test_issue_cert.py | 2 ++ http-api/app/routes/enrollments/__init__.py | 4 +-- http-api/app/rules/enrollment.py | 12 +++++--- 5 files changed, 40 insertions(+), 21 deletions(-) create mode 100644 enrollments-events/app/events/emails/reminder_cert_expired.py diff --git a/enrollments-events/app/events/emails/reminder_cert_expired.py b/enrollments-events/app/events/emails/reminder_cert_expired.py new file mode 100644 index 0000000..6aad955 --- /dev/null +++ b/enrollments-events/app/events/emails/reminder_cert_expired.py @@ -0,0 +1,13 @@ +""" +If a certificate exists, remind the user that the certificate expired. +""" + +SUBJECT = 'Seu certificado {course} expirou!' +MESSAGE = """ +Oi {first_name}, tudo bem?

+ +O certificado do curso {course} expirou.
+Para manter sua certificação válida, é necessário refazer o curso.

+ +👉 Acesse o curso e renove sua certificação +""" diff --git a/enrollments-events/app/events/issue_cert.py b/enrollments-events/app/events/issue_cert.py index 3d61ecb..249519e 100644 --- a/enrollments-events/app/events/issue_cert.py +++ b/enrollments-events/app/events/issue_cert.py @@ -15,7 +15,7 @@ from boto3clients import dynamodb_client, s3_client from config import BUCKET_NAME, ENROLLMENT_TABLE, PAPERFORGE_API logger = Logger(__name__) -enrollment_layer = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client) +dyn = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client) @event_source(data_class=EventBridgeEvent) @@ -24,24 +24,23 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool: new_image = event.detail['new_image'] now_ = now() enrollment_id = new_image['id'] - course = enrollment_layer.collection.get_items( - TransactKey(new_image['id']) - + SortKey('METADATA#COURSE', path_spec='cert', rename_key='cert') - # Post-migration: remove the following lines - + SortKey('STARTED', path_spec='started_at', rename_key='started_at') - + SortKey('COMPLETED', path_spec='completed_at', rename_key='completed_at'), - flatten_top=False, + cert = dyn.collection.get_item( + KeyPair( + pk=new_image['id'], + sk=SortKey('METADATA#COURSE', path_spec='cert', rename_key='cert'), + ), + raise_on_error=False, + default=False, ) - if 'cert' not in course: + if not cert: logger.debug('Certificate not found') # There is no certificate to issue from metadata return False - cert = course['cert'] - started_at: datetime = fromisoformat(course['started_at']) # type: ignore - completed_at: datetime = fromisoformat(course['completed_at']) # type: ignore - cert_expires_at = now_ + timedelta(days=int(cert['exp_interval'])) + started_at: datetime = fromisoformat(new_image['started_at']) # type: ignore + completed_at: datetime = fromisoformat(new_image['completed_at']) # type: ignore + cert_expires_at = completed_at + timedelta(days=int(cert['exp_interval'])) try: # Send template URI and data to Paperforge API to generate a PDF @@ -83,13 +82,14 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool: logger.exception(exc) raise - return enrollment_layer.update_item( + return dyn.update_item( key=KeyPair( pk=enrollment_id, sk='0', ), - update_expr='SET issued_cert = :issued_cert', + update_expr='SET issued_cert = :issued_cert, uploaded_at = :now', expr_attr_values={ + ':now': now_, ':issued_cert': { 'issued_at': now_, 'expires_at': cert_expires_at, diff --git a/enrollments-events/tests/events/test_issue_cert.py b/enrollments-events/tests/events/test_issue_cert.py index ec7302c..b0599b1 100644 --- a/enrollments-events/tests/events/test_issue_cert.py +++ b/enrollments-events/tests/events/test_issue_cert.py @@ -14,6 +14,8 @@ def test_issue_cert( 'detail': { 'new_image': { 'id': enrollment_id, + 'completed_at': '2025-09-21T14:20:36.276467-03:00', + 'started_at': '2025-09-19T14:34:54.704548-03:00', 'user': { 'name': 'Jimi Hendrix', 'cpf': '74630003037', diff --git a/http-api/app/routes/enrollments/__init__.py b/http-api/app/routes/enrollments/__init__.py index 208d672..d4d48cb 100644 --- a/http-api/app/routes/enrollments/__init__.py +++ b/http-api/app/routes/enrollments/__init__.py @@ -72,8 +72,8 @@ def get_enrollment(id: str): record = enrollment_layer.collection.get_items( TransactKey(id) + SortKey('0') - + SortKey('STARTED', rename_key='started_at', path_spec='started_at') - + SortKey('COMPLETED', rename_key='completed_at', path_spec='completed_at') + # + SortKey('STARTED', rename_key='started_at', path_spec='started_at') + # + SortKey('COMPLETED', rename_key='completed_at', path_spec='completed_at') + SortKey('FAILED', rename_key='failed_at', path_spec='failed_at') + SortKey('CANCELED', rename_key='canceled') + SortKey('ARCHIVED', rename_key='archived_at', path_spec='archived_at') diff --git a/http-api/app/rules/enrollment.py b/http-api/app/rules/enrollment.py index ec5d394..ebae905 100644 --- a/http-api/app/rules/enrollment.py +++ b/http-api/app/rules/enrollment.py @@ -201,7 +201,10 @@ def set_status_as_canceled( with persistence_layer.transact_writer() as transact: transact.update( key=KeyPair(id, '0'), - update_expr='SET #status = :canceled, updated_at = :updated_at', + update_expr='SET #status = :canceled, \ + access_expired = :true, \ + canceled_at = :now, \ + updated_at = :now', cond_expr='#status = :pending', expr_attr_names={ '#status': 'status', @@ -209,7 +212,8 @@ def set_status_as_canceled( expr_attr_values={ ':canceled': 'CANCELED', ':pending': 'PENDING', - ':updated_at': now_, + ':true': True, + ':now': now_, }, ) transact.put( @@ -217,7 +221,7 @@ def set_status_as_canceled( 'id': id, 'sk': 'CANCELED', 'canceled_by': created_by, - 'canceled_at': now_, + 'created_at': now_, }, ) transact.delete( @@ -256,7 +260,7 @@ def set_status_as_canceled( transact.delete( key=KeyPair( pk=id, - sk='SCHEDULE#SET_AS_EXPIRED', + sk='SCHEDULE#SET_ACCESS_EXPIRED', ) ) transact.delete(