From ac07ee0101da148421ba3768728ed4a22ce69e38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Rafael=20Siqueira?= Date: Mon, 8 Sep 2025 17:32:28 -0300 Subject: [PATCH] add download to issued cert --- http-api/app/app.py | 1 + http-api/app/boto3clients.py | 15 +- http-api/app/config.py | 16 +- http-api/app/elastic.py | 46 ---- http-api/app/routes/enrollments/__init__.py | 3 +- .../enrollments/download_issued_cert.py | 27 +++ http-api/cli/seeds.py | 4 +- http-api/env.json | 4 +- http-api/pyproject.toml | 2 +- http-api/seeds/test-enrollments.jsonl | 112 +-------- http-api/template.yaml | 9 +- http-api/tests/conftest.py | 1 + http-api/tests/routes/test_enrollments.py | 19 ++ http-api/uv.lock | 16 +- order-events/app/events/billing/template.html | 219 ------------------ 15 files changed, 94 insertions(+), 400 deletions(-) delete mode 100644 http-api/app/elastic.py create mode 100644 http-api/app/routes/enrollments/download_issued_cert.py delete mode 100644 order-events/app/events/billing/template.html diff --git a/http-api/app/app.py b/http-api/app/app.py index ee8d048..cc4004a 100644 --- a/http-api/app/app.py +++ b/http-api/app/app.py @@ -58,6 +58,7 @@ app.include_router(enrollments.slots, prefix='/enrollments') app.include_router(enrollments.enroll, prefix='/enrollments') app.include_router(enrollments.cancel, prefix='/enrollments') app.include_router(enrollments.deduplication_window, prefix='/enrollments') +app.include_router(enrollments.issued_cert, prefix='/enrollments') app.include_router(orders.router, prefix='/orders') app.include_router(users.router, prefix='/users') app.include_router(users.add, prefix='/users') diff --git a/http-api/app/boto3clients.py b/http-api/app/boto3clients.py index f9134cd..1c95cb0 100644 --- a/http-api/app/boto3clients.py +++ b/http-api/app/boto3clients.py @@ -1,7 +1,17 @@ import os +from typing import TYPE_CHECKING import boto3 +if TYPE_CHECKING: + from mypy_boto3_cognito_idp.client import CognitoIdentityProviderClient + from mypy_boto3_dynamodb.client import DynamoDBClient + from mypy_boto3_s3 import S3Client +else: + CognitoIdentityProviderClient = object + DynamoDBClient = object + S3Client = object + def get_dynamodb_client(): running_sam_local = os.getenv('AWS_SAM_LOCAL') @@ -16,5 +26,6 @@ def get_dynamodb_client(): return boto3.client('dynamodb', endpoint_url=f'http://{host}:8000') -dynamodb_client = get_dynamodb_client() -idp_client = boto3.client('cognito-idp') +s3_client: S3Client = boto3.client('s3') +dynamodb_client: DynamoDBClient = get_dynamodb_client() +idp_client: CognitoIdentityProviderClient = boto3.client('cognito-idp') diff --git a/http-api/app/config.py b/http-api/app/config.py index 1174d19..5d47207 100644 --- a/http-api/app/config.py +++ b/http-api/app/config.py @@ -3,9 +3,10 @@ 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 +BUCKET_NAME: str = os.getenv('BUCKET_NAME') # type: ignore + KONVIVA_API_URL: str = os.getenv('KONVIVA_API_URL') # type: ignore KONVIVA_SECRET_KEY: str = os.getenv('KONVIVA_SECRET_KEY') # type: ignore @@ -16,22 +17,9 @@ MEILISEARCH_API_KEY: str = os.getenv('MEILISEARCH_API_KEY') # type: ignore match os.getenv('AWS_SAM_LOCAL'), os.getenv('PYTEST_VERSION'): case str() as SAM_LOCAL, _ if SAM_LOCAL: # Only when running `sam local start-api` MEILISEARCH_HOST = 'http://host.docker.internal:7700' - ELASTIC_CONN = { - 'hosts': 'http://host.docker.internal:9200', - } case _, str() as PYTEST if PYTEST: # Only when running `pytest` MEILISEARCH_HOST = 'http://127.0.0.1:7700' - ELASTIC_CONN = { - 'hosts': 'http://127.0.0.1:9200', - } case _: MEILISEARCH_HOST: str = os.getenv('MEILISEARCH_HOST') # type: ignore - ELASTIC_CLOUD_ID = os.getenv('ELASTIC_CLOUD_ID') - ELASTIC_AUTH_PASS = os.getenv('ELASTIC_AUTH_PASS') - ELASTIC_CONN = { - 'cloud_id': ELASTIC_CLOUD_ID, - 'basic_auth': ('elastic', ELASTIC_AUTH_PASS), - } - USER_POOOL_ID = 'sa-east-1_s6YmVSfXj' diff --git a/http-api/app/elastic.py b/http-api/app/elastic.py deleted file mode 100644 index 00285bd..0000000 --- a/http-api/app/elastic.py +++ /dev/null @@ -1,46 +0,0 @@ -import math -from typing import TypedDict - -from elasticsearch import Elasticsearch -from elasticsearch_dsl import Search - -MAX_PAGE_SIZE = 100 - - -class PaginatedResult(TypedDict): - total_items: int - total_pages: int - items: list[dict] - - -def search( - index: str, - *, - query: dict, - page_size: int = 25, - elastic_client: Elasticsearch, -) -> PaginatedResult: - if page_size > MAX_PAGE_SIZE: - page_size = MAX_PAGE_SIZE - - s = Search( - using=elastic_client, - index=index, - ) - s.update_from_dict(query) - s.extra(size=page_size) - - try: - r = s.execute() - except Exception: - return { - 'total_items': 0, - 'total_pages': 0, - 'items': [], - } - else: - return { - 'total_items': r.hits.total.value, # type: ignore - 'total_pages': math.ceil(r.hits.total.value / page_size), # type: ignore - 'items': [hit.to_dict() for hit in r], - } diff --git a/http-api/app/routes/enrollments/__init__.py b/http-api/app/routes/enrollments/__init__.py index 6014fc6..b64564d 100644 --- a/http-api/app/routes/enrollments/__init__.py +++ b/http-api/app/routes/enrollments/__init__.py @@ -15,10 +15,11 @@ from middlewares import Tenant, TenantMiddleware from .cancel import router as cancel from .deduplication_window import router as deduplication_window +from .download_issued_cert import router as issued_cert from .enroll import router as enroll from .slots import router as slots -__all__ = ['slots', 'cancel', 'enroll', 'deduplication_window'] +__all__ = ['slots', 'cancel', 'enroll', 'deduplication_window', 'issued_cert'] router = Router() diff --git a/http-api/app/routes/enrollments/download_issued_cert.py b/http-api/app/routes/enrollments/download_issued_cert.py new file mode 100644 index 0000000..e208738 --- /dev/null +++ b/http-api/app/routes/enrollments/download_issued_cert.py @@ -0,0 +1,27 @@ +from aws_lambda_powertools.event_handler.api_gateway import Router +from layercake.dynamodb import DynamoDBPersistenceLayer + +from boto3clients import dynamodb_client, s3_client +from config import BUCKET_NAME, ENROLLMENT_TABLE + +EXPIRES_IN = 300 + +router = Router() +enrollment_layer = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client) + + +@router.get('//download') +def download(id: str): + params = { + 'Bucket': BUCKET_NAME, + 'Key': f'issuedcerts/{id}.pdf', + 'ResponseContentDisposition': f'attachment; filename="{id}.pdf"', + } + + return { + 'presigned_url': s3_client.generate_presigned_url( + 'get_object', + Params=params, + ExpiresIn=EXPIRES_IN, + ) + } diff --git a/http-api/cli/seeds.py b/http-api/cli/seeds.py index f13cd3b..c314761 100644 --- a/http-api/cli/seeds.py +++ b/http-api/cli/seeds.py @@ -12,9 +12,8 @@ meili_client = Meilisearch('http://127.0.0.1:7700') JSONL_FILES = ( - # 'test-orders.jsonl', 'test-users.jsonl', - # 'test-enrollments.jsonl', + 'test-enrollments.jsonl', 'test-courses.jsonl', ) @@ -63,6 +62,7 @@ if __name__ == '__main__': reader = jsonlines.Reader(fp).iter(skip_invalid=True) for line in tqdm(reader, desc=f'Processing lines in {file}'): + print(table_name, line) put_item(line, table_name, dynamodb_client) # type: ignore # Scan DynamoDB tables and index the data into Meilisearch diff --git a/http-api/env.json b/http-api/env.json index f8e9a33..110e1d5 100644 --- a/http-api/env.json +++ b/http-api/env.json @@ -4,7 +4,7 @@ "USER_TABLE": "test-users", "ORDER_TABLE": "test-orders", "ENROLLMENT_TABLE": "test-enrollments", - "NEW_ENROLLMENT_TABLE": "test-enrollments", - "COURSE_TABLE": "test-courses" + "COURSE_TABLE": "test-courses", + "BUCKET_NAME": "saladeaula.digital" } } diff --git a/http-api/pyproject.toml b/http-api/pyproject.toml index 214d7df..927d791 100644 --- a/http-api/pyproject.toml +++ b/http-api/pyproject.toml @@ -8,7 +8,7 @@ dependencies = ["layercake"] [dependency-groups] dev = [ - "boto3-stubs[essential]>=1.38.26", + "boto3-stubs[cognito-idp,essential]>=1.38.26", "jsonlines>=4.0.0", "psycopg2-binary>=2.9.10", "pycouchdb>=1.16.0", diff --git a/http-api/seeds/test-enrollments.jsonl b/http-api/seeds/test-enrollments.jsonl index 16274a8..8b38d3c 100644 --- a/http-api/seeds/test-enrollments.jsonl +++ b/http-api/seeds/test-enrollments.jsonl @@ -1,108 +1,4 @@ -{"id": {"S": "70337adf-ddb3-4960-95b7-978cab05dcfe"}, "sk": {"S": "0"}, "status": {"S": "PENDING"}, "progress": {"N": "0"}, "user": {"M": {"id": {"S": "5OxmMjL-ujoR5IMGegQz"}, "name": {"S": "Sérgio R Siqueira"}, "email": {"S": "sergio@somosbeta.com.br"},"cpf": {"S": "07879819908"}}}, "course": {"M": {"id": {"S": "2c1e724a-58c6-4c20-90df-18b5660d6304"}, "name": {"S":"Noções em Primeiros Socorros"}}}, "created_at": {"S": "2025-05-20T12:27:09.221021-03:00"}, "metadata__tenant_id": {"S": "cJtK9SsnJhKPyxESe7g3DG"}} -{"id": {"S": "70337adf-ddb3-4960-95b7-978cab05dcfe"}, "sk": {"S": "related_ids#org"}, "org_id": {"S": "cJtK9SsnJhKPyxESe7g3DG"}, "created_at": {"S": "2025-05-20T12:27:09.221021-03:00"}} -{"id": {"S": "70337adf-ddb3-4960-95b7-978cab05dcfe"}, "sk": {"S": "related_ids#order"}, "order_id": {"S": "EAooRtYH5XHm6ajWUsyJh6"}, "created_at": {"S": "2025-05-20T12:27:09.221021-03:00"}} -{"id": {"S": "70337adf-ddb3-4960-95b7-978cab05dcfe"}, "sk": {"S": "parent_vacancy"}, "vacancy": {"M": {"id": {"S": "vacancies#FT6537qmMNaSfxmqZu9xDG"}, "sk": {"S": "EAooRtYH5XHm6ajWUsyJh6#7FAfmYdCha4nTHDWU3wtrz"}}}} -{"id": {"S": "70337adf-ddb3-4960-95b7-978cab05dcfe"}, "sk": {"S": "metadata#tenant"}, "created_at": {"S": "2025-05-20T12:27:09.221021-03:00"}, "name": {"S": "Beta Educação"}, "tenant_id": {"S": "cJtK9SsnJhKPyxESe7g3DG"}} -{"id": {"S": "70337adf-ddb3-4960-95b7-978cab05dcfe"}, "sk": {"S": "metadata#lock"}, "created_at": {"S": "2025-05-20T12:27:09.221021-03:00"}, "hash": {"S": "d239d03ce8463483a3a80a6b335a6ea7"}, "ttl": {"N": "1776266829"}, "ttl_date": {"S": "2026-04-15T12:27:09.221021-03:00"}} -{"id": {"S": "70337adf-ddb3-4960-95b7-978cab05dcfe"}, "sk": {"S": "metadata#cancel_policy"}, "created_at": {"S": "2025-05-20T12:27:09.221021-03:00"}} -{"id": {"S": "70337adf-ddb3-4960-95b7-978cab05dcfe"}," sk": {"S": "metadata#konviva"}, "created_at": {"S": "2025-05-20T12:27:10.986137-03:00"}, "user_id": {"N": "239359"}} -{"id": {"S": "70337adf-ddb3-4960-95b7-978cab05dcfe"}, "sk": {"S": "metadata#author"}, "created_at": {"S": "2025-05-20T12:27:09.221021-03:00"},"name": {"S": "Sérgio R Siqueira"},"user_id": {"S": "5OxmMjL-ujoR5IMGegQz"}} -{"id": {"S": "70337adf-ddb3-4960-95b7-978cab05dcfe"}, "sk": {"S": "schedules#access_period_reminder_30_days"}, "course": {"S": "Noções em Primeiros Socorros"}, "created_at": {"S": "2025-05-20T12:27:09.221021-03:00"}, "email": {"S": "osergiosiqueira@gmail.com"},"name": {"S": "Sérgio R Siqueira"},"ttl": {"N": "1776266829"} -{"id": {"S": "70337adf-ddb3-4960-95b7-978cab05dcfe"}, "sk": {"S": "schedules#reminder_no_access_3_days"}, "course": {"S": "Noções em Primeiros Socorros"}, "created_at": {"S": "2025-05-20T12:27:09.221021-03:00"}, "email": {"S": "osergiosiqueira@gmail.com"},"name": {"S": "Sérgio R Siqueira"},"ttl": {"N": "1748014029"}} -{"id": {"S": "70337adf-ddb3-4960-95b7-978cab05dcfe"}, "sk": {"S": "lock"}, "hash": {"S": "000c8575e1508c2c66c4faa7818b0e77"}, "ttl": {"N": "1779537056"}} -{"id": {"S": "WRBj3FV7iGoxRwt63fALYd"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "12047"}, "name": {"S": "Junior Celetino Pires"}, "email": {"S": "juninhocpires@yahoo.com.br"}, "cpf": {"S": "06001201633"}}}, "course": {"M": {"id": {"S": "55"}, "name": {"S": "NR-10 Complementar (SEP)"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2016-05-16T00:00:00"}, "update_date": {"S": "2019-01-16T10:36:53"}} -{"id": {"S": "nshu3G7ndUofcy7TtEvZeM"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "98"}, "user": {"M": {"id": {"S": "99523191500"}, "name": {"S": "ADELSON DE OLIVEIRA SANTOS"}, "email": {"S": "99523191500@users.noreply.betaeducacao.com.br"}, "cpf": {"S": "99523191500"}}}, "course": {"M": {"id": {"S": "dc1a0428-47bf-4db1-a5da-24be49c9fda6"}, "name": {"S": "NR-11 \u2013 Transporte, movimenta\u00e7\u00e3o, armazenagem e manuseio de materiais"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2019-09-17T09:42:19"}, "update_date": {"S": "2020-09-03T18:36:44"}} -{"id": {"S": "W7Wzqr6jeMBgvmPCUm62UW"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "88"}, "user": {"M": {"id": {"S": "b70ca900-885e-4aca-a3ef-ceee3b2974d6"}, "name": {"S": "JOICE RIBEIRO ROCHA"}, "email": {"S": "joicerrocha@hotmail.com"}, "cpf": {"S": "12599815762"}}}, "course": {"M": {"id": {"S": "56d1c710-36b1-4db5-8a7a-dacb7098dbad"}, "name": {"S": "NR-11 Seguran\u00e7a na Opera\u00e7\u00e3o de Rebocadores"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2021-12-14T10:06:10"}, "update_date": {"S": "2021-12-15T09:55:21"}} -{"id": {"S": "edMA6KiRx7X6c3FmQnB5Vx"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "25330"}, "name": {"S": "Rafael Tomaz De Oliveira"}, "email": {"S": "rafael@previnenet.com.br"}, "cpf": {"S": "02488722065"}}}, "course": {"M": {"id": {"S": "54"}, "name": {"S": "NR-33 Trabalhadores Autorizados e Vigias em Espa\u00e7o Confinado"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2018-04-23T00:00:00"}, "update_date": {"S": "2019-01-16T10:44:31"}} -{"id": {"S": "7o93AibeVgPgyJo5GZczNw"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "14096"}, "name": {"S": "Marcos Roberto Francisco Pereira"}, "email": {"S": "marcosrobertofranciscop@gmail.com"}, "cpf": {"S": "04633472933"}}}, "course": {"M": {"id": {"S": "55"}, "name": {"S": "NR-10 Complementar (SEP)"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2016-08-29T00:00:00"}, "update_date": {"S": "2019-01-16T10:38:02"}} -{"id": {"S": "Unu6RqHV2VMckUkr3vmZr9"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "85"}, "user": {"M": {"id": {"S": "5f00cdef-6775-4a5b-90f8-ccc607c7f855"}, "name": {"S": "GILENO XAVIER DOS SANTOS"}, "email": {"S": "gileno.santos@kordsa.com"}, "cpf": {"S": "02174837552"}}}, "course": {"M": {"id": {"S": "54"}, "name": {"S": "NR-33 Trabalhadores Autorizados e Vigias em Espa\u00e7o Confinado"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2021-05-03T11:00:03"}, "update_date": {"S": "2021-09-24T09:58:50"}} -{"id": {"S": "kPXkXso3bPU5mGQs9DEKed"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "96"}, "user": {"M": {"id": {"S": "RAYG2dmH3FeABGQaQ3V8rS"}, "name": {"S": "Ariel da Silva Anestor"}, "email": {"S": "arielanestor@gmail.com"}, "cpf": {"S": "51705911870"}}}, "course": {"M": {"id": {"S": "a6775b71-d68a-4263-8ab4-acb3a4f8a8b9"}, "name": {"S": "NR-18 PEMT PTA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2024-02-19T11:06:38.918762-03:00"}, "update_date": {"S": "2025-02-18T11:20:36.752082-03:00"}} -{"id": {"S": "6o84wYvfFCzQs8Qcv28X4p"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "84"}, "user": {"M": {"id": {"S": "raMwRCA46q5pc4s4Of44"}, "name": {"S": "Renato Donizeti Franco"}, "email": {"S": "renato.donizeti@padtec.com.br"}, "cpf": {"S": "36595610884"}}}, "course": {"M": {"id": {"S": "38"}, "name": {"S": "NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2020-12-03T13:36:01"}, "update_date": {"S": "2020-12-09T15:18:16"}} -{"id": {"S": "7frP85e8F8kc9o3GWpvk7Q"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "82"}, "user": {"M": {"id": {"S": "325b79b1-f8c0-4937-92b8-9955f647ef21"}, "name": {"S": "GUILHERME EDUARDO MARTINS"}, "email": {"S": "guilhermemartins@betaeducacao.com.br"}, "cpf": {"S": "07802359910"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2021-11-23T09:00:27"}, "update_date": {"S": "2023-11-14T00:10:35.972588-03:00"}} -{"id": {"S": "68rUn4CNRZG8YEhFgC7Npa"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "98"}, "user": {"M": {"id": {"S": "bebd851f-4973-49db-a032-12747053cd69"}, "name": {"S": "Marcos Pereira Martins"}, "email": {"S": "marcos.pereira@grupogera.com"}, "cpf": {"S": "01400388686"}}}, "course": {"M": {"id": {"S": "38"}, "name": {"S": "NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2021-07-28T07:58:37"}, "update_date": {"S": "2023-11-28T02:23:04.707953-03:00"}} -{"id": {"S": "X4W7YJULgBEC3xjSakr6nL"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "f6c2db24-fd52-478b-bec0-f0fe7dcb1cb0"}, "name": {"S": "Leonardo Alesi da Silva"}, "email": {"S": "leonardoalesidasilva@gmail.com"}, "cpf": {"S": "09115295940"}}}, "course": {"M": {"id": {"S": "94"}, "name": {"S": "Reciclagem em NR-11 - Operador de Empilhadeira"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2022-03-21T11:00:47"}, "update_date": {"S": "2022-03-21T12:33:52"}} -{"id": {"S": "YqUV2iw2ZimEL8rd2tiqxT"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "19439"}, "name": {"S": "Carlos Alexandre Rosa Da Silva"}, "email": {"S": "carosa@sesc-rs.com.br"}, "cpf": {"S": "00750696010"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2017-04-20T00:00:00"}, "update_date": {"S": "2019-01-16T10:40:26"}} -{"id": {"S": "3kAeHyy8KbPtA27BScac9G"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "88"}, "user": {"M": {"id": {"S": "2bae3df3-e414-4d47-a175-72bb99f00306"}, "name": {"S": "Jasiel Lopes da Silva"}, "email": {"S": "silesia-caixeta@hotmail.com"}, "cpf": {"S": "62633210678"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2021-11-24T15:48:59"}, "update_date": {"S": "2021-11-26T11:31:54"}} -{"id": {"S": "Zffp8eokCn4L7GGuxe8pMW"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "9246"}, "name": {"S": "Marcio Antonio Bombonato"}, "email": {"S": "marcioabombonato@cofcoagri.com"}, "cpf": {"S": "24863201800"}}}, "course": {"M": {"id": {"S": "56"}, "name": {"S": "Reciclagem em NR-10 Complementar (SEP)"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2015-12-01T00:00:00"}, "update_date": {"S": "2019-01-16T16:36:26"}} -{"id": {"S": "HJjGix8ND827jqmpNUELTL"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "87"}, "user": {"M": {"id": {"S": "64bf9c8d-a5a7-4410-ab0a-2472a342d76b"}, "name": {"S": "CARLOS ALFEU FEITOSA FRISSO"}, "email": {"S": "carlos.frisso@gruppoab.com"}, "cpf": {"S": "10170224708"}}}, "course": {"M": {"id": {"S": "55"}, "name": {"S": "NR-10 Complementar (SEP)"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2021-09-27T08:37:05"}, "update_date": {"S": "2023-09-22T11:11:20.577016-03:00"}} -{"id": {"S": "ULwbjEuWLirZod8pvqGRiL"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "94"}, "user": {"M": {"id": {"S": "2411795564"}, "name": {"S": "WELLINGTON DOS SANTOS"}, "email": {"S": "02411795564@users.noreply.betaeducacao.com.br"}, "cpf": {"S": "02411795564"}}}, "course": {"M": {"id": {"S": "dc1a0428-47bf-4db1-a5da-24be49c9fda6"}, "name": {"S": "NR-11 \u2013 Transporte, movimenta\u00e7\u00e3o, armazenagem e manuseio de materiais"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2022-10-10T14:33:32"}, "update_date": {"S": "2023-10-06T14:23:23.930655-03:00"}} -{"id": {"S": "KkXuupYMMzo6TAAPovutjq"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "16508"}, "name": {"S": "Jadir Ferreira"}, "email": {"S": "jadirferreira@hotmail.com"}, "cpf": {"S": "92045898687"}}}, "course": {"M": {"id": {"S": "42"}, "name": {"S": "NR-35 Seguran\u00e7a nos Trabalhos em Altura (Te\u00f3rico)"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2017-01-19T00:00:00"}, "update_date": {"S": "2019-01-16T10:39:30"}} -{"id": {"S": "7BAMVGJYJ7BRqSuzk7qmPr"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "9659"}, "name": {"S": "Norberto Germano"}, "email": {"S": "norbertogermano@gmail.com"}, "cpf": {"S": "58376240820"}}}, "course": {"M": {"id": {"S": "31"}, "name": {"S": "No\u00e7\u00f5es em Inform\u00e1tica: Pr\u00e1ticas com o Computador"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2016-01-05T00:00:00"}, "update_date": {"S": "2019-01-16T10:35:23"}} -{"id": {"S": "boGj6bgkBQCNvhe9dRvXM4"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "95"}, "user": {"M": {"id": {"S": "1e7e261b-d4fe-4d44-924f-06d4687b14e8"}, "name": {"S": "MARCO ANTONIO STERTZ"}, "email": {"S": "marco.stertz@gruppoab.com"}, "cpf": {"S": "73654337015"}}}, "course": {"M": {"id": {"S": "dc1a0428-47bf-4db1-a5da-24be49c9fda6"}, "name": {"S": "NR-11 \u2013 Transporte, movimenta\u00e7\u00e3o, armazenagem e manuseio de materiais"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2021-04-27T11:52:13"}, "update_date": {"S": "2021-06-20T22:44:13"}} -{"id": {"S": "3k2y89VxEzeJNbiAnCCJLk"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "81"}, "user": {"M": {"id": {"S": "XBoN-wCGqAv8IL6zPF9y"}, "name": {"S": "Vitor Jose do nascimento"}, "email": {"S": "vitinho211060@gmail.com"}, "cpf": {"S": "09735073650"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2020-10-02T15:40:54"}, "update_date": {"S": "2020-10-04T22:19:10"}} -{"id": {"S": "gBLSQgqSrD7iJVLhQmAcqU"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "19549"}, "name": {"S": "Edel\u00edcia Barros De Souza"}, "email": {"S": "jrobertosousa2000@yahoo.com.br"}, "cpf": {"S": "63587513872"}}}, "course": {"M": {"id": {"S": "59"}, "name": {"S": "Boas Pr\u00e1ticas em Manipula\u00e7\u00e3o de Alimentos"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2017-06-21T00:00:00"}, "update_date": {"S": "2019-01-16T11:02:41"}} -{"id": {"S": "L6CoK4Ez8WpueFCDDRvH3f"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "cMSlCbjw-5_gam2dEuLi"}, "name": {"S": "ROBERTO PEREIRA ALVES"}, "email": {"S": "roberto.alves@melitta.com.br"}, "cpf": {"S": "73698601087"}}}, "course": {"M": {"id": {"S": "94"}, "name": {"S": "Reciclagem em NR-11 - Operador de Empilhadeira"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2020-05-11T14:07:17"}, "update_date": {"S": "2020-05-11T14:15:31"}} -{"id": {"S": "4A7kXEBdx3gpvK4o9nJiWc"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "95"}, "user": {"M": {"id": {"S": "abe53008-930b-4eec-b47d-a8a621ad0beb"}, "name": {"S": "Gustavo Pinheiro Mantovani da Silva"}, "email": {"S": "gustavo.mantovani@bdo.com.br"}, "cpf": {"S": "50220809828"}}}, "course": {"M": {"id": {"S": "54"}, "name": {"S": "NR-33 Trabalhadores Autorizados e Vigias em Espa\u00e7o Confinado"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2022-08-23T08:39:53"}, "update_date": {"S": "2022-08-24T15:14:01"}} -{"id": {"S": "ZH8mFxRXLjoCP8tthk66UQ"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "92"}, "user": {"M": {"id": {"S": "FYh_7AfNJKnmWbYN-8pY"}, "name": {"S": "Edmilton Oliveira Mota"}, "email": {"S": "edmilton.oliveira@benvista.com.br"}, "cpf": {"S": "50543733572"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2019-12-12T16:21:57"}, "update_date": {"S": "2019-12-19T17:18:19"}} -{"id": {"S": "FBNgEiLmL93LoAfxqgDCfF"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "30813"}, "name": {"S": "Guilherme Lopes"}, "email": {"S": "guilhermelopes1623@gmail.com"}, "cpf": {"S": "48755066860"}}}, "course": {"M": {"id": {"S": "70"}, "name": {"S": "NR-20 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2018-10-31T00:00:00"}, "update_date": {"S": "2019-01-16T10:47:41"}} -{"id": {"S": "iBVdws8GbDSGgAvVhNVEup"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "24630"}, "name": {"S": "Ariolando Oliveira Quintino"}, "email": {"S": "ariolandoperfor@gmail.com"}, "cpf": {"S": "01611673143"}}}, "course": {"M": {"id": {"S": "62"}, "name": {"S": "NR-12 M\u00e1quinas e Equipamentos"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2018-03-12T00:00:00"}, "update_date": {"S": "2019-01-16T10:43:56"}} -{"id": {"S": "RsDhqQqqJHqkkuquWo7e8w"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "83"}, "user": {"M": {"id": {"S": "MnqbevRRa_-Ne8tRKTxE"}, "name": {"S": "JELISSON SILVA DOS SANTOS"}, "email": {"S": "jelissonsantos@kofre.net.br"}, "cpf": {"S": "86172498541"}}}, "course": {"M": {"id": {"S": "38"}, "name": {"S": "NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2019-12-11T11:30:04"}, "update_date": {"S": "2020-03-02T11:15:58"}} -{"id": {"S": "FqGA4Xj73PMWqmKHurCUE2"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "85"}, "user": {"M": {"id": {"S": "dbmUkgqhPLoCwzGqaZcK3D"}, "name": {"S": "REGINALDO BARBOSA FEITOSA"}, "email": {"S": "reginaldopalmeiras10barbosa@gmail.com"}, "cpf": {"S": "59377437253"}}}, "course": {"M": {"id": {"S": "70"}, "name": {"S": "NR-20 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2023-02-28T08:25:16"}, "update_date": {"S": "2025-02-19T16:13:35.588639-03:00"}} -{"id": {"S": "HQfUCg6rMQdBsbn9s7VLhh"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "92"}, "user": {"M": {"id": {"S": "31691"}, "name": {"S": "Alvaro Antonio Souza Gaspar"}, "email": {"S": "copapa100@hotmail.com"}, "cpf": {"S": "12329246790"}}}, "course": {"M": {"id": {"S": "54"}, "name": {"S": "NR-33 Trabalhadores Autorizados e Vigias em Espa\u00e7o Confinado"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2022-02-25T15:09:25"}, "update_date": {"S": "2022-03-29T00:43:13"}} -{"id": {"S": "9QnJZYWsYSbq5K79ZhZpvr"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "87"}, "user": {"M": {"id": {"S": "t_dgSn7ZNLyQ7l3yD8PK"}, "name": {"S": "Henrique In\u00e1cio Marrocos"}, "email": {"S": "henrique.marrocos@usjt.br"}, "cpf": {"S": "40714881821"}}}, "course": {"M": {"id": {"S": "55"}, "name": {"S": "NR-10 Complementar (SEP)"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2021-02-19T15:58:45"}, "update_date": {"S": "2021-02-23T05:56:56"}} -{"id": {"S": "frA8cr2BdG3tFWM2w4UuSt"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "95"}, "user": {"M": {"id": {"S": "04b807ac-272c-4580-a925-ff14202924e2"}, "name": {"S": "Glauber Rosemberg Borges Ferreira Lima"}, "email": {"S": "glauber.lima@unigel.com.br"}, "cpf": {"S": "00767241584"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2019-05-09T10:40:13"}, "update_date": {"S": "2019-05-18T17:27:29"}} -{"id": {"S": "3vxMUkB6e7JPwR8bFQ4cpc"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "8453"}, "name": {"S": "Samyris Nascimento"}, "email": {"S": "samyris.nascimento@hotmail.com"}, "cpf": {"S": "01720518190"}}}, "course": {"M": {"id": {"S": "31"}, "name": {"S": "No\u00e7\u00f5es em Inform\u00e1tica: Pr\u00e1ticas com o Computador"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2015-11-03T00:00:00"}, "update_date": {"S": "2019-01-16T10:34:44"}} -{"id": {"S": "7bARdNE6M7k6UGWDH2S3g7"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "11067"}, "name": {"S": "Fernanda Fernandes"}, "email": {"S": "fsfernandes@timbrasil.com.br"}, "cpf": {"S": "43704168505"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2016-03-17T00:00:00"}, "update_date": {"S": "2019-01-16T10:36:16"}} -{"id": {"S": "M8Xj9F6inMg2KaTpFwXgju"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "90"}, "user": {"M": {"id": {"S": "MqblkE9EF2DHg4McX2J1"}, "name": {"S": "MURILO DUARTE DE MELO"}, "email": {"S": "murilo.melo@pli-petronas.com"}, "cpf": {"S": "31567241816"}}}, "course": {"M": {"id": {"S": "50"}, "name": {"S": "Dire\u00e7\u00e3o Defensiva"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2019-06-25T15:33:50"}, "update_date": {"S": "2019-06-26T10:17:37"}} -{"id": {"S": "HXKaop3z35ojT2hbj9T4tE"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "87"}, "user": {"M": {"id": {"S": "BFRSJGFBF2TDtk4mV5YiH3"}, "name": {"S": "RODRIGO MENDES"}, "email": {"S": "rodrigo.mendes@manserv.com.br"}, "cpf": {"S": "08773922692"}}}, "course": {"M": {"id": {"S": "7ac2e34e-232a-427c-a3fc-32198e3a51c6"}, "name": {"S": "Dire\u00e7\u00e3o Defensiva - 08h"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2023-05-04T14:51:01"}, "update_date": {"S": "2024-05-06T14:15:50.404165-03:00"}} -{"id": {"S": "3VM2AStsWokYtJjjuMHdth"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "4916"}, "name": {"S": "Sandra Campos Da Cruz Santos"}, "email": {"S": "etig@uol.com.br"}, "cpf": {"S": "16629826825"}}}, "course": {"M": {"id": {"S": "57"}, "name": {"S": "NR-33 Supervisor em Espa\u00e7o Confinado"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2015-02-19T00:00:00"}, "update_date": {"S": "2019-01-16T10:33:04"}} -{"id": {"S": "fcs6anxafVuD56VRxpANcQ"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "bed1053e-43c2-4990-9ae8-5f4c1d3bd746"}, "name": {"S": "Paulo Augusto Barbosa"}, "email": {"S": "pauloaugusto2688@gmail.com"}, "cpf": {"S": "07176390967"}}}, "course": {"M": {"id": {"S": "70"}, "name": {"S": "NR-20 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2019-04-25T09:11:46"}, "update_date": {"S": "2020-03-20T19:49:44"}} -{"id": {"S": "gAe26BLnHV32cLSZMLorf2"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "83"}, "user": {"M": {"id": {"S": "a41814a8-6205-4e30-99ef-7c5eccf2e056"}, "name": {"S": "Felipe Gibelli"}, "email": {"S": "felipegibelli@cetrel.com.br"}, "cpf": {"S": "28009985805"}}}, "course": {"M": {"id": {"S": "92"}, "name": {"S": "Reciclagem em NR-20 - Intermedi\u00e1rio"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2020-06-04T13:33:36"}, "update_date": {"S": "2020-06-17T13:26:07"}} -{"id": {"S": "LXHXrTfWerqarfGgSY9Df9"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "98"}, "user": {"M": {"id": {"S": "82755558504"}, "name": {"S": "PEDRO ANTONIO DOS S FILHO"}, "email": {"S": "82755558504@users.noreply.betaeducacao.com.br"}, "cpf": {"S": "82755558504"}}}, "course": {"M": {"id": {"S": "dc1a0428-47bf-4db1-a5da-24be49c9fda6"}, "name": {"S": "NR-11 \u2013 Transporte, movimenta\u00e7\u00e3o, armazenagem e manuseio de materiais"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2022-09-26T11:09:50"}, "update_date": {"S": "2023-11-14T19:02:56.175140-03:00"}} -{"id": {"S": "SE4FS2S3r5kF6D33km5vwr"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "20483"}, "name": {"S": "Emerson Oliva"}, "email": {"S": "emerson.oliva@deca.com.br"}, "cpf": {"S": "10731721802"}}}, "course": {"M": {"id": {"S": "56"}, "name": {"S": "Reciclagem em NR-10 Complementar (SEP)"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2023-02-20T08:34:45"}, "update_date": {"S": "2025-02-17T23:32:39.152242-03:00"}} -{"id": {"S": "MmA7KrvYJDAYrtbKcoRWu2"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "24795"}, "name": {"S": "Paulo Ricardo Severo Lerina"}, "email": {"S": "p.lerina@terra.com.br"}, "cpf": {"S": "42061245072"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2018-03-19T00:00:00"}, "update_date": {"S": "2019-01-16T10:44:01"}} -{"id": {"S": "awd7HzWMSdTYodtrAqLfwB"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "25239"}, "name": {"S": "Reginaldo Lino Borges"}, "email": {"S": "reginaldolinoborges@hotmail.com"}, "cpf": {"S": "02243941260"}}}, "course": {"M": {"id": {"S": "70"}, "name": {"S": "NR-20 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2018-04-10T00:00:00"}, "update_date": {"S": "2019-01-16T10:44:14"}} -{"id": {"S": "fb4q9wroyRB2UjrZoZfhqd"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "6235"}, "name": {"S": "Venkata Ramana Gollavilli"}, "email": {"S": "venkata.ramana@br.heinenhopman.com"}, "cpf": {"S": "06325946758"}}}, "course": {"M": {"id": {"S": "40"}, "name": {"S": "Reciclagem em NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2015-05-19T00:00:00"}, "update_date": {"S": "2019-01-16T10:33:35"}} -{"id": {"S": "ByKFt7FAhqXN2y5Pbt7kPA"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "97"}, "user": {"M": {"id": {"S": "v0Q_qaB_LIvBxpoK3y-v"}, "name": {"S": "GUILHERME MARTINS HENRIQUE FERREIRA"}, "email": {"S": "guilherme.mhf@hotmail.com"}, "cpf": {"S": "06922380509"}}}, "course": {"M": {"id": {"S": "54"}, "name": {"S": "NR-33 Trabalhadores Autorizados e Vigias em Espa\u00e7o Confinado"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2020-07-27T13:36:13"}, "update_date": {"S": "2020-07-28T21:08:15"}} -{"id": {"S": "RiodsomeqcLB5hE8dN9fW6"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "27338"}, "name": {"S": "Cristian Ianc"}, "email": {"S": "cristian.ianc@hexagonagriculture.com"}, "cpf": {"S": "01319953913"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2018-06-25T00:00:00"}, "update_date": {"S": "2019-01-16T10:45:40"}} -{"id": {"S": "PkTg6SqNuZoxUyxU7Evqcv"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "18002"}, "name": {"S": "Jeferson Vieira De Lima"}, "email": {"S": "jeferson.vieira@zumpnet.com.br"}, "cpf": {"S": "00929227085"}}}, "course": {"M": {"id": {"S": "38"}, "name": {"S": "NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2017-04-04T00:00:00"}, "update_date": {"S": "2019-01-16T10:40:17"}} -{"id": {"S": "JKbCztrJfZPqScwwFQp4EV"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "8211"}, "name": {"S": "Sergio Rosa De Lima"}, "email": {"S": "sergiorl@weg.net"}, "cpf": {"S": "02004815922"}}}, "course": {"M": {"id": {"S": "40"}, "name": {"S": "Reciclagem em NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2015-10-22T00:00:00"}, "update_date": {"S": "2019-01-16T10:34:27"}} -{"id": {"S": "TtEDsn7yP9wNTZvzA6TC3Q"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "89"}, "user": {"M": {"id": {"S": "24142"}, "name": {"S": "Andr\u00e9 Luiz De Almeida"}, "email": {"S": "andre.almeida@padtec.com.br"}, "cpf": {"S": "03316776109"}}}, "course": {"M": {"id": {"S": "40"}, "name": {"S": "Reciclagem em NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2019-04-22T09:49:48"}, "update_date": {"S": "2019-04-28T20:36:20"}} -{"id": {"S": "48vSHY9PjgJT3mS4A2tVVc"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "10406"}, "name": {"S": "Marcio Stein Pires"}, "email": {"S": "m.stein.pires@bol.com.br"}, "cpf": {"S": "01435162994"}}}, "course": {"M": {"id": {"S": "38"}, "name": {"S": "NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2016-02-25T00:00:00"}, "update_date": {"S": "2019-01-16T10:35:59"}} -{"id": {"S": "DnJPAxj7NQBPawpBaqxRhh"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "28116"}, "name": {"S": "Jaime Ventura Da Silva"}, "email": {"S": "jaime.gugu2016@gmail.com"}, "cpf": {"S": "00903687623"}}}, "course": {"M": {"id": {"S": "62"}, "name": {"S": "NR-12 M\u00e1quinas e Equipamentos"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2018-07-19T00:00:00"}, "update_date": {"S": "2019-01-16T10:46:12"}} -{"id": {"S": "VKj3XANhEjQMG72bXb4m9V"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "28805"}, "name": {"S": "Alexandre Baptista Da Silveira"}, "email": {"S": "cidiomar@bins.com.br"}, "cpf": {"S": "49919601004"}}}, "course": {"M": {"id": {"S": "40"}, "name": {"S": "Reciclagem em NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2018-08-28T00:00:00"}, "update_date": {"S": "2019-01-16T10:46:44"}} -{"id": {"S": "PtGqnWgsFyYD8yjHcECVhU"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "90"}, "user": {"M": {"id": {"S": "wHiuWLYzZ4S4OSpZO2kN"}, "name": {"S": "Leandro Viana Brambilha"}, "email": {"S": "leandro.brambilha@padtec.com.br"}, "cpf": {"S": "35992645896"}}}, "course": {"M": {"id": {"S": "52"}, "name": {"S": "NR-18 - Constru\u00e7\u00e3o Civil"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2021-07-05T08:19:45"}, "update_date": {"S": "2021-07-09T10:43:24"}} -{"id": {"S": "HxJmLfqU4i4dQhy7FsSbMd"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "96"}, "user": {"M": {"id": {"S": "uyUOx3pp_DT5hv29gYRa"}, "name": {"S": "Bruno Cesar Thomes"}, "email": {"S": "bruno.thomes@ponsse.com"}, "cpf": {"S": "01883920507"}}}, "course": {"M": {"id": {"S": "50"}, "name": {"S": "Dire\u00e7\u00e3o Defensiva"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2020-05-13T13:59:28"}, "update_date": {"S": "2020-05-25T16:41:47"}} -{"id": {"S": "ANEzzLrQvHXcE8DBvEcjcN"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "85"}, "user": {"M": {"id": {"S": "Ub6Q7pgG6tTzMCAG4Boiaa"}, "name": {"S": "JOSE RAUL MACHADO JUNIOR"}, "email": {"S": "jose.machado@semeq.com"}, "cpf": {"S": "38030091893"}}}, "course": {"M": {"id": {"S": "38"}, "name": {"S": "NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2023-02-23T08:49:18"}, "update_date": {"S": "2025-02-16T09:30:31.910495-03:00"}} -{"id": {"S": "hJ7X4nDwY5GRVe94szEU73"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "7512"}, "name": {"S": "Eder Cavalcanti Guilherme"}, "email": {"S": "edercalv@hotmail.com"}, "cpf": {"S": "22389063802"}}}, "course": {"M": {"id": {"S": "38"}, "name": {"S": "NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2015-07-28T00:00:00"}, "update_date": {"S": "2019-01-16T10:34:10"}} -{"id": {"S": "E74mhXWkbt8vCr2XxAj9Ak"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "21582"}, "name": {"S": "Emerson Francisco Arcos"}, "email": {"S": "emerson.arcos@deca.com.br"}, "cpf": {"S": "07596148816"}}}, "course": {"M": {"id": {"S": "40"}, "name": {"S": "Reciclagem em NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2017-09-29T00:00:00"}, "update_date": {"S": "2019-01-16T10:42:08"}} -{"id": {"S": "XJKTcxJVj52zdkWApE9eBF"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "4438"}, "name": {"S": "Samuel Xavier De Campos"}, "email": {"S": "samuel.campos@mrgnet.ind.br"}, "cpf": {"S": "35776288800"}}}, "course": {"M": {"id": {"S": "31"}, "name": {"S": "No\u00e7\u00f5es em Inform\u00e1tica: Pr\u00e1ticas com o Computador"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2014-12-20T00:00:00"}, "update_date": {"S": "2019-01-16T10:32:51"}} -{"id": {"S": "KzuHrNJkSDeP2QuV9MbgTY"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "91"}, "user": {"M": {"id": {"S": "15171"}, "name": {"S": "Fabio Akira Haraguchi"}, "email": {"S": "fabio.haraguchi@fanucamerica.com"}, "cpf": {"S": "28701842803"}}}, "course": {"M": {"id": {"S": "62"}, "name": {"S": "NR-12 M\u00e1quinas e Equipamentos"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2023-06-02T09:06:21"}, "update_date": {"S": "2024-06-11T21:04:14.709415-03:00"}} -{"id": {"S": "W3otxdCMcmVKTdaEYUVX9s"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "a079aa67-d4ba-42e2-8117-21fd26b462bd"}, "name": {"S": "Weverton Eduardo Wiezel"}, "email": {"S": "weverton.wiezel2@primient.com"}, "cpf": {"S": "39663983892"}}}, "course": {"M": {"id": {"S": "723534ae-36ae-4253-bb73-966c8268779d"}, "name": {"S": "NR-17 Ergonomia"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2021-08-18T08:12:24"}, "update_date": {"S": "2021-10-28T17:15:08"}} -{"id": {"S": "QqkE4ZhQ5o5B573oqXRag7"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "30896"}, "name": {"S": "Elias Gois"}, "email": {"S": "eliasgois1@gmail.com"}, "cpf": {"S": "06028047520"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2018-11-06T00:00:00"}, "update_date": {"S": "2019-01-16T10:47:42"}} -{"id": {"S": "RhNokgWvMQEHFnngZdCsVs"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "23182"}, "name": {"S": "Eduardo Steffens"}, "email": {"S": "eduardosteffens@outlook.com.br"}, "cpf": {"S": "08779319920"}}}, "course": {"M": {"id": {"S": "42"}, "name": {"S": "NR-35 Seguran\u00e7a nos Trabalhos em Altura (Te\u00f3rico)"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2017-12-29T00:00:00"}, "update_date": {"S": "2019-01-16T10:43:14"}} -{"id": {"S": "XcbEm5hB5LvsV7JKSY6aU4"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "87"}, "user": {"M": {"id": {"S": "7ClATyObN7z2Axzjm4pF"}, "name": {"S": "Andressa Fernanda Moraes"}, "email": {"S": "andressa.moraes@unisociesc.com.br"}, "cpf": {"S": "04803999996"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2021-07-07T15:40:14"}, "update_date": {"S": "2021-07-21T21:20:27"}} -{"id": {"S": "NT26hzBoPMAoZ6WbfTtSFG"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "90"}, "user": {"M": {"id": {"S": "8PPtvmJdUf9oSuIWyLc6"}, "name": {"S": "Wagner Donizetti Venancio"}, "email": {"S": "wagner.venancio@primient.com"}, "cpf": {"S": "31528337840"}}}, "course": {"M": {"id": {"S": "723534ae-36ae-4253-bb73-966c8268779d"}, "name": {"S": "NR-17 Ergonomia"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2021-01-05T08:40:28"}, "update_date": {"S": "2021-06-22T11:20:33"}} -{"id": {"S": "e3gWWxcoSFH2VA6TYFHXgC"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "7449"}, "name": {"S": "Eduardo Netto De Maia Bentes"}, "email": {"S": "eduardo.bentes@serpro.gov.br"}, "cpf": {"S": "83594469115"}}}, "course": {"M": {"id": {"S": "38"}, "name": {"S": "NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2015-07-30T00:00:00"}, "update_date": {"S": "2019-01-16T10:34:11"}} -{"id": {"S": "bmEpXP4wLtLiJvZjptm6ac"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "91"}, "user": {"M": {"id": {"S": "3MbYYVBH7yW3qCP2zsTgkM"}, "name": {"S": "CALEBE ALVES DOS SANTOS"}, "email": {"S": "calebealvesdossantos@gmail.com"}, "cpf": {"S": "08948473921"}}}, "course": {"M": {"id": {"S": "38"}, "name": {"S": "NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2022-10-13T08:20:32"}, "update_date": {"S": "2024-10-06T09:06:17.043613-03:00"}} -{"id": {"S": "KL3b9gB5smYm9Hw5mYPogz"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "96"}, "user": {"M": {"id": {"S": "uNSzcXMHHm5t3FS2Cq-r"}, "name": {"S": "Rafael Oliveira de Moraes"}, "email": {"S": "rafael88kv@hotmail.com"}, "cpf": {"S": "22823764801"}}}, "course": {"M": {"id": {"S": "56"}, "name": {"S": "Reciclagem em NR-10 Complementar (SEP)"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2019-03-25T10:25:32"}, "update_date": {"S": "2019-10-29T07:33:33"}} -{"id": {"S": "7x6DDicpSuxGU6Pw6UEbLN"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "71"}, "user": {"M": {"id": {"S": "WMdPRKfV6vQ7GZ6e7CSSqp"}, "name": {"S": "Iranildo da Costa Sousa"}, "email": {"S": "iranildo.sousa@unigel.com.br"}, "cpf": {"S": "72294620534"}}}, "course": {"M": {"id": {"S": "83"}, "name": {"S": "NR-20 Inicia\u00e7\u00e3o"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2022-08-08T13:08:48"}, "update_date": {"S": "2022-08-12T09:39:00"}} -{"id": {"S": "65UpJUxmc6Zi45QuLamMcf"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "9863235c-6546-4a49-984b-90b1a73d9420"}, "name": {"S": "Marcos Aur\u00e9lio Azevedo"}, "email": {"S": "marcos.azevedo@padtec.com.br"}, "cpf": {"S": "00442643993"}}}, "course": {"M": {"id": {"S": "38"}, "name": {"S": "NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2017-09-11T00:00:00"}, "update_date": {"S": "2019-01-16T10:41:59"}} -{"id": {"S": "cnYYiHtQcbnNiJtSzDdbr9"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "17823"}, "name": {"S": "Leandro Piecha Contreira"}, "email": {"S": "leandro@avato.com.br"}, "cpf": {"S": "02222513014"}}}, "course": {"M": {"id": {"S": "38"}, "name": {"S": "NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2017-03-31T00:00:00"}, "update_date": {"S": "2019-01-16T10:40:13"}} -{"id": {"S": "RqaX2J8jKKwb4Cw5zmtYxD"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "81"}, "user": {"M": {"id": {"S": "30279b05-f3d5-460a-af1e-8f9ab937032a"}, "name": {"S": "Carlos Eduardo Moretto"}, "email": {"S": "carlos.moretto@primient.com"}, "cpf": {"S": "28827990801"}}}, "course": {"M": {"id": {"S": "90"}, "name": {"S": "Reciclagem em NR-33 Trabalhadores Autorizados"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2023-05-03T14:18:19"}, "update_date": {"S": "2024-05-02T07:48:38.301431-03:00"}} -{"id": {"S": "J2xgiwj5qpPrKfYycEYuPw"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "4997"}, "name": {"S": "Laerte Leit\u00e3o Gomes"}, "email": {"S": "lgomes@qgog.com.br"}, "cpf": {"S": "21208905368"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2015-02-27T00:00:00"}, "update_date": {"S": "2019-01-16T10:33:06"}} -{"id": {"S": "MCwpAuprZVpfHG7wxWBHVv"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "93"}, "user": {"M": {"id": {"S": "21804"}, "name": {"S": "Liliane Costa Firmiano Ferrari"}, "email": {"S": "liliane.ferrari@ecosul.com.br"}, "cpf": {"S": "19265748850"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2020-09-10T10:06:05"}, "update_date": {"S": "2020-10-09T15:43:58"}} -{"id": {"S": "fKhBhVAvGAecjNxFyNn9N7"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "94"}, "user": {"M": {"id": {"S": "gmXxwsCIoU_6MSO9xJKj"}, "name": {"S": "Jandir Ademar Schmidt"}, "email": {"S": "jandir@unc.br"}, "cpf": {"S": "40959082034"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2021-04-14T15:03:43"}, "update_date": {"S": "2021-04-16T21:19:24"}} -{"id": {"S": "a3NXfaJ2yVji6PbsxaNJRL"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "98"}, "user": {"M": {"id": {"S": "d7e4db48-6297-44e7-a75e-72340b928c49"}, "name": {"S": "Rosivam Pereira Diniz"}, "email": {"S": "rosivam@chronusauditores.com"}, "cpf": {"S": "68839430482"}}}, "course": {"M": {"id": {"S": "38"}, "name": {"S": "NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2019-06-03T08:10:52"}, "update_date": {"S": "2019-06-07T09:40:19"}} -{"id": {"S": "mPhBY7HSrmftNiPucQRYoQ"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "82"}, "user": {"M": {"id": {"S": "2a911416-e83d-4f91-b03e-ab60d4895704"}, "name": {"S": "Lucival Souza Barreto"}, "email": {"S": "renata@inovvar.net.br"}, "cpf": {"S": "77711564520"}}}, "course": {"M": {"id": {"S": "42"}, "name": {"S": "NR-35 Seguran\u00e7a nos Trabalhos em Altura (Te\u00f3rico)"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2019-04-24T10:01:31"}, "update_date": {"S": "2019-04-29T21:21:01"}} -{"id": {"S": "NGo3VurF3iReLJtV7NGaYM"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "1356"}, "name": {"S": "Edson Firmino Leal"}, "email": {"S": "edsonfleal@yahoo.com.br"}, "cpf": {"S": "01954277938"}}}, "course": {"M": {"id": {"S": "38"}, "name": {"S": "NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2013-04-30T00:00:00"}, "update_date": {"S": "2019-01-16T10:31:22"}} -{"id": {"S": "fnFj3Mex3r5cFU4bt2xR93"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "18006"}, "name": {"S": "Weslley Bueno Goiembiesqui"}, "email": {"S": "weslley.goiembiesqui@solarisbrasil.com.br"}, "cpf": {"S": "37835574888"}}}, "course": {"M": {"id": {"S": "40"}, "name": {"S": "Reciclagem em NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2017-04-06T00:00:00"}, "update_date": {"S": "2019-01-16T10:40:18"}} -{"id": {"S": "8yzKp9TKtus9fyWRgnvNCV"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "19613"}, "name": {"S": "Cassiano Antonio Pereira"}, "email": {"S": "cassianopa@hotmail.com"}, "cpf": {"S": "12933714671"}}}, "course": {"M": {"id": {"S": "52"}, "name": {"S": "NR-18 - Constru\u00e7\u00e3o Civil"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2017-07-04T00:00:00"}, "update_date": {"S": "2019-01-16T10:41:12"}} -{"id": {"S": "Qqr42XiDRFsGFahF5hdMGB"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "5f00cdef-6775-4a5b-90f8-ccc607c7f855"}, "name": {"S": "GILENO XAVIER DOS SANTOS"}, "email": {"S": "gileno.santos@kordsa.com"}, "cpf": {"S": "02174837552"}}}, "course": {"M": {"id": {"S": "dc1a0428-47bf-4db1-a5da-24be49c9fda6"}, "name": {"S": "NR-11 \u2013 Transporte, movimenta\u00e7\u00e3o, armazenagem e manuseio de materiais"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2022-09-26T11:05:39"}, "update_date": {"S": "2023-10-11T01:27:42.244872-03:00"}} -{"id": {"S": "34MjPRVS3pjFqkdMGQz2AG"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "3385"}, "name": {"S": "Marcelo Eduardo Matzenbacher"}, "email": {"S": "marceloeduardonr10@hotmail.com"}, "cpf": {"S": "08110782990"}}}, "course": {"M": {"id": {"S": "38"}, "name": {"S": "NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2014-08-18T00:00:00"}, "update_date": {"S": "2019-01-16T10:32:19"}} -{"id": {"S": "A7eVTW7zE2hu4p49yYaG5j"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "93"}, "user": {"M": {"id": {"S": "CM3rntBpZYd-HlTZkJyh"}, "name": {"S": "Franciele Huzioka"}, "email": {"S": "franciele.secretaria@unc.br"}, "cpf": {"S": "05153526917"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2020-03-02T15:28:28"}, "update_date": {"S": "2020-05-29T19:00:14"}} -{"id": {"S": "DB7NH9ddpnihQ48gL8wE72"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "frlCl629Wi-vgygmeYg9"}, "name": {"S": "Jos\u00e9 Carlos da Silveira"}, "email": {"S": "jose.silveira@ponsse.com"}, "cpf": {"S": "04037747642"}}}, "course": {"M": {"id": {"S": "723534ae-36ae-4253-bb73-966c8268779d"}, "name": {"S": "NR-17 Ergonomia"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2022-09-08T09:53:26"}, "update_date": {"S": "2023-09-24T14:17:08.875174-03:00"}} -{"id": {"S": "LGPRffR57u9p3doKBeMmjX"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "346628ce-a6c8-4fff-a6ee-5378675e220a"}, "name": {"S": "Leandro Barbosa Dorea"}, "email": {"S": "leandrodorea@kofre.com.br"}, "cpf": {"S": "03004706571"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2019-08-16T14:41:11"}, "update_date": {"S": "2019-08-20T15:16:31"}} -{"id": {"S": "6uT9NjEzhpgmRmdqY8VNWS"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "db3bef3c-7851-4a5f-b444-44ea5d0b4f74"}, "name": {"S": "Jos\u00e9 Ricardo Messias Ara\u00fajo"}, "email": {"S": "josericardo.messias@primient.com"}, "cpf": {"S": "34973080802"}}}, "course": {"M": {"id": {"S": "83"}, "name": {"S": "NR-20 Inicia\u00e7\u00e3o"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2023-10-04T16:28:08.374304-03:00"}, "update_date": {"S": "2024-09-28T17:18:25.681373-03:00"}} -{"id": {"S": "Pyi5e3tfFtURcWx7ERL969"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "82"}, "user": {"M": {"id": {"S": "zukr4eXgJfjHpfZACCmr"}, "name": {"S": "Lu\u00eds Alberto Rosa Junior"}, "email": {"S": "vendasluis1@hotmail.com"}, "cpf": {"S": "06169257946"}}}, "course": {"M": {"id": {"S": "54"}, "name": {"S": "NR-33 Trabalhadores Autorizados e Vigias em Espa\u00e7o Confinado"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2019-06-14T08:17:21"}, "update_date": {"S": "2019-06-16T18:33:09"}} -{"id": {"S": "QLxRSLgb43zDzbARNiALGr"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "2d5f4cd0-7cee-418a-b93c-0cf64296c62c"}, "name": {"S": "Lucas Caldas de Oliveira"}, "email": {"S": "lca@flodim.com.br"}, "cpf": {"S": "05886606556"}}}, "course": {"M": {"id": {"S": "2c1e724a-58c6-4c20-90df-18b5660d6304"}, "name": {"S": "No\u00e7\u00f5es em Primeiros Socorros"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2023-05-15T09:54:52"}, "update_date": {"S": "2024-05-30T12:59:46.540817-03:00"}} -{"id": {"S": "3Vt6dKtWUE56CmW5kM2Zqy"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "81"}, "user": {"M": {"id": {"S": "vpwSSmSTvFZGlhWG8fHx"}, "name": {"S": "On\u00e9sio Alves Ferreira"}, "email": {"S": "onesio.ferreira@primient.com"}, "cpf": {"S": "16404716852"}}}, "course": {"M": {"id": {"S": "42"}, "name": {"S": "NR-35 Seguran\u00e7a nos Trabalhos em Altura (Te\u00f3rico)"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2021-03-02T10:31:16"}, "update_date": {"S": "2021-03-07T16:54:22"}} -{"id": {"S": "Wqr2VjM842DknTvT5meo2o"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "32268"}, "name": {"S": "Janssen Daris"}, "email": {"S": "janssen.daris@gmail.com"}, "cpf": {"S": "11285720792"}}}, "course": {"M": {"id": {"S": "63"}, "name": {"S": "NR-13 Operador de Caldeiras"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2019-01-11T00:00:00"}, "update_date": {"S": "2019-01-16T10:48:21"}} -{"id": {"S": "SiLB4g9hxQMZS3feNs3fku"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "8103"}, "name": {"S": "Ailton Santa F\u00e9"}, "email": {"S": "ailton_junior@infraero.gov.br"}, "cpf": {"S": "60190140291"}}}, "course": {"M": {"id": {"S": "40"}, "name": {"S": "Reciclagem em NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2015-10-22T00:00:00"}, "update_date": {"S": "2019-01-16T10:34:29"}} -{"id": {"S": "CbV6sdwenufkDeWLpHjaro"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "6227"}, "name": {"S": "Let\u00edcia Rieg"}, "email": {"S": "financeiro2@perfor.com.br"}, "cpf": {"S": "06699098900"}}}, "course": {"M": {"id": {"S": "41"}, "name": {"S": "CIPA"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2018-04-23T00:00:00"}, "update_date": {"S": "2019-01-16T10:44:36"}} -{"id": {"S": "LfcHK4vdC26mL97sdYHqzC"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "75"}, "user": {"M": {"id": {"S": "R2sF6F4EOdup-PLLlpkd"}, "name": {"S": "Claudinei Tadeu da Silva"}, "email": {"S": "vagasabertas@outlook.com"}, "cpf": {"S": "13976029882"}}}, "course": {"M": {"id": {"S": "62"}, "name": {"S": "NR-12 M\u00e1quinas e Equipamentos"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2020-11-06T16:06:25"}, "update_date": {"S": "2020-11-06T18:56:43"}} -{"id": {"S": "N9VpcNSKGaXx3aGeGihqeE"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "87"}, "user": {"M": {"id": {"S": "af200eb9-8084-4275-a0c2-749f4d1d023f"}, "name": {"S": "Jonas Cabral"}, "email": {"S": "jonas.cabral@unigel.com.br"}, "cpf": {"S": "29181018851"}}}, "course": {"M": {"id": {"S": "83"}, "name": {"S": "NR-20 Inicia\u00e7\u00e3o"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2022-07-22T14:14:41"}, "update_date": {"S": "2024-03-31T21:02:50.678858-03:00"}} -{"id": {"S": "YREgchZHhYLiYaSKBtT9Fm"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "87"}, "user": {"M": {"id": {"S": "ff19941a-9471-48de-8fe7-6858e9ce4549"}, "name": {"S": "Jose Alessandro De Souza"}, "email": {"S": "jose.souza@semeq.com"}, "cpf": {"S": "00878884165"}}}, "course": {"M": {"id": {"S": "54"}, "name": {"S": "NR-33 Trabalhadores Autorizados e Vigias em Espa\u00e7o Confinado"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2019-05-23T10:32:46"}, "update_date": {"S": "2021-05-27T10:09:06"}} -{"id": {"S": "kMKA4jzGnT6GwwXfvqWxW9"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "88"}, "user": {"M": {"id": {"S": "68278489572"}, "name": {"S": "ALEXSANDRO SANTOS DE OLIVEIRA"}, "email": {"S": "68278489572@users.noreply.betaeducacao.com.br"}, "cpf": {"S": "68278489572"}}}, "course": {"M": {"id": {"S": "40"}, "name": {"S": "Reciclagem em NR-10 B\u00e1sico"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2022-05-19T08:37:15"}, "update_date": {"S": "2024-05-16T19:19:29.284660-03:00"}} -{"id": {"S": "c6AmTVrLo2fACM93MG866m"}, "sk": {"S": "0"}, "status": {"S": "ARCHIVED"}, "progress": {"S": "100"}, "score": {"S": "100"}, "user": {"M": {"id": {"S": "6093"}, "name": {"S": "Sergio Weinfuter"}, "email": {"S": "sweinfuter@hotmail.com"}, "cpf": {"S": "75326256991"}}}, "course": {"M": {"id": {"S": "62"}, "name": {"S": "NR-12 M\u00e1quinas e Equipamentos"}, "cert": {"NULL": true}, "access_period": {"N": "360"}}}, "created_at": {"S": "2015-05-11T00:00:00"}, "update_date": {"S": "2019-01-16T10:33:32"}} -{"id": {"S": "vacancies#cJtK9SsnJhKPyxESe7g3DG"},"sk": {"S": "QV4sXY3DvSTUMGJ4QqsrwJ#280cdb77-f6b6-4bd3-bbbf-f770de69389c"},"course": {"M": {"id": {"S": "a6775b71-d68a-4263-8ab4-acb3a4f8a8b9"},"name": {"S": "NR-18 PEMT PTA"},"time_in_days": {"N": "365"}}},"created_at": {"S": "2025-04-28T12:04:09.389782-03:00"}} \ No newline at end of file +{"id": "f58c8fa1-d14c-4c17-955b-b47b82963f40", "sk": "0", "issued_cert": { "s3_uri": "s3://saladeaula.digital/issuedcerts/f58c8fa1-d14c-4c17-955b-b47b82963f40.pdf", "issued_at": "2025-09-02T12:57:33.066023-03:00"}, "updated_at": "2025-09-01T14:59:07.999536-03:00", "subscription_covered": true, "created_at": "2025-09-01T14:59:04.758540-03:00", "course": { "name": "CIPA Grau de Risco 1", "time_in_days": 360, "id": "3c27ea9c-9464-46a1-9717-8c1441793186" }, "tenant_id": "cJtK9SsnJhKPyxESe7g3DG", "status": "COMPLETED", "progress": 100, "score": 79, "user": {"name": "Sérgio Rafael de Siqueira", "cpf": "07879819908", "id": "5OxmMjL-ujoR5IMGegQz", "email": "sergio@somosbeta.com.br"}} +{"id": "f58c8fa1-d14c-4c17-955b-b47b82963f40", "sk": "COMPLETED", "completed_at": "2025-08-31T21:59:10.842467-03:00"} +{"id": "f58c8fa1-d14c-4c17-955b-b47b82963f40", "sk": "SCHEDULE#REMINDER_ACCESS_PERIOD_BEFORE_30_DAYS", "created_at": "2025-09-01T15:00:09.589766-03:00", "course": "CIPA Grau de Risco 1", "ttl": 1785261609, "email": "sergio@somosbeta.com.br", "name": "Sérgio Rafael de Siqueira"} +{"id": "f58c8fa1-d14c-4c17-955b-b47b82963f40", "sk": "SCHEDULE#REMINDER_NO_ACCESS_AFTER_3_DAYS", "created_at": "2025-09-01T15:00:09.589766-03:00", "course": "CIPA Grau de Risco 1", "ttl": 1757008809, "email": "sergio@somosbeta.com.br", "name": "Sérgio Rafael de Siqueira"} \ No newline at end of file diff --git a/http-api/template.yaml b/http-api/template.yaml index 8ee9286..5d3f9dd 100644 --- a/http-api/template.yaml +++ b/http-api/template.yaml @@ -2,6 +2,9 @@ AWSTemplateFormatVersion: 2010-09-09 Transform: AWS::Serverless-2016-10-31 Parameters: + BucketName: + Type: String + Default: saladeaula.digital UserTable: Type: String Default: betaeducacao-prod-users_d2o3r5gmm4it7j @@ -11,9 +14,6 @@ Parameters: EnrollmentTable: Type: String Default: betaeducacao-prod-enrollments - NewEnrollmentTable: - Type: String - Default: saladeaula_enrollments CourseTable: Type: String Default: saladeaula_courses @@ -38,6 +38,7 @@ Globals: ORDER_TABLE: !Ref OrderTable ENROLLMENT_TABLE: !Ref EnrollmentTable COURSE_TABLE: !Ref CourseTable + BUCKET_NAME: !Ref BucketName KONVIVA_API_URL: https://lms.saladeaula.digital KONVIVA_SECRET_KEY: "{{resolve:ssm:/betaeducacao/konviva/secret_key/str}}" MEILISEARCH_HOST: https://meili.saladeaula.digital @@ -85,6 +86,8 @@ Resources: TableName: !Ref OrderTable - DynamoDBCrudPolicy: TableName: !Ref EnrollmentTable + - S3ReadPolicy: + BucketName: !Ref BucketName - Version: 2012-10-17 Statement: - Effect: Allow diff --git a/http-api/tests/conftest.py b/http-api/tests/conftest.py index dc875ec..7c9b6a2 100644 --- a/http-api/tests/conftest.py +++ b/http-api/tests/conftest.py @@ -17,6 +17,7 @@ SK = 'sk' def pytest_configure(): os.environ['TZ'] = 'America/Sao_Paulo' os.environ['KONVIVA_API_URL'] = 'https://saladeaula.digital' + os.environ['BUCKET_NAME'] = 'saladeaula.digital' os.environ['DYNAMODB_PARTITION_KEY'] = PK os.environ['DYNAMODB_SORT_KEY'] = SK os.environ['USER_TABLE'] = PYTEST_TABLE_NAME diff --git a/http-api/tests/routes/test_enrollments.py b/http-api/tests/routes/test_enrollments.py index a85dc91..863269a 100644 --- a/http-api/tests/routes/test_enrollments.py +++ b/http-api/tests/routes/test_enrollments.py @@ -210,3 +210,22 @@ def test_cancel_enrollment( PartitionKey(ComposeKey('cJtK9SsnJhKPyxESe7g3DG', 'vacancies')) ) assert len(vacancies['items']) == 2 + + +def test_download( + mock_app, + http_api_proxy: HttpApiProxy, + lambda_context: LambdaContext, +): + r = mock_app.lambda_handler( + http_api_proxy( + raw_path='/enrollments/f58c8fa1-d14c-4c17-955b-b47b82963f40/download', + method=HTTPMethod.GET, + headers={'X-Tenant': '*'}, + ), + lambda_context, + ) + + assert r['statusCode'] == HTTPStatus.OK + data = json.loads(r['body']) + assert 'presigned_url' in data diff --git a/http-api/uv.lock b/http-api/uv.lock index 1c5b562..0a2987d 100644 --- a/http-api/uv.lock +++ b/http-api/uv.lock @@ -129,6 +129,9 @@ wheels = [ ] [package.optional-dependencies] +cognito-idp = [ + { name = "mypy-boto3-cognito-idp" }, +] essential = [ { name = "mypy-boto3-cloudformation" }, { name = "mypy-boto3-dynamodb" }, @@ -426,7 +429,7 @@ dependencies = [ [package.dev-dependencies] dev = [ - { name = "boto3-stubs", extra = ["essential"] }, + { name = "boto3-stubs", extra = ["cognito-idp", "essential"] }, { name = "jsonlines" }, { name = "psycopg2-binary" }, { name = "pycouchdb" }, @@ -442,7 +445,7 @@ requires-dist = [{ name = "layercake", directory = "../layercake" }] [package.metadata.requires-dev] dev = [ - { name = "boto3-stubs", extras = ["essential"], specifier = ">=1.38.26" }, + { name = "boto3-stubs", extras = ["cognito-idp", "essential"], specifier = ">=1.38.26" }, { name = "jsonlines", specifier = ">=4.0.0" }, { name = "psycopg2-binary", specifier = ">=2.9.10" }, { name = "pycouchdb", specifier = ">=1.16.0" }, @@ -586,6 +589,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1e/2f/d20ad6e0113f982ea255fcb4ed94f70d0111757d7d03bfacebc2d9f60ba4/mypy_boto3_cloudformation-1.38.0-py3-none-any.whl", hash = "sha256:a1411aa5875b737492aaac5f7e8ce450f034c18f972eb608a9eba6fe35837f6a", size = 69607, upload-time = "2025-04-22T21:19:29.235Z" }, ] +[[package]] +name = "mypy-boto3-cognito-idp" +version = "1.38.16" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/f2/5c9dc3df1c3068c010c618587a4f5cf22ec6e7867e45131f39b5bbbbbbed/mypy_boto3_cognito_idp-1.38.16.tar.gz", hash = "sha256:d88131296478c4e26423e1c724c7a653cf0fa01b22e65ce44ead377148452efd", size = 51097, upload-time = "2025-05-14T19:42:19.997Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e6/14/f291fc663d532926253eea1a5e9c70ef701aa12c0eab6e459ebf0d1f0bf4/mypy_boto3_cognito_idp-1.38.16-py3-none-any.whl", hash = "sha256:2c0c134204da63164cad90ccd6e4abaab77fa563a200e8ad8bf85b0b313e70c5", size = 56815, upload-time = "2025-05-14T19:42:18.043Z" }, +] + [[package]] name = "mypy-boto3-dynamodb" version = "1.38.4" diff --git a/order-events/app/events/billing/template.html b/order-events/app/events/billing/template.html deleted file mode 100644 index 43d30df..0000000 --- a/order-events/app/events/billing/template.html +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -

- Matrículas realizadas entre - {{ start_date|datetime_format('%d/%m/%Y') }} e - {{ end_date|datetime_format('%d/%m/%Y') }} -

- - - - - - - - - - - - - {% for x in items | sort(attribute='enrolled_at') %} - - - - - - - - {% endfor %} - - - - - - - -
ColaboradorCursoMatriculado emAutorValor unit.
{{ x.user.name }}{{ x.course.name }} - {{ x.enrolled_at|datetime_format('%d/%m/%Y, %H:%M') - }} - {{ x.author.name if x.author else 'N/A' }} - {{ x.unit_price|currency }} -
- Total - - {{ items| - map(attribute='unit_price')|map('float')|sum|currency - }} -
-
- -