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)',
)