# 2026-05-25 会话记录

## 系统模块开发（2026-05-25 13:28）

### 完成的工作

1. **操作日志功能**
   - 实体类：`OperLog.java`
   - Mapper：`OperLogMapper.java`
   - Service：`OperLogService.java` + `OperLogServiceImpl.java`
   - Controller：`OperLogController.java`
   - 切面：`LogAspect.java`（自动记录带@Log 注解的方法）
   - 注解：`@Log`（module、businessType、isSaveRequestData、isSaveResponseData）

2. **数据字典增强**
   - 新增方法：`listDataBatch()` - 批量获取字典数据
   - 新增方法：`listOptions()` - 前端下拉框格式 [{label, value}]
   - 新增方法：`listOptionsBatch()` - 批量获取下拉框选项
   - 新增接口：`GET /system/dict/data/options/batch?dictTypes=xxx,yyy`

3. **文档**
   - `04-系统模块开发指南.md` - 包含使用示例、API 文档、前端集成示例

### 业务类型枚举

| 值 | 含义 |
|----|------|
| 0 | 其它 |
| 1 | 新增 |
| 2 | 修改 |
| 3 | 删除 |
| 4 | 导出 |
| 5 | 导入 |
| 6 | 审核 |

### 已初始化字典

- `inbound_type` - 入库类型（采购入库、退货入库、其他入库）
- `outbound_type` - 出库类型（销售出库、领料出库、其他出库）
- `stocktake_diff_result` - 盘点结果（相符、盘盈、盘亏）
- `payment_method` - 收付款方式（现金、银行转账、承兑汇票）

### 下一步

- 主数据模块开发（供应商、客户） ✓
- 库存模块开发（入库单、出库单） ✓
- 财务模块开发（应收、应付、收款、付款）
- 首页模块开发 ✓

---

## 首页模块开发（2026-05-25 15:15）

### 完成的工作

1. **欢迎信息接口**
   - `GET /home/welcome` - 返回欢迎语、用户名、企业名、日期、问候语
   - 根据时间段自动切换问候语（早上好/中午好/下午好/晚上好/夜深了）
   - DTO：`HomeWelcomeResDTO.java`

2. **最新动态接口**
   - `GET /home/news` - 返回最近 20 条业务动态
   - 动态类型：入库完成、出库完成、盘点完成、新增供应商、新增客户
   - 按时间倒序排列
   - DTO：`HomeNewsItemDTO.java`

3. **文件清单**
   - `HomeController.java` - 首页控制器
   - `HomeService.java` / `HomeServiceImpl.java` - 首页服务
   - `HomeWelcomeResDTO.java` - 欢迎信息响应
   - `HomeNewsItemDTO.java` - 动态项 DTO

### API 示例

```http
GET /home/welcome
→ { welcome: "欢迎", userName: "张三", companyName: "某某公司", greeting: "下午好" }

GET /home/news
→ [ { type: "inbound", title: "入库完成", content: "RK202605250001 - 成品仓", operator: "张三", operateTime: "..." } ]
```

### TODO

- 从用户会话/配置中获取真实用户名和企业名（当前为默认值）

---

## 库存模块增强（2026-05-25 14:26）

### 完成的工作

1. **入库单管理 CRUD**
   - 实体：`Inbound.java` + `InboundItem.java`
   - DTO：`InboundSaveReqDTO.java` + `InboundItemSaveReqDTO.java`
   - Mapper：`InboundMapper.java` + `InboundItemMapper.java`
   - Service：`InboundService.java` + `InboundServiceImpl.java`
   - Controller：`InboundController.java`
   - API：分页查询、详情、明细、新增、修改、审核、作废、删除
   - 审核逻辑：检查状态 → 更新状态 → 增加库存
   - 作废逻辑：检查状态 → 更新状态 → 扣减库存

2. **出库单管理 CRUD**
   - 实体：`Outbound.java` + `OutboundItem.java`
   - DTO：`OutboundSaveReqDTO.java` + `OutboundItemSaveReqDTO.java`
   - Mapper：`OutboundMapper.java` + `OutboundItemMapper.java`
   - Service：`OutboundService.java` + `OutboundServiceImpl.java`
   - Controller：`OutboundController.java`
   - API：分页查询、详情、明细、新增、修改、审核、作废、删除
   - 审核逻辑：检查状态 → **检查库存充足** → 更新状态 → 扣减库存
   - 作废逻辑：检查状态 → 更新状态 → 恢复库存

