This commit is contained in:
2025-07-01 18:24:28 -03:00
parent a9f6a89d54
commit 0a6db8bc48
18 changed files with 170 additions and 352 deletions

View File

@@ -3,4 +3,14 @@ import os
USER_TABLE: str = os.getenv('USER_TABLE') # type: ignore
ORDER_TABLE: str = os.getenv('ORDER_TABLE') # type: ignore
ENROLLMENT_TABLE: str = os.getenv('ENROLLMENT_TABLE') # type: ignore
NEW_ENROLLMENT_TABLE: str = os.getenv('NEW_ENROLLMENT_TABLE') # type: ignore
COURSE_TABLE: str = os.getenv('COURSE_TABLE') # type: ignore
# Post-migration: remove the lines below
if os.getenv('AWS_LAMBDA_FUNCTION_NAME'):
SQLITE_DATABASE = 'courses_export_2025-06-18_110214.db'
else:
SQLITE_DATABASE = 'app/courses_export_2025-06-18_110214.db'
SQLITE_TABLE = 'courses'
OLD_ENROLLMENT_TABLE: str = os.getenv('OLD_ENROLLMENT_TABLE') # type: ignore

View File

@@ -1,14 +0,0 @@
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
logger = Logger(__name__)
@event_source(data_class=EventBridgeEvent)
@logger.inject_lambda_context
def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> None:
"""Send an email when the access period expires"""

View File

@@ -1,13 +0,0 @@
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
logger = Logger(__name__)
@event_source(data_class=EventBridgeEvent)
@logger.inject_lambda_context
def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> None: ...

View File

@@ -1,14 +0,0 @@
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
logger = Logger(__name__)
@event_source(data_class=EventBridgeEvent)
@logger.inject_lambda_context
def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> None:
"""Send an email when there is no activity 7 days after the first access"""

View File

@@ -1,14 +0,0 @@
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
logger = Logger(__name__)
@event_source(data_class=EventBridgeEvent)
@logger.inject_lambda_context
def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> None:
"""Send reminder email if the user does not access within 3 days"""

View File

@@ -1,45 +0,0 @@
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.dateutils import now
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair
from boto3clients import dynamodb_client
from config import ENROLLMENT_TABLE
logger = Logger(__name__)
enrollment_layer = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client)
@event_source(data_class=EventBridgeEvent)
@logger.inject_lambda_context
def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
new_image = event.detail['new_image']
now_ = now()
with enrollment_layer.transact_writer() as transact:
transact.update(
key=KeyPair(new_image['id'], '0'),
update_expr='SET #status = :archived, update_date = :update_date',
cond_expr='#status = :completed',
expr_attr_names={
'#status': 'status',
},
expr_attr_values={
':archived': 'ARCHIVED',
':completed': 'COMPLETED',
':update_date': now_,
},
)
transact.put(
item={
'id': new_image['id'],
'sk': 'archived_date',
'create_date': now_,
},
)
return True

View File

@@ -1,46 +0,0 @@
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.dateutils import now
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair
from boto3clients import dynamodb_client
from config import ENROLLMENT_TABLE
logger = Logger(__name__)
enrollment_layer = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client)
@event_source(data_class=EventBridgeEvent)
@logger.inject_lambda_context
def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
new_image = event.detail['new_image']
now_ = now()
with enrollment_layer.transact_writer() as transact:
transact.update(
key=KeyPair(new_image['id'], '0'),
update_expr='SET #status = :expired, update_date = :update_date',
cond_expr='#status IN (:pending, :in_progress)',
expr_attr_names={
'#status': 'status',
},
expr_attr_values={
':expired': 'EXPIRED',
':pending': 'PENDING',
':in_progress': 'IN_PROGRESS',
':update_date': now_,
},
)
transact.put(
item={
'id': new_image['id'],
'sk': 'expired_date',
'create_date': now_,
},
)
return True

View File

@@ -1,69 +0,0 @@
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 (
ComposeKey,
DynamoDBPersistenceLayer,
KeyPair,
SortKey,
TransactKey,
)
from boto3clients import dynamodb_client
from config import ENROLLMENT_TABLE, ORDER_TABLE, USER_TABLE
logger = Logger(__name__)
user_layer = DynamoDBPersistenceLayer(USER_TABLE, dynamodb_client)
order_layer = DynamoDBPersistenceLayer(ORDER_TABLE, dynamodb_client)
enrollment_layer = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client)
@event_source(data_class=EventBridgeEvent)
@logger.inject_lambda_context
def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
new_image = event.detail['new_image']
order_id = new_image['id']
data = order_layer.collection.get_items(
TransactKey(order_id)
+ SortKey('0')
+ KeyPair(
pk=order_id,
sk=SortKey(
sk='metadata#tenant',
path_spec='tenant_id',
remove_prefix='metadata#',
),
rename_key='tenant_id',
)
)
total = data['total']
tenant_id = data['tenant_id'].removeprefix('ORG#')
policy = user_layer.collection.get_item(
KeyPair(pk=tenant_id, sk='metadata#billing_policy'),
raise_on_error=False,
default=False,
)
if not policy or total <= 0:
return False
result = enrollment_layer.collection.query(
KeyPair(
ComposeKey(tenant_id, prefix='vacancies'),
order_id,
)
)
with enrollment_layer.batch_writer() as batch:
for pair in result['items']:
batch.delete_item(
Key={
'id': {'S': ComposeKey(pair['id'], prefix='vacancies')},
'sk': {'S': pair['sk']},
}
)
return True

View File

@@ -1,14 +1,59 @@
import json
import sqlite3
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
from sqlite_utils import Database
from boto3clients import dynamodb_client
from config import (
COURSE_TABLE,
ENROLLMENT_TABLE,
SQLITE_DATABASE,
SQLITE_TABLE,
)
sqlite3.register_converter('json', json.loads)
logger = Logger(__name__)
enrollment_layer = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client)
course_layer = DynamoDBPersistenceLayer(COURSE_TABLE, dynamodb_client)
deduplication_window = {'offset_days': 90}
class DeduplicationConflictError(Exception):
def __init__(self, *args):
super().__init__('Enrollment already exists')
@event_source(data_class=EventBridgeEvent)
@logger.inject_lambda_context
def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
new_image = event.detail['new_image']
return True
class CourseNotFoundError(Exception):
def __init__(self, *args):
super().__init__('Course not found')
def _get_course(course_id: str) -> dict:
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