news 2026/9/18 3:20:09

供应商质量评分自动化:MySQL+Python实现CPK、PPM与8D闭环

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
供应商质量评分自动化:MySQL+Python实现CPK、PPM与8D闭环

简介:围绕供应商质量管理与控制这一供应链核心议题,这份文档面向采购、质量与供应链管理人员,梳理了可落地的管控方法与实施要点。内容从制定联合质量计划切入,分经济、技术、管理三个维度展开,涵盖价值分析、成本与质量平衡、产品与工艺设计协同、检验测试标准化及责任分配,并说明向供应商派遣常驻代表与质检组的监督机制,以及定期或不定期监督检查、变更报告的处理思路。文档还给出定期排序评估的具体准则,如质量保证批合格率、进货批合格率、投入后工序直通合格率、纠正行动报告响应速度、交货期履行与审核分数等,并讨论帮助供应商导入 ISO9000、6Sigma 体系的方法,兼及供应商关系管理的基本框架。资源包内含 1 个 doc 文档,约 265KB,层次清晰、便于检索查阅,已有 104 人学习。适合需要搭建供应商质量管控流程、完善评估指标与内外协同机制的从业者参考。

1. 供应商质量管理不是一份躺在共享盘里的 .doc

很多公司共享盘里都躺着这样一份文档,来料检验、8D、年度审核写得挺全,可旺季一来问题照旧:IQC 判了不合格,采购说供应商已经在整改,质量说没收到整改单,月底谁也算不清这家供应商是 A 级还是 C 级。失效的原因不在文字,而在它没有和数据、流程挂上钩——评分靠人填,合格率靠各自的手工表,整改单超期没人催。

下面按一条能落地的路径推:先定指标口径和评分模型,再用数据库搭数据底座,然后用脚本把 CPK 计算、月度评分、超限告警每天自动跑一遍,最后收在 8D 闭环和复评验证上。适合 SQE、质量工程师,以及被拉来做质量看板的开发。

2. 供应商质量指标体系与分级模型的搭建方法

2.1 先定口径,再谈系统

同一个供应商,采购说合格率 99%,质量说 94%,差出来的五个点通常是口径打架:一边把让步接收算成合格,一边算成不合格;一边按批次算,一边按件数算。系统化之前必须先把口径写死,写进字段定义里,而不是写在制度文档的附件里。否则脚本跑得再快,也只是一个自动产出争议的工具。

判断口径是否合格,有个很实用的检验方式:随便挑三家供应商,让两个人各自按口径手工算一遍,结果必须完全一致。做不到就说明定义还有歧义,比如"来料批"到底指一次送货单还是一个物料号一个到货日。常见做法是把检验批定义为「物料号 + 到货日期 + 供应商」的最小组合,落到表里就是一个唯一键。

2.2 五个可落地的核心指标与取数口径

指标不在多,在于每个都能自动取到数、都能对应一个动作。下面这五个是制造业里最通用的一组。

指标计算口径数据来源更新频率对应动作
IQC 批次合格率判定 PASS 的批次 / 当期检验批次,让步接收单独打标来料检验单每批加严或放宽抽检
PPM不良件数 / 收货总件数 × 10^6来料检验 + 产线退货每日触发 SCAR
CPK 达标率CPK ≥ 1.33 的关键特性数 / 送检关键特性数SPC 测量数据每月现场审核
SCAR 按期关闭率到期前关闭的整改单 / 当期到期整改单8D 记录每周供应商约谈
重复问题复发率同失效模式 90 天内再发次数 / 问题总数缺陷明细每月降级、冻结新项目

几个容易被忽略的细节:PPM 的分母必须是收货总件数,不是抽检件数,抽样检验里用抽检数当分母会把 PPM 放大几十倍;批次合格率要有最小样本门槛,一个月只交过一批货的供应商不该拿 100% 去拉高均分;让步接收既不能算合格也不能算不合格,要用第三种状态单独统计,因为它对应的是风险,不是质量水平。

2.3 供应商分级评分卡的权重与阈值设计

