简介:这份PDF资料围绕供应链(购销存)管理系统的构成与操作流程展开,面向企业财务、ERP实施人员及经管类学习者,帮助理解采购、销售、库存、存货核算四大模块如何协同运转。内容以用友ERP-U852为背景,梳理了各模块的功能特点、手工核算与电算化核算两套流程,并配有购货、销货业务流程及系统功能简图,便于对照理解数据传递与账务处理逻辑。资源包共1个PDF文件,约754KB,轻量易读,适合作为课堂讲义或自学参考。目前已有532人学习下载。读者可从中掌握请购、定购、入库、开票、结算等关键环节的操作要点,了解先进先出、加权平均等成本计算方法,以及基础档案设置、凭证传递与综合查询等系统应用思路,为实际配置和优化供应链管理系统提供参考。
1. 供应链管理系统构成操作流程到底在解决什么问题
很多团队第一次接触供应链管理系统,都是被一份《供应链管理系统构成操作流程(带流程图).pdf》砸到脸上的。文档里画满了方框、箭头、泳道,采购申请从左边进,入库单从右边出,中间还夹着审批、对账、结算。看完第一反应往往是:流程我懂了,可系统到底怎么落地?这份文档描述的其实不是软件界面,而是一套「业务对象 + 状态机 + 角色权限」的组合。它要解决的核心痛点是:订单、库存、采购、供应商、财务这几本账各记各的,数据对不上,责任分不清。适合谁看?适合正在做进销存、ERP 二次开发、或者要把线下审批搬到线上的后端与产品同学。流程图只是表象,真正要复现的是它背后那张「单据流转表」。
2. 把流程图翻译成数据模型:五张核心表怎么定
流程图里的每一个方框,落到数据库里就是一张表或者一个状态字段。很多人一上来就照着图建了二十多张表,结果查询要 join 七八层,维护成本爆炸。我的经验是:先抓住五张主干表,其余都是它们的延伸。
2.1 供应商、物料、采购单、入库单、库存流水
这五张表构成了供应链的最小闭环。供应商表存资质和结算周期,物料表存 SKU 和单位,采购单是需求载体,入库单是履约凭证,库存流水是每一次数量变动的账本。关键设计原则是:库存数量永远不要直接改,只追加流水,当前库存由流水汇总得出。这样任何一次对账都能追溯到源头。
-- 供应商表:结算周期决定后续对账逻辑 CREATE TABLE supplier ( id BIGINT PRIMARY KEY, name VARCHAR(128) NOT NULL, settle_cycle INT DEFAULT 30, -- 账期天数,30/60/90 status TINYINT DEFAULT 1 -- 1合作中 0已停用 ); -- 物料表:单位影响库存精度 CREATE TABLE material ( id BIGINT PRIMARY KEY, sku VARCHAR(64) UNIQUE, name VARCHAR(128), unit VARCHAR(16), -- 件/箱/千克 safe_qty INT DEFAULT 0 -- 安全库存,触发补货 ); -- 采购单:状态机是流程图的骨架 CREATE TABLE purchase_order ( id BIGINT PRIMARY KEY, supplier_id BIGINT, status VARCHAR(16), -- draft/submitted/approved/received/closed total_amount DECIMAL(14,2), created_at DATETIME ); -- 入库单:一次收货对应一条 CREATE TABLE inbound_order ( id BIGINT PRIMARY KEY, po_id BIGINT, material_id BIGINT, qty INT, inbound_at DATETIME ); -- 库存流水:只追加,不修改 CREATE TABLE stock_flow ( id BIGINT PRIMARY KEY, material_id BIGINT, change_qty INT, -- 正数入库,负数出库 ref_type VARCHAR(16), -- inbound/outbound/adjust ref_id BIGINT, created_at DATETIME );逻辑说明:purchase_order.status直接对应流程图里的审批节点,stock_flow用ref_type + ref_id反查来源单据,保证每一笔库存变动都有据可查。参数上,settle_cycle决定应付账款的到期日计算,safe_qty是补货提醒的阈值,这两个字段在流程图里通常被画成菱形判断框,落到代码里就是两个数值比较。
2.2 状态机怎么和流程图节点一一对应
流程图里的箭头,本质是状态迁移。采购单从 draft 到 submitted 是提交动作,submitted 到 approved 是审批动作,approved 到 received 是收货动作。每个迁移都要校验前置条件:没有审批不能收货,收货数量不能超过采购数量。常见做法是把迁移规则写在一张配置表里,而不是散落在 if-else 中。
# 状态迁移规则:from_status -> to_status 允许的动作 TRANSITIONS = { ("draft", "submitted"): "submit", ("submitted", "approved"): "approve", ("approved", "received"): "receive", ("received", "closed"): "close", } def can_transition(cur, nxt): return (cur, nxt) in TRANSITIONS def receive(po, inbound_qty): # 收货前必须已审批,且累计收货不超采购量 if po.status != "approved": raise Exception("未审批不可收货") if po.received_qty + inbound_qty > po.total_qty: raise Exception("超量收货") po.received_qty += inbound_qty po.status = "received" if po.received_qty == po.total_qty else "approved"逻辑说明:TRANSITIONS字典把流程图上的箭头变成了可校验的规则,新增节点只改配置不改主流程。receive函数里的两个判断,对应流程图里收货节点前的两个菱形。参数received_qty需要单独加字段维护,不能靠入库单实时汇总,否则并发收货时会算错。
2.3 角色权限:谁在流程图的哪个泳道
流程图通常按泳道划分角色:采购员发起、主管审批、仓管收货、财务对账。系统里对应的是角色-动作映射。不要用硬编码判断用户名,而是用角色表加权限点。常见做法是每个状态迁移绑定一个权限码,比如po:approve只有主管角色拥有。这样流程图改泳道时,只调权限配置即可。
3. 操作流程落地:从采购申请到入库对账的完整链路
数据模型定好之后,接下来是把流程图上的每一步变成可执行的接口和页面。这一章按时间顺序走一遍完整链路,每一步给出关键参数和校验点。
3.1 采购申请提交:必填字段与校验规则
采购申请是流程起点。流程图里通常画成「填写申请单 → 提交审批」。系统实现时,提交动作要校验:供应商必须处于合作中、物料必须启用、数量必须大于零、申请人必须有该物料的申请权限。这些校验如果漏掉,后面审批环节就会收到脏数据。
def submit_purchase_order(applicant, supplier_id, items): supplier = get_supplier(supplier_id) if supplier.status != 1: raise Exception("供应商已停用") if not items: raise Exception("采购明细为空") for it in items: mat = get_material(it["material_id"]) if mat is None: raise Exception("物料不存在") if it["qty"] <= 0: raise Exception("数量必须大于零") po = create_po(supplier_id, items, status="submitted") notify_approver(po) # 推给审批人 return po逻辑说明:submit_purchase_order把流程图里提交节点的所有判断集中在一处,避免校验散落。notify_approver是流程推进的关键,没有通知机制,单据会卡在 submitted 状态无人处理。参数items是明细列表,每项含物料和数量,对应流程图里申请单的表格区域。
3.2 审批流转:会签、或签与超时自动处理
审批节点是流程图里最容易画得复杂的地方。常见有会签(所有人都同意)和或签(一人同意即可)。系统实现时,审批任务表要记录每个审批人的状态。超时处理是血泪经验:没有超时机制,单据会永远挂着。一般做法是配置超时小时数,定时任务扫描后自动通过或驳回。
-- 审批任务表 CREATE TABLE approval_task ( id BIGINT PRIMARY KEY, po_id BIGINT, approver_id BIGINT, mode VARCHAR(8), -- all=会签 any=或签 status VARCHAR(8), -- pending/approved/rejected expire_at DATETIME -- 超时时间 );逻辑说明:mode字段区分会签和或签,expire_at驱动定时任务。查询待办时按approver_id + status='pending'过滤。参数expire_at建议按工作日计算,跳过周末,否则周一早上会集中超时。
3.3 收货入库:数量差异与质检分支
收货节点在流程图里通常有分支:合格入库、不合格退货、部分收货。系统实现时,入库单要记录实收数量,和采购数量比对产生差异。差异超过阈值时触发质检流程。这一步的坑在于:库存流水必须和入库单在同一个事务里写入,否则会出现单据成功但库存没加的玄学问题。
def confirm_inbound(po_id, material_id, qty, qualified=True): with db.transaction(): if not qualified: create_return_order(po_id, material_id, qty) return inbound = create_inbound(po_id, material_id, qty) add_stock_flow(material_id, qty, "inbound", inbound.id) update_po_received(po_id, qty)逻辑说明:事务保证入库单和库存流水同时成功或同时失败。qualified参数对应流程图里的质检菱形。update_po_received累加已收数量并判断是否关闭采购单。
3.4 对账结算:账期计算与差异挂账
对账是流程终点。财务根据入库单和供应商账期生成应付账款。账期计算从入库日或对账日起算,两种口径要在系统里明确配置。差异挂账是指发票金额和入库金额不一致时,差额单独记录,不直接冲销。这一步的后悔药是:所有对账操作要留操作日志,否则月底对不上账时无从查起。
4. 流程落地最容易翻车的五个地方
4.1 库存并发扣减导致超卖
现象:两个出库单同时读取库存为 10,各自扣 8,最终库存变成 -6。原因:读-改-写不是原子操作。解决:用数据库行锁或乐观锁版本号,扣减时校验version或qty >= 扣减量。
4.2 状态机漏配迁移导致单据卡死
现象:采购单审批通过后无法收货,页面报「状态不允许」。原因:approved -> received的迁移规则没配,或者权限码没给仓管角色。解决:把迁移规则和权限码做成配置表,上线前用脚本遍历所有状态组合做校验。
4.3 账期起算日口径不一致
现象:财务算出的应付日期和采购算的差半个月。原因:一个按入库日算,一个按对账日算。解决:在供应商表加settle_base字段,明确inbound或statement,全系统统一读取。
4.4 入库单和库存流水不同事务
现象:入库单创建成功,但库存没增加,盘点时对不上。原因:两个写操作分开提交,中间抛异常。解决:强制放在同一事务,或者用本地消息表做最终一致。
4.5 审批超时无处理导致流程积压
现象:待办列表越堆越多,单据永远停在 submitted。原因:没有超时扫描任务。解决:定时任务每分钟扫描expire_at < now()的 pending 任务,按配置自动通过或驳回,并记录系统操作日志。
5. 用流程图反推测试用例:一个可复用的验证技巧
流程图不只是给人看的,它还是测试用例的天然来源。我的习惯是:每一条箭头至少对应一个正向用例和一个反向用例。正向是合法迁移,反向是非法迁移必须被拦截。这样覆盖率能到九成以上,比拍脑袋写用例靠谱得多。
具体做法是先把状态迁移表导出成 CSV,两列:from、to。然后用脚本生成测试矩阵,合法组合断言成功,非法组合断言抛异常。
import csv def gen_cases(path): cases = [] with open(path) as f: for row in csv.DictReader(f): cases.append((row["from"], row["to"], row["legal"] == "1")) return cases def run_cases(cases): for frm, to, legal in cases: po = make_po(status=frm) try: transition(po, to) assert legal, f"非法迁移 {frm}->{to} 未被拦截" except Exception: assert not legal, f"合法迁移 {frm}->{to} 被误拦"逻辑说明:gen_cases从迁移表读用例,run_cases对每个组合构造单据并尝试迁移。legal字段标记该迁移是否合法。这个脚本能在每次改状态机后快速回归,避免漏配。参数上,迁移表建议和代码里的TRANSITIONS保持同源,最好由代码生成 CSV,而不是手工维护两份。
还有一个进阶用法:把流程图里的泳道也纳入测试。每个角色对每个状态的可见性和可操作性,都可以生成权限矩阵。比如采购员不能审批、仓管不能修改采购单价。这些规则写成断言后,权限改动能被立刻发现。
最后说个我踩过的坑:曾经为了赶进度,跳过迁移表直接写 if-else,结果新增一个「部分收货」状态时,漏改了三个判断点,线上出现已关闭的采购单还能继续收货。从那以后,我坚持任何状态流转都必须走配置表,宁可多写一个加载函数,也不把规则散在业务代码里。希望帮到你。
本文还有配套的精品资源,点击获取