diff --git a/.github/workflows/CD.yml b/.github/workflows/CD.yml
index c065d30..c59b314 100644
--- a/.github/workflows/CD.yml
+++ b/.github/workflows/CD.yml
@@ -1,4 +1,3 @@
-
name: CD
on:
@@ -7,52 +6,83 @@ on:
- prod
- dev
- homolog
+ - fix/githubActions
workflow_dispatch:
jobs:
DeployToAWS:
environment:
- name: ${{ github.ref_name }}
+ name: ${{ github.ref_name }}
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- - uses: actions/checkout@v2
- - name: Setup AWS Credentials
- uses: aws-actions/configure-aws-credentials@v2
- with:
- aws-region: ${{ vars.AWS_REGION }}
- role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/GithubActionsRole
- role-session-name: github-action
-
- - name: Setting stage and stack name
- run: |
- echo "STAGE=${{ github.ref_name }}"
- echo "STACK_NAME=ReservationStackScheduleANDCourts${{github.ref_name}}" >> $GITHUB_ENV
-
- - uses: actions/checkout@v3
- - uses: actions/setup-python@v4
- with:
- python-version: '3.9'
-
- - name: Installing Dependencies
- run: |
- npm install -g aws-cdk
- cd iac
- pip install -r requirements.txt
-
- - name: DeployWithCDK
- run: |
- cd iac
- cdk synth
- cdk deploy --require-approval never
-
- env:
- AWS_REGION: ${{ vars.AWS_REGION }}
- AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
- STACK_NAME: ${{ env.STACK_NAME }}
- GITHUB_REF_NAME: ${{ github.ref_name }}
- GRAPH_MICROSOFT_ENDPOINT: ${{ secrets.GRAPH_MICROSOFT_ENDPOINT }}
\ No newline at end of file
+ - uses: actions/checkout@v2
+
+ - name: Set AWS Account ID
+ run: |
+ if [[ "${{ github.ref_name }}" == "dev" ]]; then
+ echo "AWS_ACCOUNT_ID=${{ secrets.AWS_ACCOUNT_ID_DEV }}" >> $GITHUB_ENV
+ elif [[ "${{ github.ref_name }}" == "homolog" ]]; then
+ echo "AWS_ACCOUNT_ID=${{ secrets.AWS_ACCOUNT_ID_HOML }}" >> $GITHUB_ENV
+ elif [[ "${{ github.ref_name }}" == "prod" ]]; then
+ echo "AWS_ACCOUNT_ID=${{ secrets.AWS_ACCOUNT_ID_PROD }}" >> $GITHUB_ENV
+ else
+ echo "Invalid branch name!" && exit 1
+ fi
+
+ - name: Setup AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v2
+ with:
+ aws-region: ${{ vars.AWS_REGION }}
+ role-to-assume: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/GithubActionsRole
+ role-session-name: github-action
+
+ - name: Setting stage and stack name
+ run: |
+ echo "STAGE=${{ github.ref_name }}"
+ if [[ "${{ github.ref_name }}" == "prod" ]]; then
+ echo "STAGE=prod" >> $GITHUB_ENV
+ elif [[ "${{ github.ref_name }}" == "homolog" ]]; then
+ echo "STAGE=homolog" >> $GITHUB_ENV
+ elif [[ "${{ github.ref_name }}" == "dev" ]]; then
+ echo "STAGE=dev" >> $GITHUB_ENV
+ elif [[ "${{ github.ref_name }}" == "fix/githubActions" ]]; then
+ echo "STAGE=dev" >> $GITHUB_ENV
+ else
+ echo "Invalid branch name!" && exit 1
+ fi
+ echo "STACK_NAME=ReservationStackScheduleANDCourts${{env.STAGE}}" >> $GITHUB_ENV
+
+ - uses: actions/checkout@v3
+ - uses: actions/setup-python@v4
+ with:
+ python-version: "3.13"
+
+ - name: Installing Dependencies
+ run: |
+ npm install -g aws-cdk
+ cd iac
+ pip install -r requirements.txt
+
+ - name: DeployWithCDK
+ run: |
+ cd iac
+ cdk synth
+ cdk deploy --require-approval never
+
+ env:
+ AWS_REGION: ${{ vars.AWS_REGION }}
+ AWS_ACCOUNT_ID: ${{ env.AWS_ACCOUNT_ID }}
+ STACK_NAME: ${{ env.STACK_NAME }}
+ GITHUB_REF_NAME: ${{ github.ref_name }}
+ MSS_NAME: ${{ github.event.repository.name }}
+ S3_ASSETS_CDN: ${{ vars.S3_ASSETS_CDN }}
+ AUTH_DEV_SYSTEM_USERPOOL_ARN_DEV: ${{ secrets.AUTH_DEV_SYSTEM_USERPOOL_ARN_DEV }}
+ FROM_EMAIL: ${{ vars.FROM_EMAIL }}
+ HIDDEN_COPY: ${{ vars.HIDDEN_COPY }}
+ REPLY_TO_EMAIL: ${{ vars.REPLY_TO_EMAIL }}
+ USER_API_URL: ${{ secrets.USER_API_URL }}
diff --git a/.gitignore b/.gitignore
index 5e06bd6..9d783f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -135,5 +135,5 @@ dmypy.json
/.idea/
iac/local/docker/dynamodb/shared-local-instance.db
-
+# MACOS temp files
.DS_Store
\ No newline at end of file
diff --git a/iac/adjust_layer_directory.py b/iac/adjust_layer_directory.py
index 5232368..61845b2 100644
--- a/iac/adjust_layer_directory.py
+++ b/iac/adjust_layer_directory.py
@@ -1,37 +1,57 @@
import os
import shutil
-from pathlib import Path
-import sys
-
-IAC_DIRECTORY_NAME = "iac"
-SOURCE_DIRECTORY_NAME = "src"
-LAMBDA_LAYER_PREFIX = os.path.join("python", "src")
-
-
-def adjust_layer_directory(shared_dir_name: str, destination: str):
- # Get the root directory of the source directory
- root_directory = Path(__file__).parent.parent
- iac_directory = os.path.join(root_directory, IAC_DIRECTORY_NAME)
-
- print(f"Root directory: {root_directory}")
- print(f"Root direcotry files: {os.listdir(root_directory)}")
- print(f"IaC directory: {iac_directory}")
- print(f"IaC directory files: {os.listdir(iac_directory)}")
-
-
- # Get the destination and source directory
- destination_directory = os.path.join(root_directory, IAC_DIRECTORY_NAME, destination)
- source_directory = os.path.join(root_directory, SOURCE_DIRECTORY_NAME, shared_dir_name)
-
- # Delete the destination directory if it exists
- if os.path.exists(destination_directory):
- shutil.rmtree(destination_directory)
-
- # Copy the source directory to the destination directory
- shutil.copytree(source_directory, os.path.join(destination_directory, LAMBDA_LAYER_PREFIX, shared_dir_name))
- print(
- f"Copying files from {source_directory} to {os.path.join(destination_directory, LAMBDA_LAYER_PREFIX, shared_dir_name)}")
-
-
+import subprocess
+from pathlib import Path # Importe a biblioteca pathlib
+
+# --- Configurações ---
+BUILD_DIRECTORY = "build"
+PYTHON_TOP_LEVEL_DIR = os.path.join(BUILD_DIRECTORY, "python")
+REQUIREMENTS_FILE = "requirements-layer.txt"
+
+# --- CONSTRUÇÃO CORRETA DO CAMINHO ---
+# Pega o diretório do projeto (a raiz 'reservation_api') subindo um nível a partir do script atual.
+PROJECT_ROOT = Path(__file__).parent.parent
+# Agora, constrói o caminho para 'src/shared' a partir da raiz do projeto.
+SHARED_CODE_SOURCE = os.path.join(PROJECT_ROOT, "src", "shared")
+
+
+def adjust_layer_directory():
+ """
+ Prepara um diretório 'build' para uma Lambda Layer do AWS CDK.
+
+ A função junta o código local compartilhado e as dependências externas (pip)
+ na estrutura de pastas que a Lambda espera (/python).
+ """
+
+ # Garante que o build seja sempre limpo, removendo qualquer artefato antigo.
+ if os.path.exists(BUILD_DIRECTORY):
+ shutil.rmtree(BUILD_DIRECTORY)
+
+ # Cria a estrutura de pastas 'build/python/src/'.
+ # Isso é necessário para que os imports 'from src.shared...' funcionem na Lambda.
+ shared_code_intermediate_dir = os.path.join(PYTHON_TOP_LEVEL_DIR, "src")
+ os.makedirs(shared_code_intermediate_dir)
+
+ # Copia o código compartilhado (de 'src/shared') para dentro da estrutura da Layer.
+ # O resultado final será 'build/python/src/shared'.
+ print(f"Copiando código de: {SHARED_CODE_SOURCE}") # Adicionado para debug
+ shared_code_dest = os.path.join(shared_code_intermediate_dir, os.path.basename(SHARED_CODE_SOURCE))
+ shutil.copytree(SHARED_CODE_SOURCE, shared_code_dest)
+
+ # Se o arquivo de dependências existir, instala todas as bibliotecas.
+ # O arquivo de requirements também precisa ser lido a partir da raiz.
+ requirements_path = os.path.join(PROJECT_ROOT, REQUIREMENTS_FILE)
+ if os.path.exists(requirements_path):
+ # Instala os pacotes diretamente na pasta 'build/python'.
+ # Isso permite que a Lambda importe as bibliotecas de forma padrão (ex: import requests).
+ subprocess.check_call(
+ ["pip", "install", "-r", requirements_path, "-t", PYTHON_TOP_LEVEL_DIR, "--no-cache-dir"]
+ )
+ else:
+ # Apenas um aviso caso o arquivo não seja encontrado.
+ print(f"Aviso: Arquivo '{requirements_path}' não encontrado. Nenhuma dependência externa será instalada.")
+
+
+# Ponto de entrada do script.
if __name__ == '__main__':
- adjust_layer_directory(shared_dir_name="shared", destination="copied_shared")
\ No newline at end of file
+ adjust_layer_directory()
\ No newline at end of file
diff --git a/iac/app.py b/iac/app.py
index edebb46..6e19da3 100644
--- a/iac/app.py
+++ b/iac/app.py
@@ -10,7 +10,7 @@
print("Starting the CDK")
print("Adjusting the layer directory")
-adjust_layer_directory(shared_dir_name="shared", destination="copied_shared")
+adjust_layer_directory()
print("Finished adjusting the layer directory")
diff --git a/iac/local/minio/docker-compose-minio.yml b/iac/local/minio/docker-compose-minio.yml
new file mode 100644
index 0000000..4a0b046
--- /dev/null
+++ b/iac/local/minio/docker-compose-minio.yml
@@ -0,0 +1,41 @@
+version: '3.8' # The top-level 'version' is obsolete but using a more modern one like 3.8 is fine
+
+services:
+ minio:
+ image: minio/minio:latest
+ container_name: minio-reservation
+ # ✅ SET credentials for the MinIO server
+ environment:
+ MINIO_ROOT_USER: root # If you change any credentials, you have to match it in environments
+ MINIO_ROOT_PASSWORD: root1234
+ ports:
+ - "9000:9000"
+ - "9001:9001"
+ volumes:
+ - minio-data:/data
+ command: server /data --console-address :9001
+
+ create-bucket:
+ image: minio/mc:latest
+ depends_on:
+ - minio
+ entrypoint: >
+ /bin/sh -c "
+ # ✅ Make the script exit on any error
+ set -e;
+
+ # Wait for MinIO to be ready
+ # Use the more modern 'mc alias set' and provide the credentials
+ /usr/bin/mc alias set s3 http://minio:9000 root root1234;
+
+ # Create the bucket
+ /usr/bin/mc mb s3/bucket-test;
+
+ # Set the policy
+ /usr/bin/mc policy set public s3/bucket-test;
+
+ echo '✅ Bucket created successfully!';
+ "
+
+volumes:
+ minio-data:
diff --git a/iac/stacks/bucket_stack.py b/iac/stacks/bucket_stack.py
index df796f8..2e28d8d 100644
--- a/iac/stacks/bucket_stack.py
+++ b/iac/stacks/bucket_stack.py
@@ -1,8 +1,9 @@
from aws_cdk import (
aws_s3 as s3,
+ aws_cloudfront as cloudfront,
+ aws_cloudfront_origins as origins,
aws_iam as iam,
RemovalPolicy,
- Stack,
)
from constructs import Construct
import os
@@ -24,8 +25,19 @@ def __init__(self, scope: Construct, **kwargs) -> None:
stage = 'DEV'
self.bucket = s3.Bucket(
- self, f"BACK_S3_REPORT_BUCKET_{stage}",
- bucket_name=f"{self.stack_name}-report-bucket{stage}".lower(),
+ self, f"RESERVATION_BACK_S3_BUCKET_{stage}",
+ # TODO remover isso quando voltar pra conta nova ou tentar deletar o bucket criado la com power user
+ bucket_name=f"{self.stack_name}-bucket-{stage}".lower(),
versioned=True,
removal_policy=RemovalPolicy.DESTROY if not (stage == 'PROD') else RemovalPolicy.RETAIN,
+ block_public_access=s3.BlockPublicAccess.BLOCK_ALL
+ )
+
+ self.distribution = cloudfront.Distribution(
+ self, f"ReservationBucketDistribution{stage}",
+ default_behavior=cloudfront.BehaviorOptions(
+ origin=origins.S3Origin(self.bucket),
+ viewer_protocol_policy=cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
+ ),
+ default_root_object=None # não obrigatório, mas evita erro se não tiver index.html
)
diff --git a/iac/stacks/iac_stack.py b/iac/stacks/iac_stack.py
index 7ef8b21..38c16d3 100644
--- a/iac/stacks/iac_stack.py
+++ b/iac/stacks/iac_stack.py
@@ -1,5 +1,5 @@
from aws_cdk import (
- Stack,
+ Stack, aws_iam
)
from constructs import Construct
from aws_cdk.aws_apigateway import RestApi, Cors
@@ -55,7 +55,11 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
"DYNAMO_PARTITION_KEY": "PK",
"DYNAMO_SORT_KEY": "SK",
"REGION": self.aws_region,
- "GRAPH_MICROSOFT_ENDPOINT": os.getenv("GRAPH_MICROSOFT_ENDPOINT")
+ "USER_API_URL": os.environ.get("USER_API_URL"),
+ "S3_BUCKET_NAME": self.s3_bucket.bucket.bucket_name,
+ "FROM_EMAIL": os.environ.get("FROM_EMAIL"),
+ "HIDDEN_COPY": os.environ.get("HIDDEN_COPY"),
+ "S3_ASSETS_CDN": os.environ.get("S3_ASSETS_CDN")
}
@@ -69,4 +73,23 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
for function in self.lambda_stack.functions_that_need_s3_permissions:
self.s3_bucket.bucket.grant_read_write(function)
+ ses_admin_policy = aws_iam.PolicyStatement(
+ effect=aws_iam.Effect.ALLOW,
+ actions=[
+ "ses:*",
+ ],
+ resources=[
+ "*"
+ ]
+ )
+
+ functions_that_need_ses_permissions = [
+ self.lambda_stack.delete_booking
+ ]
+
+ for f in functions_that_need_ses_permissions:
+ f.add_environment("HIDDEN_COPY", os.environ.get("HIDDEN_COPY"))
+ f.add_environment("FROM_EMAIL", os.environ.get("FROM_EMAIL"))
+ f.add_environment("REPLY_TO_EMAIL", os.environ.get("REPLY_TO_EMAIL"))
+ f.add_to_role_policy(ses_admin_policy)
diff --git a/iac/stacks/lambda_stack.py b/iac/stacks/lambda_stack.py
index dc3ebe4..dbf1138 100644
--- a/iac/stacks/lambda_stack.py
+++ b/iac/stacks/lambda_stack.py
@@ -3,13 +3,12 @@
from aws_cdk import (
aws_lambda as lambda_,
NestedStack, Duration,
- aws_apigateway as apigw,
+ aws_apigateway as apigw
)
from constructs import Construct
from aws_cdk.aws_apigateway import Resource, LambdaIntegration
-from aws_cdk.aws_events import Rule, Schedule
-from aws_cdk.aws_events_targets import LambdaFunction
-
+from aws_cdk.aws_events import Rule, Schedule, EventField, RuleTargetInput
+from aws_cdk.aws_events_targets import LambdaFunction
class LambdaStack(Construct):
functions_that_need_dynamo_permissions = []
@@ -20,7 +19,7 @@ def create_lambda_api_gateway_integration(self, module_name: str, method: str, a
self, module_name.title(),
code=lambda_.Code.from_asset(f"../src/modules/{module_name}"),
handler=f"app.{module_name}_presenter.lambda_handler",
- runtime=lambda_.Runtime.PYTHON_3_9,
+ runtime=lambda_.Runtime("python3.13"),
layers=[self.lambda_layer],
environment=environment_variables,
timeout=Duration.seconds(15)
@@ -42,18 +41,23 @@ def create_lambda_event_bridge_integration(self,
module_name.title(),
code=lambda_.Code.from_asset(f"../src/modules/{module_name}"),
handler=f"app.{module_name}_presenter.lambda_handler",
- runtime=lambda_.Runtime.PYTHON_3_9,
+ runtime=lambda_.Runtime("python3.13"),
layers=[self.lambda_layer],
environment=environment_variables,
timeout=Duration.seconds(15)
)
rule = Rule(
- self, f"{module_name.title()}EventRule",
+ self, f"{module_name.title()}EventRuleForWeeklyUpload",
schedule=cron_schedule
)
- rule.add_target(LambdaFunction(function))
+ input_transformer = RuleTargetInput.from_object({
+ "current_date": EventField.time,
+ "message": "weekly report trigger!"
+ })
+
+ rule.add_target(LambdaFunction(function, event=input_transformer))
return function
@@ -71,43 +75,47 @@ def __init__(self, scope: Construct, api_gateway_resource: Resource, environment
super().__init__(scope, f"{self.stack_name}_LambdaStack_{stage}")
self.lambda_layer = lambda_.LayerVersion(self, f"{self.stack_name}_Lambda_Layer_{stage}",
- code=lambda_.Code.from_asset("./copied_shared"),
- compatible_runtimes=[lambda_.Runtime.PYTHON_3_9]
+ code=lambda_.Code.from_asset("./build"),
+ compatible_runtimes=[lambda_.Runtime("python3.13")]
)
-
- self.graph_authorizer_lambda = lambda_.Function(
- self, "GraphAuthorizerLambdaReservationStacksANDCourts",
- code=lambda_.Code.from_asset("../src/functions/graph_authorizer"),
- handler="graph_authorizer.lambda_handler",
- runtime=lambda_.Runtime.PYTHON_3_9,
+
+ authorizer_lambda = lambda_.Function(
+ self, "AuthorizerUserMssReservationApiLambda",
+ code=lambda_.Code.from_asset("../src/shared/authorizer"),
+ handler="user_mss_authorizer.lambda_handler",
+ runtime=lambda_.Runtime("python3.13"),
layers=[self.lambda_layer],
environment=environment_variables,
- timeout=Duration.seconds(15),
+ timeout=Duration.seconds(15)
)
- self.token_authorizer_graph = apigw.TokenAuthorizer(
- self, "TokenAuthorizerGraphReservationStacksANDCourts",
- handler=self.graph_authorizer_lambda,
+ token_authorizer_lambda = apigw.TokenAuthorizer(
+ self, "TokenAuthorizerReservationApi",
+ handler=authorizer_lambda,
identity_source=apigw.IdentitySource.header("Authorization"),
- authorizer_name="GraphAuthorizerReservationStacksANDCourts",
+ authorizer_name="AuthorizerUserMssReservationMssAlertLambda",
results_cache_ttl=Duration.seconds(0)
)
+ #ready for auth
self.create_booking = self.create_lambda_api_gateway_integration(
module_name="create_booking",
method="POST",
api_resource=api_gateway_resource,
environment_variables=environment_variables,
- authorizer=self.token_authorizer_graph
+ authorizer=token_authorizer_lambda
)
+ #ready for auth
self.update_booking = self.create_lambda_api_gateway_integration(
module_name="update_booking",
method="PUT",
api_resource=api_gateway_resource,
- environment_variables=environment_variables
+ environment_variables=environment_variables,
+ authorizer=token_authorizer_lambda
)
+ #not ready for auth AND not used?
self.get_booking = self.create_lambda_api_gateway_integration(
module_name="get_booking",
method="GET",
@@ -122,14 +130,16 @@ def __init__(self, scope: Construct, api_gateway_resource: Resource, environment
environment_variables=environment_variables,
)
+ #not ready for auth??TODO
self.delete_booking = self.create_lambda_api_gateway_integration(
module_name="delete_booking",
method="DELETE",
api_resource=api_gateway_resource,
environment_variables=environment_variables,
- authorizer=self.token_authorizer_graph
+ authorizer=token_authorizer_lambda
)
+ #not auth and unused
self.get_all_bookings = self.create_lambda_api_gateway_integration(
module_name="get_all_bookings",
method="GET",
@@ -137,13 +147,16 @@ def __init__(self, scope: Construct, api_gateway_resource: Resource, environment
environment_variables=environment_variables
)
+ #ready for auth
self.create_court = self.create_lambda_api_gateway_integration(
module_name="create_court",
method="POST",
api_resource=api_gateway_resource,
- environment_variables=environment_variables
+ environment_variables=environment_variables,
+ authorizer=token_authorizer_lambda
)
+ #not ready TODO
self.get_court = self.create_lambda_api_gateway_integration(
module_name="get_court",
method="GET",
@@ -151,20 +164,25 @@ def __init__(self, scope: Construct, api_gateway_resource: Resource, environment
environment_variables=environment_variables
)
+ #ready
self.update_court = self.create_lambda_api_gateway_integration(
module_name="update_court",
method="PUT",
api_resource=api_gateway_resource,
- environment_variables=environment_variables
+ environment_variables=environment_variables,
+ authorizer=token_authorizer_lambda
)
+ #ready
self.delete_court = self.create_lambda_api_gateway_integration(
module_name="delete_court",
method="DELETE",
api_resource=api_gateway_resource,
- environment_variables=environment_variables
+ environment_variables=environment_variables,
+ authorizer=token_authorizer_lambda
)
+ #not ready? needed?
self.get_all_courts = self.create_lambda_api_gateway_integration(
module_name="get_all_courts",
method="GET",
@@ -172,6 +190,7 @@ def __init__(self, scope: Construct, api_gateway_resource: Resource, environment
environment_variables=environment_variables
)
+ #yes
self.health_check = self.create_lambda_api_gateway_integration(
module_name="health_check",
method="GET",
@@ -179,9 +198,24 @@ def __init__(self, scope: Construct, api_gateway_resource: Resource, environment
environment_variables=environment_variables
)
+ #does not need auth / not a route
self.generate_report = self.create_lambda_event_bridge_integration(
module_name="generate_report",
- cron_schedule=Schedule.cron(minute="0", hour="18", week_day="FRI"),
+ cron_schedule=Schedule.cron(minute="30", hour="11", week_day="FRI"),
+ environment_variables=environment_variables
+ )
+
+ self.get_all_admin_bookings = self.create_lambda_api_gateway_integration(
+ module_name="get_all_admin_bookings",
+ method="GET",
+ api_resource=api_gateway_resource,
+ environment_variables=environment_variables
+ )
+
+ self.get_all_bookings_grouped_by_role = self.create_lambda_api_gateway_integration(
+ module_name="get_all_bookings_grouped_by_role",
+ method="GET",
+ api_resource=api_gateway_resource,
environment_variables=environment_variables
)
@@ -197,7 +231,9 @@ def __init__(self, scope: Construct, api_gateway_resource: Resource, environment
self.delete_booking,
self.get_all_bookings,
self.get_bookings,
- self.graph_authorizer_lambda
+ self.generate_report,
+ self.get_all_admin_bookings,
+ self.get_all_bookings_grouped_by_role
]
self.functions_that_need_s3_permissions = [
diff --git a/requirements-dev.txt b/requirements-dev.txt
index ab21f95..2a9eb03 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -3,4 +3,8 @@ pytest-cov==4.0.0
boto3==1.24.88
python-dotenv==0.21.0
aws-lambda-powertools==2.9.0
-aws_xray_sdk==2.11.0
\ No newline at end of file
+aws_xray_sdk==2.11.0
+
+pandas==2.2.3
+XlsxWriter==3.2.2
+requests==2.32.3
\ No newline at end of file
diff --git a/requirements-layer.txt b/requirements-layer.txt
new file mode 100644
index 0000000..d6f5bfe
--- /dev/null
+++ b/requirements-layer.txt
@@ -0,0 +1,7 @@
+#boto3 compatibility
+urllib3<1.27
+
+#lambda needs
+pandas==2.2.3
+XlsxWriter==3.2.2
+requests==2.32.3
\ No newline at end of file
diff --git a/src/modules/create_booking/app/create_booking_controller.py b/src/modules/create_booking/app/create_booking_controller.py
index 8e737e9..798ee6b 100644
--- a/src/modules/create_booking/app/create_booking_controller.py
+++ b/src/modules/create_booking/app/create_booking_controller.py
@@ -1,5 +1,7 @@
import json
+from src.shared.domain.enums.type import BOOKING_TYPE
+
from .create_booking_usecase import CreateBookingUsecase
from .create_booking_viewmodel import CreateBookingViewmodel
from src.shared.helpers.errors.controller_errors import MissingParameters, WrongTypeParameter, AuthorizerError
@@ -29,8 +31,9 @@ def __call__(self, request: IRequest):
end_date = request.data.get('end_date', None)
court_number = request.data.get('court_number', None)
sport = request.data.get('sport', None)
- user_id = user_from_authorizer.get('id', None)
+ user_id = user_from_authorizer.get('user_id', None)
materials = request.data.get('materials', None)
+ booking_type = request.data.get('type', None)
try:
@@ -75,6 +78,13 @@ def __call__(self, request: IRequest):
raise WrongTypeParameter(fieldName='materials',
fieldTypeExpected='list',
fieldTypeReceived=type(materials).__name__)
+
+ if booking_type is None:
+ raise MissingParameters('type')
+ if not isinstance(booking_type, str):
+ raise WrongTypeParameter(fieldName='type',
+ fieldTypeExpected='str',
+ fieldTypeReceived=type(booking_type).__name__)
booking = self.create_booking_use_case(
start_date=start_date,
@@ -82,7 +92,8 @@ def __call__(self, request: IRequest):
court_number=court_number,
sport=sport,
user_id=user_id,
- materials=materials
+ materials=materials,
+ booking_type=booking_type
)
viewmodel = CreateBookingViewmodel(booking=booking)
diff --git a/src/modules/create_booking/app/create_booking_presenter.py b/src/modules/create_booking/app/create_booking_presenter.py
index c67b811..c0875c4 100644
--- a/src/modules/create_booking/app/create_booking_presenter.py
+++ b/src/modules/create_booking/app/create_booking_presenter.py
@@ -2,14 +2,23 @@
from .create_booking_usecase import CreateBookingUsecase
from src.shared.environments import Environments
from src.shared.helpers.external_interfaces.http_lambda_requests import LambdaHttpRequest, LambdaHttpResponse
+import json
repo = Environments.get_booking_repo()()
usecase = CreateBookingUsecase(repo)
controller = CreateBookingController(usecase)
def lambda_handler(event, context):
+
httpRequest = LambdaHttpRequest(data=event)
- httpRequest.data['user_from_authorizer'] = event.get('requestContext', {}).get('authorizer', {}).get('user', None)
+
+ user_info_string = event.get('requestContext', {}).get('authorizer', {}).get('user')
+
+ if user_info_string:
+ httpRequest.data['user_from_authorizer'] = json.loads(user_info_string).get('user')
+ else:
+ httpRequest.data['user_from_authorizer'] = None
+
response = controller(request=httpRequest)
httpResponse = LambdaHttpResponse(status_code=response.status_code, body=response.body, headers=response.headers)
diff --git a/src/modules/create_booking/app/create_booking_usecase.py b/src/modules/create_booking/app/create_booking_usecase.py
index aca8453..a795713 100644
--- a/src/modules/create_booking/app/create_booking_usecase.py
+++ b/src/modules/create_booking/app/create_booking_usecase.py
@@ -3,6 +3,7 @@
from src.shared.domain.entities.booking import Booking
from src.shared.domain.enums.sport import SPORT
+from src.shared.domain.enums.type import BOOKING_TYPE
from src.shared.domain.repositories.booking_repository_interface import IBookingRepository
from src.shared.helpers.errors.usecase_errors import DuplicatedItem, InvalidSchedule
@@ -15,6 +16,7 @@ class CreateBookingUsecase:
user_id: str
booking_id: str
materials: List[str]
+ booking_type: BOOKING_TYPE
def __init__(self, repo: IBookingRepository):
self.repo = repo
@@ -25,7 +27,8 @@ def __call__(self,
court_number: int,
sport: str,
user_id: str,
- materials: List[str]
+ materials: List[str],
+ booking_type: str
) -> Booking:
booking_id = str(uuid.uuid4())
@@ -41,12 +44,22 @@ def __call__(self,
for material in materials:
if not isinstance(material, str):
raise ValueError("Invalid material type")
+
+ if booking_type not in [type.value for type in BOOKING_TYPE]:
+ raise ValueError("Invalid type enum value")
+
+ self.booking_type = BOOKING_TYPE(booking_type)
all_bookings = self.repo.get_all_bookings()
for booking in all_bookings:
- if (booking.start_date < end_date and booking.end_date > start_date
- and booking.court_number == court_number):
+ if (
+ (
+ booking.start_date < end_date + (15 * 60 * 1000) #15 minutes in mseconds
+ and booking.end_date > start_date - (15 * 60 * 1000) #15 minutes in mseconds
+ and booking.court_number == court_number
+ )
+ ):
raise InvalidSchedule()
resp = self.repo.create_booking(Booking(start_date,
@@ -55,7 +68,8 @@ def __call__(self,
self.sport,
user_id,
booking_id,
- materials))
+ materials,
+ self.booking_type))
return resp
diff --git a/src/modules/create_booking/app/create_booking_viewmodel.py b/src/modules/create_booking/app/create_booking_viewmodel.py
index b91e23a..19675b4 100644
--- a/src/modules/create_booking/app/create_booking_viewmodel.py
+++ b/src/modules/create_booking/app/create_booking_viewmodel.py
@@ -1,6 +1,7 @@
from typing import List
from src.shared.domain.enums.sport import SPORT
+from src.shared.domain.enums.type import BOOKING_TYPE
class CreateBookingViewmodel:
@@ -12,6 +13,7 @@ class CreateBookingViewmodel:
user_id: str
booking_id: str
materials: List[str]
+ booking_type: BOOKING_TYPE
def __init__(self, booking):
self.start_date = booking.start_date
@@ -21,6 +23,7 @@ def __init__(self, booking):
self.user_id = booking.user_id
self.booking_id = booking.booking_id
self.materials = booking.materials
+ self.booking_type = booking.booking_type
def to_dict(self):
@@ -32,7 +35,8 @@ def to_dict(self):
"sport": self.sport.value,
"user_id": self.user_id,
"booking_id": self.booking_id,
- "materials": self.materials
+ "materials": self.materials,
+ "type": self.booking_type.value
},
"message": "Booking created successfully"
}
diff --git a/src/modules/create_court/app/create_court_controller.py b/src/modules/create_court/app/create_court_controller.py
index 8ebc8ef..4203880 100644
--- a/src/modules/create_court/app/create_court_controller.py
+++ b/src/modules/create_court/app/create_court_controller.py
@@ -2,10 +2,11 @@
from .create_court_viewmodel import CreateCourtViewmodel
from src.shared.helpers.errors.controller_errors import MissingParameters, WrongTypeParameter
from src.shared.helpers.errors.domain_errors import EntityError
-from src.shared.helpers.errors.usecase_errors import DuplicatedItem
+from src.shared.helpers.errors.usecase_errors import DuplicatedItem, ForbiddenAction
from src.shared.helpers.external_interfaces.external_interface import IRequest, IResponse
from src.shared.helpers.external_interfaces.http_codes import BadRequest, Created, InternalServerError
from src.shared.domain.enums.status_enum import STATUS
+import json
class CreateCourtController:
@@ -15,7 +16,7 @@ def __init__(self, usecase: CreateCourtUsecase):
def __call__(self, request: IRequest):
- try:
+ try:
if request.data.get('number') is None:
raise MissingParameters('number')
@@ -39,11 +40,18 @@ def __call__(self, request: IRequest):
if request.data.get('photo') is not None and type(request.data.get('photo')) is not str:
raise WrongTypeParameter(fieldName= 'photo', fieldTypeExpected= str, fieldTypeReceived= type(request.data.get('photo')))
+ user = request.data.get("user_from_authorizer")
+
+ if not isinstance(user, dict):
+
+ user = json.loads(user)
+
court = self.usecase(
number= request.data.get('number'),
status= status,
is_field= request.data.get('is_field'),
- photo= request.data.get('photo')
+ photo= request.data.get('photo'),
+ role=user.get("role")
)
viewmodel = CreateCourtViewmodel(court= court)
@@ -62,6 +70,9 @@ def __call__(self, request: IRequest):
except EntityError as err:
return BadRequest(body=err.message)
+ except ForbiddenAction as err:
+ return BadRequest(body=err.message)
+
except Exception as err:
return InternalServerError(body=err.args[0])
diff --git a/src/modules/create_court/app/create_court_presenter.py b/src/modules/create_court/app/create_court_presenter.py
index 88639b0..746f31a 100644
--- a/src/modules/create_court/app/create_court_presenter.py
+++ b/src/modules/create_court/app/create_court_presenter.py
@@ -2,14 +2,24 @@
from .create_court_usecase import CreateCourtUsecase
from src.shared.environments import Environments
from src.shared.helpers.external_interfaces.http_lambda_requests import LambdaHttpRequest, LambdaHttpResponse
+import json
repo = Environments.get_reservation_repo()()
usecase = CreateCourtUsecase(repo)
controller = CreateCourtController(usecase)
def lambda_handler(event, context):
+
httpRequest = LambdaHttpRequest(data=event)
+
+ user_info_string = event.get('requestContext', {}).get('authorizer', {}).get('user')
+
+ if user_info_string:
+ httpRequest.data['user_from_authorizer'] = json.loads(user_info_string).get('user')
+ else:
+ httpRequest.data['user_from_authorizer'] = None
+
response = controller(request=httpRequest)
httpResponse = LambdaHttpResponse(status_code=response.status_code, body=response.body, headers=response.headers)
-
+
return httpResponse.toDict()
\ No newline at end of file
diff --git a/src/modules/create_court/app/create_court_usecase.py b/src/modules/create_court/app/create_court_usecase.py
index 35bb56b..9a9068c 100644
--- a/src/modules/create_court/app/create_court_usecase.py
+++ b/src/modules/create_court/app/create_court_usecase.py
@@ -1,17 +1,20 @@
from typing import Optional
from src.shared.domain.entities.court import Court
from src.shared.domain.enums.status_enum import STATUS
-from src.shared.helpers.errors.usecase_errors import DuplicatedItem
+from src.shared.helpers.errors.usecase_errors import DuplicatedItem, ForbiddenAction
from src.shared.domain.repositories.reservation_repository_interface import IReservationRepository
class CreateCourtUsecase:
def __init__(self, repo: IReservationRepository):
self.repo = repo
- def __call__(self, number: int, status: STATUS, is_field: bool, photo: Optional[str] = None):
+ def __call__(self, number: int, status: STATUS, is_field: bool, role: str, photo: Optional[str] = None):
if self.repo.get_court(number) is not None:
raise DuplicatedItem('number')
+
+ if role != "ADMIN":
+ raise ForbiddenAction("user, only admin can create courts")
court = Court(
number = number,
diff --git a/src/modules/delete_booking/app/delete_booking_controller.py b/src/modules/delete_booking/app/delete_booking_controller.py
index ed24ede..7315569 100644
--- a/src/modules/delete_booking/app/delete_booking_controller.py
+++ b/src/modules/delete_booking/app/delete_booking_controller.py
@@ -1,13 +1,13 @@
-import json
-
+from typing import Any
+from src.shared.domain.entities.booking import Booking
from .delete_booking_usecase import DeleteBookingUsecase
from .delete_booking_viewmodel import DeleteBookingViewModel
-from src.shared.helpers.errors.controller_errors import MissingParameters, WrongTypeParameter, AuthorizerError
+from src.shared.helpers.errors.controller_errors import MissingParameters, WrongTypeParameter
from src.shared.helpers.errors.domain_errors import EntityError
from src.shared.helpers.errors.usecase_errors import NoItemsFound, ForbiddenAction
from src.shared.helpers.external_interfaces.external_interface import IRequest, IResponse
-from src.shared.helpers.external_interfaces.http_codes import OK, BadRequest, InternalServerError, NotFound, Forbidden
-
+from src.shared.helpers.external_interfaces.http_codes import OK, BadRequest, Created, InternalServerError, NotFound, Forbidden
+from src.shared.domain.enums.sport import SPORT
class DeleteBookingController:
@@ -15,35 +15,23 @@ def __init__(self, usecase: DeleteBookingUsecase):
self.usecase = usecase
def __call__(self, request: IRequest) -> IResponse:
- try:
-
- user_from_authorizer = request.data.get('user_from_authorizer', None)
- if not isinstance(request.data.get('user_from_authorizer'), dict):
-
- user_from_authorizer = json.loads(request.data.get('user_from_authorizer'))
-
- if user_from_authorizer is None:
- raise AuthorizerError()
+ try:
- user_id = user_from_authorizer.get('id', None)
+ if request.data.get('user_from_authorizer') is None:
+ raise MissingParameters('user authorizer')
+
+ user = request.data.get('user_from_authorizer')
if request.data.get('booking_id') is None:
raise MissingParameters('booking_id')
- booking = self.usecase(booking_id=request.data.get('booking_id'),
- user_id=user_id)
+ booking = self.usecase(booking_id=request.data.get('booking_id'), user=user)
viewmodel = DeleteBookingViewModel(booking)
return OK(viewmodel.to_dict())
except MissingParameters as err:
return BadRequest(body=err.message)
-
- except ForbiddenAction as err:
- return Forbidden(body=err.message)
-
- except AuthorizerError as err:
- return InternalServerError(body=err.message)
except WrongTypeParameter as err:
return BadRequest(body=err.message)
@@ -54,5 +42,8 @@ def __call__(self, request: IRequest) -> IResponse:
except EntityError as err:
return BadRequest(body=err.message)
+ except ForbiddenAction as err:
+ return Forbidden(body=err.message)
+
except Exception as err:
return InternalServerError(body=err.args[0])
\ No newline at end of file
diff --git a/src/modules/delete_booking/app/delete_booking_presenter.py b/src/modules/delete_booking/app/delete_booking_presenter.py
index 5d2836e..72a5648 100644
--- a/src/modules/delete_booking/app/delete_booking_presenter.py
+++ b/src/modules/delete_booking/app/delete_booking_presenter.py
@@ -2,15 +2,24 @@
from .delete_booking_usecase import DeleteBookingUsecase
from src.shared.environments import Environments
from src.shared.helpers.external_interfaces.http_lambda_requests import LambdaHttpRequest, LambdaHttpResponse
+import json
repo = Environments.get_booking_repo()()
usecase = DeleteBookingUsecase(repo)
controller = DeleteBookingController(usecase)
def lambda_handler(event, context):
+
httpRequest = LambdaHttpRequest(data=event)
- httpRequest.data['user_from_authorizer'] = event.get('requestContext', {}).get('authorizer', {}).get('user', {})
+
+ user_info_string = event.get('requestContext', {}).get('authorizer', {}).get('user')
+
+ if user_info_string:
+ httpRequest.data['user_from_authorizer'] = json.loads(user_info_string).get('user')
+ else:
+ httpRequest.data['user_from_authorizer'] = None
+
response = controller(request=httpRequest)
httpResponse = LambdaHttpResponse(status_code=response.status_code, body=response.body, headers=response.headers)
-
+
return httpResponse.toDict()
\ No newline at end of file
diff --git a/src/modules/delete_booking/app/delete_booking_usecase.py b/src/modules/delete_booking/app/delete_booking_usecase.py
index ceda421..18559e1 100644
--- a/src/modules/delete_booking/app/delete_booking_usecase.py
+++ b/src/modules/delete_booking/app/delete_booking_usecase.py
@@ -1,30 +1,36 @@
from src.shared.domain.entities.booking import Booking
from src.shared.domain.enums.sport import SPORT
-from src.shared.domain.repositories.booking_repository_interface import IBookingRepository
-from src.shared.helpers.errors.usecase_errors import DuplicatedItem, ForbiddenAction
+from src.shared.helpers.errors.usecase_errors import DuplicatedItem
from src.shared.helpers.errors.domain_errors import EntityError
from src.shared.helpers.errors.usecase_errors import NoItemsFound
-from src.shared.domain.repositories.reservation_repository_interface import IReservationRepository
+from src.shared.domain.repositories.booking_repository_interface import IBookingRepository
class DeleteBookingUsecase:
- def __init__(self, repo: IBookingRepository):
+ def __init__(self, repo:IBookingRepository):
self.repo = repo
- def __call__(self,
- booking_id: str,
- user_id: str):
+ def __call__(self, booking_id: int, user):
+ if user.get('user_id') is None:
+ raise EntityError('user id')
- if not Booking.validate_booking_id(booking_id):
- raise EntityError('booking_id')
+ if user.get('name') is None:
+ raise EntityError('user id')
- booking = self.repo.get_booking(booking_id=booking_id)
+ if user.get('email') is None:
+ raise EntityError('user email')
+
+ if user.get('role') is None:
+ raise EntityError('user role')
+ if not Booking.validate_booking_id(booking_id):
+ raise EntityError('booking_id')
+
+ booking = self.repo.delete_booking(booking_id=booking_id, user=user)
+
if booking is None:
raise NoItemsFound('booking')
-
- if booking.user_id != user_id:
- raise ForbiddenAction('user; trying to delete booking that is not his')
- booking = self.repo.delete_booking(booking_id=booking_id)
+ if booking is None:
+ raise NoItemsFound('booking')
return booking
\ No newline at end of file
diff --git a/src/modules/delete_booking/app/delete_booking_viewmodel.py b/src/modules/delete_booking/app/delete_booking_viewmodel.py
index eddbcd4..309192c 100644
--- a/src/modules/delete_booking/app/delete_booking_viewmodel.py
+++ b/src/modules/delete_booking/app/delete_booking_viewmodel.py
@@ -20,6 +20,7 @@ def __init__(self, booking: Booking):
self.user_id = booking.user_id
self.booking_id = booking.booking_id
self.materials = booking.materials
+ self.booking_type = booking.booking_type
def to_dict(self):
return {
@@ -29,7 +30,8 @@ def to_dict(self):
'sport': self.sport.value,
'user_id': self.user_id,
'booking_id': self.booking_id,
- 'materials': self.materials
+ 'materials': self.materials,
+ 'type': self.booking_type.value
}
class DeleteBookingViewModel:
diff --git a/src/modules/delete_court/app/delete_court_controller.py b/src/modules/delete_court/app/delete_court_controller.py
index 7902822..bed8620 100644
--- a/src/modules/delete_court/app/delete_court_controller.py
+++ b/src/modules/delete_court/app/delete_court_controller.py
@@ -1,13 +1,10 @@
-from typing import Any
-from src.shared.domain.entities.court import Court
from .delete_court_usecase import DeleteCourtUsecase
from .delete_court_viewmodel import DeleteCourtViewModel
from src.shared.helpers.errors.controller_errors import MissingParameters, WrongTypeParameter
from src.shared.helpers.errors.domain_errors import EntityError
-from src.shared.helpers.errors.usecase_errors import NoItemsFound
+from src.shared.helpers.errors.usecase_errors import NoItemsFound, ForbiddenAction
from src.shared.helpers.external_interfaces.external_interface import IRequest, IResponse
-from src.shared.helpers.external_interfaces.http_codes import OK, BadRequest, Created, InternalServerError, NotFound
-from src.shared.domain.enums.status_enum import STATUS
+from src.shared.helpers.external_interfaces.http_codes import OK, BadRequest, InternalServerError, NotFound
class DeleteCourtController:
@@ -16,10 +13,24 @@ def __init__(self, usecase: DeleteCourtUsecase):
def __call__(self, request: IRequest) -> IResponse:
try:
- if request.data.get('number') is None:
- raise MissingParameters('number')
- court = self.usecase(number=request.data.get('number'))
+ user = request.data.get("user_from_authorizer")
+ number = request.data.get("number")
+
+ if user is None:
+ raise MissingParameters('user')
+
+ if number is not None:
+ try:
+ number = int(number)
+ except ValueError:
+ raise WrongTypeParameter(fieldName="number",
+ fieldTypeExpected="int",
+ fieldTypeReceived=type(number).__name__)
+ else:
+ raise MissingParameters("number")
+
+ court = self.usecase(number=number, role=user.get("role"))
viewmodel = DeleteCourtViewModel(court)
return OK(viewmodel.to_dict())
@@ -36,5 +47,8 @@ def __call__(self, request: IRequest) -> IResponse:
except EntityError as err:
return BadRequest(body=err.message)
+ except ForbiddenAction as err:
+ return BadRequest(body=err.message)
+
except Exception as err:
return InternalServerError(body=err.args[0])
\ No newline at end of file
diff --git a/src/modules/delete_court/app/delete_court_presenter.py b/src/modules/delete_court/app/delete_court_presenter.py
index bd8d419..c0aafa0 100644
--- a/src/modules/delete_court/app/delete_court_presenter.py
+++ b/src/modules/delete_court/app/delete_court_presenter.py
@@ -1,15 +1,26 @@
from .delete_court_controller import DeleteCourtController
from .delete_court_usecase import DeleteCourtUsecase
-from src.shared.environments import Environments
from src.shared.helpers.external_interfaces.http_lambda_requests import LambdaHttpRequest, LambdaHttpResponse
+from src.shared.environments import Environments
+import json
repo = Environments.get_reservation_repo()()
usecase = DeleteCourtUsecase(repo)
controller = DeleteCourtController(usecase)
+
def lambda_handler(event, context):
+
httpRequest = LambdaHttpRequest(data=event)
+
+ user_info_string = event.get('requestContext', {}).get('authorizer', {}).get('user')
+
+ if user_info_string:
+ httpRequest.data['user_from_authorizer'] = json.loads(user_info_string).get('user')
+ else:
+ httpRequest.data['user_from_authorizer'] = None
+
response = controller(request=httpRequest)
httpResponse = LambdaHttpResponse(status_code=response.status_code, body=response.body, headers=response.headers)
-
- return httpResponse.toDict()
\ No newline at end of file
+
+ return httpResponse.toDict()
diff --git a/src/modules/delete_court/app/delete_court_usecase.py b/src/modules/delete_court/app/delete_court_usecase.py
index e13d719..2bb34e8 100644
--- a/src/modules/delete_court/app/delete_court_usecase.py
+++ b/src/modules/delete_court/app/delete_court_usecase.py
@@ -1,19 +1,20 @@
from src.shared.domain.entities.court import Court
-from src.shared.domain.enums.status_enum import STATUS
-from src.shared.helpers.errors.usecase_errors import DuplicatedItem
from src.shared.helpers.errors.domain_errors import EntityError
-from src.shared.helpers.errors.usecase_errors import NoItemsFound
+from src.shared.helpers.errors.usecase_errors import NoItemsFound, ForbiddenAction
from src.shared.domain.repositories.reservation_repository_interface import IReservationRepository
class DeleteCourtUsecase:
def __init__(self, repo:IReservationRepository):
self.repo = repo
- def __call__(self, number: int):
+ def __call__(self, number: int, role: str):
if not Court.validate_number(number):
raise EntityError('number')
+ if role != "ADMIN":
+ raise ForbiddenAction("user, only admin can delete courts")
+
court = self.repo.delete_court(number=number)
if court is None:
diff --git a/src/modules/generate_report/app/generate_report_aggregator.py b/src/modules/generate_report/app/generate_report_aggregator.py
new file mode 100644
index 0000000..6d1dee8
--- /dev/null
+++ b/src/modules/generate_report/app/generate_report_aggregator.py
@@ -0,0 +1,129 @@
+from src.shared.clients.user_api_client import UserAPIClient
+from src.shared.domain.entities.booking import Booking
+from .generate_report_extractor import GenerateReportExtractor
+from typing import List
+
+
+class GenerateReportAggregator:
+
+ def __init__(self, extractor: GenerateReportExtractor):
+ self.extractor = extractor
+
+ def __call__(self, initial_date, final_date):
+
+ bookings = self.extractor(initial_date, final_date)
+
+ users_statistics = {}
+
+ user_api_client = UserAPIClient()
+
+ for booking in bookings:
+
+ user_name = user_api_client.get_user_name(booking.user_id)
+ key = user_name if user_name is not None else booking.user_id
+
+ if key not in users_statistics:
+
+ users_statistics[key] = {
+ "reservas_feitas": 0,
+ "Tennis": 0,
+ "Football": 0,
+ "Basketball": 0,
+ "Volleyball": 0,
+ "Handball": 0,
+ "Futsal": 0,
+ "Rugby": 0,
+ "Ping Pong": 0,
+ "Beach Tennis": 0,
+ "Natação": 0,
+ "Corrida": 0,
+ "NA": 0,
+ 0: 0,
+ 1: 0,
+ 2: 0,
+ 3: 0,
+ 4: 0,
+ 5: 0,
+ 6: 0,
+ 7: 0,
+ "tempo_em_quadra": 0
+ }
+
+
+ users_statistics[key]["reservas_feitas"] += 1
+ users_statistics[key][booking.sport.value] += 1
+ users_statistics[key][booking.court_number] += 1
+ users_statistics[key]["tempo_em_quadra"] += (booking.end_date - booking.start_date) / (1000 * 60 * 60)
+
+
+ #court statistics logic
+ court_statistics = {}
+
+ for booking in bookings:
+ user_name = user_api_client.get_user_name(booking.user_id)
+ court_key = booking.court_number
+
+ if court_key not in court_statistics:
+ court_statistics[court_key] = {
+ "reservas_feitas": 0,
+ "tempo_de_uso": 0,
+ "Tennis": 0,
+ "Football": 0,
+ "Basketball": 0,
+ "Volleyball": 0,
+ "Handball": 0,
+ "Futsal": 0,
+ "Rugby": 0,
+ "Ping Pong": 0,
+ "Beach Tennis": 0,
+ "NA": 0
+ }
+
+ sport_column = booking.sport.value
+ if sport_column not in court_statistics[court_key]:
+ court_statistics[court_key][sport_column] = 0
+
+ user_column = user_name
+ if user_column not in court_statistics[court_key]:
+ court_statistics[court_key][user_column] = 0
+
+ court_statistics[court_key]["reservas_feitas"] += 1
+ court_statistics[court_key]["tempo_de_uso"] += (booking.end_date - booking.start_date)
+ court_statistics[court_key][sport_column] += 1
+ court_statistics[court_key][user_column] += 1
+
+
+ #sport_statistics logic
+ sport_statistics = {}
+
+ for booking in bookings:
+ sport_key = booking.sport.value
+ user_name = user_api_client.get_user_name(booking.user_id)
+ # Se ainda não existir, inicializa
+ if sport_key not in sport_statistics:
+ sport_statistics[sport_key] = {
+ "Reservas Feitas": 0,
+ "quadra 1": 0,
+ "quadra 2": 0,
+ "quadra 3": 0,
+ "quadra 4": 0,
+ "quadra 5": 0,
+ "quadra 6": 0,
+ "quadra 7": 0,
+ "Tempo Total Praticado": 0,
+ }
+
+ # Atualiza os valores
+ sport_statistics[sport_key]["Reservas Feitas"] += 1
+ sport_statistics[sport_key][f"quadra {booking.court_number}"] += 1
+ sport_statistics[sport_key]["Tempo Total Praticado"] += (booking.end_date - booking.start_date)
+
+ user_column = user_name
+ if user_column not in sport_statistics[sport_key]:
+ sport_statistics[sport_key][user_column] = 0
+
+ sport_statistics[sport_key][user_column] += 1
+
+ #sport_statistics logic
+
+ return users_statistics, court_statistics, sport_statistics
diff --git a/src/modules/generate_report/app/generate_report_extractor.py b/src/modules/generate_report/app/generate_report_extractor.py
new file mode 100644
index 0000000..e0e732f
--- /dev/null
+++ b/src/modules/generate_report/app/generate_report_extractor.py
@@ -0,0 +1,20 @@
+from src.shared.domain.repositories.booking_repository_interface import IBookingRepository
+from src.shared.helpers.errors.usecase_errors import DynamoDBBaseError
+
+
+class GenerateReportExtractor:
+
+ def __init__(self, booking_repository: IBookingRepository):
+ self.booking_repository = booking_repository
+
+ def __call__(self, initial_date, final_date):
+
+ try:
+
+ #TODO Add method to interface
+ bookings = self.booking_repository.get_all_bookings_by_date_range(initial_date, final_date)
+
+ except:
+ raise DynamoDBBaseError("Error extracting bookings from dynamo")
+
+ return bookings
diff --git a/src/modules/generate_report/app/generate_report_presenter.py b/src/modules/generate_report/app/generate_report_presenter.py
index e02c936..06f7eed 100644
--- a/src/modules/generate_report/app/generate_report_presenter.py
+++ b/src/modules/generate_report/app/generate_report_presenter.py
@@ -1,9 +1,58 @@
+import datetime
+import time
+
+from src.shared.environments import Environments
+from src.shared.clients.s3_client import s3_client
+
+from .generate_report_extractor import GenerateReportExtractor
+from .generate_report_aggregator import GenerateReportAggregator
+from .generate_report_transformer import GenerateReportTransformer
+
+repo = Environments.get_envs().get_booking_repo()()
def lambda_handler(event, context):
- """
- Lambda handler function for the generate_report module
- """
- print("IM ALIVE!! LAMBDA TRIGGERED BY EVENTBRIDGE")
- print('event: ', event)
- print('context', context)
\ No newline at end of file
+ #"2025-04-03T15:00:00Z" date format
+
+ current_date = datetime.datetime.now()
+
+ year = current_date.year
+ month = current_date.month
+ year_start_date = datetime.datetime(year, 1, 1)
+
+ start_date = int(time.mktime(year_start_date.timetuple())) * 1000
+ final_date = int(time.mktime(current_date.timetuple())) * 1000
+
+ file_name = f"relatorio_gerado_em_{current_date.day}_{month}_{year}.xlsx"
+ file_path = f"relatorios/"
+
+ extractor = GenerateReportExtractor(booking_repository=repo)
+ aggregator = GenerateReportAggregator(extractor=extractor)
+ transformer = GenerateReportTransformer(aggregator=aggregator)
+ report = transformer(start_date, final_date)
+
+ if report:
+
+ bucket_manager = s3_client()
+
+ try:
+
+ report = report.getvalue()
+
+ response = bucket_manager.upload_file(key=file_path + file_name,
+ file_type=".xlsx",
+ decode_string=report,
+ )
+
+ print("Report generated and uploaded successfully")
+
+ return 1
+
+ except:
+
+ raise Exception("Error uploading file to S3")
+
+
+ else:
+
+ raise Exception("Error generating report")
diff --git a/src/modules/generate_report/app/generate_report_sender.py b/src/modules/generate_report/app/generate_report_sender.py
new file mode 100644
index 0000000..0844a2f
--- /dev/null
+++ b/src/modules/generate_report/app/generate_report_sender.py
@@ -0,0 +1,57 @@
+# import datetime
+# import time
+
+# from src.shared.environments import Environments
+# from src.shared.infra.repositories.util.S3Manager import S3Manager
+
+# from .generate_report_extractor import GenerateReportExtractor
+# from .generate_report_aggregator import GenerateReportAggregator
+# from .generate_report_transformer import GenerateReportTransformer
+
+# repo = Environments.get_envs().get_booking_repo()()
+
+
+# def lambda_handler(event, context):
+# extractor = GenerateReportExtractor(repo)
+# #"2025-04-03T15:00:00Z" date format
+
+# current_date = datetime.datetime.now()
+
+# year = current_date.year
+# month = current_date.month
+# year_start_date = datetime.datetime(year, 1, 1)
+
+# start_date = int(time.mktime(year_start_date.timetuple())) * 1000
+# final_date = int(time.mktime(current_date.timetuple())) * 1000
+
+# file_name = f"relatorio_gerado_em_{current_date.day}_{month}_{year}.xlsx"
+# file_path = f"relatorios/"
+
+# extractor = GenerateReportExtractor(booking_repository=repo)
+# aggregator = GenerateReportAggregator(extractor=extractor)
+# transformer = GenerateReportTransformer(aggregator=aggregator)
+# report = transformer(start_date, final_date)
+
+# if report:
+
+# bucket_manager = S3Manager()
+
+# try:
+
+# response = bucket_manager.upload_file(key=file_path + file_name,
+# file_type=".xlsx",
+# decode_string=report,
+# )
+
+# print("Report generated and uploaded successfully")
+
+# return 1
+
+# except:
+
+# raise Exception("Error uploading file to S3")
+
+
+# else:
+
+# raise Exception("Error generating report")
diff --git a/src/modules/generate_report/app/generate_report_transformer.py b/src/modules/generate_report/app/generate_report_transformer.py
new file mode 100644
index 0000000..3a46ef0
--- /dev/null
+++ b/src/modules/generate_report/app/generate_report_transformer.py
@@ -0,0 +1,33 @@
+from .generate_report_aggregator import GenerateReportAggregator
+import pandas as pd
+import io
+
+class GenerateReportTransformer:
+
+ def __init__(self, aggregator: GenerateReportAggregator):
+ self.aggregator = aggregator
+
+ def __call__(self, initial_date, final_date):
+
+ user_statistics, court_statistics, sports_statistics = self.aggregator(initial_date, final_date)
+
+ df_users = pd.DataFrame.from_dict(user_statistics, orient="index")
+ df_courts = pd.DataFrame.from_dict(court_statistics, orient="index")
+ df_sports = pd.DataFrame.from_dict(sports_statistics, orient="index")
+
+
+ print(f"DF Users shape: {df_users.shape}")
+ print(f"DF Courts shape: {df_courts.shape}")
+ print(f"DF Sports shape: {df_sports.shape}")
+
+ output = io.BytesIO()
+
+ with pd.ExcelWriter(output, engine="xlsxwriter") as writer:
+ df_users.to_excel(writer, sheet_name="Usuários")
+ df_courts.to_excel(writer, sheet_name="Quadras")
+ df_sports.to_excel(writer, sheet_name="Esportes")
+ writer.close()
+ output.seek(0)
+
+ return output
+
diff --git a/src/functions/__init__.py b/src/modules/get_all_admin_bookings/__init__.py
similarity index 100%
rename from src/functions/__init__.py
rename to src/modules/get_all_admin_bookings/__init__.py
diff --git a/src/functions/graph_authorizer/__init__.py b/src/modules/get_all_admin_bookings/app/__init__.py
similarity index 100%
rename from src/functions/graph_authorizer/__init__.py
rename to src/modules/get_all_admin_bookings/app/__init__.py
diff --git a/src/modules/get_all_admin_bookings/app/get_all_admin_bookings_controller.py b/src/modules/get_all_admin_bookings/app/get_all_admin_bookings_controller.py
new file mode 100644
index 0000000..9692885
--- /dev/null
+++ b/src/modules/get_all_admin_bookings/app/get_all_admin_bookings_controller.py
@@ -0,0 +1,37 @@
+from .get_all_admin_bookings_usecase import GetAllAdminBookingsUsecase
+from .get_all_admin_bookings_viewmodel import GetAllAdminBookingsViewmodel
+from src.shared.helpers.external_interfaces.external_interface import IRequest, IResponse
+from src.shared.helpers.external_interfaces.http_codes import *
+from src.shared.helpers.errors.domain_errors import *
+from src.shared.helpers.errors.usecase_errors import *
+
+
+
+class GetAllAdminBookingsController:
+
+ def __init__(self, usecase: GetAllAdminBookingsUsecase):
+
+ self.usecase = usecase
+
+ def __call__(self, request: IRequest) -> IResponse:
+
+ try:
+
+ response = self.usecase()
+
+ return OK(GetAllAdminBookingsViewmodel(bookings=response).to_dict())
+
+ except EntityError as err:
+ return BadRequest(body=err.message)
+
+ except NoItemsFound as err:
+ return BadRequest(body=err.message)
+
+ except NoAdminFound as err:
+ return BadRequest(body=err.message)
+
+ except NoAdminBookingsFound as err:
+ return BadRequest(body=err.message)
+
+ except Exception as err:
+ return InternalServerError(body=err.args[0])
\ No newline at end of file
diff --git a/src/modules/get_all_admin_bookings/app/get_all_admin_bookings_presenter.py b/src/modules/get_all_admin_bookings/app/get_all_admin_bookings_presenter.py
new file mode 100644
index 0000000..4adf9c4
--- /dev/null
+++ b/src/modules/get_all_admin_bookings/app/get_all_admin_bookings_presenter.py
@@ -0,0 +1,25 @@
+import json
+from .get_all_admin_bookings_controller import GetAllAdminBookingsController
+from .get_all_admin_bookings_usecase import GetAllAdminBookingsUsecase
+from src.shared.environments import Environments
+from src.shared.helpers.external_interfaces.http_lambda_requests import LambdaHttpRequest, LambdaHttpResponse
+
+
+repo = Environments.get_booking_repo()()
+usecase = GetAllAdminBookingsUsecase(repo)
+controller = GetAllAdminBookingsController(usecase)
+
+def lambda_handler(event, context):
+ httpRequest = LambdaHttpRequest(data=event)
+
+ user_info_string = event.get('requestContext', {}).get('authorizer', {}).get('user')
+
+ if user_info_string:
+ httpRequest.data['user_from_authorizer'] = json.loads(user_info_string).get('user')
+ else:
+ httpRequest.data['user_from_authorizer'] = None
+
+ response = controller(request=httpRequest)
+ httpResponse = LambdaHttpResponse(status_code=response.status_code, body=response.body, headers=response.headers)
+
+ return httpResponse.toDict()
\ No newline at end of file
diff --git a/src/modules/get_all_admin_bookings/app/get_all_admin_bookings_usecase.py b/src/modules/get_all_admin_bookings/app/get_all_admin_bookings_usecase.py
new file mode 100644
index 0000000..d76f450
--- /dev/null
+++ b/src/modules/get_all_admin_bookings/app/get_all_admin_bookings_usecase.py
@@ -0,0 +1,40 @@
+from src.shared.domain.repositories.booking_repository_interface import IBookingRepository
+from src.shared.clients.user_api_client import UserAPIClient
+from src.shared.helpers.errors.usecase_errors import *
+
+class GetAllAdminBookingsUsecase:
+
+ def __init__(self, repo: IBookingRepository):
+
+ self.repo = repo
+ self.user_client = UserAPIClient()
+
+ def __call__(self):
+
+ all_users = self.user_client.all_users
+ admin_user = None
+
+ for item in all_users:
+
+ if item.get("role") == "ADMIN" and item.get("email") == "dev@maua.br":
+
+ admin_user = item
+
+ if admin_user == None:
+
+ raise NoAdminFound()
+
+ all_bookings = self.repo.get_all_bookings()
+ admin_bookings = []
+
+ for item in all_bookings:
+
+ if item.user_id == admin_user.get("user_id", None):
+
+ admin_bookings.append(item)
+
+ if not admin_bookings:
+
+ raise NoAdminBookingsFound()
+
+ return admin_bookings
\ No newline at end of file
diff --git a/src/modules/get_all_admin_bookings/app/get_all_admin_bookings_viewmodel.py b/src/modules/get_all_admin_bookings/app/get_all_admin_bookings_viewmodel.py
new file mode 100644
index 0000000..b16af11
--- /dev/null
+++ b/src/modules/get_all_admin_bookings/app/get_all_admin_bookings_viewmodel.py
@@ -0,0 +1,21 @@
+from typing import List
+from src.shared.domain.entities.booking import Booking
+
+
+class GetAllAdminBookingsViewmodel:
+
+ bookings: List[Booking]
+
+ def __init__(self, bookings: List[Booking]):
+
+ self.bookings = bookings
+
+ def to_dict(self):
+
+ return {
+ "bookings": [
+ {k: v for k, v in booking.to_dict().items() if k != 'user_id' or k != 'booking_id'}
+ for booking in self.bookings
+ ],
+ "message": "Admin bookings retreived"
+ }
\ No newline at end of file
diff --git a/src/modules/get_all_bookings/app/get_all_bookings_controller.py b/src/modules/get_all_bookings/app/get_all_bookings_controller.py
index df4369a..3caa8bc 100644
--- a/src/modules/get_all_bookings/app/get_all_bookings_controller.py
+++ b/src/modules/get_all_bookings/app/get_all_bookings_controller.py
@@ -1,5 +1,7 @@
+from typing import Any
from .get_all_bookings_usecase import GetAllBookingsUsecase
-from .get_all_bookings_viewmodel import GetAllBookingViewModel
+from .get_all_bookings_viewmodel import GetAllBookingsViewModel
+from src.shared.helpers.errors.controller_errors import MissingParameters, WrongTypeParameter
from src.shared.helpers.errors.domain_errors import EntityError
from src.shared.helpers.external_interfaces.external_interface import IRequest
from src.shared.helpers.external_interfaces.http_codes import BadRequest, OK, InternalServerError
@@ -13,7 +15,7 @@ def __init__(self, usecase: GetAllBookingsUsecase):
def __call__(self, request: IRequest):
try:
bookings = self.usecase()
- viewmodel = GetAllBookingViewModel(bookings).to_dict()
+ viewmodel = GetAllBookingsViewModel(bookings).to_dict()
return OK(viewmodel)
except EntityError as err:
return BadRequest(body=err.message)
diff --git a/src/modules/get_all_bookings/app/get_all_bookings_usecase.py b/src/modules/get_all_bookings/app/get_all_bookings_usecase.py
index 70acd06..fe4533e 100644
--- a/src/modules/get_all_bookings/app/get_all_bookings_usecase.py
+++ b/src/modules/get_all_bookings/app/get_all_bookings_usecase.py
@@ -1,4 +1,6 @@
+from typing import Any
from src.shared.domain.repositories.booking_repository_interface import IBookingRepository
+from src.shared.domain.entities.booking import Booking
class GetAllBookingsUsecase:
def __init__(self, repo: IBookingRepository):
diff --git a/src/modules/get_all_bookings/app/get_all_bookings_viewmodel.py b/src/modules/get_all_bookings/app/get_all_bookings_viewmodel.py
index b693175..ee8d77f 100644
--- a/src/modules/get_all_bookings/app/get_all_bookings_viewmodel.py
+++ b/src/modules/get_all_bookings/app/get_all_bookings_viewmodel.py
@@ -1,5 +1,6 @@
from src.shared.domain.entities.booking import Booking
from src.shared.domain.enums.sport import SPORT
+from src.shared.domain.enums.type import BOOKING_TYPE
from typing import List
class BookingViewModel:
@@ -7,18 +8,18 @@ class BookingViewModel:
end_date: int
court_number: int
sport: SPORT
- user_id: str
booking_id: str
materials: List[str]
+ booking_type: BOOKING_TYPE
def __init__(self, booking: Booking):
self.start_date = booking.start_date
self.end_date = booking.end_date
self.court_number = booking.court_number
self.sport = booking.sport
- self.user_id = booking.user_id
self.booking_id = booking.booking_id
self.materials = booking.materials
+ self.booking_type = booking.booking_type
def to_dict(self):
return {
@@ -26,9 +27,9 @@ def to_dict(self):
'end_date': self.end_date,
'court_number': self.court_number,
'sport': self.sport.value,
- 'user_id': self.user_id,
'booking_id': self.booking_id,
- 'materials': self.materials
+ 'materials': self.materials,
+ "type": self.booking_type.value
}
class GetBookingViewModel:
booking: Booking
@@ -41,7 +42,7 @@ def to_dict(self):
'booking' : self.booking_viewmodel.to_dict()
}
-class GetAllBookingViewModel:
+class GetAllBookingsViewModel:
bookings: List[GetBookingViewModel]
def __init__(self, bookings: list):
diff --git a/src/modules/get_all_bookings_grouped_by_role/__init__.py b/src/modules/get_all_bookings_grouped_by_role/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/modules/get_all_bookings_grouped_by_role/app/get_all_bookings_grouped_by_role_controller.py b/src/modules/get_all_bookings_grouped_by_role/app/get_all_bookings_grouped_by_role_controller.py
new file mode 100644
index 0000000..8d04e22
--- /dev/null
+++ b/src/modules/get_all_bookings_grouped_by_role/app/get_all_bookings_grouped_by_role_controller.py
@@ -0,0 +1,25 @@
+from .get_all_bookings_grouped_by_role_usecase import GetAllBookingsGroupedByRoleUsecase
+from .get_all_bookings_grouped_by_role_viewmodel import GetAllBookingsGroupedByRoleViewmodel
+from src.shared.helpers.errors.usecase_errors import NoItemsFound
+from src.shared.helpers.external_interfaces.external_interface import IRequest, IResponse
+from src.shared.helpers.external_interfaces.http_codes import OK, InternalServerError, NotFound
+
+
+class GetAllBookingsGroupedByRoleController:
+
+ def __init__(self, usecase: GetAllBookingsGroupedByRoleUsecase):
+
+ self.usecase = usecase
+
+ def __call__(self, request: IRequest) -> IResponse:
+
+ try:
+
+ response = self.usecase()
+
+ return OK(GetAllBookingsGroupedByRoleViewmodel(response).to_dict())
+
+ except NoItemsFound as err:
+ return NotFound(body=err.message)
+ except Exception as err:
+ return InternalServerError(body=err.args[0])
\ No newline at end of file
diff --git a/src/modules/get_all_bookings_grouped_by_role/app/get_all_bookings_grouped_by_role_presenter.py b/src/modules/get_all_bookings_grouped_by_role/app/get_all_bookings_grouped_by_role_presenter.py
new file mode 100644
index 0000000..7d0fa41
--- /dev/null
+++ b/src/modules/get_all_bookings_grouped_by_role/app/get_all_bookings_grouped_by_role_presenter.py
@@ -0,0 +1,25 @@
+import json
+from .get_all_bookings_grouped_by_role_controller import GetAllBookingsGroupedByRoleController
+from .get_all_bookings_grouped_by_role_usecase import GetAllBookingsGroupedByRoleUsecase
+from src.shared.environments import Environments
+from src.shared.helpers.external_interfaces.http_lambda_requests import LambdaHttpRequest, LambdaHttpResponse
+
+
+repo = Environments.get_booking_repo()()
+usecase = GetAllBookingsGroupedByRoleUsecase(repo)
+controller = GetAllBookingsGroupedByRoleController(usecase)
+
+def lambda_handler(event, context):
+ httpRequest = LambdaHttpRequest(data=event)
+
+ user_info_string = event.get('requestContext', {}).get('authorizer', {}).get('user')
+
+ if user_info_string:
+ httpRequest.data['user_from_authorizer'] = json.loads(user_info_string).get('user')
+ else:
+ httpRequest.data['user_from_authorizer'] = None
+
+ response = controller(request=httpRequest)
+ httpResponse = LambdaHttpResponse(status_code=response.status_code, body=response.body, headers=response.headers)
+
+ return httpResponse.toDict()
\ No newline at end of file
diff --git a/src/modules/get_all_bookings_grouped_by_role/app/get_all_bookings_grouped_by_role_usecase.py b/src/modules/get_all_bookings_grouped_by_role/app/get_all_bookings_grouped_by_role_usecase.py
new file mode 100644
index 0000000..e9f5eab
--- /dev/null
+++ b/src/modules/get_all_bookings_grouped_by_role/app/get_all_bookings_grouped_by_role_usecase.py
@@ -0,0 +1,45 @@
+from src.shared.clients.user_api_client import UserAPIClient
+from src.shared.domain.repositories.booking_repository_interface import IBookingRepository
+from src.shared.helpers.errors.usecase_errors import NoItemsFound
+
+
+class GetAllBookingsGroupedByRoleUsecase:
+
+ def __init__(self, repo: IBookingRepository):
+ self.repo = repo
+ self.user_client = UserAPIClient()
+
+ def __call__(self):
+ all_users = self.user_client.all_users
+
+ all_bookings = self.repo.get_all_bookings()
+
+ if all_bookings is None:
+ raise NoItemsFound('all_bookings')
+
+ all_bookings_by_role = {
+ 'UNKNOWN': []
+ }
+
+ for user in all_users:
+
+ user_role = user.get('role', None)
+ user_id = user.get('user_id', None)
+
+ if user_role is not None:
+
+ if user_role not in all_bookings_by_role:
+ all_bookings_by_role[user_role] = []
+
+ user_bookings = [
+ {k: v for k, v in booking.to_dict().items() if k != 'user_id'}
+ for booking in all_bookings
+ if booking.user_id == user_id
+ ]
+
+ all_bookings_by_role[user_role if user_role is not None else 'UNKNOWN'].extend(user_bookings)
+
+ return all_bookings_by_role
+
+
+
\ No newline at end of file
diff --git a/src/modules/get_all_bookings_grouped_by_role/app/get_all_bookings_grouped_by_role_viewmodel.py b/src/modules/get_all_bookings_grouped_by_role/app/get_all_bookings_grouped_by_role_viewmodel.py
new file mode 100644
index 0000000..521480a
--- /dev/null
+++ b/src/modules/get_all_bookings_grouped_by_role/app/get_all_bookings_grouped_by_role_viewmodel.py
@@ -0,0 +1,16 @@
+from typing import Dict, List
+from src.shared.domain.entities.booking import Booking
+
+
+class GetAllBookingsGroupedByRoleViewmodel:
+
+ def __init__(self, all_bookings_by_role: Dict[str, List[Booking]]):
+
+ self.all_bookings_by_role = all_bookings_by_role
+
+ def to_dict(self):
+
+ return {
+ 'bookings': self.all_bookings_by_role,
+ 'message': "The bookings grouped by roles were retrieved."
+ }
\ No newline at end of file
diff --git a/src/modules/get_all_courts/app/get_all_courts_controller.py b/src/modules/get_all_courts/app/get_all_courts_controller.py
index ef80113..e7d5ba9 100644
--- a/src/modules/get_all_courts/app/get_all_courts_controller.py
+++ b/src/modules/get_all_courts/app/get_all_courts_controller.py
@@ -1,7 +1,5 @@
-from typing import Any
from .get_all_courts_usecase import GetAllCourtsUsecase
from .get_all_courts_viewmodel import GetAllCourtsViewModel
-from src.shared.helpers.errors.controller_errors import MissingParameters, WrongTypeParameter
from src.shared.helpers.errors.domain_errors import EntityError
from src.shared.helpers.external_interfaces.external_interface import IRequest
from src.shared.helpers.external_interfaces.http_codes import BadRequest, OK, InternalServerError
@@ -17,7 +15,6 @@ def __call__(self, request: IRequest):
courts = self.usecase()
viewmodel = GetAllCourtsViewModel(courts).to_dict()
return OK(viewmodel)
-
except EntityError as err:
return BadRequest(body=err.message)
diff --git a/src/modules/get_booking/app/get_booking_controller.py b/src/modules/get_booking/app/get_booking_controller.py
index 2939634..3d9d0a2 100644
--- a/src/modules/get_booking/app/get_booking_controller.py
+++ b/src/modules/get_booking/app/get_booking_controller.py
@@ -1,6 +1,6 @@
from .get_booking_viewmodel import GetBookingViewmodel
from .get_booking_usecase import GetBookingUseCase
-from src.shared.helpers.errors.controller_errors import MissingParameters, WrongTypeParameter, EmptyQueryParameters
+from src.shared.helpers.errors.controller_errors import MissingParameters, WrongTypeParameter
from src.shared.helpers.errors.domain_errors import EntityError
from src.shared.helpers.errors.usecase_errors import NoItemsFound
from src.shared.helpers.external_interfaces.external_interface import IRequest
@@ -13,26 +13,25 @@ def __init__(self, usecase: GetBookingUseCase):
def __call__(self, request: IRequest):
try:
-
- booking_id = request.data.get('booking_id', None)
+ if request.data.get('booking_id') is None:
+ raise MissingParameters('booking_id')
+
+ booking_id = request.data.get('booking_id')
if booking_id is not None:
- if not isinstance(booking_id, str):
- raise WrongTypeParameter('booking_id',
- fieldTypeReceived=type(booking_id).__name__,
- fieldTypeExpected='str')
- else:
- raise MissingParameters('booking_id')
+ if type(booking_id) is not str:
+ raise WrongTypeParameter(
+ 'booking_id',
+ 'str',
+ (type(booking_id)).__name__
+ )
booking = self.usecase(
- booking_id=booking_id
+ booking_id = request.data.get('booking_id')
)
booking_viewmodel = GetBookingViewmodel(booking)
return OK(booking_viewmodel.to_dict())
- except EmptyQueryParameters as err:
- return BadRequest(body=err.message)
-
except MissingParameters as err:
return BadRequest(body=err.message)
diff --git a/src/modules/get_booking/app/get_booking_usecase.py b/src/modules/get_booking/app/get_booking_usecase.py
index c31b44b..ecc32e8 100644
--- a/src/modules/get_booking/app/get_booking_usecase.py
+++ b/src/modules/get_booking/app/get_booking_usecase.py
@@ -1,9 +1,7 @@
-from typing import Optional
-
from src.shared.domain.entities.booking import Booking
from src.shared.domain.repositories.booking_repository_interface import IBookingRepository
from src.shared.helpers.errors.domain_errors import EntityError
-from src.shared.helpers.errors.usecase_errors import NoItemsFound, DependantFilter
+from src.shared.helpers.errors.usecase_errors import NoItemsFound
class GetBookingUseCase:
repo: IBookingRepository
@@ -11,15 +9,11 @@ class GetBookingUseCase:
def __init__(self, repo: IBookingRepository):
self.repo = repo
- def __call__(self,
- booking_id: str):
-
- if not Booking.validate_booking_id(booking_id):
+ def __call__(self, booking_id: str):
+ if not Booking.validate_booking_id(booking_id=booking_id):
raise EntityError('booking_id')
-
- booking = self.repo.get_booking(
- booking_id=booking_id
- )
+
+ booking = self.repo.get_booking(booking_id=booking_id)
if booking is None:
raise NoItemsFound('booking_id')
diff --git a/src/modules/get_booking/app/get_booking_viewmodel.py b/src/modules/get_booking/app/get_booking_viewmodel.py
index 484e7d5..a046cab 100644
--- a/src/modules/get_booking/app/get_booking_viewmodel.py
+++ b/src/modules/get_booking/app/get_booking_viewmodel.py
@@ -6,7 +6,6 @@ class BookingViewmodel:
end_date: int
court_number: int
sport: SPORT
- user_id: str
booking_id: str
materials: list
@@ -15,9 +14,9 @@ def __init__(self, booking: Booking):
self.end_date = booking.end_date
self.court_number = booking.court_number
self.sport = booking.sport
- self.user_id = booking.user_id
self.booking_id = booking.booking_id
self.materials = booking.materials
+ self.booking_type = booking.booking_type
def to_dict(self):
return {
@@ -25,9 +24,9 @@ def to_dict(self):
'end_date': self.end_date,
'court_number': self.court_number,
'sport': self.sport.value,
- 'user_id': self.user_id,
'booking_id': self.booking_id,
- 'materials': self.materials
+ 'materials': self.materials,
+ "type": self.booking_type.value
}
class GetBookingViewmodel:
diff --git a/src/modules/get_bookings/app/get_bookings_controller.py b/src/modules/get_bookings/app/get_bookings_controller.py
index 5715e8d..10e7781 100644
--- a/src/modules/get_bookings/app/get_bookings_controller.py
+++ b/src/modules/get_bookings/app/get_bookings_controller.py
@@ -23,6 +23,7 @@ def __call__(self, request: IRequest):
court_number = request.data.get('court_number', None)
end_date = request.data.get('end_date', None)
start_date = request.data.get('start_date', None)
+ booking_type = request.data.get('type', None)
booking_id = booking_id if booking_id != "" else None
user_id = user_id if user_id != "" else None
@@ -30,10 +31,11 @@ def __call__(self, request: IRequest):
court_number = court_number if court_number != "" else None
end_date = end_date if end_date != "" else None
start_date = start_date if start_date != "" else None
+ booking_type = booking_type if booking_type != "" else None
- if not booking_id and not user_id and not sport and not court_number and not end_date and not start_date:
+ if not booking_id and not user_id and not sport and not court_number and not end_date and not start_date and not booking_type:
raise EmptyQueryParameters(
- 'At least one of the filters must be provided: booking_id, user_id, sport, court_number, end_date, start_date')
+ 'At least one of the filters must be provided: booking_id, user_id, sport, court_number, end_date, start_date, type')
if court_number is not None:
try:
@@ -65,7 +67,8 @@ def __call__(self, request: IRequest):
sport=sport,
court_number=court_number,
end_date=end_date,
- start_date=start_date
+ start_date=start_date,
+ booking_type=booking_type
)
booking_viewmodel = GetBookingsViewmodel(booking)
return OK(booking_viewmodel.to_dict())
diff --git a/src/modules/get_bookings/app/get_bookings_usecase.py b/src/modules/get_bookings/app/get_bookings_usecase.py
index 614b675..1290fda 100644
--- a/src/modules/get_bookings/app/get_bookings_usecase.py
+++ b/src/modules/get_bookings/app/get_bookings_usecase.py
@@ -2,6 +2,7 @@
from src.shared.domain.entities.booking import Booking
from src.shared.domain.enums.sport import SPORT
+from src.shared.domain.enums.type import BOOKING_TYPE
from src.shared.domain.repositories.booking_repository_interface import IBookingRepository
from src.shared.helpers.errors.domain_errors import EntityError
from src.shared.helpers.errors.usecase_errors import NoItemsFound, DependantFilter
@@ -18,7 +19,8 @@ def __call__(self,
sport: Optional[str] = None,
court_number: Optional[int] = None,
end_date: Optional[int] = None,
- start_date: Optional[int] = None):
+ start_date: Optional[int] = None,
+ booking_type: Optional[str] = None):
if booking_id:
if not Booking.validate_booking_id(booking_id):
@@ -39,13 +41,18 @@ def __call__(self,
if (start_date and not end_date) or (end_date and not start_date):
raise DependantFilter('start_date and end_date')
+ if booking_type:
+ if not Booking.validate_booking_type(BOOKING_TYPE(booking_type)):
+ raise EntityError('type')
+
bookings = self.repo.get_bookings(
booking_id=booking_id if booking_id else None,
user_id=user_id if user_id else None,
sport=SPORT(sport) if sport else None,
court_number=court_number if court_number else None,
end_date=end_date if end_date else None,
- start_date=start_date if start_date else None)
+ start_date=start_date if start_date else None,
+ booking_type=BOOKING_TYPE(booking_type) if booking_type else None)
if bookings is None or bookings == []:
raise NoItemsFound('booking filters passed')
diff --git a/src/modules/get_bookings/app/get_bookings_viewmodel.py b/src/modules/get_bookings/app/get_bookings_viewmodel.py
index 94cdb07..fefc788 100644
--- a/src/modules/get_bookings/app/get_bookings_viewmodel.py
+++ b/src/modules/get_bookings/app/get_bookings_viewmodel.py
@@ -10,7 +10,9 @@ def __init__(self, bookings: list):
def to_dict(self):
return {
- 'bookings': [booking.to_dict() for booking in self.bookings],
+ 'bookings': [
+ {k: v for k, v in booking.to_dict().items() if k != 'user_id'}
+ for booking in self.bookings
+ ],
'message': 'the bookings were retrieved'
}
-
diff --git a/src/modules/get_court/app/get_court_controller.py b/src/modules/get_court/app/get_court_controller.py
index 35427bd..ec8d652 100644
--- a/src/modules/get_court/app/get_court_controller.py
+++ b/src/modules/get_court/app/get_court_controller.py
@@ -15,21 +15,20 @@ def __call__(self, request: IRequest):
try:
if request.data.get('number') is None:
raise MissingParameters('number')
-
+
number = request.data.get('number')
if number is not None:
-
try:
number = int(number)
-
except ValueError:
raise WrongTypeParameter('number', 'int', type(number).__name__)
- court = self.usecase(
+
+ court = self.usecase(
number=number
- )
- court_viewmodel = GetCourtViewmodel(court=court)
+ )
+ court_viewmodel = GetCourtViewmodel(court= court)
return OK(court_viewmodel.to_dict())
@@ -48,3 +47,9 @@ def __call__(self, request: IRequest):
except Exception as err:
return InternalServerError(body=err.args[0])
+
+
+
+
+
+
diff --git a/src/modules/update_booking/app/update_booking_controller.py b/src/modules/update_booking/app/update_booking_controller.py
index ecdd232..62e07a4 100644
--- a/src/modules/update_booking/app/update_booking_controller.py
+++ b/src/modules/update_booking/app/update_booking_controller.py
@@ -1,11 +1,12 @@
+from src.shared.domain.enums.type import BOOKING_TYPE
from .update_booking_usecase import UpdateBookingUsecase
from .update_booking_viewmodel import UpdateBookingViewmodel
from src.shared.domain.enums.sport import SPORT
from src.shared.helpers.errors.controller_errors import MissingParameters, WrongTypeParameter
from src.shared.helpers.errors.domain_errors import EntityError
from src.shared.helpers.external_interfaces.external_interface import IRequest, IResponse
-from src.shared.helpers.external_interfaces.http_codes import OK, BadRequest, InternalServerError, NotFound
-from src.shared.helpers.errors.usecase_errors import NoItemsFound
+from src.shared.helpers.external_interfaces.http_codes import OK, BadRequest, Forbidden, InternalServerError, NotFound
+from src.shared.helpers.errors.usecase_errors import ForbiddenAction, NoItemsFound
class UpdateBookingController:
def __init__(self, update_booking_use_case: UpdateBookingUsecase):
@@ -16,14 +17,18 @@ def __call__(self, request: IRequest) -> IResponse:
if request.data.get('booking_id') is None:
raise MissingParameters('booking_id')
+ if request.data.get('user_from_authorizer') is None:
+ raise MissingParameters('user authorizer')
+
booking_id = request.data.get('booking_id')
start_date = request.data.get('start_date')
end_date = request.data.get('end_date')
court_number = request.data.get('court_number')
sport_value = request.data.get('sport')
materials = request.data.get('materials')
-
-
+ booking_type = request.data.get('type')
+ user = request.data.get('user_from_authorizer')
+
if not isinstance(booking_id, str):
raise WrongTypeParameter('booking_id', 'str', type(booking_id).__name__)
@@ -45,18 +50,30 @@ def __call__(self, request: IRequest) -> IResponse:
raise EntityError('sport')
sport = SPORT(sport_value)
+
+ if booking_type is not None:
+ if not isinstance(booking_type, str):
+ raise WrongTypeParameter('type', 'str', type(booking_type).__name__)
+ if booking_type not in [type.value for type in BOOKING_TYPE]:
+ raise EntityError('type')
+
+ booking_type = BOOKING_TYPE(booking_type)
+
if materials is not None and not isinstance(materials, list):
raise WrongTypeParameter('materials', 'list', type(materials).__name__)
+
booking = self.UpdateBookingUsecase(
booking_id=booking_id,
+ user=user,
start_date=start_date,
end_date=end_date,
court_number=court_number,
sport=sport,
- materials=materials
+ materials=materials,
+ booking_type=booking_type
)
viewmodel = UpdateBookingViewmodel(booking=booking)
@@ -75,5 +92,8 @@ def __call__(self, request: IRequest) -> IResponse:
except NoItemsFound as err:
return NotFound(body=f"Booking not found: {err.message}")
+ except ForbiddenAction as err:
+ return Forbidden(body=err.message)
+
except Exception as err:
return InternalServerError(body=err.args[0])
\ No newline at end of file
diff --git a/src/modules/update_booking/app/update_booking_presenter.py b/src/modules/update_booking/app/update_booking_presenter.py
index 19b0404..17fd9d3 100644
--- a/src/modules/update_booking/app/update_booking_presenter.py
+++ b/src/modules/update_booking/app/update_booking_presenter.py
@@ -1,3 +1,4 @@
+import json
from .update_booking_controller import UpdateBookingController
from .update_booking_usecase import UpdateBookingUsecase
from src.shared.environments import Environments
@@ -10,6 +11,14 @@
def lambda_handler(event, context):
httpRequest = LambdaHttpRequest(data=event)
+
+ user_info_string = event.get('requestContext', {}).get('authorizer', {}).get('user')
+
+ if user_info_string:
+ httpRequest.data['user_from_authorizer'] = json.loads(user_info_string).get('user')
+ else:
+ httpRequest.data['user_from_authorizer'] = None
+
response = controller(request=httpRequest)
httpResponse = LambdaHttpResponse(status_code=response.status_code, body=response.body, headers=response.headers)
diff --git a/src/modules/update_booking/app/update_booking_usecase.py b/src/modules/update_booking/app/update_booking_usecase.py
index 5c3e7c4..1a5cfda 100644
--- a/src/modules/update_booking/app/update_booking_usecase.py
+++ b/src/modules/update_booking/app/update_booking_usecase.py
@@ -1,9 +1,10 @@
-from typing import List, Optional
+from typing import List
from src.shared.domain.entities.booking import Booking
from src.shared.domain.enums.sport import SPORT
+from src.shared.domain.enums.type import BOOKING_TYPE
from src.shared.domain.repositories.booking_repository_interface import IBookingRepository
from src.shared.helpers.errors.domain_errors import EntityError, EntityParameterOrderDatesError
-from src.shared.helpers.errors.usecase_errors import NoItemsFound
+from src.shared.helpers.errors.usecase_errors import ForbiddenAction, NoItemsFound, InvalidSchedule
class UpdateBookingUsecase:
def __init__(self, booking_repo: IBookingRepository):
@@ -11,12 +12,17 @@ def __init__(self, booking_repo: IBookingRepository):
def __call__(self,
booking_id: str,
+ user: dict,
start_date: int = None,
end_date: int = None,
court_number: int = None,
sport: SPORT = None,
materials: List[str] = None,
- user_id: str = None):
+ new_user_id: str = None,
+ booking_type: BOOKING_TYPE = None):
+
+ user_id = user.get('user_id')
+ user_role = user.get('role')
if Booking.validate_booking_id(booking_id) is False:
raise EntityError('booking_id')
@@ -25,13 +31,18 @@ def __call__(self,
if existing_booking is None:
raise NoItemsFound('booking')
+ if user_role != 'ADMIN':
+
+ booking_user_id = existing_booking.user_id
+ if booking_user_id != user_id:
+ raise ForbiddenAction('user id')
start_date = start_date if start_date is not None else existing_booking.start_date
end_date = end_date if end_date is not None else existing_booking.end_date
court_number = court_number if court_number is not None else existing_booking.court_number
sport = sport if sport is not None else existing_booking.sport
materials = materials if materials is not None else existing_booking.materials
-
+ booking_type = booking_type if booking_type is not None else existing_booking.booking_type
if Booking.validate_dates(start_date, end_date) is False:
raise EntityError("date")
@@ -47,6 +58,24 @@ def __call__(self,
if Booking.validate_materials(materials) is False:
raise EntityError("materials")
+
+ if Booking.validate_booking_type(booking_type) is False:
+ raise EntityError("type")
+
+ all_bookings = self.booking_repo.get_all_bookings()
+
+ for booking in all_bookings:
+ if (
+ (booking.booking_id != booking_id)
+ and (
+ (
+ booking.start_date < end_date + (15 * 60 * 1000) #15 minutes in mseconds
+ and booking.end_date > start_date - (15 * 60 * 1000) #15 minutes in mseconds
+ and booking.court_number == court_number
+ )
+ )
+ ):
+ raise InvalidSchedule()
booking = self.booking_repo.update_booking(
booking_id=booking_id,
@@ -54,7 +83,8 @@ def __call__(self,
end_date=end_date,
court_number=court_number,
sport=sport,
- materials=materials
+ materials=materials,
+ booking_type=booking_type
)
if booking.user_id != existing_booking.user_id:
diff --git a/src/modules/update_booking/app/update_booking_viewmodel.py b/src/modules/update_booking/app/update_booking_viewmodel.py
index e86874a..137a88c 100644
--- a/src/modules/update_booking/app/update_booking_viewmodel.py
+++ b/src/modules/update_booking/app/update_booking_viewmodel.py
@@ -4,13 +4,6 @@
class BookingViewmodel:
- start_date: int
- end_date: int
- court_number: int
- sport: SPORT
- user_id: str
- booking_id: str
- materials: List[str]
def __init__(self, booking: Booking):
self.booking = booking
@@ -23,7 +16,8 @@ def to_dict(self) -> Booking:
'sport': self.booking.sport.value,
'user_id': self.booking.user_id,
'booking_id': self.booking.booking_id,
- 'materials': self.booking.materials
+ 'materials': self.booking.materials,
+ 'type': self.booking.booking_type.value
}
class UpdateBookingViewmodel:
diff --git a/src/modules/update_court/app/update_court_controller.py b/src/modules/update_court/app/update_court_controller.py
index e6b8fb7..1a50614 100644
--- a/src/modules/update_court/app/update_court_controller.py
+++ b/src/modules/update_court/app/update_court_controller.py
@@ -2,7 +2,7 @@
from .update_court_usecase import UpdateCourtUsecase
from .update_court_viewmodel import UpdateCourtViewmodel
from src.shared.helpers.errors.controller_errors import MissingParameters, WrongTypeParameter
-from src.shared.helpers.errors.usecase_errors import NoItemsFound
+from src.shared.helpers.errors.usecase_errors import NoItemsFound, ForbiddenAction
from src.shared.helpers.errors.domain_errors import EntityError
from src.shared.helpers.external_interfaces.external_interface import IRequest
from src.shared.helpers.external_interfaces.http_codes import BadRequest, OK, InternalServerError, NotFound
@@ -35,11 +35,14 @@ def __call__(self, request: IRequest):
if type(photo_str) is not str:
raise WrongTypeParameter(fieldName='photo', fieldTypeExpected=str,
fieldTypeReceived=type(request.data.get('photo')))
+
+ user = request.data.get("user_from_authorizer")
court = self.usecase(
number=request.data.get('number'),
status=STATUS[status_str] if status_str is not None else None,
- photo=photo_str
+ photo=photo_str,
+ role=user.get("role")
)
viewmodel = UpdateCourtViewmodel(court=court)
@@ -57,6 +60,9 @@ def __call__(self, request: IRequest):
except EntityError as err:
return BadRequest(body=err.message)
+
+ except ForbiddenAction as err:
+ return BadRequest(body=err.message)
except Exception as err:
return InternalServerError(body=err.args[0])
\ No newline at end of file
diff --git a/src/modules/update_court/app/update_court_presenter.py b/src/modules/update_court/app/update_court_presenter.py
index b0dfe9d..38a4fae 100644
--- a/src/modules/update_court/app/update_court_presenter.py
+++ b/src/modules/update_court/app/update_court_presenter.py
@@ -2,6 +2,7 @@
from .update_court_usecase import UpdateCourtUsecase
from src.shared.environments import Environments
from src.shared.helpers.external_interfaces.http_lambda_requests import LambdaHttpRequest, LambdaHttpResponse
+import json
repo = Environments.get_reservation_repo()()
usecase = UpdateCourtUsecase(repo)
@@ -9,7 +10,16 @@
def lambda_handler(event, context):
+
httpRequest = LambdaHttpRequest(data=event)
+
+ user_info_string = event.get('requestContext', {}).get('authorizer', {}).get('user')
+
+ if user_info_string:
+ httpRequest.data['user_from_authorizer'] = json.loads(user_info_string).get('user')
+ else:
+ httpRequest.data['user_from_authorizer'] = None
+
response = controller(request=httpRequest)
httpResponse = LambdaHttpResponse(status_code=response.status_code, body=response.body, headers=response.headers)
diff --git a/src/modules/update_court/app/update_court_usecase.py b/src/modules/update_court/app/update_court_usecase.py
index b26bef4..b2220bc 100644
--- a/src/modules/update_court/app/update_court_usecase.py
+++ b/src/modules/update_court/app/update_court_usecase.py
@@ -2,7 +2,7 @@
from src.shared.domain.entities.court import Court
from src.shared.domain.enums.status_enum import STATUS
from src.shared.helpers.errors.domain_errors import EntityError
-from src.shared.helpers.errors.usecase_errors import NoItemsFound
+from src.shared.helpers.errors.usecase_errors import NoItemsFound, ForbiddenAction
from src.shared.domain.repositories.reservation_repository_interface import IReservationRepository
@@ -12,6 +12,7 @@ def __init__(self, repo: IReservationRepository):
def __call__(self,
number: int,
+ role: str,
status: Optional[STATUS] = None,
photo: Optional[str] = None):
@@ -24,6 +25,9 @@ def __call__(self,
if self.repo.get_court(number) is None:
raise NoItemsFound(f'number: {number}')
+
+ if role != "ADMIN":
+ raise ForbiddenAction("user, only admin can update courts")
court = self.repo.update_court(number=number,
status=status,
diff --git a/src/shared/authorizer/__init__.py b/src/shared/authorizer/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/functions/graph_authorizer/graph_authorizer.py b/src/shared/authorizer/user_mss_authorizer.py
similarity index 73%
rename from src/functions/graph_authorizer/graph_authorizer.py
rename to src/shared/authorizer/user_mss_authorizer.py
index d771966..b250dc1 100644
--- a/src/functions/graph_authorizer/graph_authorizer.py
+++ b/src/shared/authorizer/user_mss_authorizer.py
@@ -1,8 +1,10 @@
import os
-import re
import json
import urllib3
+from src.shared.environments import Environments
+
+
def lambda_handler(event, context):
"""
This function is used to authorize the user to access the API Gateway.
@@ -17,10 +19,11 @@ def lambda_handler(event, context):
"""
try:
- # Fetching the Microsoft Graph endpoint from the environment variables
- GRAPH_MICROSOFT_ENDPOINT = os.environ.get("GRAPH_MICROSOFT_ENDPOINT", None)
- if not GRAPH_MICROSOFT_ENDPOINT:
- raise Exception("MS_GRAPH_ENDPOINT environment variable not set")
+
+ # Fetch the User Mss enpoint from the environment variables
+ MSS_USER_API_ENDPOINT = os.environ.get("USER_API_URL")
+ if not MSS_USER_API_ENDPOINT:
+ raise Exception("MSS_USER_ENDPOINT environment variable not set")
# Creating a HTTP client
http = urllib3.PoolManager()
@@ -28,14 +31,10 @@ def lambda_handler(event, context):
# Extracting the token from the event data
token = event["authorizationToken"].replace("Bearer ", "")
- print(f"token: {token}")
- print(f"graph_endpoint: {GRAPH_MICROSOFT_ENDPOINT}")
-
- # Fetching the user information from the Microsoft Graph API
- graph_endpoint = GRAPH_MICROSOFT_ENDPOINT
+ # Fetching the user information from the user mss
methodArn = event["methodArn"]
headers = {"Authorization": f"Bearer {token}"}
- response = http.request("GET", graph_endpoint, headers=headers)
+ response = http.request("GET", MSS_USER_API_ENDPOINT + "/reservation-mss-user/get-user", headers=headers)
# Checking if the request was successful
if response.status != 200:
@@ -46,16 +45,7 @@ def lambda_handler(event, context):
print("CHECK BEFORE REGEX")
print(user_data)
-
- # Checking if the user is from Maua
- email_regex = r"[\d]{2}\.[\d]{5}-[\d]@maua\.br" # Regex to match the Maua email
- if not re.match(email_regex, user_data.get("mail", "")):
- return generate_policy("user", "Deny", methodArn)
-
- print("USER_ID: ", user_data.get("id", "did not find id"))
-
- print("CHECK PASSED REGEX AND GET USER")
-
+
policy = generate_policy(
user_data.get("id", "user"), "Allow", methodArn, {"user": json.dumps(user_data)}
)
diff --git a/src/shared/clients/__init__.py b/src/shared/clients/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/shared/clients/s3_client.py b/src/shared/clients/s3_client.py
new file mode 100644
index 0000000..0d2dbf9
--- /dev/null
+++ b/src/shared/clients/s3_client.py
@@ -0,0 +1,68 @@
+import boto3
+
+from src.shared.environments import Environments
+
+
+class s3_client:
+
+ def __init__(self):
+ self.__envs = Environments.get_envs()
+ stage = self.__envs.stage.value
+ if stage == "TEST":
+ self.s3 = boto3.client(
+ "s3",
+ aws_access_key_id=self.__envs.client_id,
+ aws_secret_access_key=self.__envs.client_secret,
+ endpoint_url=self.__envs.bucket_endpoint_url,
+ region_name=self.__envs.region,
+ config=boto3.session.Config(signature_version="s3v4"),
+ )
+ else:
+ self.s3 = boto3.client("s3")
+
+ def upload_file(self, key, file_type, decode_string):
+ print(f"DEBUG upload_file - key: {key}")
+ print(f"DEBUG upload_file - file_type: {file_type}")
+ print(f"DEBUG upload_file - decode_string type: {type(decode_string)}")
+ print(f"DEBUG upload_file - decode_string length: {len(decode_string)}")
+
+ # Content type correto para Excel
+ content_types = {
+ '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ '.xls': 'application/vnd.ms-excel',
+ }
+
+ content_type = content_types.get(file_type, 'application/octet-stream')
+ print(f"DEBUG upload_file - content_type: {content_type}")
+
+ try:
+ print("DEBUG upload_file - Chamando s3.put_object...")
+ response = self.s3.put_object(
+ Bucket=self.__envs.s3_bucket_name,
+ Key=key,
+ Body=decode_string, # Este deve ser bytes
+ ContentType=content_type,
+ )
+ print("DEBUG upload_file - put_object executado com sucesso")
+
+ return {
+ 's3_response': response,
+ 'key': key
+ }
+
+ except Exception as e:
+ print(f"DEBUG upload_file - ERRO no put_object: {str(e)}")
+ print(f"DEBUG upload_file - Tipo do erro: {type(e)}")
+ print(f"DEBUG upload_file - Bucket: {self.__envs.s3_bucket_name}")
+ raise e
+
+ def delete_file(self):
+ pass
+ def get_all_files(self):
+ pass
+ def get_file(self):
+ pass
+ def generate_presigned_url(self, expiration_time: int, object_name: str, method: str, content_type: str):
+ pass
+
+
diff --git a/src/shared/clients/user_api_client.py b/src/shared/clients/user_api_client.py
new file mode 100644
index 0000000..0ba2d41
--- /dev/null
+++ b/src/shared/clients/user_api_client.py
@@ -0,0 +1,87 @@
+import json
+import os
+import requests
+
+from src.shared.environments import Environments
+
+class UserAPIClient:
+
+ def __init__(self):
+ self.all_users = self.retrieve_users()
+
+ def get_user_name(self, user_id):
+ user = next((user for user in self.all_users if user["user_id"] == user_id), None)
+ return user["name"] if user is not None else None
+
+ def authenticate_user(self, token):
+ return self._auth_user(token=token)
+
+ @staticmethod
+ def retrieve_users():
+
+ api_url= os.environ.get("USER_API_URL")
+ try:
+ response = requests.get(api_url + '/reservation-mss-user/get-all-users')
+ users = response.json().get("users")
+ return users
+ except:
+ raise Exception('Couldn\'t retrieve users')
+
+ #TODO adciionar os parametros nas request, testar se funciona mesmo
+
+ @staticmethod
+ def _auth_user(token):
+
+ '''
+ UNUSED AND DEPRECATED DO NOT USE
+ '''
+
+ #this will only get the user info if the user is already created in db, else it will delete the user shortly after
+
+ #UNUSED DO NOT USE THIS, ITS DEPRECATED
+
+ api_url = os.environ.get("USER_API_URL")
+
+ #untested funtion
+ def delete_user(token):
+
+ try:
+
+ headers = {
+ "Authorization": f"Bearer{token}"
+ }
+
+ response = requests.delete(api_url + 'reservation-mss-user/delete-user', headers=headers)
+
+ return response.json().get("message")
+
+ except:
+
+ raise Exception('Could not delete user')
+
+ try:
+
+ headers = {
+ "Authorization": f"Bearer {token}"
+ }
+
+ response = requests.get(api_url + 'reservation-mss-user/auth-user', headers=headers)
+
+ user = response.json().get("user")
+
+ identifier = user.get("message", None)
+
+ #TODO test this part
+
+ if identifier == "the user was created successfully":
+
+ #untested funtion
+ delete_user(token=token)
+
+ raise Exception('User was not registered')
+
+ return user
+
+ except:
+ raise Exception('Could not authenticate user')
+
diff --git a/src/shared/domain/entities/booking.py b/src/shared/domain/entities/booking.py
index d9c78f0..d517c67 100644
--- a/src/shared/domain/entities/booking.py
+++ b/src/shared/domain/entities/booking.py
@@ -3,6 +3,7 @@
from typing import Optional, List
from src.shared.domain.entities.court import Court
from src.shared.domain.enums.sport import SPORT
+from src.shared.domain.enums.type import BOOKING_TYPE
from src.shared.helpers.errors.domain_errors import EntityError, EntityParameterOrderDatesError
class Booking(abc.ABC):
@@ -13,9 +14,10 @@ class Booking(abc.ABC):
user_id: str
booking_id: str
materials: List[str]
+ booking_type: BOOKING_TYPE
- def __init__(self, start_date: int, end_date: int, court_number: int, sport: SPORT, user_id: str, booking_id: str, materials: List[str]):
+ def __init__(self, start_date: int, end_date: int, court_number: int, sport: SPORT, user_id: str, booking_id: str, materials: List[str], booking_type: BOOKING_TYPE):
if not Booking.validate_dates(start_date, end_date):
raise EntityError("dates")
self.start_date = start_date
@@ -44,6 +46,14 @@ def __init__(self, start_date: int, end_date: int, court_number: int, sport: SPO
raise EntityError("materials")
self.materials = materials
+ if not Booking.validate_booking_type(booking_type):
+ raise EntityError("type")
+
+ if booking_type == BOOKING_TYPE.MAINTENCE and self.sport != SPORT.NA:
+ raise EntityError("sport")
+
+ self.booking_type = booking_type
+
@staticmethod
def validate_dates(start_date: int, end_date: int) -> bool:
@@ -95,6 +105,12 @@ def validate_materials(materials: List[str]) -> bool:
return False
return True
+ @staticmethod
+ def validate_booking_type(booking_type: BOOKING_TYPE) -> bool:
+ if not isinstance(booking_type, BOOKING_TYPE):
+ return False
+ return True
+
def to_dict(self):
return {
"start_date": self.start_date,
@@ -103,7 +119,8 @@ def to_dict(self):
"sport": self.sport.value,
"user_id": self.user_id,
"booking_id": self.booking_id,
- "materials": self.materials
+ "materials": self.materials,
+ "type": self.booking_type.value
}
def __eq__(self, other):
diff --git a/src/shared/domain/enums/sport.py b/src/shared/domain/enums/sport.py
index cabb69e..a0ef3ff 100644
--- a/src/shared/domain/enums/sport.py
+++ b/src/shared/domain/enums/sport.py
@@ -8,5 +8,8 @@ class SPORT(Enum):
HANDBALL = "Handball"
FUTSAL = "Futsal"
RUGBY = "Rugby"
- PING_PONG = "Ping Pong"
+ PING_PONG= "Ping Pong"
BEACH_TENNIS = "Beach Tennis"
+ NATACAO = "Natacao"
+ CORRIDA = "Corrida"
+ NA = "NA"
diff --git a/src/shared/domain/enums/type.py b/src/shared/domain/enums/type.py
new file mode 100644
index 0000000..d1fc9d1
--- /dev/null
+++ b/src/shared/domain/enums/type.py
@@ -0,0 +1,7 @@
+from enum import Enum
+
+class BOOKING_TYPE(Enum):
+ MAINTENCE = 'Maintence'
+ TRAINING = 'Training'
+ COMMON = 'Common'
+ UNDEFINED = 'Undefined'
diff --git a/src/shared/domain/repositories/booking_repository_interface.py b/src/shared/domain/repositories/booking_repository_interface.py
index afb26a5..cc1a199 100644
--- a/src/shared/domain/repositories/booking_repository_interface.py
+++ b/src/shared/domain/repositories/booking_repository_interface.py
@@ -4,6 +4,7 @@
from src.shared.domain.entities.booking import Booking
from src.shared.domain.enums.sport import SPORT
+from src.shared.domain.enums.type import BOOKING_TYPE
class IBookingRepository(ABC):
@@ -12,6 +13,9 @@ class IBookingRepository(ABC):
def create_booking(self, booking: Booking) -> Optional[Booking]:
'''
If booking does not exist, creates it and returns it
+
+ !!!Must do time validations outside this method!!!!
+ Keep it simples, only appending or putting into repostitory
'''
pass
@@ -22,15 +26,17 @@ def update_booking(self,
end_date: int = None,
court_number: int = None,
sport: SPORT = None,
- materials: List[str] = None) -> Optional[Booking]:
+ materials: List[str] = None,
+ booking_type: BOOKING_TYPE = None) -> Optional[Booking]:
'''
If booking exists, updates it and returns it
+
+ !!!Must do time validations outside this method!!!!
'''
pass
@abstractmethod
- def get_booking(self,
- booking_id: str) -> Optional[Booking]:
+ def get_booking(self, booking_id: str) -> Optional[Booking]:
'''
If the booking exists, returns it, else returns None
'''
@@ -40,18 +46,20 @@ def get_booking(self,
def get_bookings(self,
booking_id: Optional[str] = None,
user_id: Optional[str] = None,
- sport: Optional[SPORT] = None,
+ sport: Optional[str] = None,
court_number: Optional[int] = None,
+ booking_type: Optional[str] = None,
end_date: Optional[int] = None,
- start_date: Optional[int] = None) -> List[Optional[Booking]]:
+ start_date: Optional[int] = None
+ ) -> List[Optional[Booking]]:
'''
If the booking exists, returns it, else returns None
'''
pass
+ # TODO: arrumar a lógica para receber as infos do usuário enviar e-mail
@abstractmethod
- def delete_booking(self,
- booking_id: str) -> Optional[Booking]:
+ def delete_booking(self, booking_id: int, user) -> Optional[Booking]:
'''
If booking exists, deletes it and returns it
else returns None
@@ -64,3 +72,26 @@ def get_all_bookings(self):
Returns all bookings
'''
pass
+
+ @abstractmethod
+ def get_all_bookings_by_date_range(self, initial_date: int, final_date: int) -> Optional[List[Booking]]:
+ '''
+ Returns all bookings, filtered by date range
+ '''
+ pass
+
+ @abstractmethod
+ def get_all_users(self) -> List[str]:
+ '''
+ Returns name users by user id
+ '''
+ pass
+
+ # TODO: método para enviar e-mail para o usuário
+ @abstractmethod
+ def send_user_email(self, user, deleted_booking: Booking) -> bool:
+ '''
+ Send user an e-mail
+ '''
+ pass
+
\ No newline at end of file
diff --git a/src/shared/domain/repositories/reservation_repository_interface.py b/src/shared/domain/repositories/reservation_repository_interface.py
index 584f24f..4d30fe2 100644
--- a/src/shared/domain/repositories/reservation_repository_interface.py
+++ b/src/shared/domain/repositories/reservation_repository_interface.py
@@ -1,4 +1,6 @@
from abc import ABC, abstractmethod
+from typing import Optional
+from src.shared.domain.entities.booking import Booking
from src.shared.domain.entities.court import Court
from src.shared.domain.enums.status_enum import STATUS
@@ -42,4 +44,4 @@ def get_all_courts(self):
'''
Returns all courts
'''
- pass
+ pass
\ No newline at end of file
diff --git a/src/shared/environments.py b/src/shared/environments.py
index af15aa1..bfe295c 100644
--- a/src/shared/environments.py
+++ b/src/shared/environments.py
@@ -31,6 +31,9 @@ class Environments:
dynamo_sort_key: str
cloud_front_distribution_domain: str
mss_name: str
+ from_email: str
+ hidden_copy: str
+ s3_assets: str
def _configure_local(self):
from dotenv import load_dotenv
@@ -52,6 +55,9 @@ def load_envs(self):
self.dynamo_partition_key = "PK"
self.dynamo_sort_key = "SK"
self.cloud_front_distribution_domain = "https://d3q9q9q9q9q9q9.cloudfront.net"
+ self.client_id = "root" #change to what is inside minio compose
+ self.client_secret = "root1234" #change to what is inside minio compose
+ self.bucket_endpoint_url = "http://localhost:9000"
else:
self.s3_bucket_name = os.environ.get("S3_BUCKET_NAME")
@@ -61,6 +67,9 @@ def load_envs(self):
self.dynamo_partition_key = os.environ.get("DYNAMO_PARTITION_KEY")
self.dynamo_sort_key = os.environ.get("DYNAMO_SORT_KEY")
self.cloud_front_distribution_domain = os.environ.get("CLOUD_FRONT_DISTRIBUTION_DOMAIN")
+ self.from_email = os.environ.get("FROM_EMAIL")
+ self.hidden_copy = os.environ.get("HIDDEN_COPY")
+ self.s3_assets = os.environ.get("S3_ASSETS_CDN")
# @staticmethod
# def get_user_repo() -> IUserRepository:
diff --git a/src/shared/helpers/errors/usecase_errors.py b/src/shared/helpers/errors/usecase_errors.py
index 75d75b1..1c17218 100644
--- a/src/shared/helpers/errors/usecase_errors.py
+++ b/src/shared/helpers/errors/usecase_errors.py
@@ -16,7 +16,20 @@ class DependantFilter(BaseError):
def __init__(self, message: str):
super().__init__(f'Filters have to be provided together: {message}')
+class DynamoDBBaseError(BaseError):
+ def __init__(self, message: str):
+ super().__init__(f'Error extracting bookings from dynamo: {message}')
+
class InvalidSchedule(BaseError):
def __init__(self):
- super().__init__('Court is already booked for the selected time slot')
+ super().__init__('Court is already booked for the selected time slot or has to have 15 min tolerance')
+class NoAdminFound(BaseError):
+
+ def __init__(self):
+ super().__init__("No user with role admin was found in user mss")
+
+class NoAdminBookingsFound(BaseError):
+
+ def __init__(self):
+ super().__init__("Admin does not have any bookings")
diff --git a/src/shared/helpers/functions/compose_delete_booking_email.py b/src/shared/helpers/functions/compose_delete_booking_email.py
new file mode 100644
index 0000000..6054eaf
--- /dev/null
+++ b/src/shared/helpers/functions/compose_delete_booking_email.py
@@ -0,0 +1,267 @@
+from datetime import datetime
+from src.shared.domain.entities.booking import Booking
+from src.shared.environments import Environments
+
+def compose_deleted_user_email(user, deleted_booking: Booking):
+ name = user.get('name')
+ email = user.get('email')
+ data_hora_inicio = datetime.fromtimestamp((deleted_booking.start_date - 3 * 60 * 60 * 1000)/1000)
+ data_hora_fim = datetime.fromtimestamp((deleted_booking.end_date - 3 * 60 * 60 * 1000)/1000)
+
+ s3_assets_endpoint = Environments.get_envs().s3_assets + '/assets'
+
+ message = f"""
+
+
+
+
+
+ Reserva Cancelada
+
+
+
+
+
+
+

+
+
+
Olá {name},
+
+
Lamentamos informar que sua reserva:
+
+
+
+ Quadra:
+ {deleted_booking.court_number}
+
+
+ Data:
+ {data_hora_inicio.strftime("%d/%m/%Y")}
+
+
+ Horário:
+ {data_hora_inicio.strftime("%H:%M")} - {data_hora_fim.strftime("%H:%M")}
+
+
+
+
foi CANCELADA
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """
+
+ return message
\ No newline at end of file
diff --git a/src/shared/infra/dto/booking_dynamo_dto.py b/src/shared/infra/dto/booking_dynamo_dto.py
index b8a0bd0..38ad9fb 100644
--- a/src/shared/infra/dto/booking_dynamo_dto.py
+++ b/src/shared/infra/dto/booking_dynamo_dto.py
@@ -2,6 +2,7 @@
from src.shared.domain.entities.booking import Booking
from src.shared.domain.enums.sport import SPORT
+from src.shared.domain.enums.type import BOOKING_TYPE
class BookingDynamoDTO:
@@ -12,8 +13,9 @@ class BookingDynamoDTO:
user_id: str
booking_id: str
materials: List[str]
+ booking_type: BOOKING_TYPE
- def __init__(self, start_date: int, end_date: int, court_number: int, sport: SPORT, user_id: str, booking_id: str, materials: List[str]):
+ def __init__(self, start_date: int, end_date: int, court_number: int, sport: SPORT, user_id: str, booking_id: str, materials: List[str], booking_type: BOOKING_TYPE):
self.start_date = start_date
self.end_date = end_date
self.court_number = court_number
@@ -21,6 +23,7 @@ def __init__(self, start_date: int, end_date: int, court_number: int, sport: SPO
self.user_id = user_id
self.booking_id = booking_id
self.materials = materials
+ self.booking_type = booking_type
@staticmethod
def from_entity(booking: Booking) -> 'BookingDynamoDTO':
@@ -34,7 +37,8 @@ def from_entity(booking: Booking) -> 'BookingDynamoDTO':
sport = booking.sport,
user_id = booking.user_id,
booking_id = booking.booking_id,
- materials = booking.materials
+ materials = booking.materials,
+ booking_type= booking.booking_type
)
def to_dynamo(self) -> dict:
@@ -49,7 +53,8 @@ def to_dynamo(self) -> dict:
"sport": self.sport.value,
"user_id": self.user_id,
"booking_id": self.booking_id,
- "materials": self.materials
+ "materials": self.materials or [],
+ "booking_type": self.booking_type.value
}
booking_without_none_values = {k: v for k, v in data.items() if v is not None}
@@ -68,7 +73,8 @@ def from_dynamo(booking_data: dict) -> "BookingDynamoDTO":
sport = SPORT(booking_data["sport"]),
user_id = booking_data["user_id"],
booking_id = booking_data["booking_id"],
- materials = booking_data["materials"]
+ materials = booking_data.get("materials") or [],
+ booking_type= BOOKING_TYPE(booking_data.get("booking_type", None)) if booking_data.get("booking_type", None) is not None else BOOKING_TYPE.UNDEFINED
)
def to_entity(self) -> Booking:
@@ -82,11 +88,12 @@ def to_entity(self) -> Booking:
sport=self.sport,
user_id=self.user_id,
booking_id=self.booking_id,
- materials=self.materials
+ materials=self.materials,
+ booking_type=self.booking_type
)
def __repr__(self):
- return f"BookingDynamoDTO(start_date={self.start_date}, end_date={self.end_date}, court_number={self.court_number}, sport={self.sport}, user_id={self.user_id}, booking_id={self.booking_id}, materials={self.materials})"
+ return f"BookingDynamoDTO(start_date={self.start_date}, end_date={self.end_date}, court_number={self.court_number}, sport={self.sport.value}, user_id={self.user_id}, booking_id={self.booking_id}, materials={self.materials}, booking_type={self.booking_type.value})"
def __eq__(self, other):
return self.__dict__ == other.__dict__
diff --git a/src/shared/infra/repositories/booking_repository_dynamo.py b/src/shared/infra/repositories/booking_repository_dynamo.py
index b9b6e85..b811e5e 100644
--- a/src/shared/infra/repositories/booking_repository_dynamo.py
+++ b/src/shared/infra/repositories/booking_repository_dynamo.py
@@ -1,11 +1,16 @@
+import os
from typing import Optional, List
+import boto3
from boto3.dynamodb.conditions import Key
from src.shared.domain.entities.booking import Booking
from src.shared.domain.enums.sport import SPORT
+from src.shared.domain.enums.type import BOOKING_TYPE
from src.shared.domain.repositories.booking_repository_interface import IBookingRepository
from src.shared.environments import Environments
+from src.shared.helpers.errors.usecase_errors import ForbiddenAction
+from src.shared.helpers.functions.compose_delete_booking_email import compose_deleted_user_email
from src.shared.infra.dto.booking_dynamo_dto import BookingDynamoDTO
from src.shared.infra.external.dynamo.datasources.dynamo_datasource import DynamoDatasource
@@ -48,7 +53,8 @@ def update_booking(self,
end_date: int = None,
court_number: int = None,
sport: SPORT = None,
- materials: List[str] = None) -> Optional[Booking]:
+ materials: List[str] = None,
+ booking_type: BOOKING_TYPE = None) -> Optional[Booking]:
booking_to_update = self.get_booking(booking_id)
@@ -63,6 +69,7 @@ def update_booking(self,
"materials": materials if materials is not None else booking_to_update.materials,
"user_id": booking_to_update.user_id,
"booking_id": booking_to_update.booking_id,
+ "booking_type": booking_type.value if booking_type is not None else booking_to_update.booking_type.value
}
resp = self.dynamo.update_item(update_dict=update_dict,
@@ -77,10 +84,12 @@ def update_booking(self,
def get_bookings(self,
booking_id: Optional[str] = None,
user_id: Optional[str] = None,
- sport: Optional[SPORT] = None,
+ sport: Optional[str] = None,
court_number: Optional[int] = None,
+ booking_type: Optional[str] = None,
end_date: Optional[int] = None,
- start_date: Optional[int] = None) -> List[Optional[Booking]]:
+ start_date: Optional[int] = None
+ ) -> List[Optional[Booking]]:
filters = locals().copy()
filters.pop('self')
@@ -118,23 +127,104 @@ def get_booking(self, booking_id: str) -> Optional[Booking]:
return BookingDynamoDTO.from_dynamo(dynamo_object['Item']).to_entity()
- def delete_booking(self, booking_id: str) -> Optional[Booking]:
+ def delete_booking(self, booking_id: str, user) -> Optional[Booking]:
- delete_booking = self.dynamo.delete_item(partition_key=self.booking_partition_key_format(),
- sort_key=self.booking_sort_key_format(booking_id))
- if "Attributes" not in delete_booking:
+ booking = self.get_booking(booking_id)
+ user_role = user.get('role')
+ user_id = user.get('user_id')
+
+ if not booking:
return None
- return BookingDynamoDTO.from_dynamo(delete_booking['Attributes']).to_entity()
+ is_admin = user_role == 'ADMIN'
+ is_owner = user_role == 'STUDENT' and booking.user_id == user_id
+
+ if is_admin or is_owner:
+ deleted = self.dynamo.delete_item(
+ partition_key=self.booking_partition_key_format(),
+ sort_key=self.booking_sort_key_format(booking_id)
+ )
+
+ deleted_booking = BookingDynamoDTO.from_dynamo(deleted['Attributes']).to_entity()
+
+ self.send_user_email(user, deleted_booking)
+
+ return deleted_booking
+
+ if user_role == 'STUDENT':
+ raise ForbiddenAction('user id')
+
+ return None
+
def get_all_bookings(self) -> Optional[List[Booking]]:
all_bookings = []
- all_items = self.dynamo.get_all_items().get('Items')
+ all_items = self.dynamo.get_all_items().get('Items') or []
for item in all_items:
if item.get('entity') == 'booking':
all_bookings.append(BookingDynamoDTO.from_dynamo(item).to_entity())
+
+ return all_bookings
+
+ def get_all_bookings_by_date_range(self, initial_date: int, final_date: int) -> Optional[List[Booking]]:
+
+ all_bookings = []
+ all_items = self.dynamo.get_all_items().get('Items') or []
+
+ for item in all_items:
+ if item.get('entity') == 'booking':
+ booking = BookingDynamoDTO.from_dynamo(item).to_entity()
+ if initial_date <= booking.start_date <= final_date:
+ all_bookings.append(booking)
return all_bookings
+
+ def get_all_users(self):
+ return super().get_all_users()
+
+
+ def send_user_email(self, user, deleted_booking: Booking) -> bool:
+ try:
+
+ client_ses = boto3.client('ses', region_name=os.environ.get('AWS_REGION'))
+
+ email_to_send = compose_deleted_user_email(user, deleted_booking)
+
+ print('7 mensagem email criada -> ' + email_to_send)
+
+ response = client_ses.send_email(
+ Destination={
+ 'ToAddresses': [
+ user.get('email'),
+ ],
+ 'BccAddresses':
+ [
+ Environments.get_envs().hidden_copy
+ ]
+ },
+ Message={
+ 'Body': {
+ 'Html': {
+ 'Charset': "UTF-8",
+ 'Data': email_to_send,
+ },
+ },
+ 'Subject': {
+ 'Charset': "UTF-8",
+ 'Data': 'Mauá Reservation - Reserva Cancelada',
+ },
+ },
+ Source = Environments.get_envs().from_email,
+ )
+
+ print('EMAIL ENVIADO')
+
+ return True
+ except Exception as err:
+ print(err)
+ return False
+
+
diff --git a/src/shared/infra/repositories/booking_repository_mock.py b/src/shared/infra/repositories/booking_repository_mock.py
index 3440029..1f75237 100644
--- a/src/shared/infra/repositories/booking_repository_mock.py
+++ b/src/shared/infra/repositories/booking_repository_mock.py
@@ -1,7 +1,9 @@
from typing import List, Optional
from src.shared.domain.entities.booking import Booking
from src.shared.domain.enums.sport import SPORT
+from src.shared.domain.enums.type import BOOKING_TYPE
from src.shared.domain.repositories.booking_repository_interface import IBookingRepository
+from src.shared.helpers.errors.usecase_errors import ForbiddenAction
class BookingRepositoryMock(IBookingRepository):
@@ -14,9 +16,10 @@ def __init__(self):
end_date=1634583365000,
court_number=1,
sport=SPORT.TENNIS,
- user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
+ user_id='1f25448b-3429-4c19-8287-d9e64f17bc3a',
booking_id='b1d3bebf-dc0d-4fc1-861c-506a40cc2925',
- materials=['Raquete', 'Bola', 'Rede', 'Tenis']
+ materials=['Raquete', 'Bola', 'Rede', 'Tenis'],
+ booking_type=BOOKING_TYPE.TRAINING
),
Booking(
@@ -24,9 +27,10 @@ def __init__(self):
end_date=1634567400000,
court_number=2,
sport=SPORT.FOOTBALL,
- user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
+ user_id='c07e0862-3c07-4227-ab0f-511a267cb7ff',
booking_id='b2d3bebf-dc0d-4fc1-861c-506a40cc2925',
- materials=['Bola', 'Chuteira']
+ materials=['Bola', 'Chuteira'],
+ booking_type=BOOKING_TYPE.TRAINING
),
Booking(
@@ -34,9 +38,10 @@ def __init__(self):
end_date=1634571000000,
court_number=3,
sport=SPORT.BASKETBALL,
- user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
+ user_id='d351a9b1-937f-423c-a9d1-9929b5795be1',
booking_id='b3d3bebf-dc0d-4fc1-861c-506a40cc2925',
- materials=['Bola']
+ materials=['Bola'],
+ booking_type=BOOKING_TYPE.COMMON
),
Booking(
@@ -46,7 +51,8 @@ def __init__(self):
sport=SPORT.VOLLEYBALL,
user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
booking_id='b4d3bebf-dc0d-4fc1-861c-506a40cc2925',
- materials=['Bola', 'Rede']
+ materials=['Bola', 'Rede'],
+ booking_type=BOOKING_TYPE.COMMON
),
Booking(
@@ -56,7 +62,8 @@ def __init__(self):
sport=SPORT.HANDBALL,
user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
booking_id='b5d3bebf-dc0d-4fc1-861c-506a40cc2925',
- materials=['Bola']
+ materials=['Bola'],
+ booking_type=BOOKING_TYPE.TRAINING
),
Booking(
@@ -66,7 +73,8 @@ def __init__(self):
sport=SPORT.FUTSAL,
user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
booking_id='b6d3bebf-dc0d-4fc1-861c-506a40cc2925',
- materials=['Bola', 'Chuteira']
+ materials=['Bola', 'Chuteira'],
+ booking_type=BOOKING_TYPE.TRAINING
),
Booking(
@@ -76,7 +84,8 @@ def __init__(self):
sport=SPORT.RUGBY,
user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
booking_id='b7d3bebf-dc0d-4fc1-861c-506a40cc2925',
- materials=['Bola', 'Tenis', 'Capacete']
+ materials=['Bola', 'Tenis', 'Capacete'],
+ booking_type=BOOKING_TYPE.TRAINING
),
Booking(
@@ -86,7 +95,8 @@ def __init__(self):
sport=SPORT.PING_PONG,
user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
booking_id='b8d3bebf-dc0d-4fc1-861c-506a40cc2925',
- materials=['Raquete', 'Bola']
+ materials=['Raquete', 'Bola'],
+ booking_type=BOOKING_TYPE.TRAINING
),
]
@@ -100,7 +110,8 @@ def update_booking(self,
end_date: int = None,
court_number: int = None,
sport: SPORT = None,
- materials: List[str] = None
+ materials: List[str] = None,
+ booking_type: BOOKING_TYPE = None
) -> Booking:
booking = self.get_booking(booking_id)
@@ -118,16 +129,24 @@ def update_booking(self,
booking.sport = sport
if materials is not None:
booking.materials = materials
-
+ if booking_type is not None:
+ booking.booking_type = booking_type
return booking
+ def get_booking(self, booking_id: str):
+ for booking in self.bookings:
+ if booking.booking_id == booking_id:
+ return booking
+ return None
+
def get_bookings(self,
booking_id: Optional[str] = None,
user_id: Optional[str] = None,
sport: Optional[str] = None,
court_number: Optional[int] = None,
end_date: Optional[int] = None,
- start_date: Optional[int] = None) -> List[Optional[Booking]]:
+ start_date: Optional[int] = None,
+ booking_type: Optional[str] = None) -> List[Optional[Booking]]:
filters = locals().copy()
filters.pop('self')
@@ -153,19 +172,46 @@ def get_bookings(self,
return bookings
- def get_booking(self,
- booking_id: str) -> Optional[Booking]:
+ def delete_booking(self, booking_id: str, user):
+ booking = self.get_booking(booking_id)
- for booking in self.bookings:
- if booking.booking_id == booking_id:
- return booking
+ user_role = user.get('role')
- def delete_booking(self, booking_id: str):
- booking = self.get_booking(booking_id)
if booking is not None:
- self.bookings.remove(booking)
- return booking
+
+ if user_role == 'ADMIN':
+ self.bookings.remove(booking)
+ return booking
+
+ elif user_role == 'STUDENT':
+
+ if booking.user_id == user.get('user_id'):
+
+ self.bookings.remove(booking)
+ return booking
+
+ else:
+ raise ForbiddenAction('user id')
+
return None
def get_all_bookings(self) -> List[Booking]:
return self.bookings
+
+ def get_all_bookings_by_date_range(self, initial_date, final_date):
+
+ all_bookings = []
+ for booking in self.bookings:
+ if initial_date <= booking.start_date <= final_date:
+ all_bookings.append(booking)
+
+ return all_bookings
+
+ def get_all_users(self) -> List[str]:
+ users_id = list(set([booking.user_id for booking in self.bookings]))
+ return users_id
+
+ def send_user_email(self, user) -> bool:
+ print('ENVIAR E-MAIL PARA O USUÁRIO')
+
+ return True
diff --git a/src/shared/infra/repositories/reservation_repository_dynamo.py b/src/shared/infra/repositories/reservation_repository_dynamo.py
index 5a65f38..6f2422f 100644
--- a/src/shared/infra/repositories/reservation_repository_dynamo.py
+++ b/src/shared/infra/repositories/reservation_repository_dynamo.py
@@ -5,7 +5,6 @@
from typing import List, Optional
from src.shared.infra.external.dynamo.datasources.dynamo_datasource import DynamoDatasource
from src.shared.domain.enums.status_enum import STATUS
-from boto3.dynamodb.conditions import Key
class ReservationRepositoryDynamo(IReservationRepository):
diff --git a/src/shared/infra/repositories/util/S3Manager.py b/src/shared/infra/repositories/util/S3Manager.py
new file mode 100644
index 0000000..318e02e
--- /dev/null
+++ b/src/shared/infra/repositories/util/S3Manager.py
@@ -0,0 +1,46 @@
+import boto3
+
+from src.shared.environments import Environments
+
+
+class S3Manager:
+
+ def __init__(self):
+ self.__envs = Environments.get_envs()
+ stage = self.__envs.stage.value
+ if stage == "TEST":
+ self.s3 = boto3.client(
+ "s3",
+ aws_access_key_id=self.__envs.client_id,
+ aws_secret_access_key=self.__envs.client_secret,
+ endpoint_url=self.__envs.bucket_endpoint_url,
+ region_name=self.__envs.region,
+ config=boto3.session.Config(signature_version="s3v4"),
+ )
+ else:
+ self.s3 = boto3.client("s3")
+
+ def upload_file(self, key, file_type, decode_string):
+
+ response = self.s3.put_object(
+ Bucket=self.__envs.s3_bucket_name,
+ Key=key,
+ Body=decode_string,
+ ContentType=file_type.replace(".", ""),
+ )
+
+ return {
+ 's3_response': response,
+ 'key': key
+ }
+
+ def delete_file(self):
+ pass
+ def get_all_files(self):
+ pass
+ def get_file(self):
+ pass
+ def generate_presigned_url(self, expiration_time: int, object_name: str, method: str, content_type: str):
+ pass
+
+
diff --git a/tests/clients/__init__.py b/tests/clients/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/clients/test_user_api_client.py b/tests/clients/test_user_api_client.py
new file mode 100644
index 0000000..1d415e0
--- /dev/null
+++ b/tests/clients/test_user_api_client.py
@@ -0,0 +1,37 @@
+import pytest
+from src.shared.clients.user_api_client import UserAPIClient
+
+
+class TestUserAPIClient:
+
+ # to test this, you must declare in your .env the user mss endpoint as USER_API_URL without
+ # any route at the end (the user api client already adds the routing)
+ # ex: https://api-url/reservation-mss-user
+
+ @pytest.mark.skip("Can't run test in github actions")
+ def test_get_user(self):
+
+ user_client = UserAPIClient()
+ user_name = user_client.get_user_name('1f25448b-3429-4c19-8287-d9e64f17bc3a')
+
+ assert user_name == 'GUSTAVO ALVES GOMES'
+
+ @pytest.mark.skip("Can't run test in github actions")
+ def test_auth_user(self):
+
+ #this test will only pass if user is already created in db, as method checks for this
+
+ user_client = UserAPIClient()
+ # the token in the next line must be updated for testing, it is not last longing
+ # it must be a valid microsoft graph authentication token (jwt format)
+
+ # you can get it via azure cli via the following prompts
+ # az login
+ # az account get-access-token --scope https://graph.microsoft.com/.default
+ user_token = "eyJ0eXAiOiJKV1QiLCJub25jZSI6Ii1abjloOFZOOEZuNVMxS0gyUnBmTFZJeExIbWVmUVpoaVRGd0ZwRXJ3MVEiLCJhbGciOiJSUzI1NiIsIng1dCI6Il9qTndqZVNudlRUSzhYRWRyNVFVUGtCUkxMbyIsImtpZCI6Il9qTndqZVNudlRUSzhYRWRyNVFVUGtCUkxMbyJ9.eyJhdWQiOiJodHRwczovL2dyYXBoLm1pY3Jvc29mdC5jb20iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9jNDllMTkzOS00YjUzLTQ3MzgtYmI2NC00MWZiMjk5MGU0MWMvIiwiaWF0IjoxNzUyMzQ4MjIxLCJuYmYiOjE3NTIzNDgyMjEsImV4cCI6MTc1MjQzNDkyMSwiYWNjdCI6MCwiYWNyIjoiMSIsImFpbyI6IkFVUUF1LzhaQUFBQXh4MnlPNFgySmp2S0VYMFpsbmNXS292RnI1WGxhRnlqUndCWU4wUkkzcEFLd3ZpSmdnK1ZpM09NSXQyTklseVNRVjZXQXQ0cHZWSUZzNWYzZWhDU1R3PT0iLCJhbXIiOlsicHdkIl0sImFwcF9kaXNwbGF5bmFtZSI6Ik1pY3Jvc29mdCBBenVyZSBDTEkiLCJhcHBpZCI6IjA0YjA3Nzk1LThkZGItNDYxYS1iYmVlLTAyZjllMWJmN2I0NiIsImFwcGlkYWNyIjoiMCIsImZhbWlseV9uYW1lIjoiTFVJWiBTRUlYQVMgSU9SSU8iLCJnaXZlbl9uYW1lIjoiTEVPTkFSRE8iLCJpZHR5cCI6InVzZXIiLCJpcGFkZHIiOiIxODkuMTIwLjcyLjU4IiwibmFtZSI6IkxFT05BUkRPIExVSVogU0VJWEFTIElPUklPIiwib2lkIjoiZDM1MWE5YjEtOTM3Zi00MjNjLWE5ZDEtOTkyOWI1Nzk1YmUxIiwib25wcmVtX3NpZCI6IlMtMS01LTIxLTEyNTEwOTIzMjUtMTAwNzM4MzU3OC05Mjk3MDEwMDAtNjQ2NTYiLCJwbGF0ZiI6IjUiLCJwdWlkIjoiMTAwMzIwMDI1NzkwRTY2MyIsInJoIjoiMS5BUThBT1JtZXhGTkxPRWU3WkVIN0taRGtIQU1BQUFBQUFBQUF3QUFBQUFBQUFBQVBBR3NQQUEuIiwic2NwIjoiQXBwbGljYXRpb24uUmVhZFdyaXRlLkFsbCBBcHBSb2xlQXNzaWdubWVudC5SZWFkV3JpdGUuQWxsIEF1ZGl0TG9nLlJlYWQuQWxsIERlbGVnYXRlZFBlcm1pc3Npb25HcmFudC5SZWFkV3JpdGUuQWxsIERpcmVjdG9yeS5BY2Nlc3NBc1VzZXIuQWxsIGVtYWlsIEdyb3VwLlJlYWRXcml0ZS5BbGwgb3BlbmlkIHByb2ZpbGUgVXNlci5SZWFkLkFsbCBVc2VyLlJlYWRXcml0ZS5BbGwiLCJzaWQiOiIwMDZjYWM2OS0wMzFjLWY5ZTktZTMyOC05MjlhMTJhN2E5Y2EiLCJzdWIiOiJmeG9TLVRTaGpjRHlDQmVId1N0enozQ0RmTTNJdXV3aTJYemYta1JncTFFIiwidGVuYW50X3JlZ2lvbl9zY29wZSI6IlNBIiwidGlkIjoiYzQ5ZTE5MzktNGI1My00NzM4LWJiNjQtNDFmYjI5OTBlNDFjIiwidW5pcXVlX25hbWUiOiIyMy4wMDg0Ny00QG1hdWEuYnIiLCJ1cG4iOiIyMy4wMDg0Ny00QG1hdWEuYnIiLCJ1dGkiOiJVNG5oQ0VSdGdVZU12RUlKUXRJaUFBIiwidmVyIjoiMS4wIiwid2lkcyI6WyJiNzlmYmY0ZC0zZWY5LTQ2ODktODE0My03NmIxOTRlODU1MDkiXSwieG1zX2NjIjpbIkNQMSJdLCJ4bXNfZnRkIjoiSnpLckRZeVpydU1FT3k0UHJRWW1MNUJ2WVNvTmp5bG5kRTFmVmZkSkJPa0JkWE56YjNWMGFDMWtjMjF6IiwieG1zX2lkcmVsIjoiMjAgMSIsInhtc19zc20iOiIxIiwieG1zX3N0Ijp7InN1YiI6ImoyeS05b0NleWdEeTJqVUI2QUZSTjluVDk0RVAxNWgtbDc1WFBaTHpjZnMifSwieG1zX3RjZHQiOjE0NDM0ODcxNTV9.ZJXmjXXXFX0PMiGexOEoJ-BiatTRaCeL0FBeoFbvUCaVDtCv2cRUE1yxO_82Rdhn3JTcjIb7uQ5GokkA19gM65D_aOKdelxJUP7ADlW-h5IInoPX_fISnZzpTF_gYWF0e4toGQP0RHCPuXOwrvPVJnMtRJvMf0rSuBgpvL2DQnLvFC5QMzlHRLkJamcCx3CzQ4hQ4SiRZU5BB1o8-TTFUK29hcLhPv-V0FsDPA2hcD8flTP70Ivvp1Ir17Q3U9Y-FS_MXmieYs21J6Sz77rNjwQJ2kVZ0XM70aMolR2g9tZ3In8ZQueLkzTTddBjPxaUda8He_cyftaoi6lK6rvpUA"
+
+ user_client = UserAPIClient()
+
+ user_info = user_client.authenticate_user(token=user_token)
+
+ print(user_info)
\ No newline at end of file
diff --git a/tests/modules/create_booking/app/test_create_booking_controller.py b/tests/modules/create_booking/app/test_create_booking_controller.py
index c349251..610992c 100644
--- a/tests/modules/create_booking/app/test_create_booking_controller.py
+++ b/tests/modules/create_booking/app/test_create_booking_controller.py
@@ -17,13 +17,14 @@ def test_create_booking_controller(self):
"end_date": 1630003600,
"court_number": 1,
"sport": "Tennis",
- "materials": ["racket", "balls"]
+ "materials": ["racket", "balls"],
+ "type": "Training"
},
headers={
"user_from_authorizer": {
"displayName": 'Lebron James',
"mail": 'lbj@maua.br',
- "id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ "user_id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
}
}
)
@@ -48,7 +49,7 @@ def test_create_booking_controller_missing_start_date(self):
"user_from_authorizer": {
"displayName": 'Lebron James',
"mail": 'lbj@maua.br',
- "id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ "user_id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
}
})
@@ -72,7 +73,7 @@ def test_create_booking_controller_wrong_type_start_date(self):
"user_from_authorizer": {
"displayName": 'Lebron James',
"mail": 'lbj@maua.br',
- "id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ "user_id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
}
})
@@ -95,7 +96,7 @@ def test_create_booking_controller_missing_end_date(self):
"user_from_authorizer": {
"displayName": 'Lebron James',
"mail": 'lbj@maua.br',
- "id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ "user_id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
}
})
@@ -119,7 +120,7 @@ def test_create_booking_controller_wrong_type_end_date(self):
"user_from_authorizer": {
"displayName": 'Lebron James',
"mail": 'lbj@maua.br',
- "id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ "user_id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
}
})
@@ -143,7 +144,7 @@ def test_create_booking_wrong_type_court_number(self):
"user_from_authorizer": {
"displayName": 'Lebron James',
"mail": 'lbj@maua.br',
- "id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ "user_id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
}
})
@@ -166,7 +167,7 @@ def test_create_booking_controller_missing_court_number(self):
"user_from_authorizer": {
"displayName": 'Lebron James',
"mail": 'lbj@maua.br',
- "id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ "user_id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
}
})
@@ -189,7 +190,7 @@ def test_create_booking_controller_missing_sport(self):
"user_from_authorizer": {
"displayName": 'Lebron James',
"mail": 'lbj@maua.br',
- "id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ "user_id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
}
})
@@ -213,7 +214,7 @@ def test_create_booking_controller_wrong_type_sport(self):
"user_from_authorizer": {
"displayName": 'Lebron James',
"mail": 'lbj@maua.br',
- "id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ "user_id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
}
})
@@ -236,7 +237,7 @@ def test_create_booking_controller_missing_materials(self):
"user_from_authorizer": {
"displayName": 'Lebron James',
"mail": 'lbj@maua.br',
- "id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ "user_id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
}
})
@@ -260,7 +261,7 @@ def test_create_booking_controller_wrong_type_materials(self):
"user_from_authorizer": {
"displayName": 'Lebron James',
"mail": 'lbj@maua.br',
- "id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ "user_id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
}
})
@@ -279,12 +280,13 @@ def test_create_booking_controller_wrong_type_inside_list(self):
"end_date": 1630003600,
"court_number": 1,
"sport": "Tennis",
- "materials": ["racket", 1]
+ "materials": ["racket", 1],
+ "type": 'Common'
}, headers={
"user_from_authorizer": {
"displayName": 'Lebron James',
"mail": 'lbj@maua.br',
- "id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ "user_id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
}
})
diff --git a/tests/modules/create_booking/app/test_create_booking_presenter.py b/tests/modules/create_booking/app/test_create_booking_presenter.py
index 0a6ea41..b236058 100644
--- a/tests/modules/create_booking/app/test_create_booking_presenter.py
+++ b/tests/modules/create_booking/app/test_create_booking_presenter.py
@@ -28,11 +28,12 @@ def test_create_booking_presenter(self):
"apiId": "",
"authentication": None,
"authorizer": {
- "user": {
- "displayName": 'Lebron James',
- "mail": 'lbj@maua.br',
- "id": 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
- }
+ "user": json.dumps({
+ "user": {
+ "user_id": "c8435c66-13a4-4641-9d54-773b4b8ccc98",
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -49,7 +50,7 @@ def test_create_booking_presenter(self):
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
- "body": '{"start_date": 1610617200, "end_date": 1610620800, "court_number": 1, "sport": "Tennis", "materials": ["ball", "racket"]}',
+ "body": {'start_date': 1610617200, 'end_date': 1610620800, 'court_number': 1, 'sport': 'Tennis', 'materials': ['ball', 'racket'], 'type': 'Training'},
"pathParameters": None,
"isBase64Encoded": None,
"stageVariables": None
@@ -58,5 +59,5 @@ def test_create_booking_presenter(self):
response = lambda_handler(event, None)
print(response)
- assert response['statusCode'] == 201
- assert json.loads(response['body'])['message'] == 'Booking created successfully'
\ No newline at end of file
+ assert json.loads(response['body'])['message'] == 'Booking created successfully'
+ assert response['statusCode'] == 201
\ No newline at end of file
diff --git a/tests/modules/create_booking/app/test_create_booking_usecase.py b/tests/modules/create_booking/app/test_create_booking_usecase.py
index 2781dee..84caa90 100644
--- a/tests/modules/create_booking/app/test_create_booking_usecase.py
+++ b/tests/modules/create_booking/app/test_create_booking_usecase.py
@@ -3,6 +3,7 @@
from src.modules.create_booking.app.create_booking_usecase import CreateBookingUsecase
from src.shared.domain.entities.booking import Booking
from src.shared.domain.enums.sport import SPORT
+from src.shared.domain.enums.type import BOOKING_TYPE
from src.shared.helpers.errors.usecase_errors import InvalidSchedule
from src.shared.infra.repositories.booking_repository_mock import BookingRepositoryMock
@@ -18,7 +19,8 @@ def test_create_booking_usecase(self):
sport=SPORT.TENNIS,
user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
materials=['Raquete', 'Bola', 'Rede', 'Tenis'],
- booking_id='c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ booking_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
+ booking_type=BOOKING_TYPE.TRAINING
)
booking_repository = BookingRepositoryMock()
@@ -31,7 +33,8 @@ def test_create_booking_usecase(self):
court_number=1,
sport="Tennis",
user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
- materials=['Raquete', 'Bola', 'Rede', 'Tenis']
+ materials=['Raquete', 'Bola', 'Rede', 'Tenis'],
+ booking_type='Training'
)
assert response is not None
@@ -41,6 +44,7 @@ def test_create_booking_usecase(self):
assert response.sport == booking.sport
assert response.user_id == booking.user_id
assert response.booking_id != booking.booking_id
+ assert response.booking_type == booking.booking_type
def test_create_booking_usecase_invalid_sport(self):
@@ -56,7 +60,8 @@ def test_create_booking_usecase_invalid_sport(self):
court_number=1,
sport="Invalid sport but string",
user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
- materials=['Raquete', 'Bola', 'Rede', 'Tenis']
+ materials=['Raquete', 'Bola', 'Rede', 'Tenis'],
+ booking_type='Training'
)
def test_create_booking_usecase_invalid_materials(self):
@@ -73,10 +78,11 @@ def test_create_booking_usecase_invalid_materials(self):
court_number=1,
sport="Tennis",
user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
- materials=[1, 2, 3]
+ materials=[1, 2, 3],
+ booking_type='Training'
)
- def test_create_booking_usecase_invalid_schedule(self):
+ def test_create_booking_usecase_invalid_schedule_overlap(self):
with pytest.raises(InvalidSchedule) as e:
@@ -90,5 +96,57 @@ def test_create_booking_usecase_invalid_schedule(self):
court_number=1,
sport="Tennis",
user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
- materials=["colete"]
+ materials=["colete"],
+ booking_type='Training'
+ )
+
+ assert e.value == "Court is already booked for the selected time slot or has to have 15 min tolerance"
+
+
+ def test_create_booking_usecase_invalid_schedule_15min(self):
+
+ with pytest.raises(InvalidSchedule) as e:
+
+ booking_repository = BookingRepositoryMock()
+
+ usecase = CreateBookingUsecase(repo=booking_repository)
+
+ booking_repository.create_booking(
+ booking=Booking(
+ start_date=20000000,
+ end_date=30000000,
+ court_number=5,
+ sport=SPORT.FUTSAL,
+ user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
+ materials=['Bola', 'Chuteira'],
+ booking_id='ddd35c66-13a4-4641-9d54-773b4b8ccc98',
+ booking_type=BOOKING_TYPE.TRAINING
+ )
+ )
+
+ response = usecase(
+ start_date=10000000,
+ end_date=19100001, #15 minutos de intolerância na criação
+ court_number=5,
+ sport=SPORT.FUTSAL,
+ user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
+ materials=['Bola', 'Chuteira'],
+ booking_type='Training'
)
+
+ assert e.value == "Court is already booked for the selected time slot or has to have 15 min tolerance"
+
+ with pytest.raises(InvalidSchedule) as e2:
+
+
+ response2 = usecase(
+ start_date=30899999, # 15 minutos de intolerância na criação
+ end_date=40000000,
+ court_number=5,
+ sport=SPORT.FUTSAL,
+ user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
+ materials=['Bola', 'Chuteira'],
+ booking_type='Training'
+ )
+
+ assert e2.value == "Court is already booked for the selected time slot or has to have 15 min tolerance"
diff --git a/tests/modules/create_booking/app/test_create_booking_viewmodel.py b/tests/modules/create_booking/app/test_create_booking_viewmodel.py
index 9783677..ceb50b0 100644
--- a/tests/modules/create_booking/app/test_create_booking_viewmodel.py
+++ b/tests/modules/create_booking/app/test_create_booking_viewmodel.py
@@ -1,6 +1,7 @@
from src.modules.create_booking.app.create_booking_viewmodel import CreateBookingViewmodel
from src.shared.domain.entities.booking import Booking
from src.shared.domain.enums.sport import SPORT
+from src.shared.domain.enums.type import BOOKING_TYPE
class TestCreateBookingViewmodel:
@@ -14,7 +15,8 @@ def test_create_booking_viewmodel(self):
sport=SPORT.TENNIS,
user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
booking_id='b1d3bebf-dc0d-4fc1-861c-506a40cc2925',
- materials=['Raquete', 'Bola', 'Rede', 'Tenis']
+ materials=['Raquete', 'Bola', 'Rede', 'Tenis'],
+ booking_type=BOOKING_TYPE.TRAINING
)
expected = {
@@ -25,7 +27,8 @@ def test_create_booking_viewmodel(self):
"sport": "Tennis",
"user_id": "c8435c66-13a4-4641-9d54-773b4b8ccc98",
"booking_id": "b1d3bebf-dc0d-4fc1-861c-506a40cc2925",
- "materials": ["Raquete", "Bola", "Rede", "Tenis"]
+ "materials": ["Raquete", "Bola", "Rede", "Tenis"],
+ "type": 'Training'
},
"message": "Booking created successfully"
}
diff --git a/tests/modules/create_court/app/test_create_court_controller.py b/tests/modules/create_court/app/test_create_court_controller.py
index 5932464..df2de6a 100644
--- a/tests/modules/create_court/app/test_create_court_controller.py
+++ b/tests/modules/create_court/app/test_create_court_controller.py
@@ -12,7 +12,10 @@ def test_create_court_controller(self):
"number": 7,
"status": "AVAILABLE",
"is_field": False,
- "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/"
+ "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
response = controller(request)
@@ -30,7 +33,10 @@ def test_create_court_controller_missing_number(self):
request = HttpRequest(body={
"status": "AVAILABLE",
"is_field": False,
- "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/"
+ "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
response = controller(request)
@@ -45,7 +51,10 @@ def test_create_court_controller_with_missing_status(self):
request = HttpRequest(body={
"number": 7,
"is_field": False,
- "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/"
+ "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
response = controller(request)
@@ -60,7 +69,10 @@ def test_create_court_controller_wrong_type_number(self):
"number": "cavalo",
"status": "AVAILABLE",
"is_field": False,
- "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/"
+ "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
reponse = controller(request)
@@ -76,7 +88,10 @@ def test_create_court_controller_with_wrong_type_status(self):
"number": 7,
"status": 123,
"is_field": False,
- "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/"
+ "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
response = controller(request)
@@ -91,7 +106,10 @@ def test_create_court_controllerwith_duplicated_item(self):
"number": 1,
"status": "AVAILABLE",
"is_field": False,
- "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/"
+ "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
response = controller(request)
@@ -107,7 +125,10 @@ def test_create_court_controller_number_entity_error(self):
"number": 0,
"status": "AVAILABLE",
"is_field": False,
- "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/"
+ "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
reponse = controller(request)
@@ -123,7 +144,10 @@ def test_create_court_controller_status_entity_error(self):
"number": 7,
"status": "INVALID",
"is_field": False,
- "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/"
+ "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
response = controller(request)
diff --git a/tests/modules/create_court/app/test_create_court_presenter.py b/tests/modules/create_court/app/test_create_court_presenter.py
index bf74fa5..eb05390 100644
--- a/tests/modules/create_court/app/test_create_court_presenter.py
+++ b/tests/modules/create_court/app/test_create_court_presenter.py
@@ -25,6 +25,12 @@ def test_create_court_presenter(self):
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ "role": "ADMIN",
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -77,6 +83,12 @@ def test_create_court_presenter_missing_number(self):
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ "role": "ADMIN",
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
diff --git a/tests/modules/create_court/app/test_create_court_usecase.py b/tests/modules/create_court/app/test_create_court_usecase.py
index f81659f..70993b2 100644
--- a/tests/modules/create_court/app/test_create_court_usecase.py
+++ b/tests/modules/create_court/app/test_create_court_usecase.py
@@ -1,7 +1,7 @@
import pytest
from src.modules.create_court.app.create_court_usecase import CreateCourtUsecase
from src.shared.infra.repositories.reservation_repository_mock import ReservationRepositoryMock
-from src.shared.helpers.errors.usecase_errors import DuplicatedItem
+from src.shared.helpers.errors.usecase_errors import DuplicatedItem, ForbiddenAction
from src.shared.domain.enums.status_enum import STATUS
class TestCreateCourtUsecase:
@@ -13,7 +13,8 @@ def test_create_court_usecase(self):
number= 8,
status= STATUS.AVAILABLE,
is_field= False,
- photo = "https://super.abril.com.br/mundo-estranho/os-poneis-sao-cavalos-anoes"
+ photo = "https://super.abril.com.br/mundo-estranho/os-poneis-sao-cavalos-anoes",
+ role="ADMIN"
)
assert repo.courts[-1] == court
@@ -28,7 +29,7 @@ def test_create_court_usecase_duplicated_item(self):
usecase = CreateCourtUsecase(repo=repo)
with pytest.raises(DuplicatedItem):
- court = usecase(number= 2, status= STATUS.AVAILABLE, is_field= False, photo = None)
+ court = usecase(number= 2, status= STATUS.AVAILABLE, is_field= False, photo = None, role="ADMIN")
def test_create_court_usecase_no_photo(self):
repo = ReservationRepositoryMock()
@@ -38,11 +39,26 @@ def test_create_court_usecase_no_photo(self):
number= 7,
status= STATUS.UNAVAILABLE,
is_field = False,
- photo = None
+ photo = None,
+ role="ADMIN"
)
assert court.photo is None
assert repo.courts[-1] == court
assert court.number == 7
+ def test_create_court_usecase_not_admin(self):
+
+ repo = ReservationRepositoryMock()
+ Usecase = CreateCourtUsecase(repo=repo)
+
+ with pytest.raises(ForbiddenAction):
+ court = Usecase(
+ number= 7,
+ status= STATUS.UNAVAILABLE,
+ is_field = False,
+ photo = None,
+ role="STUDENT"
+ )
+
\ No newline at end of file
diff --git a/tests/modules/delete_booking/app/test_delete_booking_controller.py b/tests/modules/delete_booking/app/test_delete_booking_controller.py
index 226724f..e25446c 100644
--- a/tests/modules/delete_booking/app/test_delete_booking_controller.py
+++ b/tests/modules/delete_booking/app/test_delete_booking_controller.py
@@ -3,19 +3,18 @@
from src.shared.helpers.external_interfaces.http_models import HttpRequest
from src.shared.infra.repositories.booking_repository_mock import BookingRepositoryMock
-
class TestDeleteBookingController:
def test_delete_booking_controller(self):
repo = BookingRepositoryMock()
usecase = DeleteBookingUsecase(repo=repo)
controller = DeleteBookingController(usecase=usecase)
- request = HttpRequest(body={
- "booking_id": 'b1d3bebf-dc0d-4fc1-861c-506a40cc2925'
- }, headers={
- 'user_from_authorizer': {
- 'id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
- 'displayName': 'John Doe',
- 'mail': 'JD@maua.br'
+ request = HttpRequest(body= {
+ "booking_id": 'b1d3bebf-dc0d-4fc1-861c-506a40cc2925',
+ "user_from_authorizer": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
}
})
@@ -25,15 +24,15 @@ def test_delete_booking_controller(self):
def test_delete_booking_controller_missing_booking_id(self):
repo = BookingRepositoryMock()
- usecase = DeleteBookingUsecase(repo=repo)
+ usecase = DeleteBookingUsecase(repo= repo)
controller = DeleteBookingController(usecase=usecase)
request = HttpRequest(body={
"booking_id": None
}, headers={
'user_from_authorizer': {
- 'id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
- 'displayName': 'John Doe',
- 'mail': 'JD@maua.br'
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
}
})
@@ -43,18 +42,19 @@ def test_delete_booking_controller_missing_booking_id(self):
def test_delete_booking_controller_booking_id_entity_error(self):
repo = BookingRepositoryMock()
- usecase = DeleteBookingUsecase(repo=repo)
+ usecase = DeleteBookingUsecase(repo= repo)
controller = DeleteBookingController(usecase=usecase)
request = HttpRequest(body={
"booking_id": 0
}, headers={
'user_from_authorizer': {
- 'id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
- 'displayName': 'John Doe',
- 'mail': 'JD@maua.br'
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
}
})
-
+
reponse = controller(request)
assert reponse.status_code == 400
assert reponse.body == "Field booking_id is not valid"
@@ -67,9 +67,10 @@ def test_delete_booking_controller_wrong_type_parameter(self):
"booking_id": "not an id"
}, headers={
'user_from_authorizer': {
- 'id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
- 'displayName': 'John Doe',
- 'mail': 'JD@maua.br'
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
}
})
@@ -85,9 +86,10 @@ def test_delete_booking_controller_not_found(self):
"booking_id": 'b1d3bebf-dc0d-4fc1-861c-506a40cc2926'
}, headers={
'user_from_authorizer': {
- 'id': 'c8435c66-23a4-4641-9d54-773b4b8ccc99',
- 'displayName': 'John Doe',
- 'mail': 'JD@maua.br'
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
}
})
@@ -103,10 +105,11 @@ def test_delete_bookings_controller_forbidden(self):
"booking_id": 'b1d3bebf-dc0d-4fc1-861c-506a40cc2925'
}, headers={
'user_from_authorizer': {
- 'id': 'c8435c66-23a4-4641-9d54-773b4b8ccc99',
- 'displayName': 'John Doe',
- 'mail': 'JD@maua.br'
- }
+ 'user_id': '2f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
})
response = controller(request)
diff --git a/tests/modules/delete_booking/app/test_delete_booking_presenter.py b/tests/modules/delete_booking/app/test_delete_booking_presenter.py
index c81563e..a7d296a 100644
--- a/tests/modules/delete_booking/app/test_delete_booking_presenter.py
+++ b/tests/modules/delete_booking/app/test_delete_booking_presenter.py
@@ -25,11 +25,15 @@ def test_delete_booking_presenter(self):
"apiId": "",
"authentication": None,
"authorizer": {
- 'user': {
- 'id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
- 'displayName': 'John Doe',
- 'mail': 'JD@maua.br'
- }
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -46,13 +50,16 @@ def test_delete_booking_presenter(self):
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
- "body": '{"booking_id": "b1d3bebf-dc0d-4fc1-861c-506a40cc2925"}',
+ "body": {
+ "booking_id": "b1d3bebf-dc0d-4fc1-861c-506a40cc2925"
+ },
"pathParameters": None,
"isBase64Encoded": None,
"stageVariables": None
}
response = lambda_handler(event, None)
+
print(response)
assert response['statusCode'] == 200
assert json.loads(response['body'])['message'] == 'the booking was deleted'
@@ -79,11 +86,15 @@ def test_delete_booking_presenter_missing_booking_id(self):
"apiId": "",
"authentication": None,
"authorizer": {
- 'user': {
- 'id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
- 'displayName': 'John Doe',
- 'mail': 'JD@maua.br'
- }
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -133,11 +144,15 @@ def test_delete_booking_not_found(self):
"apiId": "",
"authentication": None,
"authorizer": {
- 'user': {
- 'id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
- 'displayName': 'John Doe',
- 'mail': 'JD@maua.br'
- }
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -187,11 +202,15 @@ def test_delete_booking_wrong_type(self):
"apiId": "",
"authentication": None,
"authorizer": {
- 'user': {
- 'id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
- 'displayName': 'John Doe',
- 'mail': 'JD@maua.br'
- }
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
diff --git a/tests/modules/delete_booking/app/test_delete_booking_usecase.py b/tests/modules/delete_booking/app/test_delete_booking_usecase.py
index 7fc7a34..b750459 100644
--- a/tests/modules/delete_booking/app/test_delete_booking_usecase.py
+++ b/tests/modules/delete_booking/app/test_delete_booking_usecase.py
@@ -1,34 +1,76 @@
import pytest
-from src.shared.helpers.errors.domain_errors import EntityError
+from src.shared.helpers.errors.usecase_errors import DuplicatedItem, ForbiddenAction
from src.modules.delete_booking.app.delete_booking_usecase import DeleteBookingUsecase
from src.shared.infra.repositories.booking_repository_mock import BookingRepositoryMock
from src.shared.helpers.errors.usecase_errors import NoItemsFound
+from src.shared.helpers.errors.domain_errors import EntityError
class Test_DeleteBookingUsecase:
def test_delete_booking_usecase(self):
repo = BookingRepositoryMock()
usecase = DeleteBookingUsecase(repo=repo)
len_before = len(repo.bookings)
-
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
booking = usecase(booking_id='b1d3bebf-dc0d-4fc1-861c-506a40cc2925',
- user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98')
+ user=user)
+
+ assert len(repo.bookings) == len_before - 1
+
+ def test_delete_booking_usecase_admin(self):
+ repo = BookingRepositoryMock()
+ usecase = DeleteBookingUsecase(repo=repo)
+ len_before = len(repo.bookings)
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
+ booking = usecase(booking_id='b1d3bebf-dc0d-4fc1-861c-506a40cc2925', user=user)
assert len(repo.bookings) == len_before - 1
+ def test_delete_booking_usecase_invalid_student(self):
+ repo = BookingRepositoryMock()
+ usecase = DeleteBookingUsecase(repo=repo)
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
+ with pytest.raises(ForbiddenAction):
+ usecase(booking_id='b2d3bebf-dc0d-4fc1-861c-506a40cc2925', user=user)
+
def test_delete_booking_usecase_no_items_found(self):
repo = BookingRepositoryMock()
usecase = DeleteBookingUsecase(repo=repo)
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
with pytest.raises(NoItemsFound):
- booking = usecase(booking_id='b1d3bebf-dc0d-4fc1-861c-506a40cc2926',
- user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98')
-
+ booking = usecase(booking_id='b1d3bebf-dc0d-4fc1-861c-506a40cc2926', user = user)
+
def test_delete_booking_usecase_invalid_booking_id(self):
repo = BookingRepositoryMock()
usecase = DeleteBookingUsecase(repo=repo)
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
with pytest.raises(EntityError):
- usecase(booking_id=-1,
- user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98')
-
- with pytest.raises(EntityError):
- usecase(booking_id=None,
- user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98')
\ No newline at end of file
+ usecase(booking_id=-1, user=user)
+
\ No newline at end of file
diff --git a/tests/modules/delete_booking/app/test_delete_booking_viewmodel.py b/tests/modules/delete_booking/app/test_delete_booking_viewmodel.py
index a8bab9a..fe074a8 100644
--- a/tests/modules/delete_booking/app/test_delete_booking_viewmodel.py
+++ b/tests/modules/delete_booking/app/test_delete_booking_viewmodel.py
@@ -8,8 +8,13 @@ class Test_DeleteBookingViewModel:
def test_delete_booking_viewmodel(self):
repo = BookingRepositoryMock()
usecase = DeleteBookingUsecase(repo=repo)
- booking = usecase(booking_id=repo.bookings[0].booking_id,
- user_id=repo.bookings[0].user_id)
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+ booking = usecase(booking_id=repo.bookings[0].booking_id, user=user)
viewmodel = DeleteBookingViewModel(booking=booking).to_dict()
expected = {
@@ -18,9 +23,10 @@ def test_delete_booking_viewmodel(self):
'end_date': 1634583365000,
'court_number': 1,
'sport': 'Tennis',
- 'user_id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
'booking_id': 'b1d3bebf-dc0d-4fc1-861c-506a40cc2925',
- 'materials': ['Raquete', 'Bola', 'Rede', 'Tenis']
+ 'materials': ['Raquete', 'Bola', 'Rede', 'Tenis'],
+ "type": 'Training'
},
'message': 'the booking was deleted'
}
diff --git a/tests/modules/delete_court/app/test_delete_court_controller.py b/tests/modules/delete_court/app/test_delete_court_controller.py
index bdca3bf..c59da3b 100644
--- a/tests/modules/delete_court/app/test_delete_court_controller.py
+++ b/tests/modules/delete_court/app/test_delete_court_controller.py
@@ -9,7 +9,15 @@ def test_delete_court_controller(self):
usecase = DeleteCourtUsecase(repo= repo)
controller = DeleteCourtController(usecase=usecase)
request = HttpRequest(body= {
- "number": 2
+ "number": 2,
+ "user_from_authorizer": {
+ "name": "Dummy",
+ "email": "admin@maua.br",
+ "user_id": "user_id",
+ "ra": None,
+ "role": "ADMIN",
+ "confirm_user": False
+ }
})
response = controller(request)
@@ -22,7 +30,15 @@ def test_delete_court_controller_missing_number(self):
usecase = DeleteCourtUsecase(repo= repo)
controller = DeleteCourtController(usecase=usecase)
request = HttpRequest(body={
- "number": None
+ "number": None,
+ "user_from_authorizer": {
+ "name": "Dummy",
+ "email": "admin@maua.br",
+ "user_id": "user_id",
+ "ra": None,
+ "role": "ADMIN",
+ "confirm_user": False
+ }
})
response = controller(request)
@@ -34,7 +50,15 @@ def test_delete_court_controller_number_entity_error(self):
usecase = DeleteCourtUsecase(repo= repo)
controller = DeleteCourtController(usecase=usecase)
request = HttpRequest(body={
- "number": 0
+ "number": 0,
+ "user_from_authorizer": {
+ "name": "Dummy",
+ "email": "admin@maua.br",
+ "user_id": "user_id",
+ "ra": None,
+ "role": "ADMIN",
+ "confirm_user": False
+ }
})
reponse = controller(request)
@@ -46,19 +70,35 @@ def test_delete_court_controller_wrong_type_parameter(self):
usecase = DeleteCourtUsecase(repo=repo)
controller = DeleteCourtController(usecase=usecase)
request = HttpRequest(body={
- "number": "wrong_type"
+ "number": "wrong_type",
+ "user_from_authorizer": {
+ "name": "Dummy",
+ "email": "admin@maua.br",
+ "user_id": "user_id",
+ "ra": None,
+ "role": "ADMIN",
+ "confirm_user": False
+ }
})
response = controller(request)
assert response.status_code == 400
- assert response.body == "Field number is not valid"
+ assert "Field number isn't in the right type" in response.body
def test_delete_court_controller_not_found(self):
repo = ReservationRepositoryMock()
usecase = DeleteCourtUsecase(repo=repo)
controller = DeleteCourtController(usecase=usecase)
request = HttpRequest(body={
- "number": 10
+ "number": 10,
+ "user_from_authorizer": {
+ "name": "Dummy",
+ "email": "admin@maua.br",
+ "user_id": "user_id",
+ "ra": None,
+ "role": "ADMIN",
+ "confirm_user": False
+ }
})
response = controller(request)
diff --git a/tests/modules/delete_court/app/test_delete_court_presenter.py b/tests/modules/delete_court/app/test_delete_court_presenter.py
index a14b441..e9aa872 100644
--- a/tests/modules/delete_court/app/test_delete_court_presenter.py
+++ b/tests/modules/delete_court/app/test_delete_court_presenter.py
@@ -18,13 +18,22 @@ def test_delete_court_presenter(self):
"header2": "value1,value2"
},
"queryStringParameters": {
- "parameter1": "1"
+ "number": "1"
},
"requestContext": {
"accountId": "123456789012",
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'ADMIN'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -41,7 +50,7 @@ def test_delete_court_presenter(self):
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
- "body": '{"number": 1}',
+ "body": {},
"pathParameters": None,
"isBase64Encoded": None,
"stageVariables": None
@@ -74,6 +83,15 @@ def test_delete_court_presenter_missing_number(self):
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'ADMIN'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -90,7 +108,7 @@ def test_delete_court_presenter_missing_number(self):
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
- "body": '{}',
+ "body": {},
"pathParameters": None,
"isBase64Encoded": None,
"stageVariables": None
@@ -116,13 +134,22 @@ def test_delete_court_not_found(self):
"header2": "value1,value2"
},
"queryStringParameters": {
- "parameter1": "1"
+ "number": "10"
},
"requestContext": {
"accountId": "123456789012",
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'ADMIN'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -139,7 +166,7 @@ def test_delete_court_not_found(self):
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
- "body": '{"number": 10}',
+ "body": {},
"pathParameters": None,
"isBase64Encoded": None,
"stageVariables": None
@@ -165,13 +192,22 @@ def test_delete_court_wrong_type(self):
"header2": "value1,value2"
},
"queryStringParameters": {
- "parameter1": "1"
+ "number": "wrong_type"
},
"requestContext": {
"accountId": "123456789012",
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'ADMIN'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -188,7 +224,7 @@ def test_delete_court_wrong_type(self):
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
- "body": '{"number": "wrong_type"}',
+ "body": {},
"pathParameters": None,
"isBase64Encoded": None,
"stageVariables": None
@@ -197,4 +233,4 @@ def test_delete_court_wrong_type(self):
response = lambda_handler(event, None)
assert response['statusCode'] == 400
- assert json.loads(response['body']) == 'Field number is not valid'
\ No newline at end of file
+ assert "Field number isn't in the right type" in json.loads(response['body'])
\ No newline at end of file
diff --git a/tests/modules/delete_court/app/test_delete_court_usecase.py b/tests/modules/delete_court/app/test_delete_court_usecase.py
index a58d416..40ab97d 100644
--- a/tests/modules/delete_court/app/test_delete_court_usecase.py
+++ b/tests/modules/delete_court/app/test_delete_court_usecase.py
@@ -6,16 +6,23 @@
from src.shared.helpers.errors.domain_errors import EntityError
from src.modules.delete_court.app.delete_court_usecase import DeleteCourtUsecase
from src.shared.infra.repositories.reservation_repository_mock import ReservationRepositoryMock
-from src.shared.helpers.errors.usecase_errors import NoItemsFound
+from src.shared.helpers.errors.usecase_errors import NoItemsFound, ForbiddenAction
from src.shared.domain.repositories.reservation_repository_interface import IReservationRepository
class Test_DeleteCourtUsecase:
+
+ def test_delete_court_usecase_forbidden(self):
+ repo = ReservationRepositoryMock()
+ usecase = DeleteCourtUsecase(repo=repo)
+ with pytest.raises(ForbiddenAction):
+ court = usecase(number=1, role="STUDENT")
+
def test_delete_court_usecase(self):
repo = ReservationRepositoryMock()
usecase = DeleteCourtUsecase(repo=repo)
len_before = len(repo.courts)
- court = usecase(number=1)
+ court = usecase(number=1, role="ADMIN")
assert len(repo.courts) == len_before - 1
assert court.number == 1
@@ -23,16 +30,25 @@ def test_delete_court_usecase_no_items_found(self):
repo = ReservationRepositoryMock()
usecase = DeleteCourtUsecase(repo=repo)
with pytest.raises(NoItemsFound):
- court = usecase(number=10)
+ court = usecase(number=10, role="ADMIN")
def test_delete_court_usecase_invalid_number(self):
repo = ReservationRepositoryMock()
usecase = DeleteCourtUsecase(repo=repo)
with pytest.raises(EntityError):
- usecase(number=-1)
+ usecase(number=-1, role="ADMIN")
with pytest.raises(EntityError):
- usecase(number=None)
+ usecase(number=None, role="ADMIN")
+
+ def test_delete_court_usecase_not_admin(self):
+ repo = ReservationRepositoryMock()
+ usecase = DeleteCourtUsecase(repo=repo)
+
+ with pytest.raises(ForbiddenAction):
+ usecase(number=1, role="STUDENT")
+
+ assert repo.get_court(1) != None
\ No newline at end of file
diff --git a/tests/modules/delete_court/app/test_delete_court_viewmodel.py b/tests/modules/delete_court/app/test_delete_court_viewmodel.py
index 6abda91..a468098 100644
--- a/tests/modules/delete_court/app/test_delete_court_viewmodel.py
+++ b/tests/modules/delete_court/app/test_delete_court_viewmodel.py
@@ -8,7 +8,7 @@ class Test_DeleteCourtViewModel:
def test_delete_court_viewmodel(self):
repo = ReservationRepositoryMock()
usecase = DeleteCourtUsecase(repo=repo)
- court = usecase(number=repo.courts[0].number)
+ court = usecase(number=repo.courts[0].number, role="ADMIN")
viewmodel = DeleteCourtViewModel(court=court).to_dict()
expected = {
diff --git a/tests/modules/generate_report/__init__.py b/tests/modules/generate_report/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/modules/generate_report/app/__init__.py b/tests/modules/generate_report/app/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/modules/generate_report/app/test_generate_report_aggregator.py b/tests/modules/generate_report/app/test_generate_report_aggregator.py
new file mode 100644
index 0000000..6b2fcd3
--- /dev/null
+++ b/tests/modules/generate_report/app/test_generate_report_aggregator.py
@@ -0,0 +1,22 @@
+import pytest
+
+from src.modules.generate_report.app.generate_report_aggregator import GenerateReportAggregator
+from src.modules.generate_report.app.generate_report_extractor import GenerateReportExtractor
+from src.shared.infra.repositories.booking_repository_dynamo import BookingRepositoryDynamo
+
+
+class TestGenerateReportAggregator:
+
+ @pytest.mark.skip("Can't run test in gh actions")
+ def test_generate_report_aggregator(self):
+
+ repo = BookingRepositoryDynamo()
+
+ # Arrange
+ extractor = GenerateReportExtractor(booking_repository=repo)
+ aggregator = GenerateReportAggregator(extractor)
+
+ # Act
+ result = aggregator(1577836800, 1767225600)
+
+ print(result)
\ No newline at end of file
diff --git a/tests/modules/generate_report/app/test_generate_report_presenter.py b/tests/modules/generate_report/app/test_generate_report_presenter.py
new file mode 100644
index 0000000..47c499b
--- /dev/null
+++ b/tests/modules/generate_report/app/test_generate_report_presenter.py
@@ -0,0 +1,37 @@
+import pytest
+
+from src.modules.generate_report.app.generate_report_aggregator import GenerateReportAggregator
+from src.modules.generate_report.app.generate_report_extractor import GenerateReportExtractor
+from src.modules.generate_report.app.generate_report_presenter import lambda_handler
+from src.modules.generate_report.app.generate_report_transformer import GenerateReportTransformer
+from src.shared.infra.repositories.booking_repository_dynamo import BookingRepositoryDynamo
+
+
+class TestGenerateReportPresenter:
+
+ #WONT WORK WITH CURRENT MOCK, ALL DATES ARE OUTDATED AND DO NOT MATCH WITH CURRENT YEAR
+
+ @pytest.mark.skip("Can't run test in github actions")
+ def test_generate_report_presenter(self):
+
+ event_from_event_bridge = {
+ "version": "0",
+ "id": "12345678-1234-1234-1234-123456789012",
+ "detail-type": "EC2 Instance State-change Notification",
+ "source": "aws.ec2",
+ "account": "123456789012",
+ "time": "2023-11-11T12:00:00Z",
+ "region": "us-east-1",
+ "resources": [
+ "arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0"
+ ],
+ "detail": {
+ "instance-id": "i-1234567890abcdef0",
+ "state": "running"
+ }
+ }
+
+ sender = lambda_handler(event_from_event_bridge, None)
+
+ #WONT WORK WITH CURRENT MOCK, ALL DATES ARE OUTDATED AND DO NOT MATCH WITH CURRENT YEAR
+
diff --git a/tests/modules/generate_report/app/test_generate_report_sender.py b/tests/modules/generate_report/app/test_generate_report_sender.py
new file mode 100644
index 0000000..6c0d8ad
--- /dev/null
+++ b/tests/modules/generate_report/app/test_generate_report_sender.py
@@ -0,0 +1,38 @@
+import pytest
+
+from src.modules.generate_report.app.generate_report_aggregator import GenerateReportAggregator
+from src.modules.generate_report.app.generate_report_extractor import GenerateReportExtractor
+from src.modules.generate_report.app.generate_report_presenter import lambda_handler
+from src.modules.generate_report.app.generate_report_transformer import GenerateReportTransformer
+from src.shared.infra.repositories.booking_repository_dynamo import BookingRepositoryDynamo
+
+
+class TestGenerateReportPresenter:
+
+ @pytest.mark.skip("Can't run test in gh actions")
+
+ #WONT WORK WITH CURRENT MOCK, ALL DATES ARE OUTDATED AND DO NOT MATCH WITH CURRENT YEAR
+
+ def test_generate_report_presenter(self):
+
+ event_from_event_bridge = {
+ "version": "0",
+ "id": "12345678-1234-1234-1234-123456789012",
+ "detail-type": "EC2 Instance State-change Notification",
+ "source": "aws.ec2",
+ "account": "123456789012",
+ "time": "2023-11-11T12:00:00Z",
+ "region": "us-east-1",
+ "resources": [
+ "arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0"
+ ],
+ "detail": {
+ "instance-id": "i-1234567890abcdef0",
+ "state": "running"
+ }
+ }
+
+ sender = lambda_handler(event_from_event_bridge, None)
+
+ #WONT WORK WITH CURRENT MOCK, ALL DATES ARE OUTDATED AND DO NOT MATCH WITH CURRENT YEAR
+
diff --git a/tests/modules/generate_report/app/test_generate_report_transformer.py b/tests/modules/generate_report/app/test_generate_report_transformer.py
new file mode 100644
index 0000000..9a9e831
--- /dev/null
+++ b/tests/modules/generate_report/app/test_generate_report_transformer.py
@@ -0,0 +1,37 @@
+import platform
+import subprocess
+import pytest
+
+from src.modules.generate_report.app.generate_report_aggregator import GenerateReportAggregator
+from src.modules.generate_report.app.generate_report_extractor import GenerateReportExtractor
+from src.modules.generate_report.app.generate_report_transformer import GenerateReportTransformer
+from src.shared.infra.repositories.booking_repository_dynamo import BookingRepositoryDynamo
+import tempfile
+import os
+
+class TestGenerateReportTransformer:
+
+ @pytest.mark.skip("Can't run test in gh actions")
+ def test_generate_report_transformer(self):
+
+ repo = BookingRepositoryDynamo()
+ extractor = GenerateReportExtractor(booking_repository=repo)
+ aggregator = GenerateReportAggregator(extractor=extractor)
+
+ transformer = GenerateReportTransformer(aggregator=aggregator)
+
+ output = transformer(1577836800, 1767225600)
+
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx") as tmp_file:
+ tmp_file.write(output.read())
+ tmp_file_path = tmp_file.name
+
+ # os.startfile(tmp_file_path)
+
+ system = platform.system()
+ if system == 'Windows':
+ os.startfile(tmp_file_path)
+ elif system == 'Darwin':
+ subprocess.call(['open', tmp_file_path])
+ else:
+ subprocess.call(['xdg-open', tmp_file_path])
\ No newline at end of file
diff --git a/tests/modules/get_all_admin_bookings/__init__.py b/tests/modules/get_all_admin_bookings/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/modules/get_all_admin_bookings/app/__init__.py b/tests/modules/get_all_admin_bookings/app/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/modules/get_all_admin_bookings/app/test_get_all_admin_bookings_controller.py b/tests/modules/get_all_admin_bookings/app/test_get_all_admin_bookings_controller.py
new file mode 100644
index 0000000..04c3281
--- /dev/null
+++ b/tests/modules/get_all_admin_bookings/app/test_get_all_admin_bookings_controller.py
@@ -0,0 +1,16 @@
+from src.modules.get_all_admin_bookings.app.get_all_admin_bookings_controller import GetAllAdminBookingsController
+from src.modules.get_all_admin_bookings.app.get_all_admin_bookings_usecase import GetAllAdminBookingsUsecase
+from src.shared.helpers.external_interfaces.http_models import HttpRequest
+from src.shared.infra.repositories.booking_repository_mock import BookingRepositoryMock
+import pytest
+
+class TestGetAllAdminBookingsController:
+
+ @pytest.mark.skip("needs user endpoint url to urn")
+ def test_get_all_admin_bookings_controller(self):
+
+ repo = BookingRepositoryMock()
+ usecase = GetAllAdminBookingsUsecase(repo = repo)
+ controller = GetAllAdminBookingsController(usecase=usecase)
+ request = HttpRequest()
+ response = controller(request)
\ No newline at end of file
diff --git a/tests/modules/get_all_bookings/app/test_get_all_bookings_usecase.py b/tests/modules/get_all_bookings/app/test_get_all_bookings_usecase.py
index 236704e..e9a8013 100644
--- a/tests/modules/get_all_bookings/app/test_get_all_bookings_usecase.py
+++ b/tests/modules/get_all_bookings/app/test_get_all_bookings_usecase.py
@@ -4,7 +4,7 @@
from src.shared.domain.entities.booking import Booking
import pytest
-class Test_GetAllBookingsUsecase:
+class TestGetAllBookingsUsecase:
def test_get_all_bookings_usecase(self):
repo = BookingRepositoryMock()
usecase = GetAllBookingsUsecase(repo = repo)
@@ -15,6 +15,6 @@ def test_get_all_bookings_usecase(self):
assert bookings[0].start_date == 1634576165000
assert bookings[0].end_date == 1634583365000
assert bookings[0].sport == SPORT.TENNIS
- assert bookings[0].user_id == 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ assert bookings[0].user_id == '1f25448b-3429-4c19-8287-d9e64f17bc3a'
assert bookings[0].booking_id == 'b1d3bebf-dc0d-4fc1-861c-506a40cc2925'
assert bookings[0].materials == ['Raquete', 'Bola', 'Rede', 'Tenis']
\ No newline at end of file
diff --git a/tests/modules/get_all_bookings/app/test_get_all_bookings_viewmodel.py b/tests/modules/get_all_bookings/app/test_get_all_bookings_viewmodel.py
index a4ca114..5967770 100644
--- a/tests/modules/get_all_bookings/app/test_get_all_bookings_viewmodel.py
+++ b/tests/modules/get_all_bookings/app/test_get_all_bookings_viewmodel.py
@@ -1,5 +1,5 @@
from src.modules.get_all_bookings.app.get_all_bookings_usecase import GetAllBookingsUsecase
-from src.modules.get_all_bookings.app.get_all_bookings_viewmodel import GetAllBookingViewModel
+from src.modules.get_all_bookings.app.get_all_bookings_viewmodel import GetAllBookingsViewModel
from src.shared.infra.repositories.booking_repository_mock import BookingRepositoryMock
from src.shared.domain.entities.booking import Booking
@@ -7,57 +7,102 @@ class Test_GetAllBookingsViewmodel:
def test_get_all_bookings_viewmodel(self):
repo = BookingRepositoryMock()
usecase = GetAllBookingsUsecase(repo = repo)
- courts = usecase()
- viewmodel = GetAllBookingViewModel(courts).to_dict()
+ bookings = usecase()
+ viewmodel = GetAllBookingsViewModel(bookings).to_dict()
- excepted = {
- 'courts': [
- {
- 'start_date': 1634576165000,
- 'end_date': 1634583365000,
- 'court_number': 1,
- 'sport': 'TENNIS',
- 'user_id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
- 'booking_id': 'b1d3bebf-dc0d-4fc1-861c-506a40cc2925',
- 'materials': ['Raquete', 'Bola', 'Rede', 'Tenis']
+ expected = {
+ 'bookings': [
+ {
+ 'booking': {
+ 'start_date': 1634576165000,
+ 'end_date': 1634583365000,
+ 'court_number': 1,
+ 'sport': 'Tennis',
+ 'booking_id': 'b1d3bebf-dc0d-4fc1-861c-506a40cc2925',
+ 'materials': ['Raquete', 'Bola', 'Rede', 'Tenis'],
+ 'type': 'Training'
+ }
+ },
+ {
+ 'booking': {
+ 'start_date': 1634563800000,
+ 'end_date': 1634567400000,
+ 'court_number': 2,
+ 'sport': 'Football',
+ 'booking_id': 'b2d3bebf-dc0d-4fc1-861c-506a40cc2925',
+ 'materials': ['Bola', 'Chuteira'],
+ 'type': 'Training'
+ }
+ },
+ {
+ 'booking': {
+ 'start_date': 1634569200000,
+ 'end_date': 1634571000000,
+ 'court_number': 3,
+ 'sport': 'Basketball',
+ 'booking_id': 'b3d3bebf-dc0d-4fc1-861c-506a40cc2925',
+ 'materials': ['Bola'],
+ 'type': 'Common'
+ }
+ },
+ {
+ 'booking': {
+ 'start_date': 1634574600000,
+ 'end_date': 1634578200000,
+ 'court_number': 4,
+ 'sport': 'Volleyball',
+ 'booking_id': 'b4d3bebf-dc0d-4fc1-861c-506a40cc2925',
+ 'materials': ['Bola', 'Rede'],
+ 'type': 'Common'
+ }
},
{
- 'start_date': 1634563800000,
- 'end_date': 1634567400000,
- 'court_number': 2,
- 'sport': 'FOOTBALL',
- 'user_id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
- 'booking_id': 'b2d3bebf-dc0d-4fc1-861c-506a40cc2925',
- 'materials': ['Bola', 'Chuteira']
+ 'booking': {
+ 'start_date': 1634580000000,
+ 'end_date': 1634581800000,
+ 'court_number': 5,
+ 'sport': 'Handball',
+ 'booking_id': 'b5d3bebf-dc0d-4fc1-861c-506a40cc2925',
+ 'materials': ['Bola'],
+ 'type': 'Training'
+ }
},
{
- 'start_date': 1634569200000,
- 'end_date': 1634571000000,
- 'court_number': 3,
- 'sport': 'BASKETBALL',
- 'user_id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
- 'booking_id': 'b3d3bebf-dc0d-4fc1-861c-506a40cc2925',
- 'materials': ['Bola']
+ 'booking': {
+ 'start_date': 1634583600000,
+ 'end_date': 1634585400000,
+ 'court_number': 5,
+ 'sport': 'Futsal',
+ 'booking_id': 'b6d3bebf-dc0d-4fc1-861c-506a40cc2925',
+ 'materials': ['Bola', 'Chuteira'],
+ 'type': 'Training'
+ }
},
{
- 'start_date': 1634574600000,
- 'end_date': 1634578200000,
- 'court_number': 4,
- 'sport': 'VOLLEYBALL',
- 'user_id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
- 'booking_id': 'b4d3bebf-dc0d-4fc1-861c-506a40cc2925',
- 'materials': ['Bola', 'Rede']
+ 'booking': {
+ 'start_date': 1634587200000,
+ 'end_date': 1634589000000,
+ 'court_number': 5,
+ 'sport': 'Rugby',
+ 'booking_id': 'b7d3bebf-dc0d-4fc1-861c-506a40cc2925',
+ 'materials': ['Bola', 'Tenis', 'Capacete'],
+ 'type': 'Training'
+ }
},
{
- 'start_date': 1634580000000,
- 'end_date': 1634581800000,
- 'court_number': 5,
- 'sport': 'HANDBALL',
- 'user_id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
- 'booking_id': 'b5d3bebf-dc0d-4fc1-861c-506a40cc2925',
- 'materials': ['Bola']
+ 'booking': {
+ 'start_date': 1634590800000,
+ 'end_date': 1634592600000,
+ 'court_number': 5,
+ 'sport': 'Ping Pong',
+ 'booking_id': 'b8d3bebf-dc0d-4fc1-861c-506a40cc2925',
+ 'materials': ['Raquete', 'Bola'],
+ 'type': 'Training'
+ }
}
],
'message': 'the bookings were retrieved'
+ }
+
- }
\ No newline at end of file
+ assert viewmodel == expected
diff --git a/tests/modules/get_all_bookings_grouped_by_role/__init__.py b/tests/modules/get_all_bookings_grouped_by_role/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/modules/get_all_courts/app/test_get_all_courts_presenter.py b/tests/modules/get_all_courts/app/test_get_all_courts_presenter.py
index 2f214f4..61198b0 100644
--- a/tests/modules/get_all_courts/app/test_get_all_courts_presenter.py
+++ b/tests/modules/get_all_courts/app/test_get_all_courts_presenter.py
@@ -40,7 +40,7 @@ def test_lambda_handler(self):
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
- "body": None,
+ "body": '{"number": 7, "status": "AVAILABLE", "is_field": false, "photo": "photo"}',
"pathParameters": None,
"isBase64Encoded": None,
"stageVariables": None
diff --git a/tests/modules/get_booking/app/test_get_booking_controller.py b/tests/modules/get_booking/app/test_get_booking_controller.py
index bc5fdc5..ef6a1d2 100644
--- a/tests/modules/get_booking/app/test_get_booking_controller.py
+++ b/tests/modules/get_booking/app/test_get_booking_controller.py
@@ -19,7 +19,6 @@ def test_get_booking_controller(self):
assert response.body['booking']['end_date'] == 1634567400000
assert response.body['booking']['court_number'] == 2
assert response.body['booking']['sport'] == 'Football'
- assert response.body['booking']['user_id'] == 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
assert response.body['booking']['materials'] == ['Bola', 'Chuteira']
def test_get_booking_controller_missing_booking_id(self):
@@ -32,6 +31,7 @@ def test_get_booking_controller_missing_booking_id(self):
assert response.status_code == 400
assert response.body == 'Field booking_id is missing'
+
def test_get_booking_controller_wrong_type_booking_id(self):
repo = BookingRepositoryMock()
@@ -59,3 +59,4 @@ def test_get_booking_controller_booking_not_found(self):
response = controller(request)
assert response.status_code == 404
assert response.body == 'No items found for booking_id'
+
\ No newline at end of file
diff --git a/tests/modules/get_booking/app/test_get_booking_presenter.py b/tests/modules/get_booking/app/test_get_booking_presenter.py
index d54a475..eb2f0aa 100644
--- a/tests/modules/get_booking/app/test_get_booking_presenter.py
+++ b/tests/modules/get_booking/app/test_get_booking_presenter.py
@@ -57,7 +57,6 @@ def test_get_booking_presenter(self):
assert json.loads(response['body'])['booking']['end_date'] == 1634583365000
assert json.loads(response['body'])['booking']['court_number'] == 1
assert json.loads(response['body'])['booking']['sport'] == 'Tennis'
- assert json.loads(response['body'])['booking']['user_id'] == 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
assert json.loads(response['body'])['booking']['materials'] == ['Raquete', 'Bola', 'Rede', 'Tenis']
@@ -76,7 +75,7 @@ def test_get_booking_presenter_missing_parameters(self):
"header2": "value1,value2"
},
"queryStringParameters": {
- "parameter1": "1"
+
},
"requestContext": {
"accountId": "123456789012",
@@ -107,7 +106,7 @@ def test_get_booking_presenter_missing_parameters(self):
response = lambda_handler(event, None)
assert response['statusCode'] == 400
- assert json.loads(response['body']) == "Field booking_id is missing"
+ assert json.loads(response['body']) == 'Field booking_id is missing'
def test_get_booking_presenter_entity_error(self):
event = {
@@ -257,11 +256,4 @@ def test_get_booking_presenter_entity_not_found(self):
assert response['statusCode'] == 404
assert json.loads(response['body']) == 'No items found for booking_id'
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/tests/modules/get_booking/app/test_get_booking_viewmodel.py b/tests/modules/get_booking/app/test_get_booking_viewmodel.py
index a3b80a6..4defb97 100644
--- a/tests/modules/get_booking/app/test_get_booking_viewmodel.py
+++ b/tests/modules/get_booking/app/test_get_booking_viewmodel.py
@@ -16,9 +16,9 @@ def test_get_booking_viewmodel(self):
'end_date': 1634583365000,
'court_number': 1,
'sport': 'Tennis',
- 'user_id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
'booking_id': 'b1d3bebf-dc0d-4fc1-861c-506a40cc2925',
- 'materials': ['Raquete', 'Bola', 'Rede', 'Tenis']
+ 'materials': ['Raquete', 'Bola', 'Rede', 'Tenis'],
+ 'type': 'Training'
},
'message': 'the booking was retrieved'
}
diff --git a/tests/modules/get_bookings/app/test_get_bookings_controller.py b/tests/modules/get_bookings/app/test_get_bookings_controller.py
index c32de5b..8ccfa41 100644
--- a/tests/modules/get_bookings/app/test_get_bookings_controller.py
+++ b/tests/modules/get_bookings/app/test_get_bookings_controller.py
@@ -17,18 +17,17 @@ def test_get_bookings_controller(self):
usecase = GetBookingsUseCase(repo=repo)
controller = GetBookingsController(usecase=usecase)
request = HttpRequest(query_params={
- 'booking_id': 'b2d3bebf-dc0d-4fc1-861c-506a40cc2925',
+ 'booking_id': 'b6d3bebf-dc0d-4fc1-861c-506a40cc2925',
'user_id': "c8435c66-13a4-4641-9d54-773b4b8ccc98"
})
response = controller(request)
assert response.status_code == 200
- assert response.body['bookings'][0]['booking_id'] == 'b2d3bebf-dc0d-4fc1-861c-506a40cc2925'
- assert response.body['bookings'][0]['start_date'] == 1634563800000
- assert response.body['bookings'][0]['end_date'] == 1634567400000
- assert response.body['bookings'][0]['court_number'] == 2
- assert response.body['bookings'][0]['sport'] == 'Football'
- assert response.body['bookings'][0]['user_id'] == 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ assert response.body['bookings'][0]['booking_id'] == 'b6d3bebf-dc0d-4fc1-861c-506a40cc2925'
+ assert response.body['bookings'][0]['start_date'] == 1634583600000
+ assert response.body['bookings'][0]['end_date'] == 1634585400000
+ assert response.body['bookings'][0]['court_number'] == 5
+ assert response.body['bookings'][0]['sport'] == 'Futsal'
assert response.body['bookings'][0]['materials'] == ['Bola', 'Chuteira']
def test_get_bookings_controller_empty_query(self):
@@ -40,7 +39,7 @@ def test_get_bookings_controller_empty_query(self):
response = controller(request)
assert response.status_code == 400
- assert response.body == 'Empty query parameters: At least one of the filters must be provided: booking_id, user_id, sport, court_number, end_date, start_date'
+ assert response.body == 'Empty query parameters: At least one of the filters must be provided: booking_id, user_id, sport, court_number, end_date, start_date, type'
def test_get_bookings_controller_wrong_type_booking_id(self):
repo = BookingRepositoryMock()
@@ -105,8 +104,8 @@ def test_get_bookings_controller_user_id(self):
assert response.status_code == 200
- for booking in response.body['bookings']:
- assert booking['user_id'] == 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ # for booking in response.body['bookings']:
+ # assert booking['user_id'] == 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
def test_get_bookings_controller_start_date_error(self):
@@ -167,7 +166,6 @@ def test_get_bookings_controller_five_filters(self):
assert len(bookings) == 1
b = bookings[0]
assert b['booking_id'] == 'b6d3bebf-dc0d-4fc1-861c-506a40cc2925'
- assert b['user_id'] == 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
assert b['sport'] == 'Futsal'
assert b['court_number'] == 5
assert b['start_date'] >= int(start) and b['end_date'] <= int(end)
@@ -188,7 +186,6 @@ def test_get_bookings_controller_four_filters(self):
bookings = response.body['bookings']
assert len(bookings) == 1
b = bookings[0]
- assert b['user_id'] == 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
assert b['sport'] == 'Volleyball'
assert b['court_number'] == 4
assert b['start_date'] >= int(start) and b['end_date'] <= int(end)
@@ -207,7 +204,6 @@ def test_get_bookings_controller_three_filters(self):
b = bookings[0]
assert b['sport'] == 'Rugby'
assert b['court_number'] == 5
- assert b['user_id'] == 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
def test_get_bookings_user_id_not_valid(self):
request = HttpRequest(query_params={
@@ -215,4 +211,3 @@ def test_get_bookings_user_id_not_valid(self):
})
response = self.controller(request)
assert response.status_code == 400
-
diff --git a/tests/modules/get_bookings/app/test_get_bookings_presenter.py b/tests/modules/get_bookings/app/test_get_bookings_presenter.py
index d150375..c58e4d7 100644
--- a/tests/modules/get_bookings/app/test_get_bookings_presenter.py
+++ b/tests/modules/get_bookings/app/test_get_bookings_presenter.py
@@ -2,7 +2,7 @@
from src.modules.get_bookings.app.get_bookings_presenter import lambda_handler
from src.shared.infra.repositories.booking_repository_mock import BookingRepositoryMock
-class Test_GetBookingPresenter:
+class TestGetBookingsPresenter:
def test_get_bookings_presenter(self):
event = {
@@ -32,7 +32,7 @@ def test_get_bookings_presenter(self):
"authentication": None,
"authorizer": {
"user": {
- "id": "c8435c66-13a4-4641-9d54-773b4b8ccc98",
+ "id": "1f25448b-3429-4c19-8287-d9e64f17bc3a",
"displayName": "User",
"mail": "lbj@maua.br"
}
@@ -67,7 +67,6 @@ def test_get_bookings_presenter(self):
assert json.loads(response['body'])['bookings'][0]['end_date'] == 1634583365000
assert json.loads(response['body'])['bookings'][0]['court_number'] == 1
assert json.loads(response['body'])['bookings'][0]['sport'] == 'Tennis'
- assert json.loads(response['body'])['bookings'][0]['user_id'] == 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
assert json.loads(response['body'])['bookings'][0]['materials'] == ['Raquete', 'Bola', 'Rede', 'Tenis']
@@ -122,7 +121,7 @@ def test_get_bookings_presenter_missing_parameters(self):
response = lambda_handler(event, None)
assert response['statusCode'] == 400
- assert json.loads(response['body']) == 'Empty query parameters: At least one of the filters must be provided: booking_id, user_id, sport, court_number, end_date, start_date'
+ assert json.loads(response['body']) == 'Empty query parameters: At least one of the filters must be provided: booking_id, user_id, sport, court_number, end_date, start_date, type'
def test_get_bookings_presenter_entity_error(self):
event = {
@@ -287,11 +286,3 @@ def test_get_bookings_presenter_entity_not_found(self):
assert response['statusCode'] == 404
assert json.loads(response['body']) == 'No items found for booking filters passed'
-
-
-
-
-
-
-
-
diff --git a/tests/modules/get_bookings/app/test_get_bookings_viewmodel.py b/tests/modules/get_bookings/app/test_get_bookings_viewmodel.py
index 27bcd57..d5bdb4f 100644
--- a/tests/modules/get_bookings/app/test_get_bookings_viewmodel.py
+++ b/tests/modules/get_bookings/app/test_get_bookings_viewmodel.py
@@ -16,9 +16,9 @@ def test_get_bookings_viewmodel(self):
'end_date': 1634583365000,
'court_number': 1,
'sport': 'Tennis',
- 'user_id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
'booking_id': 'b1d3bebf-dc0d-4fc1-861c-506a40cc2925',
- 'materials': ['Raquete', 'Bola', 'Rede', 'Tenis']
+ 'materials': ['Raquete', 'Bola', 'Rede', 'Tenis'],
+ 'type': 'Training'
}],
'message': 'the bookings were retrieved'
}
diff --git a/tests/modules/get_court/app/test_get_court_controller.py b/tests/modules/get_court/app/test_get_court_controller.py
index f6055a4..62fe2ca 100644
--- a/tests/modules/get_court/app/test_get_court_controller.py
+++ b/tests/modules/get_court/app/test_get_court_controller.py
@@ -11,7 +11,7 @@ def test_get_court_controller(self):
usecase = GetCourtUsecase(repo=repo)
controller = GetCourtController(usecase=usecase)
request = HttpRequest(query_params={
- "number": 2
+ "number": "2"
})
response = controller(request)
diff --git a/tests/modules/get_court/app/test_get_court_presenter.py b/tests/modules/get_court/app/test_get_court_presenter.py
index 7f93dfb..46ee487 100644
--- a/tests/modules/get_court/app/test_get_court_presenter.py
+++ b/tests/modules/get_court/app/test_get_court_presenter.py
@@ -19,7 +19,7 @@ def test_get_court_presenter(self):
"header2": "value1,value2"
},
"queryStringParameters": {
- "number": "1" #tem que passar ja que no querry sempre vem como string
+ "parameter1": "1"
},
"requestContext": {
"accountId": "123456789012",
@@ -42,7 +42,7 @@ def test_get_court_presenter(self):
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
- "body": {},
+ "body": {"number":1},
"pathParameters": None,
"isBase64Encoded": None,
"stageVariables": None
@@ -117,7 +117,7 @@ def test_get_court_presenter_entity_error(self):
"header2": "value1,value2"
},
"queryStringParameters": {
- "number": 15
+ "parameter1": "1"
},
"requestContext": {
"accountId": "123456789012",
@@ -140,7 +140,7 @@ def test_get_court_presenter_entity_error(self):
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
- "body": {},
+ "body": {"number": 15},
"pathParameters": None,
"isBase64Encoded": None,
"stageVariables": None
@@ -166,7 +166,7 @@ def test_get_court_presenter_wrong_type_parameter(self):
"header2": "value1,value2"
},
"queryStringParameters": {
- "code": "1"
+ "parameter1": "1"
},
"requestContext": {
"accountId": "123456789012",
@@ -189,7 +189,7 @@ def test_get_court_presenter_wrong_type_parameter(self):
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
- "body": {},
+ "body": {"code": "1"},
"pathParameters": None,
"isBase64Encoded": None,
"stageVariables": None
@@ -216,7 +216,7 @@ def test_get_court_presenter_not_found(self):
"header2": "value1,value2"
},
"queryStringParameters": {
- "number": 8
+ "parameter1": "1"
},
"requestContext": {
"accountId": "123456789012",
@@ -239,7 +239,7 @@ def test_get_court_presenter_not_found(self):
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
- "body": {},
+ "body": {"number": 8},
"pathParameters": None,
"isBase64Encoded": None,
"stageVariables": None
diff --git a/tests/modules/update_booking/app/test_update_booking_controller.py b/tests/modules/update_booking/app/test_update_booking_controller.py
index 02f02d2..fd19080 100644
--- a/tests/modules/update_booking/app/test_update_booking_controller.py
+++ b/tests/modules/update_booking/app/test_update_booking_controller.py
@@ -14,12 +14,18 @@ def test_update_booking_controller(self):
controller = UpdateBookingController(update_booking_use_case=usecase)
request = HttpRequest(body={
- "booking_id": booking_repo.bookings[0].booking_id,
- "start_date": booking_repo.bookings[0].start_date,
- "end_date": booking_repo.bookings[0].end_date,
- "court_number": 1,
- "sport": "Tennis",
- "materials": ['Raquete', 'Bola', 'Rede', 'Tenis']
+ "booking_id": booking_repo.bookings[0].booking_id,
+ "start_date": booking_repo.bookings[0].start_date,
+ "end_date": booking_repo.bookings[0].end_date,
+ "court_number": 1,
+ "sport": "Tennis",
+ "materials": ['Raquete', 'Bola', 'Rede', 'Tenis'],
+ "user_from_authorizer": {
+ 'user_id': 'qualquer-id',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'ADMIN'
+ }
})
response = controller(request)
@@ -27,17 +33,51 @@ def test_update_booking_controller(self):
assert response.status_code == 200
assert response.body['message'] == "the booking was retrieved"
+
+ def test_update_booking_controller_with_invalid_user_id(self):
+ booking_repo = BookingRepositoryMock()
+ usecase = UpdateBookingUsecase(booking_repo=booking_repo)
+ controller = UpdateBookingController(update_booking_use_case=usecase)
+
+ request = HttpRequest(body={
+ "booking_id": booking_repo.bookings[0].booking_id,
+ "start_date": booking_repo.bookings[0].start_date,
+ "end_date": booking_repo.bookings[0].end_date,
+ "court_number": 1,
+ "sport": "Tennis",
+ "materials": ['Raquete', 'Bola', 'Rede', 'Tenis'],
+ "user_from_authorizer": {
+ 'user_id': 'invalid',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+ })
+
+ response = controller(request)
+
+ assert response.status_code == 403
+ assert response.body == "That action is forbidden for this user id"
+
+
def test_update_booking_controller_booking_id_missing(self):
booking_repo = BookingRepositoryMock()
usecase = UpdateBookingUsecase(booking_repo=booking_repo)
controller = UpdateBookingController(update_booking_use_case=usecase)
request = HttpRequest(body={
- "start_date": booking_repo.bookings[0].start_date,
- "end_date": booking_repo.bookings[0].end_date,
- "court_number": 1,
- "sport": "Tennis",
- "materials": ['Raquete', 'Bola', 'Rede', 'Tenis']
+ "start_date": booking_repo.bookings[0].start_date,
+ "end_date": booking_repo.bookings[0].end_date,
+ "court_number": 1,
+ "sport": "Tennis",
+ "materials": ['Raquete', 'Bola', 'Rede', 'Tenis'],
+ "user_from_authorizer": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
})
response = controller(request)
@@ -51,12 +91,19 @@ def test_update_booking_controller_booking_id_wrong_type(self):
controller = UpdateBookingController(update_booking_use_case=usecase)
request = HttpRequest(body={
- "booking_id": 123,
- "start_date": booking_repo.bookings[0].start_date,
- "end_date": booking_repo.bookings[0].end_date,
- "court_number": 1,
- "sport": "Tennis",
- "materials": ['Raquete', 'Bola', 'Rede', 'Tenis']
+ "booking_id": 123,
+ "start_date": booking_repo.bookings[0].start_date,
+ "end_date": booking_repo.bookings[0].end_date,
+ "court_number": 1,
+ "sport": "Tennis",
+ "materials": ['Raquete', 'Bola', 'Rede', 'Tenis'],
+ "user_from_authorizer": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
})
response = controller(request)
@@ -71,12 +118,18 @@ def test_update_booking_controller_start_date_wrong_type(self):
controller = UpdateBookingController(update_booking_use_case=usecase)
request = HttpRequest(body={
- "booking_id": booking_repo.bookings[0].booking_id,
- "start_date": "123",
- "end_date": booking_repo.bookings[0].end_date,
- "court_number": 1,
- "sport": "Tennis",
- "materials": ['Raquete', 'Bola', 'Rede', 'Tenis']
+ "booking_id": booking_repo.bookings[0].booking_id,
+ "start_date": "123",
+ "end_date": booking_repo.bookings[0].end_date,
+ "court_number": 1,
+ "sport": "Tennis",
+ "materials": ['Raquete', 'Bola', 'Rede', 'Tenis'],
+ "user_from_authorizer": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
})
response = controller(request)
@@ -91,12 +144,18 @@ def test_update_booking_controller_end_date_wrong_type(self):
controller = UpdateBookingController(update_booking_use_case=usecase)
request = HttpRequest(body={
- "booking_id": booking_repo.bookings[0].booking_id,
- "start_date": booking_repo.bookings[0].start_date,
- "end_date": "123",
- "court_number": 1,
- "sport": "Tennis",
- "materials": ['Raquete', 'Bola', 'Rede', 'Tenis']
+ "booking_id": booking_repo.bookings[0].booking_id,
+ "start_date": booking_repo.bookings[0].start_date,
+ "end_date": "123",
+ "court_number": 1,
+ "sport": "Tennis",
+ "materials": ['Raquete', 'Bola', 'Rede', 'Tenis'],
+ "user_from_authorizer": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
})
response = controller(request)
@@ -111,12 +170,18 @@ def test_update_booking_controller_court_number_wrong_type(self):
controller = UpdateBookingController(update_booking_use_case=usecase)
request = HttpRequest(body={
- "booking_id": booking_repo.bookings[0].booking_id,
- "start_date": booking_repo.bookings[0].start_date,
- "end_date": booking_repo.bookings[0].end_date,
- "court_number": "1",
- "sport": "Tennis",
- "materials": ['Raquete', 'Bola', 'Rede', 'Tenis']
+ "booking_id": booking_repo.bookings[0].booking_id,
+ "start_date": booking_repo.bookings[0].start_date,
+ "end_date": booking_repo.bookings[0].end_date,
+ "court_number": "1",
+ "sport": "Tennis",
+ "materials": ['Raquete', 'Bola', 'Rede', 'Tenis'],
+ "user_from_authorizer": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
})
response = controller(request)
@@ -131,12 +196,18 @@ def test_update_booking_controller_sport_wrong_type(self):
controller = UpdateBookingController(update_booking_use_case=usecase)
request = HttpRequest(body={
- "booking_id": booking_repo.bookings[0].booking_id,
- "start_date": booking_repo.bookings[0].start_date,
- "end_date": booking_repo.bookings[0].end_date,
- "court_number": 1,
- "sport": 123,
- "materials": ['Raquete', 'Bola', 'Rede', 'Tenis']
+ "booking_id": booking_repo.bookings[0].booking_id,
+ "start_date": booking_repo.bookings[0].start_date,
+ "end_date": booking_repo.bookings[0].end_date,
+ "court_number": 1,
+ "sport": 123,
+ "materials": ['Raquete', 'Bola', 'Rede', 'Tenis'],
+ "user_from_authorizer": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
})
response = controller(request)
@@ -151,12 +222,18 @@ def test_update_booking_controller_materials_wrong_type(self):
controller = UpdateBookingController(update_booking_use_case=usecase)
request = HttpRequest(body={
- "booking_id": booking_repo.bookings[0].booking_id,
- "start_date": booking_repo.bookings[0].start_date,
- "end_date": booking_repo.bookings[0].end_date,
- "court_number": 1,
- "sport": "Tennis",
- "materials": "Raquete, Bola, Rede, Tenis"
+ "booking_id": booking_repo.bookings[0].booking_id,
+ "start_date": booking_repo.bookings[0].start_date,
+ "end_date": booking_repo.bookings[0].end_date,
+ "court_number": 1,
+ "sport": "Tennis",
+ "materials": "Raquete, Bola, Rede, Tenis",
+ "user_from_authorizer": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
})
response = controller(request)
@@ -174,7 +251,13 @@ def test_update_booking_controller_only_booking_id(self):
booking_id = original_booking.booking_id
request = HttpRequest(body={
- "booking_id": booking_id
+ "booking_id": booking_id,
+ "user_from_authorizer": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
})
response = controller(request)
@@ -192,13 +275,19 @@ def test_update_booking_controller_user_id_ignored(self):
new_user_id = "novo-user-id-que-nao-deve-ser-usado"
request = HttpRequest(body={
- "booking_id": original_booking.booking_id,
- "start_date": original_booking.start_date,
- "end_date": original_booking.end_date,
- "court_number": 1,
- "sport": "Tennis",
- "materials": ['Raquete', 'Bola', 'Rede', 'Tenis'],
- "user_id": new_user_id
+ "booking_id": original_booking.booking_id,
+ "start_date": original_booking.start_date,
+ "end_date": original_booking.end_date,
+ "court_number": 1,
+ "sport": "Tennis",
+ "materials": ['Raquete', 'Bola', 'Rede', 'Tenis'],
+ "user_id": new_user_id,
+ "user_from_authorizer": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
})
response = controller(request)
@@ -224,12 +313,18 @@ def get_booking_mock(booking_id):
booking_repo.get_booking = get_booking_mock
request = HttpRequest(body={
- "booking_id": non_existent_booking_id,
- "start_date": 1634576165000,
- "end_date": 1634583365000,
- "court_number": 1,
- "sport": "Tennis",
- "materials": ['Raquete', 'Bola', 'Rede', 'Tenis']
+ "booking_id": non_existent_booking_id,
+ "start_date": 1634576165000,
+ "end_date": 1634583365000,
+ "court_number": 1,
+ "sport": "Tennis",
+ "materials": ['Raquete', 'Bola', 'Rede', 'Tenis'],
+ "user_from_authorizer": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
})
response = controller(request)
@@ -251,7 +346,13 @@ def test_update_booking_controller_partial_update(self):
request = HttpRequest(body={
"booking_id": booking_id,
- "court_number": new_court_number
+ "court_number": new_court_number,
+ "user_from_authorizer": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
})
response = controller(request)
diff --git a/tests/modules/update_booking/app/test_update_booking_presenter.py b/tests/modules/update_booking/app/test_update_booking_presenter.py
index 9887f18..6fe8ca3 100644
--- a/tests/modules/update_booking/app/test_update_booking_presenter.py
+++ b/tests/modules/update_booking/app/test_update_booking_presenter.py
@@ -26,6 +26,15 @@ def test_lambda_handler(self):
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
diff --git a/tests/modules/update_booking/app/test_update_booking_usecase.py b/tests/modules/update_booking/app/test_update_booking_usecase.py
index 2b6a3d4..f853693 100644
--- a/tests/modules/update_booking/app/test_update_booking_usecase.py
+++ b/tests/modules/update_booking/app/test_update_booking_usecase.py
@@ -3,7 +3,7 @@
from src.modules.update_booking.app.update_booking_usecase import UpdateBookingUsecase
from src.shared.domain.enums.sport import SPORT
from src.shared.helpers.errors.domain_errors import EntityError, EntityParameterOrderDatesError, EntityParameterTimeError
-from src.shared.helpers.errors.usecase_errors import NoItemsFound
+from src.shared.helpers.errors.usecase_errors import ForbiddenAction, InvalidSchedule
from src.shared.infra.repositories.booking_repository_mock import BookingRepositoryMock
@@ -14,7 +14,15 @@ def test_update_booking_usecase(self):
booking_id = booking_repo.bookings[0].booking_id
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
booking = usecase(booking_id=booking_id,
+ user=user,
court_number=2,
start_date=1634576165000,
end_date=1634583365000,
@@ -29,12 +37,97 @@ def test_update_booking_usecase(self):
assert booking_repo.bookings[0].sport == booking.sport
assert booking_repo.bookings[0].materials == booking.materials
+ def test_update_booking_usecase_with_invalid_user_id(self):
+ booking_repo = BookingRepositoryMock()
+ usecase = UpdateBookingUsecase(booking_repo=booking_repo)
+
+ booking_id = booking_repo.bookings[0].booking_id
+
+ user = {
+ 'user_id': 'c07e0862-3c07-4227-ab0f-511a267cb7ff',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
+ with pytest.raises(ForbiddenAction):
+ usecase(booking_id=booking_id,
+ user=user,
+ court_number=2,
+ start_date=1634576165000,
+ end_date=1634583365000,
+ sport=SPORT.TENNIS,
+ materials=['Raquete', 'Bola', 'Rede', 'Tenis']
+ )
+
+ def test_update_booking_usecase_invalid_schedule_overlap(self):
+
+ with pytest.raises(InvalidSchedule) as e:
+
+ booking_repo = BookingRepositoryMock()
+ usecase = UpdateBookingUsecase(booking_repo=booking_repo)
+
+ booking_id = booking_repo.bookings[0].booking_id
+
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
+ booking = usecase(booking_id=booking_id,
+ user=user,
+ court_number=3,
+ start_date=1634569200000,
+ end_date=1634570000000,
+ sport=SPORT.TENNIS,
+ materials=['Raquete', 'Bola', 'Rede', 'Tenis']
+ )
+
+ assert e.value == "Court is already booked for the selected time slot or has to have 15 min tolerance"
+
+ def test_update_booking_usecase_invalid_schedule_15min_intolerance(self):
+
+ with pytest.raises(InvalidSchedule) as e:
+
+ booking_repo = BookingRepositoryMock()
+ usecase = UpdateBookingUsecase(booking_repo=booking_repo)
+
+ booking_id = booking_repo.bookings[0].booking_id
+
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
+ booking = usecase(booking_id=booking_id,
+ user=user,
+ court_number=3,
+ start_date=1634571899999,
+ end_date=1734571000000,
+ sport=SPORT.TENNIS,
+ materials=['Raquete', 'Bola', 'Rede', 'Tenis']
+ )
+
+ assert e.value == "Court is already booked for the selected time slot or has to have 15 min tolerance"
+
def test_update_booking_usecase_invalid_booking_id(self):
booking_repo = BookingRepositoryMock()
usecase = UpdateBookingUsecase(booking_repo=booking_repo)
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
with pytest.raises(EntityError):
booking = usecase(booking_id=111,
+ user=user,
court_number=2,
start_date=1634576165000,
end_date=1634583365000,
@@ -46,8 +139,16 @@ def test_update_booking_usecase_invalid_dates(self):
booking_repo = BookingRepositoryMock()
usecase = UpdateBookingUsecase(booking_repo=booking_repo)
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
with pytest.raises(EntityError):
booking = usecase(booking_id=booking_repo.bookings[0].booking_id,
+ user=user,
court_number=2,
start_date="1634583365000",
end_date="1634576165000",
@@ -59,8 +160,16 @@ def test_update_booking_usecase_invalid_sport(self):
booking_repo = BookingRepositoryMock()
usecase = UpdateBookingUsecase(booking_repo=booking_repo)
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
with pytest.raises(EntityError):
- booking = usecase(booking_id=booking_repo.bookings[0].booking_id,
+ booking = usecase(booking_id=booking_repo.bookings[0].booking_id,
+ user=user,
court_number=2,
start_date=1634576165000,
end_date=1634583365000,
@@ -72,8 +181,16 @@ def test_update_booking_usecase_invalid_materials(self):
booking_repo = BookingRepositoryMock()
usecase = UpdateBookingUsecase(booking_repo=booking_repo)
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
with pytest.raises(EntityError):
- booking = usecase(booking_id=booking_repo.bookings[0].booking_id,
+ booking = usecase(booking_id=booking_repo.bookings[0].booking_id,
+ user=user,
court_number=2,
start_date=1634576165000,
end_date=1634583365000,
@@ -85,8 +202,16 @@ def test_update_booking_usecase_none_booking_id(self):
booking_repo = BookingRepositoryMock()
usecase = UpdateBookingUsecase(booking_repo=booking_repo)
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
with pytest.raises(EntityError):
- booking = usecase(booking_id=None,
+ booking = usecase(booking_id=None,
+ user=user,
court_number=2,
start_date=1634576165000,
end_date=1634583365000,
@@ -97,12 +222,20 @@ def test_update_booking_usecase_none_booking_id(self):
def test_update_booking_usecase_none_court_number(self):
booking_repo = BookingRepositoryMock()
usecase = UpdateBookingUsecase(booking_repo=booking_repo)
-
+
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
original_booking = booking_repo.bookings[0]
original_court_number = original_booking.court_number
booking = usecase(
- booking_id=original_booking.booking_id,
+ booking_id=original_booking.booking_id,
+ user=user,
court_number=None,
start_date=1634576165000,
end_date=1634583365000,
@@ -118,9 +251,17 @@ def test_update_booking_usecase_none_start_date(self):
original_booking = booking_repo.bookings[0]
original_start_date = original_booking.start_date
-
+
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
booking = usecase(
- booking_id=original_booking.booking_id,
+ booking_id=original_booking.booking_id,
+ user=user,
court_number=2,
start_date=None,
end_date=1634583365000,
@@ -133,12 +274,20 @@ def test_update_booking_usecase_none_start_date(self):
def test_update_booking_usecase_none_end_date(self):
booking_repo = BookingRepositoryMock()
usecase = UpdateBookingUsecase(booking_repo=booking_repo)
-
+
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
original_booking = booking_repo.bookings[0]
original_end_date = original_booking.end_date
booking = usecase(
- booking_id=original_booking.booking_id,
+ booking_id=original_booking.booking_id,
+ user=user,
court_number=2,
start_date=1634576165000,
end_date=None,
@@ -152,8 +301,16 @@ def test_update_booking_usecase_order_dates_incorrect(self):
booking_repo = BookingRepositoryMock()
usecase = UpdateBookingUsecase(booking_repo=booking_repo)
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
with pytest.raises(EntityParameterOrderDatesError):
- booking = usecase(booking_id=booking_repo.bookings[0].booking_id,
+ booking = usecase(booking_id=booking_repo.bookings[0].booking_id,
+ user=user,
court_number=2,
start_date=1634583365000,
end_date=1634576165000,
@@ -164,12 +321,20 @@ def test_update_booking_usecase_order_dates_incorrect(self):
def test_update_booking_usecase_none_sport(self):
booking_repo = BookingRepositoryMock()
usecase = UpdateBookingUsecase(booking_repo=booking_repo)
-
+
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
original_booking = booking_repo.bookings[0]
original_sport = original_booking.sport
booking = usecase(
- booking_id=original_booking.booking_id,
+ booking_id=original_booking.booking_id,
+ user=user,
court_number=2,
start_date=1634576165000,
end_date=1634583365000,
@@ -182,12 +347,20 @@ def test_update_booking_usecase_none_sport(self):
def test_update_booking_usecase_none_materials(self):
booking_repo = BookingRepositoryMock()
usecase = UpdateBookingUsecase(booking_repo=booking_repo)
-
+
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
original_booking = booking_repo.bookings[0]
original_materials = original_booking.materials
booking = usecase(
- booking_id=original_booking.booking_id,
+ booking_id=original_booking.booking_id,
+ user=user,
court_number=2,
start_date=1634576165000,
end_date=1634583365000,
@@ -201,18 +374,26 @@ def test_update_booking_usecase_cannot_update_user_id(self):
booking_repo = BookingRepositoryMock()
usecase = UpdateBookingUsecase(booking_repo=booking_repo)
+ user = {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'STUDENT'
+ }
+
original_booking = booking_repo.bookings[0]
booking_id = original_booking.booking_id
original_user_id = original_booking.user_id
booking = usecase(
- booking_id=booking_id,
+ booking_id=booking_id,
+ user=user,
court_number=2,
start_date=1634576165000,
end_date=1634583365000,
sport=SPORT.TENNIS,
materials=['Raquete', 'Bola', 'Rede', 'Tenis'],
- user_id="novo-user-id-que-nao-deve-ser-usado"
+ new_user_id="novo-user-id-que-nao-deve-ser-usado"
)
assert booking.user_id == original_user_id
\ No newline at end of file
diff --git a/tests/modules/update_booking/app/test_update_booking_viewmodel.py b/tests/modules/update_booking/app/test_update_booking_viewmodel.py
index 6e9e708..1458306 100644
--- a/tests/modules/update_booking/app/test_update_booking_viewmodel.py
+++ b/tests/modules/update_booking/app/test_update_booking_viewmodel.py
@@ -1,6 +1,7 @@
from src.modules.update_booking.app.update_booking_viewmodel import UpdateBookingViewmodel
from src.shared.domain.entities.booking import Booking
from src.shared.domain.enums.sport import SPORT
+from src.shared.domain.enums.type import BOOKING_TYPE
class Test_UpdateBookingViewmodel:
@@ -12,7 +13,8 @@ def test_update_booking_view_model(self):
sport=SPORT.FOOTBALL,
user_id='c8435c66-13a4-4641-9d54-773b4b8ccc98',
booking_id='b1d3bebf-dc0d-4fc1-861c-506a40cc2925',
- materials=['Bola'])
+ materials=['Bola'],
+ booking_type=BOOKING_TYPE.TRAINING)
viewmodel = UpdateBookingViewmodel(booking=booking).to_dict()
@@ -24,7 +26,8 @@ def test_update_booking_view_model(self):
'sport': 'Football',
'user_id': 'c8435c66-13a4-4641-9d54-773b4b8ccc98',
'booking_id': 'b1d3bebf-dc0d-4fc1-861c-506a40cc2925',
- 'materials': ['Bola']
+ 'materials': ['Bola'],
+ 'type': 'Training'
},
'message': 'the booking was retrieved'
}
diff --git a/tests/modules/update_court/app/test_update_court_controller.py b/tests/modules/update_court/app/test_update_court_controller.py
index 118c53f..bd048be 100644
--- a/tests/modules/update_court/app/test_update_court_controller.py
+++ b/tests/modules/update_court/app/test_update_court_controller.py
@@ -14,7 +14,10 @@ def test_update_court_controller_two_params(self):
request = HttpRequest(body={
"number": court_number,
"status": "MAINTENANCE",
- "photo": "https://www.linkedin.com/in/leonardo-iorio-b83360279/"
+ "photo": "https://www.linkedin.com/in/leonardo-iorio-b83360279/",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
response = controller(request)
@@ -34,6 +37,9 @@ def test_update_court_controller_only_status_param(self):
request = HttpRequest(body={
"number": court_number,
"status": "MAINTENANCE",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
response = controller(request)
@@ -52,7 +58,10 @@ def test_update_court_controller_only_photo_param(self):
request = HttpRequest(body={
"number": court_number,
- "photo": "photostr"
+ "photo": "photostr",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
response = controller(request)
@@ -71,7 +80,10 @@ def test_update_court_controller_missing_number(self):
request = HttpRequest(body={
"status": "AVAILABLE",
"is_field": False,
- "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/"
+ "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
response = controller(request)
@@ -87,7 +99,10 @@ def test_update_court_controller_wrong_type_number(self):
"number": "cavalo",
"status": "AVAILABLE",
"is_field": False,
- "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/"
+ "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
reponse = controller(request)
@@ -104,7 +119,10 @@ def test_update_court_controller_with_wrong_type_status(self):
"number": 7,
"status": 123,
"is_field": False,
- "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/"
+ "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
response = controller(request)
@@ -120,7 +138,10 @@ def test_update_court_controller_status_entity_error(self):
"number": 7,
"status": "INVALID",
"is_field": False,
- "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/"
+ "photo": "https://www.linkedin.com/in/vinicius-berti-a80354209/",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
response = controller(request)
@@ -136,7 +157,10 @@ def test_update_court_controller_photo_type_error(self):
"number": 7,
"status": "AVAILABLE",
"is_field": False,
- "photo": 1337
+ "photo": 1337,
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
response = controller(request)
@@ -152,7 +176,10 @@ def test_update_court_controller_number_not_found(self):
"number": 9,
"status": "AVAILABLE",
"is_field": False,
- "photo": "1234"
+ "photo": "1234",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
response = controller(request)
@@ -168,7 +195,10 @@ def test_update_court_controller_invalid_number(self):
"number": -999,
"status": "AVAILABLE",
"is_field": False,
- "photo": "1234"
+ "photo": "1234",
+ "user_from_authorizer": {
+ "role": "ADMIN"
+ }
})
response = controller(request)
diff --git a/tests/modules/update_court/app/test_update_court_presenter.py b/tests/modules/update_court/app/test_update_court_presenter.py
index 6fa0f82..1ec1697 100644
--- a/tests/modules/update_court/app/test_update_court_presenter.py
+++ b/tests/modules/update_court/app/test_update_court_presenter.py
@@ -25,6 +25,15 @@ def test_update_court_presenter_one_param(self):
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'ADMIN'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -77,6 +86,15 @@ def test_update_court_presenter(self):
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'ADMIN'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -130,6 +148,15 @@ def test_update_court_presenter_missing_number(self):
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'ADMIN'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -179,6 +206,15 @@ def test_update_court_presenter_wrong_type_number(self):
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'ADMIN'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -228,6 +264,15 @@ def test_update_court_presenter_wrong_type_status(self):
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'ADMIN'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -278,6 +323,15 @@ def test_update_court_presenter_wrong_status_entity(self):
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'ADMIN'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -327,6 +381,15 @@ def test_update_court_presenter_wrong_photo_type(self):
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'ADMIN'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -376,6 +439,15 @@ def test_update_court_presenter_number_not_found(self):
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'ADMIN'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
@@ -425,6 +497,15 @@ def test_update_court_presenter_invalid_number(self):
"apiId": "",
"authentication": None,
"authorizer": {
+ "user": json.dumps({
+ "user": {
+ 'user_id': '1f25448b-3429-4c19-8287-d9e64f17bc3a',
+ 'name': 'Nome',
+ 'email': 'user@email.com',
+ 'role': 'ADMIN'
+ },
+ "message": "the user was retrieved"
+ })
},
"domainName": ".lambda-url.us-west-2.on.aws",
"domainPrefix": "",
diff --git a/tests/modules/update_court/app/test_update_court_usecase.py b/tests/modules/update_court/app/test_update_court_usecase.py
index 4322ee6..4706b2a 100644
--- a/tests/modules/update_court/app/test_update_court_usecase.py
+++ b/tests/modules/update_court/app/test_update_court_usecase.py
@@ -2,7 +2,7 @@
from src.modules.update_court.app.update_court_usecase import UpdateCourtUsecase
from src.shared.helpers.errors.domain_errors import EntityError
from src.shared.infra.repositories.reservation_repository_mock import ReservationRepositoryMock
-from src.shared.helpers.errors.usecase_errors import NoItemsFound
+from src.shared.helpers.errors.usecase_errors import NoItemsFound, ForbiddenAction
from src.shared.domain.enums.status_enum import STATUS
@@ -16,7 +16,8 @@ def test_update_court_usecase(self):
court = usecase(
number=court_number,
status=STATUS.MAINTENANCE,
- photo="https://super.abril.com.br/mundo-estranho/os-poneis-sao-cavalos-anoes"
+ photo="https://super.abril.com.br/mundo-estranho/os-poneis-sao-cavalos-anoes",
+ role="ADMIN"
)
assert repo.get_court(court_number).number == court.number
@@ -32,7 +33,8 @@ def test_update_court_usecase_not_found_number(self):
court = usecase(
number=9,
status=STATUS.MAINTENANCE,
- photo="http://foto"
+ photo="http://foto",
+ role="ADMIN"
)
def test_update_court_usecase_invalid_court_number(self):
@@ -44,7 +46,8 @@ def test_update_court_usecase_invalid_court_number(self):
court = usecase(
number=-999,
status=STATUS.MAINTENANCE,
- photo="https://super.abril.com.br/mundo-estranho/os-poneis-sao-cavalos-anoes"
+ photo="https://super.abril.com.br/mundo-estranho/os-poneis-sao-cavalos-anoes",
+ role="ADMIN"
)
def test_update_court_usecase_court_number_not_found(self):
@@ -56,5 +59,19 @@ def test_update_court_usecase_court_number_not_found(self):
court = usecase(
number=9,
status=STATUS.MAINTENANCE,
- photo="https://super.abril.com.br/mundo-estranho/os-poneis-sao-cavalos-anoes"
+ photo="https://super.abril.com.br/mundo-estranho/os-poneis-sao-cavalos-anoes",
+ role="ADMIN"
+ )
+
+ def test_update_court_usecase_not_admin(self):
+
+ repo = ReservationRepositoryMock()
+ usecase = UpdateCourtUsecase(repo=repo)
+
+ with pytest.raises(ForbiddenAction):
+ court = usecase(
+ number=1,
+ status=STATUS.MAINTENANCE,
+ photo="https://super.abril.com.br/mundo-estranho/os-poneis-sao-cavalos-anoes",
+ role="STUDENT"
)
diff --git a/tests/shared/domain/entities/test_booking.py b/tests/shared/domain/entities/test_booking.py
index d508dae..dc7e366 100644
--- a/tests/shared/domain/entities/test_booking.py
+++ b/tests/shared/domain/entities/test_booking.py
@@ -2,6 +2,7 @@
from src.shared.domain.entities.booking import Booking
from src.shared.domain.enums.sport import SPORT
+from src.shared.domain.enums.type import BOOKING_TYPE
from src.shared.helpers.errors.domain_errors import EntityError, EntityParameterOrderDatesError
@@ -16,7 +17,8 @@ def test_booking(self):
sport= SPORT.FOOTBALL,
user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- materials= ["ball"]
+ materials= ["ball"],
+ booking_type=BOOKING_TYPE.TRAINING
)
assert type(booking) == Booking
@@ -27,6 +29,7 @@ def test_booking(self):
assert booking.user_id == "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5"
assert booking.booking_id == "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1"
assert booking.materials == ["ball"]
+ assert booking.booking_type.value == 'Training'
def test_order_dates_incorrect(self):
with pytest.raises(EntityParameterOrderDatesError):
@@ -37,7 +40,8 @@ def test_order_dates_incorrect(self):
sport= SPORT.FOOTBALL,
user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- materials= ["ball"]
+ materials= ["ball"],
+ booking_type=BOOKING_TYPE.TRAINING
)
def test_invalid_dates(self):
@@ -49,7 +53,8 @@ def test_invalid_dates(self):
sport= SPORT.FOOTBALL,
user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- materials= ["ball"]
+ materials= ["ball"],
+ booking_type=BOOKING_TYPE.TRAINING
)
def test_invalid_court_number(self):
@@ -61,7 +66,8 @@ def test_invalid_court_number(self):
sport= SPORT.FOOTBALL,
user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- materials= ["ball"]
+ materials= ["ball"],
+ booking_type=BOOKING_TYPE.TRAINING
)
def test_invalid_sport(self):
@@ -73,7 +79,8 @@ def test_invalid_sport(self):
sport= "football",
user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- materials= ["ball"]
+ materials= ["ball"],
+ booking_type=BOOKING_TYPE.TRAINING
)
def test_invalid_user_id(self):
@@ -85,7 +92,8 @@ def test_invalid_user_id(self):
sport= SPORT.FOOTBALL,
user_id= "123",
booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- materials= ["ball"]
+ materials= ["ball"],
+ booking_type=BOOKING_TYPE.TRAINING
)
def test_invalid_booking_id(self):
@@ -97,7 +105,8 @@ def test_invalid_booking_id(self):
sport= SPORT.FOOTBALL,
user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
booking_id= "123",
- materials= ["ball"]
+ materials= ["ball"],
+ booking_type=BOOKING_TYPE.TRAINING
)
def test_invalid_materials(self):
@@ -109,7 +118,8 @@ def test_invalid_materials(self):
sport= SPORT.FOOTBALL,
user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- materials= "ball"
+ materials= "ball",
+ booking_type=BOOKING_TYPE.TRAINING
)
def test_invalid_materials2(self):
@@ -121,7 +131,8 @@ def test_invalid_materials2(self):
sport= SPORT.FOOTBALL,
user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- materials= [1]
+ materials= [1],
+ booking_type=BOOKING_TYPE.TRAINING
)
def test_invalid_materials3(self):
@@ -133,7 +144,8 @@ def test_invalid_materials3(self):
sport= SPORT.FOOTBALL,
user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- materials= ["ball", 2]
+ materials= ["ball", 2],
+ booking_type=BOOKING_TYPE.TRAINING
)
def test_booking_none_dates(self):
@@ -145,7 +157,8 @@ def test_booking_none_dates(self):
sport= SPORT.FOOTBALL,
user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- materials= ["ball"]
+ materials= ["ball"],
+ booking_type=BOOKING_TYPE.TRAINING
)
def test_booking_none_court_number(self):
@@ -157,7 +170,8 @@ def test_booking_none_court_number(self):
sport= SPORT.FOOTBALL,
user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- materials= ["ball"]
+ materials= ["ball"],
+ booking_type=BOOKING_TYPE.TRAINING
)
def test_booking_none_sport(self):
@@ -169,7 +183,8 @@ def test_booking_none_sport(self):
sport= None,
user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- materials= ["ball"]
+ materials= ["ball"],
+ booking_type=BOOKING_TYPE.TRAINING
)
def test_booking_none_user_id(self):
@@ -181,7 +196,8 @@ def test_booking_none_user_id(self):
sport= SPORT.FOOTBALL,
user_id= None,
booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- materials= ["ball"]
+ materials= ["ball"],
+ booking_type=BOOKING_TYPE.TRAINING
)
def test_booking_none_booking_id(self):
@@ -193,7 +209,8 @@ def test_booking_none_booking_id(self):
sport= SPORT.FOOTBALL,
user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
booking_id= None,
- materials= ["ball"]
+ materials= ["ball"],
+ booking_type=BOOKING_TYPE.TRAINING
)
def test_booking_none_materials(self):
@@ -205,29 +222,60 @@ def test_booking_none_materials(self):
sport= SPORT.FOOTBALL,
user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- materials= None
+ materials= None,
+ booking_type=BOOKING_TYPE.TRAINING
)
+ def test_booking_with_invalid_type(self):
+
+ with pytest.raises(EntityError):
+ Booking(
+ start_date= 1738940138,
+ end_date= 1838940138,
+ court_number= 1,
+ sport= SPORT.FOOTBALL,
+ user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
+ booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
+ materials= ["ball"],
+ booking_type='invalid'
+ )
+
+ def test_booking_with_maintance_invalid_sport(self):
+
+ with pytest.raises(EntityError):
+ Booking(
+ start_date= 1738940138,
+ end_date= 1838940138,
+ court_number= 1,
+ sport= SPORT.TENNIS,
+ user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
+ booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
+ materials= ["ball"],
+ booking_type=BOOKING_TYPE.MAINTENCE
+ )
+
def test_booking_to_dict(self):
booking = Booking(
start_date= 1738940138,
end_date= 1838940138,
court_number= 1,
- sport= SPORT.FOOTBALL,
+ sport= SPORT.NA,
user_id= "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
booking_id= "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- materials= ["ball"]
+ materials= ["ball"],
+ booking_type=BOOKING_TYPE.MAINTENCE
)
expected = {
"start_date": 1738940138,
"end_date": 1838940138,
"court_number": 1,
- "sport": "Football",
+ "sport": "NA",
"user_id": "d3b07384-d9a1-4e8a-b3ef-4f1d2a87c6f5",
"booking_id": "a1f5e2c3-7d8b-4c9e-b012-34f6a789d0e1",
- "materials": ["ball"]
+ "materials": ["ball"],
+ "type": BOOKING_TYPE.MAINTENCE.value
}
assert booking.to_dict() == expected
\ No newline at end of file
diff --git a/tests/shared/infra/repositories/test_booking_repository_dynamo.py b/tests/shared/infra/repositories/test_booking_repository_dynamo.py
index 59c0241..1a2a31d 100644
--- a/tests/shared/infra/repositories/test_booking_repository_dynamo.py
+++ b/tests/shared/infra/repositories/test_booking_repository_dynamo.py
@@ -5,13 +5,16 @@
from src.shared.domain.entities.booking import Booking
class TestBookingRepositoryDynamo:
-
+
@pytest.mark.skip("Can't run test in github actions")
def test_dynamo_get_all_bookings(self):
dynamo_repo = BookingRepositoryDynamo()
mock_repo = BookingRepositoryMock()
dynamo_bookings = dynamo_repo.get_all_bookings()
mock_bookings = mock_repo.get_all_bookings()
+
+ print( dynamo_bookings[0].start_date )
+
assert len(dynamo_bookings) == len(mock_bookings)
@@ -33,6 +36,9 @@ def test_dynamo_get_bookings_sport(self):
assert len(dynamo_bookings) == len(mock_bookings)
for d_booking, m_booking in zip(dynamo_bookings, mock_bookings):
+
+
+
assert d_booking.start_date == m_booking.start_date
assert d_booking.end_date == m_booking.end_date
assert d_booking.court_number == m_booking.court_number
@@ -57,7 +63,6 @@ def test_get_bookings_by_user_id(self):
for booking in dynamo_bookings:
assert booking.user_id == test_user_id
-
@pytest.mark.skip("Can't run test in github actions")
def test_get_bookings_by_court_number(self):
diff --git a/tests/shared/infra/repositories/test_booking_repository_mock.py b/tests/shared/infra/repositories/test_booking_repository_mock.py
index c42e320..8039bc2 100644
--- a/tests/shared/infra/repositories/test_booking_repository_mock.py
+++ b/tests/shared/infra/repositories/test_booking_repository_mock.py
@@ -1,3 +1,4 @@
+from src.shared.domain.enums.type import BOOKING_TYPE
from src.shared.infra.repositories.booking_repository_mock import BookingRepositoryMock
from src.shared.domain.enums.sport import SPORT
from src.shared.domain.entities.booking import Booking
@@ -6,7 +7,7 @@
class TestBookingRepositoryMock:
def test_create_booking(self):
repo_mock = BookingRepositoryMock()
- new_booking = Booking(start_date=1634576165000, end_date=1634583365000, court_number=1,sport=SPORT.TENNIS, user_id='c8435c66-13a4-4641-9d54-773b4b8ccd09', booking_id='c2d3bebf-dc0d-4fc1-861c-506a40cc2036', materials=['Raquete', 'Bola', 'Rede', 'Tenis'])
+ new_booking = Booking(start_date=1634576165000, end_date=1634583365000, court_number=1,sport=SPORT.TENNIS, user_id='c8435c66-13a4-4641-9d54-773b4b8ccd09', booking_id='c2d3bebf-dc0d-4fc1-861c-506a40cc2036', materials=['Raquete', 'Bola', 'Rede', 'Tenis'], booking_type=BOOKING_TYPE.TRAINING)
len_before = len(repo_mock.bookings)
response = repo_mock.create_booking(new_booking)
@@ -40,7 +41,7 @@ def test_get_booking(self):
assert booking is not None
assert booking.booking_id == booking_id
- assert booking.user_id == 'c8435c66-13a4-4641-9d54-773b4b8ccc98'
+ assert booking.user_id == '1f25448b-3429-4c19-8287-d9e64f17bc3a'
assert booking.sport == SPORT.TENNIS
assert booking.court_number == 1
assert booking.start_date == 1634576165000
@@ -58,9 +59,14 @@ def test_get_all_bookings(self):
def test_delete_booking(self):
repo_mock = BookingRepositoryMock()
booking_id = 'b1d3bebf-dc0d-4fc1-861c-506a40cc2925'
+ user = {
+ 'user_id': 'd351a9b1-937f-423c-a9d1-9929b5795be1',
+ 'email': 'user@email.com',
+ 'role': 'ADMIN'
+ }
len_before = len(repo_mock.bookings)
- deleted_booking = repo_mock.delete_booking(booking_id)
+ deleted_booking = repo_mock.delete_booking(booking_id, user)
len_after = len(repo_mock.bookings)
assert deleted_booking is not None
diff --git a/tests/shared/infra/repositories/test_reservation_repository_dynamo.py b/tests/shared/infra/repositories/test_reservation_repository_dynamo.py
index b486e55..e465106 100644
--- a/tests/shared/infra/repositories/test_reservation_repository_dynamo.py
+++ b/tests/shared/infra/repositories/test_reservation_repository_dynamo.py
@@ -10,7 +10,7 @@
class TestReservationRepositoryDynamo:
-
+
@pytest.mark.skip("Can't run test in github actions")
def test_dynamo_delete_court(self):
dynamo_repo = ReservationRepositoryDynamo()
@@ -30,7 +30,7 @@ def test_dynamo_delete_court_not_found(self):
@pytest.mark.skip("Can't run test in github actions")
def test_update_court(self):
repo = ReservationRepositoryDynamo()
- resp = repo.update_court(number=3, photo="https://www.linkedin.com/in/giovanna-albuquerque-16917a245/")
+ resp = repo.update_court(number=3, new_photo="https://www.linkedin.com/in/giovanna-albuquerque-16917a245/")
assert resp.number == 3
assert resp.photo == "https://www.linkedin.com/in/giovanna-albuquerque-16917a245/"
@@ -62,6 +62,6 @@ def test_dynamo_create_court(self):
new_court = Court(number=6, status=STATUS.MAINTENANCE, is_field=False, photo=None)
size = len(dynamo_repo.get_all_courts())
- assert new_court.__dict__ == dynamo_repo.create_court(new_court).__dict__
- assert dynamo_repo.get_court(6).__dict__ == new_court.__dict__
+ assert new_court == dynamo_repo.create_court(new_court)
+ assert dynamo_repo.get_court(6) == new_court