一开始只是想把 Frappe / ERPNext 的 Docker 环境跑顺。跑起来之后,问题就变成了另一个:如果真的要围绕 ERPNext 做一个自己的业务系统,代码应该怎么组织才不至于越写越散?
于是有了这个 myapp。它现在更像一组持续整理中的实践:后端有自定义 App 和业务网关,前端有 Web 和移动端方向,旁边还放着接口集合、HTTP 测试和一些性能记录。
为什么要加一层网关
myapp 是一个基于 Frappe / ERPNext 的业务系统扩展。它没有直接让前端散落调用 ERPNext 原生接口,而是用 myapp.api.gateway.* 组织出一层更稳定的业务网关。
这层网关覆盖了商品、客户、销售、采购、供应商、结算、报表、媒体上传和移动端版本信息等能力。
这样做的价值在于,前端看到的是业务动作,而不是 ERPNext 里面更底层的 DocType 细节:
- 前端面对的是业务语义,而不是 ERPNext 的底层 DocType 细节
- 错误码、响应格式和权限处理可以统一
- 销售、采购等主链路可以围绕幂等和真实 HTTP 测试做回归
- 后续替换图片存储、打印服务或移动端能力时,接口契约更稳定
现在的结构
从目录和文档看,项目大概分成三块:
apps/myapp:自定义 Frappe App,放业务接口和测试frontend/myapp-web:Web 管理端,基于 React、Umi Max、Ant Design Profrontend/myapp-mobile:移动端,基于 Expo、React Native、expo-router
这让我比较在意的一点是:它不是只停留在后台配置页面,而是开始往“业务现场怎么用”这个方向走。比如移动端依赖里已经出现了相机、图片、打印、PDF、图表这些能力,这些都更接近收货、上传、查看和现场处理。
接口怎么组织
文档里把接口按业务域组织,而不是按“原生接口 / 自定义接口”划分。这一点很重要,因为调用方真正关心的是“销售要调哪些接口”“采购要调哪些接口”“报表要调哪些接口”。
当前网关包含这些方向:
- 商品搜索、商品创建、商品详情、图片上传
- 客户与供应商主数据
- 销售订单、发货、开票、收款、退货
- 采购订单、收货、采购发票、供应商付款、采购退货
- 经营总览、销售分析、采购分析、应收应付、资金流水
- 移动端版本信息与认证
接口返回也统一成类似这样的包络:
{ "ok": true, "status": "success", "code": "ORDER_CREATED", "message": "业务提示信息", "data": {}, "meta": {}}错误响应也做了统一错误码,例如认证、权限、资源不存在、库存不足、参数校验失败等。这个细节很容易被忽略,但对前端开发很友好:不用在每个页面里猜后端到底抛了什么异常。
采购链路里一个值得记的点
采购模块的设计文档比较完整。它把采购拆成:
- 创建采购订单
- 按实际到货生成采购收货单
- 按实际收货生成采购发票
- 供应商付款登记
- 采购退货
这里有一个关键设计原则:采购订单表示“预期采购”,真正库存入账以 Purchase Receipt 为准。也就是说,如果供应商实际到货数量和订单数量不一致,系统应该允许按实收数量收货和结算。
这比“采购订单一建就默认全部到货”的实现更接近真实业务。以后如果单独写采购模块,这个点值得展开讲。
测试体系
项目文档强调优先使用 HTTP 测试,而不是在宿主机里直接导入 Frappe 服务层。
原因是 HTTP 测试更接近真实调用路径,可以覆盖:
- 鉴权
- 权限
- 路由
- 响应包装
- 真实主数据
- devcontainer 网络环境
文档中记录了多组测试:
- 销售与采购主链路
- 商品工作台与销售状态聚合
- 采购快捷链路
- 幂等、并发和不同数据重放
- 单位换算与库存结算回归
- 性能基线脚本
这部分我觉得很值得继续保留。很多项目写到后面乱,不只是代码问题,也是缺少一套能确认“这次改动没有把主链路弄坏”的方法。
接下来想补什么
这篇先把轮廓记下来。后面更值得写的是这些具体问题:
- Frappe / ERPNext 自定义业务网关设计
- 采购链路如何处理“订单数量”和“实际到货”的差异
- 移动端如何对接 ERPNext 业务接口
- 商品图片上传、临时文件绑定和清理策略
- HTTP 测试如何覆盖 ERPNext 自定义接口
目前最应该补的,是截图和一条完整业务链路的可视化流程图。只有文字会有点干,等把图补上,这个项目才会更像一篇可以回看的博客文章。