3. **盘点单管理 CRUD**
   - 实体：`Stocktake.java` + `StocktakeItem.java`
   - DTO：`StocktakeSaveReqDTO.java` + `StocktakeItemSaveReqDTO.java`
   - Mapper：`StocktakeMapper.java` + `StocktakeItemMapper.java`
   - Service：`StocktakeService.java` + `StocktakeServiceImpl.java`
   - Controller：`StocktakeController.java`
   - API：分页查询、详情、明细、新增、修改、审核、作废、删除
   - 审核逻辑：计算差异 → 设置盘点结果 → **调整库存**（盘盈 +，盘亏 -）
   - 作废逻辑：反向调整库存

4. **库存服务增强**
   - 新增方法：`addStock()` - 入库单调用（包含物料信息）
   - 新增方法：`reduceStock()` - 出库单调用
   - 新增方法：`checkStock()` - 检查库存是否充足

5. **文档**
   - `06-库存模块开发指南.md` - 完整 API 文档、业务流程、测试示例

### 业务类型字典

| 类型 | 值 | 标签 |
|------|-----|------|
| inbound_type | 10 | 采购入库 |
| inbound_type | 20 | 退货入库 |
| inbound_type | 30 | 其他入库 |
| outbound_type | 10 | 销售出库 |
| outbound_type | 20 | 领料出库 |
| outbound_type | 30 | 其他出库 |
| stocktake_diff_result | 0 | 相符 |
| stocktake_diff_result | 1 | 盘盈 |
| stocktake_diff_result | 2 | 盘亏 |

### 状态流转

```
草稿 (0) → 已审核 (1) → 已作废 (2)
```

### 编译状态

```
✅ mvn compile 成功
```

---

## 主数据模块开发（2026-05-25 13:46）

### 完成的工作

1. **供应商管理 CRUD**
   - 实体：`Supplier.java`（name、contact、mobile 等简洁字段）
   - DTO：`SupplierSaveReqDTO.java`
   - Mapper：`SupplierMapper.java`
   - Service：`SupplierService.java` + `SupplierServiceImpl.java`
   - Controller：`SupplierController.java`
   - API：分页查询、列表、详情、新增、修改、删除
   - 操作日志：@Log 注解自动记录

2. **客户管理 CRUD**
   - 实体：`Customer.java`（增加 level 客户级别字段）
   - DTO：`CustomerSaveReqDTODTO.java`
   - Mapper：`CustomerMapper.java`
   - Service：`CustomerService.java` + `CustomerServiceImpl.java`
   - Controller：`CustomerController.java`
   - API：分页查询、列表、详情、新增、修改、删除
   - 操作日志：@Log 注解自动记录

3. **文档**
   - `05-主数据模块开发指南.md` - 包含 API 文档、前端集成示例

### 设计特点

- 字段命名参考 ruoyi-pro：`name`、`contact`、`mobile`（简洁风格）
- 必填字段仅 `name`，支持快捷新增
- 客户级别：10-普通、20-重要、30-VIP（字典数据管理）
- 所有操作自动记录日志

### 编译状态

```
✅ mvn compile 成功
```

---

## Tiny-ERP 表架构设计与实现

### 完成的工作

1. **表架构设计文档**
   - 位置：`/home/yangxuan/Projects/IdeaProjects/tiny-erp/yangxuan/设计/表架构设计.md`
   - 参考项目：ruoyi-vue-pro（别名 ruoyi-pro）
   - 设计原则：务实、简洁、不过度设计

2. **SQL 脚本生成与执行**
   - `20-master-data.sql` - 主数据模块（供应商、客户表参考 ruoyi-pro 风格）
   - `50-inventory.sql` - 库存模块（入库/出库/盘点单及明细）
   - `60-finance.sql` - 财务模块（应收/应付/收款/付款及核销明细）
   - `99-data.sql` - 初始化数据（修复为幂等脚本）

3. **数据库表统计**
   - 系统模块：5 表（含操作日志）
   - 主数据：6 表（供应商、客户）
   - 销售：4 表
   - 采购：2 表
   - 库存：8 表（入库/出库/盘点）
   - 财务：8 表（应收/应付/收款/付款 + 核销明细）
   - **总计：27 表**

