设备科六个人,管着全厂一百七十多台设备。一天二十来张维修工单,大故障要两个人上:一个主修,一个递工具、看图纸、扶梯子。听着简单,真正乱的就是这"两个人"。
原来的工单系统只有"负责人"一个字段。谁接的单就写谁,两个人一起上,另一个人没地方写。等月底统计工时,那个人等于白干。转派更随意,直接把负责人改掉,原负责人第二天打开系统发现自己名下的单不见了,打电话来问。
去年有一张液压站的单子,转了四手,从老陈到小刘再到外协,中间跨了九天,工单上只留下一个当前负责人。设备停着,谁去的现场、什么时候去的、查了什么,全查不出来。那次之后我下决心把状态机重写,转派必须经过接收方确认,协同必须两条人员记录。
一、转派为什么老出事
1.1 一张工单要经过几个人
正常流程是:班长报修、设备科计划员派工、维修工到场、修完、班长验收。中间任何一个环节人不在,就要转。请假、倒班、技能不对口、缺备件要换人,都会触发转派。
二十张单子里,一周内发生过转派的有六七张。转派本身不是问题,问题是转派之后信息断了:新来的人不知道前面查过什么,前面的人不知道后面怎么处理,同一台设备被两个人各查一遍。
还有一种更隐蔽的:单子挂在一个人名下,实际是另一个人在干。打电话问进度,负责人说"我没去,是小刘去的",小刘那边又没有权限更新工单,后来谁也没更新,单子就那么挂着。这种事在六个人的科室里一个月能碰上三四回,规模不大,但足以让整套工单数据的可信度打折。
1.2 改字段不等于转派
直接在数据库里把负责人改掉,是多数小系统的做法,也是省事的做法。省事的代价是:没有人知道发生过转派,没有交接内容,没有时间点,被转的人也没有同意过。
真正的转派应该是一次有握手的动作。原负责人提交转派申请,写清已排查的内容和转派原因;接收方点确认,工单才真正换手;接收方不确认,超过设定时间退回原负责人,或者升级给科长。这三步走完,责任才真正交出去。
1.3 协同的三种形态
两个人一起上,其实是三种不同的关系,混在一起做就会乱。一种是主修加协助,一个人负责判断和动手,一个人配合,责任在主修。一种是交接,前一个人干到一半,后一个人接着干,两个人不同时在场。一种是支援,隔壁班组来人帮两小时,不接手工单。
这三种关系在数据上的记法完全不同:主修加协助要在同一张工单下挂两条人员记录;交接要留两段工时和一段交接说明;支援只记工时,不参与验收。分不清这三种,工时统计永远是糊涂账。
二、状态机怎么定
2.1 八个状态够不够
我们把工单状态定成八个:待受理、已派工、待接收、到场、维修中、待验收、已关闭、已挂起。比常见的四个状态多了"待接收"和"已挂起"。
"待接收"是为了转派握手,前面说过。"已挂起"是为了等备件------设备停着但暂时修不了,工单既不能关闭也不能算在维修中,挂起是唯一合理的位置。挂起时要求填预计恢复时间,超过时间没恢复,科长那边会看到。
2.2 状态机代码
python
STATUS = {0: "待受理", 1: "已派工", 2: "待接收", 3: "到场",
4: "维修中", 5: "待验收", 6: "已关闭", 7: "已挂起"}
TRANSITIONS = [
("assign", 0, 1), ("transfer", 1, 2), ("accept", 2, 1),
("reject", 2, 0), ("arrive", 1, 3), ("start", 3, 4),
("finish", 4, 5), ("verify", 5, 6), ("hold", 4, 7),
("resume", 7, 4),
]
ROLE_OF = {"assign": "planner", "transfer": "planner", "accept": "tech",
"reject": "tech", "arrive": "tech", "start": "tech",
"finish": "tech", "verify": "supervisor",
"hold": "tech", "resume": "tech"}
def fire(order, action, actor, now, note=""):
rule = next(((s, d) for a, s, d in TRANSITIONS
if a == action and s == order["status"]), None)
if rule is None:
raise ValueError("%s 不能从 %s 发起" % (action, STATUS[order["status"]]))
if actor["role"] != ROLE_OF[action]:
raise PermissionError("%s 无权执行 %s" % (actor["role"], action))
if action in ("accept", "reject") and order["pending_to"] != actor["emp"]:
raise PermissionError("只有被转派的人可以处理")
if action == "transfer" and not note:
raise ValueError("转派必须写明已排查内容")
if action == "finish" and not all(p["done"] for p in order["persons"]):
raise ValueError("主修与协助都提交后才能转待验收")
if action == "verify" and not order.get("result"):
raise ValueError("验收必须填结论")
order["status"] = rule[1]
order["log"].append({"at": now, "by": actor["emp"],
"action": action, "note": note})
if action == "accept":
order["owner"], order["pending_to"] = order["pending_to"], None
return order["status"]
这段代码不长,但把三件事钉死了。动作和状态是一张白名单,不在表里的组合直接报错,绕不过去;角色校验放在服务层,前端藏按钮只是辅助;转派和完成这两个动作各有前置条件,不满足就抛异常。
log 这个列表落地时是一张独立的流水表,每次动作追加一行,永不更新。工单主表只存当前状态,历史全在流水里。这样查"这张单转过几次手",是查流水,不是猜。
2.3 为什么接收方要确认
转派不确认,等于把责任硬塞给人家。有过教训:一张单子转到正在休假的人名下,五天后才被发现,设备停了两天。
加了"待接收"之后,工单在系统里是"悬空"的,接收方不点,它就一直亮在待办列表上,同时倒计时。四小时不处理,自动退给原负责人,并给科长推一条。这条规则上线后,转派卡住的情况从每周两三起降到零。
三、两个人一起上:工时怎么记
3.1 主修和协助不是主次,是分工
系统里一张工单可以有多个参与人,但必须有一个主修。主修负责判断故障、决定方案、填维修记录;协助负责配合,也填自己的工时和做了什么。两个人的记录都提交了,工单才能进待验收。
这样做的直接好处是工时能算清。以前两个人干三小时,工时只记一个人三小时,另一人的产出在系统里是零。现在两条记录,各自填各自干的活,月底统计时看得出来谁在哪些设备上花的时间多。
3.2 支援怎么记
隔壁班组来帮忙,不接手工单,只在工单下加一条支援记录:来的人、起止时间、帮了什么。支援记录不参与验收,也不改变主修。
这条看着琐碎,实际很有用。有一台老冲床反复出问题,三个月里支援来了七次,全都记在案。后来买新设备时,这份记录是很有力的说明材料------不是某个人技术不行,是设备确实撑不住了。
3.3 验收只认一个签字
参与的人多,验收签字只能有一个:报修方的班长。验收要填三项:是否恢复正常、试机时长、遗留问题。三项填完才算关闭。
我们特意不允许维修工自己点"已修复"。以前有这个口子,工单关闭率很好看,设备该停还停。现在关闭权在报修方手上,维修工只能提交"待验收",这中间的差别,跑两个月就显出来了。
四、落地细节
4.1 手机端的四个按钮
维修工在现场用的是手机端,界面上只放四个按钮:到场、开工、挂起、完成。按钮的可用状态由状态机算出来,不该点的直接置灰,不弹错误提示。
置灰比弹窗好。弹窗要人读一行字再点确定,现场戴着手套、手上是油,谁也不愿意读。置灰是一眼就懂,点不了就是不能点。
4.2 三个月的数字
上线三个月,工单平均闭环时间从四天多降到一天半。转派次数没降,反而升了一点------因为转派变得容易了,大家愿意走流程,而不是硬扛着不转。
闭环时间的计算方式也换了。原来按工单创建到关闭算,中间挂起等备件的天数也算在内,数字很难看;现在把挂起时长单独扣出来,看的才是真正的响应速度。两个口径都留着,一个对外报,一个对内改流程。
挂起的单子从没人管变成有预计恢复时间,超期的每周两张左右,科长直接看得到。这个数字不大,但以前是彻底的黑洞。
工时统计也跟着变了。以前月底汇总,六个人的工时加起来总比实际出勤少两成,差额就散在那些"两个人一起上"的单子里。现在每张单上几个参与人、各干了多久,都是维修工自己点的,汇总出来能对上九成五以上。这个数准了,排班和加班安排才有依据,不用再靠班长回忆。
常见问题
问:状态机用代码写死,以后加状态是不是要改代码?
答:状态和转移放在配置表里更灵活,但要加一层校验:配置改动必须走审核,且上线前跑一遍全量状态可达性检查,确保没有走不到的状态、没有出不去的死状态。我们一开始也是配置化的,后来发现改得太随意,才收回成代码加版本管理。
问:转派时原负责人填的排查内容,怎么保证不是敷衍?
答:靠格式约束,不靠态度。转派说明里必填三项:已检查的部位、已排除的原因、建议下一步。三项都是短文本,填"已检查"这种话提交不了------我们在提交时做了字数下限和关键词校验,低于下限直接拦住。
问:两个人同时操作一张工单,会不会冲突?
答:会,靠状态机的当前状态挡。A 点了完成,工单进待验收,B 再点完成就会因为状态不匹配报错。真正要防的是同一秒的并发请求,做法是更新时带上状态条件,where status = 4 之类,影响行数为零就说明被人抢先了,前端提示刷新。
问:外协单位的工单怎么接进这套流程?
答:外协不给他们开系统账号,由设备科的人代录,工单上标注外协单位名称和进场时间。外协的处理记录以附件形式挂在工单下,验收仍由报修方班长签字。这样责任链完整,又不用处理外部账号和权限的麻烦。