2.3.1 权重分配与归一化方式

五项指标量纲不同,直接加权没意义,必须先各自归一化到 0~100 分。越大越好的指标(批次合格率)直接用比例映射;越小越好的指标(PPM、复发率)用目标值到最差值做线性映射,目标值得满分,最差值得 0 分。权重建议按「结果类 40%、过程类 35%、闭环类 25%」的大框架分配,避免全压在结果指标上,那会导致供应商只救火不改善。

# supplier_scorecard.yaml —— 权重合计必须为 1.0,改完用校验脚本跑一遍 weights: lot_pass_rate: 0.15 # 结果类:批次合格率 ppm: 0.25 # 结果类:百万件缺陷数 cpk_rate: 0.20 # 过程类:关键特性过程能力达标率 scar_ontime: 0.15 # 闭环类:整改单按期关闭 recurrence: 0.25 # 闭环类:重复问题复发(反向指标) targets: # 归一化的满分点与零点 ppm: {best: 200, worst: 3000} recurrence: {best: 0, worst: 0.3} grade_cutoffs: {A: 85, B: 70, C: 60} # D 为 60 分以下
2.3.2 阈值别拍脑袋,用历史分位数校准

分级线最容易犯的错是按"感觉"定,比如 90 分以上算 A,结果全年没有一家达标,分级失去区分度。稳妥做法是拉过去 12 个月的数据算分位数:前 25% 对应的分数作为 A 线,中位数附近作为 B 线,后 25% 作为 C 线,再结合业务容忍度上下浮动 2~3 分。分级的意义在于区分对待,而不是给所有供应商发奖状。

阈值确定后要固化成配置,而不是写死在代码里。每次调整阈值都留一次版本记录,否则三个月后没人说得清为什么这家供应商从 B 掉到了 C。

3. 用 MySQL 搭供应商质量数据底座

3.1 三张核心表:来料批次、缺陷明细、整改单

数据底座不需要多复杂,三张事实表加一张供应商主数据基本够用。重点是字段定义要和第 2 章的口径一一对应,特别是结果状态和数量字段。