4. **关键设计决策**
   - 供应商/客户字段命名参考 ruoyi-pro：`name`、`contact`、`mobile`（去掉冗余前缀）
   - 应收应付按物料明细记录（fi_receivable_item / fi_payable_item）
   - 数量：NUMERIC(12,3)，金额/单价：NUMERIC(18,2)
   - 所有业务表包含 ecid 字段实现多租户隔离
   - 99-data.sql 使用 `INSERT ... SELECT ... WHERE NOT EXISTS` 实现幂等

### 待确认事项（已确认）

| 序号 | 事项 | 结论 |
|------|------|------|
| 1 | 多仓库管理 | 不需要 |
| 2 | 批次/序列号 | 不需要 |
| 3 | 应收应付物料明细 | 需要 ✓ |
| 4 | 多计量单位换算 | 不需要 |

### 数据库状态

- 数据库名：`tinyerp`
- 连接方式：Unix socket (`/var/run/postgresql`)
- 所有脚本执行成功，无 ERROR
- 初始化数据：1 租户、1 用户 (admin)、6 字典类型、16 字典数据

### 下一步

- 开始 Java 后端开发
- 实体类设计参考 ruoyi-pro 的 DO 结构

---

## 入库出库优化（2026-05-25 16:44）

### 完成的工作

1. **生产入库 & 采购入库**
   - DTO：`ProductionInboundSaveReqDTO.java`、`ProductionInboundItemReqDTO.java`
   - DTO：`PurchaseInboundSaveReqDTO.java`、`PurchaseInboundItemReqDTO.java`
   - 接口：`POST /im/inbound/production`、`POST /im/inbound/purchase`
   - 特点：生产入库无需单价，采购入库含单价

2. **领料出库 & 销售出库**
   - DTO：`MaterialOutboundSaveReqDTO.java`、`MaterialOutboundItemReqDTO.java`
   - DTO：`SalesOutboundSaveReqDTO.java`、`SalesOutboundItemReqDTO.java`
   - 接口：`POST /im/outbound/material`、`POST /im/outbound/sales`
   - 特点：领料出库无需单价，销售出库含单价

3. **入库/出库历史查询**
   - DTO：`InboundHistoryQueryReqDTO.java`、`InboundHistoryDTO.java`
   - DTO：`OutboundHistoryQueryReqDTO.java`、`OutboundHistoryDTO.java`
   - 接口：`POST /im/inbound/history-list`、`POST /im/outbound/history-list`
   - 功能：查询已审核的单据，返回汇总信息

4. **物料信息填充**
   - 保存时自动填充物料编码、名称、规格、单位
   - 避免后续关联查询，提高查询性能

5. **文档**
   - `04-入库出库优化 - 实现总结.md` - 完整 API 文档、测试示例

### 编译状态
```
✅ mvn compile 成功
```

---

## 实时库存 & 库存盘点（2026-05-25 17:16）

### 完成的工作

1. **实时库存分页查询**
   - DTO：`StockPageQueryReqDTO.java`、`StockPageDTO.java`
   - 接口：`POST /im/stock/page`
   - 功能：带安全库存校验，返回 `isLowStock` 标识
   - 校验规则：最小安全库存 > 0 且 库存 < 最小安全库存 → 库存过低

2. **最小安全库存管理**
   - 接口：`PUT /md/material/{id}/safe-qty` - 更新最小安全库存
   - 接口：`PUT /md/material/{id}/safe-qty/clear` - 清除（设置为 0）
   - 使用 MyBatis XML 实现（支持设置为 0）
   - 字段：`md_material.min_safe_qty NUMERIC(12,3)`

3. **快速盘点**
   - DTO：`StocktakeQuickSaveReqDTO.java`、`StocktakeQuickItemReqDTO.java`
   - 接口：`POST /im/stocktake/quick-save`
   - 功能：批量保存盘点单（草稿），自动获取当前库存作为账面数量

4. **盘点历史列表**
   - DTO：`StocktakeHistoryQueryReqDTO.java`、`StocktakeHistoryDTO.java`
   - 接口：`POST /im/stocktake/history-list`
   - 日期范围：`today`（当日）、`week`（近 7 日）、`month`（近 30 日）

