ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

报废品处理流程数字化:状态机、扫码报废与指导书可用

报废品处理流程数字化:状态机、扫码报废与指导书可用 简介面向制造企业质量、生产、物流、EHS、采购与财务岗位的报废品处理流程指导文件可用于规范采购品、外协品、半成品及成品的报废确认、退库、仓储、出售与最终处置帮助企业在成本控制、资源回收和环保合规之间取得平衡。资源包内含1个PDF文件大小约159KB篇幅精炼便于直接查阅、打印或作为内部培训与制度修订参考。全文围绕目的、适用范围、权责分配、名词定义和作业内容展开逐项界定财务、采购、EHS、质量、制造、设备工程、计划与物流等部门的职责并梳理不合格品评审单、报废品处理单、IQC检验、MRB会议、废品仓库入账标识等关键操作。还涉及报废品出售询议价、财务审批、过磅确认、EHS放行、仓库暂存15天、记录保存一年可追溯及流程图示覆盖跨部门协作要点。已有93人学习可供质量体系与生产运营人员借鉴。1. 报废品处理流程文件躺在共享盘为什么现场还是不按它做车间公告栏上那份《报废品处理流程》贴了两年共享盘里还有一份报废品处理流程,指导书可用.pdf但真正出问题时追溯靠的是班组长回忆和一本翻烂的纸质台账。上个月一批外观不良的注塑件被判成待检品重新上线客户投诉后才倒查出来文件里写的判定标准、隔离时限、审批层级都对唯独没有任何一处能被系统读取也没人知道手上那份 PDF 到底是 Rev.B 还是 Rev.C。这个标题真正要解决的不是再写一份更漂亮的指导书而是让报废品处理流程从一份静态 PDF变成一套可校验、可审批、可对账的线上流程并且让导出的指导书本身可用——现场扫码能带出单据版本号能一眼分辨字段能直接进台账。适合品质工程、制造 IT、MES/ERP 实施和做数字化车间的开发者尤其是那些已经有一堆 Word 和 PDF 规程、但流程依然靠人盯的团队。2. 把报废品处理流程拆成可执行的状态机与字段模型一份报废品指导书里最容易被忽略的部分是它其实描述了一个状态流转过程谁判定、谁审批、实物去哪、账什么时候关。这一步不做结构化后面所有系统化都是空谈。2.1 报废品处理流程的六个状态与每个状态的流转边界常见做法是把报废品处理流程收敛成六个状态每个状态只有一个明确的责任角色和一组允许操作。状态多了现场记不住少了又会出现批了但没入报废库这种账实不符。状态责任角色允许操作超时阈值超时动作待判定现场班组长发起、补照片4 小时提醒品质待审批品质工程师通过、驳回24 小时升级至品质主管已批准仓储打印报废单、转移8 小时卡住下一工单领料已入报废库仓储分区上架、登记72 小时日报预警已处置处置方拆解/变卖/销毁登记7 天财务挂账提醒已关账财务只读—不可再改这张表的价值在于它把指导书正文里那些应及时原则上的模糊表述换成了可配置的数值。阈值不是拍脑袋定的取的是过去三个月单据流转时间的 P90先设成 P90跑一个月再收紧。2.2 字段模型从指导书正文里抽出的必填项字段模型要覆盖判定、隔离、审批、处置、入账五个环节缺任何一个都会在事后追溯时断链。字段类型必填取值来源说明scrap_nostring(20)是系统生成报废单号规则 SQ车间码年月日4 位流水request_idstring(36)是客户端生成幂等键防止重复提交重复扣账material_codestring(30)是MES 工单物料编码qtydecimal(12,3)是现场录入按基本计量单位禁止用箱/托defect_codestring(10)是品质判定关联不良项字典scrap_reasonstring(200)是现场品质指导书附录 B 有填写范例stationstring(20)是工位主数据发生工位用于责任归属owner_deptstring(20)是组织主数据决定审批分级dispose_wayenum条件必填指导书附录 A拆解/变卖/销毁/退供evidence_urlstring(255)条件必填拍照上传金额超阈值时必须附证据request_id这一列值得单独说。车间网络抖一下扫码枪重复触发两次重复的报废单会直接造成库存多扣。把幂等键做成必填是最便宜的一道防线。2.3 用 Python 落一个可单测的状态机状态机不要写在 UI 里写成独立模块这样加签、撤回、升级这些规则才测得动。from enum import Enum from datetime import datetime, timedelta class ScrapState(Enum): DRAFT 待判定 REVIEW 待审批 APPROVED 已批准 IN_STORE 已入报废库 DISPOSED 已处置 CLOSED 已关账 # 只允许这些迁移其余一律拒绝 TRANSITIONS { ScrapState.DRAFT: [ScrapState.REVIEW], ScrapState.REVIEW: [ScrapState.APPROVED, ScrapState.DRAFT], # 驳回回到待判定 ScrapState.APPROVED: [ScrapState.IN_STORE], ScrapState.IN_STORE: [ScrapState.DISPOSED], ScrapState.DISPOSED: [ScrapState.CLOSED], ScrapState.CLOSED: [], } def transition(order, to_state, operator, role): if to_state not in TRANSITIONS[order.state]: raise ValueError(f非法流转 {order.state.value} - {to_state.value}) if not can_operate(role, order.state, to_state): raise PermissionError(f角色 {role} 无权执行该流转) order.state to_state order.trail.append((datetime.now(), operator, to_state.value)) if to_state is ScrapState.IN_STORE: # 入报废库才扣库存早扣晚扣都容易错 order.freeze_inventory() # 冻结而非直接扣减等关账再落账 return order def can_operate(role, cur, nxt): RULES { (ScrapState.DRAFT, ScrapState.REVIEW): {班组长, 品质工程师}, (ScrapState.REVIEW, ScrapState.APPROVED): {品质工程师, 品质主管}, (ScrapState.REVIEW, ScrapState.DRAFT): {品质工程师, 品质主管}, (ScrapState.APPROVED, ScrapState.IN_STORE): {仓储}, (ScrapState.IN_STORE, ScrapState.DISPOSED): {仓储, 处置方}, (ScrapState.DISPOSED, ScrapState.CLOSED): {财务}, } return role in RULES.get((cur, nxt), set())TRANSITIONS是唯一事实来源UI 上的按钮显隐也从它推导避免出现按钮能点但后端拒绝的割裂。freeze_inventory选择冻结而不是直接扣减是因为报废在关账前仍有被撤回的可能先扣会导致月底对账反复调整。trail记录每次流转的时间、操作人和目标状态这就是指导书里记录保存三年要求的落地方式。2.4 参数怎么定审批分级、金额阈值与超时兜底审批分级不要按人按金额和部门两个维度交叉定规则写死在配置表里而不是代码里后续改阈值不用发版。单张报废金额小于 500 元品质工程师一级审批。500 到 5000 元加品质主管二级审批。超过 5000 元或涉及安全件加制造经理、财务会签且必须附证据照片。超时处理待审批超过 24 小时自动升级并给主管推送48 小时未处理则锁死该工单的下一道领料逼现场来处理。阈值上线后要回看两个指标一是审批时长中位数超过 12 小时说明层级还是太重二是驳回率高于 15% 通常是填写指引不清该改的是指导书的范例部分不是加审批人。3. 生成一份真正可用的指导书 PDF版式、条码与版本校验指导书可用.pdf这个后缀其实提了要求这份 PDF 不只是给人看的还要能被扫码枪读、能被系统比对、能证明自己是最新版。3.1 可读、可扫、可追溯三条硬指标可读指 A4 单面能放下判定标准和填写范例现场不用翻页可扫指每张报废单带唯一条码扫码直接带出单据状态可追溯指页脚有版本号、生效日期和文件哈希。三条缺一条指导书就会退回成墙上的装饰。很多团队只做到了第一条结果现场拿的还是旧版流程判定按旧标准走。3.2 用 reportlab 生成带条码与版本号的指导书# gen_work_instruction.py from reportlab.lib.pagesizes import A4 from reportlab.lib.units import mm from reportlab.pdfgen import canvas from reportlab.graphics.barcode import code128 DOC_VERSION WI-QA-014 Rev.C # 正文任何一处改动都必须递增禁止原地覆盖 EFFECTIVE_DATE 2024-07-01 def build_pdf(path, fields): c canvas.Canvas(path, pagesizeA4) w, h A4 # 页眉固定版本号和生效日期现场一眼分新旧 c.setFont(Helvetica-Bold, 14) c.drawString(20*mm, h - 20*mm, fields[title]) c.setFont(Helvetica, 9) c.drawString(20*mm, h - 26*mm, f{DOC_VERSION} 生效日期 {EFFECTIVE_DATE}) # 正文按 95 个字符折行避免长句被页边距截断 text c.beginText(20*mm, h - 40*mm) text.setFont(Helvetica, 10) for line in fields[body]: text.textLine(line) c.drawText(text) # 右下角贴单号条码扫码即带出流程状态 bc code128.Code128(fields[scrap_no], barHeight12*mm, barWidth0.3*mm) bc.drawOn(c, w - 85*mm, 20*mm) c.setFont(Helvetica, 8) c.drawString(w - 85*mm, 16*mm, fields[scrap_no]) c.save()DOC_VERSION和EFFECTIVE_DATE必须是常量而不是运行时取值否则同一份内容每次生成出来的版本号都不一样比对就失去意义。barHeight取 12mm、barWidth取 0.3mm是车间常见标签打印机和扫码枪都能稳定识读的下限低于这个尺寸在油污或覆膜后误读率明显上升。正文折行宽度按 95 字符控制是为了让判定标准段落不跨页。3.3 版本哈希确保现场拿到的一定是最新那份# 发布时生成哈希清单随文件一起下发 sha256sum 报废品处理流程_WI-QA-014_RevC.pdf WI-QA-014_RevC.sha256 # 现场公告机或平板开机自检哈希不符说明是旧版或被改过 sha256sum -c WI-QA-014_RevC.sha256 || echo 版本异常请重新下发哈希清单要和服务端存的那份一致这样现场拿的版本对不对就不再靠人问人。把这段脚本挂到公告机开机自启里比每周派人去各车间核对文件有效期省事得多。3.4 条码与二维码的关键参数对照参数推荐值下限影响barWidth0.33mm0.25mm过细时喷墨打印会糊扫描失败barHeight12mm8mm过矮时扫码枪倾斜角度稍大就读不到quiet zone6mm3mm留白不足会导致首尾字符误读二维码纠错等级ML现场有油污建议提到 Q打印分辨率300dpi203dpi低于 203dpi 条码边缘会毛刺条码内容建议直接放scrap_no不要塞 JSON长度一长条码密度就上去了识读率下降得很快。需要在扫码后带出更多信息让扫码端拿单号去查接口。4. 报废品处理流程对接 MES/ERP扫码报废、审批与台账对账指导书管的是人怎么判系统管的是账怎么走。这两者接不上流程就永远有两套记录。4.1 扫码报废接口的契约与幂等设计接口只做一件事把现场扫到的单号和判定结果落库并返回当前状态。幂等键用客户端生成的request_id服务端先查后写。def post_scrap(cur, payload, request_id): 报废接口request_id 幂等重复提交只落一条不重复冻结库存 cur.execute(SELECT scrap_no, state FROM scrap_order WHERE request_id %s, (request_id,)) row cur.fetchone() if row: return {scrap_no: row[0], state: row[1], dup: True} scrap_no next_scrap_no(cur, payload[station]) # SQ 车间码 日期 流水 cur.execute( INSERT INTO scrap_order (scrap_no, request_id, material_code, qty, defect_code, scrap_reason, station, owner_dept, state, created_at) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, 待判定, now()) , (scrap_no, request_id, payload[material_code], payload[qty], payload[defect_code], payload[scrap_reason], payload[station], payload[owner_dept])) return {scrap_no: scrap_no, state: 待判定, dup: False}next_scrap_no的流水号必须走数据库序列或带行锁的计数表不能用时间戳拼接否则并发扫码会撞号。dup字段返回给扫码端让操作员看到这张单刚才已提交比抛异常友好得多。整个接口不直接扣库存只写单据库存动作留给状态机在入报废库时触发。4.2 报废台账表结构与必须建的索引CREATE TABLE scrap_order ( id BIGSERIAL PRIMARY KEY, scrap_no VARCHAR(20) NOT NULL UNIQUE, request_id VARCHAR(36) NOT NULL UNIQUE, material_code VARCHAR(30) NOT NULL, qty NUMERIC(12,3) NOT NULL CHECK (qty 0), defect_code VARCHAR(10) NOT NULL, scrap_reason VARCHAR(200) NOT NULL, station VARCHAR(20) NOT NULL, owner_dept VARCHAR(20) NOT NULL, dispose_way VARCHAR(10), evidence_url VARCHAR(255), state VARCHAR(16) NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), closed_at TIMESTAMPTZ ); -- 车间看板按工位状态过滤这条索引撑住 90% 的查询 CREATE INDEX idx_scrap_station_state ON scrap_order (station, state); -- 月末按部门出报废汇总 CREATE INDEX idx_scrap_dept_created ON scrap_order (owner_dept, created_at DESC);qty加CHECK (qty 0)是防呆报废数量为负或零在业务上无意义能在库层挡住的错误不要留到报表阶段才发现。state用字符串而不是数字枚举运维排查时肉眼可读代价只是几个字节。closed_at单独一列方便算处置周期。4.3 审批通过与库存冻结的时序问题审批和库存动作分属两个系统最容易踩的坑是审批通过了但冻结失败导致实物已经隔离、账面还有库存。常见做法是把冻结做成带重试的异步任务并在报废单上记录冻结状态。def on_approved(order, cur, mq): # 先落本地状态再发消息去触发冻结失败可重放 cur.execute(UPDATE scrap_order SET state已批准, freeze_statusPENDING WHERE scrap_no%s AND state待审批, (order.scrap_no,)) if cur.rowcount 0: # 乐观锁别处已改过状态直接放弃本次 return mq.publish(scrap.freeze, {scrap_no: order.scrap_no, material_code: order.material_code, qty: str(order.qty)})WHERE state待审批是乐观锁两个审批人同时点通过时只有一个能更新成功。freeze_status字段让运维能一眼找出卡在中间态的单据PENDING超过 10 分钟的就是失败任务直接重放消息即可不需要人工去改库存。4.4 一条 SQL 找出账实不符的报废单月末对账最实用的查询是把已入报废库但库存未冻结和已关账但处置未登记两类异常捞出来。SELECT scrap_no, material_code, qty, state, freeze_status, now() - created_at AS aging FROM scrap_order WHERE (state IN (已入报废库,已处置) AND freeze_status DONE) OR (state 已关账 AND dispose_way IS NULL) ORDER BY aging DESC LIMIT 200;aging用来排优先级挂得越久越可能是流程断点。把这条查询做成每日定时任务结果直接推给品质主管比等财务月底发现差异再回头翻单子高效得多。freeze_status和dispose_way这两个字段看起来是冗余的实际是排错时最省钱的两个抓手。5. 让指导书可检索现场排错、参数基线与复盘查询指导书最大的浪费是写完就锁进 PDF。把正文按章节切成结构化条目存起来现场遇到安全件报废要不要会签这类问题扫码或搜关键词就能直接命中条款而不是翻到第 7 页找。import re, json def parse_instruction(pdf_text): 把指导书正文拆成条款级条目便于按关键词检索 sections re.split(r\n(?\d(\.\d)*\s), pdf_text) # 按 1、1.1 这样的编号切 items [] for s in sections: m re.match(r(\d(\.\d)*)\s(.), s.strip()) if not m: continue no, _, rest m.groups() body rest.split(\n, 1)[1] if \n in rest else items.append({ clause: no, title: rest.split(\n)[0][:60], body: body.strip(), doc_version: DOC_VERSION, # 条款要绑版本否则新旧混检 }) return itemsclause保留原始编号是为了让检索结果能精确回指到 PDF 的章节doc_version必须一起存否则改版后旧条款还留在索引里现场搜出来的可能是已经作废的判定标准。切分正则按数字编号走前提是指导书正文本身编号规范这也是写指导书时该守的一条纪律。现场排错时最常被问到的参数其实就三个建议直接做成基线卡片贴在工位排错现象先看哪个参数常见取值处理动作扫码报废无响应request_id 是否重复36 位 UUID让扫码端重新生成后重试审批卡住审批层级与金额阈值500 / 5000 元核对 owner_dept 是否填错库存账实不符freeze_statusPENDING / DONE重放冻结消息不手工改库存条码扫不出barWidth0.33mm重新生成并提高打印分辨率搜不到条款doc_version当前 Rev重建索引清掉旧版本条目复盘查询可以固定在每周一跑一次把上周所有跨越三个以上状态、且总时长超过 7 天的单据捞出来逐条看卡在哪一步。多数时候问题不在审批人而在owner_dept填错导致审批路由到了不相干的部门这类数据质量问题从时长分布上看得最清楚。把aging超过 7 天的单据和它的流转轨迹trail一起导出就是下一次修订指导书最扎实的输入。本文还有配套的精品资源点击获取
返回列表