数据库 Schema · 酒库管理系统
MySQL 8.0+ · 多租户(所有业务表含
shop_id 隔离)· 启动时 GORM AutoMigrate31 张表
365 个字段
来源:
backend/schema/schema.sql + model AutoMigrate
PK 主键
UNIQUE 唯一键
INDEX 普通索引
FULLTEXT 全文索引
租户 多租户隔离列
租户 · 用户 · 安全
多租户根表与登录/会话/审计。所有业务表的 shop_id 都指向 shops。
shops 门店(租户)
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| name | VARCHAR(100) | 否 | — | 门店名称 |
| code | VARCHAR(50) | 否 | — | 门店编号(唯一) |
| address | VARCHAR(255) | 是 | NULL | |
| phone | VARCHAR(30) | 是 | NULL | |
| manager_name | VARCHAR(50) | 是 | NULL | 负责人 |
| description | TEXT | 是 | NULL | 店铺简介 |
| logo_url | VARCHAR(500) | 是 | — | 门店 logo URL |
| business_license | VARCHAR(500) | 是 | NULL | 营业执照照片URL |
| shop_photos | JSON | 是 | NULL | 门店照片URL数组 |
| custom_fields | JSON | 是 | NULL | 扩展字段 |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| deleted_at | DATETIME | 是 | NULL |
PRIMARY (`id`)
UNIQUE uk_code (`code`)
INDEX idx_deleted_at (`deleted_at`)
UNIQUE uk_code (`code`)
INDEX idx_deleted_at (`deleted_at`)
users 用户
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| username | VARCHAR(50) | 否 | — | |
| password_hash | VARCHAR(255) | 否 | — | bcrypt |
| real_name | VARCHAR(50) | 是 | NULL | |
| phone | VARCHAR(30) | 是 | NULL | |
| role | ENUM('admin','operator','readonly','superadmin') | 否 | operator | |
| is_active | TINYINT(1) | 否 | 1 | |
| last_login_at | DATETIME | 是 | NULL | 最近登录时间 |
| custom_fields | JSON | 是 | NULL | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| deleted_at | DATETIME | 是 | NULL |
PRIMARY (`id`)
UNIQUE uk_shop_username (`shop_id`, `username`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_deleted_at (`deleted_at`)
UNIQUE uk_shop_username (`shop_id`, `username`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_deleted_at (`deleted_at`)
user_sessions 登录会话
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| user_id | BIGINT UNSIGNED | 否 | — | |
| sid | VARCHAR(64) | 否 | — | 嵌入 JWT 的会话标识 |
| device_id | VARCHAR(255) | 是 | NULL | |
| device_name | VARCHAR(255) | 是 | NULL | |
| platform | VARCHAR(50) | 是 | NULL | windows|macos|linux|android|ios|web |
| platform_class | VARCHAR(20) | 是 | NULL | desktop|mobile|web |
| ip | VARCHAR(64) | 是 | NULL | |
| user_agent | VARCHAR(512) | 是 | NULL | |
| refresh_jti | VARCHAR(64) | 是 | NULL | 当前有效 refresh token 的 jti,用于轮换+重用检测 |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| last_seen_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| revoked_at | DATETIME | 是 | NULL | |
| revoked_reason | VARCHAR(30) | 是 | NULL | kicked|logout|admin|disabled|reuse|pwd_reset |
| revoked_by | BIGINT UNSIGNED | 是 | NULL | 吊销操作人 user_id;系统/自助吊销为 NULL |
| refresh_exp_at | DATETIME | 是 | NULL |
PRIMARY (`id`)
UNIQUE uk_session_sid (`sid`)
INDEX idx_session_shop_user (`shop_id`, `user_id`)
INDEX idx_session_class (`platform_class`)
INDEX idx_session_revoked (`revoked_at`)
UNIQUE uk_session_sid (`sid`)
INDEX idx_session_shop_user (`shop_id`, `user_id`)
INDEX idx_session_class (`platform_class`)
INDEX idx_session_revoked (`revoked_at`)
login_attempts 登录尝试审计
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_code | VARCHAR(64) | 是 | NULL | |
| username | VARCHAR(50) | 是 | NULL | |
| ip | VARCHAR(64) | 是 | NULL | |
| user_agent | VARCHAR(512) | 是 | NULL | |
| success | TINYINT(1) | 否 | 0 | |
| reason | VARCHAR(40) | 是 | NULL | invalid_shop|invalid_user|bad_password|locked|inactive|platform_not_allowed |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP |
PRIMARY (`id`)
INDEX idx_attempt_user (`username`, `created_at`)
INDEX idx_attempt_ip (`ip`, `created_at`)
INDEX idx_attempt_user (`username`, `created_at`)
INDEX idx_attempt_ip (`ip`, `created_at`)
授权 · 兑换券
门店授权与时长兑换券码池(ed25519/HMAC 已退役,改时长兑换券模型)。
licenses 许可证
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| license_key | VARCHAR(768) | 否 | — | Ed25519 signed token |
| device_id | VARCHAR(255) | 是 | NULL | deprecated: use license_devices |
| type | ENUM('trial','monthly','annual','lifetime') | 否 | trial | |
| tier | VARCHAR(32) | 否 | standard | 权益档位钩子(pro/max-like),当前默认 standard |
| expires_at | DATETIME | 是 | NULL | NULL=永久 |
| is_active | TINYINT(1) | 否 | 1 | |
| max_devices | INT | 否 | 3 | 最大绑定设备数 |
| features | JSON | 是 | NULL | 功能开关 {"finance":true} |
| activated_at | DATETIME | 是 | NULL | deprecated |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP |
PRIMARY (`id`)
UNIQUE uk_license_key (`license_key`)
INDEX idx_shop_id (`shop_id`)
UNIQUE uk_license_key (`license_key`)
INDEX idx_shop_id (`shop_id`)
license_devices 许可证设备绑定
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| license_id | BIGINT UNSIGNED | 否 | — | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| device_id | VARCHAR(255) | 否 | — | |
| device_name | VARCHAR(255) | 是 | NULL | |
| platform | VARCHAR(50) | 是 | NULL | windows|macos|android|ios|web |
| activated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| last_seen_at | DATETIME | 否 | CURRENT_TIMESTAMP |
PRIMARY (`id`)
UNIQUE uk_license_device (`license_id`, `device_id`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_license_id (`license_id`)
UNIQUE uk_license_device (`license_id`, `device_id`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_license_id (`license_id`)
license_codes 兑换券码池
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| code | VARCHAR(32) | 否 | — | 归一化大写无连字符 |
| type | ENUM('trial','monthly','annual','lifetime') | 否 | annual | 计费/时长标签 |
| tier | VARCHAR(32) | 否 | standard | 档位钩子(pro/max-like),当前默认 standard |
| duration_days | INT | 否 | 0 | 授予时长;0=永久(lifetime) |
| max_devices | INT | 否 | 0 | 授予设备上限;0=不改变现值 |
| status | ENUM('unused','redeemed','void') | 否 | unused | |
| redeemed_shop_id | BIGINT UNSIGNED | 是 | NULL | 被哪个门店兑换 |
| redeemed_at | DATETIME | 是 | NULL | |
| redeemed_device_id | VARCHAR(255) | 是 | NULL | 兑换设备(审计) |
| batch | VARCHAR(64) | 是 | NULL | 发放批次/活动名 |
| note | VARCHAR(255) | 是 | NULL | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP |
PRIMARY (`id`)
UNIQUE uk_code (`code`)
INDEX idx_status (`status`)
INDEX idx_redeemed_shop (`redeemed_shop_id`)
UNIQUE uk_code (`code`)
INDEX idx_status (`status`)
INDEX idx_redeemed_shop (`redeemed_shop_id`)
license_purchases 在线购买/续费记录
pay 收款中枢:契约见
~/code/pay-contract(v1.0.0)。out_trade_no = pay 订单号,兼作对账键与幂等键(同一单只续期一次);amount 为 pay 下单响应回传的权威金额,webhook 回调时逐分核对。| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| user_id | BIGINT UNSIGNED | 否 | — | 下单管理员 |
| product_biz_code | VARCHAR(64) | 否 | — | 套餐稳定码:monthly_standard / annual_standard / monthly_pro / annual_pro |
| amount | VARCHAR(16) | 是 | NULL | pay 下单回传金额,如 2999.00 |
| out_trade_no | VARCHAR(64) | 是 | NULL | pay 订单号(对账+幂等键) |
| status | ENUM('pending','paid','failed') | 否 | pending | |
| trade_no | VARCHAR(64) | 是 | NULL | 渠道交易号(支付宝/微信) |
| channel | VARCHAR(16) | 是 | NULL | |
| paid_at | DATETIME | 是 | NULL | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| deleted_at | DATETIME | 是 | NULL | 软删除 |
PRIMARY (`id`)
UNIQUE uk_out_trade_no (`out_trade_no`)
INDEX idx_shop (`shop_id`)
INDEX idx_status (`status`)
UNIQUE uk_out_trade_no (`out_trade_no`)
INDEX idx_shop (`shop_id`)
INDEX idx_status (`status`)
商品主数据
products 每行 = 一个特有产品/序列号(非 SKU),是商品信息的单一来源。基础数据字典为入库选文本服务。
products 商品
单一来源铁律:批次号
batch_no、生产日期 production_date、进价、图片、public_id 均以此表为准。每行 = 一个序列号(uk_product_code 同店唯一)。| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| code | VARCHAR(50) | 是 | NULL | 商品编号 |
| barcode | VARCHAR(100) | 是 | NULL | 条码 |
| name | VARCHAR(200) | 否 | — | 商品名称 |
| series | VARCHAR(100) | 是 | NULL | 系列 |
| spec | VARCHAR(100) | 是 | NULL | 规格 |
| unit | VARCHAR(20) | 是 | NULL | 单位 |
| category_id | BIGINT UNSIGNED | 是 | NULL | |
| brand | VARCHAR(100) | 是 | NULL | 品牌 |
| purchase_price | DECIMAL(16,2) | 是 | NULL | 参考进价 |
| sale_price | DECIMAL(16,2) | 是 | NULL | 参考售价 |
| public_id | CHAR(36) | 否 | — | UUID,公开URL使用 |
| min_stock | INT | 是 | 0 | 库存预警值 |
| description | TEXT | 是 | NULL | 商品描述 |
| custom_fields | JSON | 是 | NULL | 动态扩展字段 |
| remark | VARCHAR(500) | 是 | NULL | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| deleted_at | DATETIME | 是 | NULL |
PRIMARY (`id`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_category (`category_id`)
INDEX idx_deleted_at (`deleted_at`)
UNIQUE uk_product_code (`shop_id`, `code`)
UNIQUE uk_public_id (`public_id`)
FULLTEXT ft_name (`name`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_category (`category_id`)
INDEX idx_deleted_at (`deleted_at`)
UNIQUE uk_product_code (`shop_id`, `code`)
UNIQUE uk_public_id (`public_id`)
FULLTEXT ft_name (`name`)
product_categories 商品分类
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| name | VARCHAR(100) | 否 | — | |
| parent_id | BIGINT UNSIGNED | 是 | NULL | 父分类,支持二级 |
| sort_order | INT | 否 | 0 | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| deleted_at | DATETIME | 是 | NULL |
PRIMARY (`id`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_shop_id (`shop_id`)
product_images 商品图片
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| product_id | BIGINT UNSIGNED | 否 | — | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| url | VARCHAR(500) | 否 | — | 相对路径,如 /images/products/1/xxx.jpg |
| sort_order | INT | 否 | 0 | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP |
PRIMARY (`id`)
INDEX idx_product_id (`product_id`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_product_id (`product_id`)
INDEX idx_shop_id (`shop_id`)
product_name_options 商品名称选项
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| code | VARCHAR(50) | 是 | NULL | 选项编号 |
| name | VARCHAR(200) | 否 | — | 名称 |
| remark | VARCHAR(500) | 是 | NULL | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| deleted_at | DATETIME | 是 | NULL |
PRIMARY (`id`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_deleted_at (`deleted_at`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_deleted_at (`deleted_at`)
product_series_options 商品系列选项
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| code | VARCHAR(50) | 是 | NULL | 选项编号 |
| name | VARCHAR(200) | 否 | — | 系列名称 |
| remark | VARCHAR(500) | 是 | NULL | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| deleted_at | DATETIME | 是 | NULL |
PRIMARY (`id`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_deleted_at (`deleted_at`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_deleted_at (`deleted_at`)
product_spec_options 商品规格选项
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| code | VARCHAR(50) | 是 | NULL | 选项编号 |
| name | VARCHAR(200) | 否 | — | 规格名称 |
| quantity | INT | 是 | 0 | 单品数量 |
| remark | VARCHAR(500) | 是 | NULL | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| deleted_at | DATETIME | 是 | NULL |
PRIMARY (`id`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_deleted_at (`deleted_at`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_deleted_at (`deleted_at`)
product_origin_options 商品产地选项(基础数据·AutoMigrate)
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | 租户隔离 |
| code | VARCHAR(50) | 是 | — | 选项编号 |
| name | VARCHAR(200) | 否 | — | 名称 |
| remark | VARCHAR(500) | 是 | — | |
| created_at / updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| deleted_at | DATETIME | 是 | NULL | 软删除 |
product_shelf_life_options 商品保质期选项(如「24个月」「无限期」·AutoMigrate)
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | 租户隔离 |
| code | VARCHAR(50) | 是 | — | 选项编号 |
| name | VARCHAR(200) | 否 | — | 名称 |
| remark | VARCHAR(500) | 是 | — | |
| created_at / updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| deleted_at | DATETIME | 是 | NULL | 软删除 |
product_storage_options 商品储存条件选项(如「阴凉避光」·AutoMigrate)
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | 租户隔离 |
| code | VARCHAR(50) | 是 | — | 选项编号 |
| name | VARCHAR(200) | 否 | — | 名称 |
| remark | VARCHAR(500) | 是 | — | |
| created_at / updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| deleted_at | DATETIME | 是 | NULL | 软删除 |
product_description_docs 商品介绍文档(富文本·AutoMigrate)
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | 租户隔离 |
| title | VARCHAR(200) | 否 | — | 标题 |
| content | TEXT | 是 | — | 正文 |
| remark | VARCHAR(500) | 是 | — | |
| created_at / updated_at / deleted_at | DATETIME | — | — |
仓库 · 往来单位
warehouses 仓库
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| name | VARCHAR(100) | 否 | — | |
| location | VARCHAR(200) | 是 | NULL | |
| is_default | TINYINT(1) | 否 | 0 | |
| custom_fields | JSON | 是 | NULL | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| deleted_at | DATETIME | 是 | NULL |
PRIMARY (`id`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_shop_id (`shop_id`)
partners 往来单位
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| code | VARCHAR(50) | 是 | NULL | |
| name | VARCHAR(200) | 否 | — | |
| type | SET('supplier','customer') | 否 | supplier | 可同时是供应商和客户 |
| contact | VARCHAR(50) | 是 | NULL | 联系人 |
| phone | VARCHAR(30) | 是 | NULL | |
| address | VARCHAR(255) | 是 | NULL | |
| bank_account | VARCHAR(100) | 是 | NULL | 银行账号 |
| status | ENUM('enabled','disabled') | 否 | enabled | 正常/禁用 |
| custom_fields | JSON | 是 | NULL | |
| remark | VARCHAR(500) | 是 | NULL | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| deleted_at | DATETIME | 是 | NULL |
PRIMARY (`id`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_deleted_at (`deleted_at`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_deleted_at (`deleted_at`)
出入库单据
单据明细含「快照列」(product_code/name/series/spec/batch_no/production_date):导入/审核时拷贝,作历史保真+显示兜底。
stock_in_orders 入库单
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| order_no | VARCHAR(50) | 否 | — | 入库单号 |
| type | VARCHAR(30) | 否 | purchase | 入库类型: purchase采购/return退货/other其他 |
| warehouse_id | BIGINT UNSIGNED | 否 | — | |
| partner_id | BIGINT UNSIGNED | 是 | NULL | 供应商 |
| operator_id | BIGINT UNSIGNED | 否 | — | 经办人 |
| creator_id | BIGINT UNSIGNED | 是 | NULL | 制单人 |
| reviewer_id | BIGINT UNSIGNED | 是 | NULL | 审核人 |
| status | ENUM('draft','pending','approved','rejected') | 否 | draft | |
| order_date | DATE | 否 | — | |
| cost_total | DECIMAL(16,2) | 否 | 0 | 应付合计=Σ总进价(2026-07 消歧,旧列 total_amount 弃用待删) |
| reviewed_at | DATETIME | 是 | NULL | |
| custom_fields | JSON | 是 | NULL | |
| remark | VARCHAR(500) | 是 | NULL | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| deleted_at | DATETIME | 是 | NULL |
PRIMARY (`id`)
UNIQUE uk_order_no (`shop_id`, `order_no`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_warehouse (`warehouse_id`)
INDEX idx_order_date (`order_date`)
INDEX idx_status (`status`)
UNIQUE uk_order_no (`shop_id`, `order_no`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_warehouse (`warehouse_id`)
INDEX idx_order_date (`order_date`)
INDEX idx_status (`status`)
stock_in_items 入库单明细
快照列:
product_code/product_name/series/spec/batch_no/production_date 在导入/录入时拷贝,product_id 可为 0(历史导入占位)。库存页的批次/生产日期实际从这里取(见 inventories 说明)。| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| order_id | BIGINT UNSIGNED | 否 | — | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| product_id | BIGINT UNSIGNED | 否 | — | |
| product_code | VARCHAR(50) | 是 | NULL | 商品编号(源流水号,历史导入) |
| product_name | VARCHAR(255) | 是 | NULL | 商品名称(历史导入快照) |
| series | VARCHAR(100) | 是 | NULL | 系列(历史导入快照) |
| spec | VARCHAR(100) | 是 | NULL | 规格(历史导入快照) |
| quantity | DECIMAL(12,3) | 否 | — | 数量 |
| cost_price | DECIMAL(16,2) | 否 | 0 | 进价·单瓶(旧列 unit_price 弃用待删) |
| cost_amount | DECIMAL(16,2) | 否 | 0 | 总进价=quantity×cost_price(旧列 total_price 弃用待删) |
| batch_no | VARCHAR(50) | 是 | NULL | 批次号 |
| production_date | DATE | 是 | NULL | 生产日期 |
| expire_date | DATE | 是 | NULL | 有效期 |
| custom_fields | JSON | 是 | NULL | |
| remark | VARCHAR(255) | 是 | NULL |
PRIMARY (`id`)
INDEX idx_order_id (`order_id`)
INDEX idx_shop_product (`shop_id`, `product_id`)
INDEX idx_order_id (`order_id`)
INDEX idx_shop_product (`shop_id`, `product_id`)
stock_out_orders 出库单
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| order_no | VARCHAR(50) | 否 | — | |
| type | VARCHAR(30) | 否 | sale | sale销售/return退货/other其他 |
| warehouse_id | BIGINT UNSIGNED | 否 | — | |
| partner_id | BIGINT UNSIGNED | 是 | NULL | 客户 |
| operator_id | BIGINT UNSIGNED | 否 | — | |
| creator_id | BIGINT UNSIGNED | 是 | NULL | 制单人 |
| reviewer_id | BIGINT UNSIGNED | 是 | NULL | |
| status | ENUM('draft','pending','approved','rejected') | 否 | draft | |
| order_date | DATE | 否 | — | |
| sale_total | DECIMAL(16,2) | 否 | 0 | 应收合计=Σ售价小计(旧列 total_amount 弃用待删) |
| profit_total | DECIMAL(16,2) | 否 | 0 | 总利润=Σ(售价>0?(售价-成本)×数量:0),建单落库、确认售价/进价联动重算;仅管理员可见(operator 响应抹零) |
| reviewed_at | DATETIME | 是 | NULL | |
| custom_fields | JSON | 是 | NULL | |
| remark | VARCHAR(500) | 是 | NULL | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| deleted_at | DATETIME | 是 | NULL |
PRIMARY (`id`)
UNIQUE uk_order_no (`shop_id`, `order_no`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_warehouse (`warehouse_id`)
INDEX idx_order_date (`order_date`)
INDEX idx_status (`status`)
UNIQUE uk_order_no (`shop_id`, `order_no`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_warehouse (`warehouse_id`)
INDEX idx_order_date (`order_date`)
INDEX idx_status (`status`)
stock_out_items 出库单明细
当前问题相关:出库行快照
batch_no/production_date 在 App 建单时常为空(选货按 product 聚合、未带批次)。打印回退到 products 主记录——若该 product 也没填,就显示空白,但库存页仍能显示(取自入库明细)。cost_price=成本、sale_price=售价(2026-07 已消歧改名)。| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| order_id | BIGINT UNSIGNED | 否 | — | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| product_id | BIGINT UNSIGNED | 否 | — | |
| product_code | VARCHAR(50) | 是 | NULL | 商品编号(源流水号,历史导入) |
| product_name | VARCHAR(255) | 是 | NULL | 商品名称(历史导入快照) |
| series | VARCHAR(100) | 是 | NULL | 系列(历史导入快照) |
| spec | VARCHAR(100) | 是 | NULL | 规格(历史导入快照) |
| quantity | DECIMAL(12,3) | 否 | — | |
| cost_price | DECIMAL(16,2) | 否 | 0 | 成本单价·入库成本快照(旧列 unit_price 弃用待删;仅管理员可见) |
| sale_price | DECIMAL(16,2) | 否 | 0 | 售价(出库实际销售单价,应收按售价×数量) |
| cost_amount | DECIMAL(16,2) | 否 | 0 | 成本小计=quantity×cost_price(旧列弃用待删;仅管理员可见) |
| sale_amount | DECIMAL(16,2) | 否 | 0 | 售价小计=quantity×sale_price(待定价=0) |
| batch_no | VARCHAR(50) | 是 | NULL | 批次号 |
| production_date | DATE | 是 | NULL | 生产日期 |
| custom_fields | JSON | 是 | NULL | |
| remark | VARCHAR(255) | 是 | NULL |
PRIMARY (`id`)
INDEX idx_order_id (`order_id`)
INDEX idx_shop_product (`shop_id`, `product_id`)
INDEX idx_so_items_shop_code (`shop_id`, `product_code`)
INDEX idx_order_id (`order_id`)
INDEX idx_shop_product (`shop_id`, `product_id`)
INDEX idx_so_items_shop_code (`shop_id`, `product_code`)
库存 · 流水 · 盘点
库存为批次模式:每条 inventories 记录 = 一个入库批次,经 stock_in_item_id 关联其入库明细。
inventories 库存批次记录
批次模式 + 显示口径:每行 = 一个入库批次。列表查询的批次/生产日期取
COALESCE(DATE(sii.production_date), DATE(inv.production_date))、COALESCE(NULLIF(sii.batch_no,''), inv.batch_no)——优先关联入库明细 sii,不读 products。本表 batch_no/production_date 为快照兜底。| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | 主键 |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | 所属门店(多租户隔离,所有查询必带) |
| warehouse_id | BIGINT UNSIGNED | 是 | NULL | 所在仓库;NULL 表示历史导入未指定仓 |
| product_id | BIGINT UNSIGNED | 是 | NULL | 指向 products 的特有产品/序列号;历史导入占位单据可为 NULL/0 |
| stock_in_item_id | BIGINT UNSIGNED | 是 | NULL | 来源入库明细行。批次/生产日期显示优先从此关联取(sii),是本表的「真值上游」 |
| inventory_check_id | BIGINT UNSIGNED | 是 | NULL | 若由盘点调整产生,指向盘点单 inventory_checks |
| quantity | DECIMAL(12,3) | 否 | 0 | 当前批次结存数量(出入库审核时在事务内增减) |
| status | ENUM('stock','on_sale','sold') | 否 | 'stock' | 库存三态(2026-07-07):stock=库存(在库不公开,默认)/ on_sale=在售(公开酒单展示,抽屉 switch 手动挂售)/ sold=已售(出库审核扣光自动置入,留痕不软删;列表默认排除,点已售卡才显示)。公开店铺页只列 on_sale;索引 idx_inv_status |
| product_code | VARCHAR(50) | 是 | NULL | 商品编号快照(拷贝自入库时),product 缺失时兜底显示 |
| product_name | VARCHAR(200) | 是 | NULL | 商品名称快照,兜底显示 |
| series | VARCHAR(100) | 是 | NULL | 系列快照(语义=型号),兜底显示 |
| spec | VARCHAR(100) | 是 | NULL | 规格快照(语义=版本),兜底显示 |
| unit | VARCHAR(20) | 是 | NULL | 单位快照 |
| warehouse_name | VARCHAR(100) | 是 | NULL | 仓库名快照,warehouse 关联缺失时兜底 |
| unit_price | DECIMAL(16,2) | 是 | NULL | 入库成本单价快照 |
| production_date | DATE | 是 | NULL | 生产日期快照兜底(显示口径见上方:优先取 stock_in_item) |
| batch_no | VARCHAR(50) | 是 | NULL | 批次号快照兜底(显示口径见上方:优先取 stock_in_item) |
| supplier_name | VARCHAR(200) | 是 | NULL | 供应商名快照(入库来源) |
| remark | VARCHAR(500) | 是 | NULL | 备注 |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | 创建时间(FIFO 排序依据 idx_fifo 用到) |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted_at | DATETIME | 是 | NULL | 软删除标记,NULL=有效 |
PRIMARY (`id`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_fifo (`shop_id`, `warehouse_id`, `product_id`, `created_at`)
INDEX idx_shop_wh_product (`shop_id`, `warehouse_id`, `product_id`)
INDEX idx_stock_in_item (`stock_in_item_id`)
INDEX idx_inventory_check (`inventory_check_id`)
INDEX idx_deleted_at (`deleted_at`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_fifo (`shop_id`, `warehouse_id`, `product_id`, `created_at`)
INDEX idx_shop_wh_product (`shop_id`, `warehouse_id`, `product_id`)
INDEX idx_stock_in_item (`stock_in_item_id`)
INDEX idx_inventory_check (`inventory_check_id`)
INDEX idx_deleted_at (`deleted_at`)
inventory_logs 库存流水
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| warehouse_id | BIGINT UNSIGNED | 否 | — | |
| product_id | BIGINT UNSIGNED | 否 | — | |
| direction | ENUM('in','out') | 否 | — | |
| quantity | DECIMAL(12,3) | 否 | — | |
| qty_before | DECIMAL(12,3) | 否 | — | 变动前数量 |
| qty_after | DECIMAL(12,3) | 否 | — | 变动后数量 |
| ref_type | VARCHAR(30) | 否 | — | stock_in/stock_out/check |
| ref_id | BIGINT UNSIGNED | 否 | — | 关联单据ID |
| operator_id | BIGINT UNSIGNED | 是 | NULL | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP |
PRIMARY (`id`)
INDEX idx_shop_product (`shop_id`, `product_id`)
INDEX idx_ref (`ref_type`, `ref_id`)
INDEX idx_shop_product (`shop_id`, `product_id`)
INDEX idx_ref (`ref_type`, `ref_id`)
inventory_checks 库存盘点单
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| check_no | VARCHAR(50) | 否 | — | |
| warehouse_id | BIGINT UNSIGNED | 否 | — | |
| operator_id | BIGINT UNSIGNED | 否 | — | |
| status | ENUM('draft','completed') | 否 | draft | |
| check_date | DATE | 否 | — | |
| remark | VARCHAR(500) | 是 | NULL | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP |
PRIMARY (`id`)
UNIQUE uk_check_no (`shop_id`, `check_no`)
INDEX idx_shop_id (`shop_id`)
UNIQUE uk_check_no (`shop_id`, `check_no`)
INDEX idx_shop_id (`shop_id`)
inventory_check_items 盘点明细
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| check_id | BIGINT UNSIGNED | 否 | — | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| product_id | BIGINT UNSIGNED | 否 | — | |
| system_qty | DECIMAL(12,3) | 否 | — | 系统数量 |
| actual_qty | DECIMAL(12,3) | 否 | — | 实际盘点数量 |
| diff_qty | DECIMAL(12,3) | 是 | 计算列 | 差异 |
| remark | VARCHAR(255) | 是 | NULL |
PRIMARY (`id`)
INDEX idx_check_id (`check_id`)
INDEX idx_check_id (`check_id`)
财务
finance_records 财务流水
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| partner_id | BIGINT UNSIGNED | 是 | NULL | |
| type | ENUM('receivable','payable','receipt','payment') | 否 | — | 应收/应付/收款/付款 |
| amount | DECIMAL(16,2) | 否 | — | |
| balance | DECIMAL(16,2) | 否 | — | 操作后余额 |
| status | ENUM('open','closed') | 否 | open | 结清状态(payable/receivable 有效) |
| ref_type | VARCHAR(30) | 是 | NULL | 关联单据类型 |
| ref_id | BIGINT UNSIGNED | 是 | NULL | |
| operator_id | BIGINT UNSIGNED | 否 | — | |
| record_date | DATE | 否 | — | |
| custom_fields | JSON | 是 | NULL | |
| remark | VARCHAR(500) | 是 | NULL | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP |
PRIMARY (`id`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_partner (`partner_id`)
INDEX idx_record_date (`record_date`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_partner (`partner_id`)
INDEX idx_record_date (`record_date`)
配置 · 运维 · 反馈
number_rules 单号规则
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| type | VARCHAR(30) | 否 | — | stock_in/stock_out/check |
| prefix | VARCHAR(20) | 是 | — | 前缀 |
| current_no | INT | 否 | 0 | 当前序号 |
| date_format | VARCHAR(20) | 是 | YYYYMMDD | 日期格式 |
| updated_at | DATETIME | 否 | CURRENT_TIMESTAMP |
PRIMARY (`id`)
UNIQUE uk_shop_type (`shop_id`, `type`)
UNIQUE uk_shop_type (`shop_id`, `type`)
feedbacks 用户意见反馈
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| created_at | DATETIME | 否 | CURRENT_TIMESTAMP | |
| shop_id 租户 | BIGINT UNSIGNED | 否 | — | |
| shop_code | VARCHAR(50) | 是 | NULL | |
| user_id | BIGINT UNSIGNED | 是 | NULL | |
| username | VARCHAR(50) | 是 | NULL | |
| role | VARCHAR(20) | 是 | NULL | |
| type | VARCHAR(20) | 否 | — | bug / suggestion |
| content | TEXT | 是 | — | |
| images | JSON | 是 | — | |
| app_version | VARCHAR(30) | 是 | NULL | |
| platform | VARCHAR(20) | 是 | NULL | |
| client_ip | VARCHAR(60) | 是 | NULL | |
| status | VARCHAR(20) | 否 | new |
PRIMARY (`id`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_user_id (`user_id`)
INDEX idx_type (`type`)
INDEX idx_status (`status`)
INDEX idx_shop_id (`shop_id`)
INDEX idx_user_id (`user_id`)
INDEX idx_type (`type`)
INDEX idx_status (`status`)
error_reports 客户端异常上报(AutoMigrate,无 shop 软删除)
| 列名 | 类型 | 可空 | 默认 | 说明 |
|---|---|---|---|---|
| id PK | BIGINT UNSIGNED | 否 | AUTO_INC | |
| error_type | VARCHAR(30) | 否 | — | flutter_error / zone_error / caught_exception |
| app_version | VARCHAR(30) | 是 | — | |
| platform | VARCHAR(20) | 是 | — | ios/android/web/windows/macos |
| username | VARCHAR(50) | 是 | — | |
| shop_id 租户 | BIGINT UNSIGNED | 是 | — | |
| shop_no | VARCHAR(50) | 是 | — | |
| role | VARCHAR(20) | 是 | — | |
| product_info | VARCHAR(200) | 是 | — | 设备/系统信息 |
| client_ip | VARCHAR(60) | 是 | — | |
| error_msg | TEXT | 否 | — | 错误信息 |
| stack_trace | TEXT | 是 | — | 堆栈 |
| occurred_at | DATETIME | — | — | 发生时间 |
| created_at | DATETIME | — | — | 上报时间 |
生成时间:2026-06-26 · 字段以 schema.sql 为准;产地/保质期/储存/介绍文档/异常上报等表由 GORM AutoMigrate 建,列信息取自 backend/internal/model/。