From 0501dc8f16336256e0af5327c8a1146d8fd041de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Rafael=20Siqueira?= Date: Thu, 18 Sep 2025 17:11:38 -0300 Subject: [PATCH] fix issued cert --- ...reminder_cert_expiration_before_30_days.py | 3 +- .../emails/reminder_no_access_after_3_days.py | 3 +- enrollments-events/app/events/issue_cert.py | 59 +++++++++++-------- konviva-events/app/enrollment.py | 9 ++- 4 files changed, 43 insertions(+), 31 deletions(-) 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 1fd2b16..57cfd58 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 @@ -23,7 +23,8 @@ MESSAGE = """ Oi {first_name}, tudo bem?

O certificado do curso {course} vai expirar em breve.
-Para manter sua certificação válida, é recomendável refazer o curso 30 dias antes da expiração.

+Para manter sua certificação válida, é recomendável refazer o curso 30 dias +antes da expiração.

👉 Acesse o curso e renove sua certificação """ 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 093f058..e708269 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 @@ -23,7 +23,8 @@ MESSAGE = """ Oi {first_name}, tudo bem?

Há 3 dias você foi matriculado no curso {course}.
-Ainda não começou? Não perca a oportunidade de aprender e aproveitar ao máximo seu curso!

+Ainda não começou? Não perca a oportunidade de aprender e aproveitar +ao máximo seu curso!

👉 Acesse seu curso agora """ diff --git a/enrollments-events/app/events/issue_cert.py b/enrollments-events/app/events/issue_cert.py index 0ef1ec1..3d61ecb 100644 --- a/enrollments-events/app/events/issue_cert.py +++ b/enrollments-events/app/events/issue_cert.py @@ -27,6 +27,7 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool: 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, @@ -42,40 +43,46 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool: completed_at: datetime = fromisoformat(course['completed_at']) # type: ignore cert_expires_at = now_ + timedelta(days=int(cert['exp_interval'])) - data = json.dumps( - { - 'template_s3_uri': cert['s3_uri'], - 'template_vars': { - 'name': new_image['user']['name'], - 'cpf': _cpffmt(new_image['user']['cpf']), - 'score': new_image['score'], - 'started_at': started_at.strftime('%d/%m/%Y'), - 'completed_at': completed_at.strftime('%d/%m/%Y'), - 'today': _datefmt(now_), - 'year': now_.strftime('%Y'), - }, - }, - ) - # Send template URI and data to Paperforge API to generate a PDF - r = requests.post(PAPERFORGE_API, data=data) - r.raise_for_status() - - object_key = f'issuedcerts/{enrollment_id}.pdf' - s3_uri = f's3://{BUCKET_NAME}/{object_key}' - try: + # Send template URI and data to Paperforge API to generate a PDF + r = requests.post( + PAPERFORGE_API, + data=json.dumps( + { + 'template_s3_uri': cert['s3_uri'], + 'template_vars': { + 'name': new_image['user']['name'], + 'cpf': _cpffmt(new_image['user']['cpf']), + 'score': new_image['score'], + 'started_at': started_at.strftime('%d/%m/%Y'), + 'completed_at': completed_at.strftime('%d/%m/%Y'), + 'today': _datefmt(now_), + 'year': now_.strftime('%Y'), + }, + }, + ), + ) + r.raise_for_status() + + object_key = f'issuedcerts/{enrollment_id}.pdf' + s3_uri = f's3://{BUCKET_NAME}/{object_key}' + s3_client.put_object( Bucket=BUCKET_NAME, Key=object_key, Body=r.content, ContentType='application/pdf', ) - except Exception as exc: + + logger.debug(f'PDF uploaded successfully to {s3_uri}') + except KeyError: + # PDF generation fails if template URI is missing + s3_uri = None + logger.debug('Template URI is missing') + except requests.exceptions.RequestException as exc: logger.exception(exc) raise - logger.debug(f'PDF uploaded successfully to {s3_uri}') - return enrollment_layer.update_item( key=KeyPair( pk=enrollment_id, @@ -84,10 +91,10 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool: update_expr='SET issued_cert = :issued_cert', expr_attr_values={ ':issued_cert': { - 's3_uri': s3_uri, 'issued_at': now_, 'expires_at': cert_expires_at, - }, + } + | ({'s3_uri': s3_uri} if s3_uri else {}), }, cond_expr='attribute_exists(sk)', ) diff --git a/konviva-events/app/enrollment.py b/konviva-events/app/enrollment.py index a17ffbd..225d6f0 100644 --- a/konviva-events/app/enrollment.py +++ b/konviva-events/app/enrollment.py @@ -55,6 +55,7 @@ def update_progress( key=KeyPair(id, '0'), update_expr='SET progress = :progress, \ #status = :in_progress, \ + started_at = :now, \ updated_at = :now', cond_expr='#status = :pending', expr_attr_names={ @@ -73,7 +74,7 @@ def update_progress( item={ 'id': id, 'sk': 'STARTED', - 'started_at': now_, + 'created_at': now_, }, cond_expr='attribute_not_exists(sk)', ) @@ -191,6 +192,7 @@ def _set_status_as_completed( update_expr='SET #status = :completed, \ progress = :progress, \ score = :score, \ + completed_at = :now, \ updated_at = :now', cond_expr='#status = :in_progress', expr_attr_names={'#status': 'status'}, @@ -207,7 +209,7 @@ def _set_status_as_completed( item={ 'id': id, 'sk': 'COMPLETED', - 'completed_at': now_, + 'created_at': now_, }, cond_expr='attribute_not_exists(sk)', ) @@ -291,6 +293,7 @@ def _set_status_as_failed( progress = :progress, \ score = :score, \ access_expired = :true, \ + failed_at = :now, \ updated_at = :now', cond_expr='#status = :in_progress', expr_attr_names={'#status': 'status'}, @@ -308,7 +311,7 @@ def _set_status_as_failed( item={ 'id': id, 'sk': 'FAILED', - 'failed_at': now_, + 'created_at': now_, }, cond_expr='attribute_not_exists(sk)', )