Commit Graph

124 Commits

Author SHA1 Message Date
文睿 张
062abcb3d0 物料备注放宽到 500 字,补回被截断的两条备注
- scripts/init.sql:materials.remark 由 VARCHAR(200) 改为 VARCHAR(500);并从
  源 SQLite 库补回武汉 B010059、B010076 被截断的完整备注(222 字,此前只落库
  前 200 字,结尾断在 &upStre)
- 后端:maxMaterialRemarkLength 与错误文案改为 500,Excel 模板填写说明同步
- 前端:物料表单备注输入框 maxlength 与提交前校验改为 500
- 文档:api.md、数据库表结构与关系说明、后端结构说明同步;并补充说明默认用户
  由后端启动时创建,重建数据库后重启后端即可恢复
2026-10-14 17:05:37 +08:00
文睿 张
18df4f48e4 修复 21 个测试与代码脱节导致的既有失败
go test ./... 从 21 个失败回到 0。根因都是测试没跟上代码改动,其中两处
被「自动补位」的补丁 hack 掩盖住了:

- handler 的 materialRow 在「列数 20、值 18」时自动插两个 nil,掩盖了
  materials 新增 supplier_id/manufacturer_id 后的列错位。它碰巧补对位置,
  而 order 测试的 activeMaterialRows 没走这个 helper,直接 panic。
  已删掉补丁、把测试数据补齐到 20 列。
- 导入测试的 buildTestWorkbookWithHeaders 按 7 列给数据补位,而表头这时
  已经扩到 9 列(多了供应商、制造商),把「大类/小类」静默塞进了
  「来源/备注」。已按 materialImportHeaders 的实际列序修正补位。

其余为非补丁式的期望过时:materials 的 INSERT 参数补到 15 个、物料列表
查询结果集补到 20 列、导入模板表头断言改为按 materialImportHeaders 取末列
而不是写死下标。

顺带清掉已废弃的升级路径残留:upgrades/ 目录在 85525c97 已删除,增量升级
不再使用,因此删除 scripts/sync-company-integrity.ps1(把 checks SQL 嵌入
upgrade SQL 的生成器)与它的测试,application.go 里指向 upgrades 的错误
文案改为只提 init.sql。
2026-10-14 16:27:18 +08:00
文睿 张
3cc783b5ff 物料数据迁移,并让每个公司自带默认单位与仓库
数据迁移(北京 / 武汉两个 SQLite 物料库 → wmms)
- 北京进默认组织、武汉单独建组织:两套分类编码完全相同但含义不同(北京 A01=标准件,
  武汉 A01=机加工件),共存会撞 material_categories 的组织内编码唯一约束
- 199 条物料、37 个企业、45 条变更日志,以及各分类的 code_rules.next_sequence
  (对齐到已导入的最大序号 +1,否则用户新增物料会撞上已有编码)
- 迁移段并入 scripts/init.sql 末尾,空库初始化即得完整数据

公司默认数据
- 新建公司时种入 32 个物料单位 + 默认仓库 + 主库位,与建公司同事务,
  种一半失败会整体回滚(否则留下一个没单位、又占着公司编码的组织)
- 单位在后端按公司隔离(MaterialRepo.IsActiveUnit 要求物料引用的单位属于本公司),
  此前新建的公司连单位下拉都是空的,物料的 base_unit_id 也无处可指
- init.sql 的单位段补齐「块」「Pcs」,与代码里的清单保持逐条一致

