diff --git a/api_server.py b/api_server.py index f109488..b027b3f 100644 --- a/api_server.py +++ b/api_server.py @@ -1,533 +1,363 @@ - +import mysql.connector from flask import Flask, request, jsonify 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__) -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(): - """Get a connection from the pool.""" + """Establishes a new database connection.""" try: - return db_pool.get_connection() + conn = mysql.connector.connect(**db_config) + return conn except mysql.connector.Error as err: - print(f"Error getting connection from pool: {err}") + print(f"Database connection error: {err}") return None -def make_response(status, code, message, data=None): - """Standardized response format.""" +def make_success_response(data, code, message="Success"): + """Wrapper for a successful API response.""" response = { - "status": status, + "status": "success", "code": code, - "message": message + "message": message, } if data is not None: response["data"] = data return jsonify(response), code -# --- Error Handlers --- -@app.errorhandler(404) -def not_found(error): - return make_response("error", 404, "The requested resource was not found.") +def make_error_response(message, code): + """Wrapper for an error API response.""" + return jsonify({ + "status": "error", + "code": code, + "message": message + }), code -@app.errorhandler(500) -def internal_server_error(error): - return make_response("error", 500, "An internal server error occurred.") +def query_to_dict(cursor, data): + """Converts query result to a list of dictionaries.""" + 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']) -def get_employees(): - 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/', 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/', methods=['PATCH']) -def update_employee(emp_id): +@app.route('/v1/orders', methods=['POST']) +def create_order(): data = request.get_json() 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() if not conn: - return make_response("error", 503, "Database service unavailable.") - 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.") + return make_error_response("Database connection failed", 500) - cursor.execute("SELECT * FROM employee WHERE id = %s", (emp_id,)) - updated_employee = cursor.fetchone() - return make_response("success", 200, "Employee updated successfully.", updated_employee) + try: + cursor = conn.cursor(dictionary=True) + 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: - conn.rollback() - return make_response("error", 500, str(err)) + return make_error_response(f"Database error: {err}", 500) finally: - cursor.close() - conn.close() + if conn.is_connected(): + conn.close() -@app.route('/v1/employee/', methods=['DELETE']) -def delete_employee(emp_id): +@app.route('/v1/orders/', methods=['GET']) +def get_order_by_id(order_id): conn = get_db_connection() if not conn: - return make_response("error", 503, "Database service unavailable.") - cursor = conn.cursor() + return make_error_response("Database connection failed", 500) + + 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: - # Note: Deleting an employee might fail if they have existing votes due to foreign key constraints. - # This should be handled by the application logic (e.g., delete votes first or prevent deletion). - cursor.execute("DELETE FROM employee WHERE id = %s", (emp_id,)) - conn.commit() - if cursor.rowcount == 0: - return make_response("error", 404, "Employee not found.") - return make_response("success", 204, "Employee deleted successfully.") + cursor = conn.cursor(dictionary=True) + cursor.execute(sql, params) + orders = cursor.fetchall() + + meta = { + "total_items": len(orders), + "query_params": query_params + } + data = { + "orders": orders, + "meta": meta + } + return make_success_response(data, 200) except mysql.connector.Error as err: - conn.rollback() - # 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)) + return make_error_response(f"Database error: {err}", 500) finally: - cursor.close() - conn.close() + if conn.is_connected(): + conn.close() +@app.route('/v1/orders/', 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/', 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 --- -@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/', 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']) def create_menu_item(): data = request.get_json() - if not data or not all(k in data for k in ['main_course', 'side_dish', 'addon', 'menu_date']): - return make_response("error", 400, "Missing required fields: main_course, side_dish, addon, menu_date.") - + if not data: + 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() if not conn: - return make_response("error", 503, "Database service unavailable.") - cursor = conn.cursor(dictionary=True) + return make_error_response("Database connection failed", 500) + + 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/', 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: - sql = "INSERT INTO menu_items (main_course, side_dish, addon, menu_date) VALUES (%s, %s, %s, %s)" - params = (data['main_course'], data['side_dish'], data['addon'], data['menu_date']) + cursor = conn.cursor(dictionary=True) cursor.execute(sql, params) - new_item_id = cursor.lastrowid - conn.commit() + items = cursor.fetchall() - cursor.execute("SELECT * FROM menu_items WHERE id = %s", (new_item_id,)) - new_item = cursor.fetchone() - return make_response("success", 201, "Menu item created successfully.", new_item) + meta = { + "total_items": len(items), + "query_params": query_params + } + data = { + "menu_items": items, + "meta": meta + } + return make_success_response(data, 200) except mysql.connector.Error as err: - conn.rollback() - return make_response("error", 500, str(err)) + return make_error_response(f"Database error: {err}", 500) finally: - cursor.close() - conn.close() + if conn.is_connected(): + conn.close() @app.route('/v1/menu_items/', methods=['PATCH']) def update_menu_item(item_id): data = request.get_json() 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() if not conn: - return make_response("error", 503, "Database service unavailable.") - 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" + return make_error_response("Database connection failed", 500) 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() - 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,)) 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: - conn.rollback() - return make_response("error", 500, str(err)) + return make_error_response(f"Database error: {err}", 500) finally: - cursor.close() - conn.close() + if conn.is_connected(): + conn.close() @app.route('/v1/menu_items/', methods=['DELETE']) def delete_menu_item(item_id): conn = get_db_connection() if not conn: - return make_response("error", 503, "Database service unavailable.") - cursor = conn.cursor() + return make_error_response("Database connection failed", 500) 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,)) conn.commit() - if cursor.rowcount == 0: - return make_response("error", 404, "Menu item not found.") - return make_response("success", 204, "Menu item deleted successfully.") + return make_success_response(None, 204, "Menu item deleted successfully.") except mysql.connector.Error as err: - conn.rollback() - 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)) + return make_error_response(f"Database error: {err}", 500) finally: - cursor.close() - conn.close() + if conn.is_connected(): + 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/', 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/', 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/', 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__': - # To run this server: - # 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) + app.run(host='0.0.0.0', port=5000, debug=True) \ No newline at end of file diff --git a/creat_api.txt b/creat_api.txt index 537113d..87e6e30 100644 --- a/creat_api.txt +++ b/creat_api.txt @@ -8,32 +8,27 @@ DB_NAME = db_A027 DB_USER = A027 DB_PASSWORD = E1CelfxqlKoj -TABLE = employee -- 路由: -- GET /v1/employee:支援 ?Id、?main_course、?side_dish、?addon、?is_active,要多回傳 {meta} -- GET /v1/employee/:找不到回 404 -- POST /v1/employee:接收 JSON {ID,main_course,side_dish,addon,is_active},欄位驗證,成功回 201 並回新資料 -- PATCH /v1/employee/:可更新任一欄位(ID/main_course/side_dish/addon/is_active),成功回 200 回更新後資料 -- DELETE /v1/employee/:成功回 204 + -TABLE = employee_votes +TABLE = orders - 路由: -- GET /v1/employee_votes:支援 ?Id、?emp_id、?name、?order_date、?menu_item_id、?order_qty,要多回傳 {meta} -- GET /v1/employee_votes/:找不到回 404 -- POST /v1/employee_votes:接收 JSON {Id,emp_id,name,order_date,menu_item_id,order_qty},欄位驗證,成功回 201 並回新資料 -- PATCH /v1/employee_votes/:可更新任一欄位(Id/emp_id/name/order_date/menu_item_id/order_qty),成功回 200 回更新後資料 -- DELETE /v1/employee_votes/:成功回 204 +- GET /v1/orders:支援 ?Id、?emp_id、?emp_name、?menu_item_id、?main_course、?order_date、?order_qty,要多回傳 {meta} +- GET /v1/orders/:找不到回 404 +- POST /v1/orders:接收 JSON {Id,emp_id,emp_name,menu_item_id,main_course,order_date,order_qty},欄位驗證,成功回 201 並回新資料 +- PATCH /v1/orders/:可更新任一欄位(id/emp_id/name/menu_item_id/main_course/order_date/order_qty),成功回 200 回更新後資料 +- DELETE /v1/orders/:成功回 204 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/:找不到回 404 -- POST /v1/menu_items:接收 JSON {ID,main_course,side_dish,addon,is_active},欄位驗證,成功回 201 並回新資料 -- PATCH /v1/menu_items/:可更新任一欄位(ID/main_course/side_dish/addon/is_active),成功回 200 回更新後資料 +- POST /v1/menu_items:接收 JSON {id,main_course,side_dish,addon,menu_date},欄位驗證,成功回 201 並回新資料 +- PATCH /v1/menu_items/:可更新任一欄位(id/main_course/side_dish/addon/menu_date),成功回 200 回更新後資料 - DELETE /v1/menu_items/:成功回 204 + - 所有寫入請用參數化查詢避免 SQL 注入 diff --git a/create_menu_table.py b/create_menu_table.py new file mode 100644 index 0000000..23dc1a5 --- /dev/null +++ b/create_menu_table.py @@ -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() diff --git a/create_order_table.py b/create_order_table.py new file mode 100644 index 0000000..d2ca0ee --- /dev/null +++ b/create_order_table.py @@ -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() diff --git a/create_order_table.txt b/create_order_table.txt new file mode 100644 index 0000000..c9aeeeb --- /dev/null +++ b/create_order_table.txt @@ -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. 若資料表已存在,先刪除再重建。 diff --git a/requirements.txt b/requirements.txt index 2b30791..523fd84 100644 Binary files a/requirements.txt and b/requirements.txt differ diff --git a/update_table.py b/update_table.py new file mode 100644 index 0000000..ef6117d --- /dev/null +++ b/update_table.py @@ -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() \ No newline at end of file diff --git a/update_table.txt b/update_table.txt new file mode 100644 index 0000000..d321d48 --- /dev/null +++ b/update_table.txt @@ -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. 執行成功後,印出「資料表修改成功!」。