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 from ..utils import calculate_price 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')) strategy_id = int(config.get('now_price', 'strategy_id')) 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, pricing_strategy_id ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s) """, (order_id, user[0], table_id, order_date, start_datetime, num_players, 'in_progress', strategy_id)) 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: with connection.cursor(dictionary=True) as cursor: # 获取订单信息 cursor.execute(""" SELECT o.user_id, o.start_datetime FROM orders o 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 not user or order['user_id'] != user['user_id']: raise HTTPException(status_code=403, detail="无权操作此订单") # 计算订单时长 end_datetime = datetime.now() duration_minutes = (end_datetime - order['start_datetime']).total_seconds() / 60 duration_minutes_dec = Decimal(str(duration_minutes)) # 先更新订单状态 cursor.execute(""" UPDATE orders SET end_datetime = %s, game_process_time = %s, order_status = 'pending' WHERE order_id = %s """, (end_datetime, duration_minutes_dec, order_id)) # 提交事务,确保订单结束 connection.commit() # 调用价格计算逻辑(会自动写入数据库) success = calculate_price.calculate_order_price(order_id) if not success: raise HTTPException(status_code=500, detail="订单价格计算失败") return {"message": "订单已结束待结算"} except Exception as e: connection.rollback() raise HTTPException(status_code=500, detail=str(e)) finally: 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()