36564571fa
- fix(test): 同步 listInventory 签名(补 series/spec 参数) - test(backend): 新增 import_parse_test.go - chore(backend): 新增 cmd/test_xls 调试工具 - docs: UI 筛选组件设计规范、Gemini 项目配置 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
42 lines
1.5 KiB
Markdown
42 lines
1.5 KiB
Markdown
# 酒库管理系统 — Gemini 编码规则
|
||
|
||
## 项目背景
|
||
|
||
这是一个多租户酒类库存管理系统,Go 后端 + Flutter 前端。
|
||
|
||
## 强制规则(违反即重写)
|
||
|
||
### 多租户隔离
|
||
- `shop_id` **永远**从 `middleware.GetShopID(c)` 获取
|
||
- **绝不**从 request body、URL params、query string 读取 shop_id
|
||
- 所有数据库查询必须带 `WHERE shop_id = ?` 条件
|
||
|
||
### 并发安全
|
||
- 同一事务内读后写必须用 `FOR UPDATE` 锁行:
|
||
```go
|
||
tx.Set("gorm:query_option", "FOR UPDATE").Where(...).First(&model)
|
||
```
|
||
- 适用:单号生成、库存扣减、任何 check-then-act 模式
|
||
|
||
### 代码风格(参考 handler/product.go)
|
||
- Handler 函数签名:`func (h *Handler) ActionName(c *gin.Context)`
|
||
- 统一错误返回:`c.JSON(http.StatusBadRequest, gin.H{"error": "..."})`
|
||
- 成功返回:`c.JSON(http.StatusOK, result)`
|
||
- 所有 DB 操作通过 `h.db`,不直接引用全局变量
|
||
|
||
### Schema 管理
|
||
- 表结构变更同步修改 `backend/schema/schema.sql`
|
||
- 无单独迁移文件,启动时 AutoMigrate
|
||
- 不为单个字段加新列,用 `custom_fields JSON` 扩展
|
||
|
||
### 测试规范
|
||
- 测试文件放在同包下:`xxx_test.go`
|
||
- 使用 `testutil/` 下的辅助函数
|
||
- 每个 handler 至少覆盖:正常路径 + 缺少 shop_id 的 403 场景
|
||
|
||
## 参考文件
|
||
- Handler 模式:`backend/internal/handler/product.go`
|
||
- Model 模式:`backend/internal/model/product.go`
|
||
- 认证中间件:`backend/internal/middleware/auth.go`
|
||
- Schema:`backend/schema/schema.sql`
|