#!/usr/bin/env python3 """Fill A-suite (UATTEST_CHL) start-state rows for the 100-case closed-loop UAT. Tenant 838257186181189 only. Idempotent by business keys. Does not change UATA-WO-001..009, existing IQC PASS MDP, B/Demo, KPI, kit, or schedule results. """ from __future__ import annotations import json from datetime import datetime from typing import Any from apply_sql_file import connect TENANT = 838257186181189 FACTORY = 838257186320453 NOW = datetime.now().replace(microsecond=0) BATCH = "UATA-GAPFILL-20260824" WO_SRC = "UATA-WO-001" WO_NEW = "UATA-A01-WO-P01" MES_ID = 9206082410003001 IQC_A01_HDR = 9206082410001001 IQC_A01_ENT = 9206082410001002 IQC_A04_HDR = 9206082410001003 IQC_A04_ENT = 9206082410001004 IQC_A01_NO = "UATA-A01-IQC-001" IQC_A04_NO = "UATA-A04-IQC-NG" IPQC_A01_ID = 9206082410002001 IPQC_A01_ZB = 9206082410002002 IPQC_A05_ZB = 9206082410002003 IPQC_A01_NO = "UATA-A01-IPQC-001" IPQC_A05_NO = "UATA-A05-IPQC-001" DEMAND_ID = 9206082410004001 CUS_CODE = "UATA-A01-CUS" S0_CUS_ID = 9206082410005001 S0_MAT_ID = 9206082410005002 S0_BOM_ID = 9206082410005003 S0_RTE_ID = 9206082410005004 S0_LINE_ID = 9206082410005005 S0_SUP_ID = 9206082410005006 DS_CODE = "UATA-A01-DS" RULE_CODE = "UATA-A01-WATCH-01" EX_CODE = "UATA-A03-EX-NEW" def cols(cur, table: str) -> list[str]: cur.execute( """ SELECT COLUMN_NAME, EXTRA FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=%s ORDER BY ORDINAL_POSITION """, (table,), ) return [r["COLUMN_NAME"] for r in cur.fetchall() if "auto_increment" not in (r.get("EXTRA") or "")] def exists(cur, sql: str, args: tuple) -> bool: cur.execute(sql, args) row = cur.fetchone() return bool(row and list(row.values())[0]) def clone_work_order(cur) -> str: if exists(cur, "SELECT 1 FROM WorkOrdMaster WHERE tenant_id=%s AND WorkOrd=%s", (TENANT, WO_NEW)): return "exists" wo_cols = cols(cur, "WorkOrdMaster") select_exprs = [] for c in wo_cols: if c == "WorkOrd": select_exprs.append("%s") elif c == "Status": select_exprs.append("%s") elif c in ("ReleaseDate", "LotSerial", "Batch"): select_exprs.append("NULL") elif c == "CreateUser": select_exprs.append("%s") elif c == "UpdateUser": select_exprs.append("%s") elif c in ("CreateTime", "UpdateTime"): select_exprs.append("%s") else: select_exprs.append(f"`{c}`") sql = ( f"INSERT INTO WorkOrdMaster ({', '.join('`'+c+'`' for c in wo_cols)}) " f"SELECT {', '.join(select_exprs)} FROM WorkOrdMaster " f"WHERE tenant_id=%s AND WorkOrd=%s LIMIT 1" ) params: list[Any] = [] for c in wo_cols: if c == "WorkOrd": params.append(WO_NEW) elif c == "Status": params.append("p") elif c in ("CreateUser", "UpdateUser"): params.append("UATA-GAPFILL") elif c in ("CreateTime", "UpdateTime"): params.append(NOW) params.extend([TENANT, WO_SRC]) cur.execute(sql, params) for table, wo_col in (("WorkOrdDetail", "WorkOrd"), ("WorkOrdRouting", "WorkOrd")): dcols = cols(cur, table) select_exprs = [] extra: list[Any] = [] for c in dcols: if c == wo_col: select_exprs.append("%s") extra.append(WO_NEW) else: select_exprs.append(f"`{c}`") cur.execute( f"INSERT INTO `{table}` ({', '.join('`'+c+'`' for c in dcols)}) " f"SELECT {', '.join(select_exprs)} FROM `{table}` " f"WHERE {wo_col}=%s AND (tenant_id=%s OR tenant_id IS NULL)", extra + [WO_SRC, TENANT], ) if not exists(cur, "SELECT 1 FROM mes_morder WHERE tenant_id=%s AND morder_no=%s", (TENANT, WO_NEW)): mcols = cols(cur, "mes_morder") select_exprs = [] extra = [] for c in mcols: if c == "Id": select_exprs.append("%s") extra.append(MES_ID) elif c == "morder_no": select_exprs.append("%s") extra.append(WO_NEW) elif c == "morder_state": select_exprs.append("%s") extra.append("新建") elif c == "create_by_name": select_exprs.append("%s") extra.append("UATA-GAPFILL") elif c == "update_by_name": select_exprs.append("%s") extra.append("UATA-GAPFILL") elif c in ("create_time", "update_time"): select_exprs.append("%s") extra.append(NOW) else: select_exprs.append(f"`{c}`") cur.execute( f"INSERT INTO mes_morder ({', '.join('`'+c+'`' for c in mcols)}) " f"SELECT {', '.join(select_exprs)} FROM mes_morder " f"WHERE tenant_id=%s AND morder_no=%s LIMIT 1", extra + [TENANT, WO_SRC], ) return "inserted" def seed_iqc(cur) -> str: if exists(cur, "SELECT 1 FROM qms_qcp_inspecapplyn WHERE tenant_id=%s AND FBILLNO=%s", (TENANT, IQC_A01_NO)): return "exists" cur.execute( """ INSERT INTO qms_qcp_inspecapplyn (id, tenant_id, FBILLNO, FBILLTYPE, FAPPLYTIME, FCOMMENT) VALUES (%s, %s, %s, 'UAT', %s, 'A套UAT合格路径待认领') """, (IQC_A01_HDR, TENANT, IQC_A01_NO, NOW), ) cur.execute( """ INSERT INTO qms_qcp_insappnentry (id, tenant_id, glid, FSEQ, FMATERIALCFG, wlmc, FLOTNUMBER, FAPPLYQTY, FSRCORDERTYPE, FSRCORDERNUM, FSUPPLIER, gysbm, gysmc, FINSPECTSTATUS, jyfzr, shdh) VALUES (%s, %s, %s, 1, '3121C0035', '上底(45PUL)', 'UATA-A01-LOT', 100, 'po', 'UATA-PO-001', 'SUP-A01', 'SUP-A01', 'A01试验供应商', '未检验', NULL, 'UATA-A01-RCV') """, (IQC_A01_ENT, TENANT, IQC_A01_HDR), ) cur.execute( """ INSERT INTO qms_qcp_inspecapplyn (id, tenant_id, FBILLNO, FBILLTYPE, FAPPLYTIME, FCOMMENT) VALUES (%s, %s, %s, 'UAT', %s, 'A套UAT不合格路径待认领,勿改已有PASS') """, (IQC_A04_HDR, TENANT, IQC_A04_NO, NOW), ) cur.execute( """ INSERT INTO qms_qcp_insappnentry (id, tenant_id, glid, FSEQ, FMATERIALCFG, wlmc, FLOTNUMBER, FAPPLYQTY, FSRCORDERTYPE, FSRCORDERNUM, FSUPPLIER, gysbm, gysmc, FINSPECTSTATUS, jyfzr, shdh) VALUES (%s, %s, %s, 1, '1AB9275', '-IM60IL', 'UATA-A04-LOT', 80, 'po', 'UATA-PO-004', 'SUP-A04', 'SUP-A04', 'A04试验供应商', '未检验', NULL, 'UATA-A04-RCV') """, (IQC_A04_ENT, TENANT, IQC_A04_HDR), ) return "inserted" def seed_ipqc(cur) -> str: if not exists(cur, "SELECT 1 FROM qms_gcjyd WHERE tenant_id=%s AND djbh=%s", (TENANT, IPQC_A01_NO)): cur.execute( """ INSERT INTO qms_gcjyd (id, tenant_id, djbh, cplx, scph, lydjbh, jgpd, jyhgsl, jybhgsl, bz, jyr, gxbm, gxmc, ybl, sxrq, wlbm, wlmc, title, status) VALUES (%s, %s, %s, 'A01产品', 'UATA-A01-BATCH', %s, NULL, NULL, NULL, 'A套UAT合格路径待提交', NULL, 'OP10', '注塑', 20, %s, '3121C0035', '上底(45PUL)', 'UAT A01 IPQC', '待检验') """, (IPQC_A01_ID, TENANT, IPQC_A01_NO, WO_NEW, NOW), ) if not exists(cur, "SELECT 1 FROM qms_gcjydzb WHERE id=%s", (IPQC_A01_ZB,)): cur.execute( """ INSERT INTO qms_gcjydzb (id, tenant_id, glid, jyxm, jyyj, jyff, ProcessCode, ProcessName, ybl, jysl, bhgsl, pd) VALUES (%s, %s, %s, '外观', '目视无裂纹', '目视', 'OP10', '注塑', 20, NULL, NULL, NULL) """, (IPQC_A01_ZB, TENANT, IPQC_A01_ID), ) cur.execute("SELECT id FROM qms_gcjyd WHERE tenant_id=%s AND djbh=%s", (TENANT, IPQC_A05_NO)) a05 = cur.fetchone() if a05 and not exists(cur, "SELECT 1 FROM qms_gcjydzb WHERE tenant_id=%s AND glid=%s", (TENANT, a05["id"])): cur.execute( """ INSERT INTO qms_gcjydzb (id, tenant_id, glid, jyxm, jyyj, jyff, ProcessCode, ProcessName, ybl, jysl, bhgsl, pd) VALUES (%s, %s, %s, '装配尺寸', '卡尺', '测量', 'OP20', '装配', 20, 20, 2, 0) """, (IPQC_A05_ZB, TENANT, a05["id"]), ) cur.execute( """ INSERT INTO mdp_std_ipqc_inspection (tenant_id, factory_id, source_system, bill_no, product_model, production_batch_no, production_work_order, result_judgement, remark, inspector, process_code, process_name, sample_qty, material_code, material_name, inspection_status, source_row_id, source_biz_key, sync_batch_id, sync_time) SELECT g.tenant_id, 1, 'AIDOP', g.djbh, g.cplx, g.scph, g.lydjbh, CAST(g.jgpd AS CHAR), g.bz, g.jyr, g.gxbm, g.gxmc, g.ybl, g.wlbm, g.wlmc, g.status, CAST(g.id AS CHAR), g.djbh, %s, %s FROM qms_gcjyd g WHERE g.tenant_id=%s AND NOT EXISTS ( SELECT 1 FROM mdp_std_ipqc_inspection s WHERE s.tenant_id=g.tenant_id AND s.source_row_id=CAST(g.id AS CHAR) ) """, (BATCH, NOW, TENANT), ) return "upserted" def seed_s8(cur) -> str: if not exists( cur, "SELECT 1 FROM ado_s8_data_source WHERE tenant_id=%s AND factory_id=%s AND data_source_code=%s", (TENANT, FACTORY, DS_CODE), ): cur.execute( """ INSERT INTO ado_s8_data_source (tenant_id, factory_id, data_source_code, type, endpoint, auth_type, enabled, created_at, updated_at) VALUES (%s, %s, %s, 'SQL', 'aidopdev.local/uat', 'NONE', 1, %s, %s) """, (TENANT, FACTORY, DS_CODE, NOW, NOW), ) cur.execute( "SELECT id FROM ado_s8_data_source WHERE tenant_id=%s AND factory_id=%s AND data_source_code=%s", (TENANT, FACTORY, DS_CODE), ) ds_id = cur.fetchone()["id"] if not exists( cur, "SELECT 1 FROM ado_s8_watch_rule WHERE tenant_id=%s AND factory_id=%s AND rule_code=%s", (TENANT, FACTORY, RULE_CODE), ): cur.execute( """ INSERT INTO ado_s8_watch_rule (tenant_id, factory_id, rule_code, scene_code, data_source_id, watch_object_type, expression, severity, poll_interval_seconds, enabled, created_at, updated_at, consecutive_failure_count, trigger_count_required, recover_count_required, rule_mechanism) VALUES (%s, %s, %s, 'S3', %s, 'ORDER', 'UATA closed-loop watch', 'HIGH', 300, 1, %s, %s, 0, 1, 1, 'RULE') """, (TENANT, FACTORY, RULE_CODE, ds_id, NOW, NOW), ) if not exists( cur, "SELECT 1 FROM ado_s8_exception WHERE tenant_id=%s AND exception_code=%s", (TENANT, EX_CODE), ): cur.execute( """ INSERT INTO ado_s8_exception (tenant_id, factory_id, exception_code, title, description, scene_code, source_type, status, severity, priority_score, priority_level, occurrence_dept_id, responsible_dept_id, timeout_flag, created_at, updated_at, is_deleted, created_by, updated_by, related_object_code, module_code, exception_type_code, source_payload, dedup_key, consecutive_hit_count, consecutive_miss_count, rule_mechanism) VALUES (%s, %s, %s, %s, %s, 'S3', 'MANUAL', 'NEW', 'HIGH', 80, 'P1', 1, 1, 0, %s, %s, 0, 'UATA-GAPFILL', 'UATA-GAPFILL', 'UATA-A03-SO', 'S3', 'SUPPLIER_ETA_ISSUE', %s, %s, 1, 0, 'MANUAL') """, ( TENANT, FACTORY, EX_CODE, "UATA-A03 供应回复交期异常(待认领)", "A套UAT主动提报起点,状态NEW,供认领→处理→复检", NOW, NOW, json.dumps({"source": "uata-gapfill", "so": "UATA-A03-SO"}, ensure_ascii=False), EX_CODE, ), ) return "upserted" def seed_s0(cur) -> str: if not exists(cur, "SELECT 1 FROM CustMaster WHERE tenant_id=%s AND Cust=%s", (TENANT, CUS_CODE)): rec_extra = None cur.execute( "SELECT EXTRA FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='CustMaster' AND COLUMN_NAME='RecID'" ) rec_extra = (cur.fetchone() or {}).get("EXTRA") or "" if "auto_increment" in rec_extra: cur.execute( """ INSERT INTO CustMaster (company_ref_id, factory_ref_id, Domain, Cust, SortName, TaxIn, IsActive, IsConfirm, CreateUser, CreateTime, UpdateUser, UpdateTime, tenant_id, CustFullName, Remarks) VALUES (%s, %s, '2410', %s, 'UATAA01CUS', 0, 1, 1, 'UATA-GAPFILL', %s, 'UATA-GAPFILL', %s, %s, 'A套UAT客户', 'UAT A01') """, (FACTORY, FACTORY, CUS_CODE, NOW, NOW, TENANT), ) else: cur.execute("SELECT COALESCE(MAX(RecID),0)+1 AS n FROM CustMaster") rec = cur.fetchone()["n"] cur.execute( """ INSERT INTO CustMaster (RecID, company_ref_id, factory_ref_id, Domain, Cust, SortName, TaxIn, IsActive, IsConfirm, CreateUser, CreateTime, UpdateUser, UpdateTime, tenant_id, CustFullName, Remarks) VALUES (%s, %s, %s, '2410', %s, 'UATAA01CUS', 0, 1, 1, 'UATA-GAPFILL', %s, 'UATA-GAPFILL', %s, %s, 'A套UAT客户', 'UAT A01') """, (rec, FACTORY, FACTORY, CUS_CODE, NOW, NOW, TENANT), ) if not exists(cur, "SELECT 1 FROM ado_s0_sales_customer WHERE Code=%s AND CompanyRefId=%s", (CUS_CODE, FACTORY)): cur.execute( """ INSERT INTO ado_s0_sales_customer (Id, CompanyRefId, FactoryRefId, Code, Name, ForbidStatus, IsTaxIncluded, CustomerLevel, IsEnabled, CreatedAt) VALUES (%s, %s, %s, %s, 'A套UAT客户', 0, 0, 1, 1, %s) """, (S0_CUS_ID, FACTORY, FACTORY, CUS_CODE, NOW), ) if not exists(cur, "SELECT 1 FROM ado_s0_sales_material WHERE Code=%s AND CompanyRefId=%s", ("3121C0035", FACTORY)): cur.execute( """ INSERT INTO ado_s0_sales_material (Id, CompanyRefId, FactoryRefId, Code, Name, IsOnDemand, IsInspectionRequired, IsKeyMaterial, IsMainMaterial, IsPreprocess, IsAutoBatch, IsLabelRequired, IsBatchFifoReminder, IsBatchFifoStrict, ForbidStatus, IsEnabled, CreatedAt) VALUES (%s, %s, %s, '3121C0035', '上底(45PUL)', 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, %s) """, (S0_MAT_ID, FACTORY, FACTORY, NOW), ) if not exists(cur, "SELECT 1 FROM ado_s0_mfg_bom WHERE Code=%s AND CompanyRefId=%s", ("UATA-A01-BOM", FACTORY)): cur.execute( """ INSERT INTO ado_s0_mfg_bom (Id, CompanyRefId, FactoryRefId, Code, Name, MaterialId, BizVersion, DocStatus, IsEnabled, CreatedAt) VALUES (%s, %s, %s, 'UATA-A01-BOM', 'A01标准BOM', %s, '1.0', '生效', 1, %s) """, (S0_BOM_ID, FACTORY, FACTORY, S0_MAT_ID, NOW), ) if not exists(cur, "SELECT 1 FROM ado_s0_mfg_routing WHERE Code=%s AND CompanyRefId=%s", ("UATA-A01-RTE", FACTORY)): cur.execute( """ INSERT INTO ado_s0_mfg_routing (Id, CompanyRefId, FactoryRefId, Code, Name, BizVersion, DocStatus, IsEnabled, CreatedAt) VALUES (%s, %s, %s, 'UATA-A01-RTE', 'A01标准工艺', '1.0', '生效', 1, %s) """, (S0_RTE_ID, FACTORY, FACTORY, NOW), ) if not exists(cur, "SELECT 1 FROM ado_s0_mfg_production_line WHERE Code=%s AND CompanyRefId=%s", ("UATA-A01-LINE", FACTORY)): cur.execute( """ INSERT INTO ado_s0_mfg_production_line (Id, CompanyRefId, FactoryRefId, Code, Name, IsEnabled, CreatedAt) VALUES (%s, %s, %s, 'UATA-A01-LINE', 'A01产线', 1, %s) """, (S0_LINE_ID, FACTORY, FACTORY, NOW), ) cur.execute( "SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='srm_supplier' ORDER BY ORDINAL_POSITION" ) scols = [r["COLUMN_NAME"] for r in cur.fetchall()] code_col = next((c for c in ("supplier_code", "code", "Supp", "supplier_no", "FNumber") if c in scols), None) name_col = next((c for c in ("supplier_name", "name", "SuppName", "fname", "FName") if c in scols), None) if code_col and name_col and not exists( cur, f"SELECT 1 FROM srm_supplier WHERE tenant_id=%s AND `{code_col}`=%s", (TENANT, "UATA-A01-SUP"), ): cur.execute( f""" INSERT INTO srm_supplier (Id, tenant_id, IsDeleted, `{code_col}`, `{name_col}`) VALUES (%s, %s, 0, %s, %s) """, (S0_SUP_ID, TENANT, "UATA-A01-SUP", "A01试验供应商"), ) return "upserted" def seed_demand(cur) -> str: if exists(cur, "SELECT 1 FROM ic_demandschedule WHERE tenant_id=%s AND Id=%s", (TENANT, DEMAND_ID)): return "exists" if exists( cur, "SELECT 1 FROM ic_demandschedule WHERE tenant_id=%s AND itemnum=%s AND IFNULL(status,'')='' AND IFNULL(IsDeleted,0)=0 AND remarks LIKE %s", (TENANT, "3121C0035", "%UATA-A01%"), ): return "exists" cur.execute( """ INSERT INTO ic_demandschedule (Id, itemnum, fversion, requestdate, arrivaldate, shortqty, mesqty, locqty, sechedqty, tosechedqty, status, remarks, create_by_name, create_time, tenant_id, factory_id, IsDeleted, wolist) VALUES (%s, '3121C0035', '1.0', %s, %s, 50, 0, 0, 0, 50, '', 'UATA-A01 未发布需求,供勾选发布', 'UATA-GAPFILL', %s, %s, %s, 0, %s) """, (DEMAND_ID, NOW, NOW, NOW, TENANT, FACTORY, WO_NEW), ) return "inserted" def verify(cur) -> dict[str, int]: checks = { "wo_p": "SELECT COUNT(*) c FROM WorkOrdMaster WHERE tenant_id=%s AND WorkOrd=%s AND LOWER(TRIM(Status))='p'", "iqc_apply_entry": "SELECT COUNT(*) c FROM qms_qcp_insappnentry WHERE tenant_id=%s", "ipqc_std": "SELECT COUNT(*) c FROM mdp_std_ipqc_inspection WHERE tenant_id=%s", "s8_watch_a": "SELECT COUNT(*) c FROM ado_s8_watch_rule WHERE tenant_id=%s AND enabled=1", "s8_exc_new": "SELECT COUNT(*) c FROM ado_s8_exception WHERE tenant_id=%s AND status='NEW'", "wo_released": "SELECT COUNT(*) c FROM mes_morder WHERE tenant_id=%s AND IsDeleted=0 AND morder_state='Released'", "s0_customer": "SELECT COUNT(*) c FROM ado_s0_sales_customer", "s0_material": "SELECT COUNT(*) c FROM ado_s0_sales_material", "s0_bom": "SELECT COUNT(*) c FROM ado_s0_mfg_bom", "s0_routing": "SELECT COUNT(*) c FROM ado_s0_mfg_routing", "cust_picker": "SELECT COUNT(*) c FROM CustMaster WHERE tenant_id=%s", "demand_writable": "SELECT COUNT(*) c FROM ic_demandschedule WHERE tenant_id=%s AND IFNULL(IsDeleted,0)=0", } out: dict[str, int] = {} for k, sql in checks.items(): args = (TENANT,) if "%s" in sql else () if k == "wo_p": args = (TENANT, WO_NEW) cur.execute(sql, args) out[k] = int(cur.fetchone()["c"]) return out def main() -> None: conn = connect() result: dict[str, Any] = {"tenant": TENANT, "factory": FACTORY, "batch": BATCH} try: conn.autocommit(False) conn.begin() with conn.cursor() as cur: result["wo"] = clone_work_order(cur) result["iqc"] = seed_iqc(cur) result["ipqc"] = seed_ipqc(cur) result["s8"] = seed_s8(cur) result["s0"] = seed_s0(cur) result["demand"] = seed_demand(cur) result["verify"] = verify(cur) conn.commit() except Exception: conn.rollback() raise finally: conn.close() print(json.dumps(result, ensure_ascii=False, indent=2, default=str)) if __name__ == "__main__": main()