Initial commit

This commit is contained in:
2025-09-16 12:38:41 +08:00
parent 10261cab65
commit 8b777f57ad
8 changed files with 443 additions and 470 deletions

View File

@@ -1,533 +1,363 @@
import mysql.connector
from flask import Flask, request, jsonify from flask import Flask, request, jsonify
from flask_cors import CORS from flask_cors import CORS
import mysql.connector
from mysql.connector import pooling
import os
# --- Database Configuration ---
DB_HOST = "mysql.theaken.com"
DB_PORT = 33306
DB_NAME = "db_A027"
DB_USER = "A027"
DB_PASSWORD = "E1CelfxqlKoj"
# --- Create a connection pool ---
try:
db_pool = pooling.MySQLConnectionPool(
pool_name="api_pool",
pool_size=5,
host=DB_HOST,
port=DB_PORT,
database=DB_NAME,
user=DB_USER,
password=DB_PASSWORD
)
print("Database connection pool created successfully.")
except mysql.connector.Error as err:
print(f"Error creating connection pool: {err}")
exit()
# --- Flask App Initialization ---
app = Flask(__name__) app = Flask(__name__)
CORS(app) # Enable CORS for all routes CORS(app) # Enable CORS for all routes
# Database configuration
db_config = {
'host': 'mysql.theaken.com',
'port': 33306,
'user': 'A027',
'password': 'E1CelfxqlKoj',
'database': 'db_A027'
}
# --- Helper Functions ---
def get_db_connection(): def get_db_connection():
"""Get a connection from the pool.""" """Establishes a new database connection."""
try: try:
return db_pool.get_connection() conn = mysql.connector.connect(**db_config)
return conn
except mysql.connector.Error as err: except mysql.connector.Error as err:
print(f"Error getting connection from pool: {err}") print(f"Database connection error: {err}")
return None return None
def make_response(status, code, message, data=None): def make_success_response(data, code, message="Success"):
"""Standardized response format.""" """Wrapper for a successful API response."""
response = { response = {
"status": status, "status": "success",
"code": code, "code": code,
"message": message "message": message,
} }
if data is not None: if data is not None:
response["data"] = data response["data"] = data
return jsonify(response), code return jsonify(response), code
# --- Error Handlers --- def make_error_response(message, code):
@app.errorhandler(404) """Wrapper for an error API response."""
def not_found(error): return jsonify({
return make_response("error", 404, "The requested resource was not found.") "status": "error",
"code": code,
"message": message
}), code
@app.errorhandler(500) def query_to_dict(cursor, data):
def internal_server_error(error): """Converts query result to a list of dictionaries."""
return make_response("error", 500, "An internal server error occurred.") columns = [desc[0] for desc in cursor.description]
return [dict(zip(columns, row)) for row in data]
# --- Employee API Endpoints --- # --- Orders API Endpoints ---
@app.route('/v1/employee', methods=['GET']) @app.route('/v1/orders', methods=['POST'])
def get_employees(): def create_order():
conn = get_db_connection()
if not conn:
return make_response("error", 503, "Database service unavailable.")
cursor = conn.cursor(dictionary=True)
query = "SELECT * FROM employee WHERE 1=1"
params = []
if 'id' in request.args:
query += " AND id = %s"
params.append(request.args['id'])
if 'name' in request.args:
query += " AND name LIKE %s"
params.append(f"%{request.args['name']}%")
try:
cursor.execute(query, tuple(params))
employees = cursor.fetchall()
return make_response("success", 200, "Employees retrieved successfully.", {"employees": employees, "meta": {"total": len(employees)}})
except mysql.connector.Error as err:
return make_response("error", 500, str(err))
finally:
cursor.close()
conn.close()
@app.route('/v1/employee/<string:emp_id>', methods=['GET'])
def get_employee(emp_id):
conn = get_db_connection()
if not conn:
return make_response("error", 503, "Database service unavailable.")
cursor = conn.cursor(dictionary=True)
try:
cursor.execute("SELECT * FROM employee WHERE id = %s", (emp_id,))
employee = cursor.fetchone()
if employee:
return make_response("success", 200, "Employee found.", employee)
else:
return make_response("error", 404, "Employee not found.")
except mysql.connector.Error as err:
return make_response("error", 500, str(err))
finally:
cursor.close()
conn.close()
@app.route('/v1/employee', methods=['POST'])
def create_employee():
data = request.get_json()
if not data or 'id' not in data or 'name' not in data:
return make_response("error", 400, "Missing required fields: id, name.")
conn = get_db_connection()
if not conn:
return make_response("error", 503, "Database service unavailable.")
cursor = conn.cursor(dictionary=True)
try:
cursor.execute("INSERT INTO employee (id, name) VALUES (%s, %s)", (data['id'], data['name']))
conn.commit()
cursor.execute("SELECT * FROM employee WHERE id = %s", (data['id'],))
new_employee = cursor.fetchone()
return make_response("success", 201, "Employee created successfully.", new_employee)
except mysql.connector.Error as err:
conn.rollback()
return make_response("error", 500, str(err))
finally:
cursor.close()
conn.close()
@app.route('/v1/employee/<string:emp_id>', methods=['PATCH'])
def update_employee(emp_id):
data = request.get_json() data = request.get_json()
if not data: if not data:
return make_response("error", 400, "No update data provided.") return make_error_response("Invalid JSON", 400)
required_fields = ['emp_id', 'emp_name', 'menu_item_id', 'main_course', 'order_date', 'order_qty']
if not all(field in data for field in required_fields):
return make_error_response(f"Missing required fields: {required_fields}", 400)
sql = """
INSERT INTO orders (emp_id, emp_name, menu_item_id, main_course, order_date, order_qty)
VALUES (%(emp_id)s, %(emp_name)s, %(menu_item_id)s, %(main_course)s, %(order_date)s, %(order_qty)s)
"""
conn = get_db_connection() conn = get_db_connection()
if not conn: if not conn:
return make_response("error", 503, "Database service unavailable.") return make_error_response("Database connection failed", 500)
cursor = conn.cursor(dictionary=True)
updates = []
params = []
if 'name' in data:
updates.append("name = %s")
params.append(data['name'])
if not updates:
return make_response("error", 400, "No valid fields to update.")
params.append(emp_id)
query = f"UPDATE employee SET {', '.join(updates)} WHERE id = %s"
try:
cursor.execute(query, tuple(params))
conn.commit()
if cursor.rowcount == 0:
return make_response("error", 404, "Employee not found or data is the same.")
cursor.execute("SELECT * FROM employee WHERE id = %s", (emp_id,)) try:
updated_employee = cursor.fetchone() cursor = conn.cursor(dictionary=True)
return make_response("success", 200, "Employee updated successfully.", updated_employee) cursor.execute(sql, data)
conn.commit()
new_id = cursor.lastrowid
cursor.execute("SELECT * FROM orders WHERE id = %s", (new_id,))
new_order = cursor.fetchone()
return make_success_response(new_order, 201, "Order created successfully.")
except mysql.connector.Error as err: except mysql.connector.Error as err:
conn.rollback() return make_error_response(f"Database error: {err}", 500)
return make_response("error", 500, str(err))
finally: finally:
cursor.close() if conn.is_connected():
conn.close() conn.close()
@app.route('/v1/employee/<string:emp_id>', methods=['DELETE']) @app.route('/v1/orders/<int:order_id>', methods=['GET'])
def delete_employee(emp_id): def get_order_by_id(order_id):
conn = get_db_connection() conn = get_db_connection()
if not conn: if not conn:
return make_response("error", 503, "Database service unavailable.") return make_error_response("Database connection failed", 500)
cursor = conn.cursor()
try:
cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT * FROM orders WHERE id = %s", (order_id,))
order = cursor.fetchone()
if order:
return make_success_response(order, 200)
else:
return make_error_response("Order not found", 404)
except mysql.connector.Error as err:
return make_error_response(f"Database error: {err}", 500)
finally:
if conn.is_connected():
conn.close()
@app.route('/v1/orders', methods=['GET'])
def get_orders():
query_params = request.args.to_dict()
sql = "SELECT * FROM orders"
conditions = []
params = {}
for key, value in query_params.items():
# Basic filtering, can be expanded
conditions.append(f"{key} = %({key})s")
params[key] = value
if conditions:
sql += " WHERE " + " AND ".join(conditions)
conn = get_db_connection()
if not conn:
return make_error_response("Database connection failed", 500)
try: try:
# Note: Deleting an employee might fail if they have existing votes due to foreign key constraints. cursor = conn.cursor(dictionary=True)
# This should be handled by the application logic (e.g., delete votes first or prevent deletion). cursor.execute(sql, params)
cursor.execute("DELETE FROM employee WHERE id = %s", (emp_id,)) orders = cursor.fetchall()
conn.commit()
if cursor.rowcount == 0: meta = {
return make_response("error", 404, "Employee not found.") "total_items": len(orders),
return make_response("success", 204, "Employee deleted successfully.") "query_params": query_params
}
data = {
"orders": orders,
"meta": meta
}
return make_success_response(data, 200)
except mysql.connector.Error as err: except mysql.connector.Error as err:
conn.rollback() return make_error_response(f"Database error: {err}", 500)
# Check for foreign key constraint violation
if err.errno == 1451:
return make_response("error", 409, "Cannot delete employee with existing votes. Please remove their votes first.")
return make_response("error", 500, str(err))
finally: finally:
cursor.close() if conn.is_connected():
conn.close() conn.close()
@app.route('/v1/orders/<int:order_id>', methods=['PATCH'])
def update_order(order_id):
data = request.get_json()
if not data:
return make_error_response("Invalid JSON", 400)
set_clauses = []
params = {}
for key, value in data.items():
set_clauses.append(f"{key} = %({key})s")
params[key] = value
if not set_clauses:
return make_error_response("No fields to update", 400)
params['id'] = order_id
sql = f"UPDATE orders SET {', '.join(set_clauses)} WHERE id = %(id)s"
conn = get_db_connection()
if not conn:
return make_error_response("Database connection failed", 500)
try:
cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT * FROM orders WHERE id = %s", (order_id,))
if not cursor.fetchone():
return make_error_response("Order not found", 404)
cursor.execute(sql, params)
conn.commit()
cursor.execute("SELECT * FROM orders WHERE id = %s", (order_id,))
updated_order = cursor.fetchone()
return make_success_response(updated_order, 200, "Order updated successfully.")
except mysql.connector.Error as err:
return make_error_response(f"Database error: {err}", 500)
finally:
if conn.is_connected():
conn.close()
@app.route('/v1/orders/<int:order_id>', methods=['DELETE'])
def delete_order(order_id):
conn = get_db_connection()
if not conn:
return make_error_response("Database connection failed", 500)
try:
cursor = conn.cursor()
cursor.execute("SELECT * FROM orders WHERE id = %s", (order_id,))
if not cursor.fetchone():
return make_error_response("Order not found", 404)
cursor.execute("DELETE FROM orders WHERE id = %s", (order_id,))
conn.commit()
return make_success_response(None, 204, "Order deleted successfully.")
except mysql.connector.Error as err:
return make_error_response(f"Database error: {err}", 500)
finally:
if conn.is_connected():
conn.close()
# --- Menu Items API Endpoints --- # --- Menu Items API Endpoints ---
@app.route('/v1/menu_items', methods=['GET'])
def get_menu_items():
conn = get_db_connection()
if not conn:
return make_response("error", 503, "Database service unavailable.")
cursor = conn.cursor(dictionary=True)
query = "SELECT * FROM menu_items WHERE 1=1"
params = []
if 'id' in request.args:
query += " AND id = %s"
params.append(request.args['id'])
if 'main_course' in request.args:
query += " AND main_course LIKE %s"
params.append(f"%{request.args['main_course']}%")
if 'side_dish' in request.args:
query += " AND side_dish LIKE %s"
params.append(f"%{request.args['side_dish']}%")
if 'addon' in request.args:
query += " AND addon LIKE %s"
params.append(f"%{request.args['addon']}%")
if 'menu_date' in request.args:
query += " AND menu_date = %s"
params.append(request.args['menu_date'])
try:
cursor.execute(query, tuple(params))
items = cursor.fetchall()
return make_response("success", 200, "Menu items retrieved successfully.", {"menu_items": items, "meta": {"total": len(items)}})
except mysql.connector.Error as err:
return make_response("error", 500, str(err))
finally:
cursor.close()
conn.close()
@app.route('/v1/menu_items/<int:item_id>', methods=['GET'])
def get_menu_item(item_id):
conn = get_db_connection()
if not conn:
return make_response("error", 503, "Database service unavailable.")
cursor = conn.cursor(dictionary=True)
try:
cursor.execute("SELECT * FROM menu_items WHERE id = %s", (item_id,))
item = cursor.fetchone()
if item:
return make_response("success", 200, "Menu item found.", item)
else:
return make_response("error", 404, "Menu item not found.")
except mysql.connector.Error as err:
return make_response("error", 500, str(err))
finally:
cursor.close()
conn.close()
@app.route('/v1/menu_items', methods=['POST']) @app.route('/v1/menu_items', methods=['POST'])
def create_menu_item(): def create_menu_item():
data = request.get_json() data = request.get_json()
if not data or not all(k in data for k in ['main_course', 'side_dish', 'addon', 'menu_date']): if not data:
return make_response("error", 400, "Missing required fields: main_course, side_dish, addon, menu_date.") return make_error_response("Invalid JSON", 400)
required_fields = ['main_course', 'menu_date']
if not all(field in data for field in required_fields):
return make_error_response(f"Missing required fields: {required_fields}", 400)
sql = """
INSERT INTO menu_items (main_course, side_dish, addon, menu_date)
VALUES (%(main_course)s, %(side_dish)s, %(addon)s, %(menu_date)s)
"""
conn = get_db_connection() conn = get_db_connection()
if not conn: if not conn:
return make_response("error", 503, "Database service unavailable.") return make_error_response("Database connection failed", 500)
cursor = conn.cursor(dictionary=True)
try:
cursor = conn.cursor(dictionary=True)
cursor.execute(sql, data)
conn.commit()
new_id = cursor.lastrowid
cursor.execute("SELECT * FROM menu_items WHERE id = %s", (new_id,))
new_item = cursor.fetchone()
return make_success_response(new_item, 201, "Menu item created successfully.")
except mysql.connector.Error as err:
return make_error_response(f"Database error: {err}", 500)
finally:
if conn.is_connected():
conn.close()
@app.route('/v1/menu_items/<int:item_id>', methods=['GET'])
def get_menu_item_by_id(item_id):
conn = get_db_connection()
if not conn:
return make_error_response("Database connection failed", 500)
try:
cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT * FROM menu_items WHERE id = %s", (item_id,))
item = cursor.fetchone()
if item:
return make_success_response(item, 200)
else:
return make_error_response("Menu item not found", 404)
except mysql.connector.Error as err:
return make_error_response(f"Database error: {err}", 500)
finally:
if conn.is_connected():
conn.close()
@app.route('/v1/menu_items', methods=['GET'])
def get_menu_items():
query_params = request.args.to_dict()
sql = "SELECT * FROM menu_items"
conditions = []
params = {}
for key, value in query_params.items():
conditions.append(f"{key} = %({key})s")
params[key] = value
if conditions:
sql += " WHERE " + " AND ".join(conditions)
conn = get_db_connection()
if not conn:
return make_error_response("Database connection failed", 500)
try: try:
sql = "INSERT INTO menu_items (main_course, side_dish, addon, menu_date) VALUES (%s, %s, %s, %s)" cursor = conn.cursor(dictionary=True)
params = (data['main_course'], data['side_dish'], data['addon'], data['menu_date'])
cursor.execute(sql, params) cursor.execute(sql, params)
new_item_id = cursor.lastrowid items = cursor.fetchall()
conn.commit()
cursor.execute("SELECT * FROM menu_items WHERE id = %s", (new_item_id,)) meta = {
new_item = cursor.fetchone() "total_items": len(items),
return make_response("success", 201, "Menu item created successfully.", new_item) "query_params": query_params
}
data = {
"menu_items": items,
"meta": meta
}
return make_success_response(data, 200)
except mysql.connector.Error as err: except mysql.connector.Error as err:
conn.rollback() return make_error_response(f"Database error: {err}", 500)
return make_response("error", 500, str(err))
finally: finally:
cursor.close() if conn.is_connected():
conn.close() conn.close()
@app.route('/v1/menu_items/<int:item_id>', methods=['PATCH']) @app.route('/v1/menu_items/<int:item_id>', methods=['PATCH'])
def update_menu_item(item_id): def update_menu_item(item_id):
data = request.get_json() data = request.get_json()
if not data: if not data:
return make_response("error", 400, "No update data provided.") return make_error_response("Invalid JSON", 400)
set_clauses = []
params = {}
for key, value in data.items():
set_clauses.append(f"{key} = %({key})s")
params[key] = value
if not set_clauses:
return make_error_response("No fields to update", 400)
params['id'] = item_id
sql = f"UPDATE menu_items SET {', '.join(set_clauses)} WHERE id = %(id)s"
conn = get_db_connection() conn = get_db_connection()
if not conn: if not conn:
return make_response("error", 503, "Database service unavailable.") return make_error_response("Database connection failed", 500)
cursor = conn.cursor(dictionary=True)
updates = []
params = []
for key in ['main_course', 'side_dish', 'addon', 'menu_date']:
if key in data:
updates.append(f"{key} = %s")
params.append(data[key])
if not updates:
return make_response("error", 400, "No valid fields to update.")
params.append(item_id)
query = f"UPDATE menu_items SET {', '.join(updates)} WHERE id = %s"
try: try:
cursor.execute(query, tuple(params)) cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT * FROM menu_items WHERE id = %s", (item_id,))
if not cursor.fetchone():
return make_error_response("Menu item not found", 404)
cursor.execute(sql, params)
conn.commit() conn.commit()
if cursor.rowcount == 0:
return make_response("error", 404, "Menu item not found or data is the same.")
cursor.execute("SELECT * FROM menu_items WHERE id = %s", (item_id,)) cursor.execute("SELECT * FROM menu_items WHERE id = %s", (item_id,))
updated_item = cursor.fetchone() updated_item = cursor.fetchone()
return make_response("success", 200, "Menu item updated successfully.", updated_item) return make_success_response(updated_item, 200, "Menu item updated successfully.")
except mysql.connector.Error as err: except mysql.connector.Error as err:
conn.rollback() return make_error_response(f"Database error: {err}", 500)
return make_response("error", 500, str(err))
finally: finally:
cursor.close() if conn.is_connected():
conn.close() conn.close()
@app.route('/v1/menu_items/<int:item_id>', methods=['DELETE']) @app.route('/v1/menu_items/<int:item_id>', methods=['DELETE'])
def delete_menu_item(item_id): def delete_menu_item(item_id):
conn = get_db_connection() conn = get_db_connection()
if not conn: if not conn:
return make_response("error", 503, "Database service unavailable.") return make_error_response("Database connection failed", 500)
cursor = conn.cursor()
try: try:
cursor = conn.cursor()
cursor.execute("SELECT * FROM menu_items WHERE id = %s", (item_id,))
if not cursor.fetchone():
return make_error_response("Menu item not found", 404)
cursor.execute("DELETE FROM menu_items WHERE id = %s", (item_id,)) cursor.execute("DELETE FROM menu_items WHERE id = %s", (item_id,))
conn.commit() conn.commit()
if cursor.rowcount == 0: return make_success_response(None, 204, "Menu item deleted successfully.")
return make_response("error", 404, "Menu item not found.")
return make_response("success", 204, "Menu item deleted successfully.")
except mysql.connector.Error as err: except mysql.connector.Error as err:
conn.rollback() return make_error_response(f"Database error: {err}", 500)
if err.errno == 1451:
return make_response("error", 409, "Cannot delete menu item that has been voted on.")
return make_response("error", 500, str(err))
finally: finally:
cursor.close() if conn.is_connected():
conn.close() conn.close()
# --- Employee Votes API Endpoints ---
@app.route('/v1/employee_votes', methods=['GET'])
def get_employee_votes():
conn = get_db_connection()
if not conn:
return make_response("error", 503, "Database service unavailable.")
cursor = conn.cursor(dictionary=True)
query = """
SELECT v.*, e.name
FROM employee_votes v
JOIN employee e ON v.emp_id = e.id
WHERE 1=1
"""
params = []
if 'id' in request.args:
query += " AND v.id = %s"
params.append(request.args['id'])
if 'emp_id' in request.args:
query += " AND v.emp_id = %s"
params.append(request.args['emp_id'])
if 'name' in request.args: # Search by employee name
query += " AND e.name LIKE %s"
params.append(f"%{request.args['name']}%")
if 'order_date' in request.args:
query += " AND v.order_date = %s"
params.append(request.args['order_date'])
if 'menu_item_id' in request.args:
query += " AND v.menu_item_id = %s"
params.append(request.args['menu_item_id'])
if 'order_qty' in request.args:
query += " AND v.order_qty = %s"
params.append(request.args['order_qty'])
try:
cursor.execute(query, tuple(params))
votes = cursor.fetchall()
return make_response("success", 200, "Employee votes retrieved successfully.", {"employee_votes": votes, "meta": {"total": len(votes)}})
except mysql.connector.Error as err:
return make_response("error", 500, str(err))
finally:
cursor.close()
conn.close()
@app.route('/v1/employee_votes/<int:vote_id>', methods=['GET'])
def get_employee_vote(vote_id):
conn = get_db_connection()
if not conn:
return make_response("error", 503, "Database service unavailable.")
cursor = conn.cursor(dictionary=True)
try:
cursor.execute("""
SELECT v.*, e.name
FROM employee_votes v
JOIN employee e ON v.emp_id = e.id
WHERE v.id = %s
""", (vote_id,))
vote = cursor.fetchone()
if vote:
return make_response("success", 200, "Employee vote found.", vote)
else:
return make_response("error", 404, "Employee vote not found.")
except mysql.connector.Error as err:
return make_response("error", 500, str(err))
finally:
cursor.close()
conn.close()
@app.route('/v1/employee_votes', methods=['POST'])
def create_employee_vote():
data = request.get_json()
required_fields = ['emp_id', 'order_date', 'menu_item_id', 'order_qty']
if not data or not all(k in data for k in required_fields):
return make_response("error", 400, f"Missing required fields: {', '.join(required_fields)}.")
conn = get_db_connection()
if not conn:
return make_response("error", 503, "Database service unavailable.")
cursor = conn.cursor(dictionary=True)
try:
sql = "INSERT INTO employee_votes (emp_id, order_date, menu_item_id, order_qty) VALUES (%s, %s, %s, %s)"
params = (data['emp_id'], data['order_date'], data['menu_item_id'], data['order_qty'])
cursor.execute(sql, params)
new_vote_id = cursor.lastrowid
conn.commit()
cursor.execute("""
SELECT v.*, e.name
FROM employee_votes v
JOIN employee e ON v.emp_id = e.id
WHERE v.id = %s
""", (new_vote_id,))
new_vote = cursor.fetchone()
return make_response("success", 201, "Employee vote created successfully.", new_vote)
except mysql.connector.Error as err:
conn.rollback()
if err.errno == 1452: # Foreign key constraint fails
return make_response("error", 400, "Invalid emp_id or menu_item_id. The specified employee or menu item does not exist.")
return make_response("error", 500, str(err))
finally:
cursor.close()
conn.close()
@app.route('/v1/employee_votes/<int:vote_id>', methods=['PATCH'])
def update_employee_vote(vote_id):
data = request.get_json()
if not data:
return make_response("error", 400, "No update data provided.")
conn = get_db_connection()
if not conn:
return make_response("error", 503, "Database service unavailable.")
cursor = conn.cursor(dictionary=True)
updates = []
params = []
for key in ['emp_id', 'order_date', 'menu_item_id', 'order_qty']:
if key in data:
updates.append(f"{key} = %s")
params.append(data[key])
if not updates:
return make_response("error", 400, "No valid fields to update.")
params.append(vote_id)
query = f"UPDATE employee_votes SET {', '.join(updates)} WHERE id = %s"
try:
cursor.execute(query, tuple(params))
conn.commit()
if cursor.rowcount == 0:
return make_response("error", 404, "Employee vote not found or data is the same.")
cursor.execute("""
SELECT v.*, e.name
FROM employee_votes v
JOIN employee e ON v.emp_id = e.id
WHERE v.id = %s
""", (vote_id,))
updated_vote = cursor.fetchone()
return make_response("success", 200, "Employee vote updated successfully.", updated_vote)
except mysql.connector.Error as err:
conn.rollback()
if err.errno == 1452:
return make_response("error", 400, "Invalid emp_id or menu_item_id. The specified employee or menu item does not exist.")
return make_response("error", 500, str(err))
finally:
cursor.close()
conn.close()
@app.route('/v1/employee_votes/<int:vote_id>', methods=['DELETE'])
def delete_employee_vote(vote_id):
conn = get_db_connection()
if not conn:
return make_response("error", 503, "Database service unavailable.")
cursor = conn.cursor()
try:
cursor.execute("DELETE FROM employee_votes WHERE id = %s", (vote_id,))
conn.commit()
if cursor.rowcount == 0:
return make_response("error", 404, "Employee vote not found.")
return make_response("success", 204, "Employee vote deleted successfully.")
except mysql.connector.Error as err:
conn.rollback()
return make_response("error", 500, str(err))
finally:
cursor.close()
conn.close()
# --- Main Execution ---
if __name__ == '__main__': if __name__ == '__main__':
# To run this server: app.run(host='0.0.0.0', port=5000, debug=True)
# 1. Make sure you have Flask, Flask-Cors, and mysql-connector-python installed:
# pip install Flask Flask-Cors mysql-connector-python
# 2. Run the script:
# python api_server.py
# The server will start on http://127.0.0.1:5000
app.run(debug=True, host='0.0.0.0', port=5000)

