feat(old-items): complete reuse workflow and refine miniapp home

This commit is contained in:
2026-08-15 16:38:30 +08:00
parent 65d23eab4a
commit f3737c80be
94 changed files with 7880 additions and 215 deletions
@@ -0,0 +1,102 @@
ALTER TABLE `files` MODIFY `business_type` ENUM('SERVICE_RECORD','PROJECT_COVER','ACTIVITY_COVER','CONTENT_COVER','OLD_ITEM_DONATION_IMAGE') NOT NULL;
CREATE TABLE `old_item_drop_off_points` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `public_id` CHAR(36) NOT NULL,
`name` VARCHAR(120) NOT NULL, `region_text` VARCHAR(120) NOT NULL,
`address_text` VARCHAR(300) NOT NULL, `opening_hours` VARCHAR(200) NOT NULL,
`is_active` BOOLEAN NOT NULL DEFAULT true, `sort_order` INTEGER NOT NULL DEFAULT 0,
`created_by` BIGINT UNSIGNED NOT NULL, `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updated_at` DATETIME(3) NOT NULL, UNIQUE INDEX `old_item_drop_off_points_public_id_key` (`public_id`),
INDEX `old_item_drop_off_points_active_sort_idx` (`is_active`,`sort_order`), PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE `old_item_needs` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `public_id` CHAR(36) NOT NULL,
`client_request_id` CHAR(36) NOT NULL, `request_fingerprint` CHAR(64) NOT NULL,
`title` VARCHAR(160) NOT NULL, `category` ENUM('CLOTHING','BOOKS','HOUSEHOLD','SPORTS') NOT NULL,
`region_text` VARCHAR(120) NOT NULL, `beneficiary_group` VARCHAR(160) NOT NULL, `description` TEXT NOT NULL,
`requested_quantity` INTEGER UNSIGNED NOT NULL, `fulfilled_quantity` INTEGER UNSIGNED NOT NULL DEFAULT 0,
`priority` INTEGER NOT NULL DEFAULT 0, `sort_order` INTEGER NOT NULL DEFAULT 0,
`status` ENUM('DRAFT','PUBLISHED','FULFILLED','CLOSED') NOT NULL DEFAULT 'DRAFT',
`revision` INTEGER UNSIGNED NOT NULL DEFAULT 1, `published_at` DATETIME(3) NULL,
`created_by` BIGINT UNSIGNED NOT NULL, `updated_by` BIGINT UNSIGNED NOT NULL,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `updated_at` DATETIME(3) NOT NULL,
UNIQUE INDEX `old_item_needs_public_id_key` (`public_id`),
UNIQUE INDEX `old_item_needs_creator_request_key` (`created_by`,`client_request_id`),
INDEX `old_item_needs_public_list_idx` (`status`,`category`,`priority`,`sort_order`), PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE `old_item_need_status_history` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `need_id` BIGINT UNSIGNED NOT NULL,
`request_id` CHAR(36) NOT NULL, `request_fingerprint` CHAR(64) NOT NULL,
`from_status` ENUM('DRAFT','PUBLISHED','FULFILLED','CLOSED') NULL,
`to_status` ENUM('DRAFT','PUBLISHED','FULFILLED','CLOSED') NOT NULL,
`operator_user_id` BIGINT UNSIGNED NOT NULL, `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
UNIQUE INDEX `old_item_need_status_history_request_id_key` (`request_id`),
INDEX `old_item_need_history_need_created_idx` (`need_id`,`created_at`), PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE `old_item_donations` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `public_id` CHAR(36) NOT NULL, `donation_no` VARCHAR(32) NOT NULL,
`donor_user_id` BIGINT UNSIGNED NOT NULL, `client_request_id` CHAR(36) NOT NULL, `request_fingerprint` CHAR(64) NOT NULL,
`category` ENUM('CLOTHING','BOOKS','HOUSEHOLD','SPORTS') NOT NULL,
`item_condition` ENUM('NEW','LIKE_NEW','GOOD','FAIR') NOT NULL, `quantity` INTEGER UNSIGNED NOT NULL,
`description_encrypted` TEXT NOT NULL, `method` ENUM('PICKUP','DROP_OFF') NOT NULL,
`contact_name_encrypted` VARCHAR(512) NOT NULL, `mobile_encrypted` VARCHAR(512) NOT NULL, `mobile_hash` CHAR(64) NOT NULL,
`address_encrypted` TEXT NULL, `appointment_at` DATETIME(3) NULL, `drop_off_point_id` BIGINT UNSIGNED NULL,
`target_need_id` BIGINT UNSIGNED NULL, `assigned_user_id` BIGINT UNSIGNED NULL,
`rejection_reason_encrypted` TEXT NULL,
`status` ENUM('SUBMITTED','REJECTED','WAITING_PICKUP','WAITING_DROP_OFF','RECEIVED','PROCESSING','COMPLETED','CANCELLED') NOT NULL DEFAULT 'SUBMITTED',
`revision` INTEGER UNSIGNED NOT NULL DEFAULT 1, `assisted_people` INTEGER UNSIGNED NOT NULL DEFAULT 0,
`received_at` DATETIME(3) NULL, `completed_at` DATETIME(3) NULL,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `updated_at` DATETIME(3) NOT NULL,
UNIQUE INDEX `old_item_donations_public_id_key` (`public_id`), UNIQUE INDEX `old_item_donations_donation_no_key` (`donation_no`),
UNIQUE INDEX `old_item_donations_donor_request_key` (`donor_user_id`,`client_request_id`),
INDEX `old_item_donations_donor_status_created_idx` (`donor_user_id`,`status`,`created_at`),
INDEX `old_item_donations_admin_list_idx` (`status`,`method`,`created_at`),
INDEX `old_item_donations_need_status_idx` (`target_need_id`,`status`), PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE `old_item_donation_status_history` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `donation_id` BIGINT UNSIGNED NOT NULL,
`request_id` CHAR(36) NOT NULL, `request_fingerprint` CHAR(64) NOT NULL,
`from_status` ENUM('SUBMITTED','REJECTED','WAITING_PICKUP','WAITING_DROP_OFF','RECEIVED','PROCESSING','COMPLETED','CANCELLED') NULL,
`to_status` ENUM('SUBMITTED','REJECTED','WAITING_PICKUP','WAITING_DROP_OFF','RECEIVED','PROCESSING','COMPLETED','CANCELLED') NOT NULL,
`note_encrypted` TEXT NULL, `operator_user_id` BIGINT UNSIGNED NOT NULL,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
UNIQUE INDEX `old_item_donation_status_history_request_id_key` (`request_id`),
INDEX `old_item_donation_history_donation_created_idx` (`donation_id`,`created_at`), PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE `old_item_donation_files` (
`donation_id` BIGINT UNSIGNED NOT NULL, `file_id` BIGINT UNSIGNED NOT NULL,
`sort_order` INTEGER NOT NULL DEFAULT 0, `attached_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
INDEX `old_item_donation_files_file_idx` (`file_id`), PRIMARY KEY (`donation_id`,`file_id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `old_item_drop_off_points` ADD CONSTRAINT `old_item_drop_off_points_created_by_fkey` FOREIGN KEY (`created_by`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_needs` ADD CONSTRAINT `old_item_needs_created_by_fkey` FOREIGN KEY (`created_by`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_needs` ADD CONSTRAINT `old_item_needs_updated_by_fkey` FOREIGN KEY (`updated_by`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_need_status_history` ADD CONSTRAINT `old_item_need_history_need_fkey` FOREIGN KEY (`need_id`) REFERENCES `old_item_needs`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_need_status_history` ADD CONSTRAINT `old_item_need_history_operator_fkey` FOREIGN KEY (`operator_user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_donations` ADD CONSTRAINT `old_item_donations_donor_fkey` FOREIGN KEY (`donor_user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_donations` ADD CONSTRAINT `old_item_donations_assignee_fkey` FOREIGN KEY (`assigned_user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_donations` ADD CONSTRAINT `old_item_donations_drop_off_point_fkey` FOREIGN KEY (`drop_off_point_id`) REFERENCES `old_item_drop_off_points`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_donations` ADD CONSTRAINT `old_item_donations_target_need_fkey` FOREIGN KEY (`target_need_id`) REFERENCES `old_item_needs`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_donation_status_history` ADD CONSTRAINT `old_item_donation_history_donation_fkey` FOREIGN KEY (`donation_id`) REFERENCES `old_item_donations`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_donation_status_history` ADD CONSTRAINT `old_item_donation_history_operator_fkey` FOREIGN KEY (`operator_user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_donation_files` ADD CONSTRAINT `old_item_donation_files_donation_fkey` FOREIGN KEY (`donation_id`) REFERENCES `old_item_donations`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_donation_files` ADD CONSTRAINT `old_item_donation_files_file_fkey` FOREIGN KEY (`file_id`) REFERENCES `files`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
INSERT INTO `permissions` (`code`,`name`,`description`) VALUES
('old_items:read','查看旧物善用','查看旧物捐赠、需求与统计'),
('old_items:manage','管理旧物善用','审核、分配并更新旧物捐赠状态'),
('old_item_needs:manage','管理旧物需求','发布、编辑和下架物资需求');
INSERT INTO `role_permissions` (`role_id`,`permission_id`)
SELECT r.id,p.id FROM `roles` r CROSS JOIN `permissions` p
WHERE r.code IN ('ADMIN','SUPER_ADMIN') AND p.code IN ('old_items:read','old_items:manage','old_item_needs:manage');
INSERT INTO `role_permissions` (`role_id`,`permission_id`)
SELECT r.id,p.id FROM `roles` r CROSS JOIN `permissions` p
WHERE r.code IN ('STAFF','PROJECT_MANAGER') AND p.code IN ('old_items:read','old_items:manage')
ON DUPLICATE KEY UPDATE `role_id`=`role_id`;
@@ -0,0 +1,89 @@
CREATE TABLE `old_item_inventory_imports` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`public_id` CHAR(36) NOT NULL,
`client_request_id` CHAR(36) NOT NULL,
`request_fingerprint` CHAR(64) NOT NULL,
`original_filename_encrypted` VARCHAR(512) NOT NULL,
`row_count` INTEGER UNSIGNED NOT NULL,
`created_by` BIGINT UNSIGNED NOT NULL,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
UNIQUE INDEX `old_item_inventory_imports_public_id_key` (`public_id`),
UNIQUE INDEX `old_item_inventory_import_creator_request_key` (`created_by`, `client_request_id`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE `old_item_inventory_items` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`public_id` CHAR(36) NOT NULL,
`inventory_no` VARCHAR(32) NOT NULL,
`source_donation_id` BIGINT UNSIGNED NULL,
`import_id` BIGINT UNSIGNED NULL,
`category` ENUM('CLOTHING','BOOKS','HOUSEHOLD','SPORTS') NOT NULL,
`item_name` VARCHAR(160) NOT NULL,
`quantity` INTEGER UNSIGNED NOT NULL,
`unit` VARCHAR(20) NOT NULL DEFAULT '件',
`storage_location` VARCHAR(160) NOT NULL,
`status` ENUM('IN_STOCK','SORTED','DISINFECTED','OUTBOUND','DELIVERED') NOT NULL DEFAULT 'IN_STOCK',
`target_need_id` BIGINT UNSIGNED NULL,
`beneficiary_id` BIGINT UNSIGNED NULL,
`destination_region` VARCHAR(120) NULL,
`note_encrypted` TEXT NULL,
`landing_at` DATETIME(3) NULL,
`revision` INTEGER UNSIGNED NOT NULL DEFAULT 1,
`created_by` BIGINT UNSIGNED NOT NULL,
`updated_by` BIGINT UNSIGNED NOT NULL,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updated_at` DATETIME(3) NOT NULL,
UNIQUE INDEX `old_item_inventory_items_public_id_key` (`public_id`),
UNIQUE INDEX `old_item_inventory_items_inventory_no_key` (`inventory_no`),
UNIQUE INDEX `old_item_inventory_items_source_donation_id_key` (`source_donation_id`),
INDEX `old_item_inventory_status_category_created_idx` (`status`, `category`, `created_at`),
INDEX `old_item_inventory_need_status_idx` (`target_need_id`, `status`),
INDEX `old_item_inventory_beneficiary_status_idx` (`beneficiary_id`, `status`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE `old_item_inventory_events` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`inventory_item_id` BIGINT UNSIGNED NOT NULL,
`request_id` CHAR(36) NOT NULL,
`request_fingerprint` CHAR(64) NOT NULL,
`event_type` ENUM('INBOUND','SORTED','DISINFECTED','OUTBOUND','DELIVERED') NOT NULL,
`from_status` ENUM('IN_STOCK','SORTED','DISINFECTED','OUTBOUND','DELIVERED') NULL,
`to_status` ENUM('IN_STOCK','SORTED','DISINFECTED','OUTBOUND','DELIVERED') NOT NULL,
`location_text` VARCHAR(160) NULL,
`note_encrypted` TEXT NULL,
`event_at` DATETIME(3) NOT NULL,
`operator_user_id` BIGINT UNSIGNED NOT NULL,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
UNIQUE INDEX `old_item_inventory_events_request_id_key` (`request_id`),
INDEX `old_item_inventory_events_item_event_idx` (`inventory_item_id`, `event_at`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `old_item_inventory_imports` ADD CONSTRAINT `old_item_inventory_imports_created_by_fkey` FOREIGN KEY (`created_by`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_inventory_items` ADD CONSTRAINT `old_item_inventory_items_source_donation_fkey` FOREIGN KEY (`source_donation_id`) REFERENCES `old_item_donations`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_inventory_items` ADD CONSTRAINT `old_item_inventory_items_import_fkey` FOREIGN KEY (`import_id`) REFERENCES `old_item_inventory_imports`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_inventory_items` ADD CONSTRAINT `old_item_inventory_items_target_need_fkey` FOREIGN KEY (`target_need_id`) REFERENCES `old_item_needs`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_inventory_items` ADD CONSTRAINT `old_item_inventory_items_beneficiary_fkey` FOREIGN KEY (`beneficiary_id`) REFERENCES `beneficiary_profiles`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_inventory_items` ADD CONSTRAINT `old_item_inventory_items_created_by_fkey` FOREIGN KEY (`created_by`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_inventory_items` ADD CONSTRAINT `old_item_inventory_items_updated_by_fkey` FOREIGN KEY (`updated_by`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_inventory_events` ADD CONSTRAINT `old_item_inventory_events_item_fkey` FOREIGN KEY (`inventory_item_id`) REFERENCES `old_item_inventory_items`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_inventory_events` ADD CONSTRAINT `old_item_inventory_events_operator_fkey` FOREIGN KEY (`operator_user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
INSERT INTO `permissions` (`code`, `name`, `description`) VALUES
('old_item_inventory:read', '查看旧物台账', '查看旧物物资全流程台账'),
('old_item_inventory:manage', '管理旧物台账', '入库并更新旧物物资流转状态'),
('old_item_inventory:import', '导入旧物台账', '从标准 Excel 模板批量导入物资'),
('old_item_inventory:export', '导出旧物台账', '导出和打印最小化旧物台账');
INSERT INTO `role_permissions` (`role_id`, `permission_id`)
SELECT r.id, p.id FROM `roles` r CROSS JOIN `permissions` p
WHERE r.code IN ('ADMIN','SUPER_ADMIN') AND p.code IN (
'old_item_inventory:read','old_item_inventory:manage','old_item_inventory:import','old_item_inventory:export'
);
INSERT INTO `role_permissions` (`role_id`, `permission_id`)
SELECT r.id, p.id FROM `roles` r CROSS JOIN `permissions` p
WHERE r.code IN ('STAFF','PROJECT_MANAGER') AND p.code IN ('old_item_inventory:read','old_item_inventory:manage')
ON DUPLICATE KEY UPDATE `role_id` = `role_id`;
@@ -0,0 +1,113 @@
CREATE TABLE `old_item_reward_configs` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`public_id` CHAR(36) NOT NULL,
`client_request_id` CHAR(36) NOT NULL,
`request_fingerprint` CHAR(64) NOT NULL,
`version` INTEGER UNSIGNED NOT NULL,
`active_key` VARCHAR(16) NULL,
`certificate_title` VARCHAR(120) NOT NULL,
`certificate_message` VARCHAR(1000) NOT NULL,
`issuer_name` VARCHAR(120) NOT NULL,
`legal_notice` VARCHAR(500) NOT NULL,
`clothing_points` INTEGER UNSIGNED NOT NULL,
`books_points` INTEGER UNSIGNED NOT NULL,
`household_points` INTEGER UNSIGNED NOT NULL,
`sports_points` INTEGER UNSIGNED NOT NULL,
`max_points_per_donation` INTEGER UNSIGNED NOT NULL,
`created_by` BIGINT UNSIGNED NOT NULL,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
UNIQUE INDEX `old_item_reward_configs_public_id_key` (`public_id`),
UNIQUE INDEX `old_item_reward_configs_client_request_id_key` (`client_request_id`),
UNIQUE INDEX `old_item_reward_configs_version_key` (`version`),
UNIQUE INDEX `old_item_reward_configs_active_key_key` (`active_key`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE `old_item_certificates` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`public_id` CHAR(36) NOT NULL,
`certificate_no` VARCHAR(40) NOT NULL,
`donation_id` BIGINT UNSIGNED NOT NULL,
`config_id` BIGINT UNSIGNED NULL,
`issue_request_id` CHAR(36) NOT NULL,
`issue_fingerprint` CHAR(64) NOT NULL,
`active_key` VARCHAR(16) NULL,
`status` ENUM('ISSUED','REVOKED') NOT NULL DEFAULT 'ISSUED',
`recipient_name_encrypted` VARCHAR(512) NOT NULL,
`title_snapshot` VARCHAR(120) NOT NULL,
`message_snapshot` VARCHAR(1000) NOT NULL,
`issuer_snapshot` VARCHAR(120) NOT NULL,
`legal_notice_snapshot` VARCHAR(500) NOT NULL,
`issued_by` BIGINT UNSIGNED NOT NULL,
`issued_at` DATETIME(3) NOT NULL,
`revoked_by` BIGINT UNSIGNED NULL,
`revoked_request_id` CHAR(36) NULL,
`revoked_fingerprint` CHAR(64) NULL,
`revoke_reason_encrypted` TEXT NULL,
`revoked_at` DATETIME(3) NULL,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
UNIQUE INDEX `old_item_certificates_public_id_key` (`public_id`),
UNIQUE INDEX `old_item_certificates_certificate_no_key` (`certificate_no`),
UNIQUE INDEX `old_item_certificates_issue_request_id_key` (`issue_request_id`),
UNIQUE INDEX `old_item_certificates_revoked_request_id_key` (`revoked_request_id`),
UNIQUE INDEX `old_item_certificates_donation_active_key` (`donation_id`, `active_key`),
INDEX `old_item_certificates_donation_issued_idx` (`donation_id`, `issued_at`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE `old_item_point_accounts` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`public_id` CHAR(36) NOT NULL,
`user_id` BIGINT UNSIGNED NOT NULL,
`balance` INTEGER UNSIGNED NOT NULL DEFAULT 0,
`revision` INTEGER UNSIGNED NOT NULL DEFAULT 1,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updated_at` DATETIME(3) NOT NULL,
UNIQUE INDEX `old_item_point_accounts_public_id_key` (`public_id`),
UNIQUE INDEX `old_item_point_accounts_user_id_key` (`user_id`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE `old_item_point_entries` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`public_id` CHAR(36) NOT NULL,
`account_id` BIGINT UNSIGNED NOT NULL,
`user_id` BIGINT UNSIGNED NOT NULL,
`donation_id` BIGINT UNSIGNED NULL,
`config_id` BIGINT UNSIGNED NULL,
`request_id` CHAR(36) NOT NULL,
`request_fingerprint` CHAR(64) NOT NULL,
`source_key` VARCHAR(100) NOT NULL,
`entry_type` ENUM('EARNED','ADJUSTMENT') NOT NULL,
`points_delta` INTEGER NOT NULL,
`balance_after` INTEGER UNSIGNED NOT NULL,
`note_encrypted` TEXT NULL,
`operator_user_id` BIGINT UNSIGNED NOT NULL,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
UNIQUE INDEX `old_item_point_entries_public_id_key` (`public_id`),
UNIQUE INDEX `old_item_point_entries_request_id_key` (`request_id`),
UNIQUE INDEX `old_item_point_entries_source_key_key` (`source_key`),
INDEX `old_item_point_entries_user_created_idx` (`user_id`, `created_at`),
INDEX `old_item_point_entries_donation_idx` (`donation_id`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `old_item_reward_configs` ADD CONSTRAINT `old_item_reward_configs_created_by_fkey` FOREIGN KEY (`created_by`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_certificates` ADD CONSTRAINT `old_item_certificates_donation_fkey` FOREIGN KEY (`donation_id`) REFERENCES `old_item_donations`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_certificates` ADD CONSTRAINT `old_item_certificates_config_fkey` FOREIGN KEY (`config_id`) REFERENCES `old_item_reward_configs`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_certificates` ADD CONSTRAINT `old_item_certificates_issued_by_fkey` FOREIGN KEY (`issued_by`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_certificates` ADD CONSTRAINT `old_item_certificates_revoked_by_fkey` FOREIGN KEY (`revoked_by`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_point_accounts` ADD CONSTRAINT `old_item_point_accounts_user_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_point_entries` ADD CONSTRAINT `old_item_point_entries_account_fkey` FOREIGN KEY (`account_id`) REFERENCES `old_item_point_accounts`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_point_entries` ADD CONSTRAINT `old_item_point_entries_user_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_point_entries` ADD CONSTRAINT `old_item_point_entries_donation_fkey` FOREIGN KEY (`donation_id`) REFERENCES `old_item_donations`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_point_entries` ADD CONSTRAINT `old_item_point_entries_config_fkey` FOREIGN KEY (`config_id`) REFERENCES `old_item_reward_configs`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `old_item_point_entries` ADD CONSTRAINT `old_item_point_entries_operator_fkey` FOREIGN KEY (`operator_user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
INSERT INTO `permissions` (`code`, `name`, `description`) VALUES
('old_item_rewards:read', '查看旧物证书积分', '查看旧物善用证书、积分账户和规则'),
('old_item_rewards:manage', '管理旧物证书积分', '配置规则、补发撤销证书和调整公益积分');
INSERT INTO `role_permissions` (`role_id`, `permission_id`)
SELECT r.id, p.id FROM `roles` r CROSS JOIN `permissions` p
WHERE r.code IN ('ADMIN','SUPER_ADMIN') AND p.code IN ('old_item_rewards:read','old_item_rewards:manage');