Skip to content

Commit

Permalink
Merge pull request #24 from cf15-t5/development
Browse files Browse the repository at this point in the history
Feat/tickets (#23)
  • Loading branch information
lutfianRhdn authored Aug 21, 2023
2 parents cf1b74f + d6d647a commit a5c621d
Show file tree
Hide file tree
Showing 29 changed files with 472 additions and 105 deletions.
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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 = '[email protected]'
MAIL_PASSWORD = 'duewujqfideibbkm'
MAIL_USE_TLS = False
MAIL_USE_SSL = True
44 changes: 44 additions & 0 deletions migrations/versions/734664dd0b82_create_ticket_table.py
Original file line number Diff line number Diff line change
@@ -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 ###
77 changes: 77 additions & 0 deletions public/mail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Event Information Ticket</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.container {
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
padding: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
h1 {
color: #333;
}
p {
line-height: 1.6;
color: #666;
}
.event-details {
background-color: #f9f9f9;
padding: 10px;
border-radius: 5px;
}
.button {
display: inline-block;
padding: 10px 20px;
background-color: #007BFF;
color: #ffffff;
text-decoration: none;
border-radius: 5px;
}
.ticket-code {
background-color: #007BFF;
color: #ffffff;
padding: 10px;
border-radius: 5px;
margin-top: 20px;
}
</style>
</head>
<body>
<div class="container">
<h1>Your Event Information Ticket</h1>
<p>Dear [Recipient's Name],</p>
<p>We are excited to have you join us for our upcoming event. Here are the details you'll need:</p>

<div class="event-details">
<h2>Event Details</h2>
<p><strong>Event Name:</strong> [Event Name]</p>
<p><strong>Date:</strong> [Event Date]</p>
<p><strong>Time:</strong> [Event Time]</p>
<p><strong>Location:</strong> [Event Location]</p>
</div>

<p>If you have any questions or need further assistance, please don't hesitate to contact us.</p>
<p>Thank you for being a part of this event!</p>

<p>Your Ticket Code:</p>
<div class="ticket-code">
{{ code }}
</div>

<p>Best Regards,<br>Your Event Team</p>

<p><a class="button" href="[Event Link]">Get Directions</a></p>
</div>
</body>
</html>
3 changes: 2 additions & 1 deletion requirement.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Flask-Migrate==4.0.4
Flask-Mail==0.9.1
10 changes: 10 additions & 0 deletions src/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'
13 changes: 13 additions & 0 deletions src/config/mail.py
Original file line number Diff line number Diff line change
@@ -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)

1 change: 1 addition & 0 deletions src/config/permission.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
'/auth/logout',
'/categories',
'/events/',
'/tickets/'
]

admin_permission=[
Expand Down
41 changes: 41 additions & 0 deletions src/controllers/TicketController.py
Original file line number Diff line number Diff line change
@@ -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('/<id>/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")
4 changes: 3 additions & 1 deletion src/middlewares/AuthMiddleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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)
Expand Down
17 changes: 1 addition & 16 deletions src/models/Category.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,4 @@ class Category(db.Model):

def __init__(self,name ):
self.name = name

def __repr__(self):

return f"<Event (id={self.event_id}, name={self.name})>"


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


36 changes: 3 additions & 33 deletions src/models/Event.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"<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 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

18 changes: 18 additions & 0 deletions src/models/Ticket.py
Original file line number Diff line number Diff line change
@@ -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

27 changes: 4 additions & 23 deletions src/models/User.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,14 @@ 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
self.role = role
self.password = password
self.balance = balance
self.status = status

def __repr__(self):
return f"<User(id={self.user_id}, email={self.email}, name={self.name}, role={self.role}, balance={self.balance}, status={self.status})>"


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 '<User %r>' % self.name

4 changes: 2 additions & 2 deletions src/repositories/CategoryRepository.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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()
Expand Down
Loading

0 comments on commit a5c621d

Please sign in to comment.