Spaces:
Running
Running
winderoman
commited on
Commit
•
35c6a2c
1
Parent(s):
3637185
Add application file
Browse files- .env +13 -0
- .gitignore +1 -0
- Dockerfile +11 -0
- core/config.py +27 -0
- core/seguridad.py +35 -0
- core/utils.py +21 -0
- cruds/MovimientosCrud.py +132 -0
- cruds/ReservaCrud.py +153 -0
- cruds/TarifaCrud.py +71 -0
- cruds/UsuarioCrud.py +96 -0
- db/barber_db.sql +70 -0
- db/boovngmcolkrlajvvjia.sql +117 -0
- db/session.py +23 -0
- main.py +22 -0
- models/Base_class.py +17 -0
- models/MovimientosM.py +16 -0
- models/ReservaM.py +19 -0
- models/TarifaM.py +20 -0
- models/UsuarioM.py +18 -0
- requirements.txt +33 -0
- routes/MovimientosR.py +108 -0
- routes/ReservaR.py +95 -0
- routes/TarifaR.py +74 -0
- routes/UsuarioR.py +160 -0
- schemas/MovimientosSh.py +34 -0
- schemas/ReservaSh.py +26 -0
- schemas/TarifaSh.py +24 -0
- schemas/UsuarioSh.py +42 -0
- toma_de_requerimientos.txt +19 -0
.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
|