5. **MyBatis XML 按模块分类**
   - `mapper/md/material/MaterialMapper.xml` - 物料模块
   - `mapper/im/stock/StockMapper.xml` - 库存模块

### 数字格式规范
| 字段类型 | 数据库类型 | 小数位 | 展示规则 |
|---------|-----------|--------|---------|
| 数量 | NUMERIC(12,3) | 3 | 小数全为 0 时不展示 |
| 单价/金额 | NUMERIC(11,2) | 2 | 小数全为 0 时不展示 |

### 编译状态
```
✅ mvn compile 成功
```

---

## 库存积压分析（2026-05-25 17:23）

### 完成的工作

1. **积压统计（按分类分组）**
   - DTO：`StockOverstockDTO.java`、`StockOverstockQueryReqDTO.java`
   - 接口：`POST /im/stock/overstock/summary`
   - 返回：分类、物料数量、积压金额、平均积压天数
   - 默认积压阈值：90 天

2. **积压明细（下钻页面）**
   - DTO：`StockOverstockDetailDTO.java`
   - 接口：`POST /im/stock/overstock/detail`
   - 参数：`category`（分类筛选）、`sortBy`（amount/qty 排序）
   - 返回：物料编码、名称、规格、库存数量、单价、积压天数、积压金额

3. **SQL 实现**
   - 积压判定：最后入库日期 < 当前日期 - 阈值
   - 单价计算：平均入库单价
   - 积压金额 = 库存数量 × 平均单价

### 新增文件
- `StockMapper.xml` - 积压统计和明细 SQL
- `06-库存积压分析 - 实现总结.md` - 完整文档

### 编译状态
```
✅ mvn compile 成功
```

---

## 项目规范建立（2026-05-25 17:17-18:32）

### Git 操作规范
- ⛔ **禁止自动 push** - 所有 commit 后必须人工审查
- ✅ 流程：编译验证 → 提交代码 → 停止等待 → 人工确认后手动 push

### Java 语法规范
- ☕ **只能使用 Java 8 语法**
- ❌ 禁止：`var`、`Map.of()`、`List.of()`、switch 表达式、文本块、record
- ✅ 推荐：Lambda、Stream API、Optional、方法引用

### 状态字段规范
| 值 | 含义 |
|----|------|
| 0 | 有效（默认） |
| 1 | 无效 |

### 架构规范
- Service 层处理业务逻辑（查询、填充、组装）
- Controller 层保持简洁（调用 Service、返回结果）
- 接口支持可选字段参数（`withStock`、`withCategoryName`）提高复用性

### 本地开发规范
- ✅ 支持免登录（请求头 `X-User-Id` 或默认用户）
- ⚠️ 仅 local 环境启用，生产环境严禁开启

---

## 物料分页查询重构（2026-05-25 18:15-18:37）

### 完成的工作

1. **Java 填充方案（替代 XML JOIN）**
   - 删除：`MaterialMapper.xml` 中的复杂 JOIN 查询
   - 删除：`MaterialListWithStockReqDTO.java`、`MaterialWithStockDTO.java`
   - 新增：`MaterialPageDTO.java`、`MaterialPageQueryReqDTO.java`
   - 逻辑：Service 层批量查询库存和分类，内存填充

2. **可选字段参数**
   - `withStock`（默认 true）- 是否返回库存数量
   - `withCategoryName`（默认 true）- 是否返回分类名称
   - 性能优化：不查关联时只需 1 次 SQL

3. **本地开发免登录**
   - 配置：`development.mock-auth.enabled`
   - 请求头：`X-User-Id`、`X-User-Name`、`X-Nickname` 等
   - 过滤器：`UserContextFilter` 支持免登录模式

4. **代码整理**
   - 简化 `MaterialController.java` - 移除 XML 查询接口
   - 精简 `MaterialMapper.java` - 只保留安全库存更新方法
   - 重构 `MaterialServiceImpl.java` - 添加 `pageWithStock()` 方法

### 性能对比
| 场景 | withStock | withCategoryName | SQL 次数 |
|------|-----------|------------------|---------|
| 下拉选择器 | ❌ | ❌ | 1 |
| 简单列表 | ❌ | ❌ | 1 |
| 库存管理 | ✅ | ❌ | 2 |
| 完整展示 | ✅ | ✅ | 3 |

