- Add tab_scheduling_notifications table with bootstrap via ensureSchedulingTables() - Notify endpoint rewritten: dedup by (suggestion_id, candidate_plate), history list, PATCH /:id for execute/cancel lifecycle - Batch notify endpoint returns success/skipped/failed counts - Suggestions response now carries notificationId + notificationStatus per candidate (joined from active-notification map) - UI: select mode with checkboxes, floating action bar, confirmation modal listing each swap; already-notified items are dimmed and skipped - Detail view badges show sent/executed state, preventing duplicate notify Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
35 lines
1.2 KiB
TypeScript
35 lines
1.2 KiB
TypeScript
import pool from '../../db.js';
|
|
|
|
const CREATE_NOTIFICATIONS_TABLE = `
|
|
CREATE TABLE IF NOT EXISTS tab_scheduling_notifications (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
suggestion_id VARCHAR(128) NOT NULL,
|
|
current_plate VARCHAR(32) NOT NULL,
|
|
candidate_plate VARCHAR(32) NOT NULL,
|
|
operator_id VARCHAR(64),
|
|
operator_name VARCHAR(128),
|
|
status VARCHAR(16) NOT NULL DEFAULT 'sent',
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
executed_at DATETIME NULL,
|
|
notes VARCHAR(500) NULL,
|
|
before_mileage INT NULL,
|
|
after_mileage INT NULL,
|
|
INDEX idx_suggestion_id (suggestion_id),
|
|
INDEX idx_current_plate (current_plate),
|
|
INDEX idx_candidate_plate (candidate_plate),
|
|
INDEX idx_status (status),
|
|
INDEX idx_created_at (created_at)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='智能调度通知/执行记录'
|
|
`;
|
|
|
|
export async function ensureSchedulingTables(): Promise<void> {
|
|
try {
|
|
await pool.query(CREATE_NOTIFICATIONS_TABLE);
|
|
console.log('[scheduling] notifications table ready');
|
|
} catch (e) {
|
|
console.error('[scheduling] failed to ensure tables:', e);
|
|
throw e;
|
|
}
|
|
}
|