winderoman commited on
Commit
35c6a2c
1 Parent(s): 3637185

Add application file

Browse files
.env ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ DB_HOST = boovngmcolkrlajvvjia-mysql.services.clever-cloud.com
2
+ DB_USER = umukctgy3i8noafv
3
+ DB_PASSWORD = wqSy96POmhKjWfeOYt8j
4
+ DB_NAME = boovngmcolkrlajvvjia
5
+ # ---------------------------------------------------------------
6
+ # DB_HOST = localhost
7
+ # DB_USER = root
8
+ # DB_PASSWORD = ""
9
+ # DB_NAME = barberia
10
+ DB_PORT = 3306
11
+ ALGORITHM=HS256
12
+
13
+ SECRET_KEY = roman456alexand3r
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ __pycache__/
Dockerfile ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9
2
+
3
+ WORKDIR /code
4
+
5
+ COPY ./requirements.txt /code/requirements.txt
6
+
7
+ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
8
+
9
+ COPY . .
10
+
11
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
core/config.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dotenv import load_dotenv
2
+ import os
3
+
4
+ # Obtener la ruta al archivo .env
5
+ dotenv_path = os.path.join(os.path.dirname(__file__),'..','.env')
6
+
7
+ # Cargar variables de entorno desde el archivo .env
8
+ load_dotenv(dotenv_path)
9
+
10
+ class Settings:
11
+ PROJECT_NAME: str = "Barber-Shop"
12
+ PROJECT_VERSION: str = "0.0.1"
13
+ PROJECT_DESCRIPTION: str = "Aplicacion para administrar los ingresos de una barberia"
14
+
15
+ DB_HOST: str = os.getenv("DB_HOST")
16
+ DB_USER: str = os.getenv("DB_USER")
17
+ DB_PASSWORD: str = os.getenv("DB_PASSWORD")
18
+ DB_NAME: str = os.getenv("DB_NAME")
19
+ DB_PORT: str = os.getenv("DB_PORT",3306) # por defecto
20
+
21
+ DATABASE_URL = f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}"
22
+
23
+ SECRET_KEY:str = os.getenv("SECRET_KEY")
24
+ TOKEN_EXPIRE_MIN = 1200
25
+ ALGORITHM: str = os.getenv("ALGORITHM")
26
+
27
+ settings = Settings()
core/seguridad.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from passlib.context import CryptContext
2
+ from datetime import datetime,timedelta
3
+ from jose import JWTError,jwt
4
+ from core.config import settings
5
+
6
+ # Configurar hashing de contraselas
7
+ pwd_context = CryptContext(schemes=["bcrypt"],deprecated="auto")
8
+
9
+ # Funcion para generar un hash_passw
10
+
11
+ def get_hashed_password(password :str):
12
+ return pwd_context.hash(password)
13
+
14
+ # Funcion para verificar una contraseña hashada
15
+ def verify_password(plain_password:str,hashed_password:str):
16
+ return pwd_context.verify(plain_password,hashed_password)
17
+
18
+ # Crear un token JWT
19
+ def create_access_token(data:dict):
20
+ to_encode = data.copy()
21
+ expire = datetime.utcnow() + timedelta(minutes=settings.TOKEN_EXPIRE_MIN)
22
+ to_encode.update({"exp":expire})
23
+ encode_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
24
+ return encode_jwt
25
+
26
+ # Funcion para verificar si un token valido
27
+ async def verify_token(token:str):
28
+ try:
29
+ payload = jwt.decode(token,settings.SECRET_KEY,algorithms=[settings.ALGORITHM])
30
+ user:str = payload.get("sub") # obtener identificador de usuario
31
+ return user
32
+ except jwt.ExpiredSignatureError: # token expirado
33
+ return None
34
+ except JWTError:
35
+ return None
core/utils.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import secrets
2
+ import string
3
+
4
+ # Funcion para generar un ID de usuario aleatorio
5
+ def generate_user_id(length = 30):
6
+ # Caracteres posibles para le ID aleatorio
7
+ characteres = string.ascii_letters + string.digits
8
+
9
+ # Genera un ID aleatorio de la longitud deseada
10
+ random_id = ''.join(secrets.choice(characteres) for _ in range(length))
11
+
12
+ return random_id
13
+
14
+ list_reserve = ["10:00:00","11:00:00","14:00:00","15:00:00","16:00:00","17:00:00","18:00:00","19:00:00","20:00:00"]
15
+ def get_list_reserve():
16
+ return list_reserve
17
+
18
+ def sort_object_by_index(object):
19
+ sorted_keys = sorted(object.keys())
20
+ sorted_reservations = {key: object[key] for key in sorted_keys}
21
+ return sorted_reservations
cruds/MovimientosCrud.py ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ from models.MovimientosM import Movimiento
3
+ from fastapi import HTTPException
4
+ from schemas.MovimientosSh import *
5
+ from sqlalchemy.orm import Session
6
+ from datetime import date,datetime,timedelta
7
+ from sqlalchemy import func,between
8
+
9
+ def create_new_movimiento(movi:MovimientosCreate,id_usuario:str,db:Session):
10
+ db_movimiento = Movimiento(
11
+ id_usuario = id_usuario,
12
+ cuenta = movi.cuenta,
13
+ tipo_movimiento = movi.tipo_movimiento,
14
+ fecha = movi.fecha,
15
+ descripcion = movi.descripcion,
16
+ )
17
+
18
+ try:
19
+ db.add(db_movimiento)
20
+ db.commit()
21
+ db.refresh(db_movimiento)
22
+ db.close()
23
+ return db_movimiento
24
+ except Exception as e :
25
+ db.rollback()
26
+ # Imprimir el error en la consola
27
+ print(f"Error al crear un usuario: {str(e)}",file=sys.stderr)
28
+ raise HTTPException(status_code=500,detail=f"Error al crear un movimiento: {str(e)} ")
29
+
30
+ def get_weekly_expenses(db: Session, user_id: str,tipo:str):
31
+ today = datetime.today()
32
+ if tipo == "SEMANA":
33
+ start_week = today - timedelta(days=today.weekday())
34
+ end_week = start_week + timedelta(days=6)
35
+
36
+ if tipo == "MES":
37
+ start_week = today.replace(day=1)
38
+ next_month = start_week.replace(month=start_week.month + 1, day=1)
39
+ end_week = next_month - timedelta(days=1)
40
+
41
+ if tipo == "HOY":
42
+ start_week = today.replace(hour=0, minute=0, second=0, microsecond=0)
43
+
44
+ # Obtener el último momento del día (23:59:59)
45
+ end_week = today.replace(hour=23, minute=59, second=59, microsecond=999999)
46
+
47
+ expenses = db.query(Movimiento.descripcion, Movimiento.cuenta,Movimiento.id_movimientos).\
48
+ filter(Movimiento.id_usuario == user_id,
49
+ Movimiento.tipo_movimiento == 'GASTO',
50
+ Movimiento.estado_gasto == True,
51
+ between(Movimiento.fecha, start_week.date(), end_week.date())).\
52
+ all()
53
+
54
+ total_expenses = sum(exp[1] for exp in expenses)
55
+ details = [{"descripcion": exp[0], "cuenta": float(exp[1]),"id_movimientos":int(exp[2])} for exp in expenses]
56
+ return total_expenses,details
57
+
58
+
59
+ def get_consulted_expenses(db: Session, user_id: str,start_week : date,end_week:date):
60
+ expenses = db.query(Movimiento.descripcion, Movimiento.cuenta).\
61
+ filter(Movimiento.id_usuario == user_id,
62
+ Movimiento.tipo_movimiento == 'GASTO',
63
+ Movimiento.estado_gasto == True,
64
+ between(Movimiento.fecha, start_week, end_week)).\
65
+ all()
66
+
67
+ total_expenses = sum(exp[1] for exp in expenses) # Sumando las cuentas (índice 1)
68
+
69
+ # Convertir los detalles de gastos a una lista de diccionarios
70
+ details = [{"descripcion": exp[0], "cuenta": float(exp[1])} for exp in expenses]
71
+ return total_expenses,details
72
+
73
+ def buscar_movimientos(id:int,db:Session):
74
+ movimiento_db = db.query(Movimiento).filter(Movimiento.id_movimientos == id).first()
75
+ return movimiento_db
76
+
77
+ def money_account(db:Session,id_usuario:str,fecha_inicio:date = None,fecha_fin:date = None):
78
+ if fecha_inicio is None or fecha_fin is None:
79
+ fecha_inicio = str(date.today())
80
+ fecha_fin = str(date.today())
81
+
82
+ ingresos = db.query(func.sum(Movimiento.cuenta)).filter(
83
+ Movimiento.tipo_movimiento == 'INGRESO',
84
+ between(Movimiento.fecha,fecha_inicio,fecha_fin),
85
+ Movimiento.id_usuario == id_usuario,
86
+ Movimiento.estado_gasto == 1
87
+ ).scalar() or 0
88
+
89
+ gastos = db.query(func.sum(Movimiento.cuenta)).filter(
90
+ Movimiento.tipo_movimiento == 'GASTO',
91
+ between(Movimiento.fecha,fecha_inicio,fecha_fin),
92
+ Movimiento.id_usuario == id_usuario,
93
+ Movimiento.estado_gasto == 1
94
+ ).scalar() or 0
95
+
96
+ resultado = ingresos - gastos;
97
+ return resultado
98
+
99
+
100
+ def update_movimiento_crud(movi:MovimientosUpdate,db:Session):
101
+ movimiento_db = buscar_movimientos(movi.id_movimientos,db)
102
+ if movimiento_db:
103
+ try:
104
+ movimiento_db.cuenta = movi.cuenta
105
+ movimiento_db.tipo_movimiento = movi.tipo_movimiento
106
+ movimiento_db.descripcion = movi.descripcion
107
+ db.add(movimiento_db)
108
+ db.commit()
109
+ db.refresh(movimiento_db)
110
+ return movimiento_db
111
+ except Exception as e :
112
+ db.rollback()
113
+ print(f"Error al actualizar movimiento: {str(e)}",file=sys.stderr)
114
+ raise HTTPException(status_code=500,detail=f"Error al actualizar un movimiento: {str(e)} ")
115
+ return None
116
+
117
+
118
+ def update_movimientos_status_crud(movi:MovimientosUpdateStatus, db:Session):
119
+ movimientos_db = buscar_movimientos(movi.id_movimientos, db)
120
+ if movimientos_db:
121
+ try:
122
+ movimientos_db.estado_gasto = movi.estado_gasto
123
+ db.add(movimientos_db)
124
+ db.commit()
125
+
126
+ return True
127
+ except Exception as e :
128
+ db.rollback()
129
+ print(f"Error al update un movimiento {str(e)}",file=sys.stderr)
130
+ raise HTTPException(status_code=500,detail=f"Error al update movimiento: {str(e)} ")
131
+
132
+ return False
cruds/ReservaCrud.py ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+
3
+ from fastapi import HTTPException
4
+ from schemas.ReservaSh import *
5
+ from models.ReservaM import Reserva
6
+ from sqlalchemy.orm import Session
7
+ from sqlalchemy import asc,between
8
+ from datetime import date,time
9
+ from datetime import datetime
10
+ from core.utils import get_list_reserve,sort_object_by_index
11
+ list_reserve = get_list_reserve()
12
+ def create_new_reserve(reserve:ReserveCreate, id_usuario:str,created_at:datetime,db:Session):
13
+ isExistReserve = get_reserve_by_time_date(reserve.hora,reserve.fecha,id_usuario,db)
14
+ if isExistReserve != None:
15
+ raise HTTPException(status_code=409, detail="Conflict:The reserve already exist.")
16
+ db_reserve = Reserva(
17
+ id_usuario = id_usuario,
18
+ cliente = reserve.cliente,
19
+ fecha = reserve.fecha,
20
+ hora = reserve.hora,
21
+ created_at = created_at
22
+ )
23
+
24
+ try:
25
+ db.add(db_reserve)
26
+ db.commit()
27
+ db.refresh(db_reserve)
28
+ db.close()
29
+
30
+ return db_reserve
31
+ except Exception as e:
32
+ db.rollback()
33
+ print(f"error creating reserve: {str(e)}",file=sys.stderr)
34
+ raise HTTPException(status_code=500,detail=f"error creating reserve: {str(e)}")
35
+
36
+ def update_reserve(reserve:ReserveUpdate, user_id:str, db:Session):
37
+ reserve_db = get_reserve_by_id(reserve.id_reserva, user_id, db)
38
+ if reserve_db.estado_reserva == 0:
39
+ try:
40
+ reserve_db.cliente = reserve.cliente
41
+ reserve_db.fecha = reserve.fecha
42
+ reserve_db.hora = reserve.hora
43
+ db.add(reserve_db)
44
+ db.commit()
45
+ db.refresh(reserve_db)
46
+ db.close()
47
+
48
+ return reserve_db
49
+ except Exception as e:
50
+ db.rollback()
51
+ print(f"error updating reserve: {str(e)}",file=sys.stderr)
52
+ raise HTTPException(status_code=500,detail=f"error updating reserve: {str(e)} ")
53
+ else:
54
+ return None
55
+
56
+ def update_reserve_tarifa(reserve:ReserveUpdateTarifa, user_id:str, db:Session):
57
+ reserve_db = get_reserve_by_id(reserve.id_reserva, user_id, db)
58
+ if reserve_db:
59
+ try:
60
+ reserve_db.estado_reserva = 1
61
+ reserve_db.id_tarifa = reserve.id_tarifa
62
+
63
+ db.add(reserve_db)
64
+ db.commit()
65
+ db.refresh(reserve_db)
66
+ db.close()
67
+
68
+ return reserve_db
69
+ except Exception as e:
70
+ db.rollback()
71
+ print(f"error updating reserve: {str(e)}",file=sys.stderr)
72
+ raise HTTPException(status_code=500,detail=f"error updating reserve: {str(e)} ")
73
+ else:
74
+ return None
75
+
76
+
77
+ def get_reserve_by_id(id_reserve:int, user_id:str, db:Session):
78
+ reserve_db = db.query(Reserva).filter((Reserva.id_reserva == id_reserve) & (Reserva.id_usuario == user_id) ).first()
79
+ return reserve_db
80
+
81
+ def get_reserve_by_time_date(time:time,date:date, user_id:str, db:Session):
82
+ reserve_db = db.query(Reserva).filter(
83
+ Reserva.hora == time,
84
+ Reserva.fecha == date,
85
+ Reserva.id_usuario == user_id
86
+ ).first()
87
+ if reserve_db is None:
88
+ return None
89
+ return reserve_db
90
+
91
+ def update_status_reserve(reserve:ReserveUpdateStatus,db:Session,id_user:str):
92
+ reserve_db = get_reserve_by_id(reserve.id_reserva,id_user,db)
93
+ if reserve_db:
94
+ try:
95
+ reserve_db.estado_reserva = reserve.estado_reserva
96
+ db.add(reserve_db)
97
+ db.commit()
98
+ return reserve_db
99
+
100
+ except Exception as e:
101
+ db.rollback()
102
+ print(f"Error al update una reserva {str(e)}",file=sys.stderr)
103
+ raise HTTPException(status_code=500,detail=f"Error al update una reserva: {str(e)} ")
104
+ raise HTTPException(status_code=500,detail="No se encontro nada")
105
+
106
+
107
+
108
+
109
+ def get_reserve_false(id_user:str,db):
110
+ fecha = str(date.today())
111
+ reserve_db = db.query(Reserva).filter((Reserva.id_usuario == id_user ) & (Reserva.fecha == fecha) & (Reserva.estado_reserva == 0)).order_by(asc(Reserva.hora)).all()
112
+ return reserve_db
113
+
114
+ def get_reserve_all(id_user:str,db,fecha_inicio:date = None,fecha_fin:date = None):
115
+ if fecha_inicio is None or fecha_fin is None:
116
+ fecha_inicio = str(date.today())
117
+ fecha_fin = str(date.today())
118
+
119
+ reserve_db = db.query(Reserva).filter(
120
+ Reserva.id_usuario == id_user,
121
+ between(Reserva.fecha, fecha_inicio, fecha_fin)
122
+ ).order_by(asc(Reserva.hora)).all()
123
+
124
+ return reserve_db
125
+
126
+ def get_reservations_by_date(id_user:str,db,fecha:date = None):
127
+ if (fecha is None): fecha = str(date.today())
128
+ reservations_db = db.query(Reserva).filter(
129
+ Reserva.id_usuario == id_user,
130
+ Reserva.fecha == fecha
131
+ ).all()
132
+ return reservations_db
133
+
134
+
135
+ def get_reservations_available(id_user:str,db,fecha:date = None):
136
+ list_reservations = get_reservations_by_date(id_user,db,fecha)
137
+ object_reservations = {}
138
+
139
+ for reserva_db in list_reservations:
140
+ time_reserve = reserva_db.hora.strftime('%H:%M:%S')
141
+ if time_reserve in list_reserve:
142
+ object_reservations[time_reserve] = reserva_db.cliente;
143
+
144
+ for time_reserve in list_reserve:
145
+ # bueno mi so el setdefault lo que hace es que si el objeto tiene esa clave no lo modifica de lo contrario coloca el valor Disponible
146
+ object_reservations.setdefault(time_reserve, "Disponible")
147
+
148
+ object_sort = sort_object_by_index(object_reservations)
149
+ reservations_available = list(object_sort.items())
150
+ return reservations_available
151
+
152
+
153
+
cruds/TarifaCrud.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ from models.TarifaM import Tarifa
3
+ from fastapi import HTTPException
4
+ from schemas.TarifaSh import *
5
+ from sqlalchemy.orm import Session
6
+ from sqlalchemy import desc
7
+ from datetime import datetime
8
+
9
+ def create_new_tarifa(tarifa_create:TarifaCreate,id_usuario:str,fecha_hora:datetime,db:Session):
10
+ db_tarifa = Tarifa(
11
+ id_usuario = id_usuario,
12
+ descripcion = tarifa_create.descripcion,
13
+ costo = tarifa_create.costo,
14
+ created_at = fecha_hora
15
+ )
16
+
17
+ try:
18
+ db.add(db_tarifa)
19
+ db.commit()
20
+ db.refresh(db_tarifa)
21
+ db.close()
22
+ return db_tarifa
23
+ except Exception as e :
24
+ db.rollback()
25
+ # Imprimir el error en la consola
26
+ print(f"Error al crear una tarifa: {str(e)}",file=sys.stderr)
27
+ raise HTTPException(status_code=500,detail=f"Error al crear una tarifa: {str(e)} ")
28
+
29
+ def get_all_tarifas(db:Session,id_usuario:str):
30
+ tarifas = db.query(Tarifa).filter(Tarifa.id_usuario == id_usuario,Tarifa.estado_tarifa == 1).order_by(desc(Tarifa.created_at)).all()
31
+ if tarifas is None:
32
+ return None
33
+ return tarifas
34
+
35
+ def get_tarifa_by_id(id_tarifa:int,db:Session):
36
+ tarifa_db = db.query(Tarifa).filter(Tarifa.id_tarifa == id_tarifa).first()
37
+ return tarifa_db
38
+
39
+ def tarifa_update(tarifaUpdate:TarifaUpdate,db:Session):
40
+ tarifa_db = get_tarifa_by_id(tarifaUpdate.id_tarifa,db)
41
+ if tarifa_db:
42
+ try:
43
+ tarifa_db.descripcion = tarifaUpdate.descripcion
44
+ tarifa_db.costo = tarifaUpdate.costo
45
+ db.add(tarifa_db)
46
+ db.commit()
47
+ db.refresh(tarifa_db)
48
+ return tarifa_db
49
+ except Exception as e :
50
+ db.rollback()
51
+ print(f"Error al crear un usuario: {str(e)}",file=sys.stderr)
52
+ raise HTTPException(status_code=500,detail=f"Error al crear usuario: {str(e)} ")
53
+ raise HTTPException(status_code=404, detail="No existen tarifas")
54
+
55
+
56
+ def delete_tarifa(tarifaUpdateStatus:TarifaBase,db:Session):
57
+ tarifa_db = get_tarifa_by_id(tarifaUpdateStatus.id_tarifa,db)
58
+ if tarifa_db:
59
+ try:
60
+ tarifa_db.estado_tarifa = False
61
+ db.add(tarifa_db)
62
+ db.commit()
63
+ db.refresh(tarifa_db)
64
+ return tarifa_db
65
+ except Exception as e:
66
+ db.rollback()
67
+ print(f"Error al Editar Estado: {str(e)}",file=sys.stderr)
68
+ raise HTTPException(status_code=500,detail=f"Error al Editar usuario: {str(e)} ")
69
+ raise HTTPException(status_code=404, detail="No existe la tarifas")
70
+
71
+
cruds/UsuarioCrud.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys # Mandar mensajes de error al log
2
+
3
+ from models.UsuarioM import User
4
+ from fastapi import HTTPException
5
+ from schemas.UsuarioSh import UserCreate,UserRead, UserUpdate, UserUpdateStatus
6
+ from sqlalchemy.orm import Session
7
+ from core.seguridad import get_hashed_password,verify_password
8
+ from core.utils import generate_user_id
9
+
10
+ def create_new_user(user:UserCreate,db:Session):
11
+ db_user = User(
12
+ id_usuario = generate_user_id(),
13
+ correo = user.correo,
14
+ contrasenia = get_hashed_password(user.contrasenia),
15
+ rol = "BARBERO"
16
+ )
17
+
18
+ try:
19
+ db.add(db_user)
20
+ db.commit()
21
+ db.refresh(db_user)
22
+ db.close()
23
+ return db_user
24
+ except Exception as e :
25
+ db.rollback()
26
+ # Imprimir el error en la consola
27
+ print(f"Error al crear un usuario: {str(e)}",file=sys.stderr)
28
+ raise HTTPException(status_code=500,detail=f"Error al crear usuario: {str(e)} ")
29
+
30
+ def get_user_by_email(email:str,db:Session):
31
+ user = db.query(User).filter(User.correo == email).first()
32
+ return user
33
+
34
+ # def get_user_by_email_verify(user_id : str,email:str,db:Session):
35
+ # user_db = db.query(User).filter(User.user_id == user_id).first()
36
+ # if user_db.mail != email:
37
+ # validation = get_user_by_email(email,db)
38
+ # if validation is None:
39
+ # return True
40
+ # else:
41
+ # return False
42
+ # return True
43
+
44
+
45
+
46
+ def get_user_by_id(id:str,db:Session):
47
+ user = db.query(User).filter(User.id_usuario == id).first()
48
+ return user
49
+
50
+ def get_all_users_bd(db:Session):
51
+ users = db.query(User).filter(User.rol == "BARBERO").all()
52
+ return users
53
+
54
+ def authenticate_user(username:str,password:str,db:Session):
55
+ user = get_user_by_email(username,db)
56
+ if not user:
57
+ return False
58
+ if not verify_password(password,user.contrasenia):
59
+ return False
60
+
61
+ return user
62
+
63
+ def update_user_crud(user:UserUpdate,db:Session):
64
+ user_db = get_user_by_id(user.id_usuario,db)
65
+ if user_db:
66
+ try:
67
+ if user.contrasenia:
68
+ user_db.contrasenia = get_hashed_password(user.contrasenia)
69
+ user_db.correo = user.correo
70
+ db.add(user_db)
71
+ db.commit()
72
+ db.refresh(user_db)
73
+ return user_db
74
+ except Exception as e :
75
+ db.rollback()
76
+ print(f"Error al crear un usuario: {str(e)}",file=sys.stderr)
77
+ raise HTTPException(status_code=500,detail=f"Error al crear usuario: {str(e)} ")
78
+ return None
79
+
80
+
81
+ def update_user_status_crud(user:UserUpdateStatus, db:Session):
82
+ user_db = get_user_by_id(user.user_id, db)
83
+ if user_db:
84
+ try:
85
+ user_db.estado_usuario = user.estado_usuario
86
+ db.add(user_db)
87
+ db.commit()
88
+
89
+ return True
90
+ except Exception as e :
91
+ db.rollback()
92
+ print(f"Error al crear un usuario: {str(e)}",file=sys.stderr)
93
+ raise HTTPException(status_code=500,detail=f"Error al crear usuario: {str(e)} ")
94
+
95
+ return False
96
+
db/barber_db.sql ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ DROP DATABASE IF EXISTS barberia;
2
+ CREATE DATABASE barberia;
3
+ USE barberia;
4
+
5
+ SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
6
+ START TRANSACTION;
7
+ SET time_zone = "-05:00";
8
+
9
+
10
+
11
+ CREATE TABLE usuario(
12
+ id_usuario CHAR(30) PRIMARY KEY,
13
+ correo VARCHAR(80) NOT NULL,
14
+ contrasenia VARCHAR(250) NOT NULL,
15
+ rol ENUM('SUPERADMIN','BARBERO'),
16
+ created_at TIMESTAMP,
17
+ estado_usuario TINYINT(1) DEFAULT 1
18
+ );
19
+
20
+ CREATE TABLE tarifa(
21
+ id_tarifa INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
22
+ id_usuario CHAR(30),
23
+ descripcion VARCHAR(100) NOT NULL,
24
+ costo SMALLINT UNSIGNED NOT NULL,
25
+ created_at TIMESTAMP,
26
+ estado_tarifa TINYINT(1) DEFAULT 1,
27
+ FOREIGN KEY (id_usuario) REFERENCES usuario(id_usuario)
28
+ );
29
+
30
+ CREATE TABLE reserva (
31
+ id_reserva INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
32
+ id_usuario CHAR(30),
33
+ cliente VARCHAR(100) NOT NULL,
34
+ fecha DATE NOT NULL,
35
+ hora TIME NOT NULL,
36
+ estado_reserva TINYINT(1) DEFAULT 0,
37
+ id_tarifa INT UNSIGNED,
38
+ created_at TIMESTAMP,
39
+ FOREIGN KEY (id_tarifa) REFERENCES tarifa(id_tarifa),
40
+ FOREIGN KEY (id_usuario) REFERENCES usuario(id_usuario)
41
+ );
42
+
43
+ CREATE TABLE movimientos(
44
+ id_movimientos INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
45
+ id_usuario CHAR(30),
46
+ cuenta FLOAT(10,2) NOT NULL,
47
+ tipo_movimiento ENUM('INGRESO','GASTO'),
48
+ fecha DATE NOT NULL,
49
+ descripcion TEXT,
50
+ created_at TIMESTAMP,
51
+ estado_gasto TINYINT(1) DEFAULT 1,
52
+ FOREIGN KEY (id_usuario) REFERENCES usuario(id_usuario)
53
+ );
54
+
55
+
56
+ INSERT INTO `usuario` (`id_usuario`, `correo`, `contrasenia`, `rol`, `estado_usuario`) VALUES
57
+ ('42wgnk2xMsBODXI9CpFDftUxDSmSMn', 'winder@gmail.com', '$2b$12$cyr2SZu703rNSF5OkxghCuzPlNZGOSDS2clPPJcCSau3RPDHtdes.', 'SUPERADMIN', 1),
58
+ ('7hDj9DmYUSdfrrbjQU5iWKClL4UYen', 'patron@mail.com', '$2b$12$SfVZEyvAGZuGdlnKYZKBdOEpbgBLAlR4d5cF6KPkONyWWLKD3pmqm', 'SUPERADMIN', 1),
59
+ ('DwoznM0AvFXV28EPDhpCl9wPOsqFux', 'user10@example.com', '$2b$12$fsdlCeTvr1Iq5jIX5m93GuKGyfWmkzo6rI7LOAAgmAbo7T4T96xNC', 'BARBERO', 1),
60
+ ('G0BgHtRKvSmzaoMvXmcNZEyluSM7y6', 'milu@mail.com', '$2b$12$zYuj8Nt4GHfsKy9F3S9N2OQ5Lq62TtaJEtRJUSyioIhjLKGAfxwsq', 'BARBERO', 1),
61
+ ('Gp1q2OZwEv3aklEto8cX9pvpEKMHFT', 'mateo@mail.com', '$2b$12$ExyQSeLcG/1ZovP7I/cIHOYbmpcK3BQWjWHSuSDbJXuTQfbJji.MW', 'SUPERADMIN', 1),
62
+ ('JG2PgMvagVKxRWEWK7lNAXle6TTACF', 'patron2@gmail.com', '$2b$12$iSJvhNYbQhdXu3pZJG5WSey1MZNxFHvnQY5Ljku3oCeBKpw3l6h02', 'SUPERADMIN', 1),
63
+ ('mvEPrFmVAHxiyC1eOqGu5zmT0mfrz6', 'braulio@gmail.com', '$2b$12$L3lSqvjUp9FBEu99pRQDgO2TtTIiq4aK92XvNKMwyLJ.oV7Dmv8Ty', 'SUPERADMIN', 1),
64
+ ('N8Hw0t9SXbRgjIppRteiGZeWxRLkru', 'user3@example.com', '$2b$12$sguVhgGXqsk..5P7lFqGyeFi9ge8MOc4T1ckx/1T0360PTYBRSDKG', 'BARBERO', 1),
65
+ ('OaYhqvnl6s0DJTANQX0jFPrQj8MbDw', 'JUANPISS@example.com', '$2b$12$dcxtPEBDWZR9IT.bVmSmDeEfS6wvx.G.M3rWvUlFzw6aVR1HY3oM6', 'BARBERO', 0),
66
+ ('plZr7wfSLDQac8bj1G5zVoEpr10tUM', 'user@example.com', '$2b$12$O3fLsh5FT2r9sFQztpG9..m1Nzu1C./wjseVL4Yi6CEWQvaViEFc.', 'BARBERO', 1),
67
+ ('Q62ehy208AhtcLeXgE0zzsQmrHvcec', 'user5@example.com', '$2b$12$ybcsZsGkHiygzAmDLWzuPOL0Rj9iopxcxJ66cFcfeLB3NSIvA8cC2', 'BARBERO', 1),
68
+ ('U3h1ZpO3onjHyfYu0OYh558eUiT5aF', 'user2@example.com', '$2b$12$Yo9ZMDnBUg0UfYaISgm6ROiYBK0mgPFJhoo0vWyCYnWijgV5P8SKW', 'BARBERO', 1),
69
+ ('YzR0ReQOG8bvUuv31J4yGBW8aAuVCS', 'user4@example.com', '$2b$12$SeT65vSaR5WkxJqkhmLEuez555LEaVtRzzt2aqy1tAgr1iCGH50Z2', 'BARBERO', 1);
70
+
db/boovngmcolkrlajvvjia.sql ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ DROP DATABASE IF EXISTS barberia;
4
+ CREATE DATABASE barberia;
5
+ USE barberia;
6
+
7
+ SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
8
+ START TRANSACTION;
9
+ SET time_zone = "-05:00";
10
+
11
+
12
+
13
+ CREATE TABLE `movimientos` (
14
+ `id_movimientos` int UNSIGNED NOT NULL,
15
+ `cuenta` float(10,2) NOT NULL,
16
+ `tipo_movimiento` enum('INGRESO','GASTO') DEFAULT NULL,
17
+ `fecha` date NOT NULL,
18
+ `descripcion` text,
19
+ created_at TIMESTAMP ,
20
+ `estado_gasto` tinyint(1) DEFAULT '1'
21
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
22
+
23
+
24
+
25
+ INSERT INTO `movimientos` (`id_movimientos`, `cuenta`, `tipo_movimiento`, `fecha`, `descripcion`, `estado_gasto`) VALUES
26
+ (1, 1000.00, 'INGRESO', '2024-02-26', 'hola mundo', 1),
27
+ (2, 1000.00, 'INGRESO', '2024-02-26', 'hola mundo', 1),
28
+ (3, 1000.00, 'INGRESO', '2024-02-26', 'hola mundo', 1),
29
+ (4, 1000.00, 'INGRESO', '2024-02-26', 'hola mundo', 1),
30
+ (5, 100.00, 'GASTO', '2024-02-26', 'hola mundo ', 1),
31
+ (6, 0.00, 'INGRESO', '2024-02-26', 'probando2', 0);
32
+
33
+ CREATE TABLE `reserva` (
34
+ `id_reserva` int UNSIGNED NOT NULL,
35
+ `cliente` varchar(100) NOT NULL,
36
+ `fecha` date NOT NULL,
37
+ `hora` time NOT NULL,
38
+ `estado_reserva` tinyint(1) DEFAULT '0',
39
+ created_at TIMESTAMP ,
40
+ `id_tarifa` int UNSIGNED DEFAULT NULL
41
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
42
+
43
+
44
+ INSERT INTO `reserva` (`id_reserva`, `cliente`, `fecha`, `hora`, `estado_reserva`, `id_tarifa`) VALUES
45
+ (1, 'jaimito', '2024-02-26', '10:13:29', 0, NULL);
46
+
47
+
48
+ CREATE TABLE `tarifa` (
49
+ `id_tarifa` int UNSIGNED NOT NULL,
50
+ `descripcion` varchar(100) NOT NULL,
51
+ `costo` smallint UNSIGNED NOT NULL,
52
+ created_at TIMESTAMP ,
53
+ `estado_tarifa` tinyint(1) DEFAULT '1'
54
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
55
+
56
+
57
+ CREATE TABLE `usuario` (
58
+ `id_usuario` char(30) NOT NULL,
59
+ `correo` varchar(80) NOT NULL,
60
+ `contrasenia` varchar(250) NOT NULL,
61
+ `rol` enum('SUPERADMIN','BARBERO') DEFAULT NULL,
62
+ created_at TIMESTAMP ,
63
+ `estado_usuario` tinyint(1) DEFAULT '1'
64
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
65
+
66
+
67
+
68
+ INSERT INTO `usuario` (`id_usuario`, `correo`, `contrasenia`, `rol`, `estado_usuario`) VALUES
69
+ ('42wgnk2xMsBODXI9CpFDftUxDSmSMn', 'winder@gmail.com', '$2b$12$cyr2SZu703rNSF5OkxghCuzPlNZGOSDS2clPPJcCSau3RPDHtdes.', 'SUPERADMIN', 1),
70
+ ('7hDj9DmYUSdfrrbjQU5iWKClL4UYen', 'patron@mail.com', '$2b$12$SfVZEyvAGZuGdlnKYZKBdOEpbgBLAlR4d5cF6KPkONyWWLKD3pmqm', 'SUPERADMIN', 1),
71
+ ('DwoznM0AvFXV28EPDhpCl9wPOsqFux', 'user10@example.com', '$2b$12$fsdlCeTvr1Iq5jIX5m93GuKGyfWmkzo6rI7LOAAgmAbo7T4T96xNC', 'BARBERO', 1),
72
+ ('G0BgHtRKvSmzaoMvXmcNZEyluSM7y6', 'milu@mail.com', '$2b$12$zYuj8Nt4GHfsKy9F3S9N2OQ5Lq62TtaJEtRJUSyioIhjLKGAfxwsq', 'BARBERO', 1),
73
+ ('Gp1q2OZwEv3aklEto8cX9pvpEKMHFT', 'mateo@mail.com', '$2b$12$ExyQSeLcG/1ZovP7I/cIHOYbmpcK3BQWjWHSuSDbJXuTQfbJji.MW', 'SUPERADMIN', 1),
74
+ ('JG2PgMvagVKxRWEWK7lNAXle6TTACF', 'patron2@gmail.com', '$2b$12$iSJvhNYbQhdXu3pZJG5WSey1MZNxFHvnQY5Ljku3oCeBKpw3l6h02', 'SUPERADMIN', 1),
75
+ ('mvEPrFmVAHxiyC1eOqGu5zmT0mfrz6', 'braulio@gmail.com', '$2b$12$L3lSqvjUp9FBEu99pRQDgO2TtTIiq4aK92XvNKMwyLJ.oV7Dmv8Ty', 'SUPERADMIN', 1),
76
+ ('N8Hw0t9SXbRgjIppRteiGZeWxRLkru', 'user3@example.com', '$2b$12$sguVhgGXqsk..5P7lFqGyeFi9ge8MOc4T1ckx/1T0360PTYBRSDKG', 'BARBERO', 1),
77
+ ('OaYhqvnl6s0DJTANQX0jFPrQj8MbDw', 'JUANPISS@example.com', '$2b$12$dcxtPEBDWZR9IT.bVmSmDeEfS6wvx.G.M3rWvUlFzw6aVR1HY3oM6', 'BARBERO', 0),
78
+ ('plZr7wfSLDQac8bj1G5zVoEpr10tUM', 'user@example.com', '$2b$12$O3fLsh5FT2r9sFQztpG9..m1Nzu1C./wjseVL4Yi6CEWQvaViEFc.', 'BARBERO', 1),
79
+ ('Q62ehy208AhtcLeXgE0zzsQmrHvcec', 'user5@example.com', '$2b$12$ybcsZsGkHiygzAmDLWzuPOL0Rj9iopxcxJ66cFcfeLB3NSIvA8cC2', 'BARBERO', 1),
80
+ ('U3h1ZpO3onjHyfYu0OYh558eUiT5aF', 'user2@example.com', '$2b$12$Yo9ZMDnBUg0UfYaISgm6ROiYBK0mgPFJhoo0vWyCYnWijgV5P8SKW', 'BARBERO', 1),
81
+ ('YzR0ReQOG8bvUuv31J4yGBW8aAuVCS', 'user4@example.com', '$2b$12$SeT65vSaR5WkxJqkhmLEuez555LEaVtRzzt2aqy1tAgr1iCGH50Z2', 'BARBERO', 1);
82
+
83
+
84
+
85
+ ALTER TABLE `movimientos`
86
+ ADD PRIMARY KEY (`id_movimientos`);
87
+
88
+
89
+ ALTER TABLE `reserva`
90
+ ADD PRIMARY KEY (`id_reserva`),
91
+ ADD KEY `id_tarifa` (`id_tarifa`);
92
+
93
+
94
+ ALTER TABLE `tarifa`
95
+ ADD PRIMARY KEY (`id_tarifa`);
96
+
97
+
98
+ ALTER TABLE `usuario`
99
+ ADD PRIMARY KEY (`id_usuario`);
100
+
101
+
102
+ ALTER TABLE `movimientos`
103
+ MODIFY `id_movimientos` int UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
104
+
105
+
106
+ ALTER TABLE `reserva`
107
+ MODIFY `id_reserva` int UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
108
+
109
+
110
+ ALTER TABLE `tarifa`
111
+ MODIFY `id_tarifa` int UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
112
+
113
+
114
+ ALTER TABLE `reserva`
115
+ ADD CONSTRAINT `reserva_ibfk_1` FOREIGN KEY (`id_tarifa`) REFERENCES `tarifa` (`id_tarifa`);
116
+ COMMIT;
117
+
db/session.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy import create_engine
2
+ from sqlalchemy.orm import sessionmaker
3
+ from sqlalchemy.ext.declarative import declarative_base
4
+ from core.config import settings
5
+
6
+ DB_URL = settings.DATABASE_URL
7
+
8
+ # Crear una instancia de motor SQLAlchemy
9
+ engine = create_engine(DB_URL,pool_pre_ping=True)
10
+
11
+ # Crear una instancia de sessionmaker
12
+ SessionLocal = sessionmaker(autocommit=False,autoflush=False,bind=engine)
13
+
14
+ # Crear una clase base para las clases de modelo
15
+ Base = declarative_base()
16
+
17
+ # Funcino para crear la sesion de base de datos
18
+ def get_session():
19
+ database = SessionLocal()
20
+ try:
21
+ yield database
22
+ finally:
23
+ database.close()
main.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi.middleware.cors import CORSMiddleware
2
+ from fastapi import FastAPI,APIRouter
3
+ from routes import UsuarioR,MovimientosR,TarifaR, ReservaR
4
+ from core.config import settings
5
+
6
+ api_router = APIRouter()
7
+ api_router.include_router(UsuarioR.router,prefix="/users",tags=["users"])
8
+ api_router.include_router(MovimientosR.router,prefix="/movimientos",tags=["movimientos"])
9
+ api_router.include_router(TarifaR.router,prefix="/tarifas",tags=["tarifas"])
10
+ api_router.include_router(ReservaR.router,prefix="/reserves",tags=["reservas"])
11
+
12
+ app = FastAPI(title=settings.PROJECT_NAME,version=settings.PROJECT_VERSION,description=settings.PROJECT_DESCRIPTION)
13
+
14
+ app.add_middleware(
15
+ CORSMiddleware,
16
+ allow_origins=["*"],
17
+ allow_credentials=True,
18
+ allow_methods=["*"],
19
+ allow_headers=["*"],
20
+ )
21
+ app.include_router(api_router)
22
+
models/Base_class.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import AnyStr
2
+
3
+ from sqlalchemy.ext.declarative import as_declarative
4
+ from sqlalchemy.ext.declarative import declared_attr
5
+
6
+ @as_declarative()
7
+ class Base:
8
+ id:AnyStr
9
+ __name__:str
10
+
11
+ # to generate tablename from classname
12
+ #
13
+ @declared_attr
14
+ def __tablename__(cls) -> str:
15
+ return cls.__name__.lower()
16
+
17
+
models/MovimientosM.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy import Column, Integer, String, Enum, Float, Date, Boolean, func,ForeignKey
2
+ from sqlalchemy.orm import relationship
3
+ from models.Base_class import Base
4
+ from models.UsuarioM import User
5
+ class Movimiento(Base):
6
+ __tablename__ = 'movimientos'
7
+
8
+ id_movimientos = Column(Integer, autoincrement=True, primary_key=True)
9
+ id_usuario = Column(String(30),ForeignKey("usuario.id_usuario"))
10
+ cuenta = Column(Float(10,2), nullable=False)
11
+ tipo_movimiento = Column(Enum('INGRESO', 'GASTO', name='tipo_movimiento'), nullable=False)
12
+ fecha = Column(Date, nullable=False) # Usa func.current_date() para obtener la fecha actual
13
+ descripcion = Column(String, nullable=True)
14
+ estado_gasto = Column(Boolean, default=True)
15
+
16
+ usuario = relationship("User", back_populates="movimiento")
models/ReservaM.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy.orm import relationship
2
+ from sqlalchemy import Column, Integer, String, Float, Date, Boolean, func,Time,ForeignKey,TIMESTAMP
3
+ from models.Base_class import Base
4
+ from models.UsuarioM import User
5
+
6
+
7
+ class Reserva(Base):
8
+ tablename = 'reserva'
9
+ id_reserva = Column(Integer, primary_key=True, autoincrement=True)
10
+ id_usuario = Column(String(30), ForeignKey('usuario.id_usuario'))
11
+ cliente = Column(String(100), nullable=False)
12
+ fecha = Column(Date, nullable=False)
13
+ hora = Column(Time, nullable=False)
14
+ estado_reserva = Column(Integer,default=0)
15
+ id_tarifa = Column(Integer, ForeignKey('tarifa.id_tarifa'))
16
+ created_at = Column(TIMESTAMP)
17
+
18
+ tarifa = relationship("Tarifa",back_populates="reserva")
19
+ usuario = relationship("User", back_populates="reserva")
models/TarifaM.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy import Column, Integer, String, Enum, Float, Date, Boolean, func,TIMESTAMP,String,ForeignKey
2
+ from sqlalchemy.ext.declarative import declarative_base
3
+ from sqlalchemy.orm import relationship
4
+ from models.Base_class import Base
5
+ from models.ReservaM import Reserva
6
+ from models.UsuarioM import User
7
+ from datetime import datetime
8
+
9
+ class Tarifa(Base):
10
+ __tablename__ = 'tarifa'
11
+
12
+ id_tarifa = Column(Integer, autoincrement=True, primary_key=True)
13
+ id_usuario = Column(String(30),ForeignKey("usuario.id_usuario"))
14
+ descripcion = Column(String, nullable=True)
15
+ costo = Column(Integer, nullable=False)
16
+ estado_tarifa = Column(Boolean, default=True)
17
+ created_at = Column(TIMESTAMP)
18
+ usuario = relationship("User",back_populates="tarifa")
19
+ reserva = relationship("Reserva",back_populates="tarifa")
20
+
models/UsuarioM.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy import Column, Integer, String, Enum, ForeignKey, Float, Date, Boolean, Time, SmallInteger
2
+ from enum import Enum as PyEnum
3
+ from sqlalchemy.orm import relationship
4
+ from models.Base_class import Base
5
+ from sqlalchemy.orm import relationship
6
+
7
+ class User(Base):
8
+ __tablename__ = 'usuario'
9
+ id_usuario = Column(String(30), primary_key=True)
10
+ correo = Column(String(80), nullable=False)
11
+ contrasenia = Column(String(250), nullable=False)
12
+ rol = Column(Enum('SUPERADMIN', 'BARBERO', name='rol'), nullable=False)
13
+ estado_usuario = Column(Boolean, default=True)
14
+
15
+ tarifa = relationship("Tarifa", back_populates="usuario")
16
+ reserva = relationship("Reserva",back_populates="usuario")
17
+ movimiento = relationship("Movimiento",back_populates="usuario")
18
+
requirements.txt ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ annotated-types==0.6.0
2
+ anyio==4.2.0
3
+ bcrypt==4.1.2
4
+ cffi==1.16.0
5
+ click==8.1.7
6
+ colorama==0.4.6
7
+ cryptography==42.0.2
8
+ dnspython==2.5.0
9
+ ecdsa==0.18.0
10
+ email-validator==2.1.0.post1
11
+ fastapi==0.109.0
12
+ greenlet==3.0.3
13
+ h11==0.14.0
14
+ idna==3.6
15
+ passlib==1.7.4
16
+ pyasn1==0.5.1
17
+ pycparser==2.21
18
+ pydantic==2.5.3
19
+ pydantic_core==2.14.6
20
+ PyMySQL==1.1.0
21
+ python-dotenv==1.0.1
22
+ python-jose==3.3.0
23
+ python-multipart==0.0.6
24
+ pytz==2024.1
25
+ rsa==4.9
26
+ setuptools==68.2.2
27
+ six==1.16.0
28
+ sniffio==1.3.0
29
+ SQLAlchemy==2.0.25
30
+ starlette==0.35.1
31
+ typing_extensions==4.9.0
32
+ uvicorn==0.27.0
33
+ wheel==0.41.2
routes/MovimientosR.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import List, Optional
2
+ from fastapi import APIRouter,Depends,HTTPException
3
+ from fastapi.security import OAuth2PasswordBearer
4
+ from sqlalchemy.orm import Session
5
+ from db.session import get_session
6
+ from schemas.MovimientosSh import *
7
+ from schemas.UsuarioSh import UserRead
8
+ from cruds.MovimientosCrud import *
9
+ from routes.UsuarioR import get_current_user
10
+ router = APIRouter()
11
+
12
+ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/users/login")
13
+
14
+ BARBERO = "BARBERO"
15
+
16
+ @router.post("/create/",response_model=MovimientosRead)
17
+ async def create_movimiento(movi:MovimientosCreate,db:Session = Depends(get_session), current_user: UserRead = Depends(get_current_user)):
18
+ if current_user.estado_usuario:
19
+ if current_user.rol == BARBERO:
20
+ return create_new_movimiento(movi,current_user.id_usuario,db)
21
+ else:
22
+ raise HTTPException(status_code=401, detail="Not authorized")
23
+ else:
24
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo /create")
25
+
26
+
27
+ @router.get("/get/{movimiento_id}",response_model=MovimientosRead)
28
+ def read_movimiento(id_movimientos:int, db:Session = Depends(get_session), current_user: UserRead = Depends(get_current_user)):
29
+
30
+ if current_user.estado_usuario:
31
+ user = buscar_movimientos(id_movimientos,db)
32
+ if user is None:
33
+ raise HTTPException(status_code=404,detail="Movimiento no encontrado")
34
+
35
+ return user
36
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo")
37
+
38
+ @router.post("/weekly-expenses")
39
+ def weekly_expenses(datos: dict, db: Session = Depends(get_session), current_user: UserRead = Depends(get_current_user)):
40
+ if not current_user.estado_usuario:
41
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo")
42
+
43
+ if current_user.rol != 'BARBERO':
44
+ raise HTTPException(status_code=401, detail="Not authorized")
45
+
46
+ tipo = datos.get("tipo")
47
+ if not tipo:
48
+ raise HTTPException(status_code=400, detail="El campo 'tipo' es requerido")
49
+
50
+ total_expenses, details = get_weekly_expenses(db, current_user.id_usuario, tipo)
51
+ return {"total_expenses": total_expenses, "details": details}
52
+
53
+
54
+
55
+ @router.post("/consulted_expenses")
56
+ def consulted_expenses(datos: dict, db: Session = Depends(get_session), current_user: UserRead = Depends(get_current_user)):
57
+ if not current_user.estado_usuario:
58
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo")
59
+
60
+ if current_user.rol != 'BARBERO':
61
+ raise HTTPException(status_code=401, detail="Not authorized")
62
+
63
+ start_week = datos.get("start_week")
64
+ end_week = datos.get("end_week")
65
+
66
+ if not start_week and end_week:
67
+ raise HTTPException(status_code=400, detail="Los campos son requeridos")
68
+
69
+ total_expenses, details = get_consulted_expenses(db, current_user.id_usuario, start_week,end_week)
70
+ return {"total_expenses": total_expenses, "details": details}
71
+
72
+
73
+ @router.get("/get-cuenta")
74
+ async def account_money(fecha_inicio : Optional[str] = None,fecha_fin : Optional[str] = None,db:Session = Depends(get_session),current_user:UserRead = Depends(get_current_user)):
75
+ if current_user.estado_usuario:
76
+ if current_user.rol == BARBERO:
77
+ cuenta = money_account(db,current_user.id_usuario,fecha_inicio,fecha_fin)
78
+ return {"money_account":cuenta}
79
+ raise HTTPException(status_code=401, detail="Not authorized")
80
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo /get_reserve_pendiente")
81
+
82
+ @router.post("/update-movimiento", response_model=MovimientosRead)
83
+ def update_user_func(movi: MovimientosUpdate, db: Session = Depends(get_session), current_user: UserRead = Depends(get_current_user)):
84
+
85
+ if current_user.estado_usuario:
86
+ if current_user.rol == BARBERO:
87
+ movimientoread = update_movimiento_crud(movi,db)
88
+ if movimientoread is None:
89
+ raise HTTPException(status_code=401, detail="no se encontro el movimiento")
90
+ return movimientoread
91
+
92
+ raise HTTPException(status_code=401, detail="Not authorized")
93
+ else:
94
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo")
95
+
96
+
97
+ @router.post("/update-movimientos-status")
98
+ def update_movimientos_status(movi: MovimientosUpdateStatus, db: Session = Depends(get_session), current_user: UserRead = Depends(get_current_user)):
99
+
100
+ if current_user.estado_usuario:
101
+ if current_user.rol == BARBERO:
102
+ statusUpdate = update_movimientos_status_crud(movi, db)
103
+ if statusUpdate:
104
+ return {"message:":"The movimiento status has been successfully updated", "status": statusUpdate}
105
+ return {"message:":"An error occurred at the time of updating the movimiento.", "status": statusUpdate}
106
+ raise HTTPException(status_code=401, detail="Not authorized")
107
+ else:
108
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo")
routes/ReservaR.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import List,Optional
2
+ from fastapi import APIRouter, Depends, HTTPException
3
+ from fastapi.security import OAuth2PasswordBearer
4
+ from sqlalchemy.orm import Session
5
+ from core.seguridad import verify_token
6
+ from cruds.ReservaCrud import *
7
+ from cruds.UsuarioCrud import get_user_by_id
8
+ import pytz
9
+ from db.session import get_session
10
+ from schemas.ReservaSh import *
11
+ from schemas.UsuarioSh import UserRead
12
+
13
+ # Obtener la zona horaria de Colombia
14
+ colombia_tz = pytz.timezone('America/Bogota')
15
+
16
+ router = APIRouter()
17
+
18
+ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/users/login")
19
+
20
+ BARBERO = "BARBERO"
21
+
22
+ async def get_current_user(token:str = Depends(oauth2_scheme), db:Session = Depends(get_session)):
23
+ user_id = await verify_token(token)
24
+ if user_id is None:
25
+ raise HTTPException(status_code=481,detail="Invalid token")
26
+ user_db = get_user_by_id(user_id, db)
27
+ if user_db is None:
28
+ raise HTTPException(status_code=484,detail="User not found")
29
+ return user_db
30
+
31
+ @router.post("/create-reserve",response_model=ReserveRead)
32
+ async def create_reserve(reserve:ReserveCreate,db:Session = Depends(get_session),current_user:UserRead = Depends(get_current_user)):
33
+ if current_user.estado_usuario:
34
+ if current_user.rol == BARBERO:
35
+ fecha_actual_colombia = datetime.now(colombia_tz)
36
+ return create_new_reserve(reserve,current_user.id_usuario,fecha_actual_colombia,db)
37
+ else:
38
+ raise HTTPException(status_code=401, detail="Not authorized")
39
+ else:
40
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo /create-reserve")
41
+
42
+ @router.post("/update-reserve", response_model=ReserveRead)
43
+ def reserve_update(reserve: ReserveUpdate, db: Session = Depends(get_session), current_user: UserRead = Depends(get_current_user)):
44
+ if current_user.estado_usuario and current_user.rol == BARBERO:
45
+ updated_reserve = update_reserve(reserve, current_user.id_usuario, db)
46
+ if updated_reserve is None:
47
+ raise HTTPException(status_code=404, detail="reserve not found or reserva is not at 0")
48
+ return updated_reserve
49
+ else:
50
+ raise HTTPException(status_code=401, detail="Not authorized")
51
+
52
+ @router.post("/update-reserve-tarifa", response_model=ReserveRead)
53
+ def reserve_update_tarifa(reserve: ReserveUpdateTarifa, db: Session = Depends(get_session), current_user: UserRead = Depends(get_current_user)):
54
+ if current_user.estado_usuario and current_user.rol == BARBERO:
55
+ updated_reserve_tarifa = update_reserve_tarifa(reserve, current_user.id_usuario, db)
56
+ if updated_reserve_tarifa is None:
57
+ raise HTTPException(status_code=404, detail="reserve tarifa not found")
58
+ return updated_reserve_tarifa
59
+ else:
60
+ raise HTTPException(status_code=401, detail="Not authorized")
61
+
62
+ @router.post("/delete-reserve",response_model=ReserveRead)
63
+ async def update_status(reserve:ReserveUpdateStatus,db:Session = Depends(get_session),current_user:UserRead = Depends(get_current_user)):
64
+ if current_user.estado_usuario:
65
+ if current_user.rol == BARBERO:
66
+ return update_status_reserve(reserve,db,current_user.id_usuario)
67
+ raise HTTPException(status_code=401, detail="Not authorized")
68
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo /update-reserve")
69
+
70
+
71
+
72
+ @router.get("/get-reserve-pendiente",response_model=List[ReserveRead])
73
+ async def get_reserve_pendiente(db:Session = Depends(get_session),current_user:UserRead = Depends(get_current_user)):
74
+ if current_user.estado_usuario:
75
+ if current_user.rol == BARBERO:
76
+ return get_reserve_false(current_user.id_usuario,db)
77
+ raise HTTPException(status_code=401, detail="Not authorized")
78
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo /get_reserve_pendiente")
79
+
80
+
81
+ @router.get("/get-reserve-all",response_model=List[ReserveRead])
82
+ async def get_all(fecha_inicio : Optional[str] = None,fecha_fin : Optional[str] = None,db:Session = Depends(get_session),current_user:UserRead = Depends(get_current_user)):
83
+ if current_user.estado_usuario:
84
+ if current_user.rol == BARBERO:
85
+ return get_reserve_all(current_user.id_usuario,db,fecha_inicio,fecha_fin)
86
+ raise HTTPException(status_code=401, detail="Not authorized")
87
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo /get_reserve_all")
88
+
89
+ @router.get("/get-reservations-available")
90
+ async def reservations_available(fecha:Optional[str] = None,db:Session = Depends(get_session),current_user:UserRead = Depends(get_current_user)):
91
+ if current_user.estado_usuario:
92
+ if current_user.rol == BARBERO:
93
+ return get_reservations_available(current_user.id_usuario,db,fecha)
94
+ raise HTTPException(status_code=401, detail="Not authorized")
95
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo /get-reservations-available")
routes/TarifaR.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import List
2
+ from fastapi import APIRouter,Depends,HTTPException
3
+ from fastapi.security import OAuth2PasswordBearer
4
+ from sqlalchemy.orm import Session
5
+ from db.session import get_session
6
+ from schemas.TarifaSh import *
7
+ from cruds.TarifaCrud import *
8
+ from schemas.UsuarioSh import UserRead
9
+ from routes.UsuarioR import get_current_user
10
+ import pytz
11
+
12
+ router = APIRouter()
13
+ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/users/login")
14
+ BARBERO = "BARBERO"
15
+
16
+
17
+ # Obtener la zona horaria de Colombia
18
+ colombia_tz = pytz.timezone('America/Bogota')
19
+
20
+ # # Obtener la fecha actual en la zona horaria de Colombia
21
+
22
+ @router.post("/create-tarifa/",response_model=TarifaRead)
23
+ def create_tarifa(tarifa_create:TarifaCreate,db:Session = Depends(get_session),current_user: UserRead = Depends(get_current_user)):
24
+ if current_user.estado_usuario:
25
+ if current_user.rol == BARBERO:
26
+ fecha_actual_colombia = datetime.now(colombia_tz)
27
+ return create_new_tarifa(tarifa_create,current_user.id_usuario,fecha_actual_colombia,db)
28
+ else:
29
+ raise HTTPException(status_code=401, detail="No esta autorizado")
30
+ else:
31
+ raise HTTPException(status_code=401, detail="Su usuario esta inactivo")
32
+
33
+ @router.get("/get-tarifas/",response_model=List[TarifaRead])
34
+ def obtener_tarifas(db:Session = Depends(get_session),current_user: UserRead = Depends(get_current_user)):
35
+ if current_user.estado_usuario:
36
+ if current_user.rol == BARBERO:
37
+ tarifas = get_all_tarifas(db,current_user.id_usuario)
38
+ if tarifas is None:
39
+ raise HTTPException(status_code=404, detail="No existen tarifas")
40
+ else:
41
+ return tarifas
42
+ else:
43
+ raise HTTPException(status_code=401, detail="No esta autorizado")
44
+ else:
45
+ raise HTTPException(status_code=401, detail="Su usuario esta inactivo")
46
+
47
+ @router.post("/update-tarifa/",response_model=TarifaUpdate)
48
+ def update_tarifa(updateTarifa:TarifaUpdate,db:Session = Depends(get_session),current_user: UserRead = Depends(get_current_user)):
49
+ if current_user.estado_usuario:
50
+ if current_user.rol == BARBERO:
51
+ tarifas = tarifa_update(updateTarifa,db)
52
+ if tarifas is None:
53
+ raise HTTPException(status_code=404, detail="No existen tarifas")
54
+ else:
55
+ return tarifas
56
+ else:
57
+ raise HTTPException(status_code=401, detail="No esta autorizado")
58
+ else:
59
+ raise HTTPException(status_code=401, detail="Su usuario esta inactivo")
60
+
61
+
62
+ @router.post("/update-tarifa-status/",response_model=TarifaUpdate)
63
+ def update_tarifa_status(updateTarifaStatus:TarifaBase,db:Session = Depends(get_session),current_user: UserRead = Depends(get_current_user)):
64
+ if current_user.estado_usuario:
65
+ if current_user.rol == BARBERO:
66
+ tarifas = delete_tarifa(updateTarifaStatus,db)
67
+ if tarifas is None:
68
+ raise HTTPException(status_code=404, detail="No existen la Tarifa")
69
+ else:
70
+ return tarifas
71
+ else:
72
+ raise HTTPException(status_code=401, detail="No esta autorizado")
73
+ else:
74
+ raise HTTPException(status_code=401, detail="Su usuario esta inactivo")
routes/UsuarioR.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import List
2
+ from fastapi import APIRouter,Depends,HTTPException
3
+ from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
4
+ from sqlalchemy.orm import Session
5
+ from db.session import get_session
6
+ from schemas.UsuarioSh import *
7
+ from cruds.UsuarioCrud import create_new_user,get_user_by_email,get_user_by_id, authenticate_user, update_user_crud, update_user_status_crud, get_all_users_bd
8
+ from core.seguridad import verify_token, verify_password, create_access_token, get_hashed_password
9
+
10
+ router = APIRouter()
11
+
12
+ tokens = []
13
+
14
+ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/users/login")
15
+
16
+ SUPERADMIN = "SUPERADMIN"
17
+
18
+ async def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_session)):
19
+ user_id = await verify_token(token)
20
+ if user_id is None:
21
+ if token in tokens:
22
+ tokens.remove(token)
23
+ raise HTTPException(status_code=484, detail="Token delete for time ")
24
+ else:
25
+ raise HTTPException(status_code=400, detail="El token proporcionado no es válido")
26
+ user_db = get_user_by_id(user_id, db)
27
+ if user_db is None:
28
+ raise HTTPException(status_code=484, detail="User not found")
29
+ return user_db
30
+
31
+ @router.post("/create/",response_model=UserRead)
32
+ async def create_user(user:UserCreate,db:Session = Depends(get_session), current_user: UserRead = Depends(get_current_user)):
33
+
34
+ if current_user.estado_usuario:
35
+
36
+ if current_user.rol == SUPERADMIN:
37
+
38
+ verify_user = get_user_by_email(user.correo,db)
39
+ if verify_user is None:
40
+ return create_new_user(user,db)
41
+
42
+ raise HTTPException(status_code=404,detail="Email already exists")
43
+ else:
44
+ raise HTTPException(status_code=401, detail="Not authorized")
45
+ else:
46
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo /create")
47
+
48
+
49
+ @router.get("/get/{user_id}",response_model=UserRead)
50
+ def read_user(user_id:str, db:Session = Depends(get_session), current_user: UserRead = Depends(get_current_user)):
51
+
52
+ if current_user.estado_usuario:
53
+ if current_user.rol == SUPERADMIN:
54
+ user = get_user_by_id(user_id,db)
55
+ if user is None:
56
+ raise HTTPException(status_code=404,detail="usuario no encontrado")
57
+
58
+ return user
59
+ raise HTTPException(status_code=401, detail="Not authorized")
60
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo")
61
+
62
+ @router.get("/get-all-users", response_model= List[UserRead])
63
+ def read_all_users_func(db:Session = Depends(get_session), current_user: UserRead = Depends(get_current_user)):
64
+
65
+ if current_user.estado_usuario:
66
+ if current_user.rol == SUPERADMIN:
67
+ usersFind = get_all_users_bd(db)
68
+ if usersFind is None:
69
+ raise HTTPException(status_code=404,detail="No hay usuarios registrados por el momento")
70
+ return usersFind
71
+ raise HTTPException(status_code=401, detail="Not authorized")
72
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo")
73
+
74
+
75
+
76
+
77
+
78
+ @router.post("/login",response_model=Token)
79
+ async def login_for_acces(form_data: OAuth2PasswordRequestForm= Depends(), db: Session = Depends(get_session)):
80
+ curr_user = authenticate_user(form_data.username, form_data.password, db)
81
+ if not curr_user:
82
+ raise HTTPException(
83
+ status_code=401,
84
+ detail="Invalid username or password",
85
+ headers={"WWW-Authenticate": "Bearer"}
86
+ )
87
+ if curr_user.estado_usuario:
88
+ access_token = create_access_token(data={"sub": curr_user.id_usuario})
89
+ tokens.append(access_token)
90
+ return {"access_token": access_token, "correo":curr_user.correo,"token_type":"bearer","rol":curr_user.rol}
91
+ else:
92
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo")
93
+
94
+
95
+ @router.post("/update-user", response_model=UserRead)
96
+ def update_user_func(user: UserUpdate, db: Session = Depends(get_session), current_user: UserCurrent = Depends(get_current_user)):
97
+
98
+ if current_user.estado_usuario:
99
+ if current_user.id_usuario == user.id_usuario:
100
+ user_verify = get_user_by_email(user.correo, db)
101
+ if user_verify is None or user_verify.id_usuario == user.id_usuario:
102
+ if user.contrasenia and user.contraActual: #Verificar si la contrasenia actual y la nueva son diferentes de null (None)
103
+ passwordVer = verify_password(user.contraActual, current_user.contrasenia)
104
+ if passwordVer:
105
+ user_return = update_user_crud(user, db)
106
+ if user_return is None:
107
+ raise HTTPException(status_code=403, detail="No se encontró el usuario por el id")
108
+ return user_return
109
+ raise HTTPException(status_code=404, detail="La contraseña actual es incorrecta")
110
+ else:
111
+ user_return = update_user_crud(user, db)
112
+ if user_return is None:
113
+ raise HTTPException(status_code=403, detail="No se encontró el usuario por el id")
114
+ return user_return
115
+ raise HTTPException(status_code=404, detail="El email ya existe")
116
+ raise HTTPException(status_code=401, detail="Not authorized")
117
+ else:
118
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo")
119
+
120
+ @router.post("/update-user-status")
121
+ def update_user_status_func(user: UserUpdateStatus, db: Session = Depends(get_session), current_user: UserRead = Depends(get_current_user)):
122
+
123
+ if current_user.estado_usuario:
124
+ if current_user.rol == SUPERADMIN:
125
+ statusUpdate = update_user_status_crud(user, db)
126
+ if statusUpdate:
127
+ return {"message:":"The user's status has been successfully updated", "status": statusUpdate}
128
+ return {"message:":"An error occurred at the time of updating the user.", "status": statusUpdate}
129
+ raise HTTPException(status_code=401, detail="Not authorized")
130
+ else:
131
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo")
132
+
133
+
134
+
135
+ @router.post("/logout")
136
+ def logout_user(token: str, current_user: UserRead = Depends(get_current_user)):
137
+ print(token)
138
+ if current_user.estado_usuario:
139
+ if token in tokens:
140
+ tokens.remove(token)
141
+ return {"msg": "Sesión cerrada exitosamente","status":True}
142
+ else:
143
+ raise HTTPException(status_code=400, detail="El token proporcionado no es válido")
144
+ else:
145
+ raise HTTPException(status_code=403, detail="El estado del usuario es inactivo")
146
+
147
+
148
+ @router.post("/get-user-token", response_model=UserRead)
149
+ async def get_user_log(token:str, db:Session = Depends(get_session), current_user: UserRead = Depends(get_current_user)):
150
+ if current_user.estado_usuario:
151
+ user_id = await verify_token(token)
152
+ if user_id:
153
+ user = get_user_by_id(user_id, db)
154
+ if user is None:
155
+ raise HTTPException(status_code=400, detail="El usuario no existe")
156
+ return user
157
+ raise HTTPException(status_code=400, detail="El usuario no se encontró con el token")
158
+ raise HTTPException(status_code=400, detail="El usuario esta desactivado")
159
+
160
+
schemas/MovimientosSh.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from typing import List
3
+ from enum import Enum as PydanticEnum
4
+ from datetime import date
5
+
6
+ class MovimientosStatus(str,PydanticEnum):
7
+ INGRESO = 'INGRESO'
8
+ GASTO = 'GASTO'
9
+
10
+ class MovimientosBase(BaseModel):
11
+ tipo_movimiento:MovimientosStatus
12
+ descripcion : str
13
+
14
+ class MovimientosCreate(MovimientosBase):
15
+ cuenta : int
16
+ fecha : date
17
+
18
+ class MovimientosRead(MovimientosBase):
19
+ fecha : date
20
+ cuenta : int
21
+ id_movimientos: int
22
+ estado_gasto : bool
23
+
24
+
25
+ class MovimientosUpdate(MovimientosBase):
26
+ id_movimientos: int
27
+ cuenta : int
28
+
29
+
30
+ class MovimientosUpdateStatus(BaseModel):
31
+ id_movimientos: int
32
+ estado_gasto : bool
33
+
34
+
schemas/ReservaSh.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from datetime import date, time
3
+
4
+ class ReserveCreate(BaseModel):
5
+ cliente:str
6
+ fecha:date
7
+ hora:time
8
+
9
+ class ReserveRead(ReserveCreate):
10
+ id_reserva:int
11
+ estado_reserva:int
12
+
13
+
14
+ class ReserveUpdateStatus(BaseModel):
15
+ id_reserva: int
16
+ estado_reserva : int
17
+
18
+ class ReserveUpdate(BaseModel):
19
+ id_reserva:int
20
+ cliente:str
21
+ fecha:date
22
+ hora:time
23
+
24
+ class ReserveUpdateTarifa(BaseModel):
25
+ id_reserva: int
26
+ id_tarifa:int
schemas/TarifaSh.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from datetime import datetime
3
+
4
+ # Clase para reutilzar en algunos casos
5
+ class TarifaBase(BaseModel):
6
+ id_tarifa:int
7
+
8
+ # Esquema para recibir datos para hacer un Create
9
+ class TarifaCreate(BaseModel):
10
+ descripcion:str
11
+ costo:int
12
+
13
+ # Esquema para recibir datos para hacer un Update
14
+ class TarifaUpdate(TarifaBase):
15
+ descripcion:str
16
+ costo:int
17
+
18
+
19
+ # Esquema para enviar datos
20
+ class TarifaRead(TarifaBase):
21
+ descripcion:str
22
+ costo:int
23
+ estado_tarifa:bool
24
+ created_at:datetime
schemas/UsuarioSh.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel,EmailStr
2
+ from enum import Enum as PydanticEnum
3
+ from typing import Optional
4
+ class UserRole(str,PydanticEnum):
5
+ SUPERADMIN = 'SUPERADMIN'
6
+ BARBERO = 'BARBERO'
7
+
8
+ class UserBase(BaseModel):
9
+ correo:EmailStr
10
+
11
+ class UserCreate(UserBase):
12
+ contrasenia:str
13
+
14
+ class UserRead(UserBase):
15
+ id_usuario :str
16
+ rol:UserRole
17
+ estado_usuario : bool
18
+
19
+ class UserCurrent(UserBase):
20
+ id_usuario:str
21
+ rol: UserRole
22
+ contrasenia:str
23
+ estado_usuario: bool
24
+
25
+ class UserUpdate(UserBase):
26
+ id_usuario: str
27
+ contraActual:Optional[str]
28
+ contrasenia:Optional[str]
29
+
30
+ class UserUpdateStatus(BaseModel):
31
+ user_id: str
32
+ estado_usuario: bool
33
+
34
+ class Token(UserBase):
35
+ access_token:str
36
+ token_type:str
37
+ rol:UserRole
38
+ class Config:
39
+ from_attributes = True
40
+
41
+ # Cuando orm_mode esta habilitado, permite la conversion directa de objetos SQLAlchemy a modelos Pydantic sin necesidad de definir explicitamente todos los campos
42
+
toma_de_requerimientos.txt ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Objetivo principal control de reservas, ingresos (x fechas),gastos (x fechas) y tarifas
2
+
3
+ El usuario tendra 2 roles SUPERADMIN y ADMIN
4
+
5
+ El SUPERADMIN tendra unicamente el control de los usuarios ADMIN
6
+
7
+ EL ADMIN tendra todos los servicios del Objetivo principal e ingreso al sistema
8
+
9
+
10
+ Tarifas: Hace referencia a los diferentes precios que maneja la barberia, por ejm las tarifas del parqueadero
11
+
12
+ Reservas: Son las agendaciones de las personas donde se lleva nombre del cliente, fecha y hora, quedaria con un estado en
13
+ pendiente, cuando quiera cambiar el estado a finalizado debera seleccionar la tarifa, solo los clientes con estado en
14
+ finalizado contara con ingreso
15
+
16
+ Ingresos: Son las ganancias que tendra el ADMIN(barbero) administrado por fechas, es decir puede mirar los ingresos del dia,
17
+ semana,mes y año. Teniendo en cuenta los gastos filtrados por las fechas especificas
18
+
19
+ Gastos: Gastos generales que tendra el ADMIN, que se restaran a los ingresos, controlado por fechas