### 编译状态
```
✅ mvn compile 成功
```

---

## 今日提交统计（未 push）

```
feat: 实现入库出库优化功能
feat: 实现实时库存和盘点功能
feat: 实现库存积压分析功能
refactor: 按模块分类 MyBatis XML 文件
fix: 修复物料查询 XML 中的字段错误
docs: 更新物料状态注释
feat: 物料分页查询改为 Java 填充关联数据
refactor: 物料分页查询逻辑移至 Service 层
feat: 物料分页查询支持可选字段
refactor: 删除物料 XML 查询，统一使用 Service 层 Java 填充
feat: 本地开发支持免登录
```

**总计**: 约 15 个 commit，4300+ 行新增，200+ 行删除

---

## 待办事项

1. **数据库迁移** - 添加 `md_material.min_safe_qty` 字段
2. **前端开发** - 实时库存、盘点、积压分析页面
3. **测试验证** - 使用 HTTP 测试文件验证所有接口
4. **代码审查** - 人工审查后执行 git push
## 下午-晚间增量（2026-05-25 18:37~20:18）

### 实体-DDL 字段对齐

| 文件 | 字段 | 操作 |
|------|------|------|
| `Stock.java` | `category`, `safeQty` | 彻底删除（非表字段） |
| `Outbound.java` | `warehouseName`, `totalQuantity` | 彻底删除（非表字段） |
| `Stocktake.java` | `warehouseName` | 彻底删除（非表字段） |
| `StockServiceImpl.java` | `safeQty` 操作 | 改为读写 `md_material.min_safe_qty` |

### 模糊查询支持特殊字符

- 创建 `LikeEscapeUtil.java` — 转义 `\`、`%`、`_`
- 物料/客户/供应商分页查询全部接入转义
- 客户/供应商 `/list` 接口新增 `keyword` 参数支持名称+编码联合模糊
- **踩坑**：`ESCAPE '\\'` 被 MyBatis-Plus COUNT 包装解析失败 → 移除 `ESCAPE` 子句，利用 PostgreSQL 默认 `\` 为转义字符

### 最小安全库存

- DDL `20-master-data.sql` 新增 `min_safe_qty NUMERIC(12,3) DEFAULT 0`
- 升级脚本 `upgrade/v1.0.1-alter-material-add-min-safe-qty.sql`
- 库存分页返回 `isLowStock` 标识（库存 < min_safe_qty → 过低）
- 接口：`PUT /md/material/{id}/safe-qty` / `PUT /md/material/{id}/safe-qty/clear`

### 主数据初始化脚本修正

| 改动 | 说明 |
|------|------|
| `safety_stock` 列和值 | 从 INSERT 语句中删除 |
| `supplier_code` / `customer_code` | 补全编码值 |
| 物料名称规格空格 | 对齐文档（如"宝塔3斜纹"） |

### DDL 补充字段

| 表 | 新增字段 |
|----|---------|
| `md_supplier` | `supplier_code VARCHAR(50)`, `phone VARCHAR(20)`, `address VARCHAR(200)` |
| `md_customer` | `customer_code VARCHAR(50)`, `phone VARCHAR(20)`, `address VARCHAR(200)`, `level INTEGER DEFAULT 0` |

### 今日提交统计（全部未 push）

```
418cd10 fix: 修复库存积压报表仅入库物料积压天数基准错误
e8d7bb4 docs: 重构文档目录结构，按模块分类组织
8a38d33 feat: 入库单/出库单 inboundDate/outboundDate 为空时默认当天
373a292 feat: 供应商/客户DDL补充编码、联系电话、地址、客户级别字段
6c338d1 feat: 根据文档补充default租户主数据初始化脚本的编码字段和物料名称修正
d17b970 feat: 物料/客户/供应商模糊查询支持特殊字符转义及客户供应商列表接口
f02f048 feat: DDL增加md_material.min_safe_qty字段及升级脚本
5de00d3 feat: 清理非表字段，最小安全库存统一走md_material.min_safe_qty
(plus safety_stock removal commit)
```

**原则**: 代码改动与文档改动分 commit，禁止自动 push，人工审查后手动操作。

### 环境配置

- MySQL 运行时 `tiny_erp` 数据库已配置 `min_safe_qty`
- 开发免登录配置：`development.mock-auth.enabled`