View File

@@ -8,32 +8,27 @@ DB_NAME = db_A027
DB_USER = A027 DB_USER = A027
DB_PASSWORD = E1CelfxqlKoj DB_PASSWORD = E1CelfxqlKoj
TABLE = employee
- 路由:
- GET /v1/employee支援 ?Id、?main_course、?side_dish、?addon、?is_active要多回傳 {meta}
- GET /v1/employee/<id>:找不到回 404
- POST /v1/employee接收 JSON {ID,main_course,side_dish,addon,is_active},欄位驗證,成功回 201 並回新資料
- PATCH /v1/employee/<id>可更新任一欄位ID/main_course/side_dish/addon/is_active成功回 200 回更新後資料
- DELETE /v1/employee/<id>:成功回 204
TABLE = employee_votes TABLE = orders
- 路由: - 路由:
- GET /v1/employee_votes支援 ?Id、?emp_id、?name、?order_date、?menu_item_id、?order_qty要多回傳 {meta} - GET /v1/orders支援 ?Id、?emp_id、?emp_name、?menu_item_id、?main_course、?order_date、?order_qty要多回傳 {meta}
- GET /v1/employee_votes/<id>:找不到回 404 - GET /v1/orders/<id>:找不到回 404
- POST /v1/employee_votes接收 JSON {Id,emp_id,name,order_date,menu_item_id,order_qty},欄位驗證,成功回 201 並回新資料 - POST /v1/orders接收 JSON {Id,emp_id,emp_name,menu_item_id,main_course,order_date,order_qty},欄位驗證,成功回 201 並回新資料
- PATCH /v1/employee_votes/<id>:可更新任一欄位(Id/emp_id/name/order_date/menu_item_id/order_qty成功回 200 回更新後資料 - PATCH /v1/orders/<id>:可更新任一欄位(id/emp_id/name/menu_item_id/main_course/order_date/order_qty成功回 200 回更新後資料
- DELETE /v1/employee_votes/<id>:成功回 204 - DELETE /v1/orders/<id>:成功回 204
TABLE = menu_items TABLE = menu_items
- 路由: - 路由:
- GET /v1/menu_items支援 ?Id、?main_course、?side_dish、?addon、?is_active要多回傳 {meta} - GET /v1/menu_items支援 ?id、?main_course、?side_dish、?addon、?menu_date要多回傳 {meta}
- GET /v1/menu_items/<id>:找不到回 404 - GET /v1/menu_items/<id>:找不到回 404
- POST /v1/menu_items接收 JSON {ID,main_course,side_dish,addon,is_active},欄位驗證,成功回 201 並回新資料 - POST /v1/menu_items接收 JSON {id,main_course,side_dish,addon,menu_date},欄位驗證,成功回 201 並回新資料
- PATCH /v1/menu_items/<id>:可更新任一欄位(ID/main_course/side_dish/addon/is_active成功回 200 回更新後資料 - PATCH /v1/menu_items/<id>:可更新任一欄位(id/main_course/side_dish/addon/menu_date成功回 200 回更新後資料
- DELETE /v1/menu_items/<id>:成功回 204 - DELETE /v1/menu_items/<id>:成功回 204
- 所有寫入請用參數化查詢避免 SQL 注入 - 所有寫入請用參數化查詢避免 SQL 注入

39
create_menu_table.py Normal file
View File

@@ -0,0 +1,39 @@
import mysql.connector
# DB credentials
config = {
'user': 'A027',
'password': 'E1CelfxqlKoj',
'host': 'mysql.theaken.com',
'port': 33306,
'database': 'db_A027'
}
TABLES = {}
TABLES['menu_items'] = (
"CREATE TABLE `menu_items` ("
" `id` int NOT NULL AUTO_INCREMENT,"
" `main_course` varchar(255) NOT NULL,"
" `side_dish` varchar(255) DEFAULT NULL,"
" `addon` varchar(255) DEFAULT NULL,"
" `menu_date` date NOT NULL,"
" PRIMARY KEY (`id`)"
") ENGINE=InnoDB")
try:
cnx = mysql.connector.connect(**config)
cursor = cnx.cursor()
cursor.execute("DROP TABLE IF EXISTS menu_items")
table_description = TABLES['menu_items']
cursor.execute(table_description)
print("資料表 'menu_items' 建立成功!")
except mysql.connector.Error as err:
print(f"資料庫錯誤: {err}")
finally:
if 'cursor' in locals() and cursor:
cursor.close()
if 'cnx' in locals() and cnx.is_connected():
cnx.close()

46
create_order_table.py Normal file
View File

@@ -0,0 +1,46 @@
import mysql.connector
from mysql.connector import errorcode
# Assuming the same DB credentials as the previous task
config = {
'user': 'A027',
'password': 'E1CelfxqlKoj',
'host': 'mysql.theaken.com',
'port': 33306,
'database': 'db_A027'
}
TABLES = {}
TABLES['orders'] = (
"CREATE TABLE `orders` ("
" `id` int NOT NULL AUTO_INCREMENT,"
" `emp_id` varchar(10) NOT NULL,"
" `emp_name` varchar(10) NOT NULL,"
" `menu_item_id` int NOT NULL,"
" `main_course` int NOT NULL,"
" `order_date` date NOT NULL,"
" `order_qty` int NOT NULL,"
" PRIMARY KEY (`id`)"
") ENGINE=InnoDB")
try:
cnx = mysql.connector.connect(**config)
cursor = cnx.cursor()
# Drop the table if it exists
cursor.execute("DROP TABLE IF EXISTS orders")
print("資料表 'orders' 已刪除 (如果存在的話)。")
# Create the table
table_description = TABLES['orders']
cursor.execute(table_description)
print("資料表 'orders' 建立成功!")
except mysql.connector.Error as err:
print(f"資料庫錯誤: {err}")
finally:
if 'cursor' in locals() and cursor:
cursor.close()
if 'cnx' in locals() and cnx.is_connected():
cnx.close()

14
create_order_table.txt Normal file
View File

@@ -0,0 +1,14 @@
請根據以下需求幫我產生一段 Python 程式碼,能夠連線到資料庫並建立一張 orders 資料表。
資料庫資訊 參考 ".env檔"
需求:
1. 使用 mysql.connector 套件。
2. 建立一張名稱為 orders 的資料表,包含以下欄位:
- id: 訂購id (NUMBER)
- emp_id: 員工id (VARCHAR(10))
- emp_name: 員工姓名 (VARCHAR(10))
- menu_item_id: 餐點id (NUMBER)
- main_course: 主餐點名稱 (NUMBER)
- order_date: 訂購日期 (DATE)
- order_qty: 訂購數量 (NUMBER)
3. 執行成功後,印出「資料表建立成功!」。
4. 若資料表已存在,先刪除再重建。

Binary file not shown.

35
update_table.py Normal file
View File

@@ -0,0 +1,35 @@
import mysql.connector
# Database connection details from the user's file
config = {
'user': 'A027',
'password': 'E1CelfxqlKoj',
'host': 'mysql.theaken.com',
'port': 33306,
'database': 'db_A027'
}
try:
# Connect to the database
cnx = mysql.connector.connect(**config)
cursor = cnx.cursor()
# SQL statement to modify the column
alter_table_query = "ALTER TABLE orders MODIFY COLUMN main_course VARCHAR(255)"
# Execute the query
cursor.execute(alter_table_query)
# Commit the changes
cnx.commit()
print("資料表修改成功!")
except mysql.connector.Error as err:
print(f"資料庫錯誤: {err}")
finally:
# Close the connection
if 'cursor' in locals() and cursor:
cursor.close()
if 'cnx' in locals() and cnx.is_connected():
cnx.close()

14
update_table.txt Normal file
View File

@@ -0,0 +1,14 @@
請根據以下需求幫我產生一段 Python 程式碼能夠連線到資料庫並在orders的資料表修改欄位main_course型態為varchar(255)
資料庫資訊:
DB_HOST = mysql.theaken.com
DB_PORT = 33306
DB_NAME = db_A027
DB_USER = A027
DB_PASSWORD = E1CelfxqlKoj
需求:
1. 使用 mysql.connector 套件
2. 資料表在orders 幫我修改
- main_course : 主餐點名稱(varchar(255))
3. 執行成功後,印出「資料表修改成功!」。