#!/usr/bin/env python3 # -*- coding: utf-8 -*- """演示数据落库脚本(北京电力 WMS + MES) 用途:为交付甲方的《系统页面截图说明书》准备成体系的业务数据。 数据真实落库,可长期保留。脚本可重复执行(幂等:已存在则跳过)。 用法: python demo_seed.py # 全部执行 python demo_seed.py inspect # 只探测库存/基线,不写库 """ import json import sys import time import urllib.request import urllib.error sys.stdout.reconfigure(encoding="utf-8") WMS = "http://127.0.0.1:8890" MES = "http://127.0.0.1:8888" XAPI = "Hardman_2026" OK, FAIL, SKIP = [], [], [] def req(base, method, path, body=None, token=None, xapi=None, timeout=20): url = base + path data = None headers = {"Content-Type": "application/json"} if token: headers["Authorization"] = "Bearer " + token if xapi: headers["X-API-TOKEN"] = xapi if body is not None: data = json.dumps(body, ensure_ascii=False).encode("utf-8") r = urllib.request.Request(url, data=data, headers=headers, method=method) try: with urllib.request.urlopen(r, timeout=timeout) as resp: return resp.status, resp.read().decode("utf-8", "replace") except urllib.error.HTTPError as e: return e.code, e.read().decode("utf-8", "replace") except Exception as e: return 0, str(e) def j(txt): try: return json.loads(txt) except Exception: return {"_raw": txt} def d_of(txt): d = j(txt) return d.get("data") if isinstance(d, dict) else None def step(label, st, txt, ok_cond=None, note=""): body = j(txt) ok = body.get("code") == 0 if isinstance(body, dict) else False if ok_cond is not None: ok = ok_cond tag = "OK " if ok else "FAIL" msg = body.get("message", "") if isinstance(body, dict) else txt[:120] print(" [%s] %-38s %s %s" % (tag, label, msg, note)) (OK if ok else FAIL).append(label) return body def skip(label, why): print(" [SKIP] %-38s %s" % (label, why)) SKIP.append(label) # ============================== 登录 ============================== def login_wms(): st, txt = req(WMS, "POST", "/api/auth/login", {"username": "admin", "password": "123456"}) return (d_of(txt) or {}).get("token", "") def login_mes(): st, txt = req(MES, "POST", "/api/v1/login", {"username": "admin", "password": "123456"}) return (d_of(txt) or {}).get("accessToken", "") def today(offset=0): return time.strftime("%Y-%m-%d", time.localtime(time.time() + offset * 86400)) # ============================== 探测 ============================== def fetch_details(wms_tok, manage_mode=0, page_size=200): """库存明细(原始行,含 batch_no / sn_code)——出库必须用它,聚合接口不返批次/SN""" url = "/api/stock/details?page=1&pageSize=%d" % page_size if manage_mode: url += "&manageMode=%d" % manage_mode st, txt = req(WMS, "GET", url, token=wms_tok) d = d_of(txt) or {} return d.get("list", []) def inspect(wms_tok, mes_tok): print("\n===== 库存探测(明细)=====") rows = fetch_details(wms_tok) print(" 库存明细行数=%d" % len(rows)) if rows: print(" 样例字段:%s" % sorted(rows[0].keys())) for r in rows[:12]: print(" %s mode=%s qty=%s zone=%s batch=%s sn=%s qual=%s" % ( r.get("materialCode"), r.get("manageMode"), r.get("quantity"), r.get("zoneCode"), r.get("batchNo"), r.get("snCode"), r.get("qualityStatus"))) print("\n===== MES 基线 =====") st, txt = req(MES, "GET", "/api/v1/product-types", token=mes_tok) print(" 产品类型:", json.dumps(d_of(txt), ensure_ascii=False)[:200]) st, txt = req(MES, "GET", "/api/v1/stations", token=mes_tok) sts = d_of(txt) or [] print(" 工位:%s" % [(s.get("stationNo"), s.get("name"), s.get("flowId")) for s in sts][:12]) # ============================== MES 造数 ============================== def mes_seed(mes_tok, wms_tok): print("\n===== MES 演示数据 =====") st, txt = req(MES, "GET", "/api/v1/product-types", token=mes_tok) ptypes = d_of(txt) or [] ptype = ptypes[0] ptype_id = ptype["id"] prod_code = ptype.get("code") prod_name = ptype.get("name") print(" 产品类型 id=%s code=%s name=%s" % (ptype_id, prod_code, prod_name)) # ---- BOM(用 WMS 真实物料)---- # 说明:前三项库内有现货(可走通备料出库全链路),第四项为长周期采购件 bom_items = [ {"materialCode": "ST-A100", "materialName": "标准结构件A100", "spec": "A100", "unit": "件", "manageMode": "1", "unitQty": 2, "lossRate": 5}, {"materialCode": "GJ-GANGGUAN-002", "materialName": "无缝钢管114x8", "spec": "114x8", "unit": "米", "manageMode": "1", "unitQty": 4, "lossRate": 3}, {"materialCode": "PR-S100", "materialName": "精密传感器S100", "spec": "S100", "unit": "个", "manageMode": "2", "unitQty": 1, "lossRate": 0}, {"materialCode": "JM-ZHOUCHENG-6020", "materialName": "精密轴承6020", "spec": "6020", "unit": "个", "manageMode": "2", "unitQty": 2, "lossRate": 0}, ] step("BOM 保存(4 项物料)", *req(MES, "PUT", "/api/v1/bom", {"productCode": prod_code, "items": bom_items}, token=mes_tok)) # ---- 第二个产品类型(仅 1 项物料,用于演示台账"领料完结"状态)---- prod2_code = "PROD-20260904-002" st, txt = req(MES, "GET", "/api/v1/product-types", token=mes_tok) hit = [p for p in (d_of(txt) or []) if p.get("code") == prod2_code] if hit: ptype2_id = hit[0]["id"] print(" [SKIP] 产品类型2 已存在 id=%s" % ptype2_id) else: st, txt = req(MES, "POST", "/api/v1/product-types", {"code": prod2_code, "name": "接驳体总成", "category": "总成类", "remark": "单物料演示产品", "isActive": True}, token=mes_tok) b = j(txt) print(" [%s] 创建产品类型2 %s" % ("OK " if b.get("code") == 0 else "FAIL", b.get("message", ""))) # 创建接口不返回 id,需回查 st, txt = req(MES, "GET", "/api/v1/product-types", token=mes_tok) hit = [p for p in (d_of(txt) or []) if p.get("code") == prod2_code] ptype2_id = hit[0]["id"] if hit else None if ptype2_id: step("BOM2 保存(单物料 PR-S100)", *req(MES, "PUT", "/api/v1/bom", { "productCode": prod2_code, "items": [{"materialCode": "PR-S100", "materialName": "精密传感器S100", "spec": "S100", "unit": "个", "manageMode": "2", "unitQty": 1, "lossRate": 0}]}, token=mes_tok)) # ---- 工单:覆盖各状态 ---- tag = time.strftime("%m%d") orders = {} def create_wo(no, qty, status_flow, p_id=None, p_code=None, p_name=None): body = {"workOrderNo": no, "productTypeId": p_id or ptype_id, "productCode": p_code or prod_code, "productName": p_name or prod_name, "quantity": qty, "status": "CREATED", "processSeq": ""} st, txt = req(MES, "POST", "/api/v1/work-orders", body, token=mes_tok) b = j(txt) if b.get("code") != 0 and "已存在" not in b.get("message", ""): step("工单创建 %s" % no, st, txt) return None st, txt = req(MES, "GET", "/api/v1/work-orders?orderNo=" + no, token=mes_tok) rows = d_of(txt) or [] if not rows: step("工单创建 %s" % no, st, txt) return None wo = rows[0] print(" [OK ] 工单 %-30s id=%s qty=%s" % (no, wo.get("id"), qty)) OK.append("工单 " + no) for s, reason in status_flow: st2, txt2 = req(MES, "POST", "/api/v1/work-orders/status", {"id": wo["id"], "status": s, "reason": reason}, token=mes_tok) b2 = j(txt2) if b2.get("code") == 0: print(" -> %s" % s) else: print(" -> %s 失败: %s" % (s, b2.get("message"))) orders[no] = wo return wo # WO-01 执行中(主力演示) create_wo("WO-2026%s-01" % tag, 30, [("RELEASED", ""), ("IN_PROGRESS", "按计划投产")]) # WO-02 已发布 create_wo("WO-2026%s-02" % tag, 20, [("RELEASED", "")]) # WO-03 暂停 create_wo("WO-2026%s-03" % tag, 15, [("RELEASED", ""), ("IN_PROGRESS", ""), ("PAUSED", "待料:轴承未到货")]) # WO-04 已完工 create_wo("WO-2026%s-04" % tag, 10, [("RELEASED", ""), ("IN_PROGRESS", ""), ("DONE", "按计划完工")]) # WO-05 草稿 create_wo("WO-2026%s-05" % tag, 25, []) # WO-06 单物料小工单(用于演示台账"领料完结") if ptype2_id: create_wo("WO-2026%s-06" % tag, 2, [("RELEASED", ""), ("IN_PROGRESS", "小批量试产")], p_id=ptype2_id, p_code=prod2_code, p_name="接驳体总成") # ---- 日排产 ---- print(" --- 日排产 ---") plans = [ ("WO-2026%s-01" % tag, today(-1), 10), ("WO-2026%s-01" % tag, today(0), 12), ("WO-2026%s-01" % tag, today(1), 8), ("WO-2026%s-02" % tag, today(0), 10), ("WO-2026%s-02" % tag, today(2), 10), ("WO-2026%s-05" % tag, today(3), 15), ] if ptype2_id: plans.append(("WO-2026%s-06" % tag, today(4), 2)) for no, d, qty in plans: st, txt = req(MES, "POST", "/api/v1/daily-plans", {"orderNo": no, "planDate": d, "planQty": qty, "status": ""}, token=mes_tok) b = j(txt) okk = b.get("code") == 0 or "已存在" in b.get("message", "") print(" [%s] 排产 %s %s qty=%s %s" % ("OK " if okk else "FAIL", no, d, qty, b.get("message", ""))) (OK if okk else FAIL).append("排产 %s %s" % (no, d)) # ---- 备料单(按日生成,幂等:已有该日记录则跳过)---- print(" --- 备料单生成 ---") st, txt = req(MES, "GET", "/api/v1/material-requests", token=mes_tok) exist_dates = {m.get("planDate") for m in (d_of(txt) or []) if m.get("planDate")} for d in [today(-1), today(0), today(1)] + ([today(4)] if ptype2_id else []): if d in exist_dates: skip("备料单 %s" % d, "该日已生成过") continue st, txt = req(MES, "POST", "/api/v1/material-requests/generate", {"planDate": d}, token=mes_tok) b = j(txt) cnt = (b.get("data") or {}).get("count") print(" [%s] 生成 %s 备料单 %s 条 %s" % ("OK " if b.get("code") == 0 else "FAIL", d, cnt, b.get("message", ""))) (OK if b.get("code") == 0 else FAIL).append("备料单 %s" % d) # ---- 工件:进线 / 工序报工 / 拧紧 / 完工 ---- print(" --- 工件与工序 ---") main_no = "WO-2026%s-01" % tag sns = ["SN2026%s-0001" % tag, "SN2026%s-0002" % tag, "SN2026%s-0003" % tag, "SN2026%s-0004" % tag, "SN2026%s-0005" % tag] for i, sn in enumerate(sns): st, txt = req(MES, "POST", "/api/v1/workpiece/online", {"sn": sn, "orderNo": main_no}, token=mes_tok) b = j(txt) print(" [%s] 进线 %s %s" % ("OK " if b.get("code") == 0 else "FAIL", sn, b.get("message", ""))) # 前 3 件走完工序 1~6,后 2 件只到工序 2(在制) upto = 6 if i < 3 else 2 for p in range(1, upto + 1): req(MES, "POST", "/api/v1/workpiece/process/report", {"sn": sn, "processCode": p, "stationNo": p, "steps": []}, token=mes_tok) print(" 工序 1~%d 已报工" % upto) # 拧紧数据 for i, sn in enumerate(sns[:3]): st, txt = req(MES, "POST", "/api/v1/torque/report", {"sn": sn, "workOrder": main_no, "stationNo": "7", "screwNo": "S-%03d" % (i + 1), "torque": 48.5 + i, "angle": 88.0 + i * 2, "result": "OK"}, token=mes_tok) b = j(txt) print(" [%s] 拧紧 %s torque=%.1f" % ("OK " if b.get("code") == 0 else "FAIL", sn, 48.5 + i)) # 完工 3 件 for sn in sns[:3]: st, txt = req(MES, "POST", "/api/v1/workpiece/done", {"sn": sn, "batchItems": [], "serialItems": []}, token=mes_tok) b = j(txt) print(" [%s] 完工 %s %s" % ("OK " if b.get("code") == 0 else "FAIL", sn, b.get("message", ""))) # ---- 扫码报工 ---- print(" --- 扫码报工 ---") for i, sn in enumerate(sns[3:]): st, txt = req(MES, "POST", "/api/v1/scan/report", {"station": "装配工位%d" % (i + 3), "sn": sn, "orderNo": main_no, "type": "PROCESS", "processCode": i + 1, "operator": "张装配"}, token=mes_tok) b = j(txt) print(" [%s] 报工 %s %s" % ("OK " if b.get("code") == 0 else "FAIL", sn, b.get("message", ""))) # ---- PLC 下发(握手:每次间隔 7s)---- print(" --- PLC 工位组合下发 ---") for sn in sns[3:5]: st, txt = req(MES, "POST", "/api/v1/plc/send-process", {"orderNo": main_no, "sn": sn, "stationNo": 3, "processCombination": "1"}, token=mes_tok) b = j(txt) print(" [%s] 下发 %s %s" % ("OK " if b.get("code") == 0 else "FAIL", sn, b.get("message", ""))) time.sleep(7) # ---- 巡检记录 ---- print(" --- 巡检终端 ---") insp = [ {"category": "CHECKIN", "stationNo": "1", "shift": "早", "orderNo": main_no, "sn": "", "result": "OK", "items": ["劳保穿戴齐全", "设备点检完成"], "photo": "", "remark": "到岗签到", "operator": "李巡检"}, {"category": "POINT", "stationNo": "7", "shift": "早", "orderNo": main_no, "sn": "", "result": "OK", "items": ["扭矩枪校准", "气压正常"], "photo": "", "remark": "班前点检", "operator": "李巡检"}, {"category": "PROCESS", "stationNo": "3", "shift": "中", "orderNo": main_no, "sn": sns[3], "result": "OK", "items": ["装配到位", "标识清晰"], "photo": "", "remark": "过程巡检", "operator": "王质检"}, {"category": "DONE", "stationNo": "1", "shift": "晚", "orderNo": main_no, "sn": "", "result": "OK", "items": ["现场清理", "设备断电"], "photo": "", "remark": "收工巡检", "operator": "李巡检"}, ] for it in insp: st, txt = req(MES, "POST", "/api/v1/inspections", it, token=mes_tok) b = j(txt) print(" [%s] 巡检 %s/%s %s" % ("OK " if b.get("code") == 0 else "FAIL", it["category"], it["stationNo"], b.get("message", ""))) return {"ptype_id": ptype_id, "prod_code": prod_code, "main_no": main_no, "sns": sns, "tag": tag} # ============================== WMS 造数 ============================== def wms_seed(wms_tok, mes_info): print("\n===== WMS 演示数据 =====") tag = mes_info["tag"] main_no = mes_info["main_no"] # ---- 库存探测:取可用批次/SN(明细接口,聚合行无批次/SN)---- allrows = fetch_details(wms_tok) batches = [r for r in allrows if r.get("manageMode") == 1 and (r.get("quantity") or 0) > 0] snrows = [r for r in allrows if r.get("manageMode") == 2 and (r.get("quantity") or 0) > 0] print(" 可用批次行=%d SN行=%d" % (len(batches), len(snrows))) for r in batches[:6]: print(" 批次 %s %s qty=%s zone=%s" % (r.get("materialCode"), r.get("batchNo"), r.get("quantity"), r.get("zoneCode"))) for r in snrows[:6]: print(" SN %s %s zone=%s" % (r.get("materialCode"), r.get("snCode"), r.get("zoneCode"))) # ---- 补充入库:精密件 SN(演示出库会持续消耗,先保证后续链路有货)---- print(" --- 补充入库 ---") for code, want in [("PR-S100", 12), ("ST-A100", 2)]: have = sum(1 for r in allrows if r.get("materialCode") == code and (r.get("quantity") or 0) > 0) if have >= want: skip("补入库 %s" % code, "现有 %d 已充足" % have) continue need = want - have if code == "PR-S100": body = {"inboundType": "purchase", "materialCode": code, "snList": ["PR-S100-DEMO%03d" % i for i in range(have, have + need)], "zoneCode": "Z02", "operator": "孙采购"} else: body = {"inboundType": "purchase", "materialCode": code, "batchNo": "B-DEMO-%s" % time.strftime("%H%M%S"), "quantity": 30 * need, "zoneCode": "Z01", "operator": "孙采购"} st, txt = req(WMS, "POST", "/api/inbound/create", body, token=wms_tok) step("补入库 %s x%d" % (code, need), st, txt) allrows = fetch_details(wms_tok) # ---- 台账同步(MES 工单 → WMS 工单备料台账)---- print(" --- 工单备料台账同步 ---") st, txt = req(MES, "GET", "/api/v1/material-requests", token=mes_info["mes_tok"]) mrs = d_of(txt) or [] by_order = {} for m in mrs: by_order.setdefault(m.get("orderNo"), []).append(m) # 幂等:已同步过的工单不再同步(sync 会把 status 重置为"进行中",会抹掉"领料完结") st, txt = req(WMS, "GET", "/api/ledger/query?page=1&pageSize=200", token=wms_tok) synced = {x.get("orderNo") for x in ((d_of(txt) or {}).get("list") or [])} for no, items in by_order.items(): if no in synced: skip("台账同步 %s" % no, "已同步过") continue payload = { "orderNo": no, "productCode": mes_info["prod_code"], "operator": "系统同步", "items": [{"materialCode": i.get("materialCode"), "materialName": i.get("materialName"), "totalQty": int(i.get("reqQty") or 0)} for i in items], } st, txt = req(WMS, "POST", "/api/internal/ledger/sync", payload, xapi=XAPI) b = j(txt) print(" [%s] 台账同步 %s (%d 项) %s" % ("OK " if b.get("code") == 0 else "FAIL", no, len(items), b.get("message", ""))) (OK if b.get("code") == 0 else FAIL).append("台账同步 " + no) # ---- 备料出库(受台账约束:累计出库 ≤ BOM 需求)---- print(" --- 备料出库(按台账)---") st, txt = req(WMS, "GET", "/api/ledger/query?page=1&pageSize=200", token=wms_tok) lg = (d_of(txt) or {}).get("list") or [] print(" 台账共 %d 项" % len(lg)) for item in lg: code, total = item.get("materialCode"), item.get("totalQty") or 0 out = item.get("outQty") or 0 need = total - out if need <= 0: skip("备料出库 %s/%s" % (item.get("orderNo"), code), "已领料完结") continue cand = [r for r in allrows if r.get("materialCode") == code and (r.get("quantity") or 0) > 0] if not cand: skip("备料出库 %s/%s" % (item.get("orderNo"), code), "库内无可用库存") continue r0 = cand[0] # 小单(需求≤6)一次领足 → 演示"领料完结";大单只领一部分 → 演示"部分领料" want = need if need <= 6 else min(need, 3) if r0.get("manageMode") == 2: take = cand[:min(want, len(cand))] body = {"orderNo": item.get("orderNo"), "materialCode": code, "snList": [x.get("snCode") for x in take], "qty": len(take), "operator": "刘库管", "targetDock": "DOCK03", "zoneCode": r0.get("zoneCode"), "remark": "工单备料"} else: qty = min(want, r0.get("quantity") or 1) body = {"orderNo": item.get("orderNo"), "materialCode": code, "batchNo": r0.get("batchNo"), "qty": qty, "operator": "刘库管", "targetDock": "DOCK03", "zoneCode": r0.get("zoneCode"), "remark": "工单备料"} st, txt = req(WMS, "POST", "/api/outbound/create", body, token=wms_tok) step("备料出库 %s/%s x%s" % (item.get("orderNo"), code, body["qty"]), st, txt) # 出库后刷新库存视图,避免同一行被重复分配 allrows = fetch_details(wms_tok) # ---- 通用出库(含装箱/合同号;用最新库存,避免与备料出库抢同一行)---- print(" --- 通用出库 ---") allrows = fetch_details(wms_tok) fresh_batch = [r for r in allrows if r.get("manageMode") == 1 and (r.get("quantity") or 0) > 0] fresh_sn = [r for r in allrows if r.get("manageMode") == 2 and (r.get("quantity") or 0) > 0] for i, (r, box, contract) in enumerate([(fresh_batch[0], "BOX-2026-001", "HT2026-0117"), (fresh_batch[1] if len(fresh_batch) > 1 else None, "BOX-2026-002", "HT2026-0118")]): if not r: continue st, txt = req(WMS, "POST", "/api/outbound/general", { "materialCode": r.get("materialCode"), "batchNo": r.get("batchNo"), "qty": min(3, r.get("quantity") or 1), "operator": "刘库管", "zoneCode": r.get("zoneCode"), "boxNo": box, "contractNo": contract, "remark": "销售发货", }, token=wms_tok) step("通用出库 %s/%s" % (r.get("materialCode"), box), st, txt) # SN 出库(挑库内仍可用的 SN) s0 = next((r for r in fresh_sn if r.get("materialCode") == "PR-S100"), fresh_sn[0] if fresh_sn else None) if s0: st, txt = req(WMS, "POST", "/api/outbound/general", { "materialCode": s0.get("materialCode"), "snList": [s0.get("snCode")], "operator": "刘库管", "zoneCode": s0.get("zoneCode"), "boxNo": "BOX-2026-003", "contractNo": "HT2026-0119", "remark": "精密件领用", }, token=wms_tok) step("通用出库 SN %s" % s0.get("snCode"), st, txt) # ---- 半成品入库 ---- print(" --- 半成品管理 ---") semi_plan = [ ("BP-2026%s-001" % tag, "BCP-JIEKOUTI", [1, 2, 3], "装配三", "Z02", main_no), ("BP-2026%s-002" % tag, "BCP-JIEKOUTI", [1, 2], "装配二", "Z02", main_no), ("BP-2026%s-003" % tag, "BCP-JIEKOUTI", [1, 2, 3, 4, 5, 6], "装配六", "Z02", main_no), ("BP-2026%s-004" % tag, "BCP-JIEKOUTI", [1], "装配一", "Z02", main_no), ] for sn, mat, done, comp, zone, order in semi_plan: st, txt = req(WMS, "POST", "/api/semi/inbound", { "sn": sn, "materialCode": mat, "doneProcessCodes": done, "completedProcess": comp, "zoneCode": zone, "orderNo": order, "operator": "陈产线", }, token=wms_tok) step("半成品入库 %s" % sn, st, txt) # ---- 盘点 ---- print(" --- 库存盘点 ---") st, txt = req(WMS, "GET", "/api/stocktake/query", token=wms_tok) existing = (d_of(txt) or {}).get("list") or [] if existing: skip("发起盘点", "已存在 %d 张盘点单" % len(existing)) else: zone_pick = [] for r in allrows[:60]: z = r.get("zoneCode") if z and z not in zone_pick: zone_pick.append(z) if len(zone_pick) >= 2: break st, txt = req(WMS, "POST", "/api/stocktake/start", {"operator": "赵盘点", "zones": zone_pick}, token=wms_tok) b = j(txt) st_no = (b.get("data") or {}).get("stocktakeNo") if b.get("code") == 0 else None print(" [%s] 发起盘点 zones=%s no=%s %s" % ("OK " if st_no else "FAIL", zone_pick, st_no, b.get("message", ""))) if st_no: OK.append("发起盘点") st, txt = req(WMS, "GET", "/api/stocktake/query?stocktakeNo=" + st_no + "&pageSize=200", token=wms_tok) bb = j(txt) items = (bb.get("data") or {}).get("list") or [] print(" 盘点项 %d 条" % len(items)) # 录入前 8 条实盘:前 6 条账实相符,后 2 条制造差异 for i, it in enumerate(items[:8]): tid = it.get("target_id") if not tid: continue sysq = it.get("book_qty") or 1 scan = sysq if i < 6 else max(0, sysq - 1) req(WMS, "POST", "/api/stocktake/record", { "stocktakeNo": st_no, "targetType": it.get("target_type") or "", "targetId": tid, "scanQty": scan}, token=wms_tok) print(" 已录入 8 条实盘(含 2 条差异)") st, txt = req(WMS, "POST", "/api/stocktake/finish", {"stocktakeNo": st_no, "adjust": True}, token=wms_tok) step("完成盘点 %s" % st_no, st, txt) # ---- AGV 配送 ---- print(" --- AGV 配送 ---") rows_payload = [] for i, m in enumerate((d_of(req(MES, "GET", "/api/v1/material-requests", token=mes_info["mes_tok"])[1]) or [])[:4]): rows_payload.append({ "requestNo": m.get("requestNo"), "materialCode": m.get("materialCode"), "materialName": m.get("materialName"), "unit": m.get("unit") or "件", "qty": float(m.get("reqQty") or 1), "targetDock": "DOCK%02d" % (i + 1), }) if rows_payload: st, txt = req(WMS, "POST", "/api/agv/submit", {"rows": rows_payload, "sourceDock": "DOCK21"}, token=wms_tok) step("AGV 下发 %d 行" % len(rows_payload), st, txt) # ============================== main ============================== def main(): mode = sys.argv[1] if len(sys.argv) > 1 else "all" print("=" * 70) print("演示数据落库 WMS=%s MES=%s" % (WMS, MES)) print("=" * 70) wms_tok = login_wms() mes_tok = login_mes() if not wms_tok: print("WMS 登录失败") sys.exit(1) if not mes_tok: print("MES 登录失败") sys.exit(1) print("登录成功") if mode == "inspect": inspect(wms_tok, mes_tok) return mes_info = mes_seed(mes_tok, wms_tok) mes_info["mes_tok"] = mes_tok wms_seed(wms_tok, mes_info) print("\n" + "=" * 70) print("成功 %d / 失败 %d / 跳过 %d" % (len(OK), len(FAIL), len(SKIP))) if FAIL: print("失败项:") for f in FAIL: print(" - " + f) print("=" * 70) if __name__ == "__main__": main()