文睿 张
|
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 |
|
文睿 张
|
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 |
|
文睿 张
|
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 |
|
文睿 张
|
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 |
|
文睿 张
|
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 |
|
文睿 张
|
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 |
|
文睿 张
|
ef4e68b1bd
|
docs: document company isolation rollout and acceptance
|
2026-10-09 15:54:20 +08:00 |
|
文睿 张
|
d580efebe5
|
fix: 接线公司实时连接生命周期并钉住角色撤销语义
- organization store 接线 companySocket:切换后为当前公司重连,登出/空状态只关闭不重连
- companySocket 延迟解析 WebSocket 并静默吞掉取票/建连失败,不阻断公司切换
- authApi 新增 createWebSocketTicket(组织级请求)
- 补 store 三例接线测试:切换触发重连、登出触发关闭、空公司不连接
- 补 Go 用例钉住复核边界:纯业务角色撤销、公司授权仍在时不断流
|
2026-10-09 13:50:08 +08:00 |
|
文睿 张
|
5021b039c9
|
feat: 按公司隔离 WebSocket 订阅与事件投递
- 新增 POST /api/auth/websocket-ticket:需 JWT 与公司头,签发 30 秒有效的一次性随机票据
- /ws 握手消费票据并以数据库当前状态复核身份与公司授权,JWT 不进 URL
- Hub 注册/注销/投递选人统一由事件循环串行管理,消除 RLock 内 delete 的并发缺陷
- 事件携带 organization_id,仅投递同公司订阅者,投递前复核失败即关闭连接
- 统一广播签名为 (organizationID, action, orderID, data)
- 新增前端 companySocket 模块:按当前公司取票建连、切换/登出关旧连重连、消息校验组织与上下文版本
|
2026-10-09 13:39:45 +08:00 |
|
文睿 张
|
a1bc0539dc
|
feat: 按公司隔离物料申请与审批出库
|
2026-10-09 12:37:08 +08:00 |
|
文睿 张
|
b0cab477db
|
feat: 按公司隔离入出库单据流程
|
2026-10-09 12:21:53 +08:00 |
|
文睿 张
|
ee18a2e56f
|
fix: 修正普通审批 scope、出库更新加锁顺序与预警物料归属校验
|
2026-10-09 11:19:39 +08:00 |
|
文睿 张
|
e3cfe88d4e
|
feat: 按公司隔离库存余额与流水
|
2026-10-09 11:10:13 +08:00 |
|
文睿 张
|
970ba5ccf7
|
feat: 组织列表为每家公司补充仓库摘要
组织初始化接口 GET /api/auth/organizations 现在为每项授权公司附带
warehouse 摘要({id, name, status, location: {id, name, status} | null} | null),
结构与切换接口一致,供普通用户在公司切换器直接展示,无需放开管理员仓库配置接口。
- model:新增 WarehouseSummary/LocationSummary/OrganizationSummary,
OrganizationAccess 每项改为内嵌公司资料再加 warehouse 摘要。
- repository:新增 WarehouseRepository.Summary 复用切换接口的解析规则;
ListAccessible 逐公司补齐摘要,仓库或库位配置不唯一时报错而非随意取第一条,
无仓库、无库位或已停用如实返回,不回退旧公司数据。
- service:Switch 复用 List 已解析的摘要,响应格式保持不变。
- 测试:新增服务层 sqlmock 用例与仓储层 MySQL 集成用例,
覆盖启用唯一仓库加启用库位、无仓库、仓库停用三类。
|
2026-10-09 10:43:35 +08:00 |
|
文睿 张
|
838889ce9f
|
feat: 按公司隔离物料主数据
|
2026-10-09 10:38:02 +08:00 |
|
文睿 张
|
8f4460b84a
|
feat: 强制校验可信公司上下文
|
2026-10-09 09:56:21 +08:00 |
|
文睿 张
|
8043fa198b
|
feat: 配置用户公司授权与默认公司
|
2026-10-09 09:47:27 +08:00 |
|
文睿 张
|
7e56d462b3
|
feat: 新增组织授权与审计数据底座
|
2026-10-08 17:04:09 +08:00 |
|
文睿 张
|
6ac9f2cb3c
|
新增伙伴业务分类,优化物料编辑并整理数据库脚本
|
2026-10-08 11:54:51 +08:00 |
|
文睿 张
|
7f06b2ee58
|
bugs修复
|
2026-09-23 14:46:51 +08:00 |
|
文睿 张
|
d62d6777d1
|
bugs修复
|
2026-09-23 14:20:42 +08:00 |
|
文睿 张
|
5d508cd2bb
|
fix: 给不存在的仓库建库位时误报创建成功
CreateLocation 的 INSERT...SELECT 匹配不到仓库时影响 0 行,MySQL 不报错:
err 为 nil、LastInsertId() 返回 0。此前只看 err,接口回 201
"Location created successfully" 且 data.id 为 0,而库里一行都没写进去——
刷新后库位消失,重试还是"成功"。
改为以 RowsAffected 为准(INSERT 的 RowsAffected 就是实际插入行数,不受
clientFoundRows 影响),影响 0 行返回 ErrWarehouseNotFound,接口回 400
"仓库不存在,可能已被删除或不属于当前组织"。与既有的 execExpectingRow、
role_permissions 插入保持同一套路。
实测(docker,重建后端镜像后):
不存在的仓库 999 -> HTTP 400,warehouse_locations 1 行 -> 1 行
真实仓库 1 -> HTTP 201 id=3,1 行 -> 2 行,库中确有此行
新增 warehouse_test.go 覆盖两个分支,变异验证:去掉 affected==0 判断后
"影响 0 行"用例失败(返回 <nil>,正是线上症状)。
|
2026-09-22 18:21:31 +08:00 |
|
文睿 张
|
aa017a32b4
|
fix: 已停用角色导致用户无法保存编辑
|
2026-09-22 16:41:19 +08:00 |
|
文睿 张
|
696e90893b
|
fix: 主数据编辑的两类静默失败
UPDATE 漏列:
- code_rules 的 SET 补上 category_id。此前改分类提示"保存成功"但不落库,
是唯一用户可达的活缺陷(同页的分类下拉没有 disabled,且规则只能改不能删,
没有"删了重建"这条退路)
- code_rules 有 uk_code_rules_org_category,补列后改到已占用的分类会撞唯一键,
新建与更新统一翻成中文的 ErrDuplicateCodeRule
- 分类/单位/仓库/库位/伙伴的编码定为不可变:分类编码是编码规则前缀的来源
(init.sql 的种子数据直接取 material_categories.code),伙伴编码是对外业务
编号,改掉会让历史数据脱节且查不回来。service 的 Update* 不再要求编码非空
——原先是"必须传、传了却被丢弃";新建侧的必填校验保留
- 顺带补齐两处同款漏网:organization.go 的 code 与 partner.go 的 partner_code
(前者 service 本就不校验编码,自洽,无需改)
记录不存在时的静默成功:
- DSN 开启 clientFoundRows,让 RowsAffected 返回"匹配"行数而非"实际改变"行数。
否则"编辑时一个字段都没改"和"记录不存在"都返回 0,无法区分,直接加检查会把
正常保存误判成记录不存在(真 MySQL 8.0 实测)
- 新增 repository.execExpectingRow,7 个 Update* 影响 0 行时返回 ErrRecordNotFound;
伙伴走事务内的 SELECT ... FOR UPDATE,只需翻译 sql.ErrNoRows
- 既有 4 处 RowsAffected 用法逐处核对过,均不受该 flag 影响
测试:补 6 个 Update* 的存在性检查、编码必填约束的两端、唯一键翻译、DSN 拼接;
全部做过变异验证(抽掉实现后对应测试确实变红)。
|
2026-09-21 17:26:53 +08:00 |
|
文睿 张
|
837cc5787b
|
前端问题优化
|
2026-09-21 16:53:44 +08:00 |
|
文睿 张
|
71d1829c29
|
fix: 库存列表分类筛选失效,后端补上 category 参数
前端 stores/stock.js 一直在发 category,但 handler 只读 search,service 与
repository 的方法签名里也没有这个参数,整条链路把它静默丢弃,于是选完分类
点「查询」没有任何反应。前端本来就传对了,无需改动。
repository 侧按大类 code 过滤(material_categories 里 parent_id 为空的那层,
即 SQL 里的 pc.code),与列表「大类类型」列同口径,前端下拉的 value 正是大类
code。注意 GetAllStock 的 COUNT 查询原本没有 JOIN 分类表,加 pc.code 前必须
补上与主查询一致的 LEFT JOIN,否则分页总数会和实际行数对不上、末尾多出空白
页;两张表都按主键关联,实测计数不变。小类码不会误命中(category=A01 返回 0)。
顺带修掉同一功能里的耦合缺陷:updateWarningStock 刷新列表时不传筛选参数,
筛选一旦生效,保存预警就会把列表刷回全量、而下拉框仍显示选中的分类。store
新增 stockFilters 记住当前条件,刷新时沿用。
stock_test.go 里 COUNT 的正则随 SQL 变形同步放宽,新增
TestStockRepoGetAllStockAppliesCategoryToBothQueries 覆盖两条 SQL 的成对条件
与参数顺序;前端补 4 条用例(store 沿用/清空筛选、组件查询与翻页传递分类)。
|
2026-09-21 16:19:18 +08:00 |
|
文睿 张
|
72bc6c9af2
|
test: 补齐 Update 的 happy-path 用例,锁定「编辑走 UPDATE」而非 INSERT
六个 Update* 此前只有 UpdateRequiresID 覆盖到拒绝分支,方法体里的
s.repo.Update*(item) 从未被执行。这 12 个方法互为复制粘贴的模板,
尾行一旦误写成 Create* 全部测试仍然绿灯,生产行为会退化成「编辑即新增」。
新增两条用例:PartnerService.Update(事务:SELECT ... FOR UPDATE + 两条
UPDATE)与 MasterDataService.UpdateCategory(单条 UPDATE),均登记
UPDATE 期望并以 ExpectationsWereMet 兜底。把尾行改成 Create* 实测两条
用例都会失败并指名收到了 INSERT。
同时 gofmt internal/service/admin_master.go:新增中文注释紧贴前一个函数的
},补上缺失的空行,纯空白改动。
|
2026-09-21 15:34:41 +08:00 |
|
文睿 张
|
6ed205dcb8
|
refactor: 拆分 WarehouseService 的 Create/Update,去掉 ID==0 猜分支
|
2026-09-21 15:09:37 +08:00 |
|
文睿 张
|
16ca9c02ba
|
refactor: 拆分 MasterDataService 的 Create/Update,分类与单位创建不再受脏 id 影响
|
2026-09-21 15:03:57 +08:00 |
|
文睿 张
|
1b0cdde780
|
refactor: 拆分 PartnerService 的 Create/Update,创建接口不再被脏 id 带偏
|
2026-09-21 14:59:01 +08:00 |
|
文睿 张
|
ea63cd9931
|
修改一致性问题
|
2026-09-21 14:13:30 +08:00 |
|
文睿 张
|
d463fbf71a
|
修改前端报错文案
|
2026-09-20 16:59:38 +08:00 |
|
文睿 张
|
a7c7936e0b
|
feat: 实现物料编码按分类规则自动生成、手工修改及并发安全的流水号管理
|
2026-09-20 16:48:06 +08:00 |
|
文睿 张
|
936a8d3b61
|
完善库存流水
|
2026-09-20 14:29:41 +08:00 |
|
文睿 张
|
332ac1ff7a
|
完善出库和入库逻辑
|
2026-09-20 11:18:00 +08:00 |
|
文睿 张
|
d9da2ed672
|
库存,入库,出库相关问题修改
|
2026-09-20 10:31:28 +08:00 |
|
文睿 张
|
6fe9d0da40
|
物料分类重构、物料恢复、入库预警阈值与库存明细接口
|
2026-09-18 17:20:45 +08:00 |
|
文睿 张
|
bf48c5a60f
|
chore: remove generated caches and temporary files
|
2026-09-17 15:17:23 +08:00 |
|
文睿 张
|
1cc3584f1a
|
restore lost frontend and backend changes
|
2026-09-16 23:30:25 +08:00 |
|
文睿 张
|
a103549854
|
拆分主数据和仓库数据
|
2026-09-16 16:29:04 +08:00 |
|
文睿 张
|
31aae223c2
|
Initial commit
|
2026-09-15 16:08:18 +08:00 |
|