默认组织更名:默认公司组织 → 北京
2026-10-14 16:05:36 +08:00
文睿 张
85525c97a0 合并物料功能与初始化 SQL 2026-10-14 11:39:12 +08:00
文睿 张
9c9ea5c62e Merge remote-tracking branch 'origin/feature/material-bulk-import' into dev 2026-10-13 17:29:15 +08:00
文睿 张
f65e459eef 补充物料重复检查样例 2026-10-13 16:58:01 +08:00
文睿 张
a27a318e8c 补充厂家型号字段说明 2026-10-13 16:00:23 +08:00
文睿 张
09bfd0e105 修复物料伙伴选项和空值处理 2026-10-13 15:58:30 +08:00
文睿 张
1474b4d066 功能:完善物料导入与合作伙伴管理 2026-10-13 15:20:29 +08:00
文睿 张
e4f5bf7530 Merge branch 'feature/material-bulk-import' into dev 2026-10-12 17:30:13 +08:00
文睿 张
44ef533aa0 Merge remote-tracking branch 'origin/dev' into dev 2026-10-12 17:28:50 +08:00
文睿 张
4c274804e0 chore: stop tracking server executable 2026-10-12 17:23:11 +08:00
文睿 张
b6035976ec Merge origin/dev into feature/material-bulk-import: complete v1 2026-10-12 17:03:03 +08:00
文睿 张
62372abeb6 fix(material-import): 导入上限下调为 1MB/10000 行,同步提示、文档与测试 2026-10-12 16:51:58 +08:00
文睿 张
d864294dde feat(material-import): 完善导入模板填写说明页,同步接口、计划与回归用例 2026-10-12 15:41:21 +08:00
文睿 张
ec293fa8b2 fix: 校验物料名称和规格长度 2026-10-12 15:37:54 +08:00
文睿 张
bc1352b918 docs: 标注导入记录表只写不读,留作后续入口 2026-10-12 11:56:51 +08:00
文睿 张
8d195c2d51 fix(material-import): 导入落库的单位统一写编码,与单条新增一致
模板里填单位名称(如「千克」)时原本把名称原样存进 materials.unit,而单条新增
经 syncUnit 提交的是单位编码 kg。同一个单位按录入路径留下两种写法,库存页直接
显示该字段(Stock.vue 的 unit 列)会出现「千克」与「kg」并存。

- material_import.go:Unit 一律取匹配到的单位 Code
- 补回归用例:模板填名称、填编码两条路径都断言落库为 kg
- 同步计划文档的代码与测试片段、设计约定 4 的单位一行
- 订正 api.md 中 unit 字段「单位名称」的错误描述(单条新增提交的本就是编码)
2026-10-12 11:51:44 +08:00
文睿 张
0ddda5363e fix(material-import): 完善批量导入异常提示,仅保存成功历史,补齐审计日志名称、编码、详情及物料快照。上传解析前限制请求大小,逐行读取提前拦截超限数据,保留空行和真实行号规则。补充回归测试,同步计划、接口说明及八条人工用例。 2026-10-12 11:37:37 +08:00
文睿 张
2e526be3fb docs: 计划文档同步物料导入的分类别名匹配与测试片段
计划里的代码片段落后于实现:分类匹配后来支持了「编码 名称」写法、纯编码与空白
归一化(f634e7cf、3c75537f 两个修复提交只改了代码和 docs/api.md,没回写计划)。

- Task 5 的实现与测试片段同步为实际代码,补 expectImportPersist 与 4 个新用例
- Task 2 模板「填写说明」文案补上「或编码」
- Task 3 测试块补 materialCategoryPtr 定义,insertMaterialBatchStmt 收进代码块
- 修正测试数量断言(7 个函数、9 个用例)
- 设计约定与校验规则表补上分类可按名称/编码/「编码 名称」匹配、匹配前归一化空白
2026-10-10 18:25:56 +08:00
文睿 张
3c75537f54 fix: 物料导入分类名归一化空白,兼容全角空格与 NBSP
界面上的分类显示名由前端拼成「编码 + 半角空格 + 名称」(U+0020),用户照抄进模板
时,中文输入法全角模式敲出的空格是 U+3000、从网页复制偶尔带 U+00A0。几串肉眼
一模一样、码点不同,精确匹配落空,于是出现「浏览器复制的能导入、自己手写的报
不存在」——分类名一个字没差,差的是那个看不见的空格。

- 匹配前用 normalizeWhitespace 把各种空白(半角、全角、NBSP、制表符)压成单个
  半角空格并去首尾;索引键与查询值同口径归一化,两边一致
- 只填空白的单元格现在报「大类/小类不能为空」,而不是「不存在或已停用」——它本来
  就是空的

验证:新增表驱动用例覆盖 3 种变体(全角空格、不换行空格、连续半角空格),修复前
3 个全部失败、修复后全部通过;go build ./...、go vet ./internal/...、
go test ./... 全部通过。
2026-10-10 17:44:29 +08:00
文睿 张
ec7742a39c chore: 编译产物不再入库,启动脚本改用 server.exe
- server.exe 早已写在 .gitignore 第 9 行,却仍被追踪,规则一直没生效(.gitignore
  只管未被追踪的文件)。git rm --cached 移出索引,本地文件保留
