# 酒库管理系统 — 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`