from fastapi import APIRouter, Request, Depends, Form
from fastapi.responses import HTMLResponse
from sqlalchemy.orm import Session
from sqlalchemy import text
from database import SessionLocal, redis_client
from services.template_service import build_template
from services.price_service import apply_adjust
import json
import uuid
router = APIRouter(prefix="/estimate", tags=["estimate"])
# ================= DB =================
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
# ================= 页面 =================
@router.get("/simulate", response_class=HTMLResponse)
def simulate(machine_id: int, db: Session = Depends(get_db)):
row = db.execute(text("""
SELECT estimate_packet
FROM machine_temp
WHERE machine_id=:mid
"""), {"mid": machine_id}).fetchone()
tpl = json.loads(row.estimate_packet)
html = "
估价模拟
"
html += '
"""
return html
# ================= 提交估价 =================
@router.post("/simulate", response_class=HTMLResponse)
def simulate_calc(
machine_id: int = Form(...),
option_ids: list[str] = Form([]),
db: Session = Depends(get_db)
):
base_price = 1000.0
factors = db.execute(text("""
SELECT option_id,factor,absolute_deduct
FROM price_option_factor
WHERE option_id IN :ids
"""), {"ids": tuple(option_ids)}).fetchall()
price = base_price
for f in factors:
if f.factor:
price *= float(f.factor)
if f.absolute_deduct:
price -= float(f.absolute_deduct)
# 机型调节
adjust = db.execute(text("""
SELECT factor FROM price_adjust_factor
WHERE level='machine'
AND ref_id=:mid
"""), {"mid": machine_id}).fetchone()
if adjust:
price *= float(adjust.factor)
html = f"""
估价结果
选择项:{",".join(option_ids)}
估价:{round(price,2)} 元
返回
"""
return html
@router.post("/estimate2", response_class=HTMLResponse)
def estimate_submit(
request: Request,
machine_id: int = Form(...),
capacity: str = Form(...),
option_ids: list[int] = Form([]),
db: Session = Depends(get_db)
):
# ---------- 基础价格 ----------
base_price = db.execute(
text("""
SELECT base_price
FROM machine_base_price
WHERE machine_id=:mid AND capacity=:cap
"""),
{"mid": machine_id, "cap": capacity}
).scalar() or 0
price = float(base_price)
# ---------- 扣减项 ----------
for oid in option_ids:
r = db.execute(
text("""
SELECT factor, absolute_deduct
FROM price_option_factor
WHERE option_id=:oid
"""),
{"oid": oid}
).fetchone()
if r:
price = price * float(r.factor) - float(r.absolute_deduct)
# ---------- 调节系数 ----------
brand_id = db.execute(
text("""
SELECT brand_id
FROM t_machine
WHERE machine_id=:mid
"""),
{"mid": machine_id}
).scalar()
price = apply_adjust(db, machine_id, brand_id, price)
price = round(max(price, 0), 2)
# ---------- 估价版本 ----------
version_no = str(uuid.uuid4())[:8]
db.execute(
text("""
INSERT INTO estimate_record
(machine_id, capacity, option_ids, final_price, version_no)
VALUES (:m, :c, :o, :p, :v)
"""),
{
"m": machine_id,
"c": capacity,
"o": ",".join(map(str, option_ids)),
"p": price,
"v": version_no
}
)
db.commit()
# ---------- 模板(Redis 缓存) ----------
cache_key = f"template:{machine_id}"
cached = redis_client.get(cache_key) if redis_client else None
if cached:
template = json.loads(cached)
else:
rows = db.execute(text("SELECT * FROM release_option")).fetchall()
template = build_template(rows)
if redis_client:
redis_client.set(cache_key, json.dumps(template), ex=3600)
# ---------- 重新加载页面 ----------
machines = db.execute(
text("""
SELECT machine_id, name
FROM t_machine
ORDER BY brand_name, name
""")
).fetchall()
capacities = db.execute(
text("""
SELECT capacity
FROM machine_base_price
WHERE machine_id=:mid
"""),
{"mid": machine_id}
).fetchall()
return request.app.state.templates.TemplateResponse(
"estimate.html",
{
"request": request,
"machines": machines,
"capacities": capacities,
"template": template,
"price": price,
"version": version_no,
"selected_machine": machine_id,
"selected_capacity": capacity
}
)