简介:围绕供应商质量管理与控制这一供应链核心议题,这份文档面向采购、质量与供应链管理人员,梳理了可落地的管控方法与实施要点。内容从制定联合质量计划切入,分经济、技术、管理三个维度展开,涵盖价值分析、成本与质量平衡、产品与工艺设计协同、检验测试标准化及责任分配,并说明向供应商派遣常驻代表与质检组的监督机制,以及定期或不定期监督检查、变更报告的处理思路。文档还给出定期排序评估的具体准则,如质量保证批合格率、进货批合格率、投入后工序直通合格率、纠正行动报告响应速度、交货期履行与审核分数等,并讨论帮助供应商导入 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 的查询结果逐项更新,score和grade由 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 工单上的抽检档位就自动换了档——控制从这里开始自己转起来。
本文还有配套的精品资源,点击获取