- 启动项目.bat 改为启动前先 go build 重建再运行 server.exe,编译失败就停住不启动:
  原来用 go run 正是为了不跑到过期的 exe,换成 exe 后得靠这一步补上
2026-10-10 17:32:30 +08:00
文睿 张
f634e7cf07 fix: 物料导入分类匹配兼容界面上的「编码 名称」写法
界面上的分类一律显示成「编码 名称」(如 A 机械结构类),用户照此填进导入模板,
却报「大类「A 机械结构类」不存在或已停用」。分类其实存在且已启用,是后端只按
分类名称精确匹配,对不上带编码前缀的写法。单位早有名称/编码双匹配,分类漏了。

- 分类索引同时登记名称、编码、「编码 名称」三种写法。名称优先、键已占用时不覆盖,
  结果不随分类遍历顺序变化;停用分类仍在登记前被过滤,放宽的只是写法
- 报错文案补「请核对分类名称或编码」:原文案说「不存在或已停用」,而分类明明在,
  把排查方向带偏了
- 模板「填写说明」与 api.md 同步口径(原文写的是「分类按名称填写」)

验证:2 条新用例先跑成失败再转绿(「A 机械结构类」+「A01 标准件」、纯编码);
另加 1 条停用分类的边界用例,并做变异验证——临时关掉 status 过滤后它如期失败。
go build ./...、go vet ./internal/...、go test ./... 全部通过。
2026-10-10 17:32:15 +08:00
文睿 张
e3ab3a094a docs: 补充文档覆盖范围中的物料批量导入说明
356c8520 提交接口文档时漏掉的一行,随 Task 10 收尾补上。
2026-10-10 17:04:56 +08:00
文睿 张
356c8520ca docs: 补充物料批量导入接口说明
- 覆盖范围表补一行分组入口,并注明已在 §1 展开(该表标题写的是「未展开」)
- 「1. 物料接口」末尾补 GET /material-import/template 与 POST /material-import:
  模板的两张工作表与 5 列定义、按列名解析的规则、逐行校验表、成功与失败的响应
  示例、row 是 Excel 真实行号、5MB 与 20000 行限制、任意一行失败整批不入库、
  导入记录只留汇总不落逐行明细
- 状态码旁列出真实的提示文案(含后端返回的原文),便于与响应逐字对照
2026-10-10 16:41:40 +08:00
文睿 张
2f0d978dbf docs: 修正计划 Task 9 片段的 mock 路径与断言
- 路径笔误:vi.mock('../../api/materials') 改成 '../api/materials'。测试文件在
  src/views/ 下,相对它是一级上跳,原路径会指向仓库根的 api/ 目录
- 补上 materialsApi 替身的具体两行代码,原来只有文字描述、照抄不了
- 两个用例在触发导入前加 fetchMaterials.mockClear():页面 onMounted 就会拉一次
  列表,不清的话失败用例的 not.toHaveBeenCalled() 必然失败,成功用例的断言也没区分度
- 成功用例的断言从 toHaveBeenCalled() 收紧成 toHaveBeenCalledWith(1, '', 'all')
- 两个用例包进 describe('批量导入'),并给出 beforeEach 里重置替身的写法

验证:从 Task 9 之前的测试文件出发,按文档插入替身、追加用例块,实跑 24 个用例通过。
2026-10-10 16:31:39 +08:00
文睿 张
7f2b296339 feat: 物料页面接入批量导入与模板下载
- 顶部加「下载模板」「批量导入」两个按钮和隐藏的 xlsx 文件输入
- 上传走保存互斥,飞行期间禁止切换公司;importing 标志挡住重复选文件
- 发起请求前清空 input.value,否则连续选同一个文件不会再触发 change
- 校验失败(400 且 data 带 errors)弹结果弹窗,其余错误走兜底提示
- 成功后刷新到第一页并提示导入条数

