Initial commit
This commit is contained in:
commit
0f605c4f42
142
.dockerignore
Normal file
142
.dockerignore
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
.git
|
||||||
|
Dockerfile
|
||||||
|
.DS_Store
|
||||||
|
.gitignore
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
/credentials
|
||||||
|
/cache
|
||||||
|
/store
|
||||||
|
|
||||||
|
/node_modules
|
||||||
|
|
||||||
|
# https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
|
||||||
|
|
||||||
|
# General
|
||||||
|
*.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
# https://raw.githubusercontent.com/github/gitignore/master/Python.gitignore
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
.hypothesis/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
160
.gitignore
vendored
Normal file
160
.gitignore
vendored
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/#use-with-ide
|
||||||
|
.pdm.toml
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
12
Dockerfile
Normal file
12
Dockerfile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
FROM python:3.10-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt /app
|
||||||
|
RUN pip3 install -r requirements.txt
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
ENV FLASK_APP=src/main.py
|
||||||
|
|
||||||
|
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0", "--port=5000"]
|
4
README.md
Normal file
4
README.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# Talkpal - Backend
|
||||||
|
|
||||||
|
This is the backend service for a **Meeting Room Booking System**, providing RESTful API endpoints for managing rooms, events, and users.
|
||||||
|
It is built using **Python** and integrates with a database for persistent storage.
|
9
docker-compose.yaml
Normal file
9
docker-compose.yaml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
version: '2.1'
|
||||||
|
services:
|
||||||
|
talkpal-backend:
|
||||||
|
container_name: talkpal-backend
|
||||||
|
image: talkpal-backend
|
||||||
|
build: .
|
||||||
|
network_mode: host
|
||||||
|
volumes:
|
||||||
|
- "./src:/app/src"
|
9
requirements.txt
Normal file
9
requirements.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
blinker==1.8.2
|
||||||
|
click==8.1.8
|
||||||
|
flask==3.0.3
|
||||||
|
importlib-metadata==8.5.0
|
||||||
|
itsdangerous==2.2.0
|
||||||
|
jinja2==3.1.5
|
||||||
|
MarkupSafe==2.1.5
|
||||||
|
werkzeug==3.0.6
|
||||||
|
zipp==3.20.2
|
13
src/app.py
Normal file
13
src/app.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from flask import Flask
|
||||||
|
from pymongo import MongoClient
|
||||||
|
from flask_jwt_extended import JWTManager
|
||||||
|
from singletons.database_singleton import DatabaseSingleton
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config['JWT_SECRET_KEY'] = Config.JWT_SECRET_KEY
|
||||||
|
jwt = JWTManager(app)
|
||||||
|
client = MongoClient(Config.MONGO_URI)
|
||||||
|
db = DatabaseSingleton.get_instance()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(debug=True)
|
6
src/config.py
Normal file
6
src/config.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
DB_NAME = os.getenv('DB_NAME', 'meeting_reservation')
|
||||||
|
JWT_SECRET_KEY = os.getenv('JWT_SECRET_KEY', 'your_jwt_secret_key')
|
||||||
|
MONGO_URI = os.getenv('MONGO_URI', 'mongodb://localhost:27017/')
|
65
src/controllers/reservation_controller.py
Normal file
65
src/controllers/reservation_controller.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
from flask import Blueprint, request, jsonify
|
||||||
|
from flask_jwt_extended import jwt_required, get_jwt_identity
|
||||||
|
|
||||||
|
from middlewares.validate_request import validate_request
|
||||||
|
from dtos.reservation_dtos import CreateReservationDTO, UpdateReservationDTO
|
||||||
|
from models.reservation_model import Reservation
|
||||||
|
from repos.reservation_repo import ReservationRepository
|
||||||
|
|
||||||
|
reservation_blueprint = Blueprint('reservation', __name__)
|
||||||
|
|
||||||
|
@reservation_blueprint.route('/', methods=['POST'])
|
||||||
|
@validate_request(CreateReservationDTO)
|
||||||
|
@jwt_required()
|
||||||
|
def create_reservation():
|
||||||
|
current_user = get_jwt_identity()
|
||||||
|
reservation = Reservation(**request.json.dict(), creator=current_user)
|
||||||
|
ReservationRepository.insert(reservation)
|
||||||
|
return jsonify({"message": "Reservation created successfully"})
|
||||||
|
|
||||||
|
@reservation_blueprint.route('/<reservation_id>', methods=['DELETE'])
|
||||||
|
@jwt_required()
|
||||||
|
def cancel_reservation(reservation_id):
|
||||||
|
result = ReservationRepository.delete(reservation_id)
|
||||||
|
if not result or result.deleted_count == 0:
|
||||||
|
return jsonify({"error": "Reservation not found"}), 404
|
||||||
|
return jsonify({"message": "Reservation cancelled"})
|
||||||
|
|
||||||
|
@reservation_blueprint.route('/<reservation_id>', methods=['PUT'])
|
||||||
|
@validate_request(UpdateReservationDTO)
|
||||||
|
@jwt_required()
|
||||||
|
def change_reservation(reservation_id):
|
||||||
|
data = request.json
|
||||||
|
try:
|
||||||
|
result = ReservationRepository.update(reservation_id, data)
|
||||||
|
if not result or result.matched_count == 0:
|
||||||
|
return jsonify({"error": "Reservation not found"}), 404
|
||||||
|
except:
|
||||||
|
return jsonify({"error": "Invalid reservation ID"}), 400
|
||||||
|
|
||||||
|
return jsonify({"message": "Reservation updated"})
|
||||||
|
|
||||||
|
@reservation_blueprint.route('/<reservation_id>', methods=['GET'])
|
||||||
|
@jwt_required()
|
||||||
|
def get_reservation(reservation_id):
|
||||||
|
try:
|
||||||
|
reservation = ReservationRepository.get_by_id()
|
||||||
|
if not reservation:
|
||||||
|
return jsonify({"error": "Reservation not found"}), 404
|
||||||
|
except:
|
||||||
|
return jsonify({"error": "Invalid reservation ID"}), 400
|
||||||
|
|
||||||
|
return jsonify(reservation)
|
||||||
|
|
||||||
|
@reservation_blueprint.route('/', methods=['GET'])
|
||||||
|
@jwt_required()
|
||||||
|
def list_reservations():
|
||||||
|
filters = {
|
||||||
|
"start_date": request.args.get("start_date"),
|
||||||
|
"end_date": request.args.get("end_date"),
|
||||||
|
"room_id": request.args.get("room_id")
|
||||||
|
}
|
||||||
|
filters = {k: v for k, v in filters.items() if v is not None}
|
||||||
|
|
||||||
|
reservations = ReservationRepository.list_all(filters)
|
||||||
|
return jsonify(reservations)
|
29
src/controllers/user_controller.py
Normal file
29
src/controllers/user_controller.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from flask import Blueprint, request, jsonify
|
||||||
|
from flask_jwt_extended import create_access_token
|
||||||
|
|
||||||
|
from middlewares.validate_request import validate_request
|
||||||
|
from dtos.user_dtos import RegisterUserDTO, LoginUserDTO
|
||||||
|
from repos.user_repo import UserRepo
|
||||||
|
from models.user_model import User
|
||||||
|
|
||||||
|
user_blueprint = Blueprint('user', __name__)
|
||||||
|
|
||||||
|
@user_blueprint.route('/register', methods=['POST'])
|
||||||
|
@validate_request(RegisterUserDTO)
|
||||||
|
def register_user():
|
||||||
|
data = request.json
|
||||||
|
if UserRepo.find_by_username(data.username):
|
||||||
|
return jsonify({"error": "User already exists"}), 409
|
||||||
|
user = User(**data.dict())
|
||||||
|
UserRepo.insert(user)
|
||||||
|
return jsonify({"message": "User registered successfully"})
|
||||||
|
|
||||||
|
@user_blueprint.route('/login', methods=['POST'])
|
||||||
|
@validate_request(LoginUserDTO)
|
||||||
|
def login_user():
|
||||||
|
data = request.json
|
||||||
|
user = UserRepo.find_by_username(data['username'])
|
||||||
|
if user:
|
||||||
|
access_token = create_access_token(identity=user['username'])
|
||||||
|
return jsonify(access_token=access_token)
|
||||||
|
return jsonify({"error": "Invalid credentials"}), 401
|
17
src/dtos/reservation_dtos.py
Normal file
17
src/dtos/reservation_dtos.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from typing import Optional
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
class CreateReservationDTO(BaseModel):
|
||||||
|
title: str
|
||||||
|
description: Optional[str] = None
|
||||||
|
room_id: str
|
||||||
|
start_date: datetime
|
||||||
|
finish_date: datetime
|
||||||
|
|
||||||
|
class UpdateReservationDTO(BaseModel):
|
||||||
|
title: Optional[str] = None
|
||||||
|
description: Optional[str] = None
|
||||||
|
room_id: Optional[str] = None
|
||||||
|
start_date: Optional[datetime] = None
|
||||||
|
finish_date: Optional[datetime] = None
|
15
src/dtos/user_dtos.py
Normal file
15
src/dtos/user_dtos.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
from pydantic import BaseModel, EmailStr
|
||||||
|
|
||||||
|
class RegisterUserDTO(BaseModel):
|
||||||
|
username: str
|
||||||
|
password: str
|
||||||
|
email: EmailStr
|
||||||
|
first_name: str
|
||||||
|
last_name: str
|
||||||
|
department: str
|
||||||
|
position: str
|
||||||
|
is_admin: bool = False
|
||||||
|
|
||||||
|
class LoginUserDTO(BaseModel):
|
||||||
|
username: str
|
||||||
|
password: str
|
17
src/middlewares/validate_request.py
Normal file
17
src/middlewares/validate_request.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from functools import wraps
|
||||||
|
from flask import request, jsonify
|
||||||
|
from pydantic import ValidationError
|
||||||
|
|
||||||
|
def validate_request(dto_class):
|
||||||
|
def decorator(func):
|
||||||
|
@wraps(func)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
try:
|
||||||
|
data = request.get_json()
|
||||||
|
dto = dto_class(**data)
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
except ValidationError as e:
|
||||||
|
print(e)
|
||||||
|
return jsonify({"error": e.errors()}), 400
|
||||||
|
return wrapper
|
||||||
|
return decorator
|
8
src/models/reservation_model.py
Normal file
8
src/models/reservation_model.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
class Reservation:
|
||||||
|
def __init__(self, title, description, room_id, creator, start_date, finish_date):
|
||||||
|
self.title = title
|
||||||
|
self.description = description
|
||||||
|
self.room_id = room_id
|
||||||
|
self.creator = creator
|
||||||
|
self.start_date = start_date
|
||||||
|
self.finish_date = finish_date
|
4
src/models/room_model.py
Normal file
4
src/models/room_model.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
class Room:
|
||||||
|
def __init__(self, title, office_id):
|
||||||
|
self.title = title
|
||||||
|
self.office_id = office_id
|
9
src/models/user_model.py
Normal file
9
src/models/user_model.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
class User:
|
||||||
|
def __init__(self, username, email, first_name, last_name, department, position, is_admin=False):
|
||||||
|
self.username = username
|
||||||
|
self.email = email
|
||||||
|
self.first_name = first_name
|
||||||
|
self.last_name = last_name
|
||||||
|
self.department = department
|
||||||
|
self.position = position
|
||||||
|
self.is_admin = is_admin
|
40
src/repos/reservation_repo.py
Normal file
40
src/repos/reservation_repo.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
from singletons.database_singleton import DatabaseSingleton
|
||||||
|
|
||||||
|
class ReservationRepository:
|
||||||
|
db = DatabaseSingleton.get_instance()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def insert(cls, reservation):
|
||||||
|
cls.db.reservation.insert_one(reservation.__dict__)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def delete(cls, reservation_id):
|
||||||
|
try:
|
||||||
|
result = cls.db.reservation.delete_one({"_id": ObjectId(reservation_id)})
|
||||||
|
return result
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def update(cls, reservation_id, data):
|
||||||
|
try:
|
||||||
|
result = cls.db.reservation.update_one({"_id": ObjectId(reservation_id)}, {"$set": data})
|
||||||
|
return result
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_by_id(cls):
|
||||||
|
return list(cls.db.reservation.find({"_id": ObjectId(reservation_id)}))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def list_all(cls, filters=None):
|
||||||
|
query = {}
|
||||||
|
if filters:
|
||||||
|
if "start_date" in filters:
|
||||||
|
query["start_date"] = {"$gte": filters["start_date"]}
|
||||||
|
if "end_date" in filters:
|
||||||
|
query["start_date"] = {"$lte": filters["end_date"]}
|
||||||
|
if "room_id" in filters:
|
||||||
|
query["room_id"] = filters["room_id"]
|
||||||
|
return list(cls.db.reservation.find(query))
|
12
src/repos/user_repo.py
Normal file
12
src/repos/user_repo.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from singletons.database_singleton import DatabaseSingleton
|
||||||
|
|
||||||
|
class UserRepo:
|
||||||
|
db = DatabaseSingleton.get_instance()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def insert(cls, user):
|
||||||
|
cls.db.user.insert_one(user.__dict__)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def find_by_username(cls, username):
|
||||||
|
return cls.db.user.find_one({"username": username})
|
12
src/singletons/app_singleton.py
Normal file
12
src/singletons/app_singleton.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from config import Config
|
||||||
|
from flask import Flask
|
||||||
|
|
||||||
|
class AppSingleton:
|
||||||
|
_instance = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_instance():
|
||||||
|
if AppSingleton._instance is None:
|
||||||
|
AppSingleton._instance = Flask(__name__)
|
||||||
|
AppSingleton._instance['JWT_SECRET_KEY'] = Config.JWT_SECRET_KEY
|
||||||
|
return AppSingleton._instance[Config.DB_NAME]
|
11
src/singletons/database_singleton.py
Normal file
11
src/singletons/database_singleton.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from config import Config
|
||||||
|
from pymongo import MongoClient
|
||||||
|
|
||||||
|
class DatabaseSingleton:
|
||||||
|
_instance = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_instance():
|
||||||
|
if DatabaseSingleton._instance is None:
|
||||||
|
DatabaseSingleton._instance = MongoClient(Config.MONGO_URI)
|
||||||
|
return DatabaseSingleton._instance[Config.DB_NAME]
|
Loading…
x
Reference in New Issue
Block a user