fix
This commit is contained in:
@@ -2,7 +2,7 @@ from abc import ABC
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import NotRequired, Self, TypedDict
|
from typing import NotRequired, TypedDict
|
||||||
|
|
||||||
from layercake.dateutils import now, ttl
|
from layercake.dateutils import now, ttl
|
||||||
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair
|
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair
|
||||||
|
|||||||
@@ -9,11 +9,13 @@ from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair, SortKey
|
|||||||
|
|
||||||
from boto3clients import dynamodb_client
|
from boto3clients import dynamodb_client
|
||||||
from config import (
|
from config import (
|
||||||
|
COURSE_TABLE,
|
||||||
ENROLLMENT_TABLE,
|
ENROLLMENT_TABLE,
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = Logger(__name__)
|
logger = Logger(__name__)
|
||||||
dyn = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client)
|
enrollment_layer = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client)
|
||||||
|
course_layer = DynamoDBPersistenceLayer(COURSE_TABLE, dynamodb_client)
|
||||||
|
|
||||||
|
|
||||||
@event_source(data_class=EventBridgeEvent)
|
@event_source(data_class=EventBridgeEvent)
|
||||||
@@ -28,7 +30,7 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
|||||||
# Post-migration: after removing the stopgap file `patch_course_metadata.py`,
|
# Post-migration: after removing the stopgap file `patch_course_metadata.py`,
|
||||||
# use `access_expires_at` from `new_image`
|
# use `access_expires_at` from `new_image`
|
||||||
access_period = int(
|
access_period = int(
|
||||||
dyn.collection.get_item(
|
course_layer.collection.get_item(
|
||||||
KeyPair(
|
KeyPair(
|
||||||
pk=new_image['course']['id'],
|
pk=new_image['course']['id'],
|
||||||
sk=SortKey('0', path_spec='access_period'),
|
sk=SortKey('0', path_spec='access_period'),
|
||||||
@@ -36,7 +38,7 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
with dyn.transact_writer() as transact:
|
with enrollment_layer.transact_writer() as transact:
|
||||||
transact.put(
|
transact.put(
|
||||||
item={
|
item={
|
||||||
'id': enrollment_id,
|
'id': enrollment_id,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
|||||||
terms = user_layer.get_item(
|
terms = user_layer.get_item(
|
||||||
# Post-migration (users): uncomment the following line
|
# Post-migration (users): uncomment the following line
|
||||||
# KeyPair(new_image['org_id'], 'METADATA#BILLING_TERMS'),
|
# KeyPair(new_image['org_id'], 'METADATA#BILLING_TERMS'),
|
||||||
KeyPair(new_image['tenant_id'], 'metadata#billing_policy'),
|
KeyPair(new_image['org_id'], 'metadata#billing_policy'),
|
||||||
)
|
)
|
||||||
|
|
||||||
if not terms:
|
if not terms:
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class Enrollment(BaseModel):
|
|||||||
return super().model_dump(
|
return super().model_dump(
|
||||||
exclude={
|
exclude={
|
||||||
'user': {'email_verified'},
|
'user': {'email_verified'},
|
||||||
'course': {'cert', 'access_period'},
|
'course': {'cert'},
|
||||||
},
|
},
|
||||||
*args,
|
*args,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
|
|||||||
@@ -252,6 +252,8 @@ Resources:
|
|||||||
Policies:
|
Policies:
|
||||||
- DynamoDBCrudPolicy:
|
- DynamoDBCrudPolicy:
|
||||||
TableName: !Ref EnrollmentTable
|
TableName: !Ref EnrollmentTable
|
||||||
|
- DynamoDBReadPolicy:
|
||||||
|
TableName: !Ref CourseTable
|
||||||
Events:
|
Events:
|
||||||
DynamoDBEvent:
|
DynamoDBEvent:
|
||||||
Type: EventBridgeRule
|
Type: EventBridgeRule
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
USER_TABLE: str = os.getenv('USER_TABLE') # type: ignore
|
USER_TABLE: str = os.getenv('USER_TABLE') # type: ignore
|
||||||
|
COURSE_TABLE: str = os.getenv('COURSE_TABLE') # type: ignore
|
||||||
ENROLLMENT_TABLE: str = os.getenv('ENROLLMENT_TABLE') # type: ignore
|
ENROLLMENT_TABLE: str = os.getenv('ENROLLMENT_TABLE') # type: ignore
|
||||||
|
|
||||||
KONVIVA_API_URL: str = os.getenv('KONVIVA_API_URL') # type: ignore
|
KONVIVA_API_URL: str = os.getenv('KONVIVA_API_URL') # type: ignore
|
||||||
|
|||||||
@@ -10,6 +10,12 @@ from layercake.dateutils import now, ttl
|
|||||||
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair, SortKey, TransactKey
|
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair, SortKey, TransactKey
|
||||||
from layercake.strutils import md5_hash
|
from layercake.strutils import md5_hash
|
||||||
|
|
||||||
|
from boto3clients import dynamodb_client
|
||||||
|
from config import COURSE_TABLE
|
||||||
|
|
||||||
|
# @TODO Find a better way
|
||||||
|
course_layer = DynamoDBPersistenceLayer(COURSE_TABLE, dynamodb_client)
|
||||||
|
|
||||||
|
|
||||||
def update_progress(
|
def update_progress(
|
||||||
id: str,
|
id: str,
|
||||||
@@ -106,11 +112,6 @@ def set_score(
|
|||||||
enrollment = dynamodb_persistence_layer.collection.get_items(
|
enrollment = dynamodb_persistence_layer.collection.get_items(
|
||||||
TransactKey(id)
|
TransactKey(id)
|
||||||
+ SortKey('0')
|
+ SortKey('0')
|
||||||
+ SortKey(
|
|
||||||
sk='METADATA#COURSE',
|
|
||||||
# Prevent conflicts with `course`
|
|
||||||
rename_key='metadata__course',
|
|
||||||
)
|
|
||||||
+ SortKey(
|
+ SortKey(
|
||||||
sk='METADATA#DEDUPLICATION_WINDOW',
|
sk='METADATA#DEDUPLICATION_WINDOW',
|
||||||
path_spec='offset_days',
|
path_spec='offset_days',
|
||||||
@@ -119,6 +120,14 @@ def set_score(
|
|||||||
)
|
)
|
||||||
user_id = enrollment['user']['id']
|
user_id = enrollment['user']['id']
|
||||||
course_id = glom(enrollment, 'course.id')
|
course_id = glom(enrollment, 'course.id')
|
||||||
|
exp_interval = course_layer.collection.get_item(
|
||||||
|
KeyPair(
|
||||||
|
pk=course_id,
|
||||||
|
sk=SortKey('0', path_spec='cert.exp_interval'),
|
||||||
|
),
|
||||||
|
raise_on_error=False,
|
||||||
|
default=0,
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if score >= 70:
|
if score >= 70:
|
||||||
@@ -129,9 +138,7 @@ def set_score(
|
|||||||
progress=progress,
|
progress=progress,
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
course_id=course_id,
|
course_id=course_id,
|
||||||
cert_exp_interval=int(
|
cert_exp_interval=int(exp_interval),
|
||||||
glom(enrollment, 'metadata__course.cert.exp_interval', default=0)
|
|
||||||
),
|
|
||||||
dedup_window_offset_days=int(enrollment['dedup_window_offset_days']),
|
dedup_window_offset_days=int(enrollment['dedup_window_offset_days']),
|
||||||
dynamodb_persistence_layer=dynamodb_persistence_layer,
|
dynamodb_persistence_layer=dynamodb_persistence_layer,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ Parameters:
|
|||||||
EnrollmentTable:
|
EnrollmentTable:
|
||||||
Type: String
|
Type: String
|
||||||
Default: betaeducacao-prod-enrollments
|
Default: betaeducacao-prod-enrollments
|
||||||
|
CourseTable:
|
||||||
|
Type: String
|
||||||
|
Default: saladeaula_courses
|
||||||
|
|
||||||
Globals:
|
Globals:
|
||||||
Function:
|
Function:
|
||||||
@@ -27,6 +30,7 @@ Globals:
|
|||||||
POWERTOOLS_LOGGER_LOG_EVENT: true
|
POWERTOOLS_LOGGER_LOG_EVENT: true
|
||||||
USER_TABLE: !Ref UserTable
|
USER_TABLE: !Ref UserTable
|
||||||
ENROLLMENT_TABLE: !Ref EnrollmentTable
|
ENROLLMENT_TABLE: !Ref EnrollmentTable
|
||||||
|
COURSE_TABLE: !Ref CourseTable
|
||||||
KONVIVA_API_URL: https://lms.saladeaula.digital
|
KONVIVA_API_URL: https://lms.saladeaula.digital
|
||||||
KONVIVA_SECRET_KEY: "{{resolve:ssm:/betaeducacao/konviva/secret_key/str}}"
|
KONVIVA_SECRET_KEY: "{{resolve:ssm:/betaeducacao/konviva/secret_key/str}}"
|
||||||
|
|
||||||
@@ -58,6 +62,8 @@ Resources:
|
|||||||
Policies:
|
Policies:
|
||||||
- DynamoDBCrudPolicy:
|
- DynamoDBCrudPolicy:
|
||||||
TableName: !Ref EnrollmentTable
|
TableName: !Ref EnrollmentTable
|
||||||
|
- DynamoDBReadPolicy:
|
||||||
|
TableName: !Ref CourseTable
|
||||||
Events:
|
Events:
|
||||||
Post:
|
Post:
|
||||||
Type: HttpApi
|
Type: HttpApi
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ def pytest_configure():
|
|||||||
os.environ['DYNAMODB_PARTITION_KEY'] = PK
|
os.environ['DYNAMODB_PARTITION_KEY'] = PK
|
||||||
os.environ['DYNAMODB_SORT_KEY'] = SK
|
os.environ['DYNAMODB_SORT_KEY'] = SK
|
||||||
os.environ['USER_TABLE'] = PYTEST_TABLE_NAME
|
os.environ['USER_TABLE'] = PYTEST_TABLE_NAME
|
||||||
|
os.environ['COURSE_TABLE'] = PYTEST_TABLE_NAME
|
||||||
os.environ['ENROLLMENT_TABLE'] = PYTEST_TABLE_NAME
|
os.environ['ENROLLMENT_TABLE'] = PYTEST_TABLE_NAME
|
||||||
os.environ['KONVIVA_API_URL'] = 'https://lms.saladeaula.digital'
|
os.environ['KONVIVA_API_URL'] = 'https://lms.saladeaula.digital'
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
// Users
|
// Users
|
||||||
{"id": "123", "sk": "0"}
|
{"id": "123", "sk": "0"}
|
||||||
|
|
||||||
|
// Courses
|
||||||
|
{"id": "432", "sk": "0", "access_period": 360, "cert": {"exp_interval": 365}, "created_at": "2025-04-06T11:07:32.762178-03:00"}
|
||||||
|
|
||||||
|
|
||||||
// Enrollments
|
// Enrollments
|
||||||
{"id": "197991aa-52e2-4e0c-b2a4-a7c53bcfee02", "sk": "0", "progress": 10, "status": "IN_PROGRESS"}
|
{"id": "197991aa-52e2-4e0c-b2a4-a7c53bcfee02", "sk": "0", "progress": 10, "status": "IN_PROGRESS"}
|
||||||
|
|
||||||
@@ -11,18 +15,15 @@
|
|||||||
{"id": "d9da85f2-e09f-472d-9515-3d91d70f1e8a", "sk": "SCHEDULE#REMINDER_NO_ACCESS_AFTER_3_DAYS"}
|
{"id": "d9da85f2-e09f-472d-9515-3d91d70f1e8a", "sk": "SCHEDULE#REMINDER_NO_ACCESS_AFTER_3_DAYS"}
|
||||||
|
|
||||||
{"id": "6c7e3d9b-f5d1-4da4-9e55-0825bb6ff2b8", "sk": "0", "progress": 80, "status": "IN_PROGRESS", "user": {"id": "123", "name": "Myles Kennedy"}, "course": {"id": "432", "name": "pytest"}, "created_at": "2022-04-06T11:07:32.762178-03:00"}
|
{"id": "6c7e3d9b-f5d1-4da4-9e55-0825bb6ff2b8", "sk": "0", "progress": 80, "status": "IN_PROGRESS", "user": {"id": "123", "name": "Myles Kennedy"}, "course": {"id": "432", "name": "pytest"}, "created_at": "2022-04-06T11:07:32.762178-03:00"}
|
||||||
{"id": "6c7e3d9b-f5d1-4da4-9e55-0825bb6ff2b8", "sk": "METADATA#COURSE", "access_period": 360, "cert": {"exp_interval": 365}, "created_at": "2025-04-06T11:07:32.762178-03:00"}
|
|
||||||
{"id": "6c7e3d9b-f5d1-4da4-9e55-0825bb6ff2b8", "sk": "METADATA#DEDUPLICATION_WINDOW", "offset_days": 90, "created_at": "2025-04-06T11:07:32.762178-03:00"}
|
{"id": "6c7e3d9b-f5d1-4da4-9e55-0825bb6ff2b8", "sk": "METADATA#DEDUPLICATION_WINDOW", "offset_days": 90, "created_at": "2025-04-06T11:07:32.762178-03:00"}
|
||||||
{"id": "6c7e3d9b-f5d1-4da4-9e55-0825bb6ff2b8", "sk": "SCHEDULE#REMINDER_ACCESS_PERIOD_BEFORE_30_DAYS"}
|
{"id": "6c7e3d9b-f5d1-4da4-9e55-0825bb6ff2b8", "sk": "SCHEDULE#REMINDER_ACCESS_PERIOD_BEFORE_30_DAYS"}
|
||||||
{"id": "6c7e3d9b-f5d1-4da4-9e55-0825bb6ff2b8", "sk": "SCHEDULE#SET_ACCESS_EXPIRED"}
|
{"id": "6c7e3d9b-f5d1-4da4-9e55-0825bb6ff2b8", "sk": "SCHEDULE#SET_ACCESS_EXPIRED"}
|
||||||
|
|
||||||
{"id": "cc2c3bce-c34a-4e82-aa6c-1a19e70ec5ae", "sk": "0", "progress": 109, "status": "COMPLETED", "user": {"id": "321", "name": "Chester Bennington"}, "course": {"id": "432", "name": "pytest"}, "created_at": "2022-04-06T11:07:32.762178-03:00"}
|
{"id": "cc2c3bce-c34a-4e82-aa6c-1a19e70ec5ae", "sk": "0", "progress": 109, "status": "COMPLETED", "user": {"id": "321", "name": "Chester Bennington"}, "course": {"id": "432", "name": "pytest"}, "created_at": "2022-04-06T11:07:32.762178-03:00"}
|
||||||
{"id": "cc2c3bce-c34a-4e82-aa6c-1a19e70ec5ae", "sk": "METADATA#COURSE", "access_period": 360, "cert": {"exp_interval": 365}, "created_at": "2025-04-06T11:07:32.762178-03:00"}
|
|
||||||
{"id": "cc2c3bce-c34a-4e82-aa6c-1a19e70ec5ae", "sk": "METADATA#DEDUPLICATION_WINDOW", "offset_days": 90, "created_at": "2025-04-06T11:07:32.762178-03:00"}
|
{"id": "cc2c3bce-c34a-4e82-aa6c-1a19e70ec5ae", "sk": "METADATA#DEDUPLICATION_WINDOW", "offset_days": 90, "created_at": "2025-04-06T11:07:32.762178-03:00"}
|
||||||
{"id": "cc2c3bce-c34a-4e82-aa6c-1a19e70ec5ae", "sk": "SCHEDULE#SET_AS_ARCHIVED"}
|
{"id": "cc2c3bce-c34a-4e82-aa6c-1a19e70ec5ae", "sk": "SCHEDULE#SET_AS_ARCHIVED"}
|
||||||
|
|
||||||
{"id": "5db53b35-0bae-4907-afda-a213cb5bf651", "sk": "0", "progress": 0, "status": "PENDING", "user": {"id": "1234", "name": "Michael Jackinson"}, "course": {"id": "432", "name": "pytest"}, "created_at": "2022-04-06T11:07:32.762178-03:00"}
|
{"id": "5db53b35-0bae-4907-afda-a213cb5bf651", "sk": "0", "progress": 0, "status": "PENDING", "user": {"id": "1234", "name": "Michael Jackinson"}, "course": {"id": "432", "name": "pytest"}, "created_at": "2022-04-06T11:07:32.762178-03:00"}
|
||||||
{"id": "5db53b35-0bae-4907-afda-a213cb5bf651", "sk": "METADATA#COURSE", "access_period": 360, "cert": {"exp_interval": 365}, "created_at": "2025-04-06T11:07:32.762178-03:00"}
|
|
||||||
|
|
||||||
// To relate with the enrollment
|
// To relate with the enrollment
|
||||||
{"id": "konviva", "sk": "123", "enrollment_id": "d9da85f2-e09f-472d-9515-3d91d70f1e8a"}
|
{"id": "konviva", "sk": "123", "enrollment_id": "d9da85f2-e09f-472d-9515-3d91d70f1e8a"}
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ def test_set_as_completed(
|
|||||||
|
|
||||||
docx = next((x for x in r['items'] if x['sk'] == '0'), {})
|
docx = next((x for x in r['items'] if x['sk'] == '0'), {})
|
||||||
assert 'completed_at' in docx
|
assert 'completed_at' in docx
|
||||||
assert len(r['items']) == 7
|
assert len(r['items']) == 6
|
||||||
assert any(item.get('sk') == 'LOCK' for item in r['items'])
|
assert any(item.get('sk') == 'LOCK' for item in r['items'])
|
||||||
assert any(
|
assert any(
|
||||||
item.get('sk') == 'SCHEDULE#REMINDER_CERT_EXPIRATION_BEFORE_30_DAYS'
|
item.get('sk') == 'SCHEDULE#REMINDER_CERT_EXPIRATION_BEFORE_30_DAYS'
|
||||||
|
|||||||
Reference in New Issue
Block a user