diff --git a/backend/cmd/seed/main.go b/backend/cmd/seed/main.go index 877be6f..ce48e1e 100644 --- a/backend/cmd/seed/main.go +++ b/backend/cmd/seed/main.go @@ -112,10 +112,10 @@ func main() { // ═══════════════════════════════════════════════════ // 门店 // ═══════════════════════════════════════════════════ - shop := upsert(db, &model.Shop{}, "code = ?", "H001", func() any { + shop := upsert(db, &model.Shop{}, "code = ?", "S001", func() any { return &model.Shop{ Name: "测试酒库门店", - Code: "H001", + Code: "S001", Address: "北京市朝阳区酒仙桥路甲1号", Phone: "010-12345678", ManagerName: "张三", diff --git a/backend/seeds/H001.sql b/backend/seeds/S001.sql similarity index 99% rename from backend/seeds/H001.sql rename to backend/seeds/S001.sql index 24d3be4..70fbb25 100644 --- a/backend/seeds/H001.sql +++ b/backend/seeds/S001.sql @@ -1,6 +1,6 @@ -- ============================================================= --- 测试门店 H001 种子数据 --- 用法: sh scripts/dev.sh seed H001 +-- 测试门店 S001 种子数据 +-- 用法: sh scripts/dev.sh seed S001 -- 前置条件: 数据库表结构已创建(启动一次后端即可) -- 说明: 每次执行会清空并重新写入所有业务数据 -- ============================================================= @@ -30,7 +30,7 @@ SET FOREIGN_KEY_CHECKS = 1; -- ── 门店 ──────────────────────────────────────────────────── -- id=1 INSERT INTO shops (id, name, code, address, phone, manager_name, created_at, updated_at) -VALUES (1, '测试酒库门店', 'H001', '北京市朝阳区建国路88号', '010-12345678', '张总', NOW(), NOW()); +VALUES (1, '测试酒库门店', 'S001', '北京市朝阳区建国路88号', '010-12345678', '张总', NOW(), NOW()); -- ── 用户(密码均为 password123)──────────────────────────── -- bcrypt(password123, cost=10) diff --git a/backend/seeds/S002.sql b/backend/seeds/S002.sql new file mode 100644 index 0000000..05f8b29 --- /dev/null +++ b/backend/seeds/S002.sql @@ -0,0 +1,81 @@ +-- ============================================================= +-- 测试门店 S002 种子数据(空库存版) +-- 用法: sh scripts/dev.sh seed S002 +-- 说明: 基础数据与 S001 相同,入库/出库/库存数据为空,模拟新门店初始状态 +-- ============================================================= + +SET FOREIGN_KEY_CHECKS = 0; + +-- ── 清空(子表先清)──────────────────────────────────────── +TRUNCATE TABLE inventory_check_items; +TRUNCATE TABLE inventory_checks; +TRUNCATE TABLE inventory_logs; +TRUNCATE TABLE inventories; +TRUNCATE TABLE stock_out_items; +TRUNCATE TABLE stock_out_orders; +TRUNCATE TABLE stock_in_items; +TRUNCATE TABLE stock_in_orders; +TRUNCATE TABLE finance_records; +TRUNCATE TABLE number_rules; +TRUNCATE TABLE partners; +TRUNCATE TABLE warehouses; +TRUNCATE TABLE products; +TRUNCATE TABLE product_categories; +TRUNCATE TABLE users; +TRUNCATE TABLE shops; + +SET FOREIGN_KEY_CHECKS = 1; + +-- ── 门店 ──────────────────────────────────────────────────── +INSERT INTO shops (id, name, code, address, phone, manager_name, created_at, updated_at) +VALUES (1, '测试酒库门店', 'S002', '北京市朝阳区建国路88号', '010-12345678', '张总', NOW(), NOW()); + +-- ── 用户(密码均为 password123)──────────────────────────── +SET @pwd = '$2a$10$BNHhJoKHryCCEyKqM.11TeLOnSCV8rNtOqvKHUqaczETXLtH/YE1m'; + +INSERT INTO users (id, shop_id, username, password_hash, real_name, phone, role, is_active, created_at, updated_at) VALUES +(1, 1, 'admin', @pwd, '张三(管理员)', '13800000001', 'admin', 1, NOW(), NOW()), +(2, 1, 'operator', @pwd, '李四(操作员)', '13800000002', 'operator', 1, NOW(), NOW()), +(3, 1, 'test', @pwd, '王五(只读)', '13800000003', 'readonly', 1, NOW(), NOW()); + +-- ── 仓库 ──────────────────────────────────────────────────── +INSERT INTO warehouses (id, shop_id, name, location, is_default, created_at, updated_at) VALUES +(1, 1, '主仓库', 'A栋1层东侧', 1, NOW(), NOW()), +(2, 1, '进口酒专库', 'B栋2层恒温区', 0, NOW(), NOW()); + +-- ── 商品分类 ──────────────────────────────────────────────── +INSERT INTO product_categories (id, shop_id, name, sort_order, created_at, updated_at) VALUES +(1, 1, '白酒', 1, NOW(), NOW()), +(2, 1, '进口烈酒', 2, NOW(), NOW()); + +-- ── 商品 ──────────────────────────────────────────────────── +INSERT INTO products (id, shop_id, code, barcode, name, series, spec, unit, category_id, brand, + purchase_price, sale_price, min_stock, remark, created_at, updated_at) VALUES +(1, 1, 'MT-001', '6901234567890', '飞天茅台 53度 500ml', '茅台', '500ml/瓶', '瓶', 1, '贵州茅台', 2350, 2800, 10, '酱香型白酒,53度,飞天系列', NOW(), NOW()), +(2, 1, 'WLY-001', '6902345678901', '五粮液 52度 500ml', '五粮液', '500ml/瓶', '瓶', 1, '宜宾五粮液', 950, 1200, 6, '浓香型白酒,52度,普五系列', NOW(), NOW()), +(3, 1, 'YH-001', '6903456789012', '洋河梦之蓝 M6 500ml', '洋河', '500ml/瓶', '瓶', 1, '江苏洋河', 560, 680, 6, '浓香型,绵柔苏酒代表', NOW(), NOW()), +(4, 1, 'LZ-001', '6904567890123', '泸州老窖 特曲 500ml', '泸州老窖', '500ml/瓶', '瓶', 1, '泸州老窖', 420, 520, 6, '浓香鼻祖,特曲系列', NOW(), NOW()), +(5, 1, 'JNC-001', '6905678901234', '剑南春 水晶剑 500ml', '剑南春', '500ml/瓶', '瓶', 1, '剑南春', 390, 480, 6, '浓香型,绵竹名酒', NOW(), NOW()), +(6, 1, 'LJ-001', '6906789012345', '郎酒 红花郎10 500ml', '郎酒', '500ml/瓶', '瓶', 1, '古蔺郎酒', 320, 420, 6, '酱香型,赤水河畔酿造', NOW(), NOW()), +(7, 1, 'LF-001', '3760093550058', '拉菲古堡 2018 750ml', '波尔多', '750ml/瓶', '瓶', 2, 'Château Lafite', 3800, 5200, 3, '波尔多一级名庄,2018年份', NOW(), NOW()), +(8, 1, 'RTM-001', '3021691010008', '人头马 VSOP 700ml', '人头马', '700ml/瓶', '瓶', 2, 'Rémy Martin', 480, 680, 3, '法国干邑,VSOP级别', NOW(), NOW()); + +-- ── 往来单位 ──────────────────────────────────────────────── +INSERT INTO partners (id, shop_id, code, name, type, contact, phone, address, bank_account, + credit_limit, balance, remark, created_at, updated_at) VALUES +(1, 1, 'SUP001', '贵州茅台酒股份有限公司', 'supplier', '张经理', '0851-22222001', '贵州省仁怀市茅台镇', '工商银行仁怀支行 6222 0000 0001 0001', 5000000, 0, '茅台系列直供,账期30天', NOW(), NOW()), +(2, 1, 'SUP002', '四川五粮液股份有限公司', 'supplier', '王总监', '0831-33333001', '四川省宜宾市翠屏区', '建设银行宜宾支行 6227 0000 0001 0002', 3000000, 0, '五粮液系列授权经销', NOW(), NOW()), +(3, 1, 'SUP003', '江苏洋河酒厂股份有限公司', 'supplier', '赵主任', '0527-44444001', '江苏省宿迁市洋河新区', '农业银行宿迁支行 6228 0000 0001 0003', 2000000, 0, '洋河梦之蓝系列直供', NOW(), NOW()), +(4, 1, 'SUP004', '四川郎酒股份有限公司', 'supplier', '刘经理', '0830-55555001', '四川省古蔺县二郎镇', '中国银行古蔺支行 6013 0000 0001 0004', 1500000, 0, '郎酒红花郎系列', NOW(), NOW()), +(5, 1, 'CUS001', '北京君悦大酒店', 'customer', '李采购', '010-65888001', '北京市朝阳区建国门外大街2号', '中信银行北京朝阳支行 6217 0000 0002 0001', 500000, 0, '五星级酒店,月结', NOW(), NOW()), +(6, 1, 'CUS002', '上海外滩华尔道夫酒店', 'customer', '陈主任', '021-62308001', '上海市黄浦区中山东一路2号', '浦发银行上海黄浦支行 6210 0000 0002 0002', 800000, 0, '豪华酒店,按季结算', NOW(), NOW()), +(7, 1, 'CUS003', '广州白天鹅宾馆', 'customer', '吴采购', '020-81886001', '广州市荔湾区沙面南街1号', '招商银行广州荔湾支行 6225 0000 0002 0003', 300000, 0, '高端宾馆,月结30天', NOW(), NOW()); + +-- ── 编号规则(序号从 0 开始,无历史单据)────────────────── +INSERT INTO number_rules (id, shop_id, type, prefix, current_no, date_format, updated_at) VALUES +(1, 1, 'stock_in', 'RK', 0, 'YYYYMMDD', NOW()), +(2, 1, 'stock_out', 'CK', 0, 'YYYYMMDD', NOW()), +(3, 1, 'inventory_check', 'PD', 0, 'YYYYMMDD', NOW()); + +-- ── 入库单/出库单/库存/流水/财务:均为空 ────────────────── +-- (模拟新门店初始状态,无历史数据) diff --git a/docs/context/project.md b/docs/context/project.md index e7f72df..365a101 100644 --- a/docs/context/project.md +++ b/docs/context/project.md @@ -54,7 +54,7 @@ jiu/ │ ├── testutil/setup.go # 测试工具包(SQLite DB、CreateTestXxx、GetAuthToken) │ ├── cmd/seed/main.go # 数据库工具(--reset 删表重建,--clear 清空数据) │ ├── seeds/ -│ │ └── H001.sql # 门店 H001 测试种子数据(SQL 命令形式) +│ │ └── S001.sql # 门店 S001 测试种子数据(SQL 命令形式) │ └── schema/schema.sql # 完整建表 SQL(MySQL) ├── client/ # Flutter 跨端客户端 ├── deploy/ @@ -114,7 +114,7 @@ sh scripts/dev.sh --backend-only # 仅启动后端 sh scripts/dev.sh --frontend-only # 仅启动前端 # 数据库 -sh scripts/dev.sh seed H001 # 清空并写入 H001 测试数据(执行 seeds/H001.sql) +sh scripts/dev.sh seed S001 # 清空并写入 S001 测试数据(执行 seeds/S001.sql) sh scripts/dev.sh reset # 删表重建(AutoMigrate) sh scripts/dev.sh clear # 清空所有业务数据(保留表结构) ``` @@ -129,8 +129,8 @@ docker compose -f deploy/docker-compose.yml up -d sh scripts/dev.sh run # 3. 写入测试数据(另开终端) -sh scripts/dev.sh seed H001 -# 写入后可用以下账号登录(门店编号 H001): +sh scripts/dev.sh seed S001 +# 写入后可用以下账号登录(门店编号 S001): # admin / password123 管理员 # operator / password123 操作员 # test / password123 只读 @@ -222,4 +222,5 @@ client/lib/ | 项目上下文 | docs/context/project.md | 本文件,所有 Agent 必读 | | 环境搭建 | docs/dev-setup.md | 工具安装 + 开发脚本详解 + 测试架构 | | Schema | backend/schema/schema.sql | 完整数据库建表 SQL | -| H001 种子 | backend/seeds/H001.sql | 门店 H001 测试数据 | +| S001 种子 | backend/seeds/S001.sql | 门店 S001 测试数据(含完整入库/出库/库存历史) | +| S002 种子 | backend/seeds/S002.sql | 门店 S002 测试数据(基础数据相同,无库存/单据,模拟新门店) | diff --git a/docs/dev-setup.md b/docs/dev-setup.md index 070389d..8202b92 100644 --- a/docs/dev-setup.md +++ b/docs/dev-setup.md @@ -80,14 +80,14 @@ cd client && flutter pub get | 命令 | 说明 | |------|------| -| `sh scripts/dev.sh seed H001` | 清空并写入 H001 测试数据 | +| `sh scripts/dev.sh seed S001` | 清空并写入 S001 测试数据 | | `sh scripts/dev.sh reset` | 删表重建(AutoMigrate) | | `sh scripts/dev.sh clear` | 清空所有业务数据(保留表结构) | 执行完成后会打印测试账号: ``` -门店编号: H001 +门店编号: S001 admin / password123 (管理员,可审核单据) operator / password123 (操作员,可创建/提交单据) test / password123 (只读,仅查看) @@ -101,10 +101,10 @@ test / password123 (只读,仅查看) ### 新增门店测试数据 -参照 `backend/seeds/H001.sql` 创建新文件 `backend/seeds/H002.sql`,然后执行: +参照 `backend/seeds/S001.sql` 创建新文件 `backend/seeds/S002.sql`,然后执行: ```bash -sh scripts/dev.sh seed H002 +sh scripts/dev.sh seed S002 ``` --- @@ -121,7 +121,7 @@ sh scripts/dev.sh run # Flutter 窗口自动弹出 # 第三步(另开终端):写入测试数据 -sh scripts/dev.sh seed H001 +sh scripts/dev.sh seed S001 # 数据库管理界面(可选) # http://localhost:8888 服务器:mysql 用户:root 密码:password 库:jiu_db