CREATE TABLE iqc_lot ( lot_id BIGINT PRIMARY KEY AUTO_INCREMENT, supplier_id VARCHAR(32) NOT NULL, material_no VARCHAR(64) NOT NULL, receive_qty INT NOT NULL, -- 收货总件数,PPM 的分母 defect_qty INT NOT NULL DEFAULT 0, -- 判定不良件数 inspect_date DATE NOT NULL, result ENUM('PASS','FAIL','CONCESSION') NOT NULL, -- 让步接收单独打标 UNIQUE KEY uk_lot (supplier_id, material_no, inspect_date), KEY idx_sup_date (supplier_id, inspect_date) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE defect_detail ( defect_id BIGINT PRIMARY KEY AUTO_INCREMENT, lot_id BIGINT NOT NULL, failure_mode VARCHAR(64) NOT NULL, -- 失效模式,复发率靠它聚合 defect_qty INT NOT NULL, source ENUM('IQC','LINE','CUSTOMER') NOT NULL, KEY idx_lot (lot_id), KEY idx_mode (failure_mode) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE scar ( scar_id VARCHAR(32) PRIMARY KEY, supplier_id VARCHAR(32) NOT NULL, failure_mode VARCHAR(64) NOT NULL, created_at DATETIME NOT NULL, due_at DATETIME NOT NULL, closed_at DATETIME DEFAULT NULL, status ENUM('OPEN','D5_DUE','CLOSED') NOT NULL DEFAULT 'OPEN' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

result用三值枚举而不是布尔,是为了让步接收能单独统计;defect_detail独立成表,复发率才有的算,否则只能统计总量、看不出是不是同一个问题反复发生;scar.due_at显式存到期时间,比每次用created_at + 30 天现算更稳,因为不同等级的问题时限本来就不同。

3.2 批次合格率与 PPM 的查询写法

月度汇总是最常跑的一条查询,难点全在分母和边界条件上。

SELECT l.supplier_id, DATE_FORMAT(l.inspect_date, '%Y-%m') AS ym, COUNT(*) AS lot_cnt, SUM(l.result = 'PASS') AS pass_lot_cnt, ROUND(SUM(l.result = 'PASS') / COUNT(*) * 100, 2) AS lot_pass_rate, ROUND(SUM(l.defect_qty) / NULLIF(SUM(l.receive_qty), 0) * 1000000, 1) AS ppm FROM iqc_lot l WHERE l.inspect_date >= '2024-01-01' AND l.result <> 'CONCESSION' -- 让步接收不进合格率分子分母,单独走风险统计 GROUP BY l.supplier_id, ym HAVING COUNT(*) >= 5; -- 样本不足 5 批的月份不参与评分

MySQL 里SUM(condition)会把布尔值当 0/1 求和,比SUM(CASE WHEN ... THEN 1 ELSE 0 END)短,但只适用于 MySQL;换到 PostgreSQL 要改回COUNT(*) FILTER (WHERE ...)NULLIF是防除零的,某个月只有退货没有正常收货时,分母是 0。HAVING COUNT(*) >= 5这条门槛值得坚持,否则一家每月只交一批货的供应商会频繁拿满分,把整体分布拉歪。

3.3 汇总表落库:把月度评分固化下来

评分结果要落成表,不要每次从明细现算,否则看板和 API 都被慢查询拖死。

CREATE TABLE supplier_month_score ( supplier_id VARCHAR(32) NOT NULL, ym CHAR(7) NOT NULL, lot_pass_rate DECIMAL(5,2), ppm DECIMAL(10,1), cpk_rate DECIMAL(5,2), scar_ontime DECIMAL(5,2), recurrence DECIMAL(5,2), score DECIMAL(5,2), grade CHAR(1), PRIMARY KEY (supplier_id, ym) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

主键用(supplier_id, ym)是为了后面INSERT ... ON DUPLICATE KEY UPDATE能幂等重跑,脚本中途失败重来不会产生重复月份。写入时按 3.2 的查询结果逐项更新,scoregrade由 Python 侧算好再写回,权重和阈值改动只影响脚本,不动表结构。

4. Python 自动化:CPK 计算、评分刷新与超限告警

4.1 从库里拉数据算 CPK 的最小脚本

CPK 是整个评分里最容易算错的一项,错在标准差的取法和样本量门槛上。

import pandas as pd def cpk(values, lsl, usl, min_sample=30): """单边规格传 None 即可;样本不足直接返回 None,不参与达标率统计""" s = pd.Series(values).dropna() if len(s) < min_sample: return None # 样本太少,CPK 波动极大,宁可判为未知 mu, sigma = s.mean(), s.std(ddof=1) # ddof=1 为样本标准差 if sigma == 0: return None # 全部测量值相同,通常是记录错误 upper = (usl - mu) / (3 * sigma) if usl is not None else float('inf') lower = (mu - lsl) / (3 * sigma) if lsl is not None else float('inf') return round(min(upper, lower), 2)

min取的是上下限里较差的那一侧,这正是 Cpk 与 Cp 的区别所在——Cp 只看离散程度,Cpk 还要看中心偏了多少,供应商把均值调偏一点就能骗过 Cp,骗不过 Cpk。ddof=1用样本标准差,和多数 SPC 软件的口径一致;如果供应商报告和我们算出来差一点,先对样本量和标准差口径,再怀疑数据造假。单边规格(只有上限或只有下限)很常见,比如粗糙度、杂质含量,这时传None,函数按单边处理。

4.2 评分卡落地与分级告警

评分就是把归一化和加权串起来,告警则是把评分结果变成人能看见的动作。

def norm_lower_better(value, best, worst): """越小越好的指标:达到 best 得 100 分,达到 worst 得 0 分,中间线性插值""" if value is None: return 0.0 # 无数据按 0 分处理,倒逼供应商补数据 if value <= best: return 100.0 if value >= worst: return 0.0 return (worst - value) / (worst - best) * 100 def score_supplier(row, w, targets): s = (row['lot_pass_rate'] * w['lot_pass_rate'] + norm_lower_better(row['ppm'], **targets['ppm']) * w['ppm'] + row['cpk_rate'] * w['cpk_rate'] + row['scar_ontime'] * w['scar_ontime'] + norm_lower_better(row['recurrence'], **targets['recurrence']) * w['recurrence']) grade = 'A' if s >= 85 else 'B' if s >= 70 else 'C' if s >= 60 else 'D' return round(s, 2), grade

告警要能直接推给人,不要只写进日志。

import requests def push_alert(webhook, supplier, grade, reasons): text = f"[供应商质量告警] {supplier} 本期评级 {grade}\n" + "\n".join(reasons) resp = requests.post(webhook, json={"msgtype": "text", "text": {"content": text}}, timeout=5) resp.raise_for_status() # 非 2xx 直接抛异常,交给外层重试,不吞掉失败

raise_for_status()这行不要省。很多脚本把推送失败静默吞掉,结果质量周报发了三天没人收到,也没人知道。

4.3 幂等写入与告警去重

定时任务必然会重跑,重跑不能产生副作用。落库用INSERT ... ON DUPLICATE KEY UPDATE,告警用去重键控制。

参数建议值说明
CPK 最小样本量30低于此值返回 None,不计入达标率
CPK 达标线1.33关键特性常用 1.67,按物料分级设置
PPM 预警线500超过即触发 SCAR,可按品类上下浮动
批次合格率预警线98%低于即通知 SQE
复发统计窗口90 天同失效模式在此窗口内二次发生计复发
告警去重窗口24 小时同一供应商同一原因只推一次

去重实现很简单:把supplier_id + grade + 原因哈希拼成 key,写进 Redis 并设置 24 小时过期,写入成功才推送。这样脚本被定时器重复触发、或者手工补跑历史月份,都不会让群里刷屏。补跑历史月份时记得把去重开关关掉,否则回补的告警全被吞了。

5. 8D 闭环与供应商复评的进阶技巧

5.1 SCAR 触发规则与 8D 时效校验

整改单不能靠人想起才开。把触发规则写成 SQL,每天扫一遍,命中即建单。

-- 触发条件:单批不良件数占比超过 5%,或同一失效模式 90 天内已出现两次 SELECT l.supplier_id, l.material_no, d.failure_mode, SUM(d.defect_qty) AS bad_qty FROM defect_detail d JOIN iqc_lot l ON l.lot_id = d.lot_id WHERE d.source = 'IQC' AND l.inspect_date >= DATE_SUB(CURDATE(), INTERVAL 90 DAY) GROUP BY l.supplier_id, l.material_no, d.failure_mode HAVING bad_qty >= 3;

建单之后要卡时限,否则 8D 会永远停在 D3。

SELECT scar_id, supplier_id, DATEDIFF(NOW(), created_at) AS age_days, CASE WHEN status <> 'CLOSED' AND DATEDIFF(NOW(), created_at) > 30 THEN 'OVERDUE' WHEN status <> 'CLOSED' AND DATEDIFF(NOW(), created_at) > 7 THEN 'D5_DUE' ELSE 'ON_TRACK' END AS flag FROM scar WHERE status <> 'CLOSED';

常见时限设置是:D1~D3(围堵)48 小时内提交,D4~D5(根因与对策)7 天内,D6~D8(验证与预防)30 天内。超期就自动把该供应商当月闭环类指标扣分,指标和流程绑在一起,催单才有人理。注意age_days用的是自然日,跨节假日多的月份可以改成工作日计算,但要和供应商约定清楚,否则月底又是一轮扯皮。

5.2 用加严检验与回溯验证确认控制真的生效

整改单关闭不等于问题消失,必须做效果回溯。可操作的规则是:SCAR 关闭后该供应商该物料连续 3 批加严检验(抽检比例提到正常的两倍),3 批全合格才恢复常规抽检;期间再出一次同类问题,直接升格为现场审核并冻结新项目导入。这条路子比"整改关闭即结束"严,但正是它能挡住复发。

回溯验证用数据说话,对比整改前后各 90 天的 PPM 和 CPK。

SELECT s.supplier_id, CASE WHEN l.inspect_date < s.closed_at THEN '整改前' ELSE '整改后' END AS phase, ROUND(SUM(l.defect_qty) / NULLIF(SUM(l.receive_qty), 0) * 1000000, 1) AS ppm, COUNT(*) AS lot_cnt FROM iqc_lot l JOIN scar s ON s.supplier_id = l.supplier_id AND s.failure_mode = '尺寸超差' WHERE l.inspect_date BETWEEN DATE_SUB(s.closed_at, INTERVAL 90 DAY) AND DATE_ADD(s.closed_at, INTERVAL 90 DAY) GROUP BY s.supplier_id, phase;

如果整改后 PPM 没降下来,说明 D4 根因分析是走过场,对策打在了症状上而不是原因上,这时候该退回去重开 D4,而不是继续往下走 D5 的永久对策。复评结果写回supplier.grade之后,下一轮定时任务跑完,IQC 工单上的抽检档位就自动换了档——控制从这里开始自己转起来。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 3:20:02

ToDesk清理后必须重启吗?Linux远程工具故障排查实战

如果你在成规模的 Linux 机器上部署过 ToDesk&#xff0c;大概率遇到过这种场景&#xff1a;清理了缓存目录、删掉旧版本、甚至把 /opt/todesk 整个目录移除后重装&#xff0c;结果客户端要么不弹窗&#xff0c;要么命令行报错&#xff0c;要么远程连上去一直转圈。这时候群里的…

作者头像 李华
网站建设 2026/9/18 3:18:04

毕夏AI官网的AIPPT:当“做PPT”变成“说PPT”

毕夏AI官网 www.bixiaai.com 毕夏AI写作官网 www.bixiaai.com 毕夏官网 www.bixiaai.com 毕夏智能写作官网 www.bixiaai.com 你有没有算过一笔账&#xff1f; 一篇开题报告论文写完&#xff0c;可能花了你三周。但从论文到能站在答辩现场的那份PPT&#xff0c;你还要再花…

作者头像 李华
网站建设 2026/9/18 3:16:10

定点数与浮点数:从二进制位权到精度陷阱与工程选型

1. 为什么搞懂定点数和浮点数&#xff0c;比背下IEEE 754更重要先说个场景。你写C语言&#xff0c;判断两个浮点数相等&#xff0c;写了if (a b)&#xff0c;结果程序跑起来跟抽风一样&#xff0c;有时对有时错。你调了一下午&#xff0c;最后发现是精度问题。这种经历&#x…

作者头像 李华
网站建设 2026/9/18 3:15:17

代码、源文件、编辑与编译:从双击无反应到程序跑通

1. 从"我把代码写进文本文档&#xff0c;为什么双击没反应"说起有个问题我在不同的场合被人问过不下二十遍&#xff1a;我把一段代码老老实实敲进了文本文档&#xff0c;保存了&#xff0c;双击它&#xff0c;电脑要么弹出一堆看不懂的英文&#xff0c;要么干脆一闪而…

作者头像 李华
网站建设 2026/9/18 3:13:40

LeetCode 283 移动零:双指针原地算法详解与多语言实现

1. 项目题干与考点拆解1.1 题目到底在说什么LeetCode hot100 第4题“移动零”&#xff0c;原题编号其实是283&#xff0c;题目描述非常短&#xff1a;给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。举个例子&am…

作者头像 李华
网站建设 2026/9/18 3:13:12

Python轻量级文物巡查系统:离线采集、风险评分与证据链管理

简介&#xff1a;本资源是一套面向文化遗产保护与信息系统开发人员的Python实战项目&#xff0c;聚焦古城文物巡查与数字档案管理场景&#xff0c;解决文物档案分散、巡查流程不闭环、风险识别主观性强等实际问题。资源为1个108KB的docx文档&#xff0c;完整涵盖系统设计思路、…

作者头像 李华