-- ROI 动态规则引擎(v2.0) — 事件流模型 -- 包含: projects 扩展字段、roi_strategies、project_cost_events、project_revenue_events、 -- project_revenue_mapping、unmapped_revenue_events、sync_logs.source 枚举扩展 -- ── 1. 扩展 projects 表 ── ALTER TABLE `projects` ADD COLUMN `category` enum('cash_cow','efficiency_tool','moat','composite') NULL; --> statement-breakpoint ALTER TABLE `projects` ADD COLUMN `composite_strategies` json NULL; --> statement-breakpoint ALTER TABLE `projects` ADD COLUMN `owner_id` varchar(50) NULL; --> statement-breakpoint ALTER TABLE `projects` ADD COLUMN `tags` json NULL; --> statement-breakpoint ALTER TABLE `projects` ADD COLUMN `launched_at` datetime NULL; --> statement-breakpoint ALTER TABLE `projects` ADD COLUMN `v_asset` double NULL; --> statement-breakpoint CREATE INDEX `idx_projects_category` ON `projects` (`category`); --> statement-breakpoint -- ── 2. 扩展 sync_logs.source 枚举 ── ALTER TABLE `sync_logs` MODIFY COLUMN `source` enum('plane','gitea','ai_okr','roi_cost_ingest','roi_revenue_ingest','roi_amortizer','roi_ai_driver') NOT NULL; --> statement-breakpoint -- ── 3. roi_strategies ── CREATE TABLE IF NOT EXISTS `roi_strategies` ( `id` varchar(50) NOT NULL PRIMARY KEY, `category` enum('cash_cow','efficiency_tool','moat','composite') NOT NULL, `name` varchar(200) NOT NULL, `formula_key` varchar(100) NOT NULL, `params` json NOT NULL, `updated_at` datetime NOT NULL ); --> statement-breakpoint CREATE UNIQUE INDEX `uniq_roi_strategy_category` ON `roi_strategies` (`category`); --> statement-breakpoint -- ── 4. project_cost_events ── CREATE TABLE IF NOT EXISTS `project_cost_events` ( `id` varchar(50) NOT NULL PRIMARY KEY, `project_id` varchar(50) NOT NULL, `event_date` datetime NOT NULL, `cost_type` enum('dev_hours','hardware_bom','service_fee','amortization','other') NOT NULL, `amount` double NOT NULL, `hours` double NULL, `hourly_rate_used` double NULL, `data_source` enum('auto_commits','auto_tasks','plane_actual','manual','amortization_cron') NOT NULL, `ref_type` varchar(50) NULL, `ref_id` varchar(200) NULL, `notes` text NULL, `created_by` varchar(50) NULL, `created_at` datetime NOT NULL ); --> statement-breakpoint CREATE INDEX `idx_cost_events_project_date` ON `project_cost_events` (`project_id`, `event_date`); --> statement-breakpoint CREATE UNIQUE INDEX `uniq_cost_events_ref` ON `project_cost_events` (`project_id`, `ref_type`, `ref_id`); --> statement-breakpoint -- ── 5. project_revenue_events ── CREATE TABLE IF NOT EXISTS `project_revenue_events` ( `id` varchar(50) NOT NULL PRIMARY KEY, `project_id` varchar(50) NOT NULL, `event_date` datetime NOT NULL, `revenue_type` enum('direct_revenue','subscription','saved_cost','asset_value_add','refund','other') NOT NULL, `amount` double NOT NULL, `data_source` enum('api_pulled','manual','calculated','mock') NOT NULL, `ref_type` varchar(50) NULL, `ref_id` varchar(200) NULL, `channel` varchar(50) NULL, `notes` text NULL, `created_by` varchar(50) NULL, `created_at` datetime NOT NULL ); --> statement-breakpoint CREATE INDEX `idx_revenue_events_project_date` ON `project_revenue_events` (`project_id`, `event_date`); --> statement-breakpoint CREATE UNIQUE INDEX `uniq_revenue_events_ref` ON `project_revenue_events` (`project_id`, `ref_type`, `ref_id`); --> statement-breakpoint -- ── 6. project_revenue_mapping ── CREATE TABLE IF NOT EXISTS `project_revenue_mapping` ( `id` varchar(50) NOT NULL PRIMARY KEY, `project_id` varchar(50) NOT NULL, `business_project_key` varchar(100) NOT NULL, `enabled` int NULL DEFAULT 1, `notes` text NULL, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL ); --> statement-breakpoint CREATE UNIQUE INDEX `uniq_revenue_mapping_business_key` ON `project_revenue_mapping` (`business_project_key`); --> statement-breakpoint CREATE INDEX `idx_revenue_mapping_project` ON `project_revenue_mapping` (`project_id`); --> statement-breakpoint -- ── 7. unmapped_revenue_events ── CREATE TABLE IF NOT EXISTS `unmapped_revenue_events` ( `id` varchar(50) NOT NULL PRIMARY KEY, `external_id` varchar(200) NOT NULL, `business_project_key` varchar(100) NOT NULL, `event_date` datetime NOT NULL, `amount` double NOT NULL, `revenue_type` varchar(50) NULL, `channel` varchar(50) NULL, `raw_payload` json NULL, `status` enum('pending','resolved','ignored') NULL DEFAULT 'pending', `resolved_event_id` varchar(50) NULL, `created_at` datetime NOT NULL ); --> statement-breakpoint CREATE UNIQUE INDEX `uniq_unmapped_external_id` ON `unmapped_revenue_events` (`external_id`); --> statement-breakpoint CREATE INDEX `idx_unmapped_status` ON `unmapped_revenue_events` (`status`); --> statement-breakpoint -- ── 8. seed: 4 套默认策略参数 ── INSERT INTO `roi_strategies` (`id`, `category`, `name`, `formula_key`, `params`, `updated_at`) VALUES ('strat-cash-cow', 'cash_cow', '现金牛', 'cash_cow', '{"hourlyRate":400,"commitHourCoef":0.5,"taskHourCoef":6}', NOW()), ('strat-efficiency-tool', 'efficiency_tool', '效能工具', 'efficiency_tool', '{"hourlyRate":400,"commitHourCoef":0.5,"taskHourCoef":6}', NOW()), ('strat-moat', 'moat', '资本护城河', 'moat', '{"hourlyRate":400,"amortYears":3,"commitHourCoef":0.5,"taskHourCoef":6}', NOW()), ('strat-composite', 'composite', '复合型', 'composite', '{"hourlyRate":400,"amortYears":3,"commitHourCoef":0.5,"taskHourCoef":6}', NOW());