Update main.py
Browse files
main.py
CHANGED
|
@@ -53,7 +53,10 @@ class OrderPayload(BaseModel):
|
|
| 53 |
cart: Dict[str, int] = {}
|
| 54 |
deposit_required: int = 0
|
| 55 |
total_amount: int = 0
|
| 56 |
-
kitchen_remarks: Optional[str] = ""
|
|
|
|
|
|
|
|
|
|
| 57 |
|
| 58 |
class ConfirmPayload(BaseModel):
|
| 59 |
transaction_id: str
|
|
@@ -187,11 +190,14 @@ async def submit_booking(payload: OrderPayload, background_tasks: BackgroundTask
|
|
| 187 |
|
| 188 |
if res_data.get("returnCode") == "0000":
|
| 189 |
payment_url = res_data["info"]["paymentUrl"]["web"]
|
|
|
|
|
|
|
| 190 |
booking_data = {
|
| 191 |
"name": payload.name, "tel": payload.tel, "date": payload.date,
|
| 192 |
"time": payload.time, "pax": payload.pax, "user_id": payload.line_id,
|
|
|
|
| 193 |
"status": "待付款",
|
| 194 |
-
"remarks": f"類型: {'外帶' if payload.service_type == 'takeout' else '內用'}\n訂單號: {order_id}\n\n{payload.kitchen_remarks}"
|
| 195 |
}
|
| 196 |
supabase.table("bookings").insert(booking_data).execute()
|
| 197 |
|
|
@@ -206,10 +212,14 @@ async def submit_booking(payload: OrderPayload, background_tasks: BackgroundTask
|
|
| 206 |
else: raise HTTPException(status_code=500, detail=f"LINE Pay 錯誤: {res_data.get('returnMessage')}")
|
| 207 |
except Exception as e: raise HTTPException(status_code=500, detail=f"金流連線失敗: {str(e)}")
|
| 208 |
|
|
|
|
| 209 |
booking_data = {
|
| 210 |
"name": payload.name, "tel": payload.tel, "date": payload.date, "time": payload.time,
|
| 211 |
-
"pax": payload.pax,
|
| 212 |
-
"
|
|
|
|
|
|
|
|
|
|
| 213 |
}
|
| 214 |
|
| 215 |
try:
|
|
@@ -262,8 +272,7 @@ async def repay_payment(payload: RepayPayload):
|
|
| 262 |
if "已付" in booking.get("status", "") or "確認" in booking.get("status", ""):
|
| 263 |
raise HTTPException(status_code=400, detail="此訂單已完成付款或確認,無需重新結帳")
|
| 264 |
|
| 265 |
-
|
| 266 |
-
amount = 1000 # 預設防護底線
|
| 267 |
try:
|
| 268 |
chk_uri = "/v3/payments"
|
| 269 |
chk_query = urllib.parse.urlencode({"orderId": payload.order_id})
|
|
@@ -273,7 +282,6 @@ async def repay_payment(payload: RepayPayload):
|
|
| 273 |
chk_headers = { "Content-Type": "application/json", "X-LINE-ChannelId": LINE_PAY_CHANNEL_ID, "X-LINE-Authorization-Nonce": chk_nonce, "X-LINE-Authorization": chk_sig }
|
| 274 |
chk_res = requests.get(f"{LINE_PAY_BASE_URL}{chk_uri}?{chk_query}", headers=chk_headers).json()
|
| 275 |
if chk_res.get("returnCode") == "0000" and chk_res.get("info"):
|
| 276 |
-
# 成功抓出這筆訂單原本設定的金額!
|
| 277 |
amount = chk_res["info"][0].get("payInfo", [{}])[0].get("amount", 1000)
|
| 278 |
except Exception as e:
|
| 279 |
print(f"無法取得原始金額,使用預設值: {e}")
|
|
@@ -326,23 +334,17 @@ def notify_boss(name, tel, date, time, pax, amount):
|
|
| 326 |
try: requests.post("https://api.line.me/v2/bot/message/push", headers=headers, json=payload)
|
| 327 |
except: pass
|
| 328 |
|
| 329 |
-
# ==========================================
|
| 330 |
-
# 🌟 計算某日庫存與銷量的 API (防護升級版) 🌟
|
| 331 |
-
# ==========================================
|
| 332 |
@app.get("/api/inventory/{query_date}")
|
| 333 |
async def get_inventory(query_date: str):
|
| 334 |
if not supabase: return {}
|
| 335 |
try:
|
| 336 |
-
# 找出這天所有的訂單
|
| 337 |
res = supabase.table("bookings").select("cart, status").eq("date", query_date).execute()
|
| 338 |
sold_counts = {}
|
| 339 |
if res.data:
|
| 340 |
for b in res.data:
|
| 341 |
-
# 排除已經取消或 No-Show 的訂單,把扣打還給庫存
|
| 342 |
if "取消" in b.get("status", "") or "No-Show" in b.get("status", ""):
|
| 343 |
continue
|
| 344 |
|
| 345 |
-
# 🌟 修改:加入型別檢查防護,避免 null 或 字串 引發當機
|
| 346 |
cart = b.get("cart")
|
| 347 |
if not cart:
|
| 348 |
cart = {}
|
|
@@ -350,7 +352,6 @@ async def get_inventory(query_date: str):
|
|
| 350 |
try: cart = json.loads(cart)
|
| 351 |
except: cart = {}
|
| 352 |
|
| 353 |
-
# 計算這筆訂單買了什麼
|
| 354 |
for item_id, qty in cart.items():
|
| 355 |
try: qty = int(qty)
|
| 356 |
except: qty = 0
|
|
|
|
| 53 |
cart: Dict[str, int] = {}
|
| 54 |
deposit_required: int = 0
|
| 55 |
total_amount: int = 0
|
| 56 |
+
kitchen_remarks: Optional[str] = ""
|
| 57 |
+
# 🚀 【關鍵修正 1】讓後端海關允許接收前端傳過來的 email 與 remarks
|
| 58 |
+
email: Optional[str] = ""
|
| 59 |
+
remarks: Optional[str] = ""
|
| 60 |
|
| 61 |
class ConfirmPayload(BaseModel):
|
| 62 |
transaction_id: str
|
|
|
|
| 190 |
|
| 191 |
if res_data.get("returnCode") == "0000":
|
| 192 |
payment_url = res_data["info"]["paymentUrl"]["web"]
|
| 193 |
+
|
| 194 |
+
# 🚀 【關鍵修正 2】有付訂金時,確實寫入 email 並將客人備註融入大 remarks 中
|
| 195 |
booking_data = {
|
| 196 |
"name": payload.name, "tel": payload.tel, "date": payload.date,
|
| 197 |
"time": payload.time, "pax": payload.pax, "user_id": payload.line_id,
|
| 198 |
+
"email": payload.email,
|
| 199 |
"status": "待付款",
|
| 200 |
+
"remarks": f"類型: {'外帶' if payload.service_type == 'takeout' else '內用'}\n訂單號: {order_id}\n客人備註: {payload.remarks if payload.remarks else '無'}\n\n{payload.kitchen_remarks}"
|
| 201 |
}
|
| 202 |
supabase.table("bookings").insert(booking_data).execute()
|
| 203 |
|
|
|
|
| 212 |
else: raise HTTPException(status_code=500, detail=f"LINE Pay 錯誤: {res_data.get('returnMessage')}")
|
| 213 |
except Exception as e: raise HTTPException(status_code=500, detail=f"金流連線失敗: {str(e)}")
|
| 214 |
|
| 215 |
+
# 🚀 【關鍵修正 3】免付訂金時,將寫死的 "" 改為寫入 payload.email,並融入客人備註
|
| 216 |
booking_data = {
|
| 217 |
"name": payload.name, "tel": payload.tel, "date": payload.date, "time": payload.time,
|
| 218 |
+
"pax": payload.pax,
|
| 219 |
+
"email": payload.email,
|
| 220 |
+
"user_id": payload.line_id,
|
| 221 |
+
"status": "待處理",
|
| 222 |
+
"remarks": f"類型: {'外帶' if payload.service_type == 'takeout' else '內用'}\n客人備註: {payload.remarks if payload.remarks else '無'}\n\n{payload.kitchen_remarks}"
|
| 223 |
}
|
| 224 |
|
| 225 |
try:
|
|
|
|
| 272 |
if "已付" in booking.get("status", "") or "確認" in booking.get("status", ""):
|
| 273 |
raise HTTPException(status_code=400, detail="此訂單已完成付款或確認,無需重新結帳")
|
| 274 |
|
| 275 |
+
amount = 1000
|
|
|
|
| 276 |
try:
|
| 277 |
chk_uri = "/v3/payments"
|
| 278 |
chk_query = urllib.parse.urlencode({"orderId": payload.order_id})
|
|
|
|
| 282 |
chk_headers = { "Content-Type": "application/json", "X-LINE-ChannelId": LINE_PAY_CHANNEL_ID, "X-LINE-Authorization-Nonce": chk_nonce, "X-LINE-Authorization": chk_sig }
|
| 283 |
chk_res = requests.get(f"{LINE_PAY_BASE_URL}{chk_uri}?{chk_query}", headers=chk_headers).json()
|
| 284 |
if chk_res.get("returnCode") == "0000" and chk_res.get("info"):
|
|
|
|
| 285 |
amount = chk_res["info"][0].get("payInfo", [{}])[0].get("amount", 1000)
|
| 286 |
except Exception as e:
|
| 287 |
print(f"無法取得原始金額,使用預設值: {e}")
|
|
|
|
| 334 |
try: requests.post("https://api.line.me/v2/bot/message/push", headers=headers, json=payload)
|
| 335 |
except: pass
|
| 336 |
|
|
|
|
|
|
|
|
|
|
| 337 |
@app.get("/api/inventory/{query_date}")
|
| 338 |
async def get_inventory(query_date: str):
|
| 339 |
if not supabase: return {}
|
| 340 |
try:
|
|
|
|
| 341 |
res = supabase.table("bookings").select("cart, status").eq("date", query_date).execute()
|
| 342 |
sold_counts = {}
|
| 343 |
if res.data:
|
| 344 |
for b in res.data:
|
|
|
|
| 345 |
if "取消" in b.get("status", "") or "No-Show" in b.get("status", ""):
|
| 346 |
continue
|
| 347 |
|
|
|
|
| 348 |
cart = b.get("cart")
|
| 349 |
if not cart:
|
| 350 |
cart = {}
|
|
|
|
| 352 |
try: cart = json.loads(cart)
|
| 353 |
except: cart = {}
|
| 354 |
|
|
|
|
| 355 |
for item_id, qty in cart.items():
|
| 356 |
try: qty = int(qty)
|
| 357 |
except: qty = 0
|