测试里挂载后先把 fetchMaterials mockClear 掉:onMounted 已经拉过一次列表,
不清空的话「未被调用」必然失败、成功用例的断言也没有区分度;成功那条改成断言
具体的 (1, '', 'all') 参数。
2026-10-10 16:30:27 +08:00
文睿 张
326cf77010 docs: 计划 Task 8 的组件测试片段补上 el-table 渲染时序
原片段用同步的 mountResult 直接断言 tbody tr 的文本,但 el-table 分两轮渲染:
先注册列,下一轮才把单元格填上。只等一个 tick 时拿到的是空 tr,断言会以
"expected '' to contain '2'" 这种看不出原因的方式失败(实测撞到过)。

改成 async mountResult,内部 await 两轮 nextTick 并附上原因;三个用例跟着
改成 await 调用,导出那条也复用 mountResult 传 provide,不再内联 mount。
2026-10-10 16:25:53 +08:00
文睿 张
c3835fb28d feat: 物料导入结果弹窗组件
- 摘要条按成败两种文案;失败时展示逐行错误表格、分页与导出按钮
- 分页复用现成的 BasePagination,每页 20 行
- 导出走 exportCsv,文件名带本地时间后缀
- downloadCsv 经 inject 注入,测试里可替换掉真实下载动作
- 测试等两轮 nextTick 再断言表格内容:el-table 先注册列、下一轮才填单元格,
  只等一个 tick 拿到的是空 tr,断言会以看不出原因的方式失败
2026-10-10 16:24:19 +08:00
文睿 张
f5e9029c46 docs: 修正「导入必须用独立前缀」的错误论断
实测 gin v1.9.1 允许静态段与 :id 在同一层级共存:探针测了 POST/GET 的单级与
两级共 5 种组合,把 /materials/import 放进现成的 materials 组全都不会 panic。

路由本身保持 /material-import 不变——独立成前缀是命名与分组上的选择(导入是
含模板下载与上传入库的一条链路,也避免 /materials/import 被读成物料 id),
不是 gin 的路由限制。计划文档同步更正。

顺带把计划 Task 6 Step 7 的验证方式从 go build 改成跑路由测试:go build 只做
编译、不执行 RegisterRoutes,注册期的 panic 它兜不住。
2026-10-10 16:18:02 +08:00
copper-xw
9c78dcb6db feat: 支持前端 go:embed 单容器部署
新增部署专用 Dockerfile.deploy / docker-compose.deploy.yml 与本机构建脚本:
前端 dist 经 go:embed 编入 Go 二进制,alpine 运行时只打包不编译,
旧 Dockerfile 与双容器编排保持不变。
2026-10-10 16:14:49 +08:00
文睿 张
8a61186cfd docs: 计划 Task 7 片段的 BOM 改成转义写法
内联的零宽字符在编辑器里看不见也改不动,写文件时极易悄悄落成真字符——实现这个
Task 的过程中在源码、提交信息、记忆文件里各踩了一次。改成 JS 转义写法后源码可见。

片段同步为已提交的实现与测试版本:测试引入 BOM 常量,实现片段注释也对齐。
把文档里的两个片段抽出来覆盖真实文件实跑,2 个用例通过。
2026-10-10 16:10:53 +08:00
文睿 张
444c2ed1af feat: 物料导入前端接口与 CSV 导出工具
- materialsApi 增加 importFile(silent,校验明细由页面弹窗展示)与
  downloadImportTemplate(走原生 fetch,响应是文件流)
- 下载接口绕开 axios 拦截器,自行携带令牌与当前公司头
- 新增 exportCsv:buildCsv 带 UTF-8 BOM、按 RFC 4180 转义;downloadCsv 触发下载
- BOM 不用内联零宽字符,改用 JS 转义序列写法,源码里可见可改
2026-10-10 16:02:31 +08:00
文睿 张
7b926ff60a feat: 物料导入与模板下载接口
- 新增 response.ErrorWithData:校验失败要把逐行明细一起带回,不能只给一句话
- 新增 GET /api/material-import/template 与 POST /api/material-import
- 路由挂在独立前缀 /material-import:materials 组已有 GET /:id,gin 的路由树
  不允许同一段既有静态前缀又有通配参数
- 权限沿用物料新增的口径:登录 + 公司头校验,不额外要求 super_admin
- 模板随代码生成不落盘,下载到的永远与当前校验规则一致
2026-10-10 15:46:57 +08:00
文睿 张
f34803e1a2 docs: 修正物料导入计划中 Task 5/6 的测试片段笔误
- Task 5:expectImportLog 的行数参数显式转 int64。database/sql 会把实参归一成
  driver.Value(int→int64),sqlmock 按类型比对,传 Go int 必然匹配不上
- Task 5:expectImportLog 补 fileName 参数,模板非法那条用例传的文件名与其它用例不同
- Task 5:事务内 SQL 的期望顺序改为「推进 code_rules → 分批 INSERT」,
  与已提交的 ImportTx 实现(material.go:480 在 :485 之前)一致
- Task 6:测试片段补上缺失的 strings import

按修正后的片段替换 internal/service/material_import_test.go 实跑,5 个用例全通过。
2026-10-10 15:42:06 +08:00
文睿 张
e853846070 feat: 物料导入校验与事务入库编排
- 新增 MaterialImportService.Import:解析 → 逐行校验 → 事务入库 → 写导入记录
- 校验覆盖名称/规格长度、大类小类归属、单位名称或编码匹配、小类编码规则存在性
- 同一小类的规则只查一次,避免批量行数放大成逐行往返
- 校验失败整批不入库并返回逐行明细;入库失败整体回滚
- 导入记录成功失败都写,失败原因只存前 5 行行号摘要,明细不落库
2026-10-10 15:33:13 +08:00
文睿 张
0e3b1735a5 feat: 物料导入记录仓储 2026-10-10 15:20:18 +08:00
文睿 张
f3146af838 feat: 物料批量入库的编码分配与事务插入 2026-10-10 15:13:18 +08:00
文睿 张
4960a88497 feat: 物料导入模板生成与 xlsx 解析 2026-10-10 14:57:56 +08:00
文睿 张
84e7f4d7d0 feat: 新增物料导入记录表与模型 2026-10-10 14:56:42 +08:00
文睿 张
616a4a3b1d feat: 物料增加初始单位,补充物料批量上传计划
- 物料默认单位由 pcs 改为「个」,新建/编辑表单与后端 Create 保持一致
- 单位下拉增加未选择时的默认提示
- init.sql 补充 30 个常用计量单位种子数据
- init.sql 新增 material_import_logs 表,为批量导入提供落库
- 新增物料批量导入实施计划文档,相关测试期望值同步更新
2026-10-10 14:15:49 +08:00
文睿 张
8dd0427adb feat: support customer and supplier role selection for partners 2026-10-10 10:47:12 +08:00
文睿 张
1c316d0105 回归测试用例 2026-10-09 18:18:58 +08:00
文睿 张
b24bb25553 Merge remote-tracking branch 'origin/feature/company-isolation' into feature/company-isolation 2026-10-09 16:38:54 +08:00
文睿 张
2a6a3c6bba docs: 补充后端结构说明并更新公司隔离进度
- 新增《项目后端结构说明》,梳理仓库布局、internal 分层与请求链路
- 《数据库表结构与关系说明》新增第 11 节,记录公司隔离发布后的表、约束与升级阻断规则
- 公司隔离计划补充精简版测试策略,并勾选 Task 2、Task 8 完成项与验收记录
2026-10-09 15:55:52 +08:00
文睿 张
ef4e68b1bd docs: document company isolation rollout and acceptance 2026-10-09 15:54:20 +08:00
文睿 张
dff5420a31 fix: 物料图片上传纳入保存互斥 2026-10-09 14:34:43 +08:00
文睿 张
89368ba3f8 fix: 补齐详情加载的上下文校验与保存互斥
- 入出库详情加载提交前校验公司 ID 与上下文版本,旧公司响应静默丢弃
- 新增 runWithSaving 包裹器,仓库、伙伴、基础配置等直接调接口的页面纳入保存互斥
- 切换守卫卸载时仅撤销自己注册的那一份
2026-10-09 14:25:46 +08:00
文睿 张
3674076377 chore: 忽略编辑器本地历史目录 2026-10-09 14:19:54 +08:00
文睿 张
fafbadef0c chore: 将后端启动文件注释翻译为中文 2026-10-09 14:19:18 +08:00