|
@@ -5,11 +5,12 @@ from sqlalchemy import text
|
|
|
from database import SessionLocal, redis_client
|
|
from database import SessionLocal, redis_client
|
|
|
from services.template_service import build_template
|
|
from services.template_service import build_template
|
|
|
from services.price_service import apply_adjust
|
|
from services.price_service import apply_adjust
|
|
|
|
|
+from fastapi.templating import Jinja2Templates
|
|
|
import json
|
|
import json
|
|
|
import uuid
|
|
import uuid
|
|
|
|
|
|
|
|
router = APIRouter(prefix="/estimate", tags=["estimate"])
|
|
router = APIRouter(prefix="/estimate", tags=["estimate"])
|
|
|
-
|
|
|
|
|
|
|
+templates = Jinja2Templates(directory="templates")
|
|
|
|
|
|
|
|
# ================= DB =================
|
|
# ================= DB =================
|
|
|
def get_db():
|
|
def get_db():
|
|
@@ -45,7 +46,7 @@ def simulate(db: Session = Depends(get_db)):
|
|
|
|
|
|
|
|
|
|
|
|
|
# ================= 获取机型模板和选项 =================
|
|
# ================= 获取机型模板和选项 =================
|
|
|
-@router.get("/simulate_one", response_class=HTMLResponse)
|
|
|
|
|
|
|
+@router.get("/simulate_one_del", response_class=HTMLResponse)
|
|
|
def simulate(
|
|
def simulate(
|
|
|
machine_id: int,
|
|
machine_id: int,
|
|
|
db: Session = Depends(get_db)
|
|
db: Session = Depends(get_db)
|
|
@@ -85,11 +86,42 @@ def simulate(
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
return html
|
|
return html
|
|
|
|
|
+@router.get("/simulate_one", response_class=HTMLResponse)
|
|
|
|
|
+def simulate_one_del2(
|
|
|
|
|
+ request: Request,
|
|
|
|
|
+ machine_id: int,
|
|
|
|
|
+ db: Session = Depends(get_db)
|
|
|
|
|
+):
|
|
|
|
|
+
|
|
|
|
|
+ row = db.execute(text("""
|
|
|
|
|
+ SELECT m.name AS machine_name,
|
|
|
|
|
+ t.estimate_packet
|
|
|
|
|
+ FROM machine_temp t
|
|
|
|
|
+ JOIN t_machine m ON t.machine_id = m.machine_id
|
|
|
|
|
+ WHERE t.machine_id = :mid
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ if not row:
|
|
|
|
|
+ return HTMLResponse("未找到机型模板", status_code=404)
|
|
|
|
|
+
|
|
|
|
|
+ # print("*************row****************")
|
|
|
|
|
+ # print(row)
|
|
|
|
|
+ tpl = json.loads(row.estimate_packet)
|
|
|
|
|
+
|
|
|
|
|
+ return templates.TemplateResponse(
|
|
|
|
|
+ "simulate_one.html",
|
|
|
|
|
+ {
|
|
|
|
|
+ "request": request,
|
|
|
|
|
+ "machine_id": machine_id,
|
|
|
|
|
+ "machine_name": row.machine_name,
|
|
|
|
|
+ "tpl": tpl
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ================= 提交估价并计算价格 =================
|
|
# ================= 提交估价并计算价格 =================
|
|
|
-@router.post("/simulate", response_class=HTMLResponse)
|
|
|
|
|
|
|
+@router.post("/simulate_del", response_class=HTMLResponse)
|
|
|
def simulate_calc(
|
|
def simulate_calc(
|
|
|
machine_id: int = Form(...),
|
|
machine_id: int = Form(...),
|
|
|
option_ids: list[str] = Form([]),
|
|
option_ids: list[str] = Form([]),
|
|
@@ -116,7 +148,7 @@ def simulate_calc(
|
|
|
|
|
|
|
|
for f in factors:
|
|
for f in factors:
|
|
|
if f.factor:
|
|
if f.factor:
|
|
|
- price *= float(f.factor)
|
|
|
|
|
|
|
+ price *= (1-float(f.factor))
|
|
|
if f.absolute_deduct:
|
|
if f.absolute_deduct:
|
|
|
price -= float(f.absolute_deduct)
|
|
price -= float(f.absolute_deduct)
|
|
|
|
|
|
|
@@ -161,6 +193,544 @@ def simulate_calc(
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
return html
|
|
return html
|
|
|
|
|
+@router.post("/simulate_de3", response_class=HTMLResponse)
|
|
|
|
|
+def simulate_calc(
|
|
|
|
|
+ request: Request,
|
|
|
|
|
+ machine_id: int = Form(...),
|
|
|
|
|
+ option_ids: list[str] = Form([]),
|
|
|
|
|
+ db: Session = Depends(get_db)
|
|
|
|
|
+):
|
|
|
|
|
+
|
|
|
|
|
+ # 机型名称
|
|
|
|
|
+ machine = db.execute(text("""
|
|
|
|
|
+ SELECT name, brand_name
|
|
|
|
|
+ FROM t_machine
|
|
|
|
|
+ WHERE machine_id=:mid
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ # 模板
|
|
|
|
|
+ row = db.execute(text("""
|
|
|
|
|
+ SELECT estimate_packet
|
|
|
|
|
+ FROM machine_temp
|
|
|
|
|
+ WHERE machine_id=:mid
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ tpl = json.loads(row.estimate_packet)
|
|
|
|
|
+
|
|
|
|
|
+ # ========== 基准价 ==========
|
|
|
|
|
+ base_price_row = db.execute(text("""
|
|
|
|
|
+ SELECT base_price
|
|
|
|
|
+ FROM machine_base_price
|
|
|
|
|
+ WHERE machine_id=:mid
|
|
|
|
|
+ LIMIT 1
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ base_price = float(base_price_row.base_price) if base_price_row else 1000.0
|
|
|
|
|
+
|
|
|
|
|
+ price = base_price
|
|
|
|
|
+
|
|
|
|
|
+ detail_rows = []
|
|
|
|
|
+
|
|
|
|
|
+ # ========== 选项扣减 ==========
|
|
|
|
|
+ if option_ids:
|
|
|
|
|
+ factors = db.execute(text("""
|
|
|
|
|
+ SELECT
|
|
|
|
|
+ pf.option_id,
|
|
|
|
|
+ pf.factor,
|
|
|
|
|
+ pf.absolute_deduct,
|
|
|
|
|
+ ro.option_name
|
|
|
|
|
+ FROM price_option_factor pf
|
|
|
|
|
+ LEFT JOIN release_option ro
|
|
|
|
|
+ ON pf.option_id = ro.option_id
|
|
|
|
|
+ WHERE pf.option_id IN :ids
|
|
|
|
|
+ """), {"ids": tuple(option_ids)}).fetchall()
|
|
|
|
|
+ else:
|
|
|
|
|
+ factors = []
|
|
|
|
|
+
|
|
|
|
|
+ for f in factors:
|
|
|
|
|
+ before = price
|
|
|
|
|
+
|
|
|
|
|
+ if f.factor is not None:
|
|
|
|
|
+ price *= float(f.factor)
|
|
|
|
|
+
|
|
|
|
|
+ if f.absolute_deduct is not None:
|
|
|
|
|
+ price -= float(f.absolute_deduct)
|
|
|
|
|
+
|
|
|
|
|
+ detail_rows.append({
|
|
|
|
|
+ "type": "option",
|
|
|
|
|
+ "name": f.option_name or str(f.option_id),
|
|
|
|
|
+ "option_id": f.option_id,
|
|
|
|
|
+ "factor": f.factor,
|
|
|
|
|
+ "absolute_deduct": f.absolute_deduct,
|
|
|
|
|
+ "before": round(before, 2),
|
|
|
|
|
+ "after": round(price, 2)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ # ========== 全局调节 ==========
|
|
|
|
|
+ global_adjust = db.execute(text("""
|
|
|
|
|
+ SELECT factor
|
|
|
|
|
+ FROM price_adjust_factor
|
|
|
|
|
+ WHERE level='global'
|
|
|
|
|
+ LIMIT 1
|
|
|
|
|
+ """)).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ if global_adjust:
|
|
|
|
|
+ before = price
|
|
|
|
|
+ price *= float(global_adjust.factor)
|
|
|
|
|
+
|
|
|
|
|
+ detail_rows.append({
|
|
|
|
|
+ "type": "adjust",
|
|
|
|
|
+ "name": "全局调节",
|
|
|
|
|
+ "factor": global_adjust.factor,
|
|
|
|
|
+ "before": round(before, 2),
|
|
|
|
|
+ "after": round(price, 2)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ # ========== 品牌调节 ==========
|
|
|
|
|
+ brand_adjust = db.execute(text("""
|
|
|
|
|
+ SELECT factor
|
|
|
|
|
+ FROM price_adjust_factor
|
|
|
|
|
+ WHERE level='brand'
|
|
|
|
|
+ AND ref_id=(
|
|
|
|
|
+ SELECT brand_id FROM t_machine WHERE machine_id=:mid
|
|
|
|
|
+ )
|
|
|
|
|
+ LIMIT 1
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ if brand_adjust:
|
|
|
|
|
+ before = price
|
|
|
|
|
+ price *= float(brand_adjust.factor)
|
|
|
|
|
+
|
|
|
|
|
+ detail_rows.append({
|
|
|
|
|
+ "type": "adjust",
|
|
|
|
|
+ "name": "品牌调节",
|
|
|
|
|
+ "factor": brand_adjust.factor,
|
|
|
|
|
+ "before": round(before, 2),
|
|
|
|
|
+ "after": round(price, 2)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ # ========== 机型调节 ==========
|
|
|
|
|
+ machine_adjust = db.execute(text("""
|
|
|
|
|
+ SELECT factor
|
|
|
|
|
+ FROM price_adjust_factor
|
|
|
|
|
+ WHERE level='machine'
|
|
|
|
|
+ AND ref_id=:mid
|
|
|
|
|
+ LIMIT 1
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ if machine_adjust:
|
|
|
|
|
+ before = price
|
|
|
|
|
+ price *= float(machine_adjust.factor)
|
|
|
|
|
+
|
|
|
|
|
+ detail_rows.append({
|
|
|
|
|
+ "type": "adjust",
|
|
|
|
|
+ "name": "机型调节",
|
|
|
|
|
+ "factor": machine_adjust.factor,
|
|
|
|
|
+ "before": round(before, 2),
|
|
|
|
|
+ "after": round(price, 2)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ final_price = round(price, 2)
|
|
|
|
|
+
|
|
|
|
|
+ return templates.TemplateResponse(
|
|
|
|
|
+ "simulate_one.html",
|
|
|
|
|
+ {
|
|
|
|
|
+ "request": request,
|
|
|
|
|
+ "tpl": tpl,
|
|
|
|
|
+ "machine": machine,
|
|
|
|
|
+ "machine_id": machine_id,
|
|
|
|
|
+ "selected_option_ids": option_ids,
|
|
|
|
|
+ "base_price": round(base_price, 2),
|
|
|
|
|
+ "detail_rows": detail_rows,
|
|
|
|
|
+ "final_price": final_price
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+@router.get("/simulate_one", response_class=HTMLResponse)
|
|
|
|
|
+def simulate_one(
|
|
|
|
|
+ request: Request,
|
|
|
|
|
+ machine_id: int,
|
|
|
|
|
+ db: Session = Depends(get_db)
|
|
|
|
|
+):
|
|
|
|
|
+ row = db.execute(text("""
|
|
|
|
|
+ SELECT m.name,
|
|
|
|
|
+ t.estimate_packet
|
|
|
|
|
+ FROM machine_temp t
|
|
|
|
|
+ JOIN t_machine m ON t.machine_id = m.machine_id
|
|
|
|
|
+ WHERE t.machine_id = :mid
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ tpl = json.loads(row.estimate_packet)
|
|
|
|
|
+
|
|
|
|
|
+ return templates.TemplateResponse(
|
|
|
|
|
+ "simulate_one.html",
|
|
|
|
|
+ {
|
|
|
|
|
+ "request": request,
|
|
|
|
|
+ "machine_id": machine_id,
|
|
|
|
|
+ "machine_name": row.name,
|
|
|
|
|
+ "tpl": tpl,
|
|
|
|
|
+ "result": None
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+# ================= 估价 =================
|
|
|
|
|
+@router.post("/simulate666", response_class=HTMLResponse)
|
|
|
|
|
+async def simulate_calc(
|
|
|
|
|
+ request: Request,
|
|
|
|
|
+ machine_id: int = Form(...),
|
|
|
|
|
+ db: Session = Depends(get_db)
|
|
|
|
|
+):
|
|
|
|
|
+ form = await request.form()
|
|
|
|
|
+
|
|
|
|
|
+ # ---------------- 收集 option ----------------
|
|
|
|
|
+ option_ids = []
|
|
|
|
|
+ for k, v in form.multi_items():
|
|
|
|
|
+ if k.startswith("option_"):
|
|
|
|
|
+ option_ids.append(str(v))
|
|
|
|
|
+
|
|
|
|
|
+ # ---------------- 重新取模板与机型名 ----------------
|
|
|
|
|
+ row = db.execute(text("""
|
|
|
|
|
+ SELECT m.name,
|
|
|
|
|
+ t.estimate_packet
|
|
|
|
|
+ FROM machine_temp t
|
|
|
|
|
+ JOIN t_machine m ON t.machine_id = m.machine_id
|
|
|
|
|
+ WHERE t.machine_id = :mid
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ if not row:
|
|
|
|
|
+ return HTMLResponse("机型模板不存在")
|
|
|
|
|
+
|
|
|
|
|
+ tpl = json.loads(row.estimate_packet)
|
|
|
|
|
+
|
|
|
|
|
+ # ---------------- 构造 valueId -> valueText 映射 ----------------
|
|
|
|
|
+ value_name_map = {}
|
|
|
|
|
+
|
|
|
|
|
+ for step in tpl["template"]:
|
|
|
|
|
+ for p in step["properties"]:
|
|
|
|
|
+ for v in p["values"]:
|
|
|
|
|
+ value_name_map[str(v["valueId"])] = v["valueText"]
|
|
|
|
|
+
|
|
|
|
|
+ # ---------------- 基准价 ----------------
|
|
|
|
|
+ base_row = db.execute(text("""
|
|
|
|
|
+ SELECT base_price
|
|
|
|
|
+ FROM machine_base_price
|
|
|
|
|
+ WHERE machine_id=:mid
|
|
|
|
|
+ LIMIT 1
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ base_price = float(base_row.base_price) if base_row else 1000.0
|
|
|
|
|
+
|
|
|
|
|
+ # ---------------- 选项因子 ----------------
|
|
|
|
|
+ detail_rows = []
|
|
|
|
|
+
|
|
|
|
|
+ if option_ids:
|
|
|
|
|
+ rows = db.execute(text("""
|
|
|
|
|
+ SELECT option_id, factor, absolute_deduct
|
|
|
|
|
+ FROM price_option_factor
|
|
|
|
|
+ WHERE option_id IN :ids
|
|
|
|
|
+ """), {"ids": tuple(option_ids)}).fetchall()
|
|
|
|
|
+ else:
|
|
|
|
|
+ rows = []
|
|
|
|
|
+
|
|
|
|
|
+ price = base_price
|
|
|
|
|
+
|
|
|
|
|
+ for r in rows:
|
|
|
|
|
+ before = price
|
|
|
|
|
+
|
|
|
|
|
+ if r.factor is not None:
|
|
|
|
|
+ price = price * float(r.factor)
|
|
|
|
|
+
|
|
|
|
|
+ if r.absolute_deduct is not None:
|
|
|
|
|
+ price = price - float(r.absolute_deduct)
|
|
|
|
|
+
|
|
|
|
|
+ detail_rows.append({
|
|
|
|
|
+ "option_id": r.option_id,
|
|
|
|
|
+ "option_name": value_name_map.get(str(r.option_id), str(r.option_id)),
|
|
|
|
|
+ "factor": r.factor,
|
|
|
|
|
+ "absolute": r.absolute_deduct,
|
|
|
|
|
+ "before": round(before, 2),
|
|
|
|
|
+ "after": round(price, 2)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ # ---------------- 调节因子 ----------------
|
|
|
|
|
+
|
|
|
|
|
+ # 全局
|
|
|
|
|
+ g = db.execute(text("""
|
|
|
|
|
+ SELECT factor FROM price_adjust_factor
|
|
|
|
|
+ WHERE level='global'
|
|
|
|
|
+ LIMIT 1
|
|
|
|
|
+ """)).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ if g:
|
|
|
|
|
+ before = price
|
|
|
|
|
+ price = price * float(g.factor)
|
|
|
|
|
+
|
|
|
|
|
+ detail_rows.append({
|
|
|
|
|
+ "option_id": "GLOBAL",
|
|
|
|
|
+ "option_name": "全局调节",
|
|
|
|
|
+ "factor": g.factor,
|
|
|
|
|
+ "absolute": None,
|
|
|
|
|
+ "before": round(before, 2),
|
|
|
|
|
+ "after": round(price, 2)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ # 品牌
|
|
|
|
|
+ b = db.execute(text("""
|
|
|
|
|
+ SELECT factor FROM price_adjust_factor
|
|
|
|
|
+ WHERE level='brand'
|
|
|
|
|
+ AND ref_id=(
|
|
|
|
|
+ SELECT brand_id
|
|
|
|
|
+ FROM t_machine
|
|
|
|
|
+ WHERE machine_id=:mid
|
|
|
|
|
+ )
|
|
|
|
|
+ LIMIT 1
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ if b:
|
|
|
|
|
+ before = price
|
|
|
|
|
+ price = price * float(b.factor)
|
|
|
|
|
+
|
|
|
|
|
+ detail_rows.append({
|
|
|
|
|
+ "option_id": "BRAND",
|
|
|
|
|
+ "option_name": "品牌调节",
|
|
|
|
|
+ "factor": b.factor,
|
|
|
|
|
+ "absolute": None,
|
|
|
|
|
+ "before": round(before, 2),
|
|
|
|
|
+ "after": round(price, 2)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ # 机型
|
|
|
|
|
+ m = db.execute(text("""
|
|
|
|
|
+ SELECT factor FROM price_adjust_factor
|
|
|
|
|
+ WHERE level='machine'
|
|
|
|
|
+ AND ref_id=:mid
|
|
|
|
|
+ LIMIT 1
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ if m:
|
|
|
|
|
+ before = price
|
|
|
|
|
+ price = price * float(m.factor)
|
|
|
|
|
+
|
|
|
|
|
+ detail_rows.append({
|
|
|
|
|
+ "option_id": "MACHINE",
|
|
|
|
|
+ "option_name": "机型调节",
|
|
|
|
|
+ "factor": m.factor,
|
|
|
|
|
+ "absolute": None,
|
|
|
|
|
+ "before": round(before, 2),
|
|
|
|
|
+ "after": round(price, 2)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ return templates.TemplateResponse(
|
|
|
|
|
+ "simulate_one.html",
|
|
|
|
|
+ {
|
|
|
|
|
+ "request": request,
|
|
|
|
|
+ "machine_id": machine_id,
|
|
|
|
|
+ "machine_name": row.name,
|
|
|
|
|
+ "tpl": tpl,
|
|
|
|
|
+ "result": {
|
|
|
|
|
+ "base_price": round(base_price, 2),
|
|
|
|
|
+ "final_price": round(price, 2),
|
|
|
|
|
+ "details": detail_rows,
|
|
|
|
|
+ "selected": option_ids
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+@router.post("/simulate", response_class=HTMLResponse)
|
|
|
|
|
+async def simulate_calc(
|
|
|
|
|
+ request: Request,
|
|
|
|
|
+ machine_id: int = Form(...),
|
|
|
|
|
+ db: Session = Depends(get_db)
|
|
|
|
|
+):
|
|
|
|
|
+ form = await request.form()
|
|
|
|
|
+
|
|
|
|
|
+ # 收集所有 option
|
|
|
|
|
+ option_ids = []
|
|
|
|
|
+ for k, v in form.multi_items():
|
|
|
|
|
+ if k.startswith("option_"):
|
|
|
|
|
+ option_ids.append(str(v))
|
|
|
|
|
+
|
|
|
|
|
+ # ---------------- 重新取模板与机型名 ----------------
|
|
|
|
|
+ row = db.execute(text("""
|
|
|
|
|
+ SELECT m.name,
|
|
|
|
|
+ t.estimate_packet
|
|
|
|
|
+ FROM machine_temp t
|
|
|
|
|
+ JOIN t_machine m ON t.machine_id = m.machine_id
|
|
|
|
|
+ WHERE t.machine_id = :mid
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ if not row:
|
|
|
|
|
+ return HTMLResponse("机型模板不存在")
|
|
|
|
|
+ tpl = json.loads(row.estimate_packet)
|
|
|
|
|
+ # ---------------- 构造 valueId -> valueText 映射 ----------------
|
|
|
|
|
+ value_name_map = {}
|
|
|
|
|
+
|
|
|
|
|
+ for step in tpl["template"]:
|
|
|
|
|
+ for p in step["properties"]:
|
|
|
|
|
+ for v in p["values"]:
|
|
|
|
|
+ value_name_map[str(v["valueId"])] = v["valueText"]
|
|
|
|
|
+
|
|
|
|
|
+ # ---------------- 基准价 ----------------
|
|
|
|
|
+ base_row = db.execute(text("""
|
|
|
|
|
+ SELECT base_price
|
|
|
|
|
+ FROM machine_base_price
|
|
|
|
|
+ WHERE machine_id=:mid
|
|
|
|
|
+ LIMIT 1
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ base_price_input = form.get("base_price")
|
|
|
|
|
+
|
|
|
|
|
+ if base_price_input and str(base_price_input).strip():
|
|
|
|
|
+ base_price = float(base_price_input)
|
|
|
|
|
+ else:
|
|
|
|
|
+ base_price = float(base_row.base_price) if base_row else 1
|
|
|
|
|
+
|
|
|
|
|
+ # ---------------- 选项因子 ----------------
|
|
|
|
|
+ detail_rows = []
|
|
|
|
|
+
|
|
|
|
|
+ if option_ids:
|
|
|
|
|
+ rows = db.execute(text("""
|
|
|
|
|
+ SELECT option_id, factor, absolute_deduct
|
|
|
|
|
+ FROM price_option_factor
|
|
|
|
|
+ WHERE option_id IN :ids
|
|
|
|
|
+ """), {"ids": tuple(option_ids)}).fetchall()
|
|
|
|
|
+ else:
|
|
|
|
|
+ rows = []
|
|
|
|
|
+
|
|
|
|
|
+ price = base_price
|
|
|
|
|
+
|
|
|
|
|
+ total_deduct_rate = 0
|
|
|
|
|
+ detail_rows.append({
|
|
|
|
|
+ "option_id": "GLOBAL",
|
|
|
|
|
+ "option_name": "-- 以下是扣减比例,累加",
|
|
|
|
|
+ "factor": 0,
|
|
|
|
|
+ "absolute": None,
|
|
|
|
|
+ "before": None,
|
|
|
|
|
+ "after": None
|
|
|
|
|
+ })
|
|
|
|
|
+ for r in rows:
|
|
|
|
|
+ before = price
|
|
|
|
|
+
|
|
|
|
|
+ if r.factor:
|
|
|
|
|
+ total_deduct_rate += float(r.factor)
|
|
|
|
|
+ # price = price * (1-float(r.factor))
|
|
|
|
|
+
|
|
|
|
|
+ # if r.absolute_deduct:
|
|
|
|
|
+ # price = price - float(r.absolute_deduct)
|
|
|
|
|
+
|
|
|
|
|
+ detail_rows.append({
|
|
|
|
|
+ "option_id": r.option_id,
|
|
|
|
|
+ "option_name": value_name_map.get(str(r.option_id), str(r.option_id)),
|
|
|
|
|
+ "factor": r.factor,
|
|
|
|
|
+ "absolute": r.absolute_deduct,
|
|
|
|
|
+ "before": round(before, 2),
|
|
|
|
|
+ "after": round(price, 2)
|
|
|
|
|
+ })
|
|
|
|
|
+ if total_deduct_rate:
|
|
|
|
|
+ price = price * (1 - total_deduct_rate)
|
|
|
|
|
+ price = max(price, 0.0)
|
|
|
|
|
+ # ---------------- 调节因子 ----------------
|
|
|
|
|
+
|
|
|
|
|
+ detail_rows.append({
|
|
|
|
|
+ "option_id": "GLOBAL",
|
|
|
|
|
+ "option_name": "-- 以下是调节因子,累乘",
|
|
|
|
|
+ "factor": 0,
|
|
|
|
|
+ "absolute": None,
|
|
|
|
|
+ "before": None,
|
|
|
|
|
+ "after": None
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ # 全局
|
|
|
|
|
+ g = db.execute(text("""
|
|
|
|
|
+ SELECT factor FROM price_adjust_factor
|
|
|
|
|
+ WHERE level='global'
|
|
|
|
|
+ LIMIT 1
|
|
|
|
|
+ """)).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ if g:
|
|
|
|
|
+ before = price
|
|
|
|
|
+ price = price * float(g.factor)
|
|
|
|
|
+ detail_rows.append({
|
|
|
|
|
+ "option_id": "GLOBAL",
|
|
|
|
|
+ "option_name": "全局调节系数",
|
|
|
|
|
+ "factor": g.factor,
|
|
|
|
|
+ "absolute": None,
|
|
|
|
|
+ "before": round(before, 2),
|
|
|
|
|
+ "after": round(price, 2)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ # 品牌
|
|
|
|
|
+ b = db.execute(text("""
|
|
|
|
|
+ SELECT factor FROM price_adjust_factor
|
|
|
|
|
+ WHERE level='brand'
|
|
|
|
|
+ AND ref_id=(
|
|
|
|
|
+ SELECT brand_id
|
|
|
|
|
+ FROM t_machine
|
|
|
|
|
+ WHERE machine_id=:mid
|
|
|
|
|
+ )
|
|
|
|
|
+ LIMIT 1
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ if b:
|
|
|
|
|
+ before = price
|
|
|
|
|
+ price = price * float(b.factor)
|
|
|
|
|
+ detail_rows.append({
|
|
|
|
|
+ "option_id": "BRAND",
|
|
|
|
|
+ "option_name": "品牌调节系数",
|
|
|
|
|
+ "factor": b.factor,
|
|
|
|
|
+ "absolute": None,
|
|
|
|
|
+ "before": round(before, 2),
|
|
|
|
|
+ "after": round(price, 2)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ # 机型
|
|
|
|
|
+ m = db.execute(text("""
|
|
|
|
|
+ SELECT factor FROM price_adjust_factor
|
|
|
|
|
+ WHERE level='machine'
|
|
|
|
|
+ AND ref_id=:mid
|
|
|
|
|
+ LIMIT 1
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ if m:
|
|
|
|
|
+ before = price
|
|
|
|
|
+ price = price * float(m.factor)
|
|
|
|
|
+ detail_rows.append({
|
|
|
|
|
+ "option_id": "MACHINE",
|
|
|
|
|
+ "option_name": "机型调节系数",
|
|
|
|
|
+ "factor": m.factor,
|
|
|
|
|
+ "absolute": None,
|
|
|
|
|
+ "before": round(before, 2),
|
|
|
|
|
+ "after": round(price, 2)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ # 重新取模板与机型名
|
|
|
|
|
+ row = db.execute(text("""
|
|
|
|
|
+ SELECT m.name,
|
|
|
|
|
+ t.estimate_packet
|
|
|
|
|
+ FROM machine_temp t
|
|
|
|
|
+ JOIN t_machine m ON t.machine_id = m.machine_id
|
|
|
|
|
+ WHERE t.machine_id = :mid
|
|
|
|
|
+ """), {"mid": machine_id}).fetchone()
|
|
|
|
|
+
|
|
|
|
|
+ tpl = json.loads(row.estimate_packet)
|
|
|
|
|
+
|
|
|
|
|
+ return templates.TemplateResponse(
|
|
|
|
|
+ "simulate_one.html",
|
|
|
|
|
+ {
|
|
|
|
|
+ "request": request,
|
|
|
|
|
+ "machine_id": machine_id,
|
|
|
|
|
+ "machine_name": row.name,
|
|
|
|
|
+ "tpl": tpl,
|
|
|
|
|
+ "result": {
|
|
|
|
|
+ "base_price": round(base_price, 2),
|
|
|
|
|
+ "final_price": round(price, 2),
|
|
|
|
|
+ "details": detail_rows,
|
|
|
|
|
+ "selected": option_ids
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
|
|
|
@router.post("/estimate2", response_class=HTMLResponse)
|
|
@router.post("/estimate2", response_class=HTMLResponse)
|
|
|
def estimate_submit(
|
|
def estimate_submit(
|