diff --git a/.env.example b/.env.example
index 2f099a8..52cc427 100644
--- a/.env.example
+++ b/.env.example
@@ -3,3 +3,10 @@ PORT=5000
DEBUG=True
DATABASE_URL="mysql+pymysql://username:password@localhost:3306/se_ticket"
+
+MAIL_SERVER='smtp.gmail.com'
+MAIL_PORT = 587
+MAIL_USERNAME = 'compest15team5@gmail.com'
+MAIL_PASSWORD = 'duewujqfideibbkm'
+MAIL_USE_TLS = False
+MAIL_USE_SSL = True
\ No newline at end of file
diff --git a/migrations/versions/734664dd0b82_create_ticket_table.py b/migrations/versions/734664dd0b82_create_ticket_table.py
new file mode 100644
index 0000000..a537f3d
--- /dev/null
+++ b/migrations/versions/734664dd0b82_create_ticket_table.py
@@ -0,0 +1,44 @@
+"""Create_Ticket_table
+
+Revision ID: 734664dd0b82
+Revises: c6f3e7ccf086
+Create Date: 2023-08-21 16:05:02.108956
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '734664dd0b82'
+down_revision = 'c6f3e7ccf086'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.create_table('tickets',
+ sa.Column('ticket_id', sa.Integer(), nullable=False),
+ sa.Column('event_id', sa.Integer(), nullable=True),
+ sa.Column('user_id', sa.Integer(), nullable=True),
+ sa.Column('ticket_code', sa.String(length=6), nullable=True),
+ sa.Column('is_attended', sa.Boolean(), nullable=True),
+ sa.Column('created_at', sa.DateTime(), nullable=True),
+ sa.ForeignKeyConstraint(['event_id'], ['events.event_id'], ),
+ sa.ForeignKeyConstraint(['user_id'], ['users.user_id'], ),
+ sa.PrimaryKeyConstraint('ticket_id')
+ )
+ with op.batch_alter_table('events', schema=None) as batch_op:
+ batch_op.drop_column('created_at')
+
+ # ### end Alembic commands ###
+
+
+def downgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ with op.batch_alter_table('events', schema=None) as batch_op:
+ batch_op.add_column(sa.Column('created_at', sa.DATE(), nullable=True))
+
+ op.drop_table('tickets')
+ # ### end Alembic commands ###
diff --git a/public/mail.html b/public/mail.html
new file mode 100644
index 0000000..b0a4f2f
--- /dev/null
+++ b/public/mail.html
@@ -0,0 +1,77 @@
+
+
+
+
+
+ Event Information Ticket
+
+
+
+
+
Your Event Information Ticket
+
Dear [Recipient's Name],
+
We are excited to have you join us for our upcoming event. Here are the details you'll need:
+
+
+
Event Details
+
Event Name: [Event Name]
+
Date: [Event Date]
+
Time: [Event Time]
+
Location: [Event Location]
+
+
+
If you have any questions or need further assistance, please don't hesitate to contact us.
+
Thank you for being a part of this event!
+
+
Your Ticket Code:
+
+ {{ code }}
+
+
+
Best Regards,
Your Event Team
+
+
Get Directions
+
+
+
diff --git a/requirement.txt b/requirement.txt
index ed78b1a..8f69acf 100644
--- a/requirement.txt
+++ b/requirement.txt
@@ -8,4 +8,5 @@ pydantic==2.1.1
pydantic[email]==2.1.1
werkzeug==2.3.3
pyjwt==2.8.0
-Flask-Migrate==4.0.4
\ No newline at end of file
+Flask-Migrate==4.0.4
+Flask-Mail==0.9.1
diff --git a/src/config/config.py b/src/config/config.py
index 79e5888..c088369 100644
--- a/src/config/config.py
+++ b/src/config/config.py
@@ -3,7 +3,17 @@
BASE_URL = env["BASE_URL"] or "http://localhost"
PORT= env['PORT'] or 5000
DEBUG= env['DEBUG'] or True
+
DATABASE_URL = env['DATABASE_URL'] or "mysq;://root:root@localhost:3306/se_ticket"
+
JWT_ACCESS_TOKEN_EXPIRES = env['JWT_ACCESS_TOKEN_EXPIRES'] or 60 * 60 * 24 * 7
JWT_ACCESS_TOKEN_SECRET = env['JWT_ACCESS_TOKEN_SECRET'] or "secret"
JWT_ACCESS_TOKEN_ALGORITHM = env['JWT_ACCESS_TOKEN_ALGORITHM'] or "HS256"
+
+
+MAIL_SERVER = env['MAIL_SERVER'] or 'sandbox.smtp.mailtrap.io'
+MAIL_PORT = env['MAIL_PORT'] or 2525
+MAIL_USE_TLS = env['MAIL_USE_TLS'] or True
+MAIL_USE_SSL = env['MAIL_USE_SSL'] or False
+MAIL_USERNAME = env['MAIL_USERNAME'] or '1190969a29319c'
+MAIL_PASSWORD = env['MAIL_PASSWORD'] or '39c02575b88bd3'
\ No newline at end of file
diff --git a/src/config/mail.py b/src/config/mail.py
new file mode 100644
index 0000000..c5fb10f
--- /dev/null
+++ b/src/config/mail.py
@@ -0,0 +1,13 @@
+from flask_mail import Mail
+from src.config.config import MAIL_PORT,MAIL_SERVER,MAIL_USE_SSL,MAIL_USE_TLS,MAIL_USERNAME,MAIL_PASSWORD
+def mailConfig(app):
+ print(MAIL_SERVER,MAIL_PORT,MAIL_USE_SSL,MAIL_USE_TLS,MAIL_USERNAME,MAIL_PASSWORD)
+ print(type(MAIL_SERVER),type(MAIL_PORT),type(MAIL_USE_SSL),type(MAIL_USE_TLS),type(MAIL_USERNAME),type(MAIL_PASSWORD))
+ app.config['MAIL_SERVER']= MAIL_SERVER
+ app.config['MAIL_PORT'] = MAIL_PORT
+ app.config['MAIL_USE_TLS'] = MAIL_USE_TLS == 'True'
+ app.config['MAIL_USE_SSL'] = MAIL_USE_SSL == 'True'
+ app.config['MAIL_USERNAME'] = MAIL_USERNAME
+ app.config['MAIL_PASSWORD'] = MAIL_PASSWORD
+ return Mail(app)
+
\ No newline at end of file
diff --git a/src/config/permission.py b/src/config/permission.py
index d4755dc..9bfc109 100644
--- a/src/config/permission.py
+++ b/src/config/permission.py
@@ -3,6 +3,7 @@
'/auth/logout',
'/categories',
'/events/',
+ '/tickets/'
]
admin_permission=[
diff --git a/src/controllers/TicketController.py b/src/controllers/TicketController.py
new file mode 100644
index 0000000..293459c
--- /dev/null
+++ b/src/controllers/TicketController.py
@@ -0,0 +1,41 @@
+from flask import Blueprint
+from flask import request,g
+from src.services.TicketService import TicketService
+from src.middlewares.AuthMiddleware import isAuthenticated
+import src.utils.getResponse as Response
+
+TicketApp = Blueprint('TicketApp', __name__,)
+ticketService = TicketService()
+
+@TicketApp.route('/', methods=['GET'])
+@isAuthenticated
+def index():
+
+ result = ticketService.getAllTickets()
+ return Response.success(result['data'],"success get all Tickets")
+
+@TicketApp.route('/', methods=['POST'])
+@isAuthenticated
+def store():
+ result = ticketService.createNewTicket(request.json,g.user['user_id'])
+ if(result['status'] == 'failed'):
+ return Response.error(result['data'],result['code'])
+ return Response.success(result['data'],"success create new event")
+
+@TicketApp.route('/my', methods=['GET'])
+@isAuthenticated
+def myTicket():
+ result = ticketService.getTicketByUserId(g.user['user_id'])
+ if(result['status'] == 'failed'):
+ return Response.error(result['data'],result['code'])
+ return Response.success(result['data'],"success get all my ticket")
+
+
+@TicketApp.route('//delete', methods=['DELETE'])
+@isAuthenticated
+def delete(id):
+ result = ticketService.deleteCategory(id)
+ if(result['status'] == 'failed'):
+ return Response.error(result['data'],result['code'])
+
+ return Response.success(result['data'],"success delete event")
diff --git a/src/middlewares/AuthMiddleware.py b/src/middlewares/AuthMiddleware.py
index 8aa38dd..20e7126 100644
--- a/src/middlewares/AuthMiddleware.py
+++ b/src/middlewares/AuthMiddleware.py
@@ -4,6 +4,7 @@
from flask import request, g
from src.repositories.UserRepository import UserRepository
from src.utils.permission import check_role_is_have_access
+from src.utils.convert import queryResultToDict
user_repository = UserRepository()
def isAuthenticated(func):
@@ -19,7 +20,8 @@ def wrapper(*args, **kwargs):
is_have_access = check_role_is_have_access(user.role, request.path)
if not is_have_access:
return response.error(message="Forbidden", errors=None, status_code=403)
- g.user = dict(user)
+ print(user)
+ g.user = queryResultToDict([user])[0]
return func(*args, **kwargs)
except jwt.jwt.InvalidKeyError as e:
return response.error(message="Unauthorized", errors=None, status_code=401)
diff --git a/src/models/Category.py b/src/models/Category.py
index d23ef4f..7564f97 100644
--- a/src/models/Category.py
+++ b/src/models/Category.py
@@ -8,19 +8,4 @@ class Category(db.Model):
def __init__(self,name ):
self.name = name
-
- def __repr__(self):
-
- return f""
-
-
- def toDict(self):
- return {
- 'category_id': self.category_id,
- 'name': self.name,
- }
-
- def __iter__(self):
- yield 'category_id', self.category_id
- yield 'name', self.name
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/models/Event.py b/src/models/Event.py
index e66ef5e..5dff9b5 100644
--- a/src/models/Event.py
+++ b/src/models/Event.py
@@ -14,7 +14,8 @@ class Event(db.Model):
address= db.Column(db.Text)
user_id = db.Column(db.Integer, db.ForeignKey('users.user_id'))
category_id = db.Column(db.Integer, db.ForeignKey('categories.category_id'))
-
+ category = db.relationship('Category', backref='events')
+ user = db.relationship('User', backref='events')
def __init__(self, title, description, price, date_of_event, number_of_ticket,user_id,poster_path,address,category_id ):
self.title= title
@@ -27,35 +28,4 @@ def __init__(self, title, description, price, date_of_event, number_of_ticket,us
self.status = 'PENDING'
self.category_id = category_id
self.address = address
-
- def __repr__(self):
-
- return f""
-
-
- def toDict(self):
- return {
- 'event_id': self.event_id,
- 'title': self.title,
- 'description': self.description,
- 'price': self.price,
- 'date_of_event': self.date_of_event,
- 'number_of_tickets': self.number_of_ticket,
- 'user_id': self.user_id,
- 'poster_path': self.poster_path,
- 'status': self.status,
- 'category_id': self.category_id,
- }
-
- def __iter__(self):
- yield 'event_id', self.event_id
- yield 'title', self.title
- yield 'description', self.description
- yield 'price', self.price
- yield 'date_of_event', self.date_of_event
- yield 'number_of_ticket', self.number_of_ticket
- yield 'user_id', self.user_id
- yield 'poster_path', self.poster_path
- yield 'status', self.status
- yield 'category_id', self.category_id
- yield 'address', self.address
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/models/Ticket.py b/src/models/Ticket.py
new file mode 100644
index 0000000..2d74159
--- /dev/null
+++ b/src/models/Ticket.py
@@ -0,0 +1,18 @@
+from src.server.main import db,main_app
+from src.config.database import generateDatabase
+class Ticket(db.Model):
+ __tablename__ = 'tickets'
+
+ ticket_id = db.Column(db.Integer, primary_key=True)
+ event_id = db.Column(db.Integer, db.ForeignKey('events.event_id'))
+ user_id = db.Column(db.Integer, db.ForeignKey('users.user_id'))
+ ticket_code = db.Column(db.String(6))
+ is_attended = db.Column(db.Boolean, default=False)
+ created_at = db.Column(db.DateTime, default=db.func.current_timestamp())
+ event = db.relationship("Event", backref="tickets")
+ user = db.relationship("User", back_populates="tickets")
+ def __init__(self, event_id, user_id, ticket_code):
+ self.event_id = event_id
+ self.user_id = user_id
+ self.ticket_code = ticket_code
+
\ No newline at end of file
diff --git a/src/models/User.py b/src/models/User.py
index cc53119..0856a0a 100644
--- a/src/models/User.py
+++ b/src/models/User.py
@@ -10,7 +10,7 @@ class User(db.Model):
password = db.Column(db.String(255))
balance = db.Column(db.Float, default=0)
status = db.Column(db.String(255), default='INACTIVE')
-
+ tickets = db.relationship('Ticket', back_populates='user')
def __init__(self, email, name, role, password, status, balance =0):
self.name = name
self.email = email
@@ -18,25 +18,6 @@ def __init__(self, email, name, role, password, status, balance =0):
self.password = password
self.balance = balance
self.status = status
-
- def __repr__(self):
- return f""
-
-
- def toDict(self):
- return {
- 'user_id': self.user_id,
- 'email': self.email,
- 'name': self.name,
- 'role': self.role,
- 'balance': self.balance,
- 'status': self.status
- }
-
- def __iter__(self):
- yield 'user_id', self.user_id
- yield 'email', self.email
- yield 'name', self.name
- yield 'role', self.role
- yield 'balance', self.balance
- yield 'status', self.status
+ # def __repr__(self):
+ # return '' % self.name
+
\ No newline at end of file
diff --git a/src/repositories/CategoryRepository.py b/src/repositories/CategoryRepository.py
index f13ec12..e51d744 100644
--- a/src/repositories/CategoryRepository.py
+++ b/src/repositories/CategoryRepository.py
@@ -8,7 +8,7 @@ def createNewCategory(self,data):
newCategory = Category(name=data['name'])
db.session.add(newCategory)
db.session.commit()
- return dict(newCategory)
+ return newCategory
def getCategoryById(self,category_id):
return Category.query.filter_by(category_id=category_id).first()
@@ -18,7 +18,7 @@ def updateCategory(self,id,data):
if(not category) :return False
category.name = data['name']
db.session.commit()
- return dict(category)
+ return category
def deleteCategory(self,id):
category = Category.query.filter_by(category_id=id).first()
diff --git a/src/repositories/EventRepository.py b/src/repositories/EventRepository.py
index 7e5eed9..4b5520a 100644
--- a/src/repositories/EventRepository.py
+++ b/src/repositories/EventRepository.py
@@ -40,22 +40,24 @@ def createNewEvent(self,title,description,price,date_of_event,number_of_ticket,u
)
db.session.add(newEvent)
db.session.commit()
- return dict(newEvent)
+ return newEvent
def getEventById(self,event_id):
return Event.query.filter_by(event_id=event_id).first()
- def updateEvent(self,event_id,title,description,price,date_of_event,number_of_tickets,poster_path):
+ def updateEvent(self,event_id,title,description,price,date_of_event,number_of_ticket,poster_path,address,category_id):
event = Event.query.filter_by(event_id=event_id).first()
if(not event) :return False
event.title = title
+ event.address = address
+ event.category_id = category_id
event.description = description
event.price = price
event.date_of_event = date_of_event
- event.number_of_ticket = number_of_tickets
+ event.number_of_ticket = number_of_ticket
event.poster_path = poster_path
db.session.commit()
- return dict(event)
+ return event
def deleteEvent(self,event_id):
event = Event.query.filter_by(event_id=event_id).first()
@@ -69,7 +71,7 @@ def updateStatus(self,event_id,status):
if(not event) :return False
event.status = status
db.session.commit()
- return dict(event)
+ return event
def getAllEventByUserId(self,user_id):
return Event.query.filter_by(user_id=user_id).all()
\ No newline at end of file
diff --git a/src/repositories/TicketRepository.py b/src/repositories/TicketRepository.py
new file mode 100644
index 0000000..d366446
--- /dev/null
+++ b/src/repositories/TicketRepository.py
@@ -0,0 +1,23 @@
+from src.models.Ticket import Ticket,db
+import string
+import random
+class TicketRepository:
+ def getAllTickets(self):
+ return Ticket.query.all()
+
+ def getAllTicketByUserId(self,user_id):
+ return Ticket.query.filter_by(user_id=user_id).all()
+
+ def getAllTicketByEventId(self,event_id):
+ return Ticket.query.filter_by(event_id=event_id).all()
+
+ def createNewTicket(self,data,user_id):
+ newTicket = Ticket(
+ event_id=data['event_id'],
+ user_id=user_id,
+ ticket_code=''.join(random.choices(string.ascii_uppercase + string.digits, k = 6)) ,
+ )
+ db.session.add(newTicket)
+ db.session.commit()
+ return newTicket\
+
\ No newline at end of file
diff --git a/src/repositories/UserRepository.py b/src/repositories/UserRepository.py
index be85064..664f50a 100644
--- a/src/repositories/UserRepository.py
+++ b/src/repositories/UserRepository.py
@@ -20,7 +20,7 @@ def createNewUser(self,data):
)
db.session.add(newUser)
db.session.commit()
- return dict(newUser)
+ return newUser
def getUserById(self,user_id):
return User.query.filter_by(user_id=user_id).first()
def verifyUser(self,user_id):
@@ -28,4 +28,4 @@ def verifyUser(self,user_id):
if(not user) :return False
user.status = 'ACTIVE'
db.session.commit()
- return dict(user)
\ No newline at end of file
+ return user
\ No newline at end of file
diff --git a/src/routes/main.py b/src/routes/main.py
index c39d11f..9c3d9df 100644
--- a/src/routes/main.py
+++ b/src/routes/main.py
@@ -2,9 +2,11 @@
from src.controllers.AuthController import AuthApp
from src.controllers.EventController import EventApp
from src.controllers.CategoryController import CategoryApp
+from src.controllers.TicketController import TicketApp
routes = [
{ "url": "/users", "name": UserApp },
{"url": "/auth", "name": AuthApp},
{"url":"/categories","name":CategoryApp},
{"url":"/events","name":EventApp},
+ {"url":"/tickets","name":TicketApp}
]
diff --git a/src/server/main.py b/src/server/main.py
index e99d12b..e3acc1a 100644
--- a/src/server/main.py
+++ b/src/server/main.py
@@ -1,12 +1,14 @@
-from flask import Flask
+from flask import Flask,g
from flask_cors import CORS
from flask_migrate import Migrate
from src.config.config import BASE_URL, PORT, DEBUG
+from src.config.mail import mailConfig
from src.config.database import database
-main_app = Flask(__name__,static_folder='../../public', static_url_path='/')
-
+main_app = Flask(__name__,static_folder='../../public', static_url_path='/',template_folder='../../templates')
+mail = mailConfig(main_app)
CORS(main_app)
+
db = database(main_app)
migrate = Migrate(main_app, db)
diff --git a/src/services/AuthService.py b/src/services/AuthService.py
index 5ef42b3..8053376 100644
--- a/src/services/AuthService.py
+++ b/src/services/AuthService.py
@@ -3,6 +3,7 @@
from src.repositories.UserRepository import UserRepository
import bcrypt
import src.utils.jwt as jwt
+from src.utils.convert import queryResultToDict
user_repository = UserRepository()
from src.services.Service import Service
class AuthService(Service):
@@ -26,7 +27,7 @@ def registerUser(self, data):
newUser = user_repository.createNewUser(data)
- return self.failedOrSuccessRequest('success', 201, newUser)
+ return self.failedOrSuccessRequest('success', 201, queryResultToDict([newUser])[0])
except ValueError as e:
return self.failedOrSuccessRequest('failed', 500, errorHandler(e.errors()))
@@ -37,12 +38,14 @@ def login(self,data):
return self.failedOrSuccessRequest('failed', 400, 'Validation failed')
user = user_repository.getUserByEmail(data['email'])
+ if not user:
+ return self.failedOrSuccessRequest('failed', 400, 'user not found')
isPasswordMatch = bcrypt.checkpw(data['password'].encode('utf-8'), user.password.encode('utf-8') )
if not user or not isPasswordMatch:
return self.failedOrSuccessRequest('failed', 400, 'user not found')
print(user.status)
if(user.status == 'INACTIVE'):return self.failedOrSuccessRequest('failed', 400, 'user not verified')
- user_dict = dict(user)
+ user_dict = queryResultToDict([user])[0]
user_dict['token'] = jwt.encode(user_dict)
return self.failedOrSuccessRequest('success', 200,user_dict)
@@ -57,7 +60,7 @@ def verifyEO(self,data):
user.status = 'ACTIVE'
user_repository.commit()
- return self.failedOrSuccessRequest('success', 200, dict(user))
+ return self.failedOrSuccessRequest('success', 200, queryResultToDict([user])[0])
except ValueError as e:
return self.failedOrSuccessRequest('failed', 500, errorHandler(e.errors()))
def verify(self,data):
@@ -68,6 +71,6 @@ def verify(self,data):
user = user_repository.verifyUser(data['user_id'])
if not user:
return self.failedOrSuccessRequest('failed', 400, 'user not found')
- return self.failedOrSuccessRequest('success', 200, dict(user))
+ return self.failedOrSuccessRequest('success', 200, queryResultToDict([user])[0])
except ValueError as e:
return self.failedOrSuccessRequest('failed', 500, errorHandler(e.errors()))
\ No newline at end of file
diff --git a/src/services/CategoryService.py b/src/services/CategoryService.py
index 5da28b6..846c45d 100644
--- a/src/services/CategoryService.py
+++ b/src/services/CategoryService.py
@@ -1,6 +1,6 @@
from src.repositories.CategoryRepository import CategoryRepository
-from src.utils.convert import transformToDictList
+from src.utils.convert import queryResultToDict
from src.services.Service import Service
from src.utils.validator.CategoryValidator import CreateNewCategoryValidator,UpdateCategoryValidator,DeleteCategoryValidator
@@ -19,7 +19,7 @@ def failedOrSuccessRequest(status, code, data):
def getAllCategories(self):
try:
data = categoryRepository.getAllCategories()
- return CategoryService.failedOrSuccessRequest('success', 200, transformToDictList(data))
+ return CategoryService.failedOrSuccessRequest('success', 200, queryResultToDict(data))
except Exception as e:
return CategoryService.failedOrSuccessRequest('failed', 500, str(e))
@@ -29,7 +29,7 @@ def createCategory(self,data):
if not validate:
return self.failedOrSuccessRequest('failed', 400, 'Validation failed')
newCategory = categoryRepository.createNewCategory(data)
- return self.failedOrSuccessRequest('success', 201, newCategory)
+ return self.failedOrSuccessRequest('success', 201, queryResultToDict([newCategory])[0])
except ValueError as e:
return self.failedOrSuccessRequest('failed', 500, errorHandler(e.errors()))
except Exception as e:
@@ -44,7 +44,7 @@ def updateCategory(self,id,data):
if not event:
return self.failedOrSuccessRequest('failed', 404, 'Category not found')
categoryUpdated = categoryRepository.updateCategory(id,data)
- return self.failedOrSuccessRequest('success', 201, categoryUpdated)
+ return self.failedOrSuccessRequest('success', 201, queryResultToDict([categoryUpdated])[0])
except ValueError as e:
return self.failedOrSuccessRequest('failed', 500, errorHandler(e.errors()))
except Exception as e:
diff --git a/src/services/EventService.py b/src/services/EventService.py
index ac66779..c39b911 100644
--- a/src/services/EventService.py
+++ b/src/services/EventService.py
@@ -1,6 +1,6 @@
from src.repositories.EventRepository import EventRepository
-from src.utils.convert import transformToDictList
+from src.utils.convert import queryResultToDict
from src.services.Service import Service
from src.utils.uploadFile import upload_file,delete_file
from src.utils.validator.EventValidator import CreateNewEventValidator,UpdateEventValidator,DeleteEventValidator,VerifyEventValidator
@@ -23,7 +23,7 @@ def getAllEvent(self,filter):
data = eventRepository.getAllEventFiltered(filter)
else:
data = eventRepository.getAllEvent()
- return EventService.failedOrSuccessRequest('success', 200, transformToDictList(data))
+ return EventService.failedOrSuccessRequest('success', 200, queryResultToDict(data,['user','category']))
except Exception as e:
print(e)
return EventService.failedOrSuccessRequest('failed', 500, str(e))
@@ -38,7 +38,7 @@ def createEvent(self,data,file,user_id):
return EventService.failedOrSuccessRequest('failed', 400, 'poster is required')
poster = upload_file(file['poster'])
newEvent = eventRepository.createNewEvent(**data,poster_path=poster,user_id=user_id)
- return EventService.failedOrSuccessRequest('success', 201, newEvent)
+ return EventService.failedOrSuccessRequest('success', 201, queryResultToDict([newEvent])[0])
except ValueError as e:
return EventService.failedOrSuccessRequest('failed', 500, errorHandler(e.errors()))
except Exception as e:
@@ -52,19 +52,18 @@ def updateEvent(self,id,data,file ,user_id):
if not event:
return EventService.failedOrSuccessRequest('failed', 404, 'Event not found')
data_dict = data.to_dict()
- event_copied = event.toDict().copy()
+ event_copied = queryResultToDict([event])[0]
if file:
- delete_file(event['poster_path'])
+ print(event)
event_copied['poster_path'] = upload_file(file['poster'])
event_copied.update(data_dict)
event_copied.pop('user_id')
event_copied.pop('status')
- print('event',event_copied)
-
+ print(event_copied,file=sys.stderr)
eventUpdated = eventRepository.updateEvent(**event_copied)
- return EventService.failedOrSuccessRequest('success', 201, eventUpdated)
+ return EventService.failedOrSuccessRequest('success', 201, queryResultToDict([eventUpdated])[0])
except ValueError as e:
return EventService.failedOrSuccessRequest('failed', 500, errorHandler(e.errors()))
except Exception as e:
diff --git a/src/services/TicketService.py b/src/services/TicketService.py
new file mode 100644
index 0000000..e6518df
--- /dev/null
+++ b/src/services/TicketService.py
@@ -0,0 +1,55 @@
+
+from src.repositories.TicketRepository import TicketRepository
+from src.utils.convert import queryResultToDict
+from src.services.Service import Service
+from src.utils.validator.TicketValidator import CreateNewTicketValidator
+from src.utils.errorHandler import errorHandler
+from src.utils.sendMail import sendMail
+
+ticketRepository = TicketRepository()
+
+class TicketService(Service):
+ @staticmethod
+ def failedOrSuccessRequest(status, code, data):
+ return {
+ 'status': status,
+ "code": code,
+ 'data': data,
+ }
+
+ def getAllTickets(self):
+ try:
+ data = ticketRepository.getAllTickets()
+ return self.failedOrSuccessRequest('success', 200, queryResultToDict(data,['user','event']))
+ except Exception as e:
+ return self.failedOrSuccessRequest('failed', 500, str(e))
+
+ def createNewTicket(self,data,user_id):
+ try:
+ validate = CreateNewTicketValidator(**data)
+ if(not validate):
+ return self.failedOrSuccessRequest('failed', 400, validate.errors())
+
+ data = ticketRepository.createNewTicket(data,user_id)
+ sendMail(
+ name=data.user.name,
+ code=data.ticket_code,
+ date=data.event.date_of_event,
+ event_name=data.event.title,
+ location=data.event.address,
+ subject="Ticket Event",
+ to=data.user.email
+ )
+
+ return self.failedOrSuccessRequest('success', 200, queryResultToDict([data])[0])
+ except ValueError as e:
+ return self.failedOrSuccessRequest('failed', 400, errorHandler(e.errors()))
+ except Exception as e:
+ return self.failedOrSuccessRequest('failed', 500, str(e))
+
+ def getTicketByUserId(self,user_id):
+ try:
+ data = ticketRepository.getAllTicketByUserId(user_id)
+ return self.failedOrSuccessRequest('success', 200, queryResultToDict(data,['user','event']))
+ except Exception as e:
+ return self.failedOrSuccessRequest('failed', 500, str(e))
\ No newline at end of file
diff --git a/src/services/UserService.py b/src/services/UserService.py
index c75f6cf..72bb656 100644
--- a/src/services/UserService.py
+++ b/src/services/UserService.py
@@ -1,6 +1,6 @@
from src.repositories.UserRepository import UserRepository
-from src.utils.convert import transformToDictList
+from src.utils.convert import queryResultToDict
from src.services.Service import Service
userRepository = UserRepository()
@@ -16,7 +16,7 @@ def failedOrSuccessRequest(status, code, data):
def getAllUser(self):
try:
data = userRepository.getAllUser()
- return UserService.failedOrSuccessRequest('success', 200, transformToDictList(data))
+ return UserService.failedOrSuccessRequest('success', 200, queryResultToDict(data))
except Exception as e:
return UserService.failedOrSuccessRequest('failed', 500, str(e))
diff --git a/src/utils/convert.py b/src/utils/convert.py
index 5c9b20a..835412e 100644
--- a/src/utils/convert.py
+++ b/src/utils/convert.py
@@ -1,3 +1,23 @@
def transformToDictList(data: list):
return list(map(lambda x: dict(x), data))
-
\ No newline at end of file
+
+def queryResultToDict(query_result,related_tables=None):
+ result_list = []
+ for row in query_result:
+ row_dict = {}
+ for column in row.__table__.columns:
+ row_dict[column.name] = getattr(row, column.name)
+
+ # Handle related tables
+ if related_tables:
+ for related_table in related_tables:
+ related_data = getattr(row, related_table, None)
+ if related_data is not None:
+ if isinstance(related_data, list):
+ related_data = queryResultToDict(related_data)
+ else:
+ related_data = queryResultToDict([related_data])[0]
+ row_dict[related_table] = related_data
+
+ result_list.append(row_dict)
+ return result_list
\ No newline at end of file
diff --git a/src/utils/convertResponse.py b/src/utils/convertResponse.py
new file mode 100644
index 0000000..ea507d8
--- /dev/null
+++ b/src/utils/convertResponse.py
@@ -0,0 +1,7 @@
+def query_result_to_dict(query_result):
+ result_list = []
+ for row in query_result:
+ row_dict = dict(row.__dict__)
+ row_dict.pop('_sa_instance_state', None) # Remove SQLAlchemy state
+ result_list.append(row_dict)
+ return result_list
diff --git a/src/utils/sendMail.py b/src/utils/sendMail.py
new file mode 100644
index 0000000..b48ee78
--- /dev/null
+++ b/src/utils/sendMail.py
@@ -0,0 +1,23 @@
+from flask_mail import Message
+from flask import render_template
+from src.server.main import mail
+from datetime import datetime
+def sendMail(to,subject,code,event_name,location, date:datetime,name):
+ # split date and time
+ event_date = date.strftime("%d %B %Y")
+ event_time = date.strftime("%H:%M")
+ templates = render_template('html/mail.html',code=code,event_name=event_name,location=location,name=name, date=event_date,time=event_time)
+ msg = Message(
+ subject,
+ recipients=[to],
+ html=templates,
+ sender="Ticket@gmail.com"
+ )
+ try:
+ print("sending mail")
+ mail.send(msg)
+ return True
+ except Exception as e:
+ print(e)
+ print("failed to send mail : ",e.with_traceback)
+ return False
\ No newline at end of file
diff --git a/src/utils/validator/TicketValidator.py b/src/utils/validator/TicketValidator.py
new file mode 100644
index 0000000..1a9ef8f
--- /dev/null
+++ b/src/utils/validator/TicketValidator.py
@@ -0,0 +1,5 @@
+from pydantic import BaseModel
+
+class CreateNewTicketValidator(BaseModel):
+ event_id: int
+
\ No newline at end of file
diff --git a/templates/html/mail.html b/templates/html/mail.html
new file mode 100644
index 0000000..ee25c1d
--- /dev/null
+++ b/templates/html/mail.html
@@ -0,0 +1,76 @@
+
+
+
+
+
+ Event Information Ticket
+
+
+
+
+
Your Event Information Ticket
+
Dear {{name}},
+
We are excited to have you join us for our upcoming event. Here are the details you'll need:
+
+
+
Event Details
+
Event Name: {{event_name}}
+
Date: {{date}}
+
Time: {{time}}
+
Location: {{location}}
+
+
+
If you have any questions or need further assistance, please don't hesitate to contact us.
+
Thank you for being a part of this event!
+
+
Your Ticket Code:
+
+ {{ code }}
+
+
+
Best Regards,
SeTicket Team
+
+
+
+