from fastapi import HTTPException from datetime import datetime, timedelta from decimal import Decimal from ..db import get_connection from ..utils.jwt_handler import verify_token import configparser config = configparser.ConfigParser() config.read('backend/config.conf') unit_price = Decimal(config.get('price', 'unit_price')) points_rate = Decimal(config.get('price', 'points_rate')) get_points_rate = Decimal(config.get('price', 'get_points_rate')) def get_user_active_order(token: str): try: payload = verify_token(token) phone_number = payload["sub"] print(f"Verified phone_number: {phone_number}") except ValueError as e: raise HTTPException(401, str(e)) """获取用户进行中订单""" connection = get_connection() try: cursor = connection.cursor(dictionary=True) cursor.execute(""" SELECT o.order_id, o.start_datetime, gt.game_table_number, o.num_players FROM users u INNER JOIN orders o ON u.user_id = o.user_id INNER JOIN game_tables gt ON o.game_table_id = gt.table_id WHERE u.phone_number = %s AND o.order_status = 'in_progress' ORDER BY o.start_datetime DESC LIMIT 1; """, (phone_number,)) return cursor.fetchone() or {} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) finally: cursor.close() connection.close() def create_user_order(token: str, table_id: int, num_players: int): """创建用户订单""" try: payload = verify_token(token) phone_number = payload["sub"] except ValueError as e: raise HTTPException(status_code=401, detail=str(e)) connection = get_connection() try: cursor = connection.cursor() cursor = connection.cursor() # 新增用户订单状态检查 cursor.execute(""" SELECT order_status FROM orders WHERE user_id = (SELECT user_id FROM users WHERE phone_number = %s) AND order_status IN ('in_progress', 'pending') LIMIT 1 """, (phone_number,)) existing_order = cursor.fetchone() if existing_order: status = existing_order[0] if status == 'in_progress': raise HTTPException(status_code=400, detail="存在进行中的订单") raise HTTPException(status_code=400, detail="存在未付款的订单") # 获取当前最大订单号 cursor.execute("SELECT MAX(order_id) FROM orders") max_order_id = cursor.fetchone()[0] # 生成订单号(从100开始) order_id = 100 if max_order_id is None else int(max_order_id) + 1 print("order_id:", order_id) # 验证用户存在 cursor.execute("SELECT user_id FROM users WHERE phone_number = %s", (phone_number,)) user = cursor.fetchone() if not user: raise HTTPException(status_code=404, detail="用户不存在") # 检查桌子占用 cursor.execute(""" SELECT EXISTS( SELECT 1 FROM orders WHERE game_table_id = %s AND order_status = 'in_progress' )""", (table_id,)) if cursor.fetchone()[0]: raise HTTPException(status_code=400, detail="桌子已被占用") # 创建订单 order_date = datetime.now().date() start_datetime = datetime.now() cursor.execute(""" INSERT INTO orders ( order_id, user_id, game_table_id, order_date, start_datetime, num_players, order_status ) VALUES (%s, %s, %s, %s, %s, %s, %s) """, (order_id, user[0], table_id, order_date, start_datetime, num_players, 'in_progress')) connection.commit() return {"order_id": order_id, "message": "订单创建成功"} except Exception as e: connection.rollback() raise HTTPException(status_code=500, detail=str(e)) finally: cursor.close() connection.close() def complete_user_order(token: str, order_id: int): """完成用户订单""" try: payload = verify_token(token) phone_number = payload["sub"] except ValueError as e: raise HTTPException(status_code=401, detail=str(e)) connection = get_connection() try: cursor = connection.cursor(dictionary=True) # 修改后的SQL查询 cursor.execute(""" SELECT o.user_id, t.price AS table_price, COALESCE(g.price, 1.0) AS game_price, o.num_players, o.start_datetime FROM orders o JOIN game_tables t ON o.game_table_id = t.table_id LEFT JOIN games g ON o.game_id = g.game_id WHERE o.order_id = %s FOR UPDATE """, (order_id,)) order = cursor.fetchone() if not order: raise HTTPException(status_code=404, detail="订单不存在") # 验证用户权限 cursor.execute("SELECT user_id FROM users WHERE phone_number = %s", (phone_number,)) user = cursor.fetchone() if order['user_id'] != user['user_id']: raise HTTPException(status_code=403, detail="无权操作此订单") # 计算时长(优化精度处理) end_datetime = datetime.now() duration = end_datetime - order['start_datetime'] duration_minutes = duration.total_seconds() / 60 duration_minutes_dec = Decimal(duration_minutes).quantize(Decimal('0.0000')) # 直接使用Decimal类型计算 unit_price = Decimal('0.1667') # 示例单位价格(需按实际调整) base_price = ( order['table_price'] * order['game_price'] * order['num_players'] * duration_minutes_dec * unit_price ) total_price = round(base_price, 2) # 使用Decimal类型更新数据库 cursor.execute(""" UPDATE orders SET end_datetime = %s, payable_price = %s, game_process_time = %s, order_status = 'pending' WHERE order_id = %s """, (end_datetime, total_price, duration_minutes_dec, order_id)) connection.commit() return {"message": "订单已结束待结算", "base_price": float(base_price)} except Exception as e: connection.rollback() raise HTTPException(status_code=500, detail=str(e)) finally: cursor.close() connection.close() def get_earliest_pending_order(token: str): """获取用户最早的pending订单""" try: payload = verify_token(token) phone_number = payload["sub"] except ValueError as e: raise HTTPException(401, detail=str(e)) connection = get_connection() try: with connection.cursor(dictionary=True) as cursor: # 查询最早pending订单 cursor.execute(""" SELECT o.order_id FROM users u JOIN orders o ON u.user_id = o.user_id WHERE u.phone_number = %s AND o.order_status = 'pending' ORDER BY o.start_datetime ASC LIMIT 1 """, (phone_number,)) result = cursor.fetchone() return {"order_id": result["order_id"]} if result else {} except Exception as e: raise HTTPException(500, detail=str(e)) finally: connection.close() def get_order_detail_with_points(token: str, order_id: int): """获取订单详情及用户积分""" try: payload = verify_token(token) phone_number = payload["sub"] except ValueError as e: raise HTTPException(401, detail=str(e)) connection = get_connection() try: with connection.cursor(dictionary=True) as cursor: # 验证订单归属 cursor.execute(""" SELECT o.order_id, gt.game_table_number, o.order_date, o.start_datetime AS start_time, o.end_datetime AS end_time, o.game_process_time, o.num_players, o.payable_price, u.points FROM orders o JOIN game_tables gt ON o.game_table_id = gt.table_id JOIN users u ON o.user_id = u.user_id WHERE o.order_id = %s AND u.phone_number = %s """, (order_id, phone_number)) result = cursor.fetchone() if not result: raise HTTPException(404, detail="订单不存在或无权访问") # 格式化日期字段 result['order_date'] = result['order_date'].isoformat() result['start_time'] = result['start_time'].isoformat() result['end_time'] = result['end_time'].isoformat() if result['end_time'] else None return { "order_id": result["order_id"], "game_table_number": result["game_table_number"], "order_date": result["order_date"], "start_time": result["start_time"], "end_time": result["end_time"], "num_players": result["num_players"], "payable_price": float(result["payable_price"]), "game_process_time": result["game_process_time"], "points": result["points"] } except Exception as e: raise HTTPException(500, detail=str(e)) finally: connection.close() def preview_price_adjustment(token: str, order_id: int, used_points: int): """预览价格调整(不修改数据库)""" try: payload = verify_token(token) phone_number = payload["sub"] except ValueError as e: raise HTTPException(401, detail=str(e)) connection = get_connection() try: with connection.cursor(dictionary=True) as cursor: # 获取用户当前积分 cursor.execute(""" SELECT u.user_id, u.points FROM users u WHERE u.phone_number = %s """, (phone_number,)) user = cursor.fetchone() if not user: raise HTTPException(404, "用户不存在") if user['points'] < used_points: raise HTTPException(400, "积分不足") # 获取原始价格 cursor.execute(""" SELECT payable_price FROM orders WHERE order_id = %s AND user_id = %s AND order_status = 'pending' """, (order_id, user['user_id'])) order = cursor.fetchone() if not order: raise HTTPException(404, "订单不存在或不可修改") # 计算新价格(仅预览) points_value = used_points * points_rate new_price = max(order['payable_price'] - points_value, Decimal('0')) return { "new_price": float(new_price), } except HTTPException as e: raise except Exception as e: raise HTTPException(500, f"计算失败: {str(e)}") finally: connection.close()