Amazon Operations Automation
Amazon 发货计划生成
围绕数量守恒建立发货计划:每个 SKU 都能解释需求、库存上限、运输拆分和最终去向。
Python · openpyxl · YAML · Validation
打开演示这个项目可以从一道很小的数量题讲起:某个 SKU 需要 42 件,目标市场实际可用 38 件,那么本次最多只能发 38 件;接下来无论怎样拆运输方式,加总也必须还是 38。
真正的工具就是把这道题可靠地应用到整批数据,并在写入目标模板后重新证明答案没有变。
我的方法是先把业务语言转换成一组不变量,再围绕不变量组织读取、匹配、计算、分配和校验。只要这些关系能够在单行、整批和最终工作簿三个层面同时成立,模板怎样变化都不会改变计划的核心正确性。
先看一行,而不是先看架构
整套实现围绕这条可解释关系展开。目标市场没有库存时不会借用其他市场;计划量为空时按明确规则处理;任何负数、小数或无法解释的文本都会进入异常队列。
这一行同时展示了三种不同含义:需求是期望,库存是硬上限,运输拆分是执行方案。它们不能被混成一个“建议数量”。先区分语义,才能判断哪个值可以调整、哪个值必须阻断,以及最终应该怎样解释少发的原因。
示例中需求 42、库存 38,所以实际可发为 38;这不是算法替人降低目标,而是显式承认库存约束。之后 Route A 与 Route B 只是在 38 之内重新分配,任何拆分都不能重新创造库存。
| 字段 | 示例 |
|---|---|
| 明确输入 | DEMO-A01 / 需求 42 / 可用库存 38 |
| 实际可发 | min(42, 38) = 38 |
| 运输分配 | Route A 22 + Route B 16 = 38 |
| 最终判断 | 需求被库存截断,但数量守恒通过 |
把一行计算扩展成一批可靠结果
- 01
锁定范围
读取明确传入的 SKU 集合,去除完全重复项但保留用户顺序与来源行;范围之外的数据即使存在库存也不会自动加入。
- 02
站点隔离
在建立任何索引之前先过滤目标市场,使其他站点记录从计算空间中消失;目标站点缺失时明确报错,禁止跨市场回退。
- 03
精确关联
使用规范化后的 SKU 唯一键连接需求与库存,并分别识别零命中和多命中;产品标题、相似编号或前缀不会参与猜测。
- 04
计算上限
把需求与可用库存解释成非负整数,实际可发量取两者最小值;缺失、负数、小数和异常文本进入带来源信息的复核队列。
- 05
分配数量
按照配置的运输优先级逐步消耗实际可发量,每个通道受到自身额度约束,最后保留未分配余量作为显式异常。
- 06
回读检查
生成后重新读取审批与发货工作簿,逐行验证库存上限和运输守恒,再核对两份文件的 SKU 集合与批次总量。
代码里最值得保留的是这些不变量
模板列名和位置会变化,所以映射放在 YAML;上面的数量关系不会随模板变化,因此由校验器持续守住。把“会变的格式”和“不该变的规则”分开,是这次实现里最关键的取舍。
不变量还承担沟通作用。发生差异时,报告不是简单提示“数值不一致”,而是说明哪一行违反了哪个关系:需求超过库存属于正常截断,运输合计小于可发量属于分配未完成,两份文件总量不同则属于交付失败。不同错误因此获得不同处理路径。
shippable = min(requested, available)route_a + route_b == shippableapproval_skus == shipment_skusapproval_total == shipment_total宁可暴露缺失,也不聪明地猜一个相似 SKU
发货计划里的标识错误具有放大效应:一旦库存关联到相似但错误的 SKU,后面的可发量、运输拆分和两张表都会在错误基础上保持“看似一致”。因此关联策略选择唯一键精确匹配,而不是名称相似度或模糊回退。
找不到记录、找到多条记录和跨站点命中都属于不同异常。它们不会被统一填成 0,因为 0 既可能表示真实缺货,也可能掩盖数据缺失。
精确匹配牺牲了一部分表面上的自动完成率,却提高了结果可信度。运营工具最危险的不是停下来,而是在错误关联后继续顺利生成一份看起来完整的表格。把未知暴露出来,是比提高命中率更重要的设计目标。
| 异常 | 为什么不能静默处理 |
|---|---|
| 库存记录缺失 | 无法区分真实零库存与数据未同步,应进入复核。 |
| 同一 SKU 重复 | 无法确定哪条库存有效,继续计算会制造任意答案。 |
| 只在其他站点存在 | 跨市场借值会破坏站点隔离,必须明确阻断。 |
| 数量为负数、小数或文本 | 输入语义不明确,不能通过强制转换进入正式计划。 |
运输分配不是填两个数字,而是受约束的消耗过程
实际可发量先由需求和可用库存共同决定,然后再按照配置顺序消耗运输通道额度。每一次分配都记录剩余量,最后要求所有通道加总重新等于实际可发量。
这样设计的好处是,运输方式增加或优先级改变时,只调整分配策略,不改变库存上限与数量守恒这两个核心规则。
分配结果还保留计算依据:每个通道分到了多少、受到哪个额度限制、分配后还剩多少。这样当结果不符合业务预期时,可以讨论运输优先级或额度配置,而不是怀疑库存和需求是否在中途被改变。
shippable = min(requested, available)remaining = shippableroute_a = min(remaining, route_a_limit)remaining -= route_aroute_b = remainingassert route_a + route_b == shippable计算正确还不够,写进模板后要再证明一次
内存中的结果通过校验,不代表 Excel 交付物一定正确。列映射、公式、工作表范围和模板版本都可能在写入阶段引入新错误,所以生成后会重新打开文件,从最终交付物读取 SKU、数量和合计。
校验关注两个层面:单行满足库存上限与运输守恒,整批满足两份输出的 SKU 集合和总量一致。只有最终文件能重新证明这些关系,本次计划才完成。
回读过程使用与写入不同的读取路径,避免只验证程序内存里的同一份对象。它会检查目标单元格是否真正落值、公式是否覆盖预期行、空白尾行是否被误计入,以及模板中的合计与重新计算结果是否一致。
整批结果要同时说明成功、截断与异常
一份可用计划不能只输出成功行。库存不足但可以部分发货、库存为零、数据缺失和格式异常具有不同业务含义,应该分别统计和展示。批次报告会给出请求总量、实际可发总量、因库存截断数量、各运输通道分配量以及需要人工处理的行数。
这份摘要让使用者先判断本批计划整体发生了什么,再下钻到具体 SKU。它也为后续比较不同批次提供稳定口径,而不是依赖人工浏览整张工作簿获得印象。
| 结果状态 | 后续动作 |
|---|---|
| 完整满足 | 按运输拆分进入正式输出。 |
| 库存截断 | 保留实际可发量,并明确记录未满足需求。 |
| 真实零库存 | 输出零可发状态,进入补货或复核队列。 |
| 数据异常 | 不参与正式合计,附来源行和异常原因。 |
| 分配不守恒 | 阻断整个批次提交,不生成可流转结果。 |
Lab 里把计算过程摊开来看
演示不再是泛化的进度条。四个示例 SKU 会逐行显示需求、库存、实际可发和运输分配,最后单独执行数量守恒检查。下载的 Excel 也保留公式,让结果可以被继续核对。
从单行计算到整批校验,每个数量的来源和去向都会在演示中逐步展开。
公开版本刻意展示一条正常满足、一条库存截断、一条零库存和一条需要复核的记录,使观众能够看到系统怎样区分业务状态,而不是只播放全部成功的理想路径。
Related Lab
查看公开流程演示
载入预设样本,按关键步骤运行,并下载对应的 Sample 结果。
打开演示