feat(fsgx): HJF queue merge, brokerage timing, cycle commission, points release

- Add HJF jobs, services, DAOs, models, admin/API controllers, release command
- Respect brokerage_timing (on_pay vs confirm); dispatch HjfOrderPayJob for queue goods
- Queue-only cycle commission and position index fix in StoreOrderCreateServices
- UserBill income types: frozen_points_brokerage, frozen_points_release
- Timer: fsgx_release_frozen_points -> PointsReleaseServices
- Agent tasks: no_assess filtering for direct/umbrella counts
- Migrations: queue_pool, points_release_log, fsgx_v1 checklist updates
- Admin/uniapp: crontab preset, membership level, user list, finance routes, docs

Made-with: Cursor
This commit is contained in:
apple
2026-03-24 11:59:09 +08:00
parent 434aa8c69d
commit 76ccb24679
59 changed files with 2902 additions and 237 deletions

View File

@@ -0,0 +1,42 @@
/*
Navicat Premium Dump SQL
Source Server : jxy-hjf-db
Source Server Type : MySQL
Source Server Version : 50740 (5.7.40-log)
Source Host : 182.92.142.158:3306
Source Schema : hjfshop
Target Server Type : MySQL
Target Server Version : 50740 (5.7.40-log)
File Encoding : 65001
Date: 24/03/2026 11:17:55
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for eb_points_release_log
-- ----------------------------
DROP TABLE IF EXISTS `eb_points_release_log`;
CREATE TABLE `eb_points_release_log` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`uid` int(11) NOT NULL DEFAULT '0' COMMENT '用户 ID',
`points` int(11) NOT NULL DEFAULT '0' COMMENT '积分数量(绝对值)',
`pm` tinyint(1) NOT NULL DEFAULT '1' COMMENT '收支方向1=收入 0=支出',
`type` varchar(50) NOT NULL DEFAULT '' COMMENT '类型reward_direct/reward_umbrella/release/consume',
`title` varchar(255) NOT NULL DEFAULT '' COMMENT '标题',
`mark` varchar(500) NOT NULL DEFAULT '' COMMENT '备注',
`status` varchar(30) NOT NULL DEFAULT 'frozen' COMMENT '状态frozen=冻结 released=已释放 consumed=已消费',
`order_id` varchar(50) NOT NULL DEFAULT '' COMMENT '关联订单号(奖励来源),释放记录为空',
`release_date` date DEFAULT NULL COMMENT '释放日期(每日释放时填写)',
`add_time` int(11) NOT NULL DEFAULT '0' COMMENT '记录时间Unix 时间戳)',
PRIMARY KEY (`id`),
KEY `idx_uid_type` (`uid`,`type`),
KEY `idx_uid_add_time` (`uid`,`add_time`),
KEY `idx_release_date` (`release_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='积分释放明细日志';
SET FOREIGN_KEY_CHECKS = 1;

View File

@@ -1,15 +1,17 @@
-- ============================================================
-- 黄精粉健康商城 HJF 数据库迁移脚本
-- 版本Phase 2
-- 日期2026-03-15
-- 版本Phase 3改造复用版
-- 日期2026-03-21
-- 执行说明:
-- 1. 兼容 MySQL 5.7+,数据库前缀为 eb_
-- 2. 按顺序执行 P2-01 ~ P2-05
-- 2. 按顺序执行 P3-01 ~ P3-07
-- 3. 所有操作均做幂等处理,可重复执行
-- 4. 遵循 PRD 改造复用原则:会员等级复用 eb_agent_level 体系,
-- 使用 eb_user.agent_level (FK) 代替独立的 member_level 字段
-- ============================================================
-- ============================================================
-- P2-01: 公排池表
-- P3-01: 公排池表
-- ============================================================
CREATE TABLE IF NOT EXISTS `eb_queue_pool` (
@@ -31,7 +33,7 @@ CREATE TABLE IF NOT EXISTS `eb_queue_pool` (
-- ============================================================
-- P2-02: 积分释放日志表
-- P3-02: 积分释放日志表
-- ============================================================
CREATE TABLE IF NOT EXISTS `eb_points_release_log` (
@@ -54,10 +56,42 @@ CREATE TABLE IF NOT EXISTS `eb_points_release_log` (
-- ============================================================
-- P2-03 / P2-04: eb_user / eb_store_product / eb_store_order 扩展字段
-- P3-03: eb_agent_level 扩展字段(改造复用:增加积分奖励字段)
-- ============================================================
DROP PROCEDURE IF EXISTS `hjf_migrate_agent_level`;
DELIMITER $$
CREATE PROCEDURE `hjf_migrate_agent_level`()
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'eb_agent_level' AND COLUMN_NAME = 'direct_reward_points'
) THEN
ALTER TABLE `eb_agent_level`
ADD COLUMN `direct_reward_points` int(11) NOT NULL DEFAULT 0 COMMENT '直推奖励积分(每单)';
END IF;
IF NOT EXISTS (
SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'eb_agent_level' AND COLUMN_NAME = 'umbrella_reward_points'
) THEN
ALTER TABLE `eb_agent_level`
ADD COLUMN `umbrella_reward_points` int(11) NOT NULL DEFAULT 0 COMMENT '伞下奖励积分(每单,级差基数)';
END IF;
END$$
DELIMITER ;
CALL `hjf_migrate_agent_level`();
DROP PROCEDURE IF EXISTS `hjf_migrate_agent_level`;
-- ============================================================
-- P3-04: eb_user / eb_store_product / eb_store_order 扩展字段
--
-- MySQL 5.7 不支持 "ADD COLUMN IF NOT EXISTS"
-- 改用存储过程 + information_schema 实现幂等检查。
-- 注意:不再新增 member_level 字段,复用已有的 agent_level (FK→eb_agent_level.id)
-- ============================================================
DROP PROCEDURE IF EXISTS `hjf_migrate_columns`;
@@ -66,15 +100,7 @@ DELIMITER $$
CREATE PROCEDURE `hjf_migrate_columns`()
BEGIN
-- ---- eb_user 字段 ----
IF NOT EXISTS (
SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'eb_user' AND COLUMN_NAME = 'member_level'
) THEN
ALTER TABLE `eb_user`
ADD COLUMN `member_level` tinyint(1) NOT NULL DEFAULT 0 COMMENT '会员等级0普通 1创客 2云店 3服务商 4分公司';
END IF;
-- ---- eb_user 字段(不含 member_level复用 agent_level----
IF NOT EXISTS (
SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'eb_user' AND COLUMN_NAME = 'no_assess'
@@ -99,14 +125,6 @@ BEGIN
ADD COLUMN `available_points` int(11) NOT NULL DEFAULT 0 COMMENT '可用积分';
END IF;
-- eb_user 索引idx_member_level
IF NOT EXISTS (
SELECT 1 FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'eb_user' AND INDEX_NAME = 'idx_member_level'
) THEN
ALTER TABLE `eb_user` ADD INDEX `idx_member_level` (`member_level`);
END IF;
-- ---- eb_store_product 字段 ----
IF NOT EXISTS (
SELECT 1 FROM information_schema.COLUMNS
@@ -124,7 +142,6 @@ BEGIN
ADD COLUMN `allow_pay_types` varchar(255) NOT NULL DEFAULT '' COMMENT '允许积分支付类型JSON数组';
END IF;
-- eb_store_product 索引idx_is_queue_goods
IF NOT EXISTS (
SELECT 1 FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'eb_store_product' AND INDEX_NAME = 'idx_is_queue_goods'
@@ -141,7 +158,6 @@ BEGIN
ADD COLUMN `is_queue_goods` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否报单商品订单1=是';
END IF;
-- eb_store_order 索引idx_is_queue_goods
IF NOT EXISTS (
SELECT 1 FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'eb_store_order' AND INDEX_NAME = 'idx_is_queue_goods'
@@ -157,115 +173,221 @@ DROP PROCEDURE IF EXISTS `hjf_migrate_columns`;
-- ============================================================
-- P2-05: eb_system_config 初始化配置项
-- P3-05: 初始化会员等级数据到 eb_agent_level改造复用
--
-- 字段说明(与 CRMEB 原表保持一致)
-- menu_name = 配置键名(代码中 SystemConfigService::get() 读取)
-- value = 默认值(字符串)
-- info = 后台显示名称
-- desc = 说明文字
-- config_tab_id = 0不归属某分组便于独立管理
-- status = 1启用
-- 将原分销员等级改为五级会员等级体系
-- grade=1 → 创客 (direct=500, umbrella=0)
-- grade=2 → 云店 (direct=800, umbrella=300)
-- grade=3 → 服务商 (direct=1000, umbrella=200)
-- grade=4 → 分公司 (direct=1300, umbrella=300)
--
-- 注意:普通会员 = agent_level=0无记录不需要插入
--
-- 先将 CRMEB 原有 demo 等级软删除,然后插入 HJF 会员等级
-- ============================================================
UPDATE `eb_agent_level`
SET `is_del` = 1
WHERE `name` NOT IN ('创客', '云店', '服务商', '分公司')
AND `is_del` = 0;
INSERT INTO `eb_agent_level`
(`name`, `grade`, `image`, `color`, `one_brokerage`, `two_brokerage`,
`direct_reward_points`, `umbrella_reward_points`, `status`, `is_del`, `add_time`)
SELECT '创客', 1, '', '#FF9800', 0, 0, 500, 0, 1, 0, UNIX_TIMESTAMP()
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `eb_agent_level` WHERE `name` = '创客' AND `is_del` = 0
);
INSERT INTO `eb_agent_level`
(`name`, `grade`, `image`, `color`, `one_brokerage`, `two_brokerage`,
`direct_reward_points`, `umbrella_reward_points`, `status`, `is_del`, `add_time`)
SELECT '云店', 2, '', '#2196F3', 0, 0, 800, 300, 1, 0, UNIX_TIMESTAMP()
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `eb_agent_level` WHERE `name` = '云店' AND `is_del` = 0
);
INSERT INTO `eb_agent_level`
(`name`, `grade`, `image`, `color`, `one_brokerage`, `two_brokerage`,
`direct_reward_points`, `umbrella_reward_points`, `status`, `is_del`, `add_time`)
SELECT '服务商', 3, '', '#9C27B0', 0, 0, 1000, 200, 1, 0, UNIX_TIMESTAMP()
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `eb_agent_level` WHERE `name` = '服务商' AND `is_del` = 0
);
INSERT INTO `eb_agent_level`
(`name`, `grade`, `image`, `color`, `one_brokerage`, `two_brokerage`,
`direct_reward_points`, `umbrella_reward_points`, `status`, `is_del`, `add_time`)
SELECT '分公司', 4, '', '#F44336', 0, 0, 1300, 300, 1, 0, UNIX_TIMESTAMP()
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `eb_agent_level` WHERE `name` = '分公司' AND `is_del` = 0
);
-- ============================================================
-- P3-06: 初始化等级升级任务到 eb_agent_level_task改造复用
--
-- 新增任务类型:
-- type=6 → 直推报单单数
-- type=7 → 伞下报单业绩(含业绩分离)
-- type=8 → 最低直推人数
--
-- 各等级任务配置:
-- 创客(grade=1): type=6, number=3 (直推3单)
-- 云店(grade=2): type=7, number=30 (伞下30单) + type=8, number=3 (至少3直推)
-- 服务商(grade=3): type=7, number=100 + type=8, number=3
-- 分公司(grade=4): type=7, number=1000 + type=8, number=3
-- ============================================================
DROP PROCEDURE IF EXISTS `hjf_init_agent_tasks`;
DELIMITER $$
CREATE PROCEDURE `hjf_init_agent_tasks`()
BEGIN
DECLARE v_level_id_1 INT DEFAULT 0;
DECLARE v_level_id_2 INT DEFAULT 0;
DECLARE v_level_id_3 INT DEFAULT 0;
DECLARE v_level_id_4 INT DEFAULT 0;
SELECT id INTO v_level_id_1 FROM eb_agent_level WHERE grade = 1 AND is_del = 0 LIMIT 1;
SELECT id INTO v_level_id_2 FROM eb_agent_level WHERE grade = 2 AND is_del = 0 LIMIT 1;
SELECT id INTO v_level_id_3 FROM eb_agent_level WHERE grade = 3 AND is_del = 0 LIMIT 1;
SELECT id INTO v_level_id_4 FROM eb_agent_level WHERE grade = 4 AND is_del = 0 LIMIT 1;
-- 创客直推报单3单
IF v_level_id_1 > 0 AND NOT EXISTS (
SELECT 1 FROM eb_agent_level_task WHERE level_id = v_level_id_1 AND type = 6 AND is_del = 0
) THEN
INSERT INTO eb_agent_level_task (level_id, `name`, type, number, `desc`, sort, status, is_del, add_time)
VALUES (v_level_id_1, '直推报单满3单', 6, 3, '直推下级购买报单商品满3单升级为创客', 1, 1, 0, UNIX_TIMESTAMP());
END IF;
-- 云店伞下报单30单 + 至少3个直推
IF v_level_id_2 > 0 THEN
IF NOT EXISTS (
SELECT 1 FROM eb_agent_level_task WHERE level_id = v_level_id_2 AND type = 7 AND is_del = 0
) THEN
INSERT INTO eb_agent_level_task (level_id, `name`, type, number, `desc`, sort, status, is_del, add_time)
VALUES (v_level_id_2, '伞下报单满30单', 7, 30, '伞下业绩含分离达到30单升级为云店', 1, 1, 0, UNIX_TIMESTAMP());
END IF;
IF NOT EXISTS (
SELECT 1 FROM eb_agent_level_task WHERE level_id = v_level_id_2 AND type = 8 AND is_del = 0
) THEN
INSERT INTO eb_agent_level_task (level_id, `name`, type, number, `desc`, sort, status, is_del, add_time)
VALUES (v_level_id_2, '至少3个直推', 8, 3, '需至少3个直推下级才可升级为云店', 2, 1, 0, UNIX_TIMESTAMP());
END IF;
END IF;
-- 服务商伞下报单100单 + 至少3个直推
IF v_level_id_3 > 0 THEN
IF NOT EXISTS (
SELECT 1 FROM eb_agent_level_task WHERE level_id = v_level_id_3 AND type = 7 AND is_del = 0
) THEN
INSERT INTO eb_agent_level_task (level_id, `name`, type, number, `desc`, sort, status, is_del, add_time)
VALUES (v_level_id_3, '伞下报单满100单', 7, 100, '伞下业绩含分离达到100单升级为服务商', 1, 1, 0, UNIX_TIMESTAMP());
END IF;
IF NOT EXISTS (
SELECT 1 FROM eb_agent_level_task WHERE level_id = v_level_id_3 AND type = 8 AND is_del = 0
) THEN
INSERT INTO eb_agent_level_task (level_id, `name`, type, number, `desc`, sort, status, is_del, add_time)
VALUES (v_level_id_3, '至少3个直推', 8, 3, '需至少3个直推下级才可升级为服务商', 2, 1, 0, UNIX_TIMESTAMP());
END IF;
END IF;
-- 分公司伞下报单1000单 + 至少3个直推
IF v_level_id_4 > 0 THEN
IF NOT EXISTS (
SELECT 1 FROM eb_agent_level_task WHERE level_id = v_level_id_4 AND type = 7 AND is_del = 0
) THEN
INSERT INTO eb_agent_level_task (level_id, `name`, type, number, `desc`, sort, status, is_del, add_time)
VALUES (v_level_id_4, '伞下报单满1000单', 7, 1000, '伞下业绩含分离达到1000单升级为分公司', 1, 1, 0, UNIX_TIMESTAMP());
END IF;
IF NOT EXISTS (
SELECT 1 FROM eb_agent_level_task WHERE level_id = v_level_id_4 AND type = 8 AND is_del = 0
) THEN
INSERT INTO eb_agent_level_task (level_id, `name`, type, number, `desc`, sort, status, is_del, add_time)
VALUES (v_level_id_4, '至少3个直推', 8, 3, '需至少3个直推下级才可升级为分公司', 2, 1, 0, UNIX_TIMESTAMP());
END IF;
END IF;
END$$
DELIMITER ;
CALL `hjf_init_agent_tasks`();
DROP PROCEDURE IF EXISTS `hjf_init_agent_tasks`;
-- ============================================================
-- P3-07: eb_system_config 初始化配置项
-- ============================================================
-- 防止重复执行报错,使用 INSERT IGNORE
INSERT IGNORE INTO `eb_system_config`
(`is_store`, `menu_name`, `type`, `input_type`, `config_tab_id`,
`parameter`, `upload_type`, `required`, `width`, `high`,
`value`, `info`, `desc`, `sort`, `status`)
VALUES
-- 公排触发倍数:每入 N 单退款第1单默认 4
(0, 'hjf_trigger_multiple', 'text', 'input', 0,
'', 0, '', 100, 0,
'4', '公排触发倍数', '每进入N单公排触发退款第1单默认4', 10, 1),
-- 积分每日释放比例(‰,默认 4即 4‰
(0, 'hjf_release_rate', 'text', 'input', 0,
'', 0, '', 100, 0,
'4', '积分每日释放比例(‰)', '每日释放frozen_points × N / 1000默认4即4‰', 20, 1),
-- 提现手续费率(%,默认 7即 7%
(0, 'hjf_fee_rate', 'text', 'input', 0,
'', 0, '', 100, 0,
'7', '提现手续费率(%)', '申请提现时收取的手续费比例默认7%', 30, 1),
'7', '提现手续费率(%)', '申请提现时收取的手续费比例默认7%', 30, 1);
-- 等级升级门槛普通→创客直推N单
(0, 'hjf_level_direct_require_1', 'text', 'input', 0,
'', 0, '', 100, 0,
'3', '创客升级所需直推单数', '普通会员直推N单报单商品后升级为创客默认3', 40, 1),
-- 等级升级门槛创客→云店伞下N单
(0, 'hjf_level_umbrella_require_2', 'text', 'input', 0,
'', 0, '', 100, 0,
'30', '云店升级所需伞下单数', '创客伞下业绩达到N单后升级为云店默认30', 50, 1),
-- ============================================================
-- P3-08: 如果已有旧的 member_level 字段,将数据迁移到 agent_level
-- ============================================================
-- 等级升级门槛云店→服务商伞下N单
(0, 'hjf_level_umbrella_require_3', 'text', 'input', 0,
'', 0, '', 100, 0,
'100', '服务商升级所需伞下单数', '云店伞下业绩达到N单后升级为服务商默认100', 60, 1),
DROP PROCEDURE IF EXISTS `hjf_migrate_member_to_agent_level`;
-- 等级升级门槛服务商→分公司伞下N单
(0, 'hjf_level_umbrella_require_4', 'text', 'input', 0,
'', 0, '', 100, 0,
'1000', '分公司升级所需伞下单数', '服务商伞下业绩达到N单后升级为分公司默认1000', 70, 1),
DELIMITER $$
CREATE PROCEDURE `hjf_migrate_member_to_agent_level`()
BEGIN
-- 直推奖励积分创客直推可得N积分
(0, 'hjf_reward_direct_1', 'text', 'input', 0,
'', 0, '', 100, 0,
'500', '创客直推奖励积分', '创客等级直推一单报单商品可获得的冻结积分默认500', 80, 1),
IF EXISTS (
SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'eb_user' AND COLUMN_NAME = 'member_level'
) THEN
-- 将 member_level 数值映射到 agent_level (FK → eb_agent_level.id)
UPDATE eb_user u
INNER JOIN eb_agent_level al ON al.grade = u.member_level AND al.is_del = 0
SET u.agent_level = al.id
WHERE u.member_level > 0 AND (u.agent_level = 0 OR u.agent_level IS NULL);
END IF;
-- 直推奖励积分:云店
(0, 'hjf_reward_direct_2', 'text', 'input', 0,
'', 0, '', 100, 0,
'800', '云店直推奖励积分', '云店等级直推一单报单商品可获得的冻结积分默认800', 90, 1),
END$$
DELIMITER ;
-- 直推奖励积分:服务商
(0, 'hjf_reward_direct_3', 'text', 'input', 0,
'', 0, '', 100, 0,
'1000', '服务商直推奖励积分', '服务商等级直推一单报单商品可获得的冻结积分默认1000', 100, 1),
-- 直推奖励积分:分公司
(0, 'hjf_reward_direct_4', 'text', 'input', 0,
'', 0, '', 100, 0,
'1300', '分公司直推奖励积分', '分公司等级直推一单报单商品可获得的冻结积分默认1300', 110, 1),
-- 伞下奖励积分:创客(无伞下奖励)
(0, 'hjf_reward_umbrella_1', 'text', 'input', 0,
'', 0, '', 100, 0,
'0', '创客伞下奖励积分', '创客等级伞下奖励积分级差默认0无伞下奖励', 120, 1),
-- 伞下奖励积分:云店
(0, 'hjf_reward_umbrella_2', 'text', 'input', 0,
'', 0, '', 100, 0,
'300', '云店伞下奖励积分', '云店等级伞下奖励积分级差默认300', 130, 1),
-- 伞下奖励积分:服务商
(0, 'hjf_reward_umbrella_3', 'text', 'input', 0,
'', 0, '', 100, 0,
'200', '服务商伞下奖励积分', '服务商等级伞下奖励积分级差默认200', 140, 1),
-- 伞下奖励积分:分公司
(0, 'hjf_reward_umbrella_4', 'text', 'input', 0,
'', 0, '', 100, 0,
'300', '分公司伞下奖励积分', '分公司等级伞下奖励积分级差默认300', 150, 1);
CALL `hjf_migrate_member_to_agent_level`();
DROP PROCEDURE IF EXISTS `hjf_migrate_member_to_agent_level`;
-- ============================================================
-- 迁移完成校验(可手动执行检查)
-- ============================================================
-- SELECT TABLE_NAME FROM information_schema.TABLES
-- WHERE TABLE_SCHEMA = DATABASE()
-- AND TABLE_NAME IN ('eb_queue_pool', 'eb_points_release_log');
-- SELECT id, name, grade, direct_reward_points, umbrella_reward_points
-- FROM eb_agent_level WHERE is_del = 0 ORDER BY grade;
-- SELECT alt.id, al.name AS level_name, alt.type, alt.number, alt.name AS task_name
-- FROM eb_agent_level_task alt
-- JOIN eb_agent_level al ON al.id = alt.level_id
-- WHERE alt.is_del = 0 AND al.is_del = 0
-- ORDER BY al.grade, alt.type;
-- SELECT COLUMN_NAME FROM information_schema.COLUMNS
-- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'eb_user'
-- AND COLUMN_NAME IN ('member_level','no_assess','frozen_points','available_points');
-- SELECT COLUMN_NAME FROM information_schema.COLUMNS
-- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'eb_store_product'
-- AND COLUMN_NAME IN ('is_queue_goods','allow_pay_types');
-- AND COLUMN_NAME IN ('no_assess','frozen_points','available_points');
-- SELECT menu_name, value FROM eb_system_config
-- WHERE menu_name LIKE 'hjf_%' ORDER BY sort;