diff --git a/pom.xml b/pom.xml index 9cb03ac..6f20803 100644 --- a/pom.xml +++ b/pom.xml @@ -19,6 +19,7 @@ yudao-module-bpm yudao-module-asset yudao-module-ocr + yudao-module-energy ${project.artifactId} diff --git a/sql/energy/2026-03-16-add-hydrogen-station-table.sql b/sql/energy/2026-03-16-add-hydrogen-station-table.sql new file mode 100644 index 0000000..445b0c3 --- /dev/null +++ b/sql/energy/2026-03-16-add-hydrogen-station-table.sql @@ -0,0 +1,62 @@ +-- ========================================== +-- 2026-03-16 Energy 模块优化 +-- 新增加氢站基础信息表(asset 模块) +-- 去掉 energy_station_config 表 +-- ========================================== + +-- ---------------------------- +-- 1. 在 asset 模块创建加氢站表 +-- ---------------------------- +DROP TABLE IF EXISTS `asset_hydrogen_station`; +CREATE TABLE `asset_hydrogen_station` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `name` varchar(100) NOT NULL COMMENT '站点名称', + `short_name` varchar(50) DEFAULT NULL COMMENT '简称', + `station_no` varchar(50) DEFAULT NULL COMMENT '站点编码', + `city` varchar(50) DEFAULT NULL COMMENT '所属城市', + `address` varchar(255) DEFAULT NULL COMMENT '站点地址', + `longitude` varchar(50) DEFAULT NULL COMMENT '经度', + `latitude` varchar(50) DEFAULT NULL COMMENT '纬度', + `contact` varchar(50) DEFAULT NULL COMMENT '联系人', + `phone` varchar(20) DEFAULT NULL COMMENT '联系电话', + `station_type` tinyint DEFAULT NULL COMMENT '站点类型(字典)', + `cooperation_type` tinyint NOT NULL DEFAULT 0 COMMENT '合作类型(0=合作 1=非合作)', + `auto_deduct` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否自动扣款(1=是 0=否)', + `booking_required` tinyint(1) DEFAULT 0 COMMENT '是否需要预约(1=是 0=否)', + `station_status` tinyint NOT NULL DEFAULT 1 COMMENT '站点状态(0=停用 1=启用)', + `start_business` time DEFAULT NULL COMMENT '开始营业时间', + `end_business` time DEFAULT NULL COMMENT '结束营业时间', + `billing_method` tinyint DEFAULT NULL COMMENT '结算方式(字典)', + `cooperation_term` date DEFAULT NULL COMMENT '合作期限', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_station_no` (`station_no`), + KEY `idx_name` (`name`), + KEY `idx_city` (`city`), + KEY `idx_station_status` (`station_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='加氢站基础信息'; + +-- ---------------------------- +-- 2. 删除 energy_station_config 表 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_station_config`; + +-- ---------------------------- +-- 3. 插入测试数据 +-- ---------------------------- +INSERT INTO `asset_hydrogen_station` +(`id`, `name`, `short_name`, `station_no`, `city`, `address`, `contact`, `phone`, + `cooperation_type`, `auto_deduct`, `station_status`, `start_business`, `end_business`, `remark`) +VALUES +(1, '嘉兴嘉燃经开站', '经开站', 'JX001', '嘉兴', '浙江省嘉兴市经济开发区岗山路', '张三', '13800138000', + 0, 1, 1, '08:00:00', '18:00:00', '合作站点,自动扣款'), +(2, '上海临港加氢站', '临港站', 'SH001', '上海', '上海市浦东新区临港新城', '李四', '13900139000', + 0, 1, 1, '07:00:00', '19:00:00', '合作站点,自动扣款'), +(3, '杭州萧山加氢站', '萧山站', 'HZ001', '杭州', '浙江省杭州市萧山区', '王五', '13700137000', + 1, 0, 1, '08:30:00', '17:30:00', '非合作站点,审核后扣款'); diff --git a/sql/energy/check_tables.py b/sql/energy/check_tables.py new file mode 100644 index 0000000..dcc6c94 --- /dev/null +++ b/sql/energy/check_tables.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +""" +检查数据库表结构 +""" +import pymysql + +def check_tables(host, port, user, password, database): + """检查表是否存在及字段""" + try: + connection = pymysql.connect( + host=host, + port=port, + user=user, + password=password, + database=database, + charset='utf8mb4', + cursorclass=pymysql.cursors.DictCursor + ) + + print(f"✓ 连接数据库成功: {database}") + + tables = [ + 'asset_parking', + 'asset_customer', + 'asset_vehicle_base', + 'asset_vehicle_business', + 'asset_contract' + ] + + with connection.cursor() as cursor: + for table in tables: + # 检查表是否存在 + cursor.execute(f"SHOW TABLES LIKE '{table}'") + result = cursor.fetchone() + + if result: + print(f"\n✓ 表 {table} 存在") + + # 显示字段 + cursor.execute(f"DESCRIBE {table}") + columns = cursor.fetchall() + print(f" 字段: {', '.join([col['Field'] for col in columns[:10]])}") + if len(columns) > 10: + print(f" ... 共 {len(columns)} 个字段") + else: + print(f"\n✗ 表 {table} 不存在") + + connection.close() + + except Exception as e: + print(f"✗ 错误: {e}") + +if __name__ == '__main__': + DB_HOST = '47.103.115.36' + DB_PORT = 3306 + DB_USER = 'root' + DB_PASSWORD = 'Passw0rd2026' + + print("检查 oneos_asset 数据库:") + check_tables(DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, 'oneos_asset') + + print("\n" + "="*60) + print("检查 oneos_energy 数据库:") + check_tables(DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, 'oneos_energy') diff --git a/sql/energy/energy_create_tables.sql b/sql/energy/energy_create_tables.sql new file mode 100644 index 0000000..6f22d7a --- /dev/null +++ b/sql/energy/energy_create_tables.sql @@ -0,0 +1,282 @@ +-- ========================================== +-- 能源账单模块建表 SQL(331 一期,9 张表) +-- ========================================== + +-- ---------------------------- +-- 1. energy_hydrogen_record — 加氢原始记录 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_hydrogen_record`; +CREATE TABLE `energy_hydrogen_record` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `station_id` bigint NOT NULL COMMENT '加氢站 ID(关联 asset 模块)', + `plate_number` varchar(20) NOT NULL COMMENT '车牌号', + `hydrogen_date` date NOT NULL COMMENT '加氢日期', + `hydrogen_quantity` decimal(10,2) NOT NULL COMMENT '加氢量(KG)', + `unit_price` decimal(10,2) NOT NULL COMMENT '单价(元/KG)', + `amount` decimal(12,2) NOT NULL COMMENT '金额(以数据源原始值为准,不重新计算)', + `mileage` decimal(12,2) DEFAULT NULL COMMENT '里程数', + `source_type` tinyint NOT NULL COMMENT '数据来源(1=Excel 2=Web 3=API 4=OCR)', + `match_status` tinyint NOT NULL DEFAULT 0 COMMENT '匹配状态(0=未匹配 1=已匹配 2=无法匹配)', + `vehicle_id` bigint DEFAULT NULL COMMENT '匹配到的车辆 ID(匹配后填充)', + `customer_id` bigint DEFAULT NULL COMMENT '匹配到的客户 ID(匹配后填充)', + `upload_batch_no` varchar(64) DEFAULT NULL COMMENT '导入批次号(幂等去重)', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_station_id` (`station_id`), + KEY `idx_plate_number` (`plate_number`), + KEY `idx_hydrogen_date` (`hydrogen_date`), + KEY `idx_match_status` (`match_status`), + KEY `idx_upload_batch_no` (`upload_batch_no`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='加氢原始记录'; + +-- ---------------------------- +-- 2. energy_hydrogen_detail — 加氢明细 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_hydrogen_detail`; +CREATE TABLE `energy_hydrogen_detail` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `record_id` bigint NOT NULL COMMENT '关联原始记录 ID', + `station_id` bigint NOT NULL COMMENT '加氢站 ID', + `vehicle_id` bigint NOT NULL COMMENT '车辆 ID', + `plate_number` varchar(20) NOT NULL COMMENT '车牌号(冗余)', + `hydrogen_date` date NOT NULL COMMENT '加氢日期', + `hydrogen_quantity` decimal(10,2) NOT NULL COMMENT '加氢量(KG)', + `cost_price` decimal(10,2) NOT NULL COMMENT '成本单价(元/KG)', + `cost_amount` decimal(12,2) NOT NULL COMMENT '成本金额', + `customer_price` decimal(10,2) NOT NULL COMMENT '对客单价(元/KG)', + `customer_amount` decimal(12,2) NOT NULL COMMENT '对客金额', + `contract_id` bigint NOT NULL COMMENT '合同 ID', + `customer_id` bigint NOT NULL COMMENT '客户 ID', + `project_name` varchar(100) DEFAULT NULL COMMENT '项目名称(冗余)', + `cost_bearer` tinyint NOT NULL COMMENT '费用承担方(1=客户承担 2=羚牛承担 3=自行结算)', + `pay_method` tinyint NOT NULL COMMENT '支付方式(1=预充值 2=月结算)', + `audit_status` tinyint NOT NULL DEFAULT 0 COMMENT '审核状态(0=待审核 1=已审核 2=已驳回)', + `audit_remark` varchar(500) DEFAULT NULL COMMENT '审核备注', + `deduction_status` tinyint NOT NULL DEFAULT 0 COMMENT '扣款状态(0=未扣款 1=已扣款)', + `settlement_status` tinyint NOT NULL DEFAULT 0 COMMENT '结算状态(0=未结算 1=已结算)', + `bill_id` bigint DEFAULT NULL COMMENT '关联账单 ID', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_record_id` (`record_id`), + KEY `idx_station_id` (`station_id`), + KEY `idx_vehicle_id` (`vehicle_id`), + KEY `idx_customer_id` (`customer_id`), + KEY `idx_contract_id` (`contract_id`), + KEY `idx_bill_id` (`bill_id`), + KEY `idx_audit_status` (`audit_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='加氢明细'; + +-- ---------------------------- +-- 3. energy_bill — 能源账单 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_bill`; +CREATE TABLE `energy_bill` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `bill_code` varchar(32) NOT NULL COMMENT '账单编号(唯一)', + `energy_type` tinyint NOT NULL COMMENT '能源类型(1=氢 2=电 3=ETC)', + `customer_id` bigint NOT NULL COMMENT '客户 ID', + `customer_name` varchar(100) DEFAULT NULL COMMENT '客户名称(冗余)', + `contract_id` bigint NOT NULL COMMENT '合同 ID', + `station_id` bigint DEFAULT NULL COMMENT '加氢站 ID', + `station_name` varchar(100) DEFAULT NULL COMMENT '站点名称(冗余)', + `bill_period_start` date NOT NULL COMMENT '账单周期开始日期', + `bill_period_end` date NOT NULL COMMENT '账单周期结束日期', + `receivable_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '应收总额', + `actual_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '实收总额(receivable_amount + adjustment_amount)', + `adjustment_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '调整总额(可正可负)', + `paid_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '已收金额', + `total_quantity` decimal(12,2) NOT NULL DEFAULT 0.00 COMMENT '总加氢量/总度数', + `detail_count` int NOT NULL DEFAULT 0 COMMENT '明细条数', + `status` tinyint NOT NULL DEFAULT 0 COMMENT '账单状态(0=草稿 1=已生成 2=已作废)', + `audit_status` tinyint NOT NULL DEFAULT 0 COMMENT '审核状态(0=待审核 1=已审核 2=已驳回)', + `submit_status` tinyint NOT NULL DEFAULT 0 COMMENT '提交状态(0=未提交 1=已提交 2=已驳回)', + `payment_status` tinyint NOT NULL DEFAULT 0 COMMENT '支付状态(0=未支付 1=部分支付 2=已结清)', + `auditor_id` bigint DEFAULT NULL COMMENT '审核人 ID', + `audit_time` datetime DEFAULT NULL COMMENT '审核时间', + `audit_remark` varchar(500) DEFAULT NULL COMMENT '审核备注', + `submit_time` datetime DEFAULT NULL COMMENT '提交时间', + `generate_time` datetime DEFAULT NULL COMMENT '账单生成时间', + `yos_bill_code` varchar(64) DEFAULT NULL COMMENT 'YOS 账单编号', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_bill_code` (`bill_code`), + KEY `idx_customer_id` (`customer_id`), + KEY `idx_contract_id` (`contract_id`), + KEY `idx_station_id` (`station_id`), + KEY `idx_bill_period` (`bill_period_start`, `bill_period_end`), + KEY `idx_status` (`status`), + KEY `idx_audit_status` (`audit_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='能源账单'; + +-- ---------------------------- +-- 4. energy_bill_adjustment — 账单调整记录 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_bill_adjustment`; +CREATE TABLE `energy_bill_adjustment` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `bill_id` bigint NOT NULL COMMENT '关联账单 ID', + `detail_id` bigint DEFAULT NULL COMMENT '关联明细 ID(可选)', + `adjustment_type` tinyint NOT NULL COMMENT '调整类型(1=增加 2=减少)', + `amount` decimal(12,2) NOT NULL COMMENT '调整金额(正数)', + `reason` varchar(500) DEFAULT NULL COMMENT '调整原因', + `attachment_urls` varchar(1000) DEFAULT NULL COMMENT '附件 URL(JSON 数组)', + `operator_id` bigint DEFAULT NULL COMMENT '操作人 ID', + `operate_time` datetime DEFAULT NULL COMMENT '操作时间', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_bill_id` (`bill_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='账单调整记录'; + +-- ---------------------------- +-- 5. energy_account — 客户能源总账户 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_account`; +CREATE TABLE `energy_account` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `customer_id` bigint NOT NULL COMMENT '客户 ID(唯一)', + `balance` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '当前余额(可为负数)', + `init_balance` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '初始余额', + `accumulated_recharge` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计充值', + `accumulated_hydrogen` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计氢费', + `accumulated_electric` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计电费', + `accumulated_consume` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计消费(所有能源类型合计)', + `reminder_threshold` decimal(14,2) DEFAULT NULL COMMENT '提醒阈值(低于此值触发预警)', + `account_status` tinyint NOT NULL DEFAULT 0 COMMENT '账户状态(0=正常 1=预警 2=欠费)', + `last_recharge_date` date DEFAULT NULL COMMENT '最后充值日期', + `version` int NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_customer_id` (`customer_id`), + KEY `idx_account_status` (`account_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='客户能源总账户'; + +-- ---------------------------- +-- 6. energy_project_account — 项目账户 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_project_account`; +CREATE TABLE `energy_project_account` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `account_id` bigint NOT NULL COMMENT '关联总账户 ID', + `contract_id` bigint NOT NULL COMMENT '合同 ID(唯一)', + `project_name` varchar(100) DEFAULT NULL COMMENT '项目名称', + `project_balance` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '项目余额', + `project_remit_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计划账金额', + `project_hydrogen_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计氢费', + `project_electric_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计电费', + `project_consume_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计消费', + `reminder_threshold` decimal(14,2) DEFAULT NULL COMMENT '提醒阈值', + `account_status` tinyint NOT NULL DEFAULT 0 COMMENT '账户状态(0=正常 1=预警 2=欠费)', + `version` int NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_contract_id` (`contract_id`), + KEY `idx_account_id` (`account_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目账户'; + +-- ---------------------------- +-- 7. energy_account_flow — 统一余额变更流水 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_account_flow`; +CREATE TABLE `energy_account_flow` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `account_id` bigint NOT NULL COMMENT '关联总账户 ID', + `project_account_id` bigint DEFAULT NULL COMMENT '关联项目账户 ID(可选)', + `flow_type` tinyint NOT NULL COMMENT '流水类型(1=充值 2=扣款 3=冲正 4=划账 5=退款)', + `amount` decimal(14,2) NOT NULL COMMENT '变动金额', + `balance_before` decimal(14,2) NOT NULL COMMENT '变动前余额(总账户级别)', + `balance_after` decimal(14,2) NOT NULL COMMENT '变动后余额(总账户级别)', + `project_balance_before` decimal(14,2) DEFAULT NULL COMMENT '变动前项目余额(仅项目账户操作时填写)', + `project_balance_after` decimal(14,2) DEFAULT NULL COMMENT '变动后项目余额(仅项目账户操作时填写)', + `biz_type` tinyint NOT NULL COMMENT '业务类型(1=加氢扣款 2=账单结算 3=手动调整 ...)', + `biz_id` bigint DEFAULT NULL COMMENT '关联单据 ID', + `biz_code` varchar(64) DEFAULT NULL COMMENT '关联单据编号', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `operator_id` bigint DEFAULT NULL COMMENT '操作人 ID', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_account_id` (`account_id`), + KEY `idx_project_account_id` (`project_account_id`), + KEY `idx_biz_type_biz_id` (`biz_type`, `biz_id`), + KEY `idx_create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='统一余额变更流水'; + +-- ---------------------------- +-- 8. energy_station_price — 加氢站客户价格 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_station_price`; +CREATE TABLE `energy_station_price` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `station_id` bigint NOT NULL COMMENT '加氢站 ID', + `customer_id` bigint NOT NULL COMMENT '客户 ID', + `cost_price` decimal(10,2) NOT NULL COMMENT '成本价(元/KG)', + `customer_price` decimal(10,2) NOT NULL COMMENT '对客价(元/KG)', + `effective_date` date NOT NULL COMMENT '生效日期', + `expiry_date` date DEFAULT NULL COMMENT '失效日期(可空,空=永久生效)', + `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态(0=生效中 1=已失效)', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_station_customer_date` (`station_id`, `customer_id`, `effective_date`), + KEY `idx_station_id` (`station_id`), + KEY `idx_customer_id` (`customer_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='加氢站客户价格'; + +-- ---------------------------- +-- 9. energy_station_config — 加氢站扣款配置 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_station_config`; +CREATE TABLE `energy_station_config` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `station_id` bigint NOT NULL COMMENT '加氢站 ID(唯一,每站一条记录)', + `auto_deduct` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否自动扣款(1=是 0=否)', + `cooperation_type` tinyint NOT NULL DEFAULT 0 COMMENT '合作类型(0=合作 1=非合作)', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_station_id` (`station_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='加氢站扣款配置'; diff --git a/sql/energy/energy_init_all.sql b/sql/energy/energy_init_all.sql new file mode 100644 index 0000000..7afc3e6 --- /dev/null +++ b/sql/energy/energy_init_all.sql @@ -0,0 +1,432 @@ +-- ========================================== +-- Energy 模块一键初始化脚本 +-- 使用方式: +-- 1. 用数据库工具连接 47.103.115.36:3306 (root/Passw0rd2026) +-- 2. 直接执行本脚本(脚本内部会切换数据库) +-- ========================================== + +-- ========================================== +-- 第一部分: 创建 oneos_energy 数据库 + 建表 +-- ========================================== +CREATE DATABASE IF NOT EXISTS `oneos_energy` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +USE `oneos_energy`; + +-- ---------------------------- +-- 1. energy_hydrogen_record — 加氢原始记录 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_hydrogen_record`; +CREATE TABLE `energy_hydrogen_record` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `station_id` bigint NOT NULL COMMENT '加氢站 ID(关联 asset 模块)', + `plate_number` varchar(20) NOT NULL COMMENT '车牌号', + `hydrogen_date` date NOT NULL COMMENT '加氢日期', + `hydrogen_quantity` decimal(10,2) NOT NULL COMMENT '加氢量(KG)', + `unit_price` decimal(10,2) NOT NULL COMMENT '单价(元/KG)', + `amount` decimal(12,2) NOT NULL COMMENT '金额(以数据源原始值为准,不重新计算)', + `mileage` decimal(12,2) DEFAULT NULL COMMENT '里程数', + `source_type` tinyint NOT NULL COMMENT '数据来源(1=Excel 2=Web 3=API 4=OCR)', + `match_status` tinyint NOT NULL DEFAULT 0 COMMENT '匹配状态(0=未匹配 1=已匹配 2=无法匹配)', + `vehicle_id` bigint DEFAULT NULL COMMENT '匹配到的车辆 ID(匹配后填充)', + `customer_id` bigint DEFAULT NULL COMMENT '匹配到的客户 ID(匹配后填充)', + `upload_batch_no` varchar(64) DEFAULT NULL COMMENT '导入批次号(幂等去重)', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_station_id` (`station_id`), + KEY `idx_plate_number` (`plate_number`), + KEY `idx_hydrogen_date` (`hydrogen_date`), + KEY `idx_match_status` (`match_status`), + KEY `idx_upload_batch_no` (`upload_batch_no`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='加氢原始记录'; + +-- ---------------------------- +-- 2. energy_hydrogen_detail — 加氢明细 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_hydrogen_detail`; +CREATE TABLE `energy_hydrogen_detail` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `record_id` bigint NOT NULL COMMENT '关联原始记录 ID', + `station_id` bigint NOT NULL COMMENT '加氢站 ID', + `vehicle_id` bigint NOT NULL COMMENT '车辆 ID', + `plate_number` varchar(20) NOT NULL COMMENT '车牌号(冗余)', + `hydrogen_date` date NOT NULL COMMENT '加氢日期', + `hydrogen_quantity` decimal(10,2) NOT NULL COMMENT '加氢量(KG)', + `cost_price` decimal(10,2) NOT NULL COMMENT '成本单价(元/KG)', + `cost_amount` decimal(12,2) NOT NULL COMMENT '成本金额', + `customer_price` decimal(10,2) NOT NULL COMMENT '对客单价(元/KG)', + `customer_amount` decimal(12,2) NOT NULL COMMENT '对客金额', + `contract_id` bigint NOT NULL COMMENT '合同 ID', + `customer_id` bigint NOT NULL COMMENT '客户 ID', + `project_name` varchar(100) DEFAULT NULL COMMENT '项目名称(冗余)', + `cost_bearer` tinyint NOT NULL COMMENT '费用承担方(1=客户承担 2=羚牛承担 3=自行结算)', + `pay_method` tinyint NOT NULL COMMENT '支付方式(1=预充值 2=月结算)', + `audit_status` tinyint NOT NULL DEFAULT 0 COMMENT '审核状态(0=待审核 1=已审核 2=已驳回)', + `audit_remark` varchar(500) DEFAULT NULL COMMENT '审核备注', + `deduction_status` tinyint NOT NULL DEFAULT 0 COMMENT '扣款状态(0=未扣款 1=已扣款)', + `settlement_status` tinyint NOT NULL DEFAULT 0 COMMENT '结算状态(0=未结算 1=已结算)', + `bill_id` bigint DEFAULT NULL COMMENT '关联账单 ID', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_record_id` (`record_id`), + KEY `idx_station_id` (`station_id`), + KEY `idx_vehicle_id` (`vehicle_id`), + KEY `idx_customer_id` (`customer_id`), + KEY `idx_contract_id` (`contract_id`), + KEY `idx_bill_id` (`bill_id`), + KEY `idx_audit_status` (`audit_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='加氢明细'; + +-- ---------------------------- +-- 3. energy_bill — 能源账单 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_bill`; +CREATE TABLE `energy_bill` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `bill_code` varchar(32) NOT NULL COMMENT '账单编号(唯一)', + `energy_type` tinyint NOT NULL COMMENT '能源类型(1=氢 2=电 3=ETC)', + `customer_id` bigint NOT NULL COMMENT '客户 ID', + `customer_name` varchar(100) DEFAULT NULL COMMENT '客户名称(冗余)', + `contract_id` bigint NOT NULL COMMENT '合同 ID', + `station_id` bigint DEFAULT NULL COMMENT '加氢站 ID', + `station_name` varchar(100) DEFAULT NULL COMMENT '站点名称(冗余)', + `cooperation_type` tinyint DEFAULT NULL COMMENT '合作模式(1=预充值 2=月结算)', + `bill_period_start` date NOT NULL COMMENT '账单周期开始日期', + `bill_period_end` date NOT NULL COMMENT '账单周期结束日期', + `receivable_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '应收总额', + `actual_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '实收总额(receivable_amount + adjustment_amount)', + `adjustment_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '调整总额(可正可负)', + `paid_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '已收金额', + `total_quantity` decimal(12,2) NOT NULL DEFAULT 0.00 COMMENT '总加氢量/总度数', + `detail_count` int NOT NULL DEFAULT 0 COMMENT '明细条数', + `status` tinyint NOT NULL DEFAULT 0 COMMENT '账单状态(0=草稿 1=已生成 2=已作废)', + `audit_status` tinyint NOT NULL DEFAULT 0 COMMENT '审核状态(0=待审核 1=已审核 2=已驳回)', + `submit_status` tinyint NOT NULL DEFAULT 0 COMMENT '提交状态(0=未提交 1=已提交 2=已驳回)', + `payment_status` tinyint NOT NULL DEFAULT 0 COMMENT '支付状态(0=未支付 1=部分支付 2=已结清)', + `auditor_id` bigint DEFAULT NULL COMMENT '审核人 ID', + `audit_time` datetime DEFAULT NULL COMMENT '审核时间', + `audit_remark` varchar(500) DEFAULT NULL COMMENT '审核备注', + `submit_time` datetime DEFAULT NULL COMMENT '提交时间', + `generate_time` datetime DEFAULT NULL COMMENT '账单生成时间', + `yos_bill_code` varchar(64) DEFAULT NULL COMMENT 'YOS 账单编号', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_bill_code` (`bill_code`), + KEY `idx_customer_id` (`customer_id`), + KEY `idx_contract_id` (`contract_id`), + KEY `idx_station_id` (`station_id`), + KEY `idx_bill_period` (`bill_period_start`, `bill_period_end`), + KEY `idx_status` (`status`), + KEY `idx_audit_status` (`audit_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='能源账单'; + +-- ---------------------------- +-- 4. energy_bill_adjustment — 账单调整记录 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_bill_adjustment`; +CREATE TABLE `energy_bill_adjustment` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `bill_id` bigint NOT NULL COMMENT '关联账单 ID', + `detail_id` bigint DEFAULT NULL COMMENT '关联明细 ID(可选)', + `adjustment_type` tinyint NOT NULL COMMENT '调整类型(1=增加 2=减少)', + `amount` decimal(12,2) NOT NULL COMMENT '调整金额(正数)', + `reason` varchar(500) DEFAULT NULL COMMENT '调整原因', + `attachment_urls` varchar(1000) DEFAULT NULL COMMENT '附件 URL(JSON 数组)', + `operator_id` bigint DEFAULT NULL COMMENT '操作人 ID', + `operate_time` datetime DEFAULT NULL COMMENT '操作时间', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_bill_id` (`bill_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='账单调整记录'; + +-- ---------------------------- +-- 5. energy_account — 客户能源总账户 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_account`; +CREATE TABLE `energy_account` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `customer_id` bigint NOT NULL COMMENT '客户 ID(唯一)', + `balance` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '当前余额(可为负数)', + `init_balance` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '初始余额', + `accumulated_recharge` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计充值', + `accumulated_hydrogen` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计氢费', + `accumulated_electric` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计电费', + `accumulated_consume` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计消费(所有能源类型合计)', + `reminder_threshold` decimal(14,2) DEFAULT NULL COMMENT '提醒阈值(低于此值触发预警)', + `account_status` tinyint NOT NULL DEFAULT 0 COMMENT '账户状态(0=正常 1=预警 2=欠费)', + `last_recharge_date` date DEFAULT NULL COMMENT '最后充值日期', + `version` int NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_customer_id` (`customer_id`), + KEY `idx_account_status` (`account_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='客户能源总账户'; + +-- ---------------------------- +-- 6. energy_project_account — 项目账户 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_project_account`; +CREATE TABLE `energy_project_account` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `account_id` bigint NOT NULL COMMENT '关联总账户 ID', + `contract_id` bigint NOT NULL COMMENT '合同 ID(唯一)', + `project_name` varchar(100) DEFAULT NULL COMMENT '项目名称', + `project_balance` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '项目余额', + `project_remit_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计划账金额', + `project_hydrogen_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计氢费', + `project_electric_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计电费', + `project_consume_amount` decimal(14,2) NOT NULL DEFAULT 0.00 COMMENT '累计消费', + `reminder_threshold` decimal(14,2) DEFAULT NULL COMMENT '提醒阈值', + `account_status` tinyint NOT NULL DEFAULT 0 COMMENT '账户状态(0=正常 1=预警 2=欠费)', + `version` int NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_contract_id` (`contract_id`), + KEY `idx_account_id` (`account_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目账户'; + +-- ---------------------------- +-- 7. energy_account_flow — 统一余额变更流水 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_account_flow`; +CREATE TABLE `energy_account_flow` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `account_id` bigint NOT NULL COMMENT '关联总账户 ID', + `project_account_id` bigint DEFAULT NULL COMMENT '关联项目账户 ID(可选)', + `flow_type` tinyint NOT NULL COMMENT '流水类型(1=充值 2=扣款 3=冲正 4=划账 5=退款)', + `amount` decimal(14,2) NOT NULL COMMENT '变动金额', + `balance_before` decimal(14,2) NOT NULL COMMENT '变动前余额(总账户级别)', + `balance_after` decimal(14,2) NOT NULL COMMENT '变动后余额(总账户级别)', + `project_balance_before` decimal(14,2) DEFAULT NULL COMMENT '变动前项目余额(仅项目账户操作时填写)', + `project_balance_after` decimal(14,2) DEFAULT NULL COMMENT '变动后项目余额(仅项目账户操作时填写)', + `biz_type` tinyint NOT NULL COMMENT '业务类型(1=加氢扣款 2=账单结算 3=手动调整 ...)', + `biz_id` bigint DEFAULT NULL COMMENT '关联单据 ID', + `biz_code` varchar(64) DEFAULT NULL COMMENT '关联单据编号', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `operator_id` bigint DEFAULT NULL COMMENT '操作人 ID', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_account_id` (`account_id`), + KEY `idx_project_account_id` (`project_account_id`), + KEY `idx_biz_type_biz_id` (`biz_type`, `biz_id`), + KEY `idx_create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='统一余额变更流水'; + +-- ---------------------------- +-- 8. energy_station_price — 加氢站客户价格 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_station_price`; +CREATE TABLE `energy_station_price` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `station_id` bigint NOT NULL COMMENT '加氢站 ID', + `customer_id` bigint NOT NULL COMMENT '客户 ID', + `cost_price` decimal(10,2) NOT NULL COMMENT '成本价(元/KG)', + `customer_price` decimal(10,2) NOT NULL COMMENT '对客价(元/KG)', + `effective_date` date NOT NULL COMMENT '生效日期', + `expiry_date` date DEFAULT NULL COMMENT '失效日期(可空,空=永久生效)', + `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态(0=生效中 1=已失效)', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_station_customer_date` (`station_id`, `customer_id`, `effective_date`), + KEY `idx_station_id` (`station_id`), + KEY `idx_customer_id` (`customer_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='加氢站客户价格'; + +-- ---------------------------- +-- 9. energy_station_config — 加氢站扣款配置 +-- ---------------------------- +DROP TABLE IF EXISTS `energy_station_config`; +CREATE TABLE `energy_station_config` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `station_id` bigint NOT NULL COMMENT '加氢站 ID(唯一,每站一条记录)', + `auto_deduct` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否自动扣款(1=是 0=否)', + `cooperation_type` tinyint NOT NULL DEFAULT 0 COMMENT '合作类型(0=合作 1=非合作)', + `auto_match` tinyint DEFAULT 1 COMMENT '自动匹配开关(0=关闭 1=开启)', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_station_id` (`station_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='加氢站扣款配置'; + + +-- ========================================== +-- 第二部分: 菜单权限(在 oneos_system 数据库执行) +-- ========================================== +USE `oneos_system`; + +-- 一级菜单: 能源管理(目录,type=1) +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5200, '能源管理', '', 1, 50, 0, '/energy', 'ep:lightning', NULL, NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 二级菜单(type=2) +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5201, '加氢记录管理', 'energy:hydrogen-record:query', 2, 1, 5200, 'hydrogen-record', 'ep:document', 'energy/hydrogen-record/index', 'EnergyHydrogenRecord', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5202, '加氢明细管理', 'energy:hydrogen-detail:query', 2, 2, 5200, 'hydrogen-detail', 'ep:list', 'energy/hydrogen-detail/index', 'EnergyHydrogenDetail', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5203, '能源账单管理', 'energy:bill:query', 2, 3, 5200, 'bill', 'ep:tickets', 'energy/bill/index', 'EnergyBill', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5204, '能源账户管理', 'energy:account:query', 2, 4, 5200, 'account', 'ep:wallet', 'energy/account/index', 'EnergyAccount', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5205, '价格管理', 'energy:station-price:query', 2, 5, 5200, 'station-price', 'ep:price-tag', 'energy/station-price/index', 'EnergyStationPrice', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5206, '加氢站配置', 'energy:station-config:query', 2, 6, 5200, 'station-config', 'ep:setting', 'energy/station-config/index', 'EnergyStationConfig', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 三级按钮/权限(type=3) + +-- 加氢记录管理(parent=5201) +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5210, '加氢记录查询', 'energy:hydrogen-record:query', 3, 1, 5201, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5211, '加氢记录创建', 'energy:hydrogen-record:create', 3, 2, 5201, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5212, '加氢记录更新', 'energy:hydrogen-record:update', 3, 3, 5201, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5213, '加氢记录删除', 'energy:hydrogen-record:delete', 3, 4, 5201, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5214, '加氢记录导出', 'energy:hydrogen-record:export', 3, 5, 5201, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5215, '加氢记录导入', 'energy:hydrogen-record:import', 3, 6, 5201, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 加氢明细管理(parent=5202) +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5220, '加氢明细查询', 'energy:hydrogen-detail:query', 3, 1, 5202, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5221, '加氢明细创建', 'energy:hydrogen-detail:create', 3, 2, 5202, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5222, '加氢明细更新', 'energy:hydrogen-detail:update', 3, 3, 5202, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5223, '加氢明细删除', 'energy:hydrogen-detail:delete', 3, 4, 5202, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5224, '加氢明细导出', 'energy:hydrogen-detail:export', 3, 5, 5202, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5225, '加氢明细审核', 'energy:hydrogen-detail:audit', 3, 6, 5202, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 能源账单管理(parent=5203) +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5230, '能源账单查询', 'energy:bill:query', 3, 1, 5203, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5231, '能源账单创建', 'energy:bill:create', 3, 2, 5203, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5232, '能源账单更新', 'energy:bill:update', 3, 3, 5203, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5233, '能源账单删除', 'energy:bill:delete', 3, 4, 5203, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5234, '能源账单导出', 'energy:bill:export', 3, 5, 5203, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5235, '能源账单审核', 'energy:bill:audit', 3, 6, 5203, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 能源账户管理(parent=5204) +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5240, '能源账户查询', 'energy:account:query', 3, 1, 5204, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5241, '能源账户创建', 'energy:account:create', 3, 2, 5204, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5242, '能源账户更新', 'energy:account:update', 3, 3, 5204, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5243, '能源账户删除', 'energy:account:delete', 3, 4, 5204, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5244, '能源账户导出', 'energy:account:export', 3, 5, 5204, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5245, '能源账户充值', 'energy:account:recharge', 3, 6, 5204, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 价格管理(parent=5205) +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5250, '价格查询', 'energy:station-price:query', 3, 1, 5205, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5251, '价格创建', 'energy:station-price:create', 3, 2, 5205, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5252, '价格更新', 'energy:station-price:update', 3, 3, 5205, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5253, '价格删除', 'energy:station-price:delete', 3, 4, 5205, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5254, '价格导出', 'energy:station-price:export', 3, 5, 5205, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 加氢站配置(parent=5206) +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5260, '加氢站配置查询', 'energy:station-config:query', 3, 1, 5206, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5261, '加氢站配置创建', 'energy:station-config:create', 3, 2, 5206, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5262, '加氢站配置更新', 'energy:station-config:update', 3, 3, 5206, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5263, '加氢站配置删除', 'energy:station-config:delete', 3, 4, 5206, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5264, '加氢站配置导出', 'energy:station-config:export', 3, 5, 5206, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); diff --git a/sql/energy/energy_menu.sql b/sql/energy/energy_menu.sql new file mode 100644 index 0000000..eb809cd --- /dev/null +++ b/sql/energy/energy_menu.sql @@ -0,0 +1,153 @@ +-- ========================================== +-- 能源管理模块菜单权限 SQL +-- 生成日期: 2026-03-15 +-- 说明: ID 从 5100 起步,避免与现有菜单冲突 +-- parent_id=0 表示顶级目录 +-- type: 1=目录, 2=菜单, 3=按钮 +-- status: 0=开启 +-- ========================================== + +-- ---------------------------- +-- 一级菜单: 能源管理(目录,type=1) +-- ---------------------------- +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5100, '能源管理', '', 1, 50, 0, '/energy', 'ep:lightning', NULL, NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- ---------------------------- +-- 二级菜单(type=2) +-- 5101: 加氢记录管理 +-- 5102: 加氢明细管理 +-- 5103: 能源账单管理 +-- 5104: 能源账户管理 +-- 5105: 价格管理 +-- 5106: 加氢站配置 +-- ---------------------------- +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5101, '加氢记录管理', 'energy:hydrogen-record:query', 2, 1, 5100, 'hydrogen-record', 'ep:document', 'energy/hydrogen-record/index', 'EnergyHydrogenRecord', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5102, '加氢明细管理', 'energy:hydrogen-detail:query', 2, 2, 5100, 'hydrogen-detail', 'ep:list', 'energy/hydrogen-detail/index', 'EnergyHydrogenDetail', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5103, '能源账单管理', 'energy:bill:query', 2, 3, 5100, 'bill', 'ep:tickets', 'energy/bill/index', 'EnergyBill', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5104, '能源账户管理', 'energy:account:query', 2, 4, 5100, 'account', 'ep:wallet', 'energy/account/index', 'EnergyAccount', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5105, '价格管理', 'energy:station-price:query', 2, 5, 5100, 'station-price', 'ep:price-tag', 'energy/station-price/index', 'EnergyStationPrice', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5106, '加氢站配置', 'energy:station-config:query', 2, 6, 5100, 'station-config', 'ep:setting', 'energy/station-config/index', 'EnergyStationConfig', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- ---------------------------- +-- 三级按钮/权限(type=3) +-- ---------------------------- + +-- 加氢记录管理(parent=5101): 查询、创建、更新、删除、导出、导入 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5110, '加氢记录查询', 'energy:hydrogen-record:query', 3, 1, 5101, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5111, '加氢记录创建', 'energy:hydrogen-record:create', 3, 2, 5101, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5112, '加氢记录更新', 'energy:hydrogen-record:update', 3, 3, 5101, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5113, '加氢记录删除', 'energy:hydrogen-record:delete', 3, 4, 5101, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5114, '加氢记录导出', 'energy:hydrogen-record:export', 3, 5, 5101, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5115, '加氢记录导入', 'energy:hydrogen-record:import', 3, 6, 5101, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 加氢明细管理(parent=5102): 查询、创建、更新、删除、导出、审核 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5120, '加氢明细查询', 'energy:hydrogen-detail:query', 3, 1, 5102, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5121, '加氢明细创建', 'energy:hydrogen-detail:create', 3, 2, 5102, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5122, '加氢明细更新', 'energy:hydrogen-detail:update', 3, 3, 5102, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5123, '加氢明细删除', 'energy:hydrogen-detail:delete', 3, 4, 5102, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5124, '加氢明细导出', 'energy:hydrogen-detail:export', 3, 5, 5102, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5125, '加氢明细审核', 'energy:hydrogen-detail:audit', 3, 6, 5102, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 能源账单管理(parent=5103): 查询、创建、更新、删除、导出、审核 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5130, '能源账单查询', 'energy:bill:query', 3, 1, 5103, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5131, '能源账单创建', 'energy:bill:create', 3, 2, 5103, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5132, '能源账单更新', 'energy:bill:update', 3, 3, 5103, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5133, '能源账单删除', 'energy:bill:delete', 3, 4, 5103, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5134, '能源账单导出', 'energy:bill:export', 3, 5, 5103, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5135, '能源账单审核', 'energy:bill:audit', 3, 6, 5103, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 能源账户管理(parent=5104): 查询、创建、更新、删除、导出、充值 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5140, '能源账户查询', 'energy:account:query', 3, 1, 5104, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5141, '能源账户创建', 'energy:account:create', 3, 2, 5104, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5142, '能源账户更新', 'energy:account:update', 3, 3, 5104, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5143, '能源账户删除', 'energy:account:delete', 3, 4, 5104, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5144, '能源账户导出', 'energy:account:export', 3, 5, 5104, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5145, '能源账户充值', 'energy:account:recharge', 3, 6, 5104, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 价格管理(parent=5105): 查询、创建、更新、删除、导出 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5150, '价格查询', 'energy:station-price:query', 3, 1, 5105, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5151, '价格创建', 'energy:station-price:create', 3, 2, 5105, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5152, '价格更新', 'energy:station-price:update', 3, 3, 5105, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5153, '价格删除', 'energy:station-price:delete', 3, 4, 5105, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5154, '价格导出', 'energy:station-price:export', 3, 5, 5105, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 加氢站配置(parent=5106): 查询、创建、更新、删除、导出 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5160, '加氢站配置查询', 'energy:station-config:query', 3, 1, 5106, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5161, '加氢站配置创建', 'energy:station-config:create', 3, 2, 5106, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5162, '加氢站配置更新', 'energy:station-config:update', 3, 3, 5106, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5163, '加氢站配置删除', 'energy:station-config:delete', 3, 4, 5106, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); + +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) +VALUES (5164, '加氢站配置导出', 'energy:station-config:export', 3, 5, 5106, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'); diff --git a/sql/energy/energy_mock_data.sql b/sql/energy/energy_mock_data.sql new file mode 100644 index 0000000..bfa76ef --- /dev/null +++ b/sql/energy/energy_mock_data.sql @@ -0,0 +1,230 @@ +-- ========================================== +-- Energy 模块 Mock 数据 +-- 执行方式: 用数据库工具连接 47.103.115.36:3306 直接执行 +-- 脚本会自动切换数据库 +-- ========================================== + +-- ========================================== +-- 第一部分: 在 oneos_asset 中插入关联 mock 数据 +-- (如果已有真实数据,请跳过此部分,并修改下方 energy 数据中的 ID) +-- ========================================== +USE `oneos_asset`; + +-- 3 个加氢站(停车场) +INSERT INTO `asset_parking` (`id`, `name`, `address`, `capacity`, `parked_amount`, `tenant_id`, `deleted`, `creator`, `create_time`, `updater`, `update_time`) +VALUES +(1001, '上海松江加氢站', '上海市松江区新桥镇莘砖公路368号', 50, 0, 0, b'0', 'admin', NOW(), 'admin', NOW()), +(1002, '上海嘉定加氢站', '上海市嘉定区安亭镇墨玉南路888号', 30, 0, 0, b'0', 'admin', NOW(), 'admin', NOW()), +(1003, '江苏昆山加氢站', '江苏省昆山市千灯镇石浦路199号', 40, 0, 0, b'0', 'admin', NOW(), 'admin', NOW()) +ON DUPLICATE KEY UPDATE `name` = VALUES(`name`); + +-- 3 个客户 +INSERT INTO `asset_customer` (`id`, `customer_name`, `customer_code`, `coop_status`, `province`, `city`, `contact`, `contact_mobile`, `tenant_id`, `deleted`, `creator`, `create_time`, `updater`, `update_time`) +VALUES +(2001, '上海绿能物流有限公司', 'CUST-2026-001', '合作中', '上海', '上海', '张经理', '13800001001', 0, b'0', 'admin', NOW(), 'admin', NOW()), +(2002, '江苏氢动力运输有限公司', 'CUST-2026-002', '合作中', '江苏', '苏州', '李经理', '13800001002', 0, b'0', 'admin', NOW(), 'admin', NOW()), +(2003, '浙江新能源科技有限公司', 'CUST-2026-003', '合作中', '浙江', '杭州', '王经理', '13800001003', 0, b'0', 'admin', NOW(), 'admin', NOW()) +ON DUPLICATE KEY UPDATE `customer_name` = VALUES(`customer_name`); + +-- 6 辆车 +INSERT INTO `asset_vehicle_base` (`id`, `vin`, `plate_no`, `vehicle_no`, `color`, `year`, `tenant_id`, `deleted`, `creator`, `create_time`, `updater`, `update_time`) +VALUES +(3001, 'LVBV1234567890001', '沪A12345', 'VH-001', '白色', '2025', 0, b'0', 'admin', NOW(), 'admin', NOW()), +(3002, 'LVBV1234567890002', '沪B67890', 'VH-002', '蓝色', '2025', 0, b'0', 'admin', NOW(), 'admin', NOW()), +(3003, 'LVBV1234567890003', '苏A11111', 'VH-003', '白色', '2024', 0, b'0', 'admin', NOW(), 'admin', NOW()), +(3004, 'LVBV1234567890004', '苏B22222', 'VH-004', '绿色', '2024', 0, b'0', 'admin', NOW(), 'admin', NOW()), +(3005, 'LVBV1234567890005', '浙A33333', 'VH-005', '白色', '2025', 0, b'0', 'admin', NOW(), 'admin', NOW()), +(3006, 'LVBV1234567890006', '浙B44444', 'VH-006', '银色', '2025', 0, b'0', 'admin', NOW(), 'admin', NOW()) +ON DUPLICATE KEY UPDATE `plate_no` = VALUES(`plate_no`); + +-- 车辆业务关联 +INSERT INTO `asset_vehicle_business` (`id`, `vehicle_id`, `customer_id`, `tenant_id`, `deleted`, `creator`, `create_time`, `updater`, `update_time`) +VALUES +(3001, 3001, 2001, 0, b'0', 'admin', NOW(), 'admin', NOW()), +(3002, 3002, 2001, 0, b'0', 'admin', NOW(), 'admin', NOW()), +(3003, 3003, 2002, 0, b'0', 'admin', NOW(), 'admin', NOW()), +(3004, 3004, 2002, 0, b'0', 'admin', NOW(), 'admin', NOW()), +(3005, 3005, 2003, 0, b'0', 'admin', NOW(), 'admin', NOW()), +(3006, 3006, 2003, 0, b'0', 'admin', NOW(), 'admin', NOW()) +ON DUPLICATE KEY UPDATE `customer_id` = VALUES(`customer_id`); + +-- 3 个合同 +INSERT INTO `asset_contract` (`id`, `contract_code`, `contract_type`, `project_name`, `start_date`, `end_date`, `payment_method`, `payment_cycle`, `signing_company`, `delivery_province`, `delivery_city`, `delivery_location`, `customer_id`, `customer_name`, `approval_status`, `contract_status`, `tenant_id`, `deleted`, `creator`, `create_time`, `updater`, `update_time`) +VALUES +(4001, 'HT-2026-001', 2, '绿能物流氢能车辆租赁项目', '2026-01-01', '2026-12-31', '预充值', '按次', '上海氢能科技有限公司', '上海', '上海', '上海市松江区', 2001, '上海绿能物流有限公司', 2, 2, 0, b'0', 'admin', NOW(), 'admin', NOW()), +(4002, 'HT-2026-002', 2, '氢动力城配物流项目', '2026-01-01', '2026-12-31', '月结算', '月结', '上海氢能科技有限公司', '江苏', '苏州', '江苏省苏州市昆山市', 2002, '江苏氢动力运输有限公司', 2, 2, 0, b'0', 'admin', NOW(), 'admin', NOW()), +(4003, 'HT-2026-003', 2, '新能源冷链运输项目', '2026-02-01', '2027-01-31', '预充值', '按次', '上海氢能科技有限公司', '浙江', '杭州', '浙江省杭州市西湖区', 2003, '浙江新能源科技有限公司', 2, 2, 0, b'0', 'admin', NOW(), 'admin', NOW()) +ON DUPLICATE KEY UPDATE `project_name` = VALUES(`project_name`); + + +-- ========================================== +-- 第二部分: Energy 模块 mock 数据 +-- ========================================== +USE `oneos_energy`; + +-- ---------------------------- +-- 1. 加氢站配置(3 站) +-- ---------------------------- +INSERT INTO `energy_station_config` (`id`, `station_id`, `auto_deduct`, `cooperation_type`, `auto_match`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) +VALUES +(1, 1001, 1, 0, 1, '松江站,自动扣款+自动匹配', 'admin', NOW(), 'admin', NOW(), b'0', 0), +(2, 1002, 1, 0, 1, '嘉定站,自动扣款+自动匹配', 'admin', NOW(), 'admin', NOW(), b'0', 0), +(3, 1003, 0, 1, 0, '昆山站,非合作站,手动匹配', 'admin', NOW(), 'admin', NOW(), b'0', 0); + +-- ---------------------------- +-- 2. 加氢站客户价格(6 条) +-- ---------------------------- +INSERT INTO `energy_station_price` (`id`, `station_id`, `customer_id`, `cost_price`, `customer_price`, `effective_date`, `expiry_date`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) +VALUES +-- 松江站价格 +(1, 1001, 2001, 28.00, 35.00, '2026-01-01', NULL, 0, 'admin', NOW(), 'admin', NOW(), b'0', 0), +(2, 1001, 2002, 28.00, 34.00, '2026-01-01', NULL, 0, 'admin', NOW(), 'admin', NOW(), b'0', 0), +-- 嘉定站价格 +(3, 1002, 2001, 27.50, 35.00, '2026-01-01', NULL, 0, 'admin', NOW(), 'admin', NOW(), b'0', 0), +(4, 1002, 2002, 27.50, 33.50, '2026-01-01', NULL, 0, 'admin', NOW(), 'admin', NOW(), b'0', 0), +-- 昆山站价格 +(5, 1003, 2003, 29.00, 36.00, '2026-02-01', NULL, 0, 'admin', NOW(), 'admin', NOW(), b'0', 0), +-- 已失效的旧价格 +(6, 1001, 2001, 26.00, 33.00, '2025-06-01', '2025-12-31', 1, 'admin', NOW(), 'admin', NOW(), b'0', 0); + +-- ---------------------------- +-- 3. 加氢原始记录(20 条,覆盖多种状态) +-- ---------------------------- +INSERT INTO `energy_hydrogen_record` (`id`, `station_id`, `plate_number`, `hydrogen_date`, `hydrogen_quantity`, `unit_price`, `amount`, `mileage`, `source_type`, `match_status`, `vehicle_id`, `customer_id`, `upload_batch_no`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) +VALUES +-- 已匹配记录(松江站,客户2001) +( 1, 1001, '沪A12345', '2026-03-01', 12.50, 35.00, 437.50, 15230.00, 1, 1, 3001, 2001, 'IMP20260305001A', 'admin', '2026-03-05 10:00:00', 'admin', '2026-03-05 10:00:00', b'0', 0), +( 2, 1001, '沪A12345', '2026-03-03', 15.00, 35.00, 525.00, 15580.00, 1, 1, 3001, 2001, 'IMP20260305001A', 'admin', '2026-03-05 10:00:00', 'admin', '2026-03-05 10:00:00', b'0', 0), +( 3, 1001, '沪B67890', '2026-03-02', 10.80, 35.00, 378.00, 8920.00, 1, 1, 3002, 2001, 'IMP20260305001A', 'admin', '2026-03-05 10:00:00', 'admin', '2026-03-05 10:00:00', b'0', 0), +( 4, 1001, '沪B67890', '2026-03-05', 13.20, 35.00, 462.00, 9200.00, 1, 1, 3002, 2001, 'IMP20260305001A', 'admin', '2026-03-05 10:00:00', 'admin', '2026-03-05 10:00:00', b'0', 0), +-- 已匹配记录(嘉定站,客户2002) +( 5, 1002, '苏A11111', '2026-03-01', 18.00, 33.50, 603.00, 22100.00, 1, 1, 3003, 2002, 'IMP20260306002B', 'admin', '2026-03-06 09:00:00', 'admin', '2026-03-06 09:00:00', b'0', 0), +( 6, 1002, '苏A11111', '2026-03-04', 16.50, 33.50, 552.75, 22450.00, 1, 1, 3003, 2002, 'IMP20260306002B', 'admin', '2026-03-06 09:00:00', 'admin', '2026-03-06 09:00:00', b'0', 0), +( 7, 1002, '苏B22222', '2026-03-02', 20.00, 33.50, 670.00, 18600.00, 1, 1, 3004, 2002, 'IMP20260306002B', 'admin', '2026-03-06 09:00:00', 'admin', '2026-03-06 09:00:00', b'0', 0), +( 8, 1002, '苏B22222', '2026-03-06', 14.80, 33.50, 495.80, 19010.00, 1, 1, 3004, 2002, 'IMP20260306002B', 'admin', '2026-03-06 09:00:00', 'admin', '2026-03-06 09:00:00', b'0', 0), +-- 已匹配记录(昆山站,客户2003) +( 9, 1003, '浙A33333', '2026-03-03', 22.00, 36.00, 792.00, 31200.00, 1, 1, 3005, 2003, 'IMP20260307003C', 'admin', '2026-03-07 14:00:00', 'admin', '2026-03-07 14:00:00', b'0', 0), +(10, 1003, '浙A33333', '2026-03-07', 19.50, 36.00, 702.00, 31800.00, 1, 1, 3005, 2003, 'IMP20260307003C', 'admin', '2026-03-07 14:00:00', 'admin', '2026-03-07 14:00:00', b'0', 0), +(11, 1003, '浙B44444', '2026-03-05', 17.00, 36.00, 612.00, 27500.00, 1, 1, 3006, 2003, 'IMP20260307003C', 'admin', '2026-03-07 14:00:00', 'admin', '2026-03-07 14:00:00', b'0', 0), +-- 未匹配记录(车牌在系统中不存在) +(12, 1001, '沪C99999', '2026-03-08', 11.00, 35.00, 385.00, NULL, 1, 0, NULL, NULL, 'IMP20260310004D', 'admin', '2026-03-10 11:00:00', 'admin', '2026-03-10 11:00:00', b'0', 0), +(13, 1001, '沪D88888', '2026-03-08', 9.50, 35.00, 332.50, NULL, 1, 0, NULL, NULL, 'IMP20260310004D', 'admin', '2026-03-10 11:00:00', 'admin', '2026-03-10 11:00:00', b'0', 0), +(14, 1002, '苏C77777', '2026-03-09', 14.00, 33.50, 469.00, NULL, 1, 0, NULL, NULL, 'IMP20260310004D', 'admin', '2026-03-10 11:00:00', 'admin', '2026-03-10 11:00:00', b'0', 0), +-- 无法匹配记录 +(15, 1003, '京A00001', '2026-03-10', 8.00, 36.00, 288.00, NULL, 1, 2, NULL, NULL, 'IMP20260311005E', 'admin', '2026-03-11 09:00:00', 'admin', '2026-03-11 09:00:00', b'0', 0), +-- 手动录入(source_type=2) +(16, 1001, '沪A12345', '2026-03-10', 14.00, 35.00, 490.00, 16100.00, 2, 1, 3001, 2001, NULL, 'admin', '2026-03-10 16:00:00', 'admin', '2026-03-10 16:00:00', b'0', 0), +(17, 1002, '苏A11111', '2026-03-10', 17.50, 33.50, 586.25, 23100.00, 2, 1, 3003, 2002, NULL, 'admin', '2026-03-10 16:30:00', 'admin', '2026-03-10 16:30:00', b'0', 0), +-- 最新批次(未处理) +(18, 1001, '沪A12345', '2026-03-12', 11.80, 35.00, 413.00, 16500.00, 1, 1, 3001, 2001, 'IMP20260313006F', 'admin', '2026-03-13 10:00:00', 'admin', '2026-03-13 10:00:00', b'0', 0), +(19, 1001, '沪B67890', '2026-03-13', 16.00, 35.00, 560.00, 9800.00, 1, 1, 3002, 2001, 'IMP20260313006F', 'admin', '2026-03-13 10:00:00', 'admin', '2026-03-13 10:00:00', b'0', 0), +(20, 1002, '苏B22222', '2026-03-14', 13.00, 33.50, 435.50, 19500.00, 1, 1, 3004, 2002, 'IMP20260314007G', 'admin', '2026-03-14 08:00:00', 'admin', '2026-03-14 08:00:00', b'0', 0); + +-- ---------------------------- +-- 4. 加氢明细(15 条,对应已匹配的记录,覆盖不同审核/扣款/结算状态) +-- ---------------------------- +INSERT INTO `energy_hydrogen_detail` (`id`, `record_id`, `station_id`, `vehicle_id`, `plate_number`, `hydrogen_date`, `hydrogen_quantity`, `cost_price`, `cost_amount`, `customer_price`, `customer_amount`, `contract_id`, `customer_id`, `project_name`, `cost_bearer`, `pay_method`, `audit_status`, `audit_remark`, `deduction_status`, `settlement_status`, `bill_id`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) +VALUES +-- 客户2001 明细(预充值,已审核+已扣款+已结算,关联账单1) +(1, 1, 1001, 3001, '沪A12345', '2026-03-01', 12.50, 28.00, 350.00, 35.00, 437.50, 4001, 2001, '绿能物流氢能车辆租赁项目', 1, 1, 1, '审核通过', 1, 1, 1, NULL, 'admin', '2026-03-05 10:30:00', 'admin', '2026-03-08 10:00:00', b'0', 0), +(2, 2, 1001, 3001, '沪A12345', '2026-03-03', 15.00, 28.00, 420.00, 35.00, 525.00, 4001, 2001, '绿能物流氢能车辆租赁项目', 1, 1, 1, '审核通过', 1, 1, 1, NULL, 'admin', '2026-03-05 10:30:00', 'admin', '2026-03-08 10:00:00', b'0', 0), +(3, 3, 1001, 3002, '沪B67890', '2026-03-02', 10.80, 28.00, 302.40, 35.00, 378.00, 4001, 2001, '绿能物流氢能车辆租赁项目', 1, 1, 1, '审核通过', 1, 1, 1, NULL, 'admin', '2026-03-05 10:30:00', 'admin', '2026-03-08 10:00:00', b'0', 0), +(4, 4, 1001, 3002, '沪B67890', '2026-03-05', 13.20, 28.00, 369.60, 35.00, 462.00, 4001, 2001, '绿能物流氢能车辆租赁项目', 1, 1, 1, '审核通过', 1, 1, 1, NULL, 'admin', '2026-03-05 10:30:00', 'admin', '2026-03-08 10:00:00', b'0', 0), + +-- 客户2002 明细(月结算,已审核+未扣款+未结算,关联账单2) +(5, 5, 1002, 3003, '苏A11111', '2026-03-01', 18.00, 27.50, 495.00, 33.50, 603.00, 4002, 2002, '氢动力城配物流项目', 1, 2, 1, '审核通过', 0, 0, 2, NULL, 'admin', '2026-03-06 09:30:00', 'admin', '2026-03-09 09:00:00', b'0', 0), +(6, 6, 1002, 3003, '苏A11111', '2026-03-04', 16.50, 27.50, 453.75, 33.50, 552.75, 4002, 2002, '氢动力城配物流项目', 1, 2, 1, '审核通过', 0, 0, 2, NULL, 'admin', '2026-03-06 09:30:00', 'admin', '2026-03-09 09:00:00', b'0', 0), +(7, 7, 1002, 3004, '苏B22222', '2026-03-02', 20.00, 27.50, 550.00, 33.50, 670.00, 4002, 2002, '氢动力城配物流项目', 1, 2, 1, '审核通过', 0, 0, 2, NULL, 'admin', '2026-03-06 09:30:00', 'admin', '2026-03-09 09:00:00', b'0', 0), +(8, 8, 1002, 3004, '苏B22222', '2026-03-06', 14.80, 27.50, 407.00, 33.50, 495.80, 4002, 2002, '氢动力城配物流项目', 1, 2, 1, '审核通过', 0, 0, 2, NULL, 'admin', '2026-03-06 09:30:00', 'admin', '2026-03-09 09:00:00', b'0', 0), + +-- 客户2003 明细(预充值,待审核,无账单) +( 9, 9, 1003, 3005, '浙A33333', '2026-03-03', 22.00, 29.00, 638.00, 36.00, 792.00, 4003, 2003, '新能源冷链运输项目', 1, 1, 0, NULL, 0, 0, NULL, NULL, 'admin', '2026-03-07 14:30:00', 'admin', '2026-03-07 14:30:00', b'0', 0), +(10, 10, 1003, 3005, '浙A33333', '2026-03-07', 19.50, 29.00, 565.50, 36.00, 702.00, 4003, 2003, '新能源冷链运输项目', 1, 1, 0, NULL, 0, 0, NULL, NULL, 'admin', '2026-03-07 14:30:00', 'admin', '2026-03-07 14:30:00', b'0', 0), +(11, 11, 1003, 3006, '浙B44444', '2026-03-05', 17.00, 29.00, 493.00, 36.00, 612.00, 4003, 2003, '新能源冷链运输项目', 1, 1, 0, NULL, 0, 0, NULL, NULL, 'admin', '2026-03-07 14:30:00', 'admin', '2026-03-07 14:30:00', b'0', 0), + +-- 客户2001 最新明细(已审核,未结算,无账单 — 可用于生成新账单测试) +(12, 16, 1001, 3001, '沪A12345', '2026-03-10', 14.00, 28.00, 392.00, 35.00, 490.00, 4001, 2001, '绿能物流氢能车辆租赁项目', 1, 1, 1, '审核通过', 1, 0, NULL, NULL, 'admin', '2026-03-10 16:30:00', 'admin', '2026-03-11 10:00:00', b'0', 0), +(13, 18, 1001, 3001, '沪A12345', '2026-03-12', 11.80, 28.00, 330.40, 35.00, 413.00, 4001, 2001, '绿能物流氢能车辆租赁项目', 1, 1, 1, '审核通过', 1, 0, NULL, NULL, 'admin', '2026-03-13 10:30:00', 'admin', '2026-03-14 10:00:00', b'0', 0), +(14, 19, 1001, 3002, '沪B67890', '2026-03-13', 16.00, 28.00, 448.00, 35.00, 560.00, 4001, 2001, '绿能物流氢能车辆租赁项目', 1, 1, 1, '审核通过', 1, 0, NULL, NULL, 'admin', '2026-03-13 10:30:00', 'admin', '2026-03-14 10:00:00', b'0', 0), + +-- 客户2002 已审核驳回明细 +(15, 17, 1002, 3003, '苏A11111', '2026-03-10', 17.50, 27.50, 481.25, 33.50, 586.25, 4002, 2002, '氢动力城配物流项目', 1, 2, 2, '金额异常,请核实', 0, 0, NULL, '驳回后待重新审核', 'admin', '2026-03-10 17:00:00', 'admin', '2026-03-11 15:00:00', b'0', 0); + +-- ---------------------------- +-- 5. 能源账单(3 条,覆盖不同状态) +-- ---------------------------- +INSERT INTO `energy_bill` (`id`, `bill_code`, `energy_type`, `customer_id`, `customer_name`, `contract_id`, `station_id`, `station_name`, `cooperation_type`, `bill_period_start`, `bill_period_end`, `receivable_amount`, `actual_amount`, `adjustment_amount`, `paid_amount`, `total_quantity`, `detail_count`, `status`, `audit_status`, `submit_status`, `payment_status`, `auditor_id`, `audit_time`, `audit_remark`, `generate_time`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) +VALUES +-- 账单1: 客户2001,已生成+已审核+已支付(完结状态) +(1, 'EB20260308140000A1B2', 0, 2001, '上海绿能物流有限公司', 4001, 1001, '上海松江加氢站', 1, + '2026-03-01', '2026-03-07', 1802.50, 1802.50, 0.00, 1802.50, 51.50, 4, 1, 1, 1, 2, + 1, '2026-03-09 10:00:00', '审核通过,金额核对无误', '2026-03-08 14:00:00', + 'admin', '2026-03-08 14:00:00', 'admin', '2026-03-10 10:00:00', b'0', 0), + +-- 账单2: 客户2002,已生成+待审核(月结算) +(2, 'EB20260309100000C3D4', 0, 2002, '江苏氢动力运输有限公司', 4002, 1002, '上海嘉定加氢站', 2, + '2026-03-01', '2026-03-07', 2321.55, 2221.55, -100.00, 0.00, 69.30, 4, 1, 0, 0, 0, + NULL, NULL, NULL, '2026-03-09 10:00:00', + 'admin', '2026-03-09 10:00:00', 'admin', '2026-03-09 10:00:00', b'0', 0), + +-- 账单3: 客户2001 草稿(还没提交审核) +(3, 'EB20260314120000E5F6', 0, 2001, '上海绿能物流有限公司', 4001, 1001, '上海松江加氢站', 1, + '2026-03-08', '2026-03-14', 1463.00, 1463.00, 0.00, 0.00, 41.80, 3, 0, 0, 0, 0, + NULL, NULL, NULL, '2026-03-14 12:00:00', + 'admin', '2026-03-14 12:00:00', 'admin', '2026-03-14 12:00:00', b'0', 0); + +-- ---------------------------- +-- 6. 账单调整记录(2 条,关联账单2) +-- ---------------------------- +INSERT INTO `energy_bill_adjustment` (`id`, `bill_id`, `detail_id`, `adjustment_type`, `amount`, `reason`, `attachment_urls`, `operator_id`, `operate_time`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) +VALUES +(1, 2, 8, 2, 80.00, '3月6日苏B22222加氢量数据偏高,与站点核对后减少80元', NULL, 1, '2026-03-10 11:00:00', 'admin', '2026-03-10 11:00:00', 'admin', '2026-03-10 11:00:00', b'0', 0), +(2, 2, NULL, 2, 20.00, '整单优惠减免20元', NULL, 1, '2026-03-10 11:30:00', 'admin', '2026-03-10 11:30:00', 'admin', '2026-03-10 11:30:00', b'0', 0); + +-- ---------------------------- +-- 7. 客户能源账户(3 个客户) +-- ---------------------------- +INSERT INTO `energy_account` (`id`, `customer_id`, `balance`, `init_balance`, `accumulated_recharge`, `accumulated_hydrogen`, `accumulated_electric`, `accumulated_consume`, `reminder_threshold`, `account_status`, `last_recharge_date`, `version`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) +VALUES +-- 客户2001: 预充值模式,余额正常 +(1, 2001, 47197.50, 0.00, 50000.00, 2802.50, 0.00, 2802.50, 5000.00, 0, '2026-03-01', 5, + 'admin', '2026-01-15 10:00:00', 'admin', '2026-03-14 12:00:00', b'0', 0), +-- 客户2002: 月结算模式,余额为零(月结不需要预充) +(2, 2002, 0.00, 0.00, 0.00, 2321.55, 0.00, 2321.55, NULL, 0, NULL, 2, + 'admin', '2026-01-15 10:00:00', 'admin', '2026-03-09 10:00:00', b'0', 0), +-- 客户2003: 预充值模式,余额预警 +(3, 2003, 3894.00, 0.00, 6000.00, 2106.00, 0.00, 2106.00, 5000.00, 1, '2026-02-20', 3, + 'admin', '2026-02-01 10:00:00', 'admin', '2026-03-07 15:00:00', b'0', 0); + +-- ---------------------------- +-- 8. 项目账户(3 个项目,对应3个合同) +-- ---------------------------- +INSERT INTO `energy_project_account` (`id`, `account_id`, `contract_id`, `project_name`, `project_balance`, `project_remit_amount`, `project_hydrogen_amount`, `project_electric_amount`, `project_consume_amount`, `reminder_threshold`, `account_status`, `version`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) +VALUES +(1, 1, 4001, '绿能物流氢能车辆租赁项目', 47197.50, 50000.00, 2802.50, 0.00, 2802.50, 5000.00, 0, 5, + 'admin', '2026-01-15 10:00:00', 'admin', '2026-03-14 12:00:00', b'0', 0), +(2, 2, 4002, '氢动力城配物流项目', 0.00, 0.00, 2321.55, 0.00, 2321.55, NULL, 0, 2, + 'admin', '2026-01-15 10:00:00', 'admin', '2026-03-09 10:00:00', b'0', 0), +(3, 3, 4003, '新能源冷链运输项目', 3894.00, 6000.00, 2106.00, 0.00, 2106.00, 5000.00, 1, 3, + 'admin', '2026-02-01 10:00:00', 'admin', '2026-03-07 15:00:00', b'0', 0); + +-- ---------------------------- +-- 9. 账户流水(12 条,覆盖充值/扣款场景) +-- ---------------------------- +INSERT INTO `energy_account_flow` (`id`, `account_id`, `project_account_id`, `flow_type`, `amount`, `balance_before`, `balance_after`, `project_balance_before`, `project_balance_after`, `biz_type`, `biz_id`, `biz_code`, `remark`, `operator_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) +VALUES +-- 客户2001 流水 +(1, 1, 1, 1, 50000.00, 0.00, 50000.00, 0.00, 50000.00, 3, NULL, NULL, '首次充值', 1, 'admin', '2026-03-01 10:00:00', 'admin', '2026-03-01 10:00:00', b'0', 0), +(2, 1, 1, 2, -437.50, 50000.00, 49562.50, 50000.00, 49562.50, 1, 1, NULL, '沪A12345 2026-03-01 加氢扣款', NULL, 'admin', '2026-03-05 11:00:00', 'admin', '2026-03-05 11:00:00', b'0', 0), +(3, 1, 1, 2, -525.00, 49562.50, 49037.50, 49562.50, 49037.50, 1, 2, NULL, '沪A12345 2026-03-03 加氢扣款', NULL, 'admin', '2026-03-05 11:01:00', 'admin', '2026-03-05 11:01:00', b'0', 0), +(4, 1, 1, 2, -378.00, 49037.50, 48659.50, 49037.50, 48659.50, 1, 3, NULL, '沪B67890 2026-03-02 加氢扣款', NULL, 'admin', '2026-03-05 11:02:00', 'admin', '2026-03-05 11:02:00', b'0', 0), +(5, 1, 1, 2, -462.00, 48659.50, 48197.50, 48659.50, 48197.50, 1, 4, NULL, '沪B67890 2026-03-05 加氢扣款', NULL, 'admin', '2026-03-05 11:03:00', 'admin', '2026-03-05 11:03:00', b'0', 0), +(6, 1, 1, 2, -490.00, 48197.50, 47707.50, 48197.50, 47707.50, 1, 12, NULL, '沪A12345 2026-03-10 加氢扣款', NULL, 'admin', '2026-03-11 10:00:00', 'admin', '2026-03-11 10:00:00', b'0', 0), +(7, 1, 1, 2, -413.00, 47707.50, 47294.50, 47707.50, 47294.50, 1, 13, NULL, '沪A12345 2026-03-12 加氢扣款', NULL, 'admin', '2026-03-14 10:00:00', 'admin', '2026-03-14 10:00:00', b'0', 0), +(8, 1, 1, 2, -97.00, 47294.50, 47197.50, 47294.50, 47197.50, 1, 14, NULL, '沪B67890 2026-03-13 加氢扣款(部分)', NULL, 'admin', '2026-03-14 10:01:00', 'admin', '2026-03-14 10:01:00', b'0', 0), + +-- 客户2003 流水 +( 9, 3, 3, 1, 6000.00, 0.00, 6000.00, 0.00, 6000.00, 3, NULL, NULL, '首次充值', 1, 'admin', '2026-02-20 10:00:00', 'admin', '2026-02-20 10:00:00', b'0', 0), +(10, 3, 3, 2, -792.00, 6000.00, 5208.00, 6000.00, 5208.00, 1, 9, NULL, '浙A33333 2026-03-03 加氢扣款', NULL, 'admin', '2026-03-07 15:00:00', 'admin', '2026-03-07 15:00:00', b'0', 0), +(11, 3, 3, 2, -702.00, 5208.00, 4506.00, 5208.00, 4506.00, 1, 10, NULL, '浙A33333 2026-03-07 加氢扣款', NULL, 'admin', '2026-03-07 15:01:00', 'admin', '2026-03-07 15:01:00', b'0', 0), +(12, 3, 3, 2, -612.00, 4506.00, 3894.00, 4506.00, 3894.00, 1, 11, NULL, '浙B44444 2026-03-05 加氢扣款', NULL, 'admin', '2026-03-07 15:02:00', 'admin', '2026-03-07 15:02:00', b'0', 0); diff --git a/sql/energy/import_sql.py b/sql/energy/import_sql.py new file mode 100644 index 0000000..e6ae8ea --- /dev/null +++ b/sql/energy/import_sql.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +""" +SQL 导入工具 +""" +import pymysql +import sys + +def execute_sql_file(host, port, user, password, sql_file): + """执行 SQL 文件""" + try: + # 读取 SQL 文件 + with open(sql_file, 'r', encoding='utf-8') as f: + sql_content = f.read() + + # 连接数据库(不指定数据库,让 SQL 中的 USE 语句生效) + connection = pymysql.connect( + host=host, + port=port, + user=user, + password=password, + charset='utf8mb4', + cursorclass=pymysql.cursors.DictCursor, + autocommit=False + ) + + print(f"✓ 连接数据库成功: {host}:{port}") + + # 分割 SQL 语句(按分号分割,但要处理存储过程等特殊情况) + statements = [] + current_statement = [] + in_delimiter = False + + for line in sql_content.split('\n'): + line = line.strip() + + # 跳过注释和空行 + if not line or line.startswith('--') or line.startswith('#'): + continue + + # 处理 DELIMITER + if line.upper().startswith('DELIMITER'): + in_delimiter = not in_delimiter + continue + + current_statement.append(line) + + # 判断语句结束 + if not in_delimiter and line.endswith(';'): + statements.append(' '.join(current_statement)) + current_statement = [] + + # 执行 SQL 语句 + with connection.cursor() as cursor: + success_count = 0 + error_count = 0 + + for i, statement in enumerate(statements, 1): + if not statement.strip(): + continue + + try: + cursor.execute(statement) + connection.commit() + success_count += 1 + + # 每 10 条打印一次进度 + if success_count % 10 == 0: + print(f" 已执行 {success_count} 条语句...") + + except Exception as e: + error_count += 1 + print(f"✗ 语句 {i} 执行失败: {str(e)[:100]}") + # 继续执行下一条 + + print(f"\n✓ 执行完成: 成功 {success_count} 条, 失败 {error_count} 条") + + connection.close() + return True + + except Exception as e: + print(f"✗ 错误: {e}") + return False + +if __name__ == '__main__': + # 数据库配置 + DB_HOST = '47.103.115.36' + DB_PORT = 3306 + DB_USER = 'root' + DB_PASSWORD = 'Passw0rd2026' + + # SQL 文件列表 + sql_files = [ + 'energy_init_all.sql', + 'energy_mock_data.sql' + ] + + print("=" * 60) + print("OneOS Energy 模块数据导入") + print("=" * 60) + + for sql_file in sql_files: + print(f"\n>>> 导入 {sql_file}") + success = execute_sql_file(DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, sql_file) + if not success: + print(f"✗ {sql_file} 导入失败") + sys.exit(1) + + print("\n" + "=" * 60) + print("✓ 所有数据导入完成") + print("=" * 60) diff --git a/sql/execute-all-updates.sql b/sql/execute-all-updates.sql new file mode 100644 index 0000000..ae0e2f5 --- /dev/null +++ b/sql/execute-all-updates.sql @@ -0,0 +1,209 @@ +-- ==================== 数据库更新脚本汇总 ==================== +-- 执行日期:2026-03-12 +-- 说明:包含 parking、vehiclemodel、customer、vehicleregistration 模块的所有更新 +-- +-- 执行顺序: +-- 1. 车型参数表字段补全(asset 库) +-- 2. 车辆类型字典数据(system 库) +-- 3. 车辆上牌记录表创建(asset 库) +-- 4. 菜单和权限配置(system 库) + +-- ==================== 使用说明 ==================== +-- 各个模块是分库的,请按照以下顺序执行: +-- +-- 1. 连接到 asset 库,执行第一部分和第三部分 +-- 2. 连接到 system 库(或主库),执行第二部分和第四部分 + +-- ==================== 第一部分:车型参数表字段补全(asset 库)==================== +USE `asset`; + +-- 检查字段是否已存在 +SELECT 'Checking asset_vehicle_model table...' AS status; + +-- 添加车型字段 +ALTER TABLE `asset_vehicle_model` + ADD COLUMN IF NOT EXISTS `vehicle_type` int DEFAULT NULL COMMENT '车辆类型(字典)' AFTER `model`, + ADD COLUMN IF NOT EXISTS `plate_color` varchar(50) DEFAULT NULL COMMENT '车牌颜色(如:绿牌、蓝牌、黄牌)' AFTER `notice_model`, + ADD COLUMN IF NOT EXISTS `battery_type` varchar(100) DEFAULT NULL COMMENT '电池类型(如:磷酸铁锂、三元锂)' AFTER `battery_factory`, + ADD COLUMN IF NOT EXISTS `hydrogen_factory` varchar(200) DEFAULT NULL COMMENT '供氢系统厂家' AFTER `refrigerator_factory`; + +-- 添加索引(如果不存在) +ALTER TABLE `asset_vehicle_model` + ADD INDEX IF NOT EXISTS `idx_vehicle_type` (`vehicle_type`) COMMENT '车辆类型查询', + ADD INDEX IF NOT EXISTS `idx_brand_model` (`brand`, `model`) COMMENT '品牌型号组合查询'; + +SELECT 'Vehicle model fields updated successfully!' AS status; + +-- ==================== 第二部分:车辆类型字典数据(system 库或主库)==================== +-- 注意:如果 system_dict_type 和 system_dict_data 在主库,请切换到主库 +-- USE `ruoyi-vue-pro`; -- 或者你的主库名称 + +-- 检查字典类型是否已存在 +SELECT 'Checking vehicle type dictionary...' AS status; + +-- 创建车辆类型字典类型(如果不存在) +INSERT INTO `system_dict_type` ( + `name`, + `type`, + `status`, + `remark`, + `creator`, + `create_time`, + `updater`, + `update_time`, + `deleted`, + `deleted_time` +) +SELECT + '车辆类型', + 'asset_vehicle_type', + 0, + '车辆资产管理-车辆类型分类', + 'admin', + NOW(), + 'admin', + NOW(), + 0, + NULL +FROM DUAL +WHERE NOT EXISTS ( + SELECT 1 FROM `system_dict_type` WHERE `type` = 'asset_vehicle_type' +); + +-- 创建车辆类型字典数据(如果不存在) +INSERT INTO `system_dict_data` ( + `sort`, + `label`, + `value`, + `dict_type`, + `status`, + `color_type`, + `css_class`, + `remark`, + `creator`, + `create_time`, + `updater`, + `update_time`, + `deleted` +) +SELECT * FROM ( + SELECT 1 AS sort, '小型轿车' AS label, '1' AS value, 'asset_vehicle_type' AS dict_type, 0 AS status, 'primary' AS color_type, '' AS css_class, '5座以下的小型乘用车' AS remark, 'admin' AS creator, NOW() AS create_time, 'admin' AS updater, NOW() AS update_time, 0 AS deleted UNION ALL + SELECT 2, 'SUV', '2', 'asset_vehicle_type', 0, 'success', '', '运动型多用途车', 'admin', NOW(), 'admin', NOW(), 0 UNION ALL + SELECT 3, '厢式货车', '3', 'asset_vehicle_type', 0, 'info', '', '封闭式货运车辆', 'admin', NOW(), 'admin', NOW(), 0 UNION ALL + SELECT 4, '18吨双飞翼货车', '4', 'asset_vehicle_type', 0, 'warning', '', '大型货运车辆', 'admin', NOW(), 'admin', NOW(), 0 UNION ALL + SELECT 5, '轻型货车', '5', 'asset_vehicle_type', 0, 'default', '', '4.5吨以下货车', 'admin', NOW(), 'admin', NOW(), 0 UNION ALL + SELECT 6, '中型货车', '6', 'asset_vehicle_type', 0, 'default', '', '4.5-12吨货车', 'admin', NOW(), 'admin', NOW(), 0 UNION ALL + SELECT 7, '重型货车', '7', 'asset_vehicle_type', 0, 'danger', '', '12吨以上货车', 'admin', NOW(), 'admin', NOW(), 0 UNION ALL + SELECT 8, '客车', '8', 'asset_vehicle_type', 0, 'primary', '', '大中型客运车辆', 'admin', NOW(), 'admin', NOW(), 0 UNION ALL + SELECT 9, '专用车', '9', 'asset_vehicle_type', 0, 'info', '', '特种用途车辆', 'admin', NOW(), 'admin', NOW(), 0 +) AS tmp +WHERE NOT EXISTS ( + SELECT 1 FROM `system_dict_data` WHERE `dict_type` = 'asset_vehicle_type' AND `value` = tmp.value +); + +SELECT 'Vehicle type dictionary created successfully!' AS status; + +-- ==================== 第三部分:车辆上牌记录表创建(asset 库)==================== +USE `asset`; + +-- 创建车辆上牌记录表 +CREATE TABLE IF NOT EXISTS `asset_vehicle_registration` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `vehicle_id` BIGINT NOT NULL COMMENT '车辆ID', + `vin` VARCHAR(50) NOT NULL COMMENT '车辆识别代号(VIN)', + `plate_no` VARCHAR(20) NOT NULL COMMENT '车牌号', + `plate_date` DATE NOT NULL COMMENT '上牌日期', + `operator` VARCHAR(50) COMMENT '操作员', + + -- OCR 识别信息 + `recognized_brand` VARCHAR(100) COMMENT 'OCR识别的品牌型号', + `recognized_model` VARCHAR(100) COMMENT 'OCR识别的车型', + `vehicle_type` VARCHAR(50) COMMENT '车辆类型', + `owner` VARCHAR(100) COMMENT '所有人', + `use_character` VARCHAR(50) COMMENT '使用性质', + `engine_no` VARCHAR(50) COMMENT '发动机号码', + `register_date` DATE COMMENT '注册日期', + `issue_date` DATE COMMENT '发证日期', + `inspection_record` VARCHAR(50) COMMENT '检验记录', + `scrap_date` DATE COMMENT '强制报废期止', + `curb_weight` VARCHAR(20) COMMENT '整备质量(kg)', + `total_mass` VARCHAR(20) COMMENT '总质量(kg)', + `approved_passenger_capacity` VARCHAR(20) COMMENT '核定载人数', + + -- 匹配信息 + `vehicle_model_id` BIGINT COMMENT '匹配的车型ID', + `match_confidence` DECIMAL(5,2) COMMENT '匹配置信度(0-100)', + `match_method` VARCHAR(20) COMMENT '匹配方式(exact/fuzzy/manual)', + + -- 照片信息 + `photo_url` VARCHAR(500) COMMENT '行驶证照片URL', + `photo_size` INT COMMENT '照片大小(字节)', + + -- OCR 信息 + `ocr_provider` VARCHAR(50) COMMENT 'OCR厂商', + `ocr_cost_time` INT COMMENT 'OCR识别耗时(毫秒)', + `ocr_raw_result` TEXT COMMENT 'OCR原始结果(JSON)', + + -- 状态信息 + `status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态(0-待确认 1-已确认 2-已作废)', + `remark` VARCHAR(500) COMMENT '备注', + + -- 审计字段 + `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号', + + PRIMARY KEY (`id`), + UNIQUE KEY `uk_vehicle_plate` (`vehicle_id`, `plate_no`, `deleted`), + INDEX `idx_vin` (`vin`), + INDEX `idx_plate_no` (`plate_no`), + INDEX `idx_plate_date` (`plate_date`), + INDEX `idx_status` (`status`), + INDEX `idx_create_time` (`create_time`), + INDEX `idx_tenant_id` (`tenant_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车辆上牌记录表'; + +SELECT 'Vehicle registration table created successfully!' AS status; + +-- ==================== 第四部分:菜单和权限配置(system 库或主库)==================== +-- 注意:需要先找到"车辆管理"或"资产管理"的父菜单ID +-- 如果没有父菜单,请先创建或手动指定 parent_id + +-- 查询可能的父菜单 +SELECT id, name, parent_id, path +FROM system_menu +WHERE name LIKE '%车辆%' OR name LIKE '%资产%' OR path LIKE '%vehicle%' OR path LIKE '%asset%' +ORDER BY id; + +-- 手动执行:将下面的 @parent_id 替换为实际的父菜单ID +-- SET @parent_id = YOUR_PARENT_MENU_ID; + +-- 插入上牌管理菜单(请手动替换 @parent_id) +-- INSERT INTO system_menu( +-- name, permission, type, sort, parent_id, +-- path, icon, component, status, component_name +-- ) +-- VALUES ( +-- '上牌管理', '', 2, 3, @parent_id, +-- 'registration', 'form', 'asset/vehicle/registration/index', 0, 'VehicleRegistration' +-- ); + +-- 获取刚插入的菜单ID +-- SET @menuId = LAST_INSERT_ID(); + +-- 上牌管理按钮权限 +-- INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +-- VALUES +-- ('上牌记录查询', 'asset:vehicle-registration:query', 3, 1, @menuId, '', '', '', 0), +-- ('上牌记录创建', 'asset:vehicle-registration:create', 3, 2, @menuId, '', '', '', 0), +-- ('上牌记录更新', 'asset:vehicle-registration:update', 3, 3, @menuId, '', '', '', 0), +-- ('上牌记录删除', 'asset:vehicle-registration:delete', 3, 4, @menuId, '', '', '', 0), +-- ('行驶证识别', 'asset:vehicle-registration:recognize', 3, 5, @menuId, '', '', '', 0); + +SELECT '========================================' AS ''; +SELECT 'All updates completed!' AS status; +SELECT '========================================' AS ''; +SELECT '注意:菜单部分需要手动执行,请先查询父菜单ID' AS note; diff --git a/sql/rebuild/asset_ddl.sql b/sql/rebuild/asset_ddl.sql new file mode 100644 index 0000000..86a6957 --- /dev/null +++ b/sql/rebuild/asset_ddl.sql @@ -0,0 +1,836 @@ +-- ============================================================ +-- Asset Module DDL - Generated from DO classes +-- Database: oneos_asset +-- Generated: 2026-03-16 +-- ============================================================ + +-- 1. asset_parking (停车场) +DROP TABLE IF EXISTS `asset_parking`; +CREATE TABLE `asset_parking` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `name` varchar(255) DEFAULT NULL COMMENT '停车场名称', + `capacity` int DEFAULT NULL COMMENT '容量', + `manager_name` varchar(255) DEFAULT NULL COMMENT '管理员姓名', + `manager_phone` varchar(64) DEFAULT NULL COMMENT '管理员电话', + `contact_name` varchar(255) DEFAULT NULL COMMENT '联系人姓名', + `contact_phone` varchar(64) DEFAULT NULL COMMENT '联系人电话', + `parked_amount` int DEFAULT NULL COMMENT '已停数量', + `province` varchar(64) DEFAULT NULL COMMENT '省份', + `city` varchar(64) DEFAULT NULL COMMENT '城市', + `address` varchar(500) DEFAULT NULL COMMENT '详细地址', + `longitude` varchar(32) DEFAULT NULL COMMENT '经度', + `latitude` varchar(32) DEFAULT NULL COMMENT '纬度', + `lease_start_date` date DEFAULT NULL COMMENT '租赁开始日期', + `lease_end_date` date DEFAULT NULL COMMENT '租赁结束日期', + `rent_fee` decimal(18,2) DEFAULT NULL COMMENT '租金', + `contract_file_url` varchar(500) DEFAULT NULL COMMENT '合同文件URL', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='停车场'; + +-- 2. asset_vehicle_model (车型参数) +DROP TABLE IF EXISTS `asset_vehicle_model`; +CREATE TABLE `asset_vehicle_model` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `brand` varchar(128) DEFAULT NULL COMMENT '品牌', + `model` varchar(128) DEFAULT NULL COMMENT '型号', + `vehicle_type` varchar(64) DEFAULT NULL COMMENT '车辆类型', + `model_label` varchar(128) DEFAULT NULL COMMENT '车型标签', + `fuel_type` varchar(64) DEFAULT NULL COMMENT '燃料类型', + `plate_color` varchar(32) DEFAULT NULL COMMENT '车牌颜色', + `truck_size_x` varchar(32) DEFAULT NULL COMMENT '货箱尺寸X', + `truck_size_y` varchar(32) DEFAULT NULL COMMENT '货箱尺寸Y', + `truck_size_z` varchar(32) DEFAULT NULL COMMENT '货箱尺寸Z', + `tire_size` varchar(64) DEFAULT NULL COMMENT '轮胎尺寸', + `tire_number` int DEFAULT NULL COMMENT '轮胎数量', + `battery_type` varchar(64) DEFAULT NULL COMMENT '电池类型', + `battery_factory` varchar(128) DEFAULT NULL COMMENT '电池厂家', + `reserve_electricity` decimal(18,2) DEFAULT NULL COMMENT '储备电量', + `electricity_mileage` int DEFAULT NULL COMMENT '纯电续航里程', + `hydrogen_capacity` int DEFAULT NULL COMMENT '储氢容量', + `hydrogen_factory` varchar(128) DEFAULT NULL COMMENT '氢系统厂家', + `hydrogen_unit` varchar(32) DEFAULT NULL COMMENT '氢气单位', + `hydrogen_mileage` int DEFAULT NULL COMMENT '氢续航里程', + `refrigerator_factory` varchar(128) DEFAULT NULL COMMENT '冷机厂家', + `online_spread_enterprise` varchar(255) DEFAULT NULL COMMENT '线上传播企业', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车型参数'; + +-- 3. asset_vehicle_model_maintain_item (车型保养项目) +DROP TABLE IF EXISTS `asset_vehicle_model_maintain_item`; +CREATE TABLE `asset_vehicle_model_maintain_item` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `vehicle_model_id` bigint DEFAULT NULL COMMENT '车型ID', + `maintain_item` varchar(255) DEFAULT NULL COMMENT '保养项目', + `kilometer_cycle` int DEFAULT NULL COMMENT '公里周期', + `time_cycle` int DEFAULT NULL COMMENT '时间周期(月)', + `hour_fee` decimal(18,2) DEFAULT NULL COMMENT '工时费', + `material_fee` decimal(18,2) DEFAULT NULL COMMENT '材料费', + `total_fee` decimal(18,2) DEFAULT NULL COMMENT '总费用', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车型保养项目'; + +-- 4. asset_vehicle_base (车辆基础信息) +DROP TABLE IF EXISTS `asset_vehicle_base`; +CREATE TABLE `asset_vehicle_base` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `vin` varchar(64) DEFAULT NULL COMMENT 'VIN码', + `plate_no` varchar(32) DEFAULT NULL COMMENT '车牌号', + `vehicle_no` varchar(64) DEFAULT NULL COMMENT '车辆编号', + `vehicle_model_id` bigint DEFAULT NULL COMMENT '车型ID', + `region_province` varchar(64) DEFAULT NULL COMMENT '所属省份', + `region_city` varchar(64) DEFAULT NULL COMMENT '所属城市', + `engine_no` varchar(64) DEFAULT NULL COMMENT '发动机号', + `register_date` date DEFAULT NULL COMMENT '注册日期', + `purchase_date` date DEFAULT NULL COMMENT '购买日期', + `purchase_price` decimal(18,2) DEFAULT NULL COMMENT '购买价格', + `color` varchar(32) DEFAULT NULL COMMENT '颜色', + `year` varchar(16) DEFAULT NULL COMMENT '年款', + `mileage` int DEFAULT NULL COMMENT '里程数', + `inspect_expire` varchar(32) DEFAULT NULL COMMENT '年检到期', + `scrap_date` date DEFAULT NULL COMMENT '报废日期', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_vin` (`vin`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车辆基础信息'; + +-- 5. asset_vehicle_location (车辆位置信息) +DROP TABLE IF EXISTS `asset_vehicle_location`; +CREATE TABLE `asset_vehicle_location` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `vehicle_id` bigint DEFAULT NULL COMMENT '车辆ID', + `parking_id` bigint DEFAULT NULL COMMENT '停车场ID', + `parking_name` varchar(255) DEFAULT NULL COMMENT '停车场名称', + `parking_space` varchar(64) DEFAULT NULL COMMENT '车位号', + `location` varchar(500) DEFAULT NULL COMMENT '位置描述', + `latitude` decimal(18,8) DEFAULT NULL COMMENT '纬度', + `longitude` decimal(18,8) DEFAULT NULL COMMENT '经度', + `gps_time` datetime DEFAULT NULL COMMENT 'GPS时间', + `entry_time` datetime DEFAULT NULL COMMENT '进场时间', + `exit_time` datetime DEFAULT NULL COMMENT '出场时间', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_vehicle_id` (`vehicle_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车辆位置信息'; + +-- 6. asset_vehicle_business (车辆业务信息) +DROP TABLE IF EXISTS `asset_vehicle_business`; +CREATE TABLE `asset_vehicle_business` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `vehicle_id` bigint DEFAULT NULL COMMENT '车辆ID', + `customer_id` bigint DEFAULT NULL COMMENT '客户ID', + `department_id` bigint DEFAULT NULL COMMENT '部门ID', + `manager_id` bigint DEFAULT NULL COMMENT '管理人ID', + `contract_id` bigint DEFAULT NULL COMMENT '合同ID', + `ownership` varchar(64) DEFAULT NULL COMMENT '产权归属', + `delivery_date` date DEFAULT NULL COMMENT '交车日期', + `return_date` date DEFAULT NULL COMMENT '还车日期', + `monthly_rent` decimal(18,2) DEFAULT NULL COMMENT '月租金', + `deposit` decimal(18,2) DEFAULT NULL COMMENT '押金', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_vehicle_id` (`vehicle_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车辆业务信息'; + +-- 7. asset_vehicle_status (车辆状态信息) +DROP TABLE IF EXISTS `asset_vehicle_status`; +CREATE TABLE `asset_vehicle_status` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `vehicle_id` bigint DEFAULT NULL COMMENT '车辆ID', + `status` int DEFAULT NULL COMMENT '车辆状态', + `operate_status` int DEFAULT NULL COMMENT '运营状态', + `storage_status` int DEFAULT NULL COMMENT '仓储状态', + `out_status` int DEFAULT NULL COMMENT '出库状态', + `preempt_status` int DEFAULT NULL COMMENT '占用状态', + `prepare_status` int DEFAULT NULL COMMENT '备车状态', + `transfer_status` int DEFAULT NULL COMMENT '调拨状态', + `repair_status` int DEFAULT NULL COMMENT '维修状态', + `license_status` int DEFAULT NULL COMMENT '牌照状态', + `scrap_status` int DEFAULT NULL COMMENT '报废状态', + `online_status` int DEFAULT NULL COMMENT '在线状态', + `is_prepared` bit(1) DEFAULT NULL COMMENT '是否已备车', + `is_delivered` bit(1) DEFAULT NULL COMMENT '是否已交车', + `is_returned` bit(1) DEFAULT NULL COMMENT '是否已还车', + `last_maintain_date` date DEFAULT NULL COMMENT '上次保养日期', + `next_maintain_date` date DEFAULT NULL COMMENT '下次保养日期', + `last_inspect_date` date DEFAULT NULL COMMENT '上次年检日期', + `next_inspect_date` date DEFAULT NULL COMMENT '下次年检日期', + `insurance_expire_date` date DEFAULT NULL COMMENT '保险到期日期', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_vehicle_id` (`vehicle_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车辆状态信息'; + +-- 8. asset_customer (客户) +DROP TABLE IF EXISTS `asset_customer`; +CREATE TABLE `asset_customer` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `customer_code` varchar(64) DEFAULT NULL COMMENT '客户编码', + `coop_status` varchar(32) DEFAULT NULL COMMENT '合作状态', + `customer_name` varchar(255) DEFAULT NULL COMMENT '客户名称', + `province` varchar(64) DEFAULT NULL COMMENT '省份', + `city` varchar(64) DEFAULT NULL COMMENT '城市', + `address` varchar(500) DEFAULT NULL COMMENT '地址', + `region` varchar(64) DEFAULT NULL COMMENT '区域', + `contact` varchar(64) DEFAULT NULL COMMENT '联系人', + `contact_mobile` varchar(32) DEFAULT NULL COMMENT '联系手机', + `contact_phone` varchar(32) DEFAULT NULL COMMENT '联系电话', + `email` varchar(128) DEFAULT NULL COMMENT '邮箱', + `credit_code_or_id` varchar(64) DEFAULT NULL COMMENT '统一社会信用代码/身份证', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `tax_id` varchar(64) DEFAULT NULL COMMENT '税号', + `invoice_address` varchar(500) DEFAULT NULL COMMENT '开票地址', + `invoice_phone` varchar(32) DEFAULT NULL COMMENT '开票电话', + `account` varchar(64) DEFAULT NULL COMMENT '银行账号', + `opening_bank` varchar(255) DEFAULT NULL COMMENT '开户行', + `mailing_address` varchar(500) DEFAULT NULL COMMENT '邮寄地址', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='客户'; + +-- 9. asset_customer_business_manager (客户商务经理) +DROP TABLE IF EXISTS `asset_customer_business_manager`; +CREATE TABLE `asset_customer_business_manager` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `customer_id` bigint DEFAULT NULL COMMENT '客户ID', + `business_manager_name` varchar(64) DEFAULT NULL COMMENT '商务经理名称', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='客户商务经理'; + +-- 10. asset_supplier (供应商) +DROP TABLE IF EXISTS `asset_supplier`; +CREATE TABLE `asset_supplier` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `supplier_code` varchar(64) DEFAULT NULL COMMENT '供应商编码', + `coop_status` varchar(32) DEFAULT NULL COMMENT '合作状态', + `supplier_name` varchar(255) DEFAULT NULL COMMENT '供应商名称', + `type` varchar(64) DEFAULT NULL COMMENT '类型', + `province` varchar(64) DEFAULT NULL COMMENT '省份', + `city` varchar(64) DEFAULT NULL COMMENT '城市', + `address` varchar(500) DEFAULT NULL COMMENT '地址', + `region` varchar(64) DEFAULT NULL COMMENT '区域', + `contact` varchar(64) DEFAULT NULL COMMENT '联系人', + `contact_mobile` varchar(32) DEFAULT NULL COMMENT '联系手机', + `contact_phone` varchar(32) DEFAULT NULL COMMENT '联系电话', + `email` varchar(128) DEFAULT NULL COMMENT '邮箱', + `credit_code_or_id` varchar(64) DEFAULT NULL COMMENT '统一社会信用代码', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `tax_id` varchar(64) DEFAULT NULL COMMENT '税号', + `invoice_address` varchar(500) DEFAULT NULL COMMENT '开票地址', + `invoice_phone` varchar(32) DEFAULT NULL COMMENT '开票电话', + `account` varchar(64) DEFAULT NULL COMMENT '银行账号', + `opening_bank` varchar(255) DEFAULT NULL COMMENT '开户行', + `mailing_address` varchar(500) DEFAULT NULL COMMENT '邮寄地址', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='供应商'; + +-- 11. asset_vehicle_registration (车辆行驶证) +DROP TABLE IF EXISTS `asset_vehicle_registration`; +CREATE TABLE `asset_vehicle_registration` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `vehicle_id` bigint DEFAULT NULL COMMENT '车辆ID', + `vin` varchar(64) DEFAULT NULL COMMENT 'VIN码', + `plate_no` varchar(32) DEFAULT NULL COMMENT '车牌号', + `plate_date` date DEFAULT NULL COMMENT '上牌日期', + `operator` varchar(64) DEFAULT NULL COMMENT '经办人', + `recognized_brand` varchar(128) DEFAULT NULL COMMENT '识别品牌', + `recognized_model` varchar(128) DEFAULT NULL COMMENT '识别型号', + `vehicle_type` varchar(64) DEFAULT NULL COMMENT '车辆类型', + `owner` varchar(255) DEFAULT NULL COMMENT '所有人', + `use_character` varchar(64) DEFAULT NULL COMMENT '使用性质', + `engine_no` varchar(64) DEFAULT NULL COMMENT '发动机号', + `register_date` date DEFAULT NULL COMMENT '注册日期', + `issue_date` date DEFAULT NULL COMMENT '发证日期', + `inspection_record` varchar(500) DEFAULT NULL COMMENT '检验记录', + `scrap_date` date DEFAULT NULL COMMENT '报废日期', + `curb_weight` varchar(32) DEFAULT NULL COMMENT '整备质量', + `total_mass` varchar(32) DEFAULT NULL COMMENT '总质量', + `approved_passenger_capacity` varchar(32) DEFAULT NULL COMMENT '核定载客', + `vehicle_model_id` bigint DEFAULT NULL COMMENT '车型ID', + `match_confidence` decimal(5,2) DEFAULT NULL COMMENT '匹配置信度', + `match_method` varchar(32) DEFAULT NULL COMMENT '匹配方式', + `photo_url` varchar(500) DEFAULT NULL COMMENT '照片URL', + `photo_size` int DEFAULT NULL COMMENT '照片大小', + `ocr_provider` varchar(64) DEFAULT NULL COMMENT 'OCR提供商', + `ocr_cost_time` int DEFAULT NULL COMMENT 'OCR耗时(ms)', + `ocr_raw_result` text COMMENT 'OCR原始结果', + `status` int DEFAULT NULL COMMENT '状态', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车辆行驶证'; + +-- 12. asset_contract (合同) +DROP TABLE IF EXISTS `asset_contract`; +CREATE TABLE `asset_contract` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `contract_code` varchar(64) DEFAULT NULL COMMENT '合同编号', + `contract_type` int DEFAULT NULL COMMENT '合同类型', + `project_name` varchar(255) DEFAULT NULL COMMENT '项目名称', + `start_date` date DEFAULT NULL COMMENT '开始日期', + `end_date` date DEFAULT NULL COMMENT '结束日期', + `payment_method` varchar(64) DEFAULT NULL COMMENT '付款方式', + `payment_cycle` varchar(64) DEFAULT NULL COMMENT '付款周期', + `signing_company` varchar(255) DEFAULT NULL COMMENT '签约公司', + `delivery_province` varchar(64) DEFAULT NULL COMMENT '交付省份', + `delivery_city` varchar(64) DEFAULT NULL COMMENT '交付城市', + `delivery_location` varchar(500) DEFAULT NULL COMMENT '交付地点', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `customer_id` bigint DEFAULT NULL COMMENT '客户ID', + `customer_name` varchar(255) DEFAULT NULL COMMENT '客户名称', + `third_party_enabled` bit(1) DEFAULT NULL COMMENT '是否启用第三方', + `third_party_customer_id` bigint DEFAULT NULL COMMENT '第三方客户ID', + `third_party_name` varchar(255) DEFAULT NULL COMMENT '第三方名称', + `business_dept_id` bigint DEFAULT NULL COMMENT '商务部门ID', + `business_manager_id` bigint DEFAULT NULL COMMENT '商务经理ID', + `approval_status` int DEFAULT NULL COMMENT '审批状态', + `bpm_instance_id` varchar(64) DEFAULT NULL COMMENT '流程实例ID', + `contract_status` int DEFAULT NULL COMMENT '合同状态', + `effective_time` datetime DEFAULT NULL COMMENT '生效时间', + `terminate_time` datetime DEFAULT NULL COMMENT '终止时间', + `terminate_reason` varchar(500) DEFAULT NULL COMMENT '终止原因', + `renewed_contract_id` bigint DEFAULT NULL COMMENT '续约合同ID', + `original_contract_id` bigint DEFAULT NULL COMMENT '原始合同ID', + `hydrogen_bearer` varchar(64) DEFAULT NULL COMMENT '氢费承担方', + `hydrogen_payment_method` varchar(64) DEFAULT NULL COMMENT '氢费支付方式', + `hydrogen_prepay` decimal(18,2) DEFAULT NULL COMMENT '氢费预付金额', + `hydrogen_return_price` decimal(18,2) DEFAULT NULL COMMENT '氢费返还单价', + `billing_method` varchar(64) DEFAULT NULL COMMENT '计费方式', + `main_vehicle_type` varchar(64) DEFAULT NULL COMMENT '主要车型', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同'; + +-- 13. asset_contract_vehicle (合同车辆) +DROP TABLE IF EXISTS `asset_contract_vehicle`; +CREATE TABLE `asset_contract_vehicle` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `contract_id` bigint DEFAULT NULL COMMENT '合同ID', + `vehicle_id` bigint DEFAULT NULL COMMENT '车辆ID', + `brand` varchar(128) DEFAULT NULL COMMENT '品牌', + `model` varchar(128) DEFAULT NULL COMMENT '型号', + `plate_no` varchar(32) DEFAULT NULL COMMENT '车牌号', + `vin` varchar(64) DEFAULT NULL COMMENT 'VIN码', + `month_rent` decimal(18,2) DEFAULT NULL COMMENT '月租金', + `deposit` decimal(18,2) DEFAULT NULL COMMENT '押金', + `vehicle_status` int DEFAULT NULL COMMENT '车辆状态', + `actual_delivery_time` datetime DEFAULT NULL COMMENT '实际交付时间', + `delivery_person` varchar(64) DEFAULT NULL COMMENT '交付人', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同车辆'; + +-- 14. asset_contract_vehicle_service (合同车辆服务) +DROP TABLE IF EXISTS `asset_contract_vehicle_service`; +CREATE TABLE `asset_contract_vehicle_service` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `contract_vehicle_id` bigint DEFAULT NULL COMMENT '合同车辆ID', + `service_name` varchar(255) DEFAULT NULL COMMENT '服务名称', + `service_fee` decimal(18,2) DEFAULT NULL COMMENT '服务费', + `effective_date` date DEFAULT NULL COMMENT '生效日期', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同车辆服务'; + +-- 15. asset_contract_authorized (合同授权人) +DROP TABLE IF EXISTS `asset_contract_authorized`; +CREATE TABLE `asset_contract_authorized` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `contract_id` bigint DEFAULT NULL COMMENT '合同ID', + `name` varchar(64) DEFAULT NULL COMMENT '姓名', + `phone` varchar(32) DEFAULT NULL COMMENT '电话', + `id_card` varchar(32) DEFAULT NULL COMMENT '身份证号', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同授权人'; + +-- 16. asset_contract_attachment (合同附件) +DROP TABLE IF EXISTS `asset_contract_attachment`; +CREATE TABLE `asset_contract_attachment` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `contract_id` bigint DEFAULT NULL COMMENT '合同ID', + `attachment_type` int DEFAULT NULL COMMENT '附件类型', + `file_id` bigint DEFAULT NULL COMMENT '文件ID', + `file_name` varchar(255) DEFAULT NULL COMMENT '文件名', + `file_url` varchar(500) DEFAULT NULL COMMENT '文件URL', + `file_size` bigint DEFAULT NULL COMMENT '文件大小', + `upload_time` datetime DEFAULT NULL COMMENT '上传时间', + `uploader` varchar(64) DEFAULT NULL COMMENT '上传人', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同附件'; + +-- 17. asset_contract_change_history (合同变更历史) +DROP TABLE IF EXISTS `asset_contract_change_history`; +CREATE TABLE `asset_contract_change_history` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `contract_id` bigint DEFAULT NULL COMMENT '合同ID', + `change_type` varchar(64) DEFAULT NULL COMMENT '变更类型', + `change_content` text COMMENT '变更内容', + `operator` varchar(64) DEFAULT NULL COMMENT '操作人', + `operate_time` datetime DEFAULT NULL COMMENT '操作时间', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同变更历史'; + +-- 18. asset_inspection_template (验车模板) +DROP TABLE IF EXISTS `asset_inspection_template`; +CREATE TABLE `asset_inspection_template` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `code` varchar(64) DEFAULT NULL COMMENT '模板编码', + `name` varchar(255) DEFAULT NULL COMMENT '模板名称', + `biz_type` int DEFAULT NULL COMMENT '业务类型', + `vehicle_type` varchar(64) DEFAULT NULL COMMENT '车辆类型', + `status` int DEFAULT NULL COMMENT '状态', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='验车模板'; + +-- 19. asset_inspection_template_item (验车模板项) +DROP TABLE IF EXISTS `asset_inspection_template_item`; +CREATE TABLE `asset_inspection_template_item` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `template_id` bigint DEFAULT NULL COMMENT '模板ID', + `category` varchar(64) DEFAULT NULL COMMENT '分类', + `item_name` varchar(255) DEFAULT NULL COMMENT '项目名称', + `item_code` varchar(64) DEFAULT NULL COMMENT '项目编码', + `input_type` varchar(32) DEFAULT NULL COMMENT '输入类型', + `sort` int DEFAULT NULL COMMENT '排序', + `required` int DEFAULT NULL COMMENT '是否必填', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='验车模板项'; + +-- 20. asset_inspection_record (验车记录) +DROP TABLE IF EXISTS `asset_inspection_record`; +CREATE TABLE `asset_inspection_record` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `record_code` varchar(64) DEFAULT NULL COMMENT '记录编码', + `template_id` bigint DEFAULT NULL COMMENT '模板ID', + `source_type` int DEFAULT NULL COMMENT '来源类型', + `source_id` bigint DEFAULT NULL COMMENT '来源ID', + `vehicle_id` bigint DEFAULT NULL COMMENT '车辆ID', + `inspector_name` varchar(64) DEFAULT NULL COMMENT '检查人', + `inspection_time` datetime DEFAULT NULL COMMENT '检查时间', + `status` int DEFAULT NULL COMMENT '状态', + `overall_result` int DEFAULT NULL COMMENT '总体结果', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `cloned_from_id` bigint DEFAULT NULL COMMENT '克隆自ID', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='验车记录'; + +-- 21. asset_inspection_record_item (验车记录项) +DROP TABLE IF EXISTS `asset_inspection_record_item`; +CREATE TABLE `asset_inspection_record_item` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `record_id` bigint DEFAULT NULL COMMENT '记录ID', + `item_code` varchar(64) DEFAULT NULL COMMENT '项目编码', + `category` varchar(64) DEFAULT NULL COMMENT '分类', + `item_name` varchar(255) DEFAULT NULL COMMENT '项目名称', + `input_type` varchar(32) DEFAULT NULL COMMENT '输入类型', + `result` int DEFAULT NULL COMMENT '结果', + `value` varchar(500) DEFAULT NULL COMMENT '值', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `image_urls` varchar(2000) DEFAULT NULL COMMENT '图片URL列表', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='验车记录项'; + +-- 22. asset_vehicle_prepare (备车) +DROP TABLE IF EXISTS `asset_vehicle_prepare`; +CREATE TABLE `asset_vehicle_prepare` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `vehicle_id` bigint DEFAULT NULL COMMENT '车辆ID', + `plate_no` varchar(32) DEFAULT NULL COMMENT '车牌号', + `vin` varchar(64) DEFAULT NULL COMMENT 'VIN码', + `vehicle_model_id` bigint DEFAULT NULL COMMENT '车型ID', + `brand` varchar(128) DEFAULT NULL COMMENT '品牌', + `model` varchar(128) DEFAULT NULL COMMENT '型号', + `vehicle_type` varchar(64) DEFAULT NULL COMMENT '车辆类型', + `parking_lot` varchar(255) DEFAULT NULL COMMENT '停车场', + `contract_id` bigint DEFAULT NULL COMMENT '合同ID', + `contract_code` varchar(64) DEFAULT NULL COMMENT '合同编号', + `preparation_type` varchar(64) DEFAULT NULL COMMENT '备车类型', + `mileage` int DEFAULT NULL COMMENT '里程', + `hydrogen_remaining` decimal(18,2) DEFAULT NULL COMMENT '剩余氢量', + `hydrogen_unit` varchar(32) DEFAULT NULL COMMENT '氢气单位', + `battery_remaining` decimal(18,2) DEFAULT NULL COMMENT '剩余电量', + `has_body_ad` bit(1) DEFAULT NULL COMMENT '是否有车身广告', + `body_ad_photos` varchar(2000) DEFAULT NULL COMMENT '车身广告照片', + `enlarged_text_photo` varchar(500) DEFAULT NULL COMMENT '放大字照片', + `has_tail_lift` bit(1) DEFAULT NULL COMMENT '是否有尾板', + `spare_tire_depth` decimal(18,2) DEFAULT NULL COMMENT '备胎花纹深度', + `spare_tire_photo` varchar(500) DEFAULT NULL COMMENT '备胎照片', + `trailer_plate_no` varchar(32) DEFAULT NULL COMMENT '挂车牌号', + `defect_photos` varchar(2000) DEFAULT NULL COMMENT '缺陷照片', + `inspection_record_id` bigint DEFAULT NULL COMMENT '验车记录ID', + `check_list` text COMMENT '检查清单JSON', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `status` int DEFAULT NULL COMMENT '状态', + `complete_time` datetime DEFAULT NULL COMMENT '完成时间', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='备车'; + +-- 23. asset_delivery_task (交车任务) +DROP TABLE IF EXISTS `asset_delivery_task`; +CREATE TABLE `asset_delivery_task` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `task_code` varchar(64) DEFAULT NULL COMMENT '任务编码', + `contract_id` bigint DEFAULT NULL COMMENT '合同ID', + `contract_code` varchar(64) DEFAULT NULL COMMENT '合同编号', + `project_name` varchar(255) DEFAULT NULL COMMENT '项目名称', + `customer_id` bigint DEFAULT NULL COMMENT '客户ID', + `customer_name` varchar(255) DEFAULT NULL COMMENT '客户名称', + `expected_delivery_date_start` date DEFAULT NULL COMMENT '预计交付开始日期', + `expected_delivery_date_end` date DEFAULT NULL COMMENT '预计交付结束日期', + `billing_start_date` date DEFAULT NULL COMMENT '计费开始日期', + `delivery_province` varchar(64) DEFAULT NULL COMMENT '交付省份', + `delivery_city` varchar(64) DEFAULT NULL COMMENT '交付城市', + `delivery_location` varchar(500) DEFAULT NULL COMMENT '交付地点', + `vehicle_count` int DEFAULT NULL COMMENT '车辆数量', + `task_status` int DEFAULT NULL COMMENT '任务状态', + `delivery_status` int DEFAULT NULL COMMENT '交付状态', + `need_return` bit(1) DEFAULT NULL COMMENT '是否需要还车', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='交车任务'; + +-- 24. asset_delivery_task_vehicle (交车任务车辆) +DROP TABLE IF EXISTS `asset_delivery_task_vehicle`; +CREATE TABLE `asset_delivery_task_vehicle` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `task_id` bigint DEFAULT NULL COMMENT '任务ID', + `contract_vehicle_id` bigint DEFAULT NULL COMMENT '合同车辆ID', + `vehicle_id` bigint DEFAULT NULL COMMENT '车辆ID', + `plate_no` varchar(32) DEFAULT NULL COMMENT '车牌号', + `vin` varchar(64) DEFAULT NULL COMMENT 'VIN码', + `brand` varchar(128) DEFAULT NULL COMMENT '品牌', + `model` varchar(128) DEFAULT NULL COMMENT '型号', + `month_rent` decimal(18,2) DEFAULT NULL COMMENT '月租金', + `deposit` decimal(18,2) DEFAULT NULL COMMENT '押金', + `actual_delivery_date` datetime DEFAULT NULL COMMENT '实际交付日期', + `delivery_person` varchar(64) DEFAULT NULL COMMENT '交付人', + `is_delivered` bit(1) DEFAULT NULL COMMENT '是否已交付', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='交车任务车辆'; + +-- 25. asset_delivery_order (交车单) +DROP TABLE IF EXISTS `asset_delivery_order`; +CREATE TABLE `asset_delivery_order` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `order_code` varchar(64) DEFAULT NULL COMMENT '交车单号', + `task_id` bigint DEFAULT NULL COMMENT '任务ID', + `task_code` varchar(64) DEFAULT NULL COMMENT '任务编码', + `contract_id` bigint DEFAULT NULL COMMENT '合同ID', + `contract_code` varchar(64) DEFAULT NULL COMMENT '合同编号', + `project_name` varchar(255) DEFAULT NULL COMMENT '项目名称', + `customer_id` bigint DEFAULT NULL COMMENT '客户ID', + `customer_name` varchar(255) DEFAULT NULL COMMENT '客户名称', + `delivery_date` datetime DEFAULT NULL COMMENT '交车日期', + `delivery_person` varchar(64) DEFAULT NULL COMMENT '交车人', + `delivery_location` varchar(500) DEFAULT NULL COMMENT '交车地点', + `authorized_person_id` bigint DEFAULT NULL COMMENT '授权人ID', + `authorized_person_name` varchar(64) DEFAULT NULL COMMENT '授权人姓名', + `authorized_person_phone` varchar(32) DEFAULT NULL COMMENT '授权人电话', + `authorized_person_id_card` varchar(32) DEFAULT NULL COMMENT '授权人身份证', + `esign_flow_id` varchar(128) DEFAULT NULL COMMENT '电子签章流程ID', + `esign_status` int DEFAULT NULL COMMENT '电子签章状态', + `delivery_photos` varchar(2000) DEFAULT NULL COMMENT '交车照片', + `driver_name` varchar(64) DEFAULT NULL COMMENT '司机姓名', + `driver_id_card` varchar(32) DEFAULT NULL COMMENT '司机身份证', + `driver_phone` varchar(32) DEFAULT NULL COMMENT '司机电话', + `inspection_data` text COMMENT '验车数据JSON', + `cost_list` text COMMENT '费用清单JSON', + `inspection_record_id` bigint DEFAULT NULL COMMENT '验车记录ID', + `status` int DEFAULT NULL COMMENT '状态', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='交车单'; + +-- 26. asset_delivery_order_vehicle (交车单车辆) +DROP TABLE IF EXISTS `asset_delivery_order_vehicle`; +CREATE TABLE `asset_delivery_order_vehicle` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `order_id` bigint DEFAULT NULL COMMENT '交车单ID', + `task_vehicle_id` bigint DEFAULT NULL COMMENT '任务车辆ID', + `vehicle_id` bigint DEFAULT NULL COMMENT '车辆ID', + `plate_no` varchar(32) DEFAULT NULL COMMENT '车牌号', + `vin` varchar(64) DEFAULT NULL COMMENT 'VIN码', + `brand` varchar(128) DEFAULT NULL COMMENT '品牌', + `model` varchar(128) DEFAULT NULL COMMENT '型号', + `mileage` int DEFAULT NULL COMMENT '里程', + `hydrogen_level` decimal(18,2) DEFAULT NULL COMMENT '氢量', + `battery_level` decimal(18,2) DEFAULT NULL COMMENT '电量', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='交车单车辆'; + +-- 27. asset_vehicle_replacement (替换车) +DROP TABLE IF EXISTS `asset_vehicle_replacement`; +CREATE TABLE `asset_vehicle_replacement` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `replacement_code` varchar(64) DEFAULT NULL COMMENT '替换编号', + `replacement_type` int DEFAULT NULL COMMENT '替换类型', + `contract_id` bigint DEFAULT NULL COMMENT '合同ID', + `contract_code` varchar(64) DEFAULT NULL COMMENT '合同编号', + `customer_id` bigint DEFAULT NULL COMMENT '客户ID', + `customer_name` varchar(255) DEFAULT NULL COMMENT '客户名称', + `delivery_order_id` bigint DEFAULT NULL COMMENT '交车单ID', + `original_vehicle_id` bigint DEFAULT NULL COMMENT '原车辆ID', + `original_plate_no` varchar(32) DEFAULT NULL COMMENT '原车牌号', + `original_vin` varchar(64) DEFAULT NULL COMMENT '原VIN码', + `new_vehicle_id` bigint DEFAULT NULL COMMENT '新车辆ID', + `new_plate_no` varchar(32) DEFAULT NULL COMMENT '新车牌号', + `new_vin` varchar(64) DEFAULT NULL COMMENT '新VIN码', + `replacement_reason` varchar(500) DEFAULT NULL COMMENT '替换原因', + `expected_date` date DEFAULT NULL COMMENT '预计替换日期', + `actual_date` date DEFAULT NULL COMMENT '实际替换日期', + `return_date` date DEFAULT NULL COMMENT '预计归还日期', + `actual_return_date` date DEFAULT NULL COMMENT '实际归还日期', + `status` int DEFAULT NULL COMMENT '状态', + `approval_status` int DEFAULT NULL COMMENT '审批状态', + `bpm_instance_id` varchar(64) DEFAULT NULL COMMENT '流程实例ID', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='替换车'; + +-- 28. asset_return_order (还车单) +DROP TABLE IF EXISTS `asset_return_order`; +CREATE TABLE `asset_return_order` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `order_code` varchar(64) DEFAULT NULL COMMENT '还车单号', + `contract_id` bigint DEFAULT NULL COMMENT '合同ID', + `contract_code` varchar(64) DEFAULT NULL COMMENT '合同编号', + `project_name` varchar(255) DEFAULT NULL COMMENT '项目名称', + `customer_id` bigint DEFAULT NULL COMMENT '客户ID', + `customer_name` varchar(255) DEFAULT NULL COMMENT '客户名称', + `return_date` datetime DEFAULT NULL COMMENT '还车日期', + `return_person` varchar(64) DEFAULT NULL COMMENT '还车人', + `return_location` varchar(500) DEFAULT NULL COMMENT '还车地点', + `return_reason` varchar(64) DEFAULT NULL COMMENT '还车原因', + `return_reason_desc` varchar(500) DEFAULT NULL COMMENT '还车原因描述', + `total_refund_amount` decimal(18,2) DEFAULT NULL COMMENT '退款总额', + `deposit_refund` decimal(18,2) DEFAULT NULL COMMENT '押金退款', + `hydrogen_refund` decimal(18,2) DEFAULT NULL COMMENT '氢费退款', + `other_charges` decimal(18,2) DEFAULT NULL COMMENT '其他费用', + `return_photos` varchar(2000) DEFAULT NULL COMMENT '还车照片', + `status` int DEFAULT NULL COMMENT '状态', + `approval_status` int DEFAULT NULL COMMENT '审批状态', + `bpm_instance_id` varchar(64) DEFAULT NULL COMMENT '流程实例ID', + `source_type` int DEFAULT NULL COMMENT '来源类型', + `source_id` bigint DEFAULT NULL COMMENT '来源ID', + `delivery_order_id` bigint DEFAULT NULL COMMENT '交车单ID', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='还车单'; + +-- 29. asset_return_order_vehicle (还车单车辆) +DROP TABLE IF EXISTS `asset_return_order_vehicle`; +CREATE TABLE `asset_return_order_vehicle` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `return_order_id` bigint DEFAULT NULL COMMENT '还车单ID', + `vehicle_id` bigint DEFAULT NULL COMMENT '车辆ID', + `plate_no` varchar(32) DEFAULT NULL COMMENT '车牌号', + `vin` varchar(64) DEFAULT NULL COMMENT 'VIN码', + `brand` varchar(128) DEFAULT NULL COMMENT '品牌', + `model` varchar(128) DEFAULT NULL COMMENT '型号', + `return_mileage` int DEFAULT NULL COMMENT '还车里程', + `return_hydrogen_level` decimal(18,2) DEFAULT NULL COMMENT '还车氢量', + `delivery_hydrogen_level` decimal(18,2) DEFAULT NULL COMMENT '交车氢量', + `hydrogen_diff` decimal(18,2) DEFAULT NULL COMMENT '氢量差值', + `hydrogen_unit_price` decimal(18,2) DEFAULT NULL COMMENT '氢单价', + `hydrogen_refund_amount` decimal(18,2) DEFAULT NULL COMMENT '氢费退款金额', + `check_list` text COMMENT '检查清单JSON', + `defect_photos` varchar(2000) DEFAULT NULL COMMENT '缺陷照片', + `vehicle_damage_fee` decimal(18,2) DEFAULT NULL COMMENT '车辆损坏费', + `tool_damage_fee` decimal(18,2) DEFAULT NULL COMMENT '工具损坏费', + `unpaid_maintenance_fee` decimal(18,2) DEFAULT NULL COMMENT '未付保养费', + `unpaid_repair_fee` decimal(18,2) DEFAULT NULL COMMENT '未付维修费', + `violation_fee` decimal(18,2) DEFAULT NULL COMMENT '违章费', + `other_fee` decimal(18,2) DEFAULT NULL COMMENT '其他费用', + `inspection_record_id` bigint DEFAULT NULL COMMENT '验车记录ID', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='还车单车辆'; + +-- ============================================================ +-- 车辆全量视图 (view) +-- ============================================================ +DROP VIEW IF EXISTS `v_asset_vehicle_full`; +CREATE VIEW `v_asset_vehicle_full` AS +SELECT + b.id, b.vin, b.plate_no, b.vehicle_no, b.vehicle_model_id, + b.region_province, b.region_city, b.engine_no, b.register_date, + b.purchase_date, b.purchase_price, b.color, b.year, b.mileage, + b.inspect_expire, b.scrap_date, + b.creator, b.create_time, b.updater, b.update_time, b.deleted, + l.parking_id, l.parking_name, l.parking_space, l.location, + l.latitude, l.longitude, l.gps_time, l.entry_time, l.exit_time, + biz.customer_id, biz.department_id, biz.manager_id, biz.contract_id, + biz.ownership, biz.delivery_date, biz.return_date, biz.monthly_rent, biz.deposit, + s.status, s.operate_status, s.storage_status, s.out_status, + s.preempt_status, s.prepare_status, s.transfer_status, + s.repair_status, s.license_status, s.scrap_status, s.online_status, + s.is_prepared, s.is_delivered, s.is_returned, + s.last_maintain_date, s.next_maintain_date, + s.last_inspect_date, s.next_inspect_date, s.insurance_expire_date +FROM asset_vehicle_base b +LEFT JOIN asset_vehicle_location l ON b.id = l.vehicle_id AND l.deleted = 0 +LEFT JOIN asset_vehicle_business biz ON b.id = biz.vehicle_id AND biz.deleted = 0 +LEFT JOIN asset_vehicle_status s ON b.id = s.vehicle_id AND s.deleted = 0 +WHERE b.deleted = 0; diff --git a/sql/rebuild/energy_ddl.sql b/sql/rebuild/energy_ddl.sql new file mode 100644 index 0000000..1315733 --- /dev/null +++ b/sql/rebuild/energy_ddl.sql @@ -0,0 +1,236 @@ +-- ============================================================ +-- Energy Module DDL - Generated from DO classes +-- Database: oneos_energy +-- Generated: 2026-03-16 +-- ============================================================ + +-- 1. energy_hydrogen_record (加氢记录) +DROP TABLE IF EXISTS `energy_hydrogen_record`; +CREATE TABLE `energy_hydrogen_record` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT '租户编号', + `station_id` bigint DEFAULT NULL COMMENT '加氢站ID', + `plate_number` varchar(32) DEFAULT NULL COMMENT '车牌号', + `hydrogen_date` date DEFAULT NULL COMMENT '加氢日期', + `hydrogen_quantity` decimal(18,2) DEFAULT NULL COMMENT '加氢量(kg)', + `unit_price` decimal(18,2) DEFAULT NULL COMMENT '单价', + `amount` decimal(18,2) DEFAULT NULL COMMENT '金额', + `mileage` decimal(18,2) DEFAULT NULL COMMENT '里程(km)', + `source_type` int DEFAULT NULL COMMENT '来源类型', + `match_status` int DEFAULT NULL COMMENT '匹配状态', + `vehicle_id` bigint DEFAULT NULL COMMENT '车辆ID', + `customer_id` bigint DEFAULT NULL COMMENT '客户ID', + `upload_batch_no` varchar(64) DEFAULT NULL COMMENT '上传批次号', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='加氢记录'; + +-- 2. energy_hydrogen_detail (加氢明细) +DROP TABLE IF EXISTS `energy_hydrogen_detail`; +CREATE TABLE `energy_hydrogen_detail` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `record_id` bigint DEFAULT NULL COMMENT '加氢记录ID', + `station_id` bigint DEFAULT NULL COMMENT '加氢站ID', + `vehicle_id` bigint DEFAULT NULL COMMENT '车辆ID', + `plate_number` varchar(32) DEFAULT NULL COMMENT '车牌号', + `hydrogen_date` date DEFAULT NULL COMMENT '加氢日期', + `hydrogen_quantity` decimal(18,2) DEFAULT NULL COMMENT '加氢量(kg)', + `cost_price` decimal(18,2) DEFAULT NULL COMMENT '成本价', + `cost_amount` decimal(18,2) DEFAULT NULL COMMENT '成本金额', + `customer_price` decimal(18,2) DEFAULT NULL COMMENT '客户价', + `customer_amount` decimal(18,2) DEFAULT NULL COMMENT '客户金额', + `contract_id` bigint DEFAULT NULL COMMENT '合同ID', + `customer_id` bigint DEFAULT NULL COMMENT '客户ID', + `project_name` varchar(255) DEFAULT NULL COMMENT '项目名称', + `cost_bearer` int DEFAULT NULL COMMENT '费用承担方', + `pay_method` int DEFAULT NULL COMMENT '支付方式', + `audit_status` int DEFAULT NULL COMMENT '审核状态', + `audit_remark` varchar(500) DEFAULT NULL COMMENT '审核备注', + `deduction_status` int DEFAULT NULL COMMENT '扣费状态', + `settlement_status` int DEFAULT NULL COMMENT '结算状态', + `bill_id` bigint DEFAULT NULL COMMENT '账单ID', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='加氢明细'; + +-- 3. energy_bill (能源账单) +DROP TABLE IF EXISTS `energy_bill`; +CREATE TABLE `energy_bill` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `bill_code` varchar(64) DEFAULT NULL COMMENT '账单编号', + `energy_type` int DEFAULT NULL COMMENT '能源类型', + `customer_id` bigint DEFAULT NULL COMMENT '客户ID', + `customer_name` varchar(255) DEFAULT NULL COMMENT '客户名称', + `contract_id` bigint DEFAULT NULL COMMENT '合同ID', + `station_id` bigint DEFAULT NULL COMMENT '站点ID', + `station_name` varchar(255) DEFAULT NULL COMMENT '站点名称', + `cooperation_type` int DEFAULT NULL COMMENT '合作模式(1=预充值 2=月结算)', + `bill_period_start` date DEFAULT NULL COMMENT '账单周期开始', + `bill_period_end` date DEFAULT NULL COMMENT '账单周期结束', + `receivable_amount` decimal(18,2) DEFAULT NULL COMMENT '应收金额', + `actual_amount` decimal(18,2) DEFAULT NULL COMMENT '实收金额', + `adjustment_amount` decimal(18,2) DEFAULT NULL COMMENT '调整金额', + `paid_amount` decimal(18,2) DEFAULT NULL COMMENT '已付金额', + `total_quantity` decimal(18,2) DEFAULT NULL COMMENT '总用量', + `detail_count` int DEFAULT NULL COMMENT '明细条数', + `status` int DEFAULT NULL COMMENT '账单状态', + `audit_status` int DEFAULT NULL COMMENT '审核状态', + `submit_status` int DEFAULT NULL COMMENT '提交状态', + `payment_status` int DEFAULT NULL COMMENT '付款状态', + `auditor_id` bigint DEFAULT NULL COMMENT '审核人ID', + `audit_time` datetime DEFAULT NULL COMMENT '审核时间', + `audit_remark` varchar(500) DEFAULT NULL COMMENT '审核备注', + `submit_time` datetime DEFAULT NULL COMMENT '提交时间', + `generate_time` datetime DEFAULT NULL COMMENT '生成时间', + `yos_bill_code` varchar(64) DEFAULT NULL COMMENT 'YOS账单编号', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='能源账单'; + +-- 4. energy_bill_adjustment (账单调整) +DROP TABLE IF EXISTS `energy_bill_adjustment`; +CREATE TABLE `energy_bill_adjustment` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `bill_id` bigint DEFAULT NULL COMMENT '账单ID', + `detail_id` bigint DEFAULT NULL COMMENT '明细ID', + `adjustment_type` int DEFAULT NULL COMMENT '调整类型', + `amount` decimal(18,2) DEFAULT NULL COMMENT '调整金额', + `reason` varchar(500) DEFAULT NULL COMMENT '调整原因', + `attachment_urls` varchar(2000) DEFAULT NULL COMMENT '附件URLs', + `operator_id` bigint DEFAULT NULL COMMENT '操作人ID', + `operate_time` datetime DEFAULT NULL COMMENT '操作时间', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='账单调整'; + +-- 5. energy_station_config (站点配置) +DROP TABLE IF EXISTS `energy_station_config`; +CREATE TABLE `energy_station_config` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `station_id` bigint DEFAULT NULL COMMENT '站点ID', + `auto_deduct` bit(1) DEFAULT NULL COMMENT '是否自动扣费', + `cooperation_type` int DEFAULT NULL COMMENT '合作类型', + `auto_match` bit(1) DEFAULT NULL COMMENT '自动匹配开关', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='站点配置'; + +-- 6. energy_station_price (站点价格) +DROP TABLE IF EXISTS `energy_station_price`; +CREATE TABLE `energy_station_price` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `station_id` bigint DEFAULT NULL COMMENT '站点ID', + `customer_id` bigint DEFAULT NULL COMMENT '客户ID', + `cost_price` decimal(18,2) DEFAULT NULL COMMENT '成本价', + `customer_price` decimal(18,2) DEFAULT NULL COMMENT '客户价', + `effective_date` date DEFAULT NULL COMMENT '生效日期', + `expiry_date` date DEFAULT NULL COMMENT '失效日期', + `status` int DEFAULT NULL COMMENT '状态', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='站点价格'; + +-- 7. energy_account (能源账户) +DROP TABLE IF EXISTS `energy_account`; +CREATE TABLE `energy_account` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `customer_id` bigint DEFAULT NULL COMMENT '客户ID', + `balance` decimal(18,2) DEFAULT NULL COMMENT '余额', + `init_balance` decimal(18,2) DEFAULT NULL COMMENT '初始余额', + `accumulated_recharge` decimal(18,2) DEFAULT NULL COMMENT '累计充值金额', + `accumulated_hydrogen` decimal(18,2) DEFAULT NULL COMMENT '累计加氢金额', + `accumulated_electric` decimal(18,2) DEFAULT NULL COMMENT '累计充电金额', + `accumulated_consume` decimal(18,2) DEFAULT NULL COMMENT '累计消费金额', + `reminder_threshold` decimal(18,2) DEFAULT NULL COMMENT '余额预警阈值', + `account_status` int DEFAULT NULL COMMENT '账户状态', + `last_recharge_date` date DEFAULT NULL COMMENT '最后充值日期', + `version` int DEFAULT 0 COMMENT '乐观锁版本号', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='能源账户'; + +-- 8. energy_project_account (项目账户) +DROP TABLE IF EXISTS `energy_project_account`; +CREATE TABLE `energy_project_account` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `account_id` bigint DEFAULT NULL COMMENT '账户ID', + `contract_id` bigint DEFAULT NULL COMMENT '合同ID', + `project_name` varchar(255) DEFAULT NULL COMMENT '项目名称', + `project_balance` decimal(18,2) DEFAULT NULL COMMENT '项目余额', + `project_remit_amount` decimal(18,2) DEFAULT NULL COMMENT '项目汇款总额', + `project_hydrogen_amount` decimal(18,2) DEFAULT NULL COMMENT '项目加氢金额', + `project_electric_amount` decimal(18,2) DEFAULT NULL COMMENT '项目充电金额', + `project_consume_amount` decimal(18,2) DEFAULT NULL COMMENT '项目消费总额', + `reminder_threshold` decimal(18,2) DEFAULT NULL COMMENT '余额预警阈值', + `account_status` int DEFAULT NULL COMMENT '账户状态', + `version` int DEFAULT 0 COMMENT '乐观锁版本号', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目账户'; + +-- 9. energy_account_flow (账户流水) +DROP TABLE IF EXISTS `energy_account_flow`; +CREATE TABLE `energy_account_flow` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `tenant_id` bigint NOT NULL DEFAULT 1 COMMENT 租户编号, + `account_id` bigint DEFAULT NULL COMMENT '账户ID', + `project_account_id` bigint DEFAULT NULL COMMENT '项目账户ID', + `flow_type` int DEFAULT NULL COMMENT '流水类型', + `amount` decimal(18,2) DEFAULT NULL COMMENT '金额', + `balance_before` decimal(18,2) DEFAULT NULL COMMENT '变更前余额', + `balance_after` decimal(18,2) DEFAULT NULL COMMENT '变更后余额', + `project_balance_before` decimal(18,2) DEFAULT NULL COMMENT '变更前项目余额', + `project_balance_after` decimal(18,2) DEFAULT NULL COMMENT '变更后项目余额', + `biz_type` int DEFAULT NULL COMMENT '业务类型', + `biz_id` bigint DEFAULT NULL COMMENT '业务ID', + `biz_code` varchar(64) DEFAULT NULL COMMENT '业务编号', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `operator_id` bigint DEFAULT NULL COMMENT '操作人ID', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='账户流水'; diff --git a/sql/rebuild/mock_data.sql b/sql/rebuild/mock_data.sql new file mode 100644 index 0000000..a812439 --- /dev/null +++ b/sql/rebuild/mock_data.sql @@ -0,0 +1,197 @@ +-- ============================================================ +-- Mock Data for Asset & Energy Modules +-- Part 1: Asset data → oneos_asset +-- Part 2: Energy data → oneos_energy +-- Generated: 2026-03-16 +-- ============================================================ + +-- ===================== PART 1: ASSET ===================== + +-- ---------- 停车场 ---------- +INSERT INTO `asset_parking` (`id`, `name`, `capacity`, `manager_name`, `manager_phone`, `contact_name`, `contact_phone`, `parked_amount`, `province`, `city`, `address`, `longitude`, `latitude`, `lease_start_date`, `lease_end_date`, `rent_fee`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, '上海嘉定氢能停车场', 200, '张伟', '13800001001', '李敏', '13800001002', 45, '上海', '上海市', '嘉定区安亭镇曹安公路5555号', '121.1856', '31.3856', '2025-01-01', '2027-12-31', 50000.00, 'admin', NOW(), 'admin', NOW(), 0), +(2, '上海临港停车场', 150, '王强', '13800002001', '赵丽', '13800002002', 30, '上海', '上海市', '浦东新区临港大道888号', '121.9300', '30.8900', '2025-03-01', '2027-02-28', 40000.00, 'admin', NOW(), 'admin', NOW(), 0), +(3, '佛山南海停车场', 100, '陈刚', '13800003001', '周红', '13800003002', 20, '广东', '佛山市', '南海区桂城街道海五路28号', '113.1500', '23.0200', '2025-06-01', '2027-05-31', 30000.00, 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 车型参数 ---------- +INSERT INTO `asset_vehicle_model` (`id`, `brand`, `model`, `vehicle_type`, `model_label`, `fuel_type`, `plate_color`, `hydrogen_capacity`, `hydrogen_factory`, `hydrogen_unit`, `hydrogen_mileage`, `battery_type`, `battery_factory`, `reserve_electricity`, `electricity_mileage`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, '飞驰', 'FCEV-C1', '冷藏车', '18吨氢能冷藏车', '氢燃料', '黄色', 30, '国鸿氢能', 'kg', 350, '磷酸铁锂', '宁德时代', 100.00, 200, 'admin', NOW(), 'admin', NOW(), 0), +(2, '东风', 'EQ5180', '厢式货车', '18吨氢能厢式货车', '氢燃料', '黄色', 25, '亿华通', 'kg', 300, '磷酸铁锂', '比亚迪', 80.00, 150, 'admin', NOW(), 'admin', NOW(), 0), +(3, '福田', 'BJ5120', '冷藏车', '12吨氢能冷藏车', '氢燃料', '黄色', 20, '国鸿氢能', 'kg', 280, '三元锂', '国轩高科', 60.00, 120, 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 车型保养项目 ---------- +INSERT INTO `asset_vehicle_model_maintain_item` (`id`, `vehicle_model_id`, `maintain_item`, `kilometer_cycle`, `time_cycle`, `hour_fee`, `material_fee`, `total_fee`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1, '燃料电池系统检查', 10000, 3, 200.00, 500.00, 700.00, 'admin', NOW(), 'admin', NOW(), 0), +(2, 1, '储氢瓶检测', 20000, 6, 300.00, 0.00, 300.00, 'admin', NOW(), 'admin', NOW(), 0), +(3, 2, '燃料电池系统检查', 10000, 3, 200.00, 500.00, 700.00, 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 客户 ---------- +INSERT INTO `asset_customer` (`id`, `customer_code`, `coop_status`, `customer_name`, `province`, `city`, `address`, `region`, `contact`, `contact_mobile`, `email`, `credit_code_or_id`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 'CUS-2025-001', '合作中', '上海鲜生冷链物流有限公司', '上海', '上海市', '浦东新区张江路100号', '华东', '刘总', '13900001001', 'liu@xiansheng.com', '91310000MA1FY3XY23', '大客户', 'admin', NOW(), 'admin', NOW(), 0), +(2, 'CUS-2025-002', '合作中', '广州顺达运输有限公司', '广东', '广州市', '天河区天河路200号', '华南', '黄经理', '13900002001', 'huang@shunda.com', '91440100MA5CXKQR0L', NULL, 'admin', NOW(), 'admin', NOW(), 0), +(3, 'CUS-2025-003', '合作中', '深圳绿能科技有限公司', '广东', '深圳市', '南山区科技园南路50号', '华南', '郑总', '13900003001', 'zheng@lvneng.com', '91440300MA5FKP4Y28', '氢能源客户', 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 客户商务经理 ---------- +INSERT INTO `asset_customer_business_manager` (`id`, `customer_id`, `business_manager_name`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1, '张三', 'admin', NOW(), 'admin', NOW(), 0), +(2, 2, '李四', 'admin', NOW(), 'admin', NOW(), 0), +(3, 3, '王五', 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 供应商 ---------- +INSERT INTO `asset_supplier` (`id`, `supplier_code`, `coop_status`, `supplier_name`, `type`, `province`, `city`, `address`, `contact`, `contact_mobile`, `credit_code_or_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 'SUP-2025-001', '合作中', '飞驰科技有限公司', '车辆供应商', '广东', '佛山市', '南海区狮山镇科技路1号', '孙总', '13800010001', '91440600MA4W9F1M0K', 'admin', NOW(), 'admin', NOW(), 0), +(2, 'SUP-2025-002', '合作中', '国鸿氢能科技有限公司', '配件供应商', '广东', '云浮市', '云城区工业园8号', '钱经理', '13800010002', '91445300MA4WFPQY0T', 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 车辆基础信息 (8辆) ---------- +INSERT INTO `asset_vehicle_base` (`id`, `vin`, `plate_no`, `vehicle_no`, `vehicle_model_id`, `region_province`, `region_city`, `engine_no`, `register_date`, `purchase_date`, `purchase_price`, `color`, `year`, `mileage`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 'LFCEV001202500001', '沪A12345', 'VH-2025-001', 1, '上海', '上海市', 'ENG001', '2025-01-15', '2025-01-10', 680000.00, '白色', '2025', 12000, 'admin', NOW(), 'admin', NOW(), 0), +(2, 'LFCEV001202500002', '沪A12346', 'VH-2025-002', 1, '上海', '上海市', 'ENG002', '2025-01-20', '2025-01-15', 680000.00, '白色', '2025', 15000, 'admin', NOW(), 'admin', NOW(), 0), +(3, 'LFCEV001202500003', '沪A12347', 'VH-2025-003', 2, '上海', '上海市', 'ENG003', '2025-02-10', '2025-02-05', 550000.00, '蓝色', '2025', 8000, 'admin', NOW(), 'admin', NOW(), 0), +(4, 'LFCEV001202500004', '粤B88001', 'VH-2025-004', 2, '广东', '广州市', 'ENG004', '2025-03-01', '2025-02-25', 550000.00, '白色', '2025', 20000, 'admin', NOW(), 'admin', NOW(), 0), +(5, 'LFCEV001202500005', '粤B88002', 'VH-2025-005', 3, '广东', '广州市', 'ENG005', '2025-03-15', '2025-03-10', 450000.00, '蓝色', '2025', 5000, 'admin', NOW(), 'admin', NOW(), 0), +(6, 'LFCEV001202500006', '粤B88003', 'VH-2025-006', 1, '广东', '深圳市', 'ENG006', '2025-04-01', '2025-03-25', 680000.00, '白色', '2025', 3000, 'admin', NOW(), 'admin', NOW(), 0), +(7, 'LFCEV001202500007', '沪A12348', 'VH-2025-007', 3, '上海', '上海市', 'ENG007', '2025-04-15', '2025-04-10', 450000.00, '白色', '2025', 1000, 'admin', NOW(), 'admin', NOW(), 0), +(8, 'LFCEV001202500008', '沪A12349', 'VH-2025-008', 2, '上海', '上海市', 'ENG008', '2025-05-01', '2025-04-25', 550000.00, '蓝色', '2025', 500, 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 车辆位置信息 ---------- +INSERT INTO `asset_vehicle_location` (`id`, `vehicle_id`, `parking_id`, `parking_name`, `parking_space`, `location`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1, 1, '上海嘉定氢能停车场', 'A-001', '已交车-客户运营中', 'admin', NOW(), 'admin', NOW(), 0), +(2, 2, 1, '上海嘉定氢能停车场', 'A-002', '已交车-客户运营中', 'admin', NOW(), 'admin', NOW(), 0), +(3, 3, 1, '上海嘉定氢能停车场', 'B-001', '已交车-客户运营中', 'admin', NOW(), 'admin', NOW(), 0), +(4, 4, 3, '佛山南海停车场', 'C-001', '已交车-客户运营中', 'admin', NOW(), 'admin', NOW(), 0), +(5, 5, 3, '佛山南海停车场', 'C-002', '已交车-客户运营中', 'admin', NOW(), 'admin', NOW(), 0), +(6, 6, 2, '上海临港停车场', 'D-001', '待交车', 'admin', NOW(), 'admin', NOW(), 0), +(7, 7, 1, '上海嘉定氢能停车场', 'A-003', '库存待分配', 'admin', NOW(), 'admin', NOW(), 0), +(8, 8, 2, '上海临港停车场', 'D-002', '库存待分配', 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 车辆业务信息 ---------- +INSERT INTO `asset_vehicle_business` (`id`, `vehicle_id`, `customer_id`, `contract_id`, `ownership`, `delivery_date`, `monthly_rent`, `deposit`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1, 1, 1, '公司自有', '2025-02-01', 15000.00, 30000.00, 'admin', NOW(), 'admin', NOW(), 0), +(2, 2, 1, 1, '公司自有', '2025-02-01', 15000.00, 30000.00, 'admin', NOW(), 'admin', NOW(), 0), +(3, 3, 1, 1, '公司自有', '2025-03-01', 12000.00, 25000.00, 'admin', NOW(), 'admin', NOW(), 0), +(4, 4, 2, 2, '公司自有', '2025-04-01', 12000.00, 25000.00, 'admin', NOW(), 'admin', NOW(), 0), +(5, 5, 2, 2, '公司自有', '2025-04-15', 10000.00, 20000.00, 'admin', NOW(), 'admin', NOW(), 0), +(6, 6, 3, 3, '公司自有', NULL, NULL, NULL, 'admin', NOW(), 'admin', NOW(), 0), +(7, 7, NULL, NULL, '公司自有', NULL, NULL, NULL, 'admin', NOW(), 'admin', NOW(), 0), +(8, 8, NULL, NULL, '公司自有', NULL, NULL, NULL, 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 车辆状态信息 ---------- +INSERT INTO `asset_vehicle_status` (`id`, `vehicle_id`, `status`, `operate_status`, `storage_status`, `is_prepared`, `is_delivered`, `is_returned`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1, 1, 1, 2, 1, 1, 0, 'admin', NOW(), 'admin', NOW(), 0), +(2, 2, 1, 1, 2, 1, 1, 0, 'admin', NOW(), 'admin', NOW(), 0), +(3, 3, 1, 1, 2, 1, 1, 0, 'admin', NOW(), 'admin', NOW(), 0), +(4, 4, 1, 1, 2, 1, 1, 0, 'admin', NOW(), 'admin', NOW(), 0), +(5, 5, 1, 1, 2, 1, 1, 0, 'admin', NOW(), 'admin', NOW(), 0), +(6, 6, 1, 0, 1, 1, 0, 0, 'admin', NOW(), 'admin', NOW(), 0), +(7, 7, 0, 0, 1, 0, 0, 0, 'admin', NOW(), 'admin', NOW(), 0), +(8, 8, 0, 0, 1, 0, 0, 0, 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 合同 ---------- +INSERT INTO `asset_contract` (`id`, `contract_code`, `contract_type`, `project_name`, `start_date`, `end_date`, `payment_method`, `payment_cycle`, `signing_company`, `delivery_province`, `delivery_city`, `delivery_location`, `customer_id`, `customer_name`, `approval_status`, `contract_status`, `effective_time`, `hydrogen_bearer`, `hydrogen_payment_method`, `hydrogen_prepay`, `billing_method`, `main_vehicle_type`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 'HT-2025-001', 1, '上海鲜生冷链配送项目', '2025-02-01', '2027-01-31', '月付', '月', '辽宁新能源汽车有限公司', '上海', '上海市', '嘉定区安亭镇', 1, '上海鲜生冷链物流有限公司', 2, 1, '2025-02-01 00:00:00', '客户', '预充值', 100000.00, '按月计费', '冷藏车', 'admin', NOW(), 'admin', NOW(), 0), +(2, 'HT-2025-002', 1, '广州顺达城配项目', '2025-04-01', '2027-03-31', '月付', '月', '辽宁新能源汽车有限公司', '广东', '广州市', '天河区天河路', 2, '广州顺达运输有限公司', 2, 1, '2025-04-01 00:00:00', '公司', '月结算', NULL, '按月计费', '厢式货车', 'admin', NOW(), 'admin', NOW(), 0), +(3, 'HT-2025-003', 1, '深圳绿能示范项目', '2025-06-01', '2027-05-31', '月付', '月', '辽宁新能源汽车有限公司', '广东', '深圳市', '南山区科技园', 3, '深圳绿能科技有限公司', 1, 0, NULL, '客户', '预充值', 50000.00, '按月计费', '冷藏车', 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 合同车辆 ---------- +INSERT INTO `asset_contract_vehicle` (`id`, `contract_id`, `vehicle_id`, `brand`, `model`, `plate_no`, `vin`, `month_rent`, `deposit`, `vehicle_status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1, 1, '飞驰', 'FCEV-C1', '沪A12345', 'LFCEV001202500001', 15000.00, 30000.00, 1, 'admin', NOW(), 'admin', NOW(), 0), +(2, 1, 2, '飞驰', 'FCEV-C1', '沪A12346', 'LFCEV001202500002', 15000.00, 30000.00, 1, 'admin', NOW(), 'admin', NOW(), 0), +(3, 1, 3, '东风', 'EQ5180', '沪A12347', 'LFCEV001202500003', 12000.00, 25000.00, 1, 'admin', NOW(), 'admin', NOW(), 0), +(4, 2, 4, '东风', 'EQ5180', '粤B88001', 'LFCEV001202500004', 12000.00, 25000.00, 1, 'admin', NOW(), 'admin', NOW(), 0), +(5, 2, 5, '福田', 'BJ5120', '粤B88002', 'LFCEV001202500005', 10000.00, 20000.00, 1, 'admin', NOW(), 'admin', NOW(), 0), +(6, 3, 6, '飞驰', 'FCEV-C1', '粤B88003', 'LFCEV001202500006', 15000.00, 30000.00, 0, 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 合同授权人 ---------- +INSERT INTO `asset_contract_authorized` (`id`, `contract_id`, `name`, `phone`, `id_card`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1, '刘志强', '13900001001', '310101199001011234', 'admin', NOW(), 'admin', NOW(), 0), +(2, 1, '王小明', '13900001002', '310101199205051234', 'admin', NOW(), 'admin', NOW(), 0), +(3, 2, '黄大成', '13900002001', '440103199501011234', 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 验车模板 ---------- +INSERT INTO `asset_inspection_template` (`id`, `code`, `name`, `biz_type`, `vehicle_type`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 'TPL-DELIVERY-001', '交车验车模板-冷藏车', 1, '冷藏车', 1, 'admin', NOW(), 'admin', NOW(), 0), +(2, 'TPL-RETURN-001', '还车验车模板-通用', 2, NULL, 1, 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 验车模板项 ---------- +INSERT INTO `asset_inspection_template_item` (`id`, `template_id`, `category`, `item_name`, `item_code`, `input_type`, `sort`, `required`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1, '外观检查', '车身外观', 'BODY_APPEARANCE', 'radio', 1, 1, 'admin', NOW(), 'admin', NOW(), 0), +(2, 1, '外观检查', '车灯', 'LIGHTS', 'radio', 2, 1, 'admin', NOW(), 'admin', NOW(), 0), +(3, 1, '功能检查', '制动系统', 'BRAKE', 'radio', 3, 1, 'admin', NOW(), 'admin', NOW(), 0), +(4, 1, '功能检查', '氢系统', 'HYDROGEN_SYSTEM', 'radio', 4, 1, 'admin', NOW(), 'admin', NOW(), 0), +(5, 1, '功能检查', '冷机系统', 'REFRIGERATOR', 'radio', 5, 1, 'admin', NOW(), 'admin', NOW(), 0); + + +-- ===================== PART 2: ENERGY ===================== +-- NOTE: This section runs against oneos_energy database + +-- ---------- 站点配置 (加氢站) ---------- +INSERT INTO `energy_station_config` (`id`, `station_id`, `auto_deduct`, `cooperation_type`, `auto_match`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1001, 1, 1, 1, '上海嘉定加氢站', 'admin', NOW(), 'admin', NOW(), 0), +(2, 1002, 1, 1, 1, '上海临港加氢站', 'admin', NOW(), 'admin', NOW(), 0), +(3, 1003, 0, 2, 1, '佛山南海加氢站', 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 站点价格 ---------- +INSERT INTO `energy_station_price` (`id`, `station_id`, `customer_id`, `cost_price`, `customer_price`, `effective_date`, `expiry_date`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1001, 1, 25.00, 35.00, '2025-01-01', '2027-12-31', 1, 'admin', NOW(), 'admin', NOW(), 0), +(2, 1001, 2, 25.00, 38.00, '2025-01-01', '2027-12-31', 1, 'admin', NOW(), 'admin', NOW(), 0), +(3, 1002, 1, 28.00, 38.00, '2025-01-01', '2027-12-31', 1, 'admin', NOW(), 'admin', NOW(), 0), +(4, 1003, 2, 26.00, 36.00, '2025-04-01', '2027-03-31', 1, 'admin', NOW(), 'admin', NOW(), 0), +(5, 1003, 3, 26.00, 35.00, '2025-06-01', '2027-05-31', 1, 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 能源账户 ---------- +INSERT INTO `energy_account` (`id`, `customer_id`, `balance`, `init_balance`, `accumulated_recharge`, `accumulated_hydrogen`, `accumulated_electric`, `accumulated_consume`, `reminder_threshold`, `account_status`, `last_recharge_date`, `version`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1, 52350.00, 0.00, 200000.00, 147650.00, 0.00, 147650.00, 10000.00, 1, '2026-02-15', 0, 'admin', NOW(), 'admin', NOW(), 0), +(2, 2, 0.00, 0.00, 0.00, 85600.00, 0.00, 85600.00, 5000.00, 1, NULL, 0, 'admin', NOW(), 'admin', NOW(), 0), +(3, 3, 35000.00, 0.00, 50000.00, 15000.00, 0.00, 15000.00, 5000.00, 1, '2026-01-10', 0, 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 项目账户 ---------- +INSERT INTO `energy_project_account` (`id`, `account_id`, `contract_id`, `project_name`, `project_balance`, `project_remit_amount`, `project_hydrogen_amount`, `project_electric_amount`, `project_consume_amount`, `reminder_threshold`, `account_status`, `version`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1, 1, '上海鲜生冷链配送项目', 52350.00, 200000.00, 147650.00, 0.00, 147650.00, 10000.00, 1, 0, 'admin', NOW(), 'admin', NOW(), 0), +(2, 2, 2, '广州顺达城配项目', 0.00, 0.00, 85600.00, 0.00, 85600.00, 5000.00, 1, 0, 'admin', NOW(), 'admin', NOW(), 0), +(3, 3, 3, '深圳绿能示范项目', 35000.00, 50000.00, 15000.00, 0.00, 15000.00, 5000.00, 1, 0, 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 加氢记录 ---------- +INSERT INTO `energy_hydrogen_record` (`id`, `station_id`, `plate_number`, `hydrogen_date`, `hydrogen_quantity`, `unit_price`, `amount`, `mileage`, `source_type`, `match_status`, `vehicle_id`, `customer_id`, `upload_batch_no`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1001, '沪A12345', '2026-03-01', 8.50, 35.00, 297.50, 12500, 1, 1, 1, 1, 'BATCH-20260301-001', 'admin', NOW(), 'admin', NOW(), 0), +(2, 1001, '沪A12346', '2026-03-01', 10.20, 35.00, 357.00, 15800, 1, 1, 2, 1, 'BATCH-20260301-001', 'admin', NOW(), 'admin', NOW(), 0), +(3, 1001, '沪A12347', '2026-03-02', 7.80, 35.00, 273.00, 8500, 1, 1, 3, 1, 'BATCH-20260302-001', 'admin', NOW(), 'admin', NOW(), 0), +(4, 1003, '粤B88001', '2026-03-02', 9.00, 36.00, 324.00, 20800, 1, 1, 4, 2, 'BATCH-20260302-002', 'admin', NOW(), 'admin', NOW(), 0), +(5, 1003, '粤B88002', '2026-03-03', 6.50, 36.00, 234.00, 5500, 1, 1, 5, 2, 'BATCH-20260303-001', 'admin', NOW(), 'admin', NOW(), 0), +(6, 1001, '沪A12345', '2026-03-05', 9.20, 35.00, 322.00, 12900, 1, 1, 1, 1, 'BATCH-20260305-001', 'admin', NOW(), 'admin', NOW(), 0), +(7, 1001, '沪A12346', '2026-03-06', 11.00, 35.00, 385.00, 16300, 1, 1, 2, 1, 'BATCH-20260306-001', 'admin', NOW(), 'admin', NOW(), 0), +(8, 1002, '沪A12345', '2026-03-08', 8.00, 38.00, 304.00, 13400, 1, 1, 1, 1, 'BATCH-20260308-001', 'admin', NOW(), 'admin', NOW(), 0), +(9, 1003, '粤B88001', '2026-03-08', 10.50, 36.00, 378.00, 21500, 1, 1, 4, 2, 'BATCH-20260308-002', 'admin', NOW(), 'admin', NOW(), 0), +(10, 1001, '沪A12347', '2026-03-10', 8.30, 35.00, 290.50, 9200, 1, 1, 3, 1, 'BATCH-20260310-001', 'admin', NOW(), 'admin', NOW(), 0), +-- 未匹配记录 +(11, 1001, '沪C99999', '2026-03-10', 5.00, 35.00, 175.00, NULL, 1, 0, NULL, NULL, 'BATCH-20260310-001', 'admin', NOW(), 'admin', NOW(), 0), +(12, 1002, '粤Z11111', '2026-03-11', 7.00, 38.00, 266.00, NULL, 2, 0, NULL, NULL, 'BATCH-20260311-001', 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 加氢明细 ---------- +INSERT INTO `energy_hydrogen_detail` (`id`, `record_id`, `station_id`, `vehicle_id`, `plate_number`, `hydrogen_date`, `hydrogen_quantity`, `cost_price`, `cost_amount`, `customer_price`, `customer_amount`, `contract_id`, `customer_id`, `project_name`, `cost_bearer`, `pay_method`, `audit_status`, `deduction_status`, `settlement_status`, `bill_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1, 1001, 1, '沪A12345', '2026-03-01', 8.50, 25.00, 212.50, 35.00, 297.50, 1, 1, '上海鲜生冷链配送项目', 1, 1, 1, 1, 1, 1, 'admin', NOW(), 'admin', NOW(), 0), +(2, 2, 1001, 2, '沪A12346', '2026-03-01', 10.20, 25.00, 255.00, 35.00, 357.00, 1, 1, '上海鲜生冷链配送项目', 1, 1, 1, 1, 1, 1, 'admin', NOW(), 'admin', NOW(), 0), +(3, 3, 1001, 3, '沪A12347', '2026-03-02', 7.80, 25.00, 195.00, 35.00, 273.00, 1, 1, '上海鲜生冷链配送项目', 1, 1, 1, 1, 1, 1, 'admin', NOW(), 'admin', NOW(), 0), +(4, 4, 1003, 4, '粤B88001', '2026-03-02', 9.00, 26.00, 234.00, 36.00, 324.00, 2, 2, '广州顺达城配项目', 2, 2, 1, 0, 0, NULL, 'admin', NOW(), 'admin', NOW(), 0), +(5, 5, 1003, 5, '粤B88002', '2026-03-03', 6.50, 26.00, 169.00, 36.00, 234.00, 2, 2, '广州顺达城配项目', 2, 2, 1, 0, 0, NULL, 'admin', NOW(), 'admin', NOW(), 0), +(6, 6, 1001, 1, '沪A12345', '2026-03-05', 9.20, 25.00, 230.00, 35.00, 322.00, 1, 1, '上海鲜生冷链配送项目', 1, 1, 1, 1, 1, 1, 'admin', NOW(), 'admin', NOW(), 0), +(7, 7, 1001, 2, '沪A12346', '2026-03-06', 11.00, 25.00, 275.00, 35.00, 385.00, 1, 1, '上海鲜生冷链配送项目', 1, 1, 1, 1, 1, 1, 'admin', NOW(), 'admin', NOW(), 0), +(8, 8, 1002, 1, '沪A12345', '2026-03-08', 8.00, 28.00, 224.00, 38.00, 304.00, 1, 1, '上海鲜生冷链配送项目', 1, 1, 0, 0, 0, NULL, 'admin', NOW(), 'admin', NOW(), 0), +(9, 9, 1003, 4, '粤B88001', '2026-03-08', 10.50, 26.00, 273.00, 36.00, 378.00, 2, 2, '广州顺达城配项目', 2, 2, 0, 0, 0, NULL, 'admin', NOW(), 'admin', NOW(), 0), +(10, 10, 1001, 3, '沪A12347', '2026-03-10', 8.30, 25.00, 207.50, 35.00, 290.50, 1, 1, '上海鲜生冷链配送项目', 1, 1, 0, 0, 0, NULL, 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 能源账单 ---------- +INSERT INTO `energy_bill` (`id`, `bill_code`, `energy_type`, `customer_id`, `customer_name`, `contract_id`, `station_id`, `station_name`, `cooperation_type`, `bill_period_start`, `bill_period_end`, `receivable_amount`, `actual_amount`, `adjustment_amount`, `paid_amount`, `total_quantity`, `detail_count`, `status`, `audit_status`, `submit_status`, `payment_status`, `generate_time`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 'BILL-2026-03-001', 1, 1, '上海鲜生冷链物流有限公司', 1, 1001, '上海嘉定加氢站', 1, '2026-03-01', '2026-03-15', 1634.50, 1634.50, 0.00, 1634.50, 46.70, 5, 3, 1, 1, 1, '2026-03-16 00:00:00', 'admin', NOW(), 'admin', NOW(), 0), +(2, 'BILL-2026-03-002', 1, 2, '广州顺达运输有限公司', 2, 1003, '佛山南海加氢站', 2, '2026-03-01', '2026-03-15', 936.00, NULL, 0.00, 0.00, 26.00, 3, 1, 0, 0, 0, '2026-03-16 00:00:00', 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 账单调整 ---------- +INSERT INTO `energy_bill_adjustment` (`id`, `bill_id`, `detail_id`, `adjustment_type`, `amount`, `reason`, `operator_id`, `operate_time`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1, 1, 1, -10.00, '加氢站计量偏差修正', 1, '2026-03-15 10:00:00', 'admin', NOW(), 'admin', NOW(), 0); + +-- ---------- 账户流水 ---------- +INSERT INTO `energy_account_flow` (`id`, `account_id`, `project_account_id`, `flow_type`, `amount`, `balance_before`, `balance_after`, `project_balance_before`, `project_balance_after`, `biz_type`, `biz_id`, `biz_code`, `remark`, `operator_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES +(1, 1, 1, 1, 100000.00, 0.00, 100000.00, 0.00, 100000.00, 1, NULL, NULL, '首次充值', 1, 'admin', '2025-02-01 10:00:00', 'admin', '2025-02-01 10:00:00', 0), +(2, 1, 1, 1, 100000.00, 100000.00, 200000.00, 100000.00, 200000.00, 1, NULL, NULL, '二次充值', 1, 'admin', '2026-02-15 10:00:00', 'admin', '2026-02-15 10:00:00', 0), +(3, 1, 1, 2, -297.50, 200000.00, 199702.50, 200000.00, 199702.50, 2, 1, 'BILL-2026-03-001', '加氢扣费-沪A12345', NULL, 'admin', '2026-03-01 18:00:00', 'admin', '2026-03-01 18:00:00', 0), +(4, 1, 1, 2, -357.00, 199702.50, 199345.50, 199702.50, 199345.50, 2, 1, 'BILL-2026-03-001', '加氢扣费-沪A12346', NULL, 'admin', '2026-03-01 18:05:00', 'admin', '2026-03-01 18:05:00', 0), +(5, 3, 3, 1, 50000.00, 0.00, 50000.00, 0.00, 50000.00, 1, NULL, NULL, '首次充值', 1, 'admin', '2026-01-10 10:00:00', 'admin', '2026-01-10 10:00:00', 0); diff --git a/sql/rebuild/rebuild_all.py b/sql/rebuild/rebuild_all.py new file mode 100644 index 0000000..143e41c --- /dev/null +++ b/sql/rebuild/rebuild_all.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python3 +""" +重建 Asset 和 Energy 模块数据表并插入 Mock 数据 +- Asset 表 → oneos_asset 数据库 +- Energy 表 → oneos_energy 数据库 +- 使用 pymysql 连接远程 MySQL(规避本地 mysql 客户端 auth plugin 问题) +""" + +import os +import sys +import re + +try: + import pymysql +except ImportError: + print("pymysql 未安装,正在安装...") + os.system(f"{sys.executable} -m pip install pymysql") + import pymysql + +# 数据库连接配置 +DB_CONFIG = { + "host": "47.103.115.36", + "port": 3306, + "user": "root", + "password": "Passw0rd2026", + "charset": "utf8mb4", +} + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + + +def read_sql_file(filename): + """读取 SQL 文件内容""" + filepath = os.path.join(SCRIPT_DIR, filename) + with open(filepath, "r", encoding="utf-8") as f: + return f.read() + + +def split_statements(sql_text): + """ + 将 SQL 文本拆分为独立语句。 + 处理 CREATE VIEW 等多行语句,跳过注释和空行。 + """ + statements = [] + current = [] + for line in sql_text.split("\n"): + stripped = line.strip() + # 跳过纯注释行和空行(但保留语句中间的注释) + if not stripped or stripped.startswith("--"): + if current: + # 如果当前语句已经开始,保留注释行(可能是语句内的注释) + pass + continue + current.append(line) + if stripped.endswith(";"): + stmt = "\n".join(current).strip() + if stmt: + statements.append(stmt) + current = [] + # 处理没有分号结尾的最后一条语句 + if current: + stmt = "\n".join(current).strip() + if stmt: + statements.append(stmt) + return statements + + +def execute_sql(cursor, sql_text, label=""): + """执行一段 SQL(可包含多条语句)""" + statements = split_statements(sql_text) + success = 0 + errors = 0 + for i, stmt in enumerate(statements, 1): + # 提取语句摘要用于日志 + first_line = stmt.split("\n")[0][:80] + try: + cursor.execute(stmt) + success += 1 + except pymysql.err.OperationalError as e: + code = e.args[0] + # 1051: Unknown table (DROP 不存在的表) - 忽略 + if code == 1051: + success += 1 + else: + errors += 1 + print(f" ❌ [{label}] 语句 {i} 失败: {e}") + print(f" SQL: {first_line}...") + except Exception as e: + errors += 1 + print(f" ❌ [{label}] 语句 {i} 失败: {e}") + print(f" SQL: {first_line}...") + return success, errors + + +def main(): + print("=" * 60) + print("ONE-OS 数据表重建工具") + print("=" * 60) + + # 读取 SQL 文件 + print("\n📄 读取 SQL 文件...") + asset_ddl = read_sql_file("asset_ddl.sql") + energy_ddl = read_sql_file("energy_ddl.sql") + mock_data = read_sql_file("mock_data.sql") + + # 拆分 mock_data 为 asset 和 energy 部分 + parts = mock_data.split("-- ===================== PART 2: ENERGY =====================") + if len(parts) != 2: + print("❌ mock_data.sql 格式错误:找不到 PART 2 分隔符") + sys.exit(1) + asset_mock = parts[0] + energy_mock = parts[1] + + # 从 asset_mock 中去掉文件头注释和 PART 1 标记 + # 保留实际的 INSERT 语句 + + total_success = 0 + total_errors = 0 + + # ========== 1. 处理 Asset 数据库 ========== + print("\n" + "=" * 60) + print("🔧 [1/3] 重建 oneos_asset 数据库表...") + print("=" * 60) + + conn_asset = pymysql.connect(**DB_CONFIG, database="oneos_asset") + conn_asset.autocommit(True) + cursor_asset = conn_asset.cursor() + + # 创建 Asset 表 + print("\n📋 执行 Asset DDL(29张表 + 1个视图)...") + s, e = execute_sql(cursor_asset, asset_ddl, "Asset DDL") + total_success += s + total_errors += e + print(f" ✅ Asset DDL: {s} 成功, {e} 失败") + + # 插入 Asset Mock 数据 + print("\n📋 插入 Asset Mock 数据...") + s, e = execute_sql(cursor_asset, asset_mock, "Asset Mock") + total_success += s + total_errors += e + print(f" ✅ Asset Mock: {s} 成功, {e} 失败") + + cursor_asset.close() + conn_asset.close() + + # ========== 2. 处理 Energy 数据库 ========== + print("\n" + "=" * 60) + print("🔧 [2/3] 重建 oneos_energy 数据库表...") + print("=" * 60) + + # 先确保 oneos_energy 数据库存在 + conn_init = pymysql.connect(**DB_CONFIG) + conn_init.autocommit(True) + cursor_init = conn_init.cursor() + cursor_init.execute("CREATE DATABASE IF NOT EXISTS `oneos_energy` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci") + cursor_init.close() + conn_init.close() + + conn_energy = pymysql.connect(**DB_CONFIG, database="oneos_energy") + conn_energy.autocommit(True) + cursor_energy = conn_energy.cursor() + + # 创建 Energy 表 + print("\n📋 执行 Energy DDL(9张表)...") + s, e = execute_sql(cursor_energy, energy_ddl, "Energy DDL") + total_success += s + total_errors += e + print(f" ✅ Energy DDL: {s} 成功, {e} 失败") + + # 插入 Energy Mock 数据 + print("\n📋 插入 Energy Mock 数据...") + s, e = execute_sql(cursor_energy, energy_mock, "Energy Mock") + total_success += s + total_errors += e + print(f" ✅ Energy Mock: {s} 成功, {e} 失败") + + cursor_energy.close() + conn_energy.close() + + # ========== 3. 验证 ========== + print("\n" + "=" * 60) + print("🔍 [3/3] 验证表结构和数据...") + print("=" * 60) + + # 验证 Asset + conn_v = pymysql.connect(**DB_CONFIG, database="oneos_asset") + cursor_v = conn_v.cursor() + cursor_v.execute("SELECT TABLE_NAME, TABLE_ROWS FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'oneos_asset' AND TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME") + asset_tables = cursor_v.fetchall() + print(f"\n📊 oneos_asset 数据库: {len(asset_tables)} 张表") + for table_name, row_count in asset_tables: + cursor_v.execute(f"SELECT COUNT(*) FROM `{table_name}`") + actual_count = cursor_v.fetchone()[0] + print(f" {table_name}: {actual_count} 行") + cursor_v.close() + conn_v.close() + + # 验证 Energy + conn_v2 = pymysql.connect(**DB_CONFIG, database="oneos_energy") + cursor_v2 = conn_v2.cursor() + cursor_v2.execute("SELECT TABLE_NAME, TABLE_ROWS FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'oneos_energy' AND TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME") + energy_tables = cursor_v2.fetchall() + print(f"\n📊 oneos_energy 数据库: {len(energy_tables)} 张表") + for table_name, row_count in energy_tables: + cursor_v2.execute(f"SELECT COUNT(*) FROM `{table_name}`") + actual_count = cursor_v2.fetchone()[0] + print(f" {table_name}: {actual_count} 行") + cursor_v2.close() + conn_v2.close() + + # ========== 总结 ========== + print("\n" + "=" * 60) + print(f"🎉 完成! 总计: {total_success} 成功, {total_errors} 失败") + print("=" * 60) + + if total_errors > 0: + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/sql/update-2026-03-13-contract-new-fields.sql b/sql/update-2026-03-13-contract-new-fields.sql new file mode 100644 index 0000000..701c923 --- /dev/null +++ b/sql/update-2026-03-13-contract-new-fields.sql @@ -0,0 +1,8 @@ +-- 合同表新增6个字段 +ALTER TABLE asset_contract + ADD COLUMN hydrogen_bearer VARCHAR(20) COMMENT '氢费承担方', + ADD COLUMN hydrogen_payment_method VARCHAR(20) COMMENT '氢气付款方式', + ADD COLUMN hydrogen_prepay DECIMAL(12,2) COMMENT '氢气预付款', + ADD COLUMN hydrogen_return_price DECIMAL(12,2) COMMENT '退还车氢气单价', + ADD COLUMN billing_method VARCHAR(50) COMMENT '账单计算方式', + ADD COLUMN main_vehicle_type VARCHAR(50) COMMENT '主车型'; diff --git a/yudao-module-asset/sql/mysql/contract-menu-dict.sql b/yudao-module-asset/sql/mysql/contract-menu-dict.sql new file mode 100644 index 0000000..6d9b205 --- /dev/null +++ b/yudao-module-asset/sql/mysql/contract-menu-dict.sql @@ -0,0 +1,67 @@ +-- 合同管理菜单和权限初始化脚本 + +-- 1. 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '合同管理', '', 2, 5, 5055, + 'contract', 'documentation', 'asset/contract/index', 0, 'Contract' +); + +-- 获取刚插入的菜单ID +SET @menuId = LAST_INSERT_ID(); + +-- 合同管理按钮权限 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES + ('合同查询', 'asset:contract:query', 3, 1, @menuId, '', '', '', 0), + ('合同创建', 'asset:contract:create', 3, 2, @menuId, '', '', '', 0), + ('合同更新', 'asset:contract:update', 3, 3, @menuId, '', '', '', 0), + ('合同删除', 'asset:contract:delete', 3, 4, @menuId, '', '', '', 0), + ('合同导出', 'asset:contract:export', 3, 5, @menuId, '', '', '', 0), + ('提交审批', 'asset:contract:submit-approval', 3, 6, @menuId, '', '', '', 0), + ('撤回审批', 'asset:contract:withdraw-approval', 3, 7, @menuId, '', '', '', 0), + ('终止合同', 'asset:contract:terminate', 3, 8, @menuId, '', '', '', 0), + ('续签合同', 'asset:contract:renew', 3, 9, @menuId, '', '', '', 0); + +-- 2. 字典类型 +INSERT INTO system_dict_type (name, type, status, remark, creator, create_time, updater, update_time, deleted) +VALUES + ('合同类型', 'asset_contract_type', 0, '车辆租赁合同类型', 'admin', NOW(), 'admin', NOW(), b'0'), + ('合同审批状态', 'asset_contract_approval_status', 0, '合同审批状态', 'admin', NOW(), 'admin', NOW(), b'0'), + ('合同状态', 'asset_contract_status', 0, '合同业务状态', 'admin', NOW(), 'admin', NOW(), b'0'), + ('车辆订单状态', 'asset_contract_vehicle_status', 0, '合同车辆订单状态', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 3. 字典数据 - 合同类型 +INSERT INTO system_dict_data (dict_type, label, value, sort, status, remark, creator, create_time, updater, update_time, deleted) +VALUES + ('asset_contract_type', '试用合同', '1', 1, 0, '试用期合同', 'admin', NOW(), 'admin', NOW(), b'0'), + ('asset_contract_type', '正式合同', '2', 2, 0, '正式租赁合同', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 4. 字典数据 - 合同审批状态 +INSERT INTO system_dict_data (dict_type, label, value, sort, status, color_type, remark, creator, create_time, updater, update_time, deleted) +VALUES + ('asset_contract_approval_status', '草稿', '0', 1, 0, 'info', '草稿状态', 'admin', NOW(), 'admin', NOW(), b'0'), + ('asset_contract_approval_status', '审批中', '1', 2, 0, 'warning', '审批中', 'admin', NOW(), 'admin', NOW(), b'0'), + ('asset_contract_approval_status', '审批通过', '2', 3, 0, 'success', '审批通过', 'admin', NOW(), 'admin', NOW(), b'0'), + ('asset_contract_approval_status', '审批拒绝', '3', 4, 0, 'danger', '审批拒绝', 'admin', NOW(), 'admin', NOW(), b'0'), + ('asset_contract_approval_status', '已撤回', '4', 5, 0, 'info', '已撤回', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 5. 字典数据 - 合同状态 +INSERT INTO system_dict_data (dict_type, label, value, sort, status, color_type, remark, creator, create_time, updater, update_time, deleted) +VALUES + ('asset_contract_status', '草稿', '0', 1, 0, 'info', '草稿状态', 'admin', NOW(), 'admin', NOW(), b'0'), + ('asset_contract_status', '待生效', '1', 2, 0, 'warning', '待生效', 'admin', NOW(), 'admin', NOW(), b'0'), + ('asset_contract_status', '进行中', '2', 3, 0, 'success', '进行中', 'admin', NOW(), 'admin', NOW(), b'0'), + ('asset_contract_status', '已到期', '3', 4, 0, 'info', '已到期', 'admin', NOW(), 'admin', NOW(), b'0'), + ('asset_contract_status', '已终止', '4', 5, 0, 'danger', '已终止', 'admin', NOW(), 'admin', NOW(), b'0'), + ('asset_contract_status', '已续签', '5', 6, 0, 'primary', '已续签', 'admin', NOW(), 'admin', NOW(), b'0'); + +-- 6. 字典数据 - 车辆订单状态 +INSERT INTO system_dict_data (dict_type, label, value, sort, status, color_type, remark, creator, create_time, updater, update_time, deleted) +VALUES + ('asset_contract_vehicle_status', '待交车', '0', 1, 0, 'warning', '待交车', 'admin', NOW(), 'admin', NOW(), b'0'), + ('asset_contract_vehicle_status', '已交车', '1', 2, 0, 'success', '已交车', 'admin', NOW(), 'admin', NOW(), b'0'), + ('asset_contract_vehicle_status', '已退车', '2', 3, 0, 'info', '已退车', 'admin', NOW(), 'admin', NOW(), b'0'); diff --git a/yudao-module-asset/sql/mysql/contract-tables-supplement.sql b/yudao-module-asset/sql/mysql/contract-tables-supplement.sql new file mode 100644 index 0000000..c7cc128 --- /dev/null +++ b/yudao-module-asset/sql/mysql/contract-tables-supplement.sql @@ -0,0 +1,74 @@ +-- 合同管理补充表(合同被授权人、变更历史、附件、车辆服务项目) + +-- 3. 合同被授权人表 +CREATE TABLE IF NOT EXISTS `asset_contract_authorized` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `contract_id` BIGINT NOT NULL COMMENT '合同ID', + `name` VARCHAR(100) NOT NULL COMMENT '姓名', + `phone` VARCHAR(20) COMMENT '电话', + `id_card` VARCHAR(30) COMMENT '身份证号', + `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_contract_id` (`contract_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同被授权人表'; + +-- 4. 合同变更历史表 +CREATE TABLE IF NOT EXISTS `asset_contract_change_history` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `contract_id` BIGINT NOT NULL COMMENT '合同ID', + `change_type` VARCHAR(50) NOT NULL COMMENT '变更类型', + `change_content` TEXT COMMENT '变更内容', + `operator` VARCHAR(64) COMMENT '操作人', + `operate_time` DATETIME COMMENT '操作时间', + `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_contract_id` (`contract_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同变更历史表'; + +-- 5. 合同附件表 +CREATE TABLE IF NOT EXISTS `asset_contract_attachment` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `contract_id` BIGINT NOT NULL COMMENT '合同ID', + `attachment_type` INT COMMENT '附件类型(1=合同原件 2=盖章合同)', + `file_id` BIGINT COMMENT '文件ID', + `file_name` VARCHAR(255) COMMENT '文件名称', + `file_url` VARCHAR(500) COMMENT '文件URL', + `file_size` BIGINT COMMENT '文件大小(字节)', + `upload_time` DATETIME COMMENT '上传时间', + `uploader` VARCHAR(64) COMMENT '上传人', + `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_contract_id` (`contract_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同附件表'; + +-- 6. 合同车辆服务项目表 +CREATE TABLE IF NOT EXISTS `asset_contract_vehicle_service` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `contract_vehicle_id` BIGINT NOT NULL COMMENT '合同车辆ID', + `service_name` VARCHAR(200) NOT NULL COMMENT '服务项目名称', + `service_fee` DECIMAL(10,2) COMMENT '服务费用(元)', + `effective_date` DATE COMMENT '生效日期', + `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_contract_vehicle_id` (`contract_vehicle_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同车辆服务项目表'; diff --git a/yudao-module-asset/sql/mysql/contract-tables.sql b/yudao-module-asset/sql/mysql/contract-tables.sql new file mode 100644 index 0000000..f714a67 --- /dev/null +++ b/yudao-module-asset/sql/mysql/contract-tables.sql @@ -0,0 +1,73 @@ +-- 合同管理表结构 + +-- 1. 车辆租赁合同表 +CREATE TABLE IF NOT EXISTS `asset_contract` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `contract_code` VARCHAR(50) NOT NULL COMMENT '合同编码', + `contract_type` TINYINT NOT NULL COMMENT '合同类型(1=试用 2=正式)', + `project_name` VARCHAR(200) NOT NULL COMMENT '项目名称', + `start_date` DATE NOT NULL COMMENT '生效日期', + `end_date` DATE NOT NULL COMMENT '结束日期', + `payment_method` VARCHAR(100) NOT NULL COMMENT '付款方式', + `payment_cycle` VARCHAR(100) NOT NULL COMMENT '付款周期', + `signing_company` VARCHAR(200) NOT NULL COMMENT '签约公司(乙方)', + `delivery_province` VARCHAR(50) NOT NULL COMMENT '交车省份', + `delivery_city` VARCHAR(50) NOT NULL COMMENT '交车城市', + `delivery_location` VARCHAR(255) NOT NULL COMMENT '交车地点', + `remark` VARCHAR(500) COMMENT '备注', + `customer_id` BIGINT NOT NULL COMMENT '客户ID', + `customer_name` VARCHAR(100) COMMENT '客户名称(冗余)', + `third_party_enabled` BIT(1) DEFAULT b'0' COMMENT '是否三方合同', + `third_party_customer_id` BIGINT COMMENT '丙方客户ID', + `third_party_name` VARCHAR(100) COMMENT '丙方名称', + `business_dept_id` BIGINT COMMENT '业务部门ID', + `business_manager_id` BIGINT COMMENT '业务负责人ID', + `approval_status` TINYINT NOT NULL DEFAULT 0 COMMENT '审批状态(0=草稿 1=审批中 2=审批通过 3=审批拒绝 4=已撤回)', + `bpm_instance_id` VARCHAR(64) COMMENT 'BPM流程实例ID', + `contract_status` TINYINT NOT NULL DEFAULT 0 COMMENT '合同状态(0=草稿 1=待生效 2=进行中 3=已到期 4=已终止 5=已续签)', + `effective_time` DATETIME COMMENT '实际生效时间', + `terminate_time` DATETIME COMMENT '终止时间', + `terminate_reason` VARCHAR(500) COMMENT '终止原因', + `renewed_contract_id` BIGINT COMMENT '续签后的新合同ID', + `original_contract_id` BIGINT COMMENT '原合同ID(如果是续签合同)', + `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_contract_code` (`contract_code`, `deleted`), + KEY `idx_customer_id` (`customer_id`), + KEY `idx_approval_status` (`approval_status`), + KEY `idx_contract_status` (`contract_status`), + KEY `idx_create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车辆租赁合同表'; + +-- 2. 合同车辆租赁订单表 +CREATE TABLE IF NOT EXISTS `asset_contract_vehicle` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `contract_id` BIGINT NOT NULL COMMENT '合同ID', + `vehicle_id` BIGINT COMMENT '车辆ID(关联 asset_vehicle_base)', + `brand` VARCHAR(50) NOT NULL COMMENT '品牌', + `model` VARCHAR(100) NOT NULL COMMENT '型号', + `plate_no` VARCHAR(20) COMMENT '车牌号', + `vin` VARCHAR(50) COMMENT 'VIN码', + `month_rent` DECIMAL(10,2) NOT NULL COMMENT '月租金(元)', + `deposit` DECIMAL(10,2) NOT NULL COMMENT '保证金(元)', + `vehicle_status` TINYINT NOT NULL DEFAULT 0 COMMENT '车辆状态(0=待交车 1=已交车 2=已退车)', + `actual_delivery_time` DATETIME COMMENT '实际交车时间', + `delivery_person` VARCHAR(50) COMMENT '交车人', + `remark` VARCHAR(500) COMMENT '备注', + `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_contract_id` (`contract_id`), + KEY `idx_vehicle_id` (`vehicle_id`), + KEY `idx_plate_no` (`plate_no`), + KEY `idx_vin` (`vin`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同车辆租赁订单表'; diff --git a/yudao-module-asset/sql/mysql/contract.sql b/yudao-module-asset/sql/mysql/contract.sql new file mode 100644 index 0000000..f54443e --- /dev/null +++ b/yudao-module-asset/sql/mysql/contract.sql @@ -0,0 +1,27 @@ +-- 合同管理菜单和权限初始化脚本 + +-- 1. 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '合同管理', '', 2, 6, 5055, + 'contract', 'file-text', 'asset/contract/index', 0, 'Contract' +); + +-- 获取刚插入的菜单ID +SET @menuId = LAST_INSERT_ID(); + +-- 合同管理按钮权限 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES + ('合同查询', 'asset:contract:query', 3, 1, @menuId, '', '', '', 0), + ('合同创建', 'asset:contract:create', 3, 2, @menuId, '', '', '', 0), + ('合同更新', 'asset:contract:update', 3, 3, @menuId, '', '', '', 0), + ('合同删除', 'asset:contract:delete', 3, 4, @menuId, '', '', '', 0), + ('合同导出', 'asset:contract:export', 3, 5, @menuId, '', '', '', 0), + ('提交审批', 'asset:contract:submit-approval', 3, 6, @menuId, '', '', '', 0), + ('撤回审批', 'asset:contract:withdraw-approval', 3, 7, @menuId, '', '', '', 0), + ('终止合同', 'asset:contract:terminate', 3, 8, @menuId, '', '', '', 0), + ('续签合同', 'asset:contract:renew', 3, 9, @menuId, '', '', '', 0); diff --git a/yudao-module-asset/sql/mysql/customer.sql b/yudao-module-asset/sql/mysql/customer.sql new file mode 100644 index 0000000..1149593 --- /dev/null +++ b/yudao-module-asset/sql/mysql/customer.sql @@ -0,0 +1,23 @@ +-- 客户管理菜单和权限初始化脚本 + +-- 1. 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '客户管理', '', 2, 2, 5055, + 'customer', 'user', 'asset/customer/index', 0, 'Customer' +); + +-- 获取刚插入的菜单ID +SET @menuId = LAST_INSERT_ID(); + +-- 客户管理按钮权限 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES + ('客户查询', 'asset:customer:query', 3, 1, @menuId, '', '', '', 0), + ('客户创建', 'asset:customer:create', 3, 2, @menuId, '', '', '', 0), + ('客户更新', 'asset:customer:update', 3, 3, @menuId, '', '', '', 0), + ('客户删除', 'asset:customer:delete', 3, 4, @menuId, '', '', '', 0), + ('客户导出', 'asset:customer:export', 3, 5, @menuId, '', '', '', 0); diff --git a/yudao-module-asset/sql/mysql/customer_rebuild.sql b/yudao-module-asset/sql/mysql/customer_rebuild.sql new file mode 100644 index 0000000..cee4c94 --- /dev/null +++ b/yudao-module-asset/sql/mysql/customer_rebuild.sql @@ -0,0 +1,44 @@ +-- ==================== 客户信息表重建脚本 ==================== +-- 说明:原表列名与 Java DO 不匹配,重建以对齐 +-- 日期:2026-03-13 +-- 注意:如果 asset_customer 已有数据,请先备份! + +-- 1. 备份旧表(如果存在) +-- CREATE TABLE asset_customer_bak AS SELECT * FROM asset_customer; + +-- 2. 删除旧表 +DROP TABLE IF EXISTS asset_customer; + +-- 3. 创建新表(与 CustomerDO 字段完全对齐) +CREATE TABLE `asset_customer` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `customer_code` varchar(50) DEFAULT NULL COMMENT '客户编号', + `coop_status` varchar(20) DEFAULT NULL COMMENT '合作状态', + `customer_name` varchar(100) NOT NULL COMMENT '客户名称', + `province` varchar(50) DEFAULT NULL COMMENT '省份', + `city` varchar(50) DEFAULT NULL COMMENT '城市', + `address` varchar(255) DEFAULT NULL COMMENT '地址', + `region` varchar(20) DEFAULT NULL COMMENT '区域', + `contact` varchar(50) DEFAULT NULL COMMENT '联系人', + `contact_mobile` varchar(20) DEFAULT NULL COMMENT '联系人手机', + `contact_phone` varchar(20) DEFAULT NULL COMMENT '联系人座机', + `email` varchar(100) DEFAULT NULL COMMENT '电子邮箱', + `credit_code_or_id` varchar(50) DEFAULT NULL COMMENT '统一社会信用代码/身份证', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `tax_id` varchar(50) DEFAULT NULL COMMENT '纳税人识别号', + `invoice_address` varchar(255) DEFAULT NULL COMMENT '发票地址', + `invoice_phone` varchar(20) DEFAULT NULL COMMENT '发票电话', + `account` varchar(50) DEFAULT NULL COMMENT '银行账号', + `opening_bank` varchar(100) DEFAULT NULL COMMENT '开户行', + `mailing_address` varchar(255) DEFAULT NULL COMMENT '邮寄地址', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除(0=未删除 1=已删除)', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_customer_code` (`customer_code`) USING BTREE COMMENT '客户编号查询', + KEY `idx_customer_name` (`customer_name`) USING BTREE COMMENT '客户名称查询', + KEY `idx_tenant_deleted` (`tenant_id`, `deleted`) USING BTREE COMMENT '租户隔离 + 逻辑删除' +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='客户信息表'; diff --git a/yudao-module-asset/sql/mysql/parking.sql b/yudao-module-asset/sql/mysql/parking.sql new file mode 100644 index 0000000..c9f1ab5 --- /dev/null +++ b/yudao-module-asset/sql/mysql/parking.sql @@ -0,0 +1,23 @@ +-- 停车场管理菜单和权限初始化脚本 + +-- 1. 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '停车场管理', '', 2, 1, 5055, + 'parking', 'car', 'asset/parking/index', 0, 'Parking' +); + +-- 获取刚插入的菜单ID +SET @menuId = LAST_INSERT_ID(); + +-- 停车场管理按钮权限 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES + ('停车场查询', 'asset:parking:query', 3, 1, @menuId, '', '', '', 0), + ('停车场创建', 'asset:parking:create', 3, 2, @menuId, '', '', '', 0), + ('停车场更新', 'asset:parking:update', 3, 3, @menuId, '', '', '', 0), + ('停车场删除', 'asset:parking:delete', 3, 4, @menuId, '', '', '', 0), + ('停车场导出', 'asset:parking:export', 3, 5, @menuId, '', '', '', 0); diff --git a/yudao-module-asset/sql/mysql/supplier-menu.sql b/yudao-module-asset/sql/mysql/supplier-menu.sql new file mode 100644 index 0000000..d1d5183 --- /dev/null +++ b/yudao-module-asset/sql/mysql/supplier-menu.sql @@ -0,0 +1,23 @@ +-- 供应商管理菜单和权限初始化脚本 + +-- 1. 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '供应商管理', '', 2, 3, 5055, + 'supplier', 'user', 'asset/supplier/index', 0, 'Supplier' +); + +-- 获取刚插入的菜单ID +SET @menuId = LAST_INSERT_ID(); + +-- 供应商管理按钮权限 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES + ('供应商查询', 'asset:supplier:query', 3, 1, @menuId, '', '', '', 0), + ('供应商创建', 'asset:supplier:create', 3, 2, @menuId, '', '', '', 0), + ('供应商更新', 'asset:supplier:update', 3, 3, @menuId, '', '', '', 0), + ('供应商删除', 'asset:supplier:delete', 3, 4, @menuId, '', '', '', 0), + ('供应商导出', 'asset:supplier:export', 3, 5, @menuId, '', '', '', 0); diff --git a/yudao-module-asset/sql/mysql/vehicle-model.sql b/yudao-module-asset/sql/mysql/vehicle-model.sql new file mode 100644 index 0000000..62020a3 --- /dev/null +++ b/yudao-module-asset/sql/mysql/vehicle-model.sql @@ -0,0 +1,23 @@ +-- 车型参数管理菜单和权限初始化脚本 + +-- 1. 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '车型参数', '', 2, 4, 5055, + 'vehicle-model', 'car', 'asset/vehicle-model/index', 0, 'VehicleModel' +); + +-- 获取刚插入的菜单ID +SET @menuId = LAST_INSERT_ID(); + +-- 车型参数管理按钮权限 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES + ('车型参数查询', 'asset:vehicle-model:query', 3, 1, @menuId, '', '', '', 0), + ('车型参数创建', 'asset:vehicle-model:create', 3, 2, @menuId, '', '', '', 0), + ('车型参数更新', 'asset:vehicle-model:update', 3, 3, @menuId, '', '', '', 0), + ('车型参数删除', 'asset:vehicle-model:delete', 3, 4, @menuId, '', '', '', 0), + ('车型参数导出', 'asset:vehicle-model:export', 3, 5, @menuId, '', '', '', 0); diff --git a/yudao-module-asset/sql/mysql/vehicle-registration.sql b/yudao-module-asset/sql/mysql/vehicle-registration.sql new file mode 100644 index 0000000..d302167 --- /dev/null +++ b/yudao-module-asset/sql/mysql/vehicle-registration.sql @@ -0,0 +1,25 @@ +-- 车辆上牌管理菜单和权限初始化脚本 + +-- 1. 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '车辆上牌', '', 2, 5, 5055, + 'vehicle-registration', 'file-text', 'asset/vehicle-registration/index', 0, 'VehicleRegistration' +); + +-- 获取刚插入的菜单ID +SET @menuId = LAST_INSERT_ID(); + +-- 车辆上牌管理按钮权限 +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES + ('车辆上牌查询', 'asset:vehicle-registration:query', 3, 1, @menuId, '', '', '', 0), + ('车辆上牌创建', 'asset:vehicle-registration:create', 3, 2, @menuId, '', '', '', 0), + ('车辆上牌更新', 'asset:vehicle-registration:update', 3, 3, @menuId, '', '', '', 0), + ('车辆上牌删除', 'asset:vehicle-registration:delete', 3, 4, @menuId, '', '', '', 0), + ('车辆上牌导出', 'asset:vehicle-registration:export', 3, 5, @menuId, '', '', '', 0), + ('车辆上牌确认', 'asset:vehicle-registration:confirm', 3, 6, @menuId, '', '', '', 0), + ('车辆上牌作废', 'asset:vehicle-registration:void', 3, 7, @menuId, '', '', '', 0); diff --git a/yudao-module-asset/sql/mysql/vehicle-rental-flow-alter.sql b/yudao-module-asset/sql/mysql/vehicle-rental-flow-alter.sql new file mode 100644 index 0000000..932cb9f --- /dev/null +++ b/yudao-module-asset/sql/mysql/vehicle-rental-flow-alter.sql @@ -0,0 +1,35 @@ +-- ============================================= +-- 车辆租赁业务流程表结构增量变更 +-- 对应前端新增字段 +-- ============================================= + +-- 1. 备车记录表 - 新增字段 +ALTER TABLE `asset_vehicle_prepare` + ADD COLUMN `vehicle_type` VARCHAR(50) COMMENT '车辆类型' AFTER `model`, + ADD COLUMN `parking_lot` VARCHAR(100) COMMENT '停车场' AFTER `vehicle_type`, + ADD COLUMN `preparation_type` VARCHAR(50) COMMENT '整备类型' AFTER `contract_code`, + ADD COLUMN `mileage` INT COMMENT '里程(km)' AFTER `preparation_type`, + ADD COLUMN `hydrogen_remaining` DECIMAL(10,2) COMMENT '剩余氢量' AFTER `mileage`, + ADD COLUMN `hydrogen_unit` VARCHAR(10) DEFAULT '%' COMMENT '氢量单位(%/MPa/kg)' AFTER `hydrogen_remaining`, + ADD COLUMN `battery_remaining` DECIMAL(10,2) COMMENT '剩余电量(%)' AFTER `hydrogen_unit`, + ADD COLUMN `enlarged_text_photo` VARCHAR(1000) COMMENT '放大字照片(JSON数组)' AFTER `body_ad_photos`, + ADD COLUMN `spare_tire_depth` DECIMAL(10,2) COMMENT '备胎胎纹深度(mm)' AFTER `has_tail_lift`, + ADD COLUMN `spare_tire_photo` VARCHAR(1000) COMMENT '备胎照片(JSON数组)' AFTER `spare_tire_depth`, + ADD COLUMN `remark` VARCHAR(500) COMMENT '备注' AFTER `check_list`, + ADD COLUMN `complete_time` DATETIME COMMENT '完成时间' AFTER `status`; + +-- 2. 交车单表 - 新增司机信息、交检清单、费用信息 +ALTER TABLE `asset_delivery_order` + ADD COLUMN `driver_name` VARCHAR(64) COMMENT '司机姓名' AFTER `delivery_photos`, + ADD COLUMN `driver_id_card` VARCHAR(18) COMMENT '司机身份证' AFTER `driver_name`, + ADD COLUMN `driver_phone` VARCHAR(20) COMMENT '司机手机号' AFTER `driver_id_card`, + ADD COLUMN `inspection_data` TEXT COMMENT '交检清单(JSON)' AFTER `driver_phone`, + ADD COLUMN `cost_list` TEXT COMMENT '费用信息(JSON)' AFTER `inspection_data`; + +-- 3. 交车单车辆表 - 新增电量 +ALTER TABLE `asset_delivery_order_vehicle` + ADD COLUMN `battery_level` DECIMAL(10,2) COMMENT '交车时电量(%)' AFTER `hydrogen_level`; + +-- 4. 还车车辆表 - 新增违章费用 +ALTER TABLE `asset_return_order_vehicle` + ADD COLUMN `violation_fee` DECIMAL(10,2) DEFAULT 0 COMMENT '违章费用' AFTER `unpaid_repair_fee`; diff --git a/yudao-module-asset/sql/mysql/vehicle-rental-flow.sql b/yudao-module-asset/sql/mysql/vehicle-rental-flow.sql new file mode 100644 index 0000000..78f7a02 --- /dev/null +++ b/yudao-module-asset/sql/mysql/vehicle-rental-flow.sql @@ -0,0 +1,222 @@ +-- ============================================= +-- 车辆租赁业务流程表结构 +-- 包含:备车、交车任务、交车单、还车单 +-- ============================================= + +-- 1. 备车记录表 +CREATE TABLE IF NOT EXISTS `asset_vehicle_prepare` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `vehicle_id` BIGINT NOT NULL COMMENT '车辆ID', + `plate_no` VARCHAR(20) COMMENT '车牌号', + `vin` VARCHAR(50) NOT NULL COMMENT '车辆识别代码', + `vehicle_model_id` BIGINT NOT NULL COMMENT '车型ID', + `brand` VARCHAR(100) COMMENT '品牌', + `model` VARCHAR(100) COMMENT '型号', + `contract_id` BIGINT COMMENT '关联合同ID', + `contract_code` VARCHAR(50) COMMENT '合同编码', + `has_body_ad` BIT(1) DEFAULT b'0' COMMENT '是否有车身广告', + `body_ad_photos` VARCHAR(1000) COMMENT '广告照片(JSON数组)', + `has_tail_lift` BIT(1) DEFAULT b'0' COMMENT '是否有尾板', + `trailer_plate_no` VARCHAR(20) COMMENT '挂车牌号', + `defect_photos` VARCHAR(1000) COMMENT '瑕疵照片(JSON数组)', + `check_list` TEXT COMMENT '备车检查清单(JSON)', + `status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态(0=待提交 1=已完成)', + `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + INDEX `idx_vehicle_id` (`vehicle_id`), + INDEX `idx_contract_id` (`contract_id`), + INDEX `idx_status` (`status`), + INDEX `idx_create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='备车记录表'; + +-- 2. 交车任务表 +CREATE TABLE IF NOT EXISTS `asset_delivery_task` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `task_code` VARCHAR(50) NOT NULL COMMENT '交车任务编码', + `contract_id` BIGINT NOT NULL COMMENT '合同ID', + `contract_code` VARCHAR(50) NOT NULL COMMENT '合同编码', + `project_name` VARCHAR(200) NOT NULL COMMENT '项目名称', + `customer_id` BIGINT NOT NULL COMMENT '客户ID', + `customer_name` VARCHAR(200) NOT NULL COMMENT '客户名称', + `expected_delivery_date_start` DATE COMMENT '预计交车开始日期', + `expected_delivery_date_end` DATE COMMENT '预计交车结束日期', + `billing_start_date` DATE NOT NULL COMMENT '开始计费日期', + `delivery_province` VARCHAR(50) COMMENT '交车省份', + `delivery_city` VARCHAR(50) COMMENT '交车城市', + `delivery_location` VARCHAR(255) COMMENT '交车地点', + `vehicle_count` INT NOT NULL DEFAULT 0 COMMENT '交车数量', + `task_status` TINYINT NOT NULL DEFAULT 0 COMMENT '任务状态(0=激活 1=挂起)', + `delivery_status` TINYINT NOT NULL DEFAULT 0 COMMENT '交车状态(0=未交车 1=已交车)', + `need_return` BIT(1) NOT NULL DEFAULT b'1' COMMENT '是否需要还车', + `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_task_code` (`task_code`, `deleted`), + INDEX `idx_contract_id` (`contract_id`), + INDEX `idx_customer_id` (`customer_id`), + INDEX `idx_task_status` (`task_status`), + INDEX `idx_delivery_status` (`delivery_status`), + INDEX `idx_create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='交车任务表'; + +-- 3. 交车任务车辆表 +CREATE TABLE IF NOT EXISTS `asset_delivery_task_vehicle` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `task_id` BIGINT NOT NULL COMMENT '交车任务ID', + `contract_vehicle_id` BIGINT NOT NULL COMMENT '合同车辆ID', + `vehicle_id` BIGINT NOT NULL COMMENT '车辆ID', + `plate_no` VARCHAR(20) COMMENT '车牌号', + `vin` VARCHAR(50) NOT NULL COMMENT '车辆识别代码', + `brand` VARCHAR(100) NOT NULL COMMENT '品牌', + `model` VARCHAR(100) NOT NULL COMMENT '型号', + `month_rent` DECIMAL(10,2) NOT NULL COMMENT '月租金', + `deposit` DECIMAL(10,2) NOT NULL COMMENT '保证金', + `actual_delivery_date` DATETIME COMMENT '实际交车日期', + `delivery_person` VARCHAR(64) COMMENT '交车人', + `is_delivered` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否已交车', + `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + INDEX `idx_task_id` (`task_id`), + INDEX `idx_vehicle_id` (`vehicle_id`), + INDEX `idx_contract_vehicle_id` (`contract_vehicle_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='交车任务车辆表'; + +-- 4. 交车单表 +CREATE TABLE IF NOT EXISTS `asset_delivery_order` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `order_code` VARCHAR(50) NOT NULL COMMENT '交车单编码', + `task_id` BIGINT NOT NULL COMMENT '交车任务ID', + `task_code` VARCHAR(50) NOT NULL COMMENT '交车任务编码', + `contract_id` BIGINT NOT NULL COMMENT '合同ID', + `contract_code` VARCHAR(50) NOT NULL COMMENT '合同编码', + `project_name` VARCHAR(200) NOT NULL COMMENT '项目名称', + `customer_id` BIGINT NOT NULL COMMENT '客户ID', + `customer_name` VARCHAR(200) NOT NULL COMMENT '客户名称', + `delivery_date` DATETIME NOT NULL COMMENT '交车日期', + `delivery_person` VARCHAR(64) NOT NULL COMMENT '交车人', + `delivery_location` VARCHAR(255) COMMENT '交车地点', + `authorized_person_id` BIGINT COMMENT '被授权人ID', + `authorized_person_name` VARCHAR(100) COMMENT '被授权人姓名', + `authorized_person_phone` VARCHAR(20) COMMENT '被授权人电话', + `authorized_person_id_card` VARCHAR(18) COMMENT '被授权人身份证', + `esign_flow_id` VARCHAR(100) COMMENT 'E签宝流程ID', + `esign_status` TINYINT DEFAULT 0 COMMENT 'E签宝状态(0=未签 1=已签)', + `delivery_photos` VARCHAR(1000) COMMENT '交车照片(JSON数组)', + `status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态(0=待完成 1=已完成)', + `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_order_code` (`order_code`, `deleted`), + INDEX `idx_task_id` (`task_id`), + INDEX `idx_contract_id` (`contract_id`), + INDEX `idx_status` (`status`), + INDEX `idx_delivery_date` (`delivery_date`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='交车单表'; + +-- 5. 交车单车辆表 +CREATE TABLE IF NOT EXISTS `asset_delivery_order_vehicle` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `order_id` BIGINT NOT NULL COMMENT '交车单ID', + `task_vehicle_id` BIGINT NOT NULL COMMENT '交车任务车辆ID', + `vehicle_id` BIGINT NOT NULL COMMENT '车辆ID', + `plate_no` VARCHAR(20) COMMENT '车牌号', + `vin` VARCHAR(50) NOT NULL COMMENT '车辆识别代码', + `brand` VARCHAR(100) NOT NULL COMMENT '品牌', + `model` VARCHAR(100) NOT NULL COMMENT '型号', + `mileage` INT COMMENT '交车时里程', + `hydrogen_level` DECIMAL(10,2) COMMENT '交车时氢气量(kg)', + `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + INDEX `idx_order_id` (`order_id`), + INDEX `idx_vehicle_id` (`vehicle_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='交车单车辆表'; + +-- 6. 还车单表 +CREATE TABLE IF NOT EXISTS `asset_return_order` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `order_code` VARCHAR(50) NOT NULL COMMENT '还车单编码', + `contract_id` BIGINT NOT NULL COMMENT '合同ID', + `contract_code` VARCHAR(50) NOT NULL COMMENT '合同编码', + `project_name` VARCHAR(200) NOT NULL COMMENT '项目名称', + `customer_id` BIGINT NOT NULL COMMENT '客户ID', + `customer_name` VARCHAR(200) NOT NULL COMMENT '客户名称', + `return_date` DATETIME NOT NULL COMMENT '还车日期', + `return_person` VARCHAR(64) NOT NULL COMMENT '还车验收人', + `return_location` VARCHAR(255) COMMENT '还车地点', + `return_reason` VARCHAR(50) COMMENT '还车原因', + `return_reason_desc` VARCHAR(500) COMMENT '还车原因说明', + `total_refund_amount` DECIMAL(10,2) DEFAULT 0 COMMENT '退还总金额', + `deposit_refund` DECIMAL(10,2) DEFAULT 0 COMMENT '退还保证金', + `hydrogen_refund` DECIMAL(10,2) DEFAULT 0 COMMENT '氢气退款', + `other_charges` DECIMAL(10,2) DEFAULT 0 COMMENT '其他费用', + `return_photos` VARCHAR(1000) COMMENT '还车照片(JSON数组)', + `status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态(0=待验车 1=验车完成 2=已结算)', + `approval_status` TINYINT NOT NULL DEFAULT 0 COMMENT '审批状态(0=草稿 1=审批中 2=审批通过 3=审批拒绝)', + `bpm_instance_id` VARCHAR(64) COMMENT 'BPM流程实例ID', + `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_order_code` (`order_code`, `deleted`), + INDEX `idx_contract_id` (`contract_id`), + INDEX `idx_status` (`status`), + INDEX `idx_approval_status` (`approval_status`), + INDEX `idx_return_date` (`return_date`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='还车单表'; + +-- 7. 还车车辆表 +CREATE TABLE IF NOT EXISTS `asset_return_order_vehicle` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `return_order_id` BIGINT NOT NULL COMMENT '还车单ID', + `vehicle_id` BIGINT NOT NULL COMMENT '车辆ID', + `plate_no` VARCHAR(20) COMMENT '车牌号', + `vin` VARCHAR(50) NOT NULL COMMENT '车辆识别代码', + `brand` VARCHAR(100) NOT NULL COMMENT '品牌', + `model` VARCHAR(100) NOT NULL COMMENT '型号', + `return_mileage` INT COMMENT '还车时里程', + `return_hydrogen_level` DECIMAL(10,2) COMMENT '还车时氢气量(kg)', + `delivery_hydrogen_level` DECIMAL(10,2) COMMENT '交车时氢气量(kg)', + `hydrogen_diff` DECIMAL(10,2) COMMENT '氢气差值(kg)', + `hydrogen_unit_price` DECIMAL(10,2) COMMENT '氢气单价(元/kg)', + `hydrogen_refund_amount` DECIMAL(10,2) COMMENT '氢气退款金额', + `check_list` TEXT COMMENT '还车检查清单(JSON)', + `defect_photos` VARCHAR(1000) COMMENT '瑕疵照片(JSON数组)', + `vehicle_damage_fee` DECIMAL(10,2) DEFAULT 0 COMMENT '车损费', + `tool_damage_fee` DECIMAL(10,2) DEFAULT 0 COMMENT '工具损坏费', + `unpaid_maintenance_fee` DECIMAL(10,2) DEFAULT 0 COMMENT '未结算保养费', + `unpaid_repair_fee` DECIMAL(10,2) DEFAULT 0 COMMENT '未结算维修费', + `other_fee` DECIMAL(10,2) DEFAULT 0 COMMENT '其他费用', + `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + INDEX `idx_return_order_id` (`return_order_id`), + INDEX `idx_vehicle_id` (`vehicle_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='还车车辆表'; diff --git a/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/contract/ContractApprovalStatusEnum.java b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/contract/ContractApprovalStatusEnum.java new file mode 100644 index 0000000..60496b1 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/contract/ContractApprovalStatusEnum.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.asset.enums.contract; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 合同审批状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum ContractApprovalStatusEnum { + + DRAFT(0, "草稿"), + APPROVING(1, "审批中"), + APPROVED(2, "审批通过"), + REJECTED(3, "审批拒绝"), + WITHDRAWN(4, "已撤回"); + + /** + * 状态 + */ + private final Integer status; + /** + * 名称 + */ + private final String name; + + public static ContractApprovalStatusEnum valueOf(Integer status) { + return Arrays.stream(values()) + .filter(item -> item.getStatus().equals(status)) + .findFirst() + .orElse(null); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/contract/ContractStatusEnum.java b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/contract/ContractStatusEnum.java new file mode 100644 index 0000000..b3270cf --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/contract/ContractStatusEnum.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.asset.enums.contract; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 合同状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum ContractStatusEnum { + + DRAFT(0, "草稿"), + PENDING(1, "待生效"), + IN_PROGRESS(2, "进行中"), + EXPIRED(3, "已到期"), + TERMINATED(4, "已终止"), + RENEWED(5, "已续签"); + + /** + * 状态 + */ + private final Integer status; + /** + * 名称 + */ + private final String name; + + public static ContractStatusEnum valueOf(Integer status) { + return Arrays.stream(values()) + .filter(item -> item.getStatus().equals(status)) + .findFirst() + .orElse(null); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/contract/ContractTypeEnum.java b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/contract/ContractTypeEnum.java new file mode 100644 index 0000000..987ccd4 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/contract/ContractTypeEnum.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.asset.enums.contract; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 合同类型枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum ContractTypeEnum { + + TRIAL(1, "试用合同"), + FORMAL(2, "正式合同"); + + /** + * 类型 + */ + private final Integer type; + /** + * 名称 + */ + private final String name; + + public static ContractTypeEnum valueOf(Integer type) { + return Arrays.stream(values()) + .filter(item -> item.getType().equals(type)) + .findFirst() + .orElse(null); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/delivery/DeliveryOrderStatusEnum.java b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/delivery/DeliveryOrderStatusEnum.java new file mode 100644 index 0000000..bfea52b --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/delivery/DeliveryOrderStatusEnum.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.asset.enums.delivery; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 交车单状态枚举 + */ +@Getter +@AllArgsConstructor +public enum DeliveryOrderStatusEnum { + + PENDING(0, "待完成"), + COMPLETED(1, "已完成"); + + private final Integer status; + private final String name; + + public static DeliveryOrderStatusEnum valueOf(Integer status) { + return Arrays.stream(values()) + .filter(item -> item.getStatus().equals(status)) + .findFirst() + .orElse(null); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/delivery/DeliveryStatusEnum.java b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/delivery/DeliveryStatusEnum.java new file mode 100644 index 0000000..893cd23 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/delivery/DeliveryStatusEnum.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.asset.enums.delivery; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 交车状态枚举 + */ +@Getter +@AllArgsConstructor +public enum DeliveryStatusEnum { + + NOT_DELIVERED(0, "未交车"), + DELIVERED(1, "已交车"); + + private final Integer status; + private final String name; + + public static DeliveryStatusEnum valueOf(Integer status) { + return Arrays.stream(values()) + .filter(item -> item.getStatus().equals(status)) + .findFirst() + .orElse(null); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/delivery/DeliveryTaskStatusEnum.java b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/delivery/DeliveryTaskStatusEnum.java new file mode 100644 index 0000000..ba6dc21 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/delivery/DeliveryTaskStatusEnum.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.asset.enums.delivery; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 交车任务状态枚举 + */ +@Getter +@AllArgsConstructor +public enum DeliveryTaskStatusEnum { + + ACTIVE(0, "激活"), + SUSPENDED(1, "挂起"); + + private final Integer status; + private final String name; + + public static DeliveryTaskStatusEnum valueOf(Integer status) { + return Arrays.stream(values()) + .filter(item -> item.getStatus().equals(status)) + .findFirst() + .orElse(null); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/prepare/VehiclePrepareStatusEnum.java b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/prepare/VehiclePrepareStatusEnum.java new file mode 100644 index 0000000..0824320 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/prepare/VehiclePrepareStatusEnum.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.asset.enums.prepare; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 备车状态枚举 + */ +@Getter +@AllArgsConstructor +public enum VehiclePrepareStatusEnum { + + DRAFT(0, "待提交"), + COMPLETED(1, "已完成"); + + private final Integer status; + private final String name; + + public static VehiclePrepareStatusEnum valueOf(Integer status) { + return Arrays.stream(values()) + .filter(item -> item.getStatus().equals(status)) + .findFirst() + .orElse(null); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/returnorder/ReturnOrderStatusEnum.java b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/returnorder/ReturnOrderStatusEnum.java new file mode 100644 index 0000000..e72ab40 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/returnorder/ReturnOrderStatusEnum.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.asset.enums.returnorder; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 还车单状态枚举 + */ +@Getter +@AllArgsConstructor +public enum ReturnOrderStatusEnum { + + PENDING_INSPECTION(0, "待验车"), + INSPECTION_COMPLETED(1, "验车完成"), + SETTLED(2, "已结算"); + + private final Integer status; + private final String name; + + public static ReturnOrderStatusEnum valueOf(Integer status) { + return Arrays.stream(values()) + .filter(item -> item.getStatus().equals(status)) + .findFirst() + .orElse(null); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/returnorder/ReturnReasonEnum.java b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/returnorder/ReturnReasonEnum.java new file mode 100644 index 0000000..224d2d7 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-api/src/main/java/cn/iocoder/yudao/module/asset/enums/returnorder/ReturnReasonEnum.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.asset.enums.returnorder; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 还车原因枚举 + */ +@Getter +@AllArgsConstructor +public enum ReturnReasonEnum { + + CONTRACT_EXPIRED("CONTRACT_EXPIRED", "合同到期"), + CUSTOMER_REQUEST("CUSTOMER_REQUEST", "客户申请"), + CONTRACT_TERMINATED("CONTRACT_TERMINATED", "合同终止"); + + private final String code; + private final String name; + + public static ReturnReasonEnum valueOfCode(String code) { + return Arrays.stream(values()) + .filter(item -> item.getCode().equals(code)) + .findFirst() + .orElse(null); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/AssetServerApplication.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/AssetServerApplication.java index b49b60f..9545c51 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/AssetServerApplication.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/AssetServerApplication.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.asset; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; /** * 资产管理模块 Application @@ -9,6 +10,12 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; * @author 芋道源码 */ @SpringBootApplication +@EnableFeignClients(basePackages = { + "cn.iocoder.yudao.module.system.api", // System 模块 API + "cn.iocoder.yudao.module.ocr.api", // OCR 模块 API + "cn.iocoder.yudao.module.infra.api", // Infra 模块 API + "cn.iocoder.yudao.module.bpm.api" // BPM 模块 API +}) public class AssetServerApplication { public static void main(String[] args) { diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/ContractController.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/ContractController.java new file mode 100644 index 0000000..4df8d69 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/ContractController.java @@ -0,0 +1,212 @@ +package cn.iocoder.yudao.module.asset.controller.admin.contract; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.asset.controller.admin.contract.vo.*; +import cn.iocoder.yudao.module.asset.convert.contract.ContractConvert; +import cn.iocoder.yudao.module.asset.dal.dataobject.contract.*; +import cn.iocoder.yudao.module.asset.dal.mysql.contract.*; +import cn.iocoder.yudao.module.asset.service.contract.ContractService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +/** + * 车辆租赁合同 Controller + * + * @author 芋道源码 + */ +@Tag(name = "管理后台 - 车辆租赁合同管理") +@RestController +@RequestMapping("/asset/contract") +@Validated +public class ContractController { + + @Resource + private ContractService contractService; + + @Resource + private ContractVehicleMapper contractVehicleMapper; + + @Resource + private ContractVehicleServiceMapper contractVehicleServiceMapper; + + @Resource + private ContractAuthorizedMapper contractAuthorizedMapper; + + @Resource + private ContractChangeHistoryMapper contractChangeHistoryMapper; + + @PostMapping("/create") + @Operation(summary = "创建合同") + @PreAuthorize("@ss.hasPermission('asset:contract:create')") + public CommonResult createContract(@Valid @RequestBody ContractSaveReqVO createReqVO) { + return success(contractService.createContract(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新合同") + @PreAuthorize("@ss.hasPermission('asset:contract:update')") + public CommonResult updateContract(@Valid @RequestBody ContractSaveReqVO updateReqVO) { + contractService.updateContract(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除合同") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('asset:contract:delete')") + public CommonResult deleteContract(@RequestParam("id") Long id) { + contractService.deleteContract(id); + return success(true); + } + + @DeleteMapping("/delete-list") + @Operation(summary = "批量删除合同") + @Parameter(name = "ids", description = "编号列表", required = true) + @PreAuthorize("@ss.hasPermission('asset:contract:delete')") + public CommonResult deleteContractList(@RequestParam("ids") List ids) { + for (Long id : ids) { + contractService.deleteContract(id); + } + return success(true); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出合同 Excel") + @PreAuthorize("@ss.hasPermission('asset:contract:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportContractExcel(HttpServletResponse response, @Valid ContractPageReqVO exportReqVO) throws IOException { + exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = contractService.getContractPage(exportReqVO).getList(); + // 输出 + ExcelUtils.write(response, "车辆租赁合同.xls", "合同数据", ContractExcelVO.class, + BeanUtils.toBean(list, ContractExcelVO.class)); + } + + @GetMapping("/get") + @Operation(summary = "获得合同详情") + @Parameter(name = "id", description = "编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('asset:contract:query')") + public CommonResult getContract(@RequestParam("id") Long id) { + return success(contractService.getContractDetail(id)); + } + + @GetMapping("/page") + @Operation(summary = "获得合同分页") + @PreAuthorize("@ss.hasPermission('asset:contract:query')") + public CommonResult> getContractPage(@Valid ContractPageReqVO pageReqVO) { + PageResult pageResult = contractService.getContractPage(pageReqVO); + PageResult voPage = ContractConvert.INSTANCE.convertPage(pageResult); + // 填充车辆数和已交车辆数 + for (ContractRespVO vo : voPage.getList()) { + List vehicles = contractVehicleMapper.selectListByContractId(vo.getId()); + vo.setVehicleCount(vehicles.size()); + vo.setDeliveredCount((int) vehicles.stream() + .filter(v -> Integer.valueOf(1).equals(v.getVehicleStatus())) + .count()); + } + return success(voPage); + } + + @GetMapping("/change-history") + @Operation(summary = "获得合同变更历史") + @Parameter(name = "contractId", description = "合同ID", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('asset:contract:query')") + public CommonResult> getChangeHistory(@RequestParam("contractId") Long contractId) { + return success(contractChangeHistoryMapper.selectListByContractId(contractId)); + } + + @PostMapping("/submit-approval") + @Operation(summary = "提交合同审批") + @Parameter(name = "id", description = "合同ID", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('asset:contract:update')") + public CommonResult submitApproval(@RequestParam("id") Long id) { + return success(contractService.submitContractApproval(id)); + } + + @PostMapping("/withdraw-approval") + @Operation(summary = "撤回合同审批") + @Parameter(name = "id", description = "合同ID", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('asset:contract:update')") + public CommonResult withdrawApproval(@RequestParam("id") Long id) { + contractService.withdrawContractApproval(id); + return success(true); + } + + @PostMapping("/terminate") + @Operation(summary = "终止合同") + @PreAuthorize("@ss.hasPermission('asset:contract:update')") + public CommonResult terminateContract(@RequestParam("id") Long id, + @RequestParam("reason") String reason) { + contractService.terminateContract(id, reason); + return success(true); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得合同精简列表", description = "用于下拉选择") + public CommonResult> getContractSimpleList() { + List list = contractService.getContractSimpleList(); + return success(BeanUtils.toBean(list, ContractSimpleRespVO.class)); + } + + @PostMapping("/renew") + @Operation(summary = "续签合同") + @PreAuthorize("@ss.hasPermission('asset:contract:create')") + public CommonResult renewContract(@RequestParam("id") Long id, + @Valid @RequestBody ContractSaveReqVO newContractReqVO) { + return success(contractService.renewContract(id, newContractReqVO)); + } + + @PostMapping("/convert-to-third-party") + @Operation(summary = "变更为三方合同") + @PreAuthorize("@ss.hasPermission('asset:contract:update')") + public CommonResult convertToThirdParty(@RequestParam("id") Long id, + @Valid @RequestBody ContractSaveReqVO newContractReqVO) { + return success(contractService.convertToThirdParty(id, newContractReqVO)); + } + + @PostMapping("/convert-to-formal") + @Operation(summary = "试用合同转正式") + @PreAuthorize("@ss.hasPermission('asset:contract:update')") + public CommonResult convertToFormal(@RequestParam("id") Long id, + @Valid @RequestBody ContractSaveReqVO newContractReqVO) { + return success(contractService.convertToFormal(id, newContractReqVO)); + } + + @PostMapping("/add-vehicle") + @Operation(summary = "往现有合同追加车辆") + @PreAuthorize("@ss.hasPermission('asset:contract:update')") + public CommonResult addVehicle(@RequestParam("id") Long id, + @Valid @RequestBody List vehicles) { + contractService.addVehiclesToContract(id, vehicles); + return success(true); + } + + @PostMapping("/upload-seal") + @Operation(summary = "上传盖章合同附件") + @PreAuthorize("@ss.hasPermission('asset:contract:update')") + public CommonResult uploadSeal(@RequestParam("id") Long id, + @RequestParam("fileUrl") String fileUrl, + @RequestParam("fileName") String fileName) { + contractService.uploadSealedContract(id, fileUrl, fileName); + return success(true); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractAttachmentVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractAttachmentVO.java new file mode 100644 index 0000000..48ef47e --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractAttachmentVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.asset.controller.admin.contract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 合同附件 VO + * + * @author 芋道源码 + */ +@Data +public class ContractAttachmentVO { + + @Schema(description = "主键ID", example = "1") + private Long id; + + @Schema(description = "附件类型(1=合同原件 2=盖章合同)", example = "1") + private Integer attachmentType; + + @Schema(description = "文件名称", example = "合同扫描件.pdf") + private String fileName; + + @Schema(description = "文件URL", example = "https://xxx.com/contract.pdf") + private String fileUrl; + + @Schema(description = "文件大小(字节)", example = "1024000") + private Long fileSize; + + @Schema(description = "上传时间", example = "2026-01-01 00:00:00") + private LocalDateTime uploadTime; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractAuthorizedVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractAuthorizedVO.java new file mode 100644 index 0000000..af4856b --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractAuthorizedVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.asset.controller.admin.contract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 合同被授权人 VO + * + * @author 芋道源码 + */ +@Data +public class ContractAuthorizedVO { + + @Schema(description = "主键ID", example = "1") + private Long id; + + @Schema(description = "姓名", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + private String name; + + @Schema(description = "电话", requiredMode = Schema.RequiredMode.REQUIRED, example = "13800138000") + private String phone; + + @Schema(description = "身份证号", requiredMode = Schema.RequiredMode.REQUIRED, example = "310101199001011234") + private String idCard; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractBaseVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractBaseVO.java new file mode 100644 index 0000000..af79ff3 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractBaseVO.java @@ -0,0 +1,101 @@ +package cn.iocoder.yudao.module.asset.controller.admin.contract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.NotBlank; +import java.math.BigDecimal; +import java.time.LocalDate; + +/** + * 车辆租赁合同 Base VO + * + * @author 芋道源码 + */ +@Data +public class ContractBaseVO { + + @Schema(description = "合同编码(新增时自动生成)", example = "HT-2026-001") + private String contractCode; + + @Schema(description = "合同类型(1=试用 2=正式)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "合同类型不能为空") + private Integer contractType; + + @Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张江高科技园区车辆租赁项目") + @NotBlank(message = "项目名称不能为空") + private String projectName; + + @Schema(description = "生效日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-01-01") + @NotNull(message = "生效日期不能为空") + private LocalDate startDate; + + @Schema(description = "结束日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-12-31") + @NotNull(message = "结束日期不能为空") + private LocalDate endDate; + + @Schema(description = "付款方式", example = "月付") + private String paymentMethod; + + @Schema(description = "付款周期", example = "每月1日") + private String paymentCycle; + + @Schema(description = "签约公司(乙方)", example = "上海某某汽车租赁有限公司") + private String signingCompany; + + @Schema(description = "交车省份", example = "上海市") + private String deliveryProvince; + + @Schema(description = "交车城市", example = "浦东新区") + private String deliveryCity; + + @Schema(description = "交车地点", example = "张江高科技园区") + private String deliveryLocation; + + @Schema(description = "备注", example = "特殊要求说明") + private String remark; + + @Schema(description = "客户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "客户ID不能为空") + private Long customerId; + + @Schema(description = "客户名称(由后端根据客户ID自动填充)", example = "上海某某科技有限公司") + private String customerName; + + @Schema(description = "是否三方合同", example = "false") + private Boolean thirdPartyEnabled; + + @Schema(description = "丙方客户ID", example = "2") + private Long thirdPartyCustomerId; + + @Schema(description = "丙方名称", example = "北京某某公司") + private String thirdPartyName; + + @Schema(description = "业务部门ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "业务部门ID不能为空") + private Long businessDeptId; + + @Schema(description = "业务负责人ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "业务负责人ID不能为空") + private Long businessManagerId; + + @Schema(description = "氢费承担方", example = "客户") + private String hydrogenBearer; + + @Schema(description = "氢气付款方式", example = "预付") + private String hydrogenPaymentMethod; + + @Schema(description = "氢气预付款", example = "5000.00") + private BigDecimal hydrogenPrepay; + + @Schema(description = "退还车氢气单价", example = "35.00") + private BigDecimal hydrogenReturnPrice; + + @Schema(description = "账单计算方式", example = "按自然月结算") + private String billingMethod; + + @Schema(description = "主车型", example = "氢能重卡") + private String mainVehicleType; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractDetailRespVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractDetailRespVO.java new file mode 100644 index 0000000..e432d29 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractDetailRespVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.asset.controller.admin.contract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.List; + +/** + * 车辆租赁合同详情 Response VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - 车辆租赁合同详情 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ContractDetailRespVO extends ContractRespVO { + + @Schema(description = "车辆订单列表") + private List vehicles; + + @Schema(description = "被授权人列表") + private List authorizedPersons; + + @Schema(description = "附件列表") + private List attachments; + + @Data + @EqualsAndHashCode(callSuper = true) + @ToString(callSuper = true) + public static class ContractVehicleDetailVO extends ContractVehicleVO { + + @Schema(description = "服务项目列表") + private List services; + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractExcelVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractExcelVO.java new file mode 100644 index 0000000..dfed989 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractExcelVO.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.asset.controller.admin.contract.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * 车辆租赁合同 Excel 导出 VO + * + * @author 芋道源码 + */ +@Data +@ExcelIgnoreUnannotated +public class ContractExcelVO { + + @ExcelProperty("合同编码") + private String contractCode; + + @ExcelProperty("合同类型") + private Integer contractType; + + @ExcelProperty("项目名称") + private String projectName; + + @ExcelProperty("客户名称") + private String customerName; + + @ExcelProperty("签约公司") + private String signingCompany; + + @ExcelProperty("生效日期") + private LocalDate startDate; + + @ExcelProperty("结束日期") + private LocalDate endDate; + + @ExcelProperty("付款方式") + private String paymentMethod; + + @ExcelProperty("付款周期") + private String paymentCycle; + + @ExcelProperty("交车省份") + private String deliveryProvince; + + @ExcelProperty("交车城市") + private String deliveryCity; + + @ExcelProperty("交车地点") + private String deliveryLocation; + + @ExcelProperty("主车型") + private String mainVehicleType; + + @ExcelProperty("审批状态") + private Integer approvalStatus; + + @ExcelProperty("合同状态") + private Integer contractStatus; + + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @ExcelProperty("备注") + private String remark; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractPageReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractPageReqVO.java new file mode 100644 index 0000000..7e2661a --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractPageReqVO.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.asset.controller.admin.contract.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDate; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; + +/** + * 车辆租赁合同分页查询 Request VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - 车辆租赁合同分页查询 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ContractPageReqVO extends PageParam { + + @Schema(description = "合同编码", example = "HT-2026-001") + private String contractCode; + + @Schema(description = "合同类型(1=试用 2=正式)", example = "1") + private Integer contractType; + + @Schema(description = "项目名称(模糊搜索)", example = "张江高科技园区") + private String projectName; + + @Schema(description = "客户ID", example = "1") + private Long customerId; + + @Schema(description = "客户名称(模糊搜索)", example = "上海某某科技") + private String customerName; + + @Schema(description = "审批状态(0=草稿 1=审批中 2=审批通过 3=审批拒绝 4=已撤回)", example = "0") + private Integer approvalStatus; + + @Schema(description = "合同状态(0=草稿 1=待生效 2=进行中 3=已到期 4=已终止 5=已续签)", example = "0") + private Integer contractStatus; + + @Schema(description = "生效日期", example = "[2026-01-01, 2026-12-31]") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + private LocalDate[] startDate; + + @Schema(description = "结束日期", example = "[2026-01-01, 2026-12-31]") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + private LocalDate[] endDate; + + @Schema(description = "业务部门ID", example = "1") + private Long businessDeptId; + + @Schema(description = "签约公司", example = "嘉兴羚牛") + private String signingCompany; + + @Schema(description = "业务负责人ID", example = "1") + private Long businessManagerId; + + @Schema(description = "创建人", example = "admin") + private String creator; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractRespVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractRespVO.java new file mode 100644 index 0000000..a957273 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractRespVO.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.asset.controller.admin.contract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +/** + * 车辆租赁合同 Response VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - 车辆租赁合同 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ContractRespVO extends ContractBaseVO { + + @Schema(description = "主键ID", example = "1") + private Long id; + + @Schema(description = "审批状态(0=草稿 1=审批中 2=审批通过 3=审批拒绝 4=已撤回)", example = "0") + private Integer approvalStatus; + + @Schema(description = "BPM流程实例ID", example = "123456") + private String bpmInstanceId; + + @Schema(description = "合同状态(0=草稿 1=待生效 2=进行中 3=已到期 4=已终止 5=已续签)", example = "0") + private Integer contractStatus; + + @Schema(description = "实际生效时间", example = "2026-01-01 00:00:00") + private LocalDateTime effectiveTime; + + @Schema(description = "终止时间", example = "2026-12-31 23:59:59") + private LocalDateTime terminateTime; + + @Schema(description = "终止原因", example = "客户要求终止") + private String terminateReason; + + @Schema(description = "续签后的新合同ID", example = "2") + private Long renewedContractId; + + @Schema(description = "原合同ID(如果是续签合同)", example = "1") + private Long originalContractId; + + @Schema(description = "创建时间", example = "2026-01-01 00:00:00") + private LocalDateTime createTime; + + @Schema(description = "创建者", example = "admin") + private String creator; + + @Schema(description = "租赁车辆数", example = "5") + private Integer vehicleCount; + + @Schema(description = "已交车辆数", example = "3") + private Integer deliveredCount; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractSaveReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractSaveReqVO.java new file mode 100644 index 0000000..5d9e63a --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractSaveReqVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.asset.controller.admin.contract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import java.util.List; + +/** + * 车辆租赁合同创建/更新 Request VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - 车辆租赁合同创建/更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ContractSaveReqVO extends ContractBaseVO { + + @Schema(description = "主键ID", example = "1") + private Long id; + + @Schema(description = "车辆订单列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "车辆订单列表不能为空") + @Valid + private List vehicles; + + @Schema(description = "被授权人列表") + @Valid + private List authorizedPersons; + + @Data + public static class ContractVehicleSaveVO extends ContractVehicleVO { + + @Schema(description = "服务项目列表") + @Valid + private List services; + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractSimpleRespVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractSimpleRespVO.java new file mode 100644 index 0000000..3e8eede --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractSimpleRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.asset.controller.admin.contract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 合同精简 Response VO") +@Data +public class ContractSimpleRespVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "合同编码", example = "HT-2026-0001") + private String contractCode; + + @Schema(description = "项目名称", example = "XX物流项目") + private String projectName; + + @Schema(description = "客户名称", example = "XX公司") + private String customerName; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractVehicleServiceVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractVehicleServiceVO.java new file mode 100644 index 0000000..705ed33 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractVehicleServiceVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.asset.controller.admin.contract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; + +/** + * 合同车辆服务项目 VO + * + * @author 芋道源码 + */ +@Data +public class ContractVehicleServiceVO { + + @Schema(description = "主键ID", example = "1") + private Long id; + + @Schema(description = "服务项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "保险") + private String serviceName; + + @Schema(description = "服务费用(元)", requiredMode = Schema.RequiredMode.REQUIRED, example = "3000.00") + private BigDecimal serviceFee; + + @Schema(description = "生效日期", example = "2026-01-01") + private LocalDate effectiveDate; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractVehicleVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractVehicleVO.java new file mode 100644 index 0000000..9758cd3 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/contract/vo/ContractVehicleVO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.asset.controller.admin.contract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; + +/** + * 合同车辆 VO + * + * @author 芋道源码 + */ +@Data +public class ContractVehicleVO { + + @Schema(description = "主键ID", example = "1") + private Long id; + + @Schema(description = "车辆ID", example = "1") + private Long vehicleId; + + @Schema(description = "品牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "丰田") + private String brand; + + @Schema(description = "型号", requiredMode = Schema.RequiredMode.REQUIRED, example = "凯美瑞") + private String model; + + @Schema(description = "车牌号", example = "沪A12345") + private String plateNo; + + @Schema(description = "VIN码", example = "LVSHCAMB1CE012345") + private String vin; + + @Schema(description = "月租金(元)", requiredMode = Schema.RequiredMode.REQUIRED, example = "5000.00") + private BigDecimal monthRent; + + @Schema(description = "保证金(元)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000.00") + private BigDecimal deposit; + + @Schema(description = "车辆状态(0=待交车 1=已交车 2=已退车)", example = "0") + private Integer vehicleStatus; + + @Schema(description = "备注", example = "特殊要求") + private String remark; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/CustomerController.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/CustomerController.java index 7bdcf7e..caaab61 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/CustomerController.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/customer/CustomerController.java @@ -17,6 +17,7 @@ import org.springframework.web.bind.annotation.*; import jakarta.annotation.Resource; import jakarta.validation.Valid; +import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -75,4 +76,11 @@ public class CustomerController { return success(CustomerConvert.INSTANCE.convertPage(pageResult)); } + @GetMapping("/simple-list") + @Operation(summary = "获得客户精简列表", description = "用于下拉选择") + public CommonResult> getCustomerSimpleList() { + List list = customerService.getCustomerSimpleList(); + return success(CustomerConvert.INSTANCE.convertList(list)); + } + } diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/DeliveryOrderController.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/DeliveryOrderController.java new file mode 100644 index 0000000..cd0e279 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/DeliveryOrderController.java @@ -0,0 +1,79 @@ +package cn.iocoder.yudao.module.asset.controller.admin.delivery; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.*; +import cn.iocoder.yudao.module.asset.dal.dataobject.delivery.DeliveryOrderDO; +import cn.iocoder.yudao.module.asset.service.delivery.DeliveryOrderService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import jakarta.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 交车单") +@RestController +@RequestMapping("/asset/delivery-order") +@Validated +public class DeliveryOrderController { + + @Resource + private DeliveryOrderService deliveryOrderService; + + @PostMapping("/create") + @Operation(summary = "创建交车单") + @PreAuthorize("@ss.hasPermission('asset:delivery-order:create')") + public CommonResult createDeliveryOrder(@Valid @RequestBody DeliveryOrderSaveReqVO createReqVO) { + return success(deliveryOrderService.createDeliveryOrder(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新交车单") + @PreAuthorize("@ss.hasPermission('asset:delivery-order:update')") + public CommonResult updateDeliveryOrder(@Valid @RequestBody DeliveryOrderSaveReqVO updateReqVO) { + deliveryOrderService.updateDeliveryOrder(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除交车单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('asset:delivery-order:delete')") + public CommonResult deleteDeliveryOrder(@RequestParam("id") Long id) { + deliveryOrderService.deleteDeliveryOrder(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得交车单详情") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('asset:delivery-order:query')") + public CommonResult getDeliveryOrder(@RequestParam("id") Long id) { + return success(deliveryOrderService.getDeliveryOrderDetail(id)); + } + + @GetMapping("/page") + @Operation(summary = "获得交车单分页") + @PreAuthorize("@ss.hasPermission('asset:delivery-order:query')") + public CommonResult> getDeliveryOrderPage(@Valid DeliveryOrderPageReqVO pageReqVO) { + PageResult pageResult = deliveryOrderService.getDeliveryOrderPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, DeliveryOrderRespVO.class)); + } + + @PutMapping("/complete") + @Operation(summary = "完成交车") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('asset:delivery-order:update')") + public CommonResult completeDeliveryOrder(@RequestParam("id") Long id) { + deliveryOrderService.completeDeliveryOrder(id); + return success(true); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/DeliveryTaskController.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/DeliveryTaskController.java new file mode 100644 index 0000000..f7451c7 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/DeliveryTaskController.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.asset.controller.admin.delivery; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.*; +import cn.iocoder.yudao.module.asset.dal.dataobject.delivery.DeliveryTaskDO; +import cn.iocoder.yudao.module.asset.service.delivery.DeliveryTaskService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import jakarta.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 交车任务") +@RestController +@RequestMapping("/asset/delivery-task") +@Validated +public class DeliveryTaskController { + + @Resource + private DeliveryTaskService deliveryTaskService; + + @PostMapping("/create") + @Operation(summary = "创建交车任务") + @PreAuthorize("@ss.hasPermission('asset:delivery-task:create')") + public CommonResult createDeliveryTask(@Valid @RequestBody DeliveryTaskSaveReqVO createReqVO) { + return success(deliveryTaskService.createDeliveryTask(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新交车任务") + @PreAuthorize("@ss.hasPermission('asset:delivery-task:update')") + public CommonResult updateDeliveryTask(@Valid @RequestBody DeliveryTaskSaveReqVO updateReqVO) { + deliveryTaskService.updateDeliveryTask(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除交车任务") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('asset:delivery-task:delete')") + public CommonResult deleteDeliveryTask(@RequestParam("id") Long id) { + deliveryTaskService.deleteDeliveryTask(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得交车任务详情") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('asset:delivery-task:query')") + public CommonResult getDeliveryTask(@RequestParam("id") Long id) { + return success(deliveryTaskService.getDeliveryTaskDetail(id)); + } + + @GetMapping("/page") + @Operation(summary = "获得交车任务分页") + @PreAuthorize("@ss.hasPermission('asset:delivery-task:query')") + public CommonResult> getDeliveryTaskPage(@Valid DeliveryTaskPageReqVO pageReqVO) { + PageResult pageResult = deliveryTaskService.getDeliveryTaskPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, DeliveryTaskRespVO.class)); + } + + @GetMapping("/contract-page") + @Operation(summary = "获得交车任务按合同分组分页") + @PreAuthorize("@ss.hasPermission('asset:delivery-task:query')") + public CommonResult> getDeliveryTaskContractPage( + @Valid DeliveryTaskPageReqVO pageReqVO) { + return success(deliveryTaskService.getDeliveryTaskContractPage(pageReqVO)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得交车任务精简列表", description = "用于下拉选择") + public CommonResult> getDeliveryTaskSimpleList() { + java.util.List list = deliveryTaskService.getDeliveryTaskSimpleList(); + return success(BeanUtils.toBean(list, DeliveryTaskSimpleRespVO.class)); + } + + @PutMapping("/suspend") + @Operation(summary = "挂起交车任务") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('asset:delivery-task:update')") + public CommonResult suspendDeliveryTask(@RequestParam("id") Long id) { + deliveryTaskService.suspendDeliveryTask(id); + return success(true); + } + + @PutMapping("/activate") + @Operation(summary = "激活交车任务") + @PreAuthorize("@ss.hasPermission('asset:delivery-task:update')") + public CommonResult activateDeliveryTask(@Valid @RequestBody DeliveryTaskActivateReqVO reqVO) { + deliveryTaskService.activateDeliveryTask(reqVO); + return success(true); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryOrderPageReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryOrderPageReqVO.java new file mode 100644 index 0000000..5bcaf8b --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryOrderPageReqVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.asset.controller.admin.delivery.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 交车单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class DeliveryOrderPageReqVO extends PageParam { + + @Schema(description = "交车单编码") + private String orderCode; + + @Schema(description = "任务编码") + private String taskCode; + + @Schema(description = "合同编码") + private String contractCode; + + @Schema(description = "项目名称") + private String projectName; + + @Schema(description = "客户名称") + private String customerName; + + @Schema(description = "交车人") + private String deliveryPerson; + + @Schema(description = "交车地区") + private String deliveryRegion; + + @Schema(description = "状态") + private Integer status; + + @Schema(description = "交车日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] deliveryDate; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryOrderSaveReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryOrderSaveReqVO.java new file mode 100644 index 0000000..8231a63 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryOrderSaveReqVO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.asset.controller.admin.delivery.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - 交车单创建/更新 Request VO") +@Data +public class DeliveryOrderSaveReqVO { + + @Schema(description = "主键") + private Long id; + + @Schema(description = "交车任务ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "交车任务ID不能为空") + private Long taskId; + + @Schema(description = "交车日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "交车日期不能为空") + private LocalDateTime deliveryDate; + + @Schema(description = "交车人", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "交车人不能为空") + private String deliveryPerson; + + @Schema(description = "交车地点") + private String deliveryLocation; + + @Schema(description = "被授权人ID") + private Long authorizedPersonId; + + @Schema(description = "被授权人姓名") + private String authorizedPersonName; + + @Schema(description = "被授权人电话") + private String authorizedPersonPhone; + + @Schema(description = "被授权人身份证") + private String authorizedPersonIdCard; + + @Schema(description = "交车照片") + private String deliveryPhotos; + + @Schema(description = "司机姓名") + private String driverName; + + @Schema(description = "司机身份证") + private String driverIdCard; + + @Schema(description = "司机手机号") + private String driverPhone; + + @Schema(description = "交检清单JSON") + private String inspectionData; + + @Schema(description = "费用信息JSON") + private String costList; + + @Schema(description = "车辆列表") + private List vehicles; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryOrderVehicleVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryOrderVehicleVO.java new file mode 100644 index 0000000..75235df --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryOrderVehicleVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.asset.controller.admin.delivery.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "交车单车辆 VO") +@Data +public class DeliveryOrderVehicleVO { + + @Schema(description = "主键") + private Long id; + + @Schema(description = "交车任务车辆ID") + private Long taskVehicleId; + + @Schema(description = "车辆ID") + private Long vehicleId; + + @Schema(description = "车牌号") + private String plateNo; + + @Schema(description = "VIN码") + private String vin; + + @Schema(description = "品牌") + private String brand; + + @Schema(description = "型号") + private String model; + + @Schema(description = "交车时里程") + private Integer mileage; + + @Schema(description = "交车时氢气量(kg)") + private BigDecimal hydrogenLevel; + + @Schema(description = "交车时电量(%)") + private BigDecimal batteryLevel; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskActivateReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskActivateReqVO.java new file mode 100644 index 0000000..3937c18 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskActivateReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.asset.controller.admin.delivery.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDate; + +@Schema(description = "管理后台 - 交车任务激活 Request VO") +@Data +public class DeliveryTaskActivateReqVO { + + @Schema(description = "任务ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "任务ID不能为空") + private Long id; + + @Schema(description = "预计交车开始日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "预计交车开始日期不能为空") + private LocalDate expectedDeliveryDateStart; + + @Schema(description = "预计交车结束日期") + private LocalDate expectedDeliveryDateEnd; + + @Schema(description = "开始计费日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "开始计费日期不能为空") + private LocalDate billingStartDate; +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskContractGroupRespVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskContractGroupRespVO.java new file mode 100644 index 0000000..f4701c1 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskContractGroupRespVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.asset.controller.admin.delivery.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDate; +import java.util.List; + +@Schema(description = "管理后台 - 交车任务按合同分组 Response VO") +@Data +public class DeliveryTaskContractGroupRespVO { + + @Schema(description = "合同ID") + private Long contractId; + + @Schema(description = "合同编码") + private String contractCode; + + @Schema(description = "项目名称") + private String projectName; + + @Schema(description = "客户名称") + private String customerName; + + @Schema(description = "业务部门名称") + private String businessDeptName; + + @Schema(description = "业务负责人名称") + private String businessManagerName; + + @Schema(description = "合同生效日期") + private LocalDate startDate; + + @Schema(description = "合同结束日期") + private LocalDate endDate; + + @Schema(description = "交车任务列表") + private List tasks; +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskPageReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskPageReqVO.java new file mode 100644 index 0000000..7cc4e3e --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskPageReqVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.asset.controller.admin.delivery.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 交车任务分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class DeliveryTaskPageReqVO extends PageParam { + + @Schema(description = "任务编码") + private String taskCode; + + @Schema(description = "合同编码") + private String contractCode; + + @Schema(description = "项目名称") + private String projectName; + + @Schema(description = "客户名称") + private String customerName; + + @Schema(description = "任务状态") + private Integer taskStatus; + + @Schema(description = "交车状态") + private Integer deliveryStatus; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskRespVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskRespVO.java new file mode 100644 index 0000000..198a383 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskRespVO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.asset.controller.admin.delivery.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - 交车任务 Response VO") +@Data +public class DeliveryTaskRespVO { + + @Schema(description = "主键") + private Long id; + + @Schema(description = "任务编码") + private String taskCode; + + @Schema(description = "合同ID") + private Long contractId; + + @Schema(description = "合同编码") + private String contractCode; + + @Schema(description = "项目名称") + private String projectName; + + @Schema(description = "客户ID") + private Long customerId; + + @Schema(description = "客户名称") + private String customerName; + + @Schema(description = "预计交车开始日期") + private LocalDate expectedDeliveryDateStart; + + @Schema(description = "预计交车结束日期") + private LocalDate expectedDeliveryDateEnd; + + @Schema(description = "开始计费日期") + private LocalDate billingStartDate; + + @Schema(description = "交车省份") + private String deliveryProvince; + + @Schema(description = "交车城市") + private String deliveryCity; + + @Schema(description = "交车地点") + private String deliveryLocation; + + @Schema(description = "交车数量") + private Integer vehicleCount; + + @Schema(description = "任务状态") + private Integer taskStatus; + + @Schema(description = "交车状态") + private Integer deliveryStatus; + + @Schema(description = "是否需要还车") + private Boolean needReturn; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "车辆列表") + private List vehicles; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskSaveReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskSaveReqVO.java new file mode 100644 index 0000000..2bf18a6 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskSaveReqVO.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.asset.controller.admin.delivery.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDate; +import java.util.List; + +@Schema(description = "管理后台 - 交车任务创建/更新 Request VO") +@Data +public class DeliveryTaskSaveReqVO { + + @Schema(description = "主键") + private Long id; + + @Schema(description = "合同ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "合同ID不能为空") + private Long contractId; + + @Schema(description = "合同编码") + private String contractCode; + + @Schema(description = "项目名称") + private String projectName; + + @Schema(description = "客户ID") + private Long customerId; + + @Schema(description = "客户名称") + private String customerName; + + @Schema(description = "预计交车开始日期") + private LocalDate expectedDeliveryDateStart; + + @Schema(description = "预计交车结束日期") + private LocalDate expectedDeliveryDateEnd; + + @Schema(description = "开始计费日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "开始计费日期不能为空") + private LocalDate billingStartDate; + + @Schema(description = "交车省份") + private String deliveryProvince; + + @Schema(description = "交车城市") + private String deliveryCity; + + @Schema(description = "交车地点") + private String deliveryLocation; + + @Schema(description = "是否需要还车") + private Boolean needReturn; + + @Schema(description = "车辆列表") + private List vehicles; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskSimpleRespVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskSimpleRespVO.java new file mode 100644 index 0000000..e10e1fb --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskSimpleRespVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.asset.controller.admin.delivery.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 交车任务精简 Response VO") +@Data +public class DeliveryTaskSimpleRespVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "任务编码", example = "HT-2026-0001JC0001") + private String taskCode; + + @Schema(description = "合同编码", example = "HT-2026-0001") + private String contractCode; + + @Schema(description = "项目名称", example = "XX物流项目") + private String projectName; + + @Schema(description = "客户名称", example = "XX公司") + private String customerName; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskVehicleVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskVehicleVO.java new file mode 100644 index 0000000..fd88aa7 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/delivery/vo/DeliveryTaskVehicleVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.asset.controller.admin.delivery.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "交车任务车辆 VO") +@Data +public class DeliveryTaskVehicleVO { + + @Schema(description = "主键") + private Long id; + + @Schema(description = "合同车辆ID") + private Long contractVehicleId; + + @Schema(description = "车辆ID") + private Long vehicleId; + + @Schema(description = "车牌号") + private String plateNo; + + @Schema(description = "VIN码") + private String vin; + + @Schema(description = "品牌") + private String brand; + + @Schema(description = "型号") + private String model; + + @Schema(description = "月租金") + private BigDecimal monthRent; + + @Schema(description = "保证金") + private BigDecimal deposit; + + @Schema(description = "是否已交车") + private Boolean isDelivered; + + @Schema(description = "实际交车日期") + private java.time.LocalDateTime actualDeliveryDate; + + @Schema(description = "交车人") + private String deliveryPerson; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/prepare/VehiclePrepareController.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/prepare/VehiclePrepareController.java new file mode 100644 index 0000000..a5bbd09 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/prepare/VehiclePrepareController.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.asset.controller.admin.prepare; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.asset.controller.admin.prepare.vo.*; +import cn.iocoder.yudao.module.asset.dal.dataobject.prepare.VehiclePrepareDO; +import cn.iocoder.yudao.module.asset.service.prepare.VehiclePrepareService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import jakarta.validation.Valid; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 备车管理") +@RestController +@RequestMapping("/asset/vehicle-prepare") +@Validated +public class VehiclePrepareController { + + @Resource + private VehiclePrepareService vehiclePrepareService; + + @PostMapping("/create") + @Operation(summary = "创建备车记录") + @PreAuthorize("@ss.hasPermission('asset:vehicle-prepare:create')") + public CommonResult createVehiclePrepare(@Valid @RequestBody VehiclePrepareSaveReqVO createReqVO) { + return success(vehiclePrepareService.createVehiclePrepare(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新备车记录") + @PreAuthorize("@ss.hasPermission('asset:vehicle-prepare:update')") + public CommonResult updateVehiclePrepare(@Valid @RequestBody VehiclePrepareSaveReqVO updateReqVO) { + vehiclePrepareService.updateVehiclePrepare(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除备车记录") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('asset:vehicle-prepare:delete')") + public CommonResult deleteVehiclePrepare(@RequestParam("id") Long id) { + vehiclePrepareService.deleteVehiclePrepare(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得备车记录") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('asset:vehicle-prepare:query')") + public CommonResult getVehiclePrepare(@RequestParam("id") Long id) { + VehiclePrepareDO prepare = vehiclePrepareService.getVehiclePrepare(id); + return success(BeanUtils.toBean(prepare, VehiclePrepareRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得备车记录分页") + @PreAuthorize("@ss.hasPermission('asset:vehicle-prepare:query')") + public CommonResult> getVehiclePreparePage(@Valid VehiclePreparePageReqVO pageReqVO) { + PageResult pageResult = vehiclePrepareService.getVehiclePreparePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, VehiclePrepareRespVO.class)); + } + + @PutMapping("/complete") + @Operation(summary = "完成备车") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('asset:vehicle-prepare:update')") + public CommonResult completeVehiclePrepare(@RequestParam("id") Long id) { + vehiclePrepareService.completeVehiclePrepare(id); + return success(true); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/prepare/vo/VehiclePreparePageReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/prepare/vo/VehiclePreparePageReqVO.java new file mode 100644 index 0000000..4bbffe4 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/prepare/vo/VehiclePreparePageReqVO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.asset.controller.admin.prepare.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 备车记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class VehiclePreparePageReqVO extends PageParam { + + @Schema(description = "车牌号") + private String plateNo; + + @Schema(description = "VIN码") + private String vin; + + @Schema(description = "合同编码") + private String contractCode; + + @Schema(description = "车辆类型") + private String vehicleType; + + @Schema(description = "品牌") + private String brand; + + @Schema(description = "停车场") + private String parkingLot; + + @Schema(description = "状态") + private Integer status; + + @Schema(description = "备车日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] completeTime; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/prepare/vo/VehiclePrepareSaveReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/prepare/vo/VehiclePrepareSaveReqVO.java new file mode 100644 index 0000000..b804a03 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/prepare/vo/VehiclePrepareSaveReqVO.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.asset.controller.admin.prepare.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - 备车记录创建/更新 Request VO") +@Data +public class VehiclePrepareSaveReqVO { + + @Schema(description = "主键") + private Long id; + + @Schema(description = "车辆ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "车辆ID不能为空") + private Long vehicleId; + + @Schema(description = "车牌号") + private String plateNo; + + @Schema(description = "VIN码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "VIN码不能为空") + private String vin; + + @Schema(description = "车型ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "车型ID不能为空") + private Long vehicleModelId; + + @Schema(description = "品牌") + private String brand; + + @Schema(description = "型号") + private String model; + + @Schema(description = "车辆类型") + private String vehicleType; + + @Schema(description = "停车场") + private String parkingLot; + + @Schema(description = "合同ID") + private Long contractId; + + @Schema(description = "合同编码") + private String contractCode; + + @Schema(description = "整备类型") + private String preparationType; + + @Schema(description = "里程(km)") + private Integer mileage; + + @Schema(description = "剩余氢量") + private BigDecimal hydrogenRemaining; + + @Schema(description = "氢量单位") + private String hydrogenUnit; + + @Schema(description = "剩余电量(%)") + private BigDecimal batteryRemaining; + + @Schema(description = "是否有车身广告") + private Boolean hasBodyAd; + + @Schema(description = "广告照片") + private String bodyAdPhotos; + + @Schema(description = "放大字照片") + private String enlargedTextPhoto; + + @Schema(description = "是否有尾板") + private Boolean hasTailLift; + + @Schema(description = "备胎胎纹深度(mm)") + private BigDecimal spareTireDepth; + + @Schema(description = "备胎照片") + private String spareTirePhoto; + + @Schema(description = "挂车牌号") + private String trailerPlateNo; + + @Schema(description = "瑕疵照片") + private String defectPhotos; + + @Schema(description = "检查清单JSON") + private String checkList; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "状态") + private Integer status; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/returnorder/vo/ReturnOrderPageReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/returnorder/vo/ReturnOrderPageReqVO.java new file mode 100644 index 0000000..132c0d5 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/returnorder/vo/ReturnOrderPageReqVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.asset.controller.admin.returnorder.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 还车单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ReturnOrderPageReqVO extends PageParam { + + @Schema(description = "还车单编码") + private String orderCode; + + @Schema(description = "合同编码") + private String contractCode; + + @Schema(description = "客户名称") + private String customerName; + + @Schema(description = "状态") + private Integer status; + + @Schema(description = "还车原因") + private String returnReason; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/returnorder/vo/ReturnOrderRespVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/returnorder/vo/ReturnOrderRespVO.java new file mode 100644 index 0000000..a4b03e2 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/returnorder/vo/ReturnOrderRespVO.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.asset.controller.admin.returnorder.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - 还车单 Response VO") +@Data +public class ReturnOrderRespVO { + + @Schema(description = "主键") + private Long id; + + @Schema(description = "还车单编码") + private String orderCode; + + @Schema(description = "合同ID") + private Long contractId; + + @Schema(description = "合同编码") + private String contractCode; + + @Schema(description = "项目名称") + private String projectName; + + @Schema(description = "客户ID") + private Long customerId; + + @Schema(description = "客户名称") + private String customerName; + + @Schema(description = "还车日期") + private LocalDateTime returnDate; + + @Schema(description = "还车验收人") + private String returnPerson; + + @Schema(description = "还车地点") + private String returnLocation; + + @Schema(description = "还车原因") + private String returnReason; + + @Schema(description = "还车原因说明") + private String returnReasonDesc; + + @Schema(description = "退还总金额") + private BigDecimal totalRefundAmount; + + @Schema(description = "退还保证金") + private BigDecimal depositRefund; + + @Schema(description = "氢气退款") + private BigDecimal hydrogenRefund; + + @Schema(description = "其他费用") + private BigDecimal otherCharges; + + @Schema(description = "还车照片") + private String returnPhotos; + + @Schema(description = "状态") + private Integer status; + + @Schema(description = "审批状态") + private Integer approvalStatus; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "车辆列表") + private List vehicles; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/returnorder/vo/ReturnOrderSaveReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/returnorder/vo/ReturnOrderSaveReqVO.java new file mode 100644 index 0000000..6b31117 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/returnorder/vo/ReturnOrderSaveReqVO.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.asset.controller.admin.returnorder.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - 还车单创建/更新 Request VO") +@Data +public class ReturnOrderSaveReqVO { + + @Schema(description = "主键") + private Long id; + + @Schema(description = "合同ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "合同ID不能为空") + private Long contractId; + + @Schema(description = "合同编码") + private String contractCode; + + @Schema(description = "项目名称") + private String projectName; + + @Schema(description = "客户ID") + private Long customerId; + + @Schema(description = "客户名称") + private String customerName; + + @Schema(description = "还车日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "还车日期不能为空") + private LocalDateTime returnDate; + + @Schema(description = "还车验收人", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "还车验收人不能为空") + private String returnPerson; + + @Schema(description = "还车地点") + private String returnLocation; + + @Schema(description = "还车原因") + private String returnReason; + + @Schema(description = "还车原因说明") + private String returnReasonDesc; + + @Schema(description = "退还保证金") + private BigDecimal depositRefund; + + @Schema(description = "氢气退款") + private BigDecimal hydrogenRefund; + + @Schema(description = "其他费用") + private BigDecimal otherCharges; + + @Schema(description = "还车照片") + private String returnPhotos; + + @Schema(description = "车辆列表") + private List vehicles; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/returnorder/vo/ReturnOrderVehicleVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/returnorder/vo/ReturnOrderVehicleVO.java new file mode 100644 index 0000000..c716e46 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/returnorder/vo/ReturnOrderVehicleVO.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.asset.controller.admin.returnorder.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "还车车辆 VO") +@Data +public class ReturnOrderVehicleVO { + + @Schema(description = "主键") + private Long id; + + @Schema(description = "车辆ID") + private Long vehicleId; + + @Schema(description = "车牌号") + private String plateNo; + + @Schema(description = "VIN码") + private String vin; + + @Schema(description = "品牌") + private String brand; + + @Schema(description = "型号") + private String model; + + @Schema(description = "还车时里程") + private Integer returnMileage; + + @Schema(description = "还车时氢气量") + private BigDecimal returnHydrogenLevel; + + @Schema(description = "交车时氢气量") + private BigDecimal deliveryHydrogenLevel; + + @Schema(description = "氢气差值") + private BigDecimal hydrogenDiff; + + @Schema(description = "氢气单价") + private BigDecimal hydrogenUnitPrice; + + @Schema(description = "氢气退款金额") + private BigDecimal hydrogenRefundAmount; + + @Schema(description = "检查清单JSON") + private String checkList; + + @Schema(description = "瑕疵照片") + private String defectPhotos; + + @Schema(description = "车损费") + private BigDecimal vehicleDamageFee; + + @Schema(description = "工具损坏费") + private BigDecimal toolDamageFee; + + @Schema(description = "未结算保养费") + private BigDecimal unpaidMaintenanceFee; + + @Schema(description = "未结算维修费") + private BigDecimal unpaidRepairFee; + + @Schema(description = "违章费用") + private BigDecimal violationFee; + + @Schema(description = "其他费用") + private BigDecimal otherFee; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/HydrogenStationController.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/HydrogenStationController.java new file mode 100644 index 0000000..12d8a5e --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/HydrogenStationController.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.asset.controller.admin.station; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.asset.controller.admin.station.vo.*; +import cn.iocoder.yudao.module.asset.dal.dataobject.station.HydrogenStationDO; +import cn.iocoder.yudao.module.asset.service.station.HydrogenStationService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +/** + * 加氢站管理 Controller + * + * @author 芋道源码 + */ +@Tag(name = "管理后台 - 加氢站管理") +@RestController +@RequestMapping("/asset/hydrogen-station") +@Validated +public class HydrogenStationController { + + @Resource + private HydrogenStationService hydrogenStationService; + + @PostMapping("/create") + @Operation(summary = "创建加氢站") + @PreAuthorize("@ss.hasPermission('asset:hydrogen-station:create')") + public CommonResult createHydrogenStation(@Valid @RequestBody HydrogenStationSaveReqVO createReqVO) { + return success(hydrogenStationService.createHydrogenStation(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新加氢站") + @PreAuthorize("@ss.hasPermission('asset:hydrogen-station:update')") + public CommonResult updateHydrogenStation(@Valid @RequestBody HydrogenStationSaveReqVO updateReqVO) { + hydrogenStationService.updateHydrogenStation(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除加氢站") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('asset:hydrogen-station:delete')") + public CommonResult deleteHydrogenStation(@RequestParam("id") Long id) { + hydrogenStationService.deleteHydrogenStation(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得加氢站") + @Parameter(name = "id", description = "编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('asset:hydrogen-station:query')") + public CommonResult getHydrogenStation(@RequestParam("id") Long id) { + HydrogenStationDO hydrogenStation = hydrogenStationService.getHydrogenStation(id); + return success(BeanUtils.toBean(hydrogenStation, HydrogenStationRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得加氢站分页") + @PreAuthorize("@ss.hasPermission('asset:hydrogen-station:query')") + public CommonResult> getHydrogenStationPage(@Valid HydrogenStationPageReqVO pageReqVO) { + PageResult pageResult = hydrogenStationService.getHydrogenStationPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, HydrogenStationRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得加氢站精简列表", description = "用于下拉选择") + public CommonResult> getHydrogenStationSimpleList() { + List list = hydrogenStationService.getHydrogenStationSimpleList(); + return success(BeanUtils.toBean(list, HydrogenStationSimpleRespVO.class)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/vo/HydrogenStationBaseVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/vo/HydrogenStationBaseVO.java new file mode 100644 index 0000000..ebb316a --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/vo/HydrogenStationBaseVO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.asset.controller.admin.station.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import java.time.LocalDate; +import java.time.LocalTime; + +/** + * 加氢站 Base VO + * + * @author 芋道源码 + */ +@Data +public class HydrogenStationBaseVO { + + @Schema(description = "站点名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "嘉兴嘉燃经开站") + @NotBlank(message = "站点名称不能为空") + private String name; + + @Schema(description = "简称", example = "经开站") + private String shortName; + + @Schema(description = "站点编码", example = "JX001") + private String stationNo; + + @Schema(description = "所属城市", example = "嘉兴") + private String city; + + @Schema(description = "站点地址", example = "浙江省嘉兴市经济开发区岗山路") + private String address; + + @Schema(description = "经度", example = "120.123456") + @Pattern(regexp = "^-?((0|[1-9]\\d?|1[0-7]\\d)(\\.\\d{1,6})?|180(\\.0{1,6})?)$", message = "经度格式不正确,范围:-180~180") + private String longitude; + + @Schema(description = "纬度", example = "30.123456") + @Pattern(regexp = "^-?((0|[1-8]?\\d)(\\.\\d{1,6})?|90(\\.0{1,6})?)$", message = "纬度格式不正确,范围:-90~90") + private String latitude; + + @Schema(description = "联系人", example = "张三") + private String contact; + + @Schema(description = "联系电话", example = "13800138000") + @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") + private String phone; + + @Schema(description = "站点类型(字典)", example = "1") + private Integer stationType; + + @Schema(description = "合作类型(0=合作 1=非合作)", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "合作类型不能为空") + private Integer cooperationType; + + @Schema(description = "是否自动扣款(1=是 0=否)", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否自动扣款不能为空") + private Boolean autoDeduct; + + @Schema(description = "是否需要预约(1=是 0=否)", example = "false") + private Boolean bookingRequired; + + @Schema(description = "站点状态(0=停用 1=启用)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "站点状态不能为空") + private Integer stationStatus; + + @Schema(description = "开始营业时间", example = "08:00:00") + private LocalTime startBusiness; + + @Schema(description = "结束营业时间", example = "18:00:00") + private LocalTime endBusiness; + + @Schema(description = "结算方式(字典)", example = "1") + private Integer billingMethod; + + @Schema(description = "合作期限", example = "2027-12-31") + private LocalDate cooperationTerm; + + @Schema(description = "备注", example = "合作站点,自动扣款") + private String remark; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/vo/HydrogenStationPageReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/vo/HydrogenStationPageReqVO.java new file mode 100644 index 0000000..a55d6d9 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/vo/HydrogenStationPageReqVO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.asset.controller.admin.station.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 加氢站 - 分页查询 Request VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - 加氢站分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class HydrogenStationPageReqVO extends PageParam { + + @Schema(description = "站点名称", example = "嘉兴嘉燃经开站") + private String name; + + @Schema(description = "站点编码", example = "JX001") + private String stationNo; + + @Schema(description = "所属城市", example = "嘉兴") + private String city; + + @Schema(description = "合作类型(0=合作 1=非合作)", example = "0") + private Integer cooperationType; + + @Schema(description = "站点状态(0=停用 1=启用)", example = "1") + private Integer stationStatus; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/vo/HydrogenStationRespVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/vo/HydrogenStationRespVO.java new file mode 100644 index 0000000..d394477 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/vo/HydrogenStationRespVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.asset.controller.admin.station.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +/** + * 加氢站 - Response VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - 加氢站 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class HydrogenStationRespVO extends HydrogenStationBaseVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/vo/HydrogenStationSaveReqVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/vo/HydrogenStationSaveReqVO.java new file mode 100644 index 0000000..1bad52b --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/vo/HydrogenStationSaveReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.asset.controller.admin.station.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * 加氢站 - 创建/更新 Request VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - 加氢站创建/更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class HydrogenStationSaveReqVO extends HydrogenStationBaseVO { + + @Schema(description = "主键", example = "1") + private Long id; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/vo/HydrogenStationSimpleRespVO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/vo/HydrogenStationSimpleRespVO.java new file mode 100644 index 0000000..eac3b17 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/station/vo/HydrogenStationSimpleRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.asset.controller.admin.station.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 加氢站 - 精简信息 Response VO + * 用于下拉选择 + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - 加氢站精简信息 Response VO") +@Data +public class HydrogenStationSimpleRespVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "站点名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "嘉兴嘉燃经开站") + private String name; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/vehicleregistration/VehicleRegistrationController.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/vehicleregistration/VehicleRegistrationController.java index b69c892..a89efcc 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/vehicleregistration/VehicleRegistrationController.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/controller/admin/vehicleregistration/VehicleRegistrationController.java @@ -21,6 +21,9 @@ import org.springframework.web.multipart.MultipartFile; import jakarta.annotation.Resource; import jakarta.validation.Valid; import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -58,6 +61,23 @@ public class VehicleRegistrationController { return success(result); } + @PostMapping("/ocr") + @Operation(summary = "通过文件URL识别行驶证") + @PreAuthorize("@ss.hasPermission('asset:vehicle-registration:recognize')") + public CommonResult ocrVehicleLicense( + @RequestBody Map body) throws IOException { + String fileUrl = body.get("fileUrl"); + if (fileUrl == null || fileUrl.isBlank()) { + throw new IllegalArgumentException("fileUrl 不能为空"); + } + log.info("[ocrVehicleLicense][通过URL识别行驶证:{}]", fileUrl); + try (InputStream is = URI.create(fileUrl).toURL().openStream()) { + byte[] imageData = is.readAllBytes(); + VehicleLicenseRecognizeRespVO result = vehicleRegistrationService.recognizeVehicleLicense(imageData); + return success(result); + } + } + @PostMapping("/create") @Operation(summary = "创建车辆上牌记录") @PreAuthorize("@ss.hasPermission('asset:vehicle-registration:create')") @@ -99,7 +119,7 @@ public class VehicleRegistrationController { return success(VehicleRegistrationConvert.INSTANCE.convertPage(pageResult)); } - @PostMapping("/confirm") + @PutMapping("/confirm") @Operation(summary = "确认上牌记录(更新车辆信息)") @Parameter(name = "id", description = "上牌记录ID", required = true) @PreAuthorize("@ss.hasPermission('asset:vehicle-registration:update')") @@ -108,4 +128,13 @@ public class VehicleRegistrationController { return success(true); } + @PutMapping("/void") + @Operation(summary = "作废上牌记录") + @Parameter(name = "id", description = "上牌记录ID", required = true) + @PreAuthorize("@ss.hasPermission('asset:vehicle-registration:update')") + public CommonResult voidRegistration(@RequestParam("id") Long id) { + vehicleRegistrationService.voidRegistration(id); + return success(true); + } + } diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/contract/ContractConvert.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/contract/ContractConvert.java new file mode 100644 index 0000000..a5b67f8 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/contract/ContractConvert.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.asset.convert.contract; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.contract.vo.*; +import cn.iocoder.yudao.module.asset.dal.dataobject.contract.*; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 车辆租赁合同 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface ContractConvert { + + ContractConvert INSTANCE = Mappers.getMapper(ContractConvert.class); + + ContractDO convert(ContractSaveReqVO bean); + + ContractRespVO convert(ContractDO bean); + + ContractDetailRespVO convertDetail(ContractDO bean); + + PageResult convertPage(PageResult page); + + List convertVehicleList(List list); + + ContractVehicleDO convertVehicle(ContractSaveReqVO.ContractVehicleSaveVO bean); + + List convertServiceList(List list); + + ContractVehicleServiceDO convertService(ContractVehicleServiceVO bean); + + List convertAuthorizedList(List list); + + ContractAuthorizedDO convertAuthorized(ContractAuthorizedVO bean); + + List convertVehicleDetailList(List list); + + ContractDetailRespVO.ContractVehicleDetailVO convertVehicleDetail(ContractVehicleDO bean); + + List convertServiceVOList(List list); + + List convertAuthorizedVOList(List list); + + List convertAttachmentVOList(List list); + + ContractAttachmentDO convertAttachment(ContractAttachmentVO bean); + + List convertAttachmentList(List list); + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/customer/CustomerConvert.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/customer/CustomerConvert.java index 07cb1fc..acd5150 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/customer/CustomerConvert.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/customer/CustomerConvert.java @@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.asset.dal.dataobject.customer.CustomerDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; +import java.util.List; + /** * 客户 Convert * @@ -23,4 +25,6 @@ public interface CustomerConvert { PageResult convertPage(PageResult page); + List convertList(List list); + } diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/station/HydrogenStationConvert.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/station/HydrogenStationConvert.java new file mode 100644 index 0000000..19ea54d --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/convert/station/HydrogenStationConvert.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.asset.convert.station; + +import cn.iocoder.yudao.module.asset.controller.admin.station.vo.HydrogenStationRespVO; +import cn.iocoder.yudao.module.asset.controller.admin.station.vo.HydrogenStationSimpleRespVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.station.HydrogenStationDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 加氢站 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface HydrogenStationConvert { + + HydrogenStationConvert INSTANCE = Mappers.getMapper(HydrogenStationConvert.class); + + /** + * 转换为响应 VO + */ + HydrogenStationRespVO convert(HydrogenStationDO bean); + + /** + * 转换为精简响应 VO + */ + HydrogenStationSimpleRespVO convertSimple(HydrogenStationDO bean); + + /** + * 批量转换为精简响应 VO + */ + List convertSimpleList(List list); + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractAttachmentDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractAttachmentDO.java new file mode 100644 index 0000000..e3999aa --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractAttachmentDO.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.asset.dal.dataobject.contract; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * 合同附件 DO + * + * @author 芋道源码 + */ +@TableName("asset_contract_attachment") +@KeySequence("asset_contract_attachment_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ContractAttachmentDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + + /** + * 合同ID + */ + private Long contractId; + + /** + * 附件类型(1=合同原件 2=盖章合同) + */ + private Integer attachmentType; + + /** + * 文件ID(关联 infra_file) + */ + private Long fileId; + + /** + * 文件名称 + */ + private String fileName; + + /** + * 文件URL + */ + private String fileUrl; + + /** + * 文件大小(字节) + */ + private Long fileSize; + + /** + * 上传时间 + */ + private LocalDateTime uploadTime; + + /** + * 上传人 + */ + private String uploader; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractAuthorizedDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractAuthorizedDO.java new file mode 100644 index 0000000..ea9d163 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractAuthorizedDO.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.asset.dal.dataobject.contract; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 合同被授权人 DO + * + * @author 芋道源码 + */ +@TableName("asset_contract_authorized") +@KeySequence("asset_contract_authorized_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ContractAuthorizedDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + + /** + * 合同ID + */ + private Long contractId; + + /** + * 姓名 + */ + private String name; + + /** + * 电话 + */ + private String phone; + + /** + * 身份证号 + */ + private String idCard; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractChangeHistoryDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractChangeHistoryDO.java new file mode 100644 index 0000000..6936aa0 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractChangeHistoryDO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.asset.dal.dataobject.contract; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * 合同变更历史 DO + * + * @author 芋道源码 + */ +@TableName("asset_contract_change_history") +@KeySequence("asset_contract_change_history_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ContractChangeHistoryDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + + /** + * 合同ID + */ + private Long contractId; + + /** + * 变更类型 + */ + private String changeType; + + /** + * 变更内容 + */ + private String changeContent; + + /** + * 操作人 + */ + private String operator; + + /** + * 操作时间 + */ + private LocalDateTime operateTime; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractDO.java new file mode 100644 index 0000000..a2d1946 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractDO.java @@ -0,0 +1,199 @@ +package cn.iocoder.yudao.module.asset.dal.dataobject.contract; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * 车辆租赁合同 DO + * + * @author 芋道源码 + */ +@TableName("asset_contract") +@KeySequence("asset_contract_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ContractDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + + /** + * 合同编码 + */ + private String contractCode; + + /** + * 合同类型(1=试用 2=正式) + */ + private Integer contractType; + + /** + * 项目名称 + */ + private String projectName; + + /** + * 生效日期 + */ + private LocalDate startDate; + + /** + * 结束日期 + */ + private LocalDate endDate; + + /** + * 付款方式 + */ + private String paymentMethod; + + /** + * 付款周期 + */ + private String paymentCycle; + + /** + * 签约公司(乙方) + */ + private String signingCompany; + + /** + * 交车省份 + */ + private String deliveryProvince; + + /** + * 交车城市 + */ + private String deliveryCity; + + /** + * 交车地点 + */ + private String deliveryLocation; + + /** + * 备注 + */ + private String remark; + + /** + * 客户ID + */ + private Long customerId; + + /** + * 客户名称(冗余) + */ + private String customerName; + + /** + * 是否三方合同 + */ + private Boolean thirdPartyEnabled; + + /** + * 丙方客户ID + */ + private Long thirdPartyCustomerId; + + /** + * 丙方名称 + */ + private String thirdPartyName; + + /** + * 业务部门ID + */ + private Long businessDeptId; + + /** + * 业务负责人ID + */ + private Long businessManagerId; + + /** + * 审批状态(0=草稿 1=审批中 2=审批通过 3=审批拒绝 4=已撤回) + */ + private Integer approvalStatus; + + /** + * BPM流程实例ID + */ + private String bpmInstanceId; + + /** + * 合同状态(0=草稿 1=待生效 2=进行中 3=已到期 4=已终止 5=已续签) + */ + private Integer contractStatus; + + /** + * 实际生效时间 + */ + private LocalDateTime effectiveTime; + + /** + * 终止时间 + */ + private LocalDateTime terminateTime; + + /** + * 终止原因 + */ + private String terminateReason; + + /** + * 续签后的新合同ID + */ + private Long renewedContractId; + + /** + * 原合同ID(如果是续签合同) + */ + private Long originalContractId; + + /** + * 氢费承担方 + */ + private String hydrogenBearer; + + /** + * 氢气付款方式 + */ + private String hydrogenPaymentMethod; + + /** + * 氢气预付款 + */ + private BigDecimal hydrogenPrepay; + + /** + * 退还车氢气单价 + */ + private BigDecimal hydrogenReturnPrice; + + /** + * 账单计算方式 + */ + private String billingMethod; + + /** + * 主车型 + */ + private String mainVehicleType; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractVehicleDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractVehicleDO.java new file mode 100644 index 0000000..69afe40 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractVehicleDO.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.asset.dal.dataobject.contract; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 合同车辆租赁订单 DO + * + * @author 芋道源码 + */ +@TableName("asset_contract_vehicle") +@KeySequence("asset_contract_vehicle_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ContractVehicleDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + + /** + * 合同ID + */ + private Long contractId; + + /** + * 车辆ID(关联 asset_vehicle_base) + */ + private Long vehicleId; + + /** + * 品牌 + */ + private String brand; + + /** + * 型号 + */ + private String model; + + /** + * 车牌号 + */ + private String plateNo; + + /** + * VIN码 + */ + private String vin; + + /** + * 月租金(元) + */ + private BigDecimal monthRent; + + /** + * 保证金(元) + */ + private BigDecimal deposit; + + /** + * 车辆状态(0=待交车 1=已交车 2=已退车) + */ + private Integer vehicleStatus; + + /** + * 实际交车时间 + */ + private LocalDateTime actualDeliveryTime; + + /** + * 交车人 + */ + private String deliveryPerson; + + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractVehicleServiceDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractVehicleServiceDO.java new file mode 100644 index 0000000..ff91502 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/contract/ContractVehicleServiceDO.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.asset.dal.dataobject.contract; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDate; + +/** + * 合同车辆服务项目 DO + * + * @author 芋道源码 + */ +@TableName("asset_contract_vehicle_service") +@KeySequence("asset_contract_vehicle_service_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ContractVehicleServiceDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + + /** + * 合同车辆ID + */ + private Long contractVehicleId; + + /** + * 服务项目名称 + */ + private String serviceName; + + /** + * 服务费用(元) + */ + private BigDecimal serviceFee; + + /** + * 生效日期 + */ + private LocalDate effectiveDate; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/delivery/DeliveryOrderVehicleDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/delivery/DeliveryOrderVehicleDO.java new file mode 100644 index 0000000..3b5c30f --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/delivery/DeliveryOrderVehicleDO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.asset.dal.dataobject.delivery; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * 交车单车辆 DO + */ +@TableName("asset_delivery_order_vehicle") +@KeySequence("asset_delivery_order_vehicle_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeliveryOrderVehicleDO extends BaseDO { + + @TableId + private Long id; + private Long orderId; + private Long taskVehicleId; + private Long vehicleId; + private String plateNo; + private String vin; + private String brand; + private String model; + private Integer mileage; + private BigDecimal hydrogenLevel; + private BigDecimal batteryLevel; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/delivery/DeliveryTaskDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/delivery/DeliveryTaskDO.java new file mode 100644 index 0000000..70572be --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/delivery/DeliveryTaskDO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.asset.dal.dataobject.delivery; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDate; + +/** + * 交车任务 DO + */ +@TableName("asset_delivery_task") +@KeySequence("asset_delivery_task_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeliveryTaskDO extends BaseDO { + + @TableId + private Long id; + private String taskCode; + private Long contractId; + private String contractCode; + private String projectName; + private Long customerId; + private String customerName; + private LocalDate expectedDeliveryDateStart; + private LocalDate expectedDeliveryDateEnd; + private LocalDate billingStartDate; + private String deliveryProvince; + private String deliveryCity; + private String deliveryLocation; + private Integer vehicleCount; + /** + * 任务状态(0=激活 1=挂起) + */ + private Integer taskStatus; + /** + * 交车状态(0=未交车 1=已交车) + */ + private Integer deliveryStatus; + private Boolean needReturn; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/delivery/DeliveryTaskVehicleDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/delivery/DeliveryTaskVehicleDO.java new file mode 100644 index 0000000..9321acb --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/delivery/DeliveryTaskVehicleDO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.asset.dal.dataobject.delivery; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 交车任务车辆 DO + */ +@TableName("asset_delivery_task_vehicle") +@KeySequence("asset_delivery_task_vehicle_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeliveryTaskVehicleDO extends BaseDO { + + @TableId + private Long id; + private Long taskId; + private Long contractVehicleId; + private Long vehicleId; + private String plateNo; + private String vin; + private String brand; + private String model; + private BigDecimal monthRent; + private BigDecimal deposit; + private LocalDateTime actualDeliveryDate; + private String deliveryPerson; + private Boolean isDelivered; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/station/HydrogenStationDO.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/station/HydrogenStationDO.java new file mode 100644 index 0000000..bf952f2 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/dataobject/station/HydrogenStationDO.java @@ -0,0 +1,128 @@ +package cn.iocoder.yudao.module.asset.dal.dataobject.station; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDate; +import java.time.LocalTime; + +/** + * 加氢站 DO + * + * @author 芋道源码 + */ +@TableName("asset_hydrogen_station") +@KeySequence("asset_hydrogen_station_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class HydrogenStationDO extends BaseDO { + + /** + * 主键 + */ + @TableId + private Long id; + + /** + * 站点名称 + */ + private String name; + + /** + * 简称 + */ + private String shortName; + + /** + * 站点编码 + */ + private String stationNo; + + /** + * 所属城市 + */ + private String city; + + /** + * 站点地址 + */ + private String address; + + /** + * 经度 + */ + private String longitude; + + /** + * 纬度 + */ + private String latitude; + + /** + * 联系人 + */ + private String contact; + + /** + * 联系电话 + */ + private String phone; + + /** + * 站点类型(字典) + */ + private Integer stationType; + + /** + * 合作类型(0=合作 1=非合作) + */ + private Integer cooperationType; + + /** + * 是否自动扣款(1=是 0=否) + */ + private Boolean autoDeduct; + + /** + * 是否需要预约(1=是 0=否) + */ + private Boolean bookingRequired; + + /** + * 站点状态(0=停用 1=启用) + */ + private Integer stationStatus; + + /** + * 开始营业时间 + */ + private LocalTime startBusiness; + + /** + * 结束营业时间 + */ + private LocalTime endBusiness; + + /** + * 结算方式(字典) + */ + private Integer billingMethod; + + /** + * 合作期限 + */ + private LocalDate cooperationTerm; + + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractAttachmentMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractAttachmentMapper.java new file mode 100644 index 0000000..2a14fc8 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractAttachmentMapper.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.contract; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.asset.dal.dataobject.contract.ContractAttachmentDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 合同附件 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ContractAttachmentMapper extends BaseMapperX { + + default List selectListByContractId(Long contractId) { + return selectList(new LambdaQueryWrapperX() + .eq(ContractAttachmentDO::getContractId, contractId) + .orderByAsc(ContractAttachmentDO::getId)); + } + + default int deleteByContractId(Long contractId) { + return delete(new LambdaQueryWrapperX() + .eq(ContractAttachmentDO::getContractId, contractId)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractAuthorizedMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractAuthorizedMapper.java new file mode 100644 index 0000000..4edd95b --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractAuthorizedMapper.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.contract; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.asset.dal.dataobject.contract.ContractAuthorizedDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 合同被授权人 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ContractAuthorizedMapper extends BaseMapperX { + + default List selectListByContractId(Long contractId) { + return selectList(new LambdaQueryWrapperX() + .eq(ContractAuthorizedDO::getContractId, contractId) + .orderByAsc(ContractAuthorizedDO::getId)); + } + + default int deleteByContractId(Long contractId) { + return delete(new LambdaQueryWrapperX() + .eq(ContractAuthorizedDO::getContractId, contractId)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractChangeHistoryMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractChangeHistoryMapper.java new file mode 100644 index 0000000..64c1ac8 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractChangeHistoryMapper.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.contract; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.asset.dal.dataobject.contract.ContractChangeHistoryDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 合同变更历史 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ContractChangeHistoryMapper extends BaseMapperX { + + default List selectListByContractId(Long contractId) { + return selectList(new LambdaQueryWrapperX() + .eq(ContractChangeHistoryDO::getContractId, contractId) + .orderByDesc(ContractChangeHistoryDO::getOperateTime)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractMapper.java new file mode 100644 index 0000000..85e4bca --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractMapper.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.contract; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.asset.controller.admin.contract.vo.ContractPageReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.contract.ContractDO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.time.LocalDate; + +/** + * 车辆租赁合同 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ContractMapper extends BaseMapperX { + + default PageResult selectPage(ContractPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ContractDO::getContractCode, reqVO.getContractCode()) + .eqIfPresent(ContractDO::getContractType, reqVO.getContractType()) + .likeIfPresent(ContractDO::getProjectName, reqVO.getProjectName()) + .eqIfPresent(ContractDO::getCustomerId, reqVO.getCustomerId()) + .likeIfPresent(ContractDO::getCustomerName, reqVO.getCustomerName()) + .eqIfPresent(ContractDO::getApprovalStatus, reqVO.getApprovalStatus()) + .eqIfPresent(ContractDO::getContractStatus, reqVO.getContractStatus()) + .betweenIfPresent(ContractDO::getStartDate, reqVO.getStartDate()) + .betweenIfPresent(ContractDO::getEndDate, reqVO.getEndDate()) + .eqIfPresent(ContractDO::getBusinessDeptId, reqVO.getBusinessDeptId()) + .eqIfPresent(ContractDO::getSigningCompany, reqVO.getSigningCompany()) + .eqIfPresent(ContractDO::getBusinessManagerId, reqVO.getBusinessManagerId()) + .likeIfPresent(ContractDO::getCreator, reqVO.getCreator()) + .orderByDesc(ContractDO::getId)); + } + + @Select("SELECT contract_code FROM asset_contract WHERE contract_code LIKE CONCAT(#{prefix}, '%') AND deleted = 0 ORDER BY contract_code DESC LIMIT 1") + String selectMaxContractCodeByPrefix(@Param("prefix") String prefix); + + /** + * 检查车辆在指定时间段内是否有有效合同 + */ + @Select("SELECT COUNT(*) FROM asset_contract c " + + "INNER JOIN asset_contract_vehicle cv ON c.id = cv.contract_id " + + "WHERE cv.vehicle_id = #{vehicleId} " + + "AND c.contract_status IN (1, 2) " + + "AND c.deleted = 0 AND cv.deleted = 0 " + + "AND NOT (c.end_date < #{startDate} OR c.start_date > #{endDate})") + int countActiveContractsByVehicleAndDateRange(@Param("vehicleId") Long vehicleId, + @Param("startDate") LocalDate startDate, + @Param("endDate") LocalDate endDate); + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractVehicleMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractVehicleMapper.java new file mode 100644 index 0000000..4ff23be --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractVehicleMapper.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.contract; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.asset.dal.dataobject.contract.ContractVehicleDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 合同车辆租赁订单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ContractVehicleMapper extends BaseMapperX { + + default List selectListByContractId(Long contractId) { + return selectList(new LambdaQueryWrapperX() + .eq(ContractVehicleDO::getContractId, contractId) + .orderByAsc(ContractVehicleDO::getId)); + } + + default int deleteByContractId(Long contractId) { + return delete(new LambdaQueryWrapperX() + .eq(ContractVehicleDO::getContractId, contractId)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractVehicleServiceMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractVehicleServiceMapper.java new file mode 100644 index 0000000..9e64c11 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/contract/ContractVehicleServiceMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.contract; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.asset.dal.dataobject.contract.ContractVehicleServiceDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 合同车辆服务项目 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ContractVehicleServiceMapper extends BaseMapperX { + + default List selectListByContractVehicleId(Long contractVehicleId) { + return selectList(new LambdaQueryWrapperX() + .eq(ContractVehicleServiceDO::getContractVehicleId, contractVehicleId) + .orderByAsc(ContractVehicleServiceDO::getId)); + } + + default int deleteByContractVehicleId(Long contractVehicleId) { + return delete(new LambdaQueryWrapperX() + .eq(ContractVehicleServiceDO::getContractVehicleId, contractVehicleId)); + } + + default int deleteByContractVehicleIds(List contractVehicleIds) { + return delete(new LambdaQueryWrapperX() + .in(ContractVehicleServiceDO::getContractVehicleId, contractVehicleIds)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/delivery/DeliveryOrderMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/delivery/DeliveryOrderMapper.java new file mode 100644 index 0000000..36706a2 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/delivery/DeliveryOrderMapper.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.delivery; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.DeliveryOrderPageReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.delivery.DeliveryOrderDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface DeliveryOrderMapper extends BaseMapperX { + + default PageResult selectPage(DeliveryOrderPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(DeliveryOrderDO::getOrderCode, reqVO.getOrderCode()) + .likeIfPresent(DeliveryOrderDO::getTaskCode, reqVO.getTaskCode()) + .likeIfPresent(DeliveryOrderDO::getContractCode, reqVO.getContractCode()) + .likeIfPresent(DeliveryOrderDO::getProjectName, reqVO.getProjectName()) + .likeIfPresent(DeliveryOrderDO::getCustomerName, reqVO.getCustomerName()) + .likeIfPresent(DeliveryOrderDO::getDeliveryPerson, reqVO.getDeliveryPerson()) + .eqIfPresent(DeliveryOrderDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(DeliveryOrderDO::getDeliveryDate, reqVO.getDeliveryDate()) + .betweenIfPresent(DeliveryOrderDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(DeliveryOrderDO::getId)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/delivery/DeliveryOrderVehicleMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/delivery/DeliveryOrderVehicleMapper.java new file mode 100644 index 0000000..35f0bc9 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/delivery/DeliveryOrderVehicleMapper.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.delivery; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.asset.dal.dataobject.delivery.DeliveryOrderVehicleDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface DeliveryOrderVehicleMapper extends BaseMapperX { + + default List selectListByOrderId(Long orderId) { + return selectList(DeliveryOrderVehicleDO::getOrderId, orderId); + } + + default void deleteByOrderId(Long orderId) { + delete(DeliveryOrderVehicleDO::getOrderId, orderId); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/delivery/DeliveryTaskMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/delivery/DeliveryTaskMapper.java new file mode 100644 index 0000000..da4512c --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/delivery/DeliveryTaskMapper.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.delivery; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.DeliveryTaskPageReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.delivery.DeliveryTaskDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface DeliveryTaskMapper extends BaseMapperX { + + default PageResult selectPage(DeliveryTaskPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(DeliveryTaskDO::getTaskCode, reqVO.getTaskCode()) + .likeIfPresent(DeliveryTaskDO::getContractCode, reqVO.getContractCode()) + .likeIfPresent(DeliveryTaskDO::getProjectName, reqVO.getProjectName()) + .likeIfPresent(DeliveryTaskDO::getCustomerName, reqVO.getCustomerName()) + .eqIfPresent(DeliveryTaskDO::getTaskStatus, reqVO.getTaskStatus()) + .eqIfPresent(DeliveryTaskDO::getDeliveryStatus, reqVO.getDeliveryStatus()) + .betweenIfPresent(DeliveryTaskDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(DeliveryTaskDO::getId)); + } + + default long selectCountByContractId(Long contractId) { + return selectCount(DeliveryTaskDO::getContractId, contractId); + } + + default List selectListByFilters(DeliveryTaskPageReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(DeliveryTaskDO::getTaskCode, reqVO.getTaskCode()) + .likeIfPresent(DeliveryTaskDO::getContractCode, reqVO.getContractCode()) + .likeIfPresent(DeliveryTaskDO::getProjectName, reqVO.getProjectName()) + .likeIfPresent(DeliveryTaskDO::getCustomerName, reqVO.getCustomerName()) + .eqIfPresent(DeliveryTaskDO::getTaskStatus, reqVO.getTaskStatus()) + .eqIfPresent(DeliveryTaskDO::getDeliveryStatus, reqVO.getDeliveryStatus()) + .betweenIfPresent(DeliveryTaskDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(DeliveryTaskDO::getId)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/delivery/DeliveryTaskVehicleMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/delivery/DeliveryTaskVehicleMapper.java new file mode 100644 index 0000000..d9ab106 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/delivery/DeliveryTaskVehicleMapper.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.delivery; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.asset.dal.dataobject.delivery.DeliveryTaskVehicleDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface DeliveryTaskVehicleMapper extends BaseMapperX { + + default List selectListByTaskId(Long taskId) { + return selectList(DeliveryTaskVehicleDO::getTaskId, taskId); + } + + default void deleteByTaskId(Long taskId) { + delete(DeliveryTaskVehicleDO::getTaskId, taskId); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/prepare/VehiclePrepareMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/prepare/VehiclePrepareMapper.java new file mode 100644 index 0000000..9da985f --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/prepare/VehiclePrepareMapper.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.prepare; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.asset.controller.admin.prepare.vo.VehiclePreparePageReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.prepare.VehiclePrepareDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface VehiclePrepareMapper extends BaseMapperX { + + default PageResult selectPage(VehiclePreparePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(VehiclePrepareDO::getPlateNo, reqVO.getPlateNo()) + .likeIfPresent(VehiclePrepareDO::getVin, reqVO.getVin()) + .likeIfPresent(VehiclePrepareDO::getContractCode, reqVO.getContractCode()) + .eqIfPresent(VehiclePrepareDO::getVehicleType, reqVO.getVehicleType()) + .likeIfPresent(VehiclePrepareDO::getBrand, reqVO.getBrand()) + .likeIfPresent(VehiclePrepareDO::getParkingLot, reqVO.getParkingLot()) + .eqIfPresent(VehiclePrepareDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(VehiclePrepareDO::getCompleteTime, reqVO.getCompleteTime()) + .betweenIfPresent(VehiclePrepareDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(VehiclePrepareDO::getId)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/returnorder/ReturnOrderMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/returnorder/ReturnOrderMapper.java new file mode 100644 index 0000000..7d3b9ab --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/returnorder/ReturnOrderMapper.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.returnorder; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.asset.controller.admin.returnorder.vo.ReturnOrderPageReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.returnorder.ReturnOrderDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ReturnOrderMapper extends BaseMapperX { + + default PageResult selectPage(ReturnOrderPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ReturnOrderDO::getOrderCode, reqVO.getOrderCode()) + .likeIfPresent(ReturnOrderDO::getContractCode, reqVO.getContractCode()) + .likeIfPresent(ReturnOrderDO::getCustomerName, reqVO.getCustomerName()) + .eqIfPresent(ReturnOrderDO::getStatus, reqVO.getStatus()) + .eqIfPresent(ReturnOrderDO::getReturnReason, reqVO.getReturnReason()) + .betweenIfPresent(ReturnOrderDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ReturnOrderDO::getId)); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/returnorder/ReturnOrderVehicleMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/returnorder/ReturnOrderVehicleMapper.java new file mode 100644 index 0000000..b71b928 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/returnorder/ReturnOrderVehicleMapper.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.returnorder; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.asset.dal.dataobject.returnorder.ReturnOrderVehicleDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface ReturnOrderVehicleMapper extends BaseMapperX { + + default List selectListByReturnOrderId(Long returnOrderId) { + return selectList(ReturnOrderVehicleDO::getReturnOrderId, returnOrderId); + } + + default void deleteByReturnOrderId(Long returnOrderId) { + delete(ReturnOrderVehicleDO::getReturnOrderId, returnOrderId); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/station/HydrogenStationMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/station/HydrogenStationMapper.java new file mode 100644 index 0000000..89aa481 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/station/HydrogenStationMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.asset.dal.mysql.station; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.asset.controller.admin.station.vo.HydrogenStationPageReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.station.HydrogenStationDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 加氢站 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface HydrogenStationMapper extends BaseMapperX { + + default PageResult selectPage(HydrogenStationPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(HydrogenStationDO::getName, reqVO.getName()) + .likeIfPresent(HydrogenStationDO::getStationNo, reqVO.getStationNo()) + .likeIfPresent(HydrogenStationDO::getCity, reqVO.getCity()) + .eqIfPresent(HydrogenStationDO::getCooperationType, reqVO.getCooperationType()) + .eqIfPresent(HydrogenStationDO::getStationStatus, reqVO.getStationStatus()) + .betweenIfPresent(HydrogenStationDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(HydrogenStationDO::getId)); + } + + default List selectSimpleList() { + return selectList(); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/vehicle/VehicleStatusMapper.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/vehicle/VehicleStatusMapper.java index a908239..f039ba1 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/vehicle/VehicleStatusMapper.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/dal/mysql/vehicle/VehicleStatusMapper.java @@ -20,4 +20,9 @@ public interface VehicleStatusMapper extends BaseMapperX { .in(VehicleStatusDO::getVehicleId, vehicleIds)); } + default VehicleStatusDO selectByVehicleId(Long vehicleId) { + return selectOne(new LambdaQueryWrapperX() + .eq(VehicleStatusDO::getVehicleId, vehicleId)); + } + } diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/enums/ErrorCodeConstants.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/enums/ErrorCodeConstants.java index eb49df4..7e44a80 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/enums/ErrorCodeConstants.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/enums/ErrorCodeConstants.java @@ -38,7 +38,8 @@ public interface ErrorCodeConstants { ErrorCode CONTRACT_STATUS_NOT_ALLOW_ADD_VEHICLE = new ErrorCode(1_008_005_011, "当前合同状态不允许新增车辆"); ErrorCode CONTRACT_TYPE_NOT_TRIAL = new ErrorCode(1_008_005_012, "只有试用合同才能转正式"); - // ========== 车辆登记 1-008-006-000 ========== + // ========== 车辆基础信息 1-008-006-000 ========== + ErrorCode VEHICLE_NOT_EXISTS = new ErrorCode(1_008_006_001, "车辆不存在"); ErrorCode VEHICLE_REGISTRATION_NOT_EXISTS = new ErrorCode(1_008_006_000, "车辆登记不存在"); // ========== 备车管理 1-008-007-000 ========== @@ -78,4 +79,8 @@ public interface ErrorCodeConstants { ErrorCode VEHICLE_REPLACEMENT_STATUS_NOT_ALLOW_WITHDRAW = new ErrorCode(1_008_012_004, "当前状态不允许撤回"); ErrorCode VEHICLE_REPLACEMENT_STATUS_NOT_ALLOW_CONFIRM = new ErrorCode(1_008_012_005, "当前状态不允许确认换回"); + // ========== 加氢站管理 1-008-013-000 ========== + ErrorCode HYDROGEN_STATION_NOT_EXISTS = new ErrorCode(1_008_013_000, "加氢站不存在"); + ErrorCode HYDROGEN_STATION_END_BUSINESS_BEFORE_START_BUSINESS = new ErrorCode(1_008_013_001, "结束营业时间不能早于开始营业时间"); + } diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/job/ContractStatusJob.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/job/ContractStatusJob.java new file mode 100644 index 0000000..75192c4 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/job/ContractStatusJob.java @@ -0,0 +1,106 @@ +package cn.iocoder.yudao.module.asset.job; + +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; +import cn.iocoder.yudao.module.asset.dal.dataobject.contract.ContractDO; +import cn.iocoder.yudao.module.asset.dal.mysql.contract.ContractMapper; +import cn.iocoder.yudao.module.asset.enums.contract.ContractStatusEnum; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.xxl.job.core.handler.annotation.XxlJob; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import jakarta.annotation.Resource; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 合同状态自动流转定时任务 + * + * 功能: + * 1. 将待生效的合同自动转为进行中(当前日期 >= 生效日期) + * 2. 将进行中的合同自动转为已到期(当前日期 > 结束日期) + * + * @author 芋道源码 + */ +@Component +@Slf4j +public class ContractStatusJob { + + @Resource + private ContractMapper contractMapper; + + @XxlJob("contractStatusJob") + @TenantJob + public void execute() { + log.info("[contractStatusJob] 开始执行合同状态自动流转"); + + try { + // 1. 处理待生效 -> 进行中 + int activatedCount = activatePendingContracts(); + log.info("[contractStatusJob] 激活待生效合同数量: {}", activatedCount); + + // 2. 处理进行中 -> 已到期 + int expiredCount = expireActiveContracts(); + log.info("[contractStatusJob] 到期合同数量: {}", expiredCount); + + log.info("[contractStatusJob] 执行完成,激活: {}, 到期: {}", activatedCount, expiredCount); + } catch (Exception e) { + log.error("[contractStatusJob] 执行失败", e); + } + } + + /** + * 激活待生效的合同 + */ + private int activatePendingContracts() { + LocalDate today = LocalDate.now(); + + // 查询待生效且生效日期 <= 今天的合同 + List contracts = contractMapper.selectList( + new LambdaQueryWrapper() + .eq(ContractDO::getContractStatus, ContractStatusEnum.PENDING.getStatus()) + .le(ContractDO::getStartDate, today) + ); + + int count = 0; + for (ContractDO contract : contracts) { + ContractDO updateObj = new ContractDO(); + updateObj.setId(contract.getId()); + updateObj.setContractStatus(ContractStatusEnum.IN_PROGRESS.getStatus()); + updateObj.setEffectiveTime(LocalDateTime.now()); + contractMapper.updateById(updateObj); + count++; + log.info("[contractStatusJob] 合同 {} 已激活", contract.getContractCode()); + } + + return count; + } + + /** + * 将进行中的合同标记为已到期 + */ + private int expireActiveContracts() { + LocalDate today = LocalDate.now(); + + // 查询进行中且结束日期 < 今天的合同 + List contracts = contractMapper.selectList( + new LambdaQueryWrapper() + .eq(ContractDO::getContractStatus, ContractStatusEnum.IN_PROGRESS.getStatus()) + .lt(ContractDO::getEndDate, today) + ); + + int count = 0; + for (ContractDO contract : contracts) { + ContractDO updateObj = new ContractDO(); + updateObj.setId(contract.getId()); + updateObj.setContractStatus(ContractStatusEnum.EXPIRED.getStatus()); + contractMapper.updateById(updateObj); + count++; + log.info("[contractStatusJob] 合同 {} 已到期", contract.getContractCode()); + } + + return count; + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/contract/ContractService.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/contract/ContractService.java new file mode 100644 index 0000000..f699d5f --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/contract/ContractService.java @@ -0,0 +1,145 @@ +package cn.iocoder.yudao.module.asset.service.contract; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.contract.vo.*; +import cn.iocoder.yudao.module.asset.dal.dataobject.contract.ContractDO; + +import jakarta.validation.Valid; +import java.util.List; + +/** + * 车辆租赁合同 Service 接口 + * + * @author 芋道源码 + */ +public interface ContractService { + + /** + * 创建合同 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createContract(@Valid ContractSaveReqVO createReqVO); + + /** + * 更新合同 + * + * @param updateReqVO 更新信息 + */ + void updateContract(@Valid ContractSaveReqVO updateReqVO); + + /** + * 删除合同 + * + * @param id 编号 + */ + void deleteContract(Long id); + + /** + * 获得合同 + * + * @param id 编号 + * @return 合同 + */ + ContractDO getContract(Long id); + + /** + * 获得合同分页 + * + * @param pageReqVO 分页查询 + * @return 合同分页 + */ + PageResult getContractPage(ContractPageReqVO pageReqVO); + + /** + * 提交合同审批 + * + * @param id 合同ID + * @return 流程实例ID + */ + String submitContractApproval(Long id); + + /** + * 更新合同审批状态 + * + * @param id 合同ID + * @param status 审批状态 + */ + void updateContractApprovalStatus(Long id, Integer status); + + /** + * 撤回合同审批 + * + * @param id 合同ID + */ + void withdrawContractApproval(Long id); + + /** + * 终止合同 + * + * @param id 合同ID + * @param reason 终止原因 + */ + void terminateContract(Long id, String reason); + + /** + * 续签合同 + * + * @param id 原合同ID + * @param newContractReqVO 新合同信息 + * @return 新合同ID + */ + Long renewContract(Long id, ContractSaveReqVO newContractReqVO); + + /** + * 获取合同详情(包含关联数据) + * + * @param id 合同ID + * @return 合同详情 + */ + ContractDetailRespVO getContractDetail(Long id); + + /** + * 获得合同精简列表(用于下拉选择) + * + * @return 合同列表 + */ + List getContractSimpleList(); + + /** + * 变更为三方合同 + * + * @param id 原合同ID + * @param newContractReqVO 新合同信息 + * @return 新合同ID + */ + Long convertToThirdParty(Long id, @Valid ContractSaveReqVO newContractReqVO); + + /** + * 试用合同转正式 + * + * @param id 原合同ID + * @param newContractReqVO 新合同信息 + * @return 新合同ID + */ + Long convertToFormal(Long id, @Valid ContractSaveReqVO newContractReqVO); + + /** + * 往现有合同追加车辆 + * + * @param id 合同ID + * @param vehicles 车辆列表 + */ + void addVehiclesToContract(Long id, List vehicles); + + /** + * 上传盖章合同附件 + * + * @param id 合同ID + * @param fileUrl 文件URL + * @param fileName 文件名 + */ + void uploadSealedContract(Long id, String fileUrl, String fileName); + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/contract/ContractServiceImpl.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/contract/ContractServiceImpl.java new file mode 100644 index 0000000..08b3a9e --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/contract/ContractServiceImpl.java @@ -0,0 +1,609 @@ +package cn.iocoder.yudao.module.asset.service.contract; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.contract.vo.*; +import cn.iocoder.yudao.module.asset.convert.contract.ContractConvert; +import cn.iocoder.yudao.module.asset.dal.dataobject.contract.*; +import cn.iocoder.yudao.module.asset.dal.mysql.contract.*; +import cn.iocoder.yudao.module.asset.enums.contract.ContractApprovalStatusEnum; +import cn.iocoder.yudao.module.asset.enums.contract.ContractStatusEnum; +import cn.iocoder.yudao.module.asset.service.contract.listener.ContractBpmListener; +import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCancelReqDTO; +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import jakarta.annotation.Resource; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.asset.enums.ErrorCodeConstants.*; + +/** + * 车辆租赁合同 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +@Slf4j +public class ContractServiceImpl implements ContractService { + + @Resource + private ContractMapper contractMapper; + + @Resource + private ContractVehicleMapper contractVehicleMapper; + + @Resource + private ContractVehicleServiceMapper contractVehicleServiceMapper; + + @Resource + private ContractAuthorizedMapper contractAuthorizedMapper; + + @Resource + private ContractAttachmentMapper contractAttachmentMapper; + + @Resource + private ContractChangeHistoryMapper contractChangeHistoryMapper; + + @Resource + private BpmProcessInstanceApi bpmProcessInstanceApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createContract(ContractSaveReqVO createReqVO) { + // 校验合同日期 + validateContractDate(createReqVO.getStartDate(), createReqVO.getEndDate()); + + // 转换并插入合同主表 + ContractDO contract = ContractConvert.INSTANCE.convert(createReqVO); + + // 生成合同编码 + if (contract.getContractCode() == null || contract.getContractCode().isEmpty()) { + contract.setContractCode(generateContractCode()); + } + + // 设置初始状态 + contract.setApprovalStatus(ContractApprovalStatusEnum.DRAFT.getStatus()); + contract.setContractStatus(0); // 草稿 + + contractMapper.insert(contract); + + // 保存车辆订单 + saveContractVehicles(contract.getId(), createReqVO.getVehicles()); + + // 保存被授权人 + saveContractAuthorized(contract.getId(), createReqVO.getAuthorizedPersons()); + + // 记录变更历史 + saveChangeHistory(contract.getId(), "创建合同", "创建合同:" + contract.getContractCode()); + + return contract.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateContract(ContractSaveReqVO updateReqVO) { + // 校验存在 + ContractDO existContract = validateContractExists(updateReqVO.getId()); + + // 校验状态:只有草稿、审批拒绝、已撤回状态才能修改 + if (!canEdit(existContract.getApprovalStatus())) { + throw exception(CONTRACT_STATUS_NOT_ALLOW_UPDATE); + } + + // 校验合同日期 + validateContractDate(updateReqVO.getStartDate(), updateReqVO.getEndDate()); + + // 转换并更新合同主表 + ContractDO updateObj = ContractConvert.INSTANCE.convert(updateReqVO); + contractMapper.updateById(updateObj); + + // 更新车辆订单:先删除旧的,再插入新的 + List oldVehicles = contractVehicleMapper.selectListByContractId(updateReqVO.getId()); + List oldVehicleIds = oldVehicles.stream().map(ContractVehicleDO::getId).collect(Collectors.toList()); + if (!oldVehicleIds.isEmpty()) { + contractVehicleServiceMapper.deleteByContractVehicleIds(oldVehicleIds); + } + contractVehicleMapper.deleteByContractId(updateReqVO.getId()); + saveContractVehicles(updateReqVO.getId(), updateReqVO.getVehicles()); + + // 更新被授权人:先删除旧的,再插入新的 + contractAuthorizedMapper.deleteByContractId(updateReqVO.getId()); + saveContractAuthorized(updateReqVO.getId(), updateReqVO.getAuthorizedPersons()); + + // 记录变更历史 + saveChangeHistory(updateReqVO.getId(), "更新合同", "更新合同信息"); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteContract(Long id) { + // 校验存在 + ContractDO contract = validateContractExists(id); + + // 校验状态:只有草稿、审批拒绝、已撤回状态才能删除 + if (!canEdit(contract.getApprovalStatus())) { + throw exception(CONTRACT_STATUS_NOT_ALLOW_DELETE); + } + + // 删除合同主表 + contractMapper.deleteById(id); + + // 删除关联数据 + List vehicles = contractVehicleMapper.selectListByContractId(id); + List vehicleIds = vehicles.stream().map(ContractVehicleDO::getId).collect(Collectors.toList()); + if (!vehicleIds.isEmpty()) { + contractVehicleServiceMapper.deleteByContractVehicleIds(vehicleIds); + } + contractVehicleMapper.deleteByContractId(id); + contractAuthorizedMapper.deleteByContractId(id); + contractAttachmentMapper.deleteByContractId(id); + + // 记录变更历史 + saveChangeHistory(id, "删除合同", "删除合同:" + contract.getContractCode()); + } + + @Override + public ContractDO getContract(Long id) { + return contractMapper.selectById(id); + } + + @Override + public PageResult getContractPage(ContractPageReqVO pageReqVO) { + return contractMapper.selectPage(pageReqVO); + } + + // ==================== 私有方法 ==================== + + /** + * 校验合同是否存在 + */ + private ContractDO validateContractExists(Long id) { + ContractDO contract = contractMapper.selectById(id); + if (contract == null) { + throw exception(CONTRACT_NOT_EXISTS); + } + return contract; + } + + /** + * 校验合同日期 + */ + private void validateContractDate(java.time.LocalDate startDate, java.time.LocalDate endDate) { + if (startDate != null && endDate != null && endDate.isBefore(startDate)) { + throw exception(CONTRACT_END_DATE_BEFORE_START_DATE); + } + } + + /** + * 判断是否可以编辑 + */ + private boolean canEdit(Integer approvalStatus) { + return ContractApprovalStatusEnum.DRAFT.getStatus().equals(approvalStatus) + || ContractApprovalStatusEnum.REJECTED.getStatus().equals(approvalStatus) + || ContractApprovalStatusEnum.WITHDRAWN.getStatus().equals(approvalStatus); + } + + /** + * 生成合同编码 + */ + private String generateContractCode() { + // 格式:HT-YYYY-NNNN + String year = String.valueOf(java.time.LocalDate.now().getYear()); + + // 查询当年最大序号 + String prefix = "HT-" + year + "-"; + String maxCode = contractMapper.selectMaxContractCodeByPrefix(prefix); + + int nextSeq = 1; + if (maxCode != null && maxCode.startsWith(prefix)) { + try { + String seqStr = maxCode.substring(prefix.length()); + nextSeq = Integer.parseInt(seqStr) + 1; + } catch (Exception e) { + log.warn("解析合同编码失败: {}", maxCode, e); + } + } + + return prefix + String.format("%04d", nextSeq); + } + + /** + * 保存车辆订单 + */ + private void saveContractVehicles(Long contractId, List vehicles) { + if (vehicles == null || vehicles.isEmpty()) { + return; + } + + // 获取合同信息用于校验 + ContractDO contract = contractMapper.selectById(contractId); + + for (ContractSaveReqVO.ContractVehicleSaveVO vehicleVO : vehicles) { + // 校验车辆时间冲突 + if (vehicleVO.getVehicleId() != null && contract != null) { + validateVehicleTimeConflict(vehicleVO.getVehicleId(), contract.getStartDate(), contract.getEndDate(), contractId); + } + + // 保存车辆订单 + ContractVehicleDO vehicle = ContractConvert.INSTANCE.convertVehicle(vehicleVO); + vehicle.setContractId(contractId); + contractVehicleMapper.insert(vehicle); + + // 保存服务项目 + if (vehicleVO.getServices() != null && !vehicleVO.getServices().isEmpty()) { + List services = ContractConvert.INSTANCE.convertServiceList(vehicleVO.getServices()); + for (ContractVehicleServiceDO service : services) { + service.setContractVehicleId(vehicle.getId()); + contractVehicleServiceMapper.insert(service); + } + } + } + } + + /** + * 校验车辆时间冲突 + */ + private void validateVehicleTimeConflict(Long vehicleId, java.time.LocalDate startDate, java.time.LocalDate endDate, Long excludeContractId) { + int count = contractMapper.countActiveContractsByVehicleAndDateRange(vehicleId, startDate, endDate); + if (count > 0) { + throw exception(CONTRACT_VEHICLE_TIME_CONFLICT); + } + } + + /** + * 保存被授权人 + */ + private void saveContractAuthorized(Long contractId, List authorizedPersons) { + if (authorizedPersons == null || authorizedPersons.isEmpty()) { + return; + } + + List authorizedList = ContractConvert.INSTANCE.convertAuthorizedList(authorizedPersons); + for (ContractAuthorizedDO authorized : authorizedList) { + authorized.setContractId(contractId); + contractAuthorizedMapper.insert(authorized); + } + } + + /** + * 保存变更历史 + */ + private void saveChangeHistory(Long contractId, String changeType, String changeContent) { + ContractChangeHistoryDO history = new ContractChangeHistoryDO(); + history.setContractId(contractId); + history.setChangeType(changeType); + history.setChangeContent(changeContent); + + // 获取当前登录用户 + Long userId = SecurityFrameworkUtils.getLoginUserId(); + history.setOperator(userId != null ? String.valueOf(userId) : "system"); + history.setOperateTime(LocalDateTime.now()); + + contractChangeHistoryMapper.insert(history); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public String submitContractApproval(Long id) { + // 校验存在 + ContractDO contract = validateContractExists(id); + + // 校验状态:只有草稿、审批拒绝、已撤回状态才能提交审批 + if (!canEdit(contract.getApprovalStatus())) { + throw exception(CONTRACT_STATUS_NOT_ALLOW_SUBMIT); + } + + // 创建流程变量 + Map variables = new HashMap<>(); + variables.put("contractCode", contract.getContractCode()); + variables.put("projectName", contract.getProjectName()); + variables.put("customerName", contract.getCustomerName()); + variables.put("startDate", contract.getStartDate()); + variables.put("endDate", contract.getEndDate()); + + // 创建流程实例 + BpmProcessInstanceCreateReqDTO reqDTO = new BpmProcessInstanceCreateReqDTO(); + reqDTO.setProcessDefinitionKey(ContractBpmListener.PROCESS_KEY); + reqDTO.setBusinessKey(String.valueOf(id)); + reqDTO.setVariables(variables); + + Long userId = SecurityFrameworkUtils.getLoginUserId(); + String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, reqDTO).getData(); + + // 更新合同状态 + ContractDO updateObj = new ContractDO(); + updateObj.setId(id); + updateObj.setApprovalStatus(ContractApprovalStatusEnum.APPROVING.getStatus()); + updateObj.setBpmInstanceId(processInstanceId); + contractMapper.updateById(updateObj); + + // 记录变更历史 + saveChangeHistory(id, "提交审批", "提交合同审批,流程实例ID:" + processInstanceId); + + return processInstanceId; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateContractApprovalStatus(Long id, Integer status) { + // 校验存在 + ContractDO contract = validateContractExists(id); + + // 更新审批状态 + ContractDO updateObj = new ContractDO(); + updateObj.setId(id); + + // 根据 BPM 状态映射到合同审批状态 + if (BpmProcessInstanceStatusEnum.RUNNING.getStatus().equals(status)) { + updateObj.setApprovalStatus(ContractApprovalStatusEnum.APPROVING.getStatus()); + } else if (BpmProcessInstanceStatusEnum.APPROVE.getStatus().equals(status)) { + updateObj.setApprovalStatus(ContractApprovalStatusEnum.APPROVED.getStatus()); + updateObj.setContractStatus(ContractStatusEnum.PENDING.getStatus()); // 待生效 + updateObj.setEffectiveTime(LocalDateTime.now()); + } else if (BpmProcessInstanceStatusEnum.REJECT.getStatus().equals(status)) { + updateObj.setApprovalStatus(ContractApprovalStatusEnum.REJECTED.getStatus()); + } else if (BpmProcessInstanceStatusEnum.CANCEL.getStatus().equals(status)) { + updateObj.setApprovalStatus(ContractApprovalStatusEnum.WITHDRAWN.getStatus()); + } + + contractMapper.updateById(updateObj); + + // 记录变更历史 + String changeContent = "审批状态变更:" + getApprovalStatusName(updateObj.getApprovalStatus()); + saveChangeHistory(id, "审批状态变更", changeContent); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void withdrawContractApproval(Long id) { + // 校验存在 + ContractDO contract = validateContractExists(id); + + // 校验状态:只有审批中状态才能撤回 + if (!ContractApprovalStatusEnum.APPROVING.getStatus().equals(contract.getApprovalStatus())) { + throw exception(CONTRACT_STATUS_NOT_ALLOW_WITHDRAW); + } + + // 调用 BPM API 取消流程实例 + if (contract.getBpmInstanceId() != null) { + BpmProcessInstanceCancelReqDTO cancelReqDTO = new BpmProcessInstanceCancelReqDTO(); + cancelReqDTO.setId(contract.getBpmInstanceId()); + cancelReqDTO.setReason("合同审批撤回"); + Long userId = SecurityFrameworkUtils.getLoginUserId(); + bpmProcessInstanceApi.cancelProcessInstance(userId, cancelReqDTO); + } + + // 更新合同状态 + ContractDO updateObj = new ContractDO(); + updateObj.setId(id); + updateObj.setApprovalStatus(ContractApprovalStatusEnum.WITHDRAWN.getStatus()); + contractMapper.updateById(updateObj); + + // 记录变更历史 + saveChangeHistory(id, "撤回审批", "撤回合同审批"); + } + + /** + * 获取审批状态名称 + */ + private String getApprovalStatusName(Integer status) { + ContractApprovalStatusEnum statusEnum = ContractApprovalStatusEnum.valueOf(status); + return statusEnum != null ? statusEnum.getName() : "未知"; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void terminateContract(Long id, String reason) { + // 校验存在 + ContractDO contract = validateContractExists(id); + + // 校验状态:只有进行中的合同才能终止 + if (!ContractStatusEnum.IN_PROGRESS.getStatus().equals(contract.getContractStatus())) { + throw exception(CONTRACT_STATUS_NOT_ALLOW_TERMINATE); + } + + // 更新合同状态 + ContractDO updateObj = new ContractDO(); + updateObj.setId(id); + updateObj.setContractStatus(ContractStatusEnum.TERMINATED.getStatus()); + updateObj.setTerminateTime(LocalDateTime.now()); + updateObj.setTerminateReason(reason); + contractMapper.updateById(updateObj); + + // 记录变更历史 + saveChangeHistory(id, "终止合同", "终止合同,原因:" + reason); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long renewContract(Long id, ContractSaveReqVO newContractReqVO) { + // 校验原合同存在 + ContractDO oldContract = validateContractExists(id); + + // 校验状态:只有进行中或已到期的合同才能续签 + if (!ContractStatusEnum.IN_PROGRESS.getStatus().equals(oldContract.getContractStatus()) + && !ContractStatusEnum.EXPIRED.getStatus().equals(oldContract.getContractStatus())) { + throw exception(CONTRACT_STATUS_NOT_ALLOW_RENEW); + } + + // 创建新合同 + Long newContractId = createContract(newContractReqVO); + + // 更新原合同状态 + ContractDO updateObj = new ContractDO(); + updateObj.setId(id); + updateObj.setContractStatus(ContractStatusEnum.RENEWED.getStatus()); + updateObj.setRenewedContractId(newContractId); + contractMapper.updateById(updateObj); + + // 更新新合同的原合同ID + ContractDO newContract = new ContractDO(); + newContract.setId(newContractId); + newContract.setOriginalContractId(id); + contractMapper.updateById(newContract); + + // 记录变更历史 + saveChangeHistory(id, "续签合同", "续签合同,新合同ID:" + newContractId); + saveChangeHistory(newContractId, "续签合同", "由合同ID " + id + " 续签而来"); + + return newContractId; + } + + @Override + public List getContractSimpleList() { + return contractMapper.selectList(); + } + + @Override + public ContractDetailRespVO getContractDetail(Long id) { + ContractDO contract = validateContractExists(id); + ContractDetailRespVO result = ContractConvert.INSTANCE.convertDetail(contract); + + // 查询车辆订单 + List vehicles = contractVehicleMapper.selectListByContractId(id); + List vehicleDetails = ContractConvert.INSTANCE.convertVehicleDetailList(vehicles); + + // 查询每个车辆的服务项目 + for (int i = 0; i < vehicles.size(); i++) { + List services = contractVehicleServiceMapper.selectListByContractVehicleId(vehicles.get(i).getId()); + vehicleDetails.get(i).setServices(ContractConvert.INSTANCE.convertServiceVOList(services)); + } + result.setVehicles(vehicleDetails); + + // 查询被授权人 + List authorized = contractAuthorizedMapper.selectListByContractId(id); + result.setAuthorizedPersons(ContractConvert.INSTANCE.convertAuthorizedVOList(authorized)); + + // 查询附件 + List attachments = contractAttachmentMapper.selectListByContractId(id); + result.setAttachments(ContractConvert.INSTANCE.convertAttachmentVOList(attachments)); + + return result; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long convertToThirdParty(Long id, ContractSaveReqVO newContractReqVO) { + // 校验原合同存在且进行中 + ContractDO oldContract = validateContractExists(id); + if (!ContractStatusEnum.IN_PROGRESS.getStatus().equals(oldContract.getContractStatus())) { + throw exception(CONTRACT_STATUS_NOT_ALLOW_CONVERT); + } + + // 设置三方合同标记 + newContractReqVO.setThirdPartyEnabled(true); + + // 创建新合同 + Long newContractId = createContract(newContractReqVO); + + // 更新新合同的原合同ID + ContractDO newContract = new ContractDO(); + newContract.setId(newContractId); + newContract.setOriginalContractId(id); + contractMapper.updateById(newContract); + + // 终止原合同 + ContractDO updateObj = new ContractDO(); + updateObj.setId(id); + updateObj.setContractStatus(ContractStatusEnum.TERMINATED.getStatus()); + updateObj.setTerminateTime(LocalDateTime.now()); + updateObj.setTerminateReason("变更为三方合同"); + contractMapper.updateById(updateObj); + + // 记录变更历史 + saveChangeHistory(id, "变更为三方", "变更为三方合同,新合同ID:" + newContractId); + saveChangeHistory(newContractId, "变更为三方", "由合同ID " + id + " 变更而来"); + + return newContractId; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long convertToFormal(Long id, ContractSaveReqVO newContractReqVO) { + // 校验原合同存在且进行中 + ContractDO oldContract = validateContractExists(id); + if (!ContractStatusEnum.IN_PROGRESS.getStatus().equals(oldContract.getContractStatus())) { + throw exception(CONTRACT_STATUS_NOT_ALLOW_CONVERT); + } + // 校验原合同为试用合同 + if (!Integer.valueOf(1).equals(oldContract.getContractType())) { + throw exception(CONTRACT_TYPE_NOT_TRIAL); + } + + // 设置为正式合同 + newContractReqVO.setContractType(2); + + // 创建新合同 + Long newContractId = createContract(newContractReqVO); + + // 更新新合同的原合同ID + ContractDO newContract = new ContractDO(); + newContract.setId(newContractId); + newContract.setOriginalContractId(id); + contractMapper.updateById(newContract); + + // 终止原合同 + ContractDO updateObj = new ContractDO(); + updateObj.setId(id); + updateObj.setContractStatus(ContractStatusEnum.TERMINATED.getStatus()); + updateObj.setTerminateTime(LocalDateTime.now()); + updateObj.setTerminateReason("转正式合同"); + contractMapper.updateById(updateObj); + + // 记录变更历史 + saveChangeHistory(id, "转正式", "转正式合同,新合同ID:" + newContractId); + saveChangeHistory(newContractId, "转正式", "由试用合同ID " + id + " 转正式而来"); + + return newContractId; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void addVehiclesToContract(Long id, List vehicles) { + // 校验合同存在且进行中 + ContractDO contract = validateContractExists(id); + if (!ContractStatusEnum.IN_PROGRESS.getStatus().equals(contract.getContractStatus())) { + throw exception(CONTRACT_STATUS_NOT_ALLOW_ADD_VEHICLE); + } + + // 追加车辆 + saveContractVehicles(id, vehicles); + + // 记录变更历史 + saveChangeHistory(id, "新增车辆", "追加 " + vehicles.size() + " 辆车辆"); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void uploadSealedContract(Long id, String fileUrl, String fileName) { + // 校验合同存在 + validateContractExists(id); + + // 创建附件记录 + ContractAttachmentDO attachment = new ContractAttachmentDO(); + attachment.setContractId(id); + attachment.setAttachmentType(2); // 盖章合同 + attachment.setFileName(fileName); + attachment.setFileUrl(fileUrl); + attachment.setUploadTime(LocalDateTime.now()); + Long userId = SecurityFrameworkUtils.getLoginUserId(); + attachment.setUploader(userId != null ? String.valueOf(userId) : "system"); + contractAttachmentMapper.insert(attachment); + + // 记录变更历史 + saveChangeHistory(id, "上传盖章合同", "上传盖章合同附件:" + fileName); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/contract/listener/ContractBpmListener.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/contract/listener/ContractBpmListener.java new file mode 100644 index 0000000..9130194 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/contract/listener/ContractBpmListener.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.asset.service.contract.listener; + +import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent; +import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEventListener; +import cn.iocoder.yudao.module.asset.service.contract.ContractService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +/** + * 车辆租赁合同审批状态监听器 + * + * @author 芋道源码 + */ +@Component +public class ContractBpmListener extends BpmProcessInstanceStatusEventListener { + + /** + * 流程定义 Key + */ + public static final String PROCESS_KEY = "asset_contract"; + + @Resource + private ContractService contractService; + + @Override + protected String getProcessDefinitionKey() { + return PROCESS_KEY; + } + + @Override + protected void onEvent(BpmProcessInstanceStatusEvent event) { + contractService.updateContractApprovalStatus(Long.parseLong(event.getBusinessKey()), event.getStatus()); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerService.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerService.java index b11f2a8..d04d609 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerService.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerService.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.asset.controller.admin.customer.vo.CustomerSaveRe import cn.iocoder.yudao.module.asset.dal.dataobject.customer.CustomerDO; import jakarta.validation.Valid; +import java.util.List; /** * 客户信息 Service 接口 @@ -52,4 +53,11 @@ public interface CustomerService { */ PageResult getCustomerPage(CustomerPageReqVO pageReqVO); + /** + * 获得客户精简列表(用于下拉选择) + * + * @return 客户列表 + */ + List getCustomerSimpleList(); + } diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerServiceImpl.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerServiceImpl.java index b64f3a6..6c19266 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerServiceImpl.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/customer/CustomerServiceImpl.java @@ -98,6 +98,11 @@ public class CustomerServiceImpl implements CustomerService { return customerMapper.selectPage(pageReqVO); } + @Override + public List getCustomerSimpleList() { + return customerMapper.selectList(); + } + /** * 生成客户编号 */ diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/delivery/DeliveryOrderService.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/delivery/DeliveryOrderService.java new file mode 100644 index 0000000..44801d3 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/delivery/DeliveryOrderService.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.asset.service.delivery; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.DeliveryOrderPageReqVO; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.DeliveryOrderRespVO; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.DeliveryOrderSaveReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.delivery.DeliveryOrderDO; + +import jakarta.validation.Valid; + +public interface DeliveryOrderService { + + Long createDeliveryOrder(@Valid DeliveryOrderSaveReqVO createReqVO); + + void updateDeliveryOrder(@Valid DeliveryOrderSaveReqVO updateReqVO); + + void deleteDeliveryOrder(Long id); + + DeliveryOrderDO getDeliveryOrder(Long id); + + DeliveryOrderRespVO getDeliveryOrderDetail(Long id); + + PageResult getDeliveryOrderPage(DeliveryOrderPageReqVO pageReqVO); + + void completeDeliveryOrder(Long id); + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/delivery/DeliveryOrderServiceImpl.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/delivery/DeliveryOrderServiceImpl.java index c77498f..b013435 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/delivery/DeliveryOrderServiceImpl.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/delivery/DeliveryOrderServiceImpl.java @@ -8,6 +8,8 @@ import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionRecordD import cn.iocoder.yudao.module.asset.dal.mysql.delivery.*; import cn.iocoder.yudao.module.asset.enums.inspection.InspectionSourceTypeEnum; import cn.iocoder.yudao.module.asset.service.inspection.InspectionRecordService; +import cn.iocoder.yudao.module.asset.service.delivery.event.DeliveryCompletedEvent; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -37,6 +39,9 @@ public class DeliveryOrderServiceImpl implements DeliveryOrderService { @Resource private InspectionRecordService inspectionRecordService; + @Resource + private ApplicationEventPublisher eventPublisher; + @Override @Transactional(rollbackFor = Exception.class) public Long createDeliveryOrder(DeliveryOrderSaveReqVO createReqVO) { @@ -169,6 +174,11 @@ public class DeliveryOrderServiceImpl implements DeliveryOrderService { deliveryTaskMapper.updateById(DeliveryTaskDO.builder().id(task.getId()).deliveryStatus(1).build()); } } + + // Publish delivery completed events for each vehicle + for (DeliveryOrderVehicleDO ov : orderVehicles) { + eventPublisher.publishEvent(new DeliveryCompletedEvent(id, ov.getVehicleId())); + } } private DeliveryOrderDO validateDeliveryOrderExists(Long id) { diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/delivery/DeliveryTaskService.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/delivery/DeliveryTaskService.java new file mode 100644 index 0000000..4c4c689 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/delivery/DeliveryTaskService.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.asset.service.delivery; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.DeliveryTaskActivateReqVO; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.DeliveryTaskContractGroupRespVO; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.DeliveryTaskPageReqVO; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.DeliveryTaskRespVO; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.DeliveryTaskSaveReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.delivery.DeliveryTaskDO; + +import jakarta.validation.Valid; +import java.util.List; + +public interface DeliveryTaskService { + + Long createDeliveryTask(@Valid DeliveryTaskSaveReqVO createReqVO); + + void updateDeliveryTask(@Valid DeliveryTaskSaveReqVO updateReqVO); + + void deleteDeliveryTask(Long id); + + DeliveryTaskDO getDeliveryTask(Long id); + + DeliveryTaskRespVO getDeliveryTaskDetail(Long id); + + PageResult getDeliveryTaskPage(DeliveryTaskPageReqVO pageReqVO); + + void suspendDeliveryTask(Long id); + + void activateDeliveryTask(Long id); + + /** + * 激活交车任务(带日期参数) + */ + void activateDeliveryTask(DeliveryTaskActivateReqVO reqVO); + + /** + * 获得按合同分组的交车任务分页 + */ + PageResult getDeliveryTaskContractPage(DeliveryTaskPageReqVO pageReqVO); + + List getDeliveryTaskSimpleList(); + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/delivery/DeliveryTaskServiceImpl.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/delivery/DeliveryTaskServiceImpl.java new file mode 100644 index 0000000..36bcef2 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/delivery/DeliveryTaskServiceImpl.java @@ -0,0 +1,264 @@ +package cn.iocoder.yudao.module.asset.service.delivery; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.*; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.DeliveryTaskActivateReqVO; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.DeliveryTaskContractGroupRespVO; +import cn.iocoder.yudao.module.asset.controller.admin.delivery.vo.DeliveryTaskVehicleVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.contract.ContractDO; +import cn.iocoder.yudao.module.asset.dal.dataobject.delivery.DeliveryTaskDO; +import cn.iocoder.yudao.module.asset.dal.dataobject.delivery.DeliveryTaskVehicleDO; +import cn.iocoder.yudao.module.asset.dal.mysql.contract.ContractMapper; +import cn.iocoder.yudao.module.asset.dal.mysql.delivery.DeliveryTaskMapper; +import cn.iocoder.yudao.module.asset.dal.mysql.delivery.DeliveryTaskVehicleMapper; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import jakarta.annotation.Resource; +import java.util.*; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.asset.enums.ErrorCodeConstants.*; + +@Service +@Validated +public class DeliveryTaskServiceImpl implements DeliveryTaskService { + + @Resource + private DeliveryTaskMapper deliveryTaskMapper; + + @Resource + private DeliveryTaskVehicleMapper deliveryTaskVehicleMapper; + + @Resource + private ContractMapper contractMapper; + + @Resource + private DeptApi deptApi; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createDeliveryTask(DeliveryTaskSaveReqVO createReqVO) { + // 校验合同是否存在 + if (contractMapper.selectById(createReqVO.getContractId()) == null) { + throw exception(CONTRACT_NOT_EXISTS); + } + + // Generate task code: contractCode + JC + sequence + String taskCode = generateTaskCode(createReqVO.getContractId(), createReqVO.getContractCode()); + + DeliveryTaskDO task = BeanUtils.toBean(createReqVO, DeliveryTaskDO.class); + task.setTaskCode(taskCode); + task.setTaskStatus(0); // active + task.setDeliveryStatus(0); // not delivered + task.setVehicleCount(createReqVO.getVehicles() != null ? createReqVO.getVehicles().size() : 0); + deliveryTaskMapper.insert(task); + + // Insert vehicles + if (createReqVO.getVehicles() != null) { + for (DeliveryTaskVehicleVO vehicleVO : createReqVO.getVehicles()) { + DeliveryTaskVehicleDO vehicle = BeanUtils.toBean(vehicleVO, DeliveryTaskVehicleDO.class); + vehicle.setTaskId(task.getId()); + vehicle.setIsDelivered(false); + deliveryTaskVehicleMapper.insert(vehicle); + } + } + + return task.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateDeliveryTask(DeliveryTaskSaveReqVO updateReqVO) { + DeliveryTaskDO task = validateDeliveryTaskExists(updateReqVO.getId()); + if (task.getDeliveryStatus().equals(1)) { + throw exception(DELIVERY_TASK_ALREADY_DELIVERED); + } + + DeliveryTaskDO updateObj = BeanUtils.toBean(updateReqVO, DeliveryTaskDO.class); + updateObj.setVehicleCount(updateReqVO.getVehicles() != null ? updateReqVO.getVehicles().size() : 0); + deliveryTaskMapper.updateById(updateObj); + + // Update vehicles: delete old, insert new + if (updateReqVO.getVehicles() != null) { + deliveryTaskVehicleMapper.deleteByTaskId(updateReqVO.getId()); + for (DeliveryTaskVehicleVO vehicleVO : updateReqVO.getVehicles()) { + DeliveryTaskVehicleDO vehicle = BeanUtils.toBean(vehicleVO, DeliveryTaskVehicleDO.class); + vehicle.setTaskId(updateReqVO.getId()); + vehicle.setIsDelivered(false); + deliveryTaskVehicleMapper.insert(vehicle); + } + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteDeliveryTask(Long id) { + validateDeliveryTaskExists(id); + deliveryTaskMapper.deleteById(id); + deliveryTaskVehicleMapper.deleteByTaskId(id); + } + + @Override + public DeliveryTaskDO getDeliveryTask(Long id) { + return deliveryTaskMapper.selectById(id); + } + + @Override + public DeliveryTaskRespVO getDeliveryTaskDetail(Long id) { + DeliveryTaskDO task = validateDeliveryTaskExists(id); + DeliveryTaskRespVO respVO = BeanUtils.toBean(task, DeliveryTaskRespVO.class); + List vehicles = deliveryTaskVehicleMapper.selectListByTaskId(id); + respVO.setVehicles(BeanUtils.toBean(vehicles, DeliveryTaskVehicleVO.class)); + return respVO; + } + + @Override + public PageResult getDeliveryTaskPage(DeliveryTaskPageReqVO pageReqVO) { + return deliveryTaskMapper.selectPage(pageReqVO); + } + + @Override + public void suspendDeliveryTask(Long id) { + DeliveryTaskDO task = validateDeliveryTaskExists(id); + if (task.getDeliveryStatus().equals(1)) { + throw exception(DELIVERY_TASK_ALREADY_DELIVERED); + } + deliveryTaskMapper.updateById(DeliveryTaskDO.builder().id(id).taskStatus(1).build()); + } + + @Override + public void activateDeliveryTask(Long id) { + validateDeliveryTaskExists(id); + deliveryTaskMapper.updateById(DeliveryTaskDO.builder().id(id).taskStatus(0).build()); + } + + @Override + public void activateDeliveryTask(DeliveryTaskActivateReqVO reqVO) { + validateDeliveryTaskExists(reqVO.getId()); + DeliveryTaskDO updateObj = DeliveryTaskDO.builder() + .id(reqVO.getId()) + .taskStatus(0) + .expectedDeliveryDateStart(reqVO.getExpectedDeliveryDateStart()) + .expectedDeliveryDateEnd(reqVO.getExpectedDeliveryDateEnd()) + .billingStartDate(reqVO.getBillingStartDate()) + .build(); + deliveryTaskMapper.updateById(updateObj); + } + + @Override + public PageResult getDeliveryTaskContractPage(DeliveryTaskPageReqVO pageReqVO) { + // 1. 查询所有匹配的交车任务 + List allTasks = deliveryTaskMapper.selectListByFilters(pageReqVO); + if (allTasks.isEmpty()) { + return new PageResult<>(Collections.emptyList(), 0L); + } + + // 2. 按合同 ID 分组 + Map> groupedByContract = allTasks.stream() + .collect(Collectors.groupingBy(DeliveryTaskDO::getContractId, + LinkedHashMap::new, Collectors.toList())); + + // 3. 对合同分组进行分页 + List contractIds = new ArrayList<>(groupedByContract.keySet()); + long total = contractIds.size(); + int start = (pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize(); + int end = Math.min(start + pageReqVO.getPageSize(), contractIds.size()); + if (start >= contractIds.size()) { + return new PageResult<>(Collections.emptyList(), total); + } + List pageContractIds = contractIds.subList(start, end); + + // 4. 批量查询合同信息 + List contracts = contractMapper.selectBatchIds(pageContractIds); + Map contractMap = contracts.stream() + .collect(Collectors.toMap(ContractDO::getId, c -> c, (a, b) -> a)); + + // 5. 批量查询部门和用户名称 + Set deptIds = new HashSet<>(); + Set userIds = new HashSet<>(); + contracts.forEach(c -> { + if (c.getBusinessDeptId() != null) deptIds.add(c.getBusinessDeptId()); + if (c.getBusinessManagerId() != null) userIds.add(c.getBusinessManagerId()); + }); + Map deptMap = deptIds.isEmpty() ? Collections.emptyMap() : deptApi.getDeptMap(deptIds); + Map userMap = userIds.isEmpty() ? Collections.emptyMap() : adminUserApi.getUserMap(userIds); + + // 6. 批量查询车辆信息(用于 popover 展示) + List taskIds = pageContractIds.stream() + .flatMap(cid -> groupedByContract.get(cid).stream()) + .map(DeliveryTaskDO::getId) + .toList(); + List allVehicles = taskIds.isEmpty() ? Collections.emptyList() + : deliveryTaskVehicleMapper.selectList( + new cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX() + .in(DeliveryTaskVehicleDO::getTaskId, taskIds)); + Map> vehiclesByTask = allVehicles.stream() + .collect(Collectors.groupingBy(DeliveryTaskVehicleDO::getTaskId)); + + // 7. 组装响应 + List result = new ArrayList<>(); + for (Long contractId : pageContractIds) { + DeliveryTaskContractGroupRespVO group = new DeliveryTaskContractGroupRespVO(); + ContractDO contract = contractMap.get(contractId); + if (contract != null) { + group.setContractId(contract.getId()); + group.setContractCode(contract.getContractCode()); + group.setProjectName(contract.getProjectName()); + group.setCustomerName(contract.getCustomerName()); + group.setStartDate(contract.getStartDate()); + group.setEndDate(contract.getEndDate()); + DeptRespDTO dept = deptMap.get(contract.getBusinessDeptId()); + group.setBusinessDeptName(dept != null ? dept.getName() : null); + AdminUserRespDTO user = userMap.get(contract.getBusinessManagerId()); + group.setBusinessManagerName(user != null ? user.getNickname() : null); + } else { + DeliveryTaskDO firstTask = groupedByContract.get(contractId).get(0); + group.setContractId(contractId); + group.setContractCode(firstTask.getContractCode()); + group.setProjectName(firstTask.getProjectName()); + group.setCustomerName(firstTask.getCustomerName()); + } + + List taskVOs = groupedByContract.get(contractId).stream().map(task -> { + DeliveryTaskRespVO vo = BeanUtils.toBean(task, DeliveryTaskRespVO.class); + List vehicles = vehiclesByTask.getOrDefault(task.getId(), Collections.emptyList()); + vo.setVehicles(BeanUtils.toBean(vehicles, DeliveryTaskVehicleVO.class)); + return vo; + }).toList(); + group.setTasks(taskVOs); + result.add(group); + } + + return new PageResult<>(result, total); + } + + @Override + public List getDeliveryTaskSimpleList() { + return deliveryTaskMapper.selectList(); + } + + private DeliveryTaskDO validateDeliveryTaskExists(Long id) { + DeliveryTaskDO task = deliveryTaskMapper.selectById(id); + if (task == null) { + throw exception(DELIVERY_TASK_NOT_EXISTS); + } + return task; + } + + private String generateTaskCode(Long contractId, String contractCode) { + long count = deliveryTaskMapper.selectCountByContractId(contractId); + return contractCode + "JC" + String.format("%04d", count + 1); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/event/VehicleStatusEventListener.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/event/VehicleStatusEventListener.java index 7589082..ea6bae2 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/event/VehicleStatusEventListener.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/event/VehicleStatusEventListener.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.asset.service.event; +import cn.iocoder.yudao.module.asset.dal.dataobject.vehicle.VehicleStatusDO; +import cn.iocoder.yudao.module.asset.dal.mysql.vehicle.VehicleStatusMapper; import cn.iocoder.yudao.module.asset.service.delivery.event.DeliveryCompletedEvent; import cn.iocoder.yudao.module.asset.service.replacement.event.ReplacementReturnConfirmedEvent; import cn.iocoder.yudao.module.asset.service.returnorder.event.ReturnApprovedEvent; @@ -7,6 +9,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.transaction.event.TransactionalEventListener; +import jakarta.annotation.Resource; +import java.util.List; + /** * 车辆状态事件监听器 * 负责在业务事件发生时更新车辆状态 @@ -17,22 +22,68 @@ import org.springframework.transaction.event.TransactionalEventListener; @Slf4j public class VehicleStatusEventListener { + @Resource + private VehicleStatusMapper vehicleStatusMapper; + + /** + * 交车完成:更新车辆库位状态为「已交付车-租赁交车」,标记已交车 + */ @TransactionalEventListener public void onDeliveryCompleted(DeliveryCompletedEvent event) { - log.info("[onDeliveryCompleted] vehicleId={}", event.getVehicleId()); - // TODO: update vehicle status to DELIVERED when vehicle status management is implemented + log.info("[onDeliveryCompleted] deliveryOrderId={}, vehicleId={}", event.getDeliveryOrderId(), event.getVehicleId()); + VehicleStatusDO vehicleStatus = vehicleStatusMapper.selectByVehicleId(event.getVehicleId()); + if (vehicleStatus == null) { + log.warn("[onDeliveryCompleted] vehicle status not found, vehicleId={}", event.getVehicleId()); + return; + } + vehicleStatusMapper.updateById(VehicleStatusDO.builder() + .id(vehicleStatus.getId()) + .storageStatus(5) // 已交付车-租赁交车 + .operateStatus(2) // 租赁 + .isDelivered(true) + .build()); } + /** + * 还车审批通过:更新所有还车车辆的库位状态为「库存车-可交付车」,标记已还车 + */ @TransactionalEventListener public void onReturnApproved(ReturnApprovedEvent event) { - log.info("[onReturnApproved] vehicleIds={}", event.getVehicleIds()); - // TODO: update vehicle status to AVAILABLE when vehicle status management is implemented + log.info("[onReturnApproved] returnOrderId={}, vehicleIds={}", event.getReturnOrderId(), event.getVehicleIds()); + List vehicleIds = event.getVehicleIds(); + if (vehicleIds == null || vehicleIds.isEmpty()) { + return; + } + List vehicleStatuses = vehicleStatusMapper.selectByVehicleIds(vehicleIds); + for (VehicleStatusDO vehicleStatus : vehicleStatuses) { + vehicleStatusMapper.updateById(VehicleStatusDO.builder() + .id(vehicleStatus.getId()) + .storageStatus(2) // 库存车-可交付车 + .operateStatus(1) // 库存 + .isReturned(true) + .isDelivered(false) + .build()); + } } + /** + * 替换车换回确认:更新原车辆库位状态为「库存车-可交付车」 + */ @TransactionalEventListener public void onReplacementReturnConfirmed(ReplacementReturnConfirmedEvent event) { - log.info("[onReplacementReturnConfirmed] vehicleId={}", event.getOriginalVehicleId()); - // TODO: update vehicle status to AVAILABLE + log.info("[onReplacementReturnConfirmed] replacementId={}, originalVehicleId={}", + event.getReplacementId(), event.getOriginalVehicleId()); + VehicleStatusDO vehicleStatus = vehicleStatusMapper.selectByVehicleId(event.getOriginalVehicleId()); + if (vehicleStatus == null) { + log.warn("[onReplacementReturnConfirmed] vehicle status not found, vehicleId={}", event.getOriginalVehicleId()); + return; + } + vehicleStatusMapper.updateById(VehicleStatusDO.builder() + .id(vehicleStatus.getId()) + .storageStatus(2) // 库存车-可交付车 + .operateStatus(1) // 库存 + .isDelivered(false) + .build()); } } diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/prepare/VehiclePrepareService.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/prepare/VehiclePrepareService.java new file mode 100644 index 0000000..ad26dd2 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/prepare/VehiclePrepareService.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.asset.service.prepare; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.prepare.vo.VehiclePreparePageReqVO; +import cn.iocoder.yudao.module.asset.controller.admin.prepare.vo.VehiclePrepareSaveReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.prepare.VehiclePrepareDO; + +import jakarta.validation.Valid; + +public interface VehiclePrepareService { + + Long createVehiclePrepare(@Valid VehiclePrepareSaveReqVO createReqVO); + + void updateVehiclePrepare(@Valid VehiclePrepareSaveReqVO updateReqVO); + + void deleteVehiclePrepare(Long id); + + VehiclePrepareDO getVehiclePrepare(Long id); + + PageResult getVehiclePreparePage(VehiclePreparePageReqVO pageReqVO); + + void completeVehiclePrepare(Long id); + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/prepare/VehiclePrepareServiceImpl.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/prepare/VehiclePrepareServiceImpl.java index df93d32..4a3630b 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/prepare/VehiclePrepareServiceImpl.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/prepare/VehiclePrepareServiceImpl.java @@ -6,7 +6,9 @@ import cn.iocoder.yudao.module.asset.controller.admin.prepare.vo.VehiclePrepareP import cn.iocoder.yudao.module.asset.controller.admin.prepare.vo.VehiclePrepareSaveReqVO; import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionTemplateDO; import cn.iocoder.yudao.module.asset.dal.dataobject.prepare.VehiclePrepareDO; +import cn.iocoder.yudao.module.asset.dal.mysql.contract.ContractMapper; import cn.iocoder.yudao.module.asset.dal.mysql.prepare.VehiclePrepareMapper; +import cn.iocoder.yudao.module.asset.dal.mysql.vehicle.VehicleBaseMapper; import cn.iocoder.yudao.module.asset.enums.inspection.InspectionSourceTypeEnum; import cn.iocoder.yudao.module.asset.service.inspection.InspectionRecordService; import cn.iocoder.yudao.module.asset.service.inspection.InspectionTemplateService; @@ -27,6 +29,12 @@ public class VehiclePrepareServiceImpl implements VehiclePrepareService { @Resource private VehiclePrepareMapper vehiclePrepareMapper; + @Resource + private ContractMapper contractMapper; + + @Resource + private VehicleBaseMapper vehicleBaseMapper; + @Resource private InspectionTemplateService inspectionTemplateService; @@ -35,6 +43,19 @@ public class VehiclePrepareServiceImpl implements VehiclePrepareService { @Override public Long createVehiclePrepare(VehiclePrepareSaveReqVO createReqVO) { + // 校验合同是否存在 + if (createReqVO.getContractId() != null) { + if (contractMapper.selectById(createReqVO.getContractId()) == null) { + throw exception(CONTRACT_NOT_EXISTS); + } + } + // 校验车辆是否存在 + if (createReqVO.getVehicleId() != null) { + if (vehicleBaseMapper.selectById(createReqVO.getVehicleId()) == null) { + throw exception(VEHICLE_NOT_EXISTS); + } + } + VehiclePrepareDO prepare = BeanUtils.toBean(createReqVO, VehiclePrepareDO.class); vehiclePrepareMapper.insert(prepare); diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/returnorder/ReturnOrderServiceImpl.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/returnorder/ReturnOrderServiceImpl.java index 289b35c..9151817 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/returnorder/ReturnOrderServiceImpl.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/returnorder/ReturnOrderServiceImpl.java @@ -11,12 +11,16 @@ import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionRecordD import cn.iocoder.yudao.module.asset.dal.dataobject.inspection.InspectionTemplateDO; import cn.iocoder.yudao.module.asset.dal.dataobject.returnorder.ReturnOrderDO; import cn.iocoder.yudao.module.asset.dal.dataobject.returnorder.ReturnOrderVehicleDO; +import cn.iocoder.yudao.module.asset.dal.dataobject.vehicle.VehicleBaseDO; +import cn.iocoder.yudao.module.asset.dal.dataobject.vehiclemodel.VehicleModelDO; import cn.iocoder.yudao.module.asset.dal.mysql.contract.ContractMapper; import cn.iocoder.yudao.module.asset.dal.mysql.delivery.DeliveryOrderMapper; import cn.iocoder.yudao.module.asset.dal.mysql.inspection.InspectionRecordMapper; import cn.iocoder.yudao.module.asset.dal.mysql.delivery.DeliveryOrderVehicleMapper; import cn.iocoder.yudao.module.asset.dal.mysql.returnorder.ReturnOrderMapper; import cn.iocoder.yudao.module.asset.dal.mysql.returnorder.ReturnOrderVehicleMapper; +import cn.iocoder.yudao.module.asset.dal.mysql.vehicle.VehicleBaseMapper; +import cn.iocoder.yudao.module.asset.dal.mysql.vehiclemodel.VehicleModelMapper; import cn.iocoder.yudao.module.asset.enums.inspection.InspectionSourceTypeEnum; import cn.iocoder.yudao.module.asset.service.inspection.InspectionRecordService; import cn.iocoder.yudao.module.asset.service.inspection.InspectionTemplateService; @@ -61,6 +65,12 @@ public class ReturnOrderServiceImpl implements ReturnOrderService { @Resource private ContractMapper contractMapper; + @Resource + private VehicleBaseMapper vehicleBaseMapper; + + @Resource + private VehicleModelMapper vehicleModelMapper; + @Resource private InspectionRecordMapper inspectionRecordMapper; @@ -238,10 +248,26 @@ public class ReturnOrderServiceImpl implements ReturnOrderService { returnOrderMapper.insert(order); // 创建还车车辆(原车辆) - // TODO: 查询车辆信息获取 plateNo/vin/brand/model,暂时只设置 vehicleId + VehicleBaseDO vehicleBase = vehicleBaseMapper.selectById(vehicleId); + if (vehicleBase == null) { + throw exception(VEHICLE_NOT_EXISTS); + } + ReturnOrderVehicleDO vehicle = new ReturnOrderVehicleDO(); vehicle.setReturnOrderId(order.getId()); vehicle.setVehicleId(vehicleId); + vehicle.setPlateNo(vehicleBase.getPlateNo()); + vehicle.setVin(vehicleBase.getVin()); + + // 通过车型ID查询品牌和型号 + if (vehicleBase.getVehicleModelId() != null) { + VehicleModelDO vehicleModel = vehicleModelMapper.selectById(vehicleBase.getVehicleModelId()); + if (vehicleModel != null) { + vehicle.setBrand(vehicleModel.getBrand()); + vehicle.setModel(vehicleModel.getModel()); + } + } + returnOrderVehicleMapper.insert(vehicle); return order.getId(); diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/station/HydrogenStationService.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/station/HydrogenStationService.java new file mode 100644 index 0000000..b37fa87 --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/station/HydrogenStationService.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.asset.service.station; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.asset.controller.admin.station.vo.HydrogenStationPageReqVO; +import cn.iocoder.yudao.module.asset.controller.admin.station.vo.HydrogenStationSaveReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.station.HydrogenStationDO; + +import jakarta.validation.Valid; +import java.util.List; + +/** + * 加氢站 Service 接口 + * + * @author 芋道源码 + */ +public interface HydrogenStationService { + + /** + * 创建加氢站 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createHydrogenStation(@Valid HydrogenStationSaveReqVO createReqVO); + + /** + * 更新加氢站 + * + * @param updateReqVO 更新信息 + */ + void updateHydrogenStation(@Valid HydrogenStationSaveReqVO updateReqVO); + + /** + * 删除加氢站 + * + * @param id 编号 + */ + void deleteHydrogenStation(Long id); + + /** + * 获得加氢站 + * + * @param id 编号 + * @return 加氢站 + */ + HydrogenStationDO getHydrogenStation(Long id); + + /** + * 获得加氢站分页 + * + * @param pageReqVO 分页查询 + * @return 加氢站分页 + */ + PageResult getHydrogenStationPage(HydrogenStationPageReqVO pageReqVO); + + /** + * 获得加氢站精简列表 + * + * @return 加氢站列表 + */ + List getHydrogenStationSimpleList(); + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/station/HydrogenStationServiceImpl.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/station/HydrogenStationServiceImpl.java new file mode 100644 index 0000000..a13446c --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/station/HydrogenStationServiceImpl.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.asset.service.station; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.asset.controller.admin.station.vo.HydrogenStationPageReqVO; +import cn.iocoder.yudao.module.asset.controller.admin.station.vo.HydrogenStationSaveReqVO; +import cn.iocoder.yudao.module.asset.dal.dataobject.station.HydrogenStationDO; +import cn.iocoder.yudao.module.asset.dal.mysql.station.HydrogenStationMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import jakarta.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.asset.enums.ErrorCodeConstants.*; + +/** + * 加氢站 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class HydrogenStationServiceImpl implements HydrogenStationService { + + @Resource + private HydrogenStationMapper hydrogenStationMapper; + + @Override + public Long createHydrogenStation(HydrogenStationSaveReqVO createReqVO) { + // 业务校验 + validateHydrogenStationBusiness(createReqVO); + + HydrogenStationDO hydrogenStation = BeanUtils.toBean(createReqVO, HydrogenStationDO.class); + hydrogenStationMapper.insert(hydrogenStation); + return hydrogenStation.getId(); + } + + @Override + public void updateHydrogenStation(HydrogenStationSaveReqVO updateReqVO) { + validateHydrogenStationExists(updateReqVO.getId()); + + // 业务校验 + validateHydrogenStationBusiness(updateReqVO); + + HydrogenStationDO updateObj = BeanUtils.toBean(updateReqVO, HydrogenStationDO.class); + hydrogenStationMapper.updateById(updateObj); + } + + @Override + public void deleteHydrogenStation(Long id) { + validateHydrogenStationExists(id); + hydrogenStationMapper.deleteById(id); + } + + private void validateHydrogenStationExists(Long id) { + if (hydrogenStationMapper.selectById(id) == null) { + throw exception(HYDROGEN_STATION_NOT_EXISTS); + } + } + + /** + * 业务校验 + */ + private void validateHydrogenStationBusiness(HydrogenStationSaveReqVO reqVO) { + // 校验营业时间 + if (reqVO.getStartBusiness() != null && reqVO.getEndBusiness() != null) { + if (reqVO.getEndBusiness().isBefore(reqVO.getStartBusiness())) { + throw exception(HYDROGEN_STATION_END_BUSINESS_BEFORE_START_BUSINESS); + } + } + } + + @Override + public HydrogenStationDO getHydrogenStation(Long id) { + return hydrogenStationMapper.selectById(id); + } + + @Override + public PageResult getHydrogenStationPage(HydrogenStationPageReqVO pageReqVO) { + return hydrogenStationMapper.selectPage(pageReqVO); + } + + @Override + public List getHydrogenStationSimpleList() { + return hydrogenStationMapper.selectSimpleList(); + } + +} diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/vehicleregistration/VehicleRegistrationService.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/vehicleregistration/VehicleRegistrationService.java index 9b7f06b..8309d4c 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/vehicleregistration/VehicleRegistrationService.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/vehicleregistration/VehicleRegistrationService.java @@ -68,4 +68,11 @@ public interface VehicleRegistrationService { */ void confirmRegistration(Long id); + /** + * 作废上牌记录 + * + * @param id 上牌记录ID + */ + void voidRegistration(Long id); + } diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/vehicleregistration/VehicleRegistrationServiceImpl.java b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/vehicleregistration/VehicleRegistrationServiceImpl.java index 782aae0..a6bffc1 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/vehicleregistration/VehicleRegistrationServiceImpl.java +++ b/yudao-module-asset/yudao-module-asset-server/src/main/java/cn/iocoder/yudao/module/asset/service/vehicleregistration/VehicleRegistrationServiceImpl.java @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.asset.dal.mysql.vehicleregistration.VehicleRegist import cn.iocoder.yudao.framework.common.exception.ErrorCode; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.ocr.api.OcrApi; +import cn.iocoder.yudao.module.ocr.api.dto.VehicleLicenseReqDTO; import cn.iocoder.yudao.module.ocr.api.dto.VehicleLicenseRespDTO; import cn.hutool.core.codec.Base64; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -55,7 +56,9 @@ public class VehicleRegistrationServiceImpl implements VehicleRegistrationServic String imageDataBase64 = Base64.encode(imageData); // 调用 OCR API 识别 - CommonResult ocrResult = ocrApi.recognizeVehicleLicense(imageDataBase64, null); + VehicleLicenseReqDTO reqDTO = new VehicleLicenseReqDTO(); + reqDTO.setImageData(imageDataBase64); + CommonResult ocrResult = ocrApi.recognizeVehicleLicense(reqDTO); long costTime = System.currentTimeMillis() - startTime; @@ -100,11 +103,12 @@ public class VehicleRegistrationServiceImpl implements VehicleRegistrationServic @Override @Transactional(rollbackFor = Exception.class) public Long createVehicleRegistration(VehicleRegistrationSaveReqVO createReqVO) { - // 验证车辆是否存在 - VehicleBaseDO vehicle = validateVehicleExists(createReqVO.getVehicleId()); + // 通过 VIN 验证车辆是否存在 + VehicleBaseDO vehicle = validateVehicleExistsByVin(createReqVO.getVin()); // 插入 VehicleRegistrationDO registration = VehicleRegistrationConvert.INSTANCE.convert(createReqVO); + registration.setVehicleId(vehicle.getId()); registration.setStatus(0); // 待确认 vehicleRegistrationMapper.insert(registration); @@ -120,9 +124,10 @@ public class VehicleRegistrationServiceImpl implements VehicleRegistrationServic // 校验存在 validateVehicleRegistrationExists(updateReqVO.getId()); - // 验证车辆是否存在 - if (updateReqVO.getVehicleId() != null) { - validateVehicleExists(updateReqVO.getVehicleId()); + // 通过 VIN 验证车辆是否存在 + if (StrUtil.isNotBlank(updateReqVO.getVin())) { + VehicleBaseDO vehicle = validateVehicleExistsByVin(updateReqVO.getVin()); + updateReqVO.setVehicleId(vehicle.getId()); } // 更新 @@ -192,6 +197,20 @@ public class VehicleRegistrationServiceImpl implements VehicleRegistrationServic log.info("[confirmRegistration][确认上牌记录成功,ID:{},车辆ID:{}]", id, vehicle.getId()); } + @Override + @Transactional(rollbackFor = Exception.class) + public void voidRegistration(Long id) { + VehicleRegistrationDO registration = validateVehicleRegistrationExists(id); + if (registration.getStatus() != 0) { + throw exception(new ErrorCode(400, "上牌记录已确认或已作废")); + } + VehicleRegistrationDO updateObj = new VehicleRegistrationDO(); + updateObj.setId(id); + updateObj.setStatus(2); // 2=已作废 + vehicleRegistrationMapper.updateById(updateObj); + log.info("[voidRegistration][作废上牌记录成功,ID:{}]", id); + } + // ==================== 私有方法 ==================== private VehicleRegistrationDO validateVehicleRegistrationExists(Long id) { @@ -210,4 +229,17 @@ public class VehicleRegistrationServiceImpl implements VehicleRegistrationServic return vehicle; } + private VehicleBaseDO validateVehicleExistsByVin(String vin) { + if (StrUtil.isBlank(vin)) { + throw exception(new ErrorCode(400, "VIN不能为空")); + } + VehicleBaseDO vehicle = vehicleBaseMapper.selectOne(new LambdaQueryWrapper() + .eq(VehicleBaseDO::getVin, vin) + .last("LIMIT 1")); + if (vehicle == null) { + throw exception(new ErrorCode(400, "车辆不存在,请先录入车辆信息")); + } + return vehicle; + } + } diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/resources/application-local.yaml b/yudao-module-asset/yudao-module-asset-server/src/main/resources/application-local.yaml index 3056a2d..b8e2da6 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/resources/application-local.yaml +++ b/yudao-module-asset/yudao-module-asset-server/src/main/resources/application-local.yaml @@ -109,3 +109,14 @@ knife4j: enable: true setting: language: zh_cn + +# XXL-Job 配置 +xxl: + job: + enabled: false # 本地开发禁用 + admin: + addresses: http://47.103.115.36:9090/xxl-job-admin + executor: + appname: asset-server + logpath: ./logs/xxl-job + logretentiondays: 30 diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/resources/application.yaml b/yudao-module-asset/yudao-module-asset-server/src/main/resources/application.yaml index 0d234fe..b5361ff 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/main/resources/application.yaml +++ b/yudao-module-asset/yudao-module-asset-server/src/main/resources/application.yaml @@ -3,7 +3,7 @@ spring: name: asset-server profiles: - active: dev + active: local # 允许 Bean 覆盖 main: diff --git a/yudao-module-asset/yudao-module-asset-server/src/main/resources/processes/asset_contract.bpmn20.xml b/yudao-module-asset/yudao-module-asset-server/src/main/resources/processes/asset_contract.bpmn20.xml new file mode 100644 index 0000000..c068d2c --- /dev/null +++ b/yudao-module-asset/yudao-module-asset-server/src/main/resources/processes/asset_contract.bpmn20.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + ${approved == true} + + + + ${approved == false} + + + + + + + + + + + + + + + + + ${approved == true} + + + + ${approved == false} + + + + + + + + + + + diff --git a/yudao-module-asset/yudao-module-asset-server/src/test/java/cn/iocoder/yudao/module/asset/service/customer/CustomerServiceImplTest.java b/yudao-module-asset/yudao-module-asset-server/src/test/java/cn/iocoder/yudao/module/asset/service/customer/CustomerServiceImplTest.java deleted file mode 100644 index a8f1020..0000000 --- a/yudao-module-asset/yudao-module-asset-server/src/test/java/cn/iocoder/yudao/module/asset/service/customer/CustomerServiceImplTest.java +++ /dev/null @@ -1,228 +0,0 @@ -package cn.iocoder.yudao.module.asset.service.customer; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.asset.controller.admin.customer.vo.CustomerPageReqVO; -import cn.iocoder.yudao.module.asset.controller.admin.customer.vo.CustomerSaveReqVO; -import cn.iocoder.yudao.module.asset.dal.dataobject.customer.CustomerDO; -import cn.iocoder.yudao.module.asset.dal.mysql.customer.CustomerMapper; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import jakarta.annotation.Resource; -import java.math.BigDecimal; - -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.module.asset.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; -import static org.junit.jupiter.api.Assertions.*; - -/** - * 客户管理 Service 测试类 - * - * @author 芋道源码 - */ -@Import(CustomerServiceImpl.class) -public class CustomerServiceImplTest extends BaseDbUnitTest { - - @Resource - private CustomerServiceImpl customerService; - - @Resource - private CustomerMapper customerMapper; - - @Test - public void testCreateCustomer_success() { - // 准备参数 - CustomerSaveReqVO createReqVO = randomPojo(CustomerSaveReqVO.class, o -> { - o.setCustomerName("测试客户"); - o.setCustomerType(0); - o.setContactPhone("13800138000"); - o.setContactEmail("test@example.com"); - o.setIdCardNo("310101199001011234"); - o.setCreditLevel(1); - o.setDepositAmount(new BigDecimal("5000.00")); - o.setStatus(0); - }); - - // 调用 - Long customerId = customerService.createCustomer(createReqVO); - - // 断言 - assertNotNull(customerId); - CustomerDO customer = customerMapper.selectById(customerId); - assertNotNull(customer); - assertEquals("测试客户", customer.getCustomerName()); - assertEquals(0, customer.getCustomerType()); - assertEquals("13800138000", customer.getContactPhone()); - assertNotNull(customer.getCustomerNo()); - assertTrue(customer.getCustomerNo().startsWith("CUST")); - } - - @Test - public void testUpdateCustomer_success() { - // mock 数据 - CustomerDO dbCustomer = new CustomerDO(); - dbCustomer.setCustomerNo("CUST000001"); - dbCustomer.setCustomerName("原客户名"); - dbCustomer.setCustomerType(0); - dbCustomer.setContactPhone("13800138000"); - dbCustomer.setCreditLevel(1); - dbCustomer.setDepositAmount(new BigDecimal("5000.00")); - dbCustomer.setStatus(0); - customerMapper.insert(dbCustomer); - - // 准备参数 - CustomerSaveReqVO updateReqVO = new CustomerSaveReqVO(); - updateReqVO.setId(dbCustomer.getId()); - updateReqVO.setCustomerName("新客户名"); - updateReqVO.setCustomerType(0); - updateReqVO.setContactPhone("13900139000"); - updateReqVO.setCreditLevel(2); - updateReqVO.setDepositAmount(new BigDecimal("8000.00")); - updateReqVO.setStatus(0); - - // 调用 - customerService.updateCustomer(updateReqVO); - - // 断言 - CustomerDO customer = customerMapper.selectById(updateReqVO.getId()); - assertEquals("新客户名", customer.getCustomerName()); - assertEquals("13900139000", customer.getContactPhone()); - assertEquals(2, customer.getCreditLevel()); - } - - @Test - public void testUpdateCustomer_notExists() { - // 准备参数 - CustomerSaveReqVO updateReqVO = randomPojo(CustomerSaveReqVO.class, o -> { - o.setId(999999L); - o.setCustomerName("不存在的客户"); - o.setCustomerType(0); - o.setStatus(0); - }); - - // 调用并断言异常 - assertServiceException(() -> customerService.updateCustomer(updateReqVO), CUSTOMER_NOT_EXISTS); - } - - @Test - public void testDeleteCustomer_success() { - // mock 数据 - CustomerDO dbCustomer = new CustomerDO(); - dbCustomer.setCustomerNo("CUST000001"); - dbCustomer.setCustomerName("测试客户"); - dbCustomer.setCustomerType(0); - dbCustomer.setCreditLevel(1); - dbCustomer.setDepositAmount(new BigDecimal("5000.00")); - dbCustomer.setStatus(0); - customerMapper.insert(dbCustomer); - - // 调用 - customerService.deleteCustomer(dbCustomer.getId()); - - // 断言 - assertNull(customerMapper.selectById(dbCustomer.getId())); - } - - @Test - public void testDeleteCustomer_notExists() { - // 调用并断言异常 - assertServiceException(() -> customerService.deleteCustomer(999999L), CUSTOMER_NOT_EXISTS); - } - - @Test - public void testGetCustomer() { - // mock 数据 - CustomerDO dbCustomer = new CustomerDO(); - dbCustomer.setCustomerNo("CUST000001"); - dbCustomer.setCustomerName("测试客户"); - dbCustomer.setCustomerType(0); - dbCustomer.setCreditLevel(1); - dbCustomer.setDepositAmount(new BigDecimal("5000.00")); - dbCustomer.setStatus(0); - customerMapper.insert(dbCustomer); - - // 调用 - CustomerDO customer = customerService.getCustomer(dbCustomer.getId()); - - // 断言 - assertNotNull(customer); - assertEquals("测试客户", customer.getCustomerName()); - } - - @Test - public void testGetCustomerPage() { - // mock 数据 - CustomerDO dbCustomer1 = new CustomerDO(); - dbCustomer1.setCustomerNo("CUST000001"); - dbCustomer1.setCustomerName("张三"); - dbCustomer1.setCustomerType(0); - dbCustomer1.setContactPhone("13800138001"); - dbCustomer1.setCreditLevel(1); - dbCustomer1.setDepositAmount(new BigDecimal("5000.00")); - dbCustomer1.setStatus(0); - customerMapper.insert(dbCustomer1); - - CustomerDO dbCustomer2 = new CustomerDO(); - dbCustomer2.setCustomerNo("CUST000002"); - dbCustomer2.setCustomerName("李四"); - dbCustomer2.setCustomerType(1); - dbCustomer2.setContactPhone("13800138002"); - dbCustomer2.setCreditLevel(1); - dbCustomer2.setDepositAmount(new BigDecimal("5000.00")); - dbCustomer2.setStatus(0); - customerMapper.insert(dbCustomer2); - - CustomerDO dbCustomer3 = new CustomerDO(); - dbCustomer3.setCustomerNo("CUST000003"); - dbCustomer3.setCustomerName("王五"); - dbCustomer3.setCustomerType(0); - dbCustomer3.setContactPhone("13800138003"); - dbCustomer3.setCreditLevel(1); - dbCustomer3.setDepositAmount(new BigDecimal("5000.00")); - dbCustomer3.setStatus(1); - customerMapper.insert(dbCustomer3); - - // 测试 customerName 模糊查询 - CustomerPageReqVO reqVO = new CustomerPageReqVO(); - reqVO.setCustomerName("张"); - reqVO.setPageNo(1); - reqVO.setPageSize(10); - - PageResult pageResult = customerService.getCustomerPage(reqVO); - assertEquals(1, pageResult.getTotal()); - assertEquals("张三", pageResult.getList().get(0).getCustomerName()); - - // 测试 customerType 筛选 - reqVO = new CustomerPageReqVO(); - reqVO.setCustomerType(1); - reqVO.setPageNo(1); - reqVO.setPageSize(10); - - pageResult = customerService.getCustomerPage(reqVO); - assertEquals(1, pageResult.getTotal()); - assertEquals("李四", pageResult.getList().get(0).getCustomerName()); - - // 测试 status 筛选 - reqVO = new CustomerPageReqVO(); - reqVO.setStatus(1); - reqVO.setPageNo(1); - reqVO.setPageSize(10); - - pageResult = customerService.getCustomerPage(reqVO); - assertEquals(1, pageResult.getTotal()); - assertEquals("王五", pageResult.getList().get(0).getCustomerName()); - - // 测试 contactPhone 模糊查询 - reqVO = new CustomerPageReqVO(); - reqVO.setContactPhone("138001"); - reqVO.setPageNo(1); - reqVO.setPageSize(10); - - pageResult = customerService.getCustomerPage(reqVO); - assertEquals(3, pageResult.getTotal()); - } - -} diff --git a/yudao-module-asset/yudao-module-asset-server/src/test/resources/sql/create_tables.sql b/yudao-module-asset/yudao-module-asset-server/src/test/resources/sql/create_tables.sql index 1e5f3e7..8ba6a79 100644 --- a/yudao-module-asset/yudao-module-asset-server/src/test/resources/sql/create_tables.sql +++ b/yudao-module-asset/yudao-module-asset-server/src/test/resources/sql/create_tables.sql @@ -1,30 +1,29 @@ -- 客户信息表 CREATE TABLE IF NOT EXISTS asset_customer ( id BIGINT AUTO_INCREMENT PRIMARY KEY, - customer_no VARCHAR(50) NOT NULL, - customer_name VARCHAR(100) NOT NULL, - customer_type TINYINT NOT NULL DEFAULT 0, - contact_person VARCHAR(50), - contact_phone VARCHAR(20), - contact_email VARCHAR(100), - contact_address VARCHAR(255), - id_card_no VARCHAR(18), - id_card_front_url VARCHAR(255), - id_card_back_url VARCHAR(255), - driver_license_no VARCHAR(50), - driver_license_url VARCHAR(255), - company_name VARCHAR(200), - unified_social_credit_code VARCHAR(50), - business_license_url VARCHAR(255), - legal_person VARCHAR(50), - credit_level TINYINT DEFAULT 0, - deposit_amount DECIMAL(10,2) DEFAULT 0.00, - remark VARCHAR(500), - status TINYINT NOT NULL DEFAULT 0, - creator VARCHAR(64) DEFAULT '', - create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updater VARCHAR(64) DEFAULT '', - update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - deleted TINYINT NOT NULL DEFAULT 0, - tenant_id BIGINT NOT NULL DEFAULT 0 + customer_code VARCHAR(50) COMMENT '客户编号', + coop_status VARCHAR(20) COMMENT '合作状态', + customer_name VARCHAR(100) NOT NULL COMMENT '客户名称', + province VARCHAR(50) COMMENT '省份', + city VARCHAR(50) COMMENT '城市', + address VARCHAR(255) COMMENT '地址', + region VARCHAR(20) COMMENT '区域', + contact VARCHAR(50) COMMENT '联系人', + contact_mobile VARCHAR(20) COMMENT '联系人手机', + contact_phone VARCHAR(20) COMMENT '联系人座机', + email VARCHAR(100) COMMENT '电子邮箱', + credit_code_or_id VARCHAR(50) COMMENT '统一社会信用代码/身份证', + remark VARCHAR(500) COMMENT '备注', + tax_id VARCHAR(50) COMMENT '纳税人识别号', + invoice_address VARCHAR(255) COMMENT '发票地址', + invoice_phone VARCHAR(20) COMMENT '发票电话', + account VARCHAR(50) COMMENT '银行账号', + opening_bank VARCHAR(100) COMMENT '开户行', + mailing_address VARCHAR(255) COMMENT '邮寄地址', + creator VARCHAR(64) DEFAULT '' COMMENT '创建者', + create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updater VARCHAR(64) DEFAULT '' COMMENT '更新者', + update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + deleted TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除', + tenant_id BIGINT NOT NULL DEFAULT 0 COMMENT '租户编号' ); diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApi.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApi.java index 1e3d158..0fab11e 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApi.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApi.java @@ -1,12 +1,14 @@ package cn.iocoder.yudao.module.bpm.api.task; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCancelReqDTO; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.enums.ApiConstants; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; @@ -25,4 +27,10 @@ public interface BpmProcessInstanceApi { CommonResult createProcessInstance(@RequestParam("userId") Long userId, @Valid @RequestBody BpmProcessInstanceCreateReqDTO reqDTO); + @DeleteMapping(PREFIX + "/cancel") + @Operation(summary = "取消流程实例(提供给内部)") + @Parameter(name = "userId", description = "用户编号", required = true, example = "1") + CommonResult cancelProcessInstance(@RequestParam("userId") Long userId, + @Valid @RequestBody BpmProcessInstanceCancelReqDTO reqDTO); + } diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/dto/BpmProcessInstanceCancelReqDTO.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/dto/BpmProcessInstanceCancelReqDTO.java new file mode 100644 index 0000000..d897b55 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/dto/BpmProcessInstanceCancelReqDTO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.bpm.api.task.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotEmpty; + +@Schema(description = "RPC 服务 - 流程实例的取消 Request DTO") +@Data +public class BpmProcessInstanceCancelReqDTO { + + @Schema(description = "流程实例的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotEmpty(message = "流程实例的编号不能为空") + private String id; + + @Schema(description = "取消原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "撤回审批") + @NotEmpty(message = "取消原因不能为空") + private String reason; + +} diff --git a/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java index d058a11..6a1134c 100644 --- a/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.bpm.api.task; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCancelReqDTO; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCancelReqVO; import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RestController; @@ -29,4 +31,13 @@ public class BpmProcessInstanceApiImpl implements BpmProcessInstanceApi { return success(processInstanceService.createProcessInstance(userId, reqDTO)); } + @Override + public CommonResult cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqDTO reqDTO) { + BpmProcessInstanceCancelReqVO cancelReqVO = new BpmProcessInstanceCancelReqVO(); + cancelReqVO.setId(reqDTO.getId()); + cancelReqVO.setReason(reqDTO.getReason()); + processInstanceService.cancelProcessInstanceByStartUser(userId, cancelReqVO); + return success(true); + } + } diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/EnergyServerApplication.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/EnergyServerApplication.java new file mode 100644 index 0000000..8d9ffe4 --- /dev/null +++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/EnergyServerApplication.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.energy; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * 能源管理服务启动类 + * + * @author 芋道源码 + */ +@SpringBootApplication +@EnableDiscoveryClient +@EnableFeignClients(basePackages = {"cn.iocoder.yudao.module.infra.api"}) +public class EnergyServerApplication { + + public static void main(String[] args) { + SpringApplication.run(EnergyServerApplication.class, args); + } + +} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/EnergyStationConfigController.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/EnergyStationConfigController.java deleted file mode 100644 index ff5c9a8..0000000 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/EnergyStationConfigController.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.iocoder.yudao.module.energy.controller.admin.config; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.energy.controller.admin.config.vo.EnergyStationConfigPageReqVO; -import cn.iocoder.yudao.module.energy.controller.admin.config.vo.EnergyStationConfigRespVO; -import cn.iocoder.yudao.module.energy.controller.admin.config.vo.EnergyStationConfigSaveReqVO; -import cn.iocoder.yudao.module.energy.controller.admin.config.vo.EnergyStationConfigSimpleVO; -import cn.iocoder.yudao.module.energy.convert.config.EnergyStationConfigConvert; -import cn.iocoder.yudao.module.energy.dal.dataobject.config.EnergyStationConfigDO; -import cn.iocoder.yudao.module.energy.service.config.EnergyStationConfigService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - -@Tag(name = "管理后台 - 加氢站配置") -@RestController -@RequestMapping("/energy/station-config") -@Validated -public class EnergyStationConfigController { - - @Resource - private EnergyStationConfigService stationConfigService; - - @PostMapping("/create") - @Operation(summary = "创建站点配置") - @PreAuthorize("@ss.hasPermission('energy:station-config:create')") - public CommonResult createConfig(@Valid @RequestBody EnergyStationConfigSaveReqVO createReqVO) { - return success(stationConfigService.createConfig(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新站点配置") - @PreAuthorize("@ss.hasPermission('energy:station-config:update')") - public CommonResult updateConfig(@Valid @RequestBody EnergyStationConfigSaveReqVO updateReqVO) { - stationConfigService.updateConfig(updateReqVO); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得站点配置") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('energy:station-config:query')") - public CommonResult getConfig(@RequestParam("id") Long id) { - EnergyStationConfigDO config = stationConfigService.getConfig(id); - return success(EnergyStationConfigConvert.INSTANCE.convert(config)); - } - - @GetMapping("/page") - @Operation(summary = "获得站点配置分页") - @PreAuthorize("@ss.hasPermission('energy:station-config:query')") - public CommonResult> getConfigPage(@Valid EnergyStationConfigPageReqVO pageReqVO) { - PageResult pageResult = stationConfigService.getConfigPage(pageReqVO); - return success(EnergyStationConfigConvert.INSTANCE.convertPage(pageResult)); - } - - @GetMapping("/simple-list") - @Operation(summary = "获得站点配置简单列表") - public CommonResult> getSimpleList() { - List list = stationConfigService.getConfigList(); - return success(EnergyStationConfigConvert.INSTANCE.convertSimpleList(list)); - } -} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigPageReqVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigPageReqVO.java deleted file mode 100644 index faa556c..0000000 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigPageReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.energy.controller.admin.config.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 加氢站配置分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class EnergyStationConfigPageReqVO extends PageParam { - @Schema(description = "加氢站ID") - private Long stationId; - @Schema(description = "是否自动扣款") - private Boolean autoDeduct; - @Schema(description = "合作类型") - private Integer cooperationType; -} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigRespVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigRespVO.java deleted file mode 100644 index 51fc640..0000000 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigRespVO.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.energy.controller.admin.config.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - 加氢站配置 Response VO") -@Data -public class EnergyStationConfigRespVO { - @Schema(description = "主键ID") - private Long id; - @Schema(description = "加氢站ID") - private Long stationId; - @Schema(description = "是否自动扣款") - private Boolean autoDeduct; - @Schema(description = "合作类型") - private Integer cooperationType; - @Schema(description = "站点名称") - private String stationName; - @Schema(description = "自动匹配开关") - private Boolean autoMatch; - @Schema(description = "备注") - private String remark; - @Schema(description = "创建时间") - private LocalDateTime createTime; -} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigSaveReqVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigSaveReqVO.java deleted file mode 100644 index aaa4d13..0000000 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigSaveReqVO.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.energy.controller.admin.config.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - 加氢站配置创建/更新 Request VO") -@Data -public class EnergyStationConfigSaveReqVO { - @Schema(description = "主键ID") - private Long id; - @Schema(description = "加氢站ID", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "加氢站不能为空") - private Long stationId; - @Schema(description = "是否自动扣款", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "是否自动扣款不能为空") - private Boolean autoDeduct; - @Schema(description = "合作类型") - private Integer cooperationType; - @Schema(description = "自动匹配开关") - private Boolean autoMatch; - @Schema(description = "备注") - private String remark; -} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigSimpleVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigSimpleVO.java deleted file mode 100644 index c8f327d..0000000 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigSimpleVO.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.yudao.module.energy.controller.admin.config.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - 加氢站配置简单 Response VO") -@Data -public class EnergyStationConfigSimpleVO { - @Schema(description = "配置ID") - private Long id; - @Schema(description = "站点ID") - private Long stationId; - @Schema(description = "站点名称") - private String stationName; -} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/convert/config/EnergyStationConfigConvert.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/convert/config/EnergyStationConfigConvert.java deleted file mode 100644 index 1cf4362..0000000 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/convert/config/EnergyStationConfigConvert.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.energy.convert.config; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.energy.controller.admin.config.vo.EnergyStationConfigRespVO; -import cn.iocoder.yudao.module.energy.controller.admin.config.vo.EnergyStationConfigSaveReqVO; -import cn.iocoder.yudao.module.energy.controller.admin.config.vo.EnergyStationConfigSimpleVO; -import cn.iocoder.yudao.module.energy.dal.dataobject.config.EnergyStationConfigDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface EnergyStationConfigConvert { - EnergyStationConfigConvert INSTANCE = Mappers.getMapper(EnergyStationConfigConvert.class); - EnergyStationConfigDO convert(EnergyStationConfigSaveReqVO bean); - EnergyStationConfigRespVO convert(EnergyStationConfigDO bean); - PageResult convertPage(PageResult page); - List convertSimpleList(List list); -} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/dal/dataobject/config/EnergyStationConfigDO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/dal/dataobject/config/EnergyStationConfigDO.java deleted file mode 100644 index 4a24f49..0000000 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/dal/dataobject/config/EnergyStationConfigDO.java +++ /dev/null @@ -1,53 +0,0 @@ -package cn.iocoder.yudao.module.energy.dal.dataobject.config; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -/** - * 站点配置 DO - */ -@TableName("energy_station_config") -@KeySequence("energy_station_config_seq") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class EnergyStationConfigDO extends BaseDO { - - /** - * 主键 - */ - @TableId - private Long id; - - /** - * 站点ID - */ - private Long stationId; - - /** - * 是否自动扣费 - */ - private Boolean autoDeduct; - - /** - * 合作类型 - */ - private Integer cooperationType; - - /** - * 自动匹配开关 - */ - private Boolean autoMatch; - - /** - * 备注 - */ - private String remark; - -} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/dal/mysql/config/EnergyStationConfigMapper.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/dal/mysql/config/EnergyStationConfigMapper.java deleted file mode 100644 index 6fa9481..0000000 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/dal/mysql/config/EnergyStationConfigMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.energy.dal.mysql.config; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.energy.controller.admin.config.vo.EnergyStationConfigPageReqVO; -import cn.iocoder.yudao.module.energy.dal.dataobject.config.EnergyStationConfigDO; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface EnergyStationConfigMapper extends BaseMapperX { - - default EnergyStationConfigDO selectByStationId(Long stationId) { - return selectOne(EnergyStationConfigDO::getStationId, stationId); - } - - default PageResult selectPage(EnergyStationConfigPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(EnergyStationConfigDO::getStationId, reqVO.getStationId()) - .eqIfPresent(EnergyStationConfigDO::getAutoDeduct, reqVO.getAutoDeduct()) - .eqIfPresent(EnergyStationConfigDO::getCooperationType, reqVO.getCooperationType()) - .orderByDesc(EnergyStationConfigDO::getId)); - } - -} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/BillApprovedEvent.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/BillAuditPassedEvent.java similarity index 76% rename from yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/BillApprovedEvent.java rename to yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/BillAuditPassedEvent.java index c7a3dcd..ae1804f 100644 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/BillApprovedEvent.java +++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/BillAuditPassedEvent.java @@ -5,9 +5,12 @@ import lombok.Getter; import java.util.List; +/** + * 账单审核通过事件 + */ @Getter @AllArgsConstructor -public class BillApprovedEvent { +public class BillAuditPassedEvent { private final Long billId; private final List detailIds; } diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/BillCreatedEvent.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/BillCreatedEvent.java deleted file mode 100644 index 3114600..0000000 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/BillCreatedEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.iocoder.yudao.module.energy.event; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.List; - -@Getter -@AllArgsConstructor -public class BillCreatedEvent { - private final Long billId; - private final List detailIds; -} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/DeductionCompletedEvent.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/DeductionCompletedEvent.java deleted file mode 100644 index d865a74..0000000 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/DeductionCompletedEvent.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.iocoder.yudao.module.energy.event; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public class DeductionCompletedEvent { - private final Long detailId; -} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/DetailCreatedEvent.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/DetailAuditPassedEvent.java similarity index 82% rename from yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/DetailCreatedEvent.java rename to yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/DetailAuditPassedEvent.java index 0732db0..5f66923 100644 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/DetailCreatedEvent.java +++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/DetailAuditPassedEvent.java @@ -5,9 +5,12 @@ import lombok.Getter; import java.math.BigDecimal; +/** + * 明细审核通过事件 + */ @Getter @AllArgsConstructor -public class DetailCreatedEvent { +public class DetailAuditPassedEvent { private final Long detailId; private final Long stationId; private final Long customerId; diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/DetailAuditedEvent.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/DetailAuditedEvent.java deleted file mode 100644 index ab3f2c0..0000000 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/DetailAuditedEvent.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.energy.event; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.math.BigDecimal; - -@Getter -@AllArgsConstructor -public class DetailAuditedEvent { - private final Long detailId; - private final Long stationId; - private final Long customerId; - private final Long contractId; - private final BigDecimal customerAmount; -} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/RecordMatchedEvent.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/RecordMatchedEvent.java deleted file mode 100644 index 1394757..0000000 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/event/RecordMatchedEvent.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.energy.event; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public class RecordMatchedEvent { - private final Long recordId; - private final Long stationId; - private final Long vehicleId; - private final Long customerId; - private final String plateNumber; -} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/listener/AccountEventListener.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/listener/AccountEventListener.java index 5368552..5980e1e 100644 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/listener/AccountEventListener.java +++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/listener/AccountEventListener.java @@ -1,10 +1,7 @@ package cn.iocoder.yudao.module.energy.listener; -import cn.iocoder.yudao.module.energy.dal.dataobject.config.EnergyStationConfigDO; -import cn.iocoder.yudao.module.energy.dal.mysql.config.EnergyStationConfigMapper; import cn.iocoder.yudao.module.energy.enums.DeductionStatusEnum; -import cn.iocoder.yudao.module.energy.event.DetailAuditedEvent; -import cn.iocoder.yudao.module.energy.event.DetailCreatedEvent; +import cn.iocoder.yudao.module.energy.event.DetailAuditPassedEvent; import cn.iocoder.yudao.module.energy.service.account.EnergyAccountService; import cn.iocoder.yudao.module.energy.service.detail.HydrogenDetailService; import jakarta.annotation.Resource; @@ -20,37 +17,23 @@ public class AccountEventListener { @Resource private EnergyAccountService accountService; @Resource - private EnergyStationConfigMapper stationConfigMapper; - @Resource private HydrogenDetailService detailService; /** - * 明细创建完成 → 若配置自动扣款则扣款 + * 明细审核通过 → 执行扣款 * BEFORE_COMMIT: 资金操作,必须同事务 + * + * 注意:此监听器处理审核后扣款场景(站点配置 auto_deduct=false) + * 自动扣款场景(auto_deduct=true)在明细创建时已完成 */ @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) - public void onDetailCreated(DetailCreatedEvent event) { - EnergyStationConfigDO config = stationConfigMapper.selectByStationId(event.getStationId()); - if (config != null && Boolean.TRUE.equals(config.getAutoDeduct())) { - log.info("[onDetailCreated] auto deduct: detailId={}, amount={}", event.getDetailId(), event.getCustomerAmount()); - accountService.deduct(event.getCustomerId(), event.getContractId(), - event.getCustomerAmount(), event.getDetailId(), null, "加氢自动扣款"); - detailService.updateDeductionStatus(event.getDetailId(), DeductionStatusEnum.DEDUCTED.getStatus()); - } - } - - /** - * 明细审核通过 → 若配置审核后扣款则扣款 - * BEFORE_COMMIT: 资金操作,必须同事务 - */ - @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) - public void onDetailAudited(DetailAuditedEvent event) { - EnergyStationConfigDO config = stationConfigMapper.selectByStationId(event.getStationId()); - if (config != null && !Boolean.TRUE.equals(config.getAutoDeduct())) { - log.info("[onDetailAudited] audit-then-deduct: detailId={}, amount={}", event.getDetailId(), event.getCustomerAmount()); - accountService.deduct(event.getCustomerId(), event.getContractId(), - event.getCustomerAmount(), event.getDetailId(), null, "审核后扣款"); - detailService.updateDeductionStatus(event.getDetailId(), DeductionStatusEnum.DEDUCTED.getStatus()); - } + public void onDetailAuditPassed(DetailAuditPassedEvent event) { + // TODO: 需要从 asset 模块获取站点配置判断是否需要扣款 + // 当前简化实现:审核通过后统一扣款 + log.info("[onDetailAuditPassed] deduct: detailId={}, amount={}", + event.getDetailId(), event.getCustomerAmount()); + accountService.deduct(event.getCustomerId(), event.getContractId(), + event.getCustomerAmount(), event.getDetailId(), null, "审核后扣款"); + detailService.updateDeductionStatus(event.getDetailId(), DeductionStatusEnum.DEDUCTED.getStatus()); } } diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/listener/BillEventListener.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/listener/BillEventListener.java index 898735d..77c107e 100644 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/listener/BillEventListener.java +++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/listener/BillEventListener.java @@ -1,8 +1,7 @@ package cn.iocoder.yudao.module.energy.listener; import cn.iocoder.yudao.module.energy.enums.SettlementStatusEnum; -import cn.iocoder.yudao.module.energy.event.BillApprovedEvent; -import cn.iocoder.yudao.module.energy.event.BillCreatedEvent; +import cn.iocoder.yudao.module.energy.event.BillAuditPassedEvent; import cn.iocoder.yudao.module.energy.service.detail.HydrogenDetailService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -16,23 +15,15 @@ public class BillEventListener { @Resource private HydrogenDetailService detailService; - /** - * 账单生成完成 → 更新明细的 billId - * AFTER_COMMIT: 非资金操作 - */ - @TransactionalEventListener - public void onBillCreated(BillCreatedEvent event) { - log.info("[onBillCreated] billId={}, detailCount={}", event.getBillId(), event.getDetailIds().size()); - detailService.updateBillId(event.getDetailIds(), event.getBillId()); - } - /** * 账单审核通过 → 更新明细结算状态 * AFTER_COMMIT: 非资金操作 + * + * 预留二期财务对接 */ @TransactionalEventListener - public void onBillApproved(BillApprovedEvent event) { - log.info("[onBillApproved] billId={}", event.getBillId()); + public void onBillAuditPassed(BillAuditPassedEvent event) { + log.info("[onBillAuditPassed] billId={}", event.getBillId()); detailService.updateSettlementStatus(event.getDetailIds(), SettlementStatusEnum.SETTLED.getStatus()); } } diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/listener/DetailEventListener.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/listener/DetailEventListener.java index fff088e..5090706 100644 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/listener/DetailEventListener.java +++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/listener/DetailEventListener.java @@ -1,13 +1,30 @@ package cn.iocoder.yudao.module.energy.listener; +import cn.iocoder.yudao.module.asset.dal.dataobject.station.HydrogenStationDO; +import cn.iocoder.yudao.module.asset.service.station.HydrogenStationService; +import cn.iocoder.yudao.module.energy.dal.dataobject.detail.EnergyHydrogenDetailDO; +import cn.iocoder.yudao.module.energy.dal.dataobject.price.EnergyStationPriceDO; +import cn.iocoder.yudao.module.energy.dal.dataobject.record.EnergyHydrogenRecordDO; +import cn.iocoder.yudao.module.energy.dal.mysql.detail.EnergyHydrogenDetailMapper; +import cn.iocoder.yudao.module.energy.dal.mysql.record.EnergyHydrogenRecordMapper; +import cn.iocoder.yudao.module.energy.enums.DeductionStatusEnum; import cn.iocoder.yudao.module.energy.event.RecordImportedEvent; -import cn.iocoder.yudao.module.energy.event.RecordMatchedEvent; +import cn.iocoder.yudao.module.energy.service.account.EnergyAccountService; import cn.iocoder.yudao.module.energy.service.detail.HydrogenDetailService; +import cn.iocoder.yudao.module.energy.service.match.HydrogenMatchService; +import cn.iocoder.yudao.module.energy.service.match.dto.MatchResultDTO; +import cn.iocoder.yudao.module.energy.service.price.EnergyStationPriceService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.event.TransactionalEventListener; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.List; + @Component @Slf4j public class DetailEventListener { @@ -15,26 +32,136 @@ public class DetailEventListener { @Resource private HydrogenDetailService hydrogenDetailService; + @Resource + private HydrogenMatchService hydrogenMatchService; + + @Resource + private EnergyHydrogenRecordMapper hydrogenRecordMapper; + + @Resource + private EnergyHydrogenDetailMapper hydrogenDetailMapper; + + @Resource + private HydrogenStationService hydrogenStationService; + + @Resource + private EnergyStationPriceService stationPriceService; + + @Resource + private EnergyAccountService accountService; + /** - * 记录导入完成 → 触发自动匹配(占位,后续实现批量自动匹配) + * 记录导入完成 → 触发自动匹配+生成明细 * AFTER_COMMIT: 非资金操作 */ @TransactionalEventListener + @Transactional(rollbackFor = Exception.class) public void onRecordImported(RecordImportedEvent event) { - log.info("[onRecordImported] stationId={}, recordCount={}, batchNo={}", + log.info("[onRecordImported] 开始处理导入记录,stationId={}, recordCount={}, batchNo={}", event.getStationId(), event.getRecordIds().size(), event.getBatchNo()); - // TODO: 后续接入 asset 模块实现批量自动匹配 - // hydrogenRecordService.batchMatch(event.getRecordIds()); + + // 1. 批量匹配 + MatchResultDTO matchResult = hydrogenMatchService.batchMatch(event.getRecordIds()); + log.info("[onRecordImported] 匹配完成,成功={}, 失败={}", + matchResult.getSuccessCount(), matchResult.getFailCount()); + + // 2. 批量生成明细(只为匹配成功的记录生成) + if (matchResult.getSuccessCount() > 0) { + List matchedRecords = hydrogenRecordMapper.selectBatchIds(matchResult.getSuccessIds()); + List details = new ArrayList<>(); + + for (EnergyHydrogenRecordDO record : matchedRecords) { + EnergyHydrogenDetailDO detail = createDetailFromRecord(record, event.getStationId()); + if (detail != null) { + details.add(detail); + } + } + + if (!details.isEmpty()) { + // 批量插入明细 + for (EnergyHydrogenDetailDO detail : details) { + hydrogenDetailMapper.insert(detail); + } + log.info("[onRecordImported] 生成明细完成,count={}", details.size()); + + // 3. 检查站点配置,决定是否自动扣款 + HydrogenStationDO station = hydrogenStationService.getHydrogenStation(event.getStationId()); + if (station != null && Boolean.TRUE.equals(station.getAutoDeduct())) { + log.info("[onRecordImported] 站点配置自动扣款,开始扣款流程"); + for (EnergyHydrogenDetailDO detail : details) { + try { + accountService.deduct( + detail.getCustomerId(), + detail.getContractId(), + detail.getCustomerAmount(), + detail.getId(), + null, + "加氢自动扣款" + ); + hydrogenDetailService.updateDeductionStatus( + detail.getId(), + DeductionStatusEnum.DEDUCTED.getStatus() + ); + log.info("[onRecordImported] 扣款成功,detailId={}, amount={}", + detail.getId(), detail.getCustomerAmount()); + } catch (Exception e) { + log.error("[onRecordImported] 扣款失败,detailId={}, error={}", + detail.getId(), e.getMessage(), e); + } + } + } + } + } + + log.info("[onRecordImported] 处理完成"); } /** - * 记录匹配完成 → 创建明细 - * AFTER_COMMIT: 明细创建在独立事务中 + * 从记录创建明细 */ - @TransactionalEventListener - public void onRecordMatched(RecordMatchedEvent event) { - log.info("[onRecordMatched] recordId={}, vehicleId={}, customerId={}", - event.getRecordId(), event.getVehicleId(), event.getCustomerId()); - hydrogenDetailService.createFromRecord(event); + private EnergyHydrogenDetailDO createDetailFromRecord(EnergyHydrogenRecordDO record, Long stationId) { + // 获取价格配置(使用客户ID和日期) + EnergyStationPriceDO price = stationPriceService.getEffectivePrice( + stationId, + record.getCustomerId(), + record.getHydrogenDate() + ); + if (price == null) { + log.warn("[createDetailFromRecord] 未找到有效价格配置,recordId={}, stationId={}, customerId={}, date={}", + record.getId(), stationId, record.getCustomerId(), record.getHydrogenDate()); + return null; + } + + // 重新匹配获取合同ID(因为批量匹配时已经更新了record,但需要获取contractId) + MatchResultVO matchResult = hydrogenMatchService.matchRecord(record); + + // 计算金额 + BigDecimal costAmount = record.getHydrogenQuantity() + .multiply(price.getCostPrice()) + .setScale(2, RoundingMode.HALF_UP); + BigDecimal customerAmount = record.getHydrogenQuantity() + .multiply(price.getCustomerPrice()) + .setScale(2, RoundingMode.HALF_UP); + + return EnergyHydrogenDetailDO.builder() + .recordId(record.getId()) + .stationId(stationId) + .vehicleId(record.getVehicleId()) + .plateNumber(record.getPlateNumber()) + .hydrogenDate(record.getHydrogenDate()) + .hydrogenQuantity(record.getHydrogenQuantity()) + .costPrice(price.getCostPrice()) + .costAmount(costAmount) + .customerPrice(price.getCustomerPrice()) + .customerAmount(customerAmount) + .contractId(matchResult.getContractId()) // 从匹配结果获取合同ID + .customerId(record.getCustomerId()) + .projectName(null) // 可以从合同获取,暂时为空 + .costBearer(1) // 默认客户承担,可以从合同配置获取 + .payMethod(1) // 默认预付,可以从合同配置获取 + .auditStatus(0) // 待审核 + .deductionStatus(0) // 未扣款 + .settlementStatus(0) // 未结算 + .build(); } } diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/bill/EnergyBillServiceImpl.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/bill/EnergyBillServiceImpl.java index 8b3ca14..1ae4b97 100644 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/bill/EnergyBillServiceImpl.java +++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/bill/EnergyBillServiceImpl.java @@ -12,8 +12,7 @@ import cn.iocoder.yudao.module.energy.dal.mysql.bill.EnergyBillAdjustmentMapper; import cn.iocoder.yudao.module.energy.dal.mysql.bill.EnergyBillMapper; import cn.iocoder.yudao.module.energy.dal.mysql.detail.EnergyHydrogenDetailMapper; import cn.iocoder.yudao.module.energy.enums.*; -import cn.iocoder.yudao.module.energy.event.BillApprovedEvent; -import cn.iocoder.yudao.module.energy.event.BillCreatedEvent; +import cn.iocoder.yudao.module.energy.event.BillAuditPassedEvent; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationEventPublisher; @@ -91,9 +90,11 @@ public class EnergyBillServiceImpl implements EnergyBillService { .build(); billMapper.insert(bill); - // 4. Publish event to update detail billIds + // 4. Update detail billIds directly (no event needed) List detailIds = details.stream().map(EnergyHydrogenDetailDO::getId).toList(); - eventPublisher.publishEvent(new BillCreatedEvent(bill.getId(), detailIds)); + detailMapper.update(null, new com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper() + .set(EnergyHydrogenDetailDO::getBillId, bill.getId()) + .in(EnergyHydrogenDetailDO::getId, detailIds)); return bill.getId(); } @@ -160,7 +161,7 @@ public class EnergyBillServiceImpl implements EnergyBillService { if (approved) { List details = detailMapper.selectListByBillId(id); List detailIds = details.stream().map(EnergyHydrogenDetailDO::getId).toList(); - eventPublisher.publishEvent(new BillApprovedEvent(id, detailIds)); + eventPublisher.publishEvent(new BillAuditPassedEvent(id, detailIds)); } } diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/config/EnergyStationConfigService.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/config/EnergyStationConfigService.java deleted file mode 100644 index 067250d..0000000 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/config/EnergyStationConfigService.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.module.energy.service.config; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.energy.controller.admin.config.vo.EnergyStationConfigPageReqVO; -import cn.iocoder.yudao.module.energy.controller.admin.config.vo.EnergyStationConfigSaveReqVO; -import cn.iocoder.yudao.module.energy.dal.dataobject.config.EnergyStationConfigDO; - -import java.util.List; - -public interface EnergyStationConfigService { - Long createConfig(EnergyStationConfigSaveReqVO createReqVO); - void updateConfig(EnergyStationConfigSaveReqVO updateReqVO); - EnergyStationConfigDO getConfig(Long id); - PageResult getConfigPage(EnergyStationConfigPageReqVO pageReqVO); - EnergyStationConfigDO getByStationId(Long stationId); - List getConfigList(); -} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/config/EnergyStationConfigServiceImpl.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/config/EnergyStationConfigServiceImpl.java deleted file mode 100644 index 5832e1b..0000000 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/config/EnergyStationConfigServiceImpl.java +++ /dev/null @@ -1,69 +0,0 @@ -package cn.iocoder.yudao.module.energy.service.config; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.energy.controller.admin.config.vo.EnergyStationConfigPageReqVO; -import cn.iocoder.yudao.module.energy.controller.admin.config.vo.EnergyStationConfigSaveReqVO; -import cn.iocoder.yudao.module.energy.convert.config.EnergyStationConfigConvert; -import cn.iocoder.yudao.module.energy.dal.dataobject.config.EnergyStationConfigDO; -import cn.iocoder.yudao.module.energy.dal.mysql.config.EnergyStationConfigMapper; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.energy.enums.ErrorCodeConstants.*; - -@Service -@Validated -public class EnergyStationConfigServiceImpl implements EnergyStationConfigService { - - @Resource - private EnergyStationConfigMapper stationConfigMapper; - - @Override - public Long createConfig(EnergyStationConfigSaveReqVO createReqVO) { - // 校验站点唯一 - EnergyStationConfigDO existing = stationConfigMapper.selectByStationId(createReqVO.getStationId()); - if (existing != null) { - throw exception(STATION_CONFIG_DUPLICATE); - } - EnergyStationConfigDO config = EnergyStationConfigConvert.INSTANCE.convert(createReqVO); - stationConfigMapper.insert(config); - return config.getId(); - } - - @Override - public void updateConfig(EnergyStationConfigSaveReqVO updateReqVO) { - validateConfigExists(updateReqVO.getId()); - EnergyStationConfigDO updateObj = EnergyStationConfigConvert.INSTANCE.convert(updateReqVO); - stationConfigMapper.updateById(updateObj); - } - - @Override - public EnergyStationConfigDO getConfig(Long id) { - return stationConfigMapper.selectById(id); - } - - @Override - public PageResult getConfigPage(EnergyStationConfigPageReqVO pageReqVO) { - return stationConfigMapper.selectPage(pageReqVO); - } - - @Override - public EnergyStationConfigDO getByStationId(Long stationId) { - return stationConfigMapper.selectByStationId(stationId); - } - - @Override - public List getConfigList() { - return stationConfigMapper.selectList(); - } - - private void validateConfigExists(Long id) { - if (stationConfigMapper.selectById(id) == null) { - throw exception(STATION_CONFIG_NOT_EXISTS); - } - } -} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/detail/HydrogenDetailService.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/detail/HydrogenDetailService.java index f5dddac..06bc7ae 100644 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/detail/HydrogenDetailService.java +++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/detail/HydrogenDetailService.java @@ -4,11 +4,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.energy.controller.admin.detail.vo.HydrogenDetailPageReqVO; import cn.iocoder.yudao.module.energy.controller.admin.detail.vo.HydrogenDetailSaveReqVO; import cn.iocoder.yudao.module.energy.dal.dataobject.detail.EnergyHydrogenDetailDO; -import cn.iocoder.yudao.module.energy.event.RecordMatchedEvent; import java.util.List; public interface HydrogenDetailService { - void createFromRecord(RecordMatchedEvent event); void updateDetail(HydrogenDetailSaveReqVO reqVO); PageResult getDetailPage(HydrogenDetailPageReqVO pageReqVO); EnergyHydrogenDetailDO getDetail(Long id); diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/detail/HydrogenDetailServiceImpl.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/detail/HydrogenDetailServiceImpl.java index bc30c45..fe97d22 100644 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/detail/HydrogenDetailServiceImpl.java +++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/detail/HydrogenDetailServiceImpl.java @@ -12,9 +12,7 @@ import cn.iocoder.yudao.module.energy.enums.AuditStatusEnum; import cn.iocoder.yudao.module.energy.enums.CostBearerEnum; import cn.iocoder.yudao.module.energy.enums.DeductionStatusEnum; import cn.iocoder.yudao.module.energy.enums.PayMethodEnum; -import cn.iocoder.yudao.module.energy.event.DetailAuditedEvent; -import cn.iocoder.yudao.module.energy.event.DetailCreatedEvent; -import cn.iocoder.yudao.module.energy.event.RecordMatchedEvent; +import cn.iocoder.yudao.module.energy.event.DetailAuditPassedEvent; import cn.iocoder.yudao.module.energy.service.price.EnergyStationPriceService; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import jakarta.annotation.Resource; @@ -44,54 +42,6 @@ public class HydrogenDetailServiceImpl implements HydrogenDetailService { @Resource private ApplicationEventPublisher eventPublisher; - @Override - @Transactional(rollbackFor = Exception.class) - public void createFromRecord(RecordMatchedEvent event) { - // 1. Get original record - EnergyHydrogenRecordDO record = recordMapper.selectById(event.getRecordId()); - if (record == null) { - log.warn("[createFromRecord] record not found: {}", event.getRecordId()); - return; - } - - // 2. Get price - EnergyStationPriceDO price = stationPriceService.getEffectivePrice( - event.getStationId(), event.getCustomerId(), record.getHydrogenDate()); - BigDecimal costPrice = price != null ? price.getCostPrice() : record.getUnitPrice(); - BigDecimal customerPrice = price != null ? price.getCustomerPrice() : record.getUnitPrice(); - - // 3. Calculate amounts - BigDecimal costAmount = record.getHydrogenQuantity().multiply(costPrice).setScale(2, RoundingMode.HALF_UP); - BigDecimal customerAmount = record.getHydrogenQuantity().multiply(customerPrice).setScale(2, RoundingMode.HALF_UP); - - // 4. Build detail - NOTE: contractId, costBearer, payMethod would normally come from asset/rental API - // For now, use defaults. TODO: integrate with asset module for contract lookup - EnergyHydrogenDetailDO detail = EnergyHydrogenDetailDO.builder() - .recordId(event.getRecordId()) - .stationId(event.getStationId()) - .vehicleId(event.getVehicleId()) - .plateNumber(event.getPlateNumber()) - .hydrogenDate(record.getHydrogenDate()) - .hydrogenQuantity(record.getHydrogenQuantity()) - .costPrice(costPrice) - .costAmount(costAmount) - .customerPrice(customerPrice) - .customerAmount(customerAmount) - .customerId(event.getCustomerId()) - .costBearer(CostBearerEnum.CUSTOMER.getType()) - .payMethod(PayMethodEnum.PREPAID.getType()) - .auditStatus(AuditStatusEnum.PENDING.getStatus()) - .deductionStatus(DeductionStatusEnum.NOT_DEDUCTED.getStatus()) - .settlementStatus(0) // NOT_SETTLED - .build(); - detailMapper.insert(detail); - - // 5. Publish event (BEFORE_COMMIT listener will handle auto-deduction if configured) - eventPublisher.publishEvent(new DetailCreatedEvent( - detail.getId(), event.getStationId(), event.getCustomerId(), - detail.getContractId(), customerAmount)); - } - @Override public void updateDetail(HydrogenDetailSaveReqVO reqVO) { validateDetailExists(reqVO.getId()); @@ -134,7 +84,7 @@ public class HydrogenDetailServiceImpl implements HydrogenDetailService { // If approved, publish event for deduction if (approved) { - eventPublisher.publishEvent(new DetailAuditedEvent( + eventPublisher.publishEvent(new DetailAuditPassedEvent( id, detail.getStationId(), detail.getCustomerId(), detail.getContractId(), detail.getCustomerAmount())); } diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/match/HydrogenMatchService.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/match/HydrogenMatchService.java new file mode 100644 index 0000000..7b4d227 --- /dev/null +++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/match/HydrogenMatchService.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.energy.service.match; + +import cn.iocoder.yudao.module.energy.dal.dataobject.record.EnergyHydrogenRecordDO; +import cn.iocoder.yudao.module.energy.service.match.dto.MatchResultDTO; +import cn.iocoder.yudao.module.energy.service.match.vo.MatchResultVO; + +import java.util.List; + +/** + * 加氢记录匹配服务 + * + * @author 芋道源码 + */ +public interface HydrogenMatchService { + + /** + * 批量自动匹配记录 + * + * @param recordIds 记录ID列表 + * @return 匹配结果统计(成功数、失败数) + */ + MatchResultDTO batchMatch(List recordIds); + + /** + * 单条记录匹配 + * + * @param record 原始记录 + * @return 匹配结果(vehicleId, customerId, contractId) + */ + MatchResultVO matchRecord(EnergyHydrogenRecordDO record); + +} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/match/HydrogenMatchServiceImpl.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/match/HydrogenMatchServiceImpl.java new file mode 100644 index 0000000..8e5fffa --- /dev/null +++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/match/HydrogenMatchServiceImpl.java @@ -0,0 +1,150 @@ +package cn.iocoder.yudao.module.energy.service.match; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.asset.dal.dataobject.contract.ContractDO; +import cn.iocoder.yudao.module.asset.dal.dataobject.customer.CustomerDO; +import cn.iocoder.yudao.module.asset.dal.dataobject.vehicle.VehicleBaseDO; +import cn.iocoder.yudao.module.asset.dal.mysql.contract.ContractMapper; +import cn.iocoder.yudao.module.asset.dal.mysql.customer.CustomerMapper; +import cn.iocoder.yudao.module.asset.dal.mysql.vehicle.VehicleBaseMapper; +import cn.iocoder.yudao.module.energy.dal.dataobject.record.EnergyHydrogenRecordDO; +import cn.iocoder.yudao.module.energy.dal.mysql.record.EnergyHydrogenRecordMapper; +import cn.iocoder.yudao.module.energy.service.match.dto.MatchResultDTO; +import cn.iocoder.yudao.module.energy.service.match.vo.MatchResultVO; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 加氢记录匹配服务实现 + * + * @author 芋道源码 + */ +@Service +@Slf4j +public class HydrogenMatchServiceImpl implements HydrogenMatchService { + + @Resource + private EnergyHydrogenRecordMapper hydrogenRecordMapper; + + @Resource + private VehicleBaseMapper vehicleBaseMapper; + + @Resource + private CustomerMapper customerMapper; + + @Resource + private ContractMapper contractMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public MatchResultDTO batchMatch(List recordIds) { + MatchResultDTO result = new MatchResultDTO(); + + for (Long recordId : recordIds) { + EnergyHydrogenRecordDO record = hydrogenRecordMapper.selectById(recordId); + if (record == null) { + log.warn("[batchMatch] 记录不存在,recordId={}", recordId); + result.setFailCount(result.getFailCount() + 1); + result.getFailIds().add(recordId); + continue; + } + + // 执行匹配 + MatchResultVO matchResult = matchRecord(record); + + // 更新记录 + EnergyHydrogenRecordDO updateRecord = new EnergyHydrogenRecordDO(); + updateRecord.setId(recordId); + updateRecord.setVehicleId(matchResult.getVehicleId()); + updateRecord.setCustomerId(matchResult.getCustomerId()); + updateRecord.setMatchStatus(matchResult.getMatchStatus()); + updateRecord.setUpdateTime(LocalDateTime.now()); + + hydrogenRecordMapper.updateById(updateRecord); + + // 统计结果 + if (matchResult.getMatchStatus() == 0) { + result.setSuccessCount(result.getSuccessCount() + 1); + result.getSuccessIds().add(recordId); + log.info("[batchMatch] 匹配成功,recordId={}, vehicleId={}, customerId={}, contractId={}", + recordId, matchResult.getVehicleId(), matchResult.getCustomerId(), matchResult.getContractId()); + } else { + result.setFailCount(result.getFailCount() + 1); + result.getFailIds().add(recordId); + log.warn("[batchMatch] 匹配失败,recordId={}, status={}, message={}", + recordId, matchResult.getMatchStatus(), matchResult.getMatchMessage()); + } + } + + return result; + } + + @Override + public MatchResultVO matchRecord(EnergyHydrogenRecordDO record) { + MatchResultVO result = new MatchResultVO(); + + // 1. 匹配车辆(通过车牌号) + if (StrUtil.isNotBlank(record.getPlateNumber())) { + VehicleBaseDO vehicle = vehicleBaseMapper.selectOne( + VehicleBaseDO::getPlateNo, record.getPlateNumber() + ); + if (vehicle != null) { + result.setVehicleId(vehicle.getId()); + log.debug("[matchRecord] 车辆匹配成功,plateNumber={}, vehicleId={}", + record.getPlateNumber(), vehicle.getId()); + } + } + + // 2. 匹配客户 + // 2.1 如果车辆未匹配,尝试通过客户名称模糊匹配 + if (result.getCustomerId() == null && StrUtil.isNotBlank(record.getPlateNumber())) { + // 注意:这里假设 plateNumber 字段可能包含客户信息,实际需要根据业务调整 + // 如果 Record 有独立的 customerName 字段,应该使用那个字段 + CustomerDO customer = customerMapper.selectOne( + new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() + .like(CustomerDO::getCustomerName, record.getPlateNumber()) + .last("LIMIT 1") + ); + if (customer != null) { + result.setCustomerId(customer.getId()); + log.debug("[matchRecord] 客户匹配成功(通过名称),customerId={}", customer.getId()); + } + } + + // 3. 匹配合同(通过客户ID) + if (result.getCustomerId() != null) { + ContractDO contract = contractMapper.selectOne( + new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() + .eq(ContractDO::getCustomerId, result.getCustomerId()) + .eq(ContractDO::getContractStatus, 2) // 2=进行中 + .gt(ContractDO::getEndDate, record.getHydrogenDate()) + .orderByDesc(ContractDO::getStartDate) + .last("LIMIT 1") + ); + if (contract != null) { + result.setContractId(contract.getId()); + log.debug("[matchRecord] 合同匹配成功,contractId={}", contract.getId()); + } + } + + // 4. 判断匹配状态 + if (result.getVehicleId() != null && result.getCustomerId() != null && result.getContractId() != null) { + result.setMatchStatus(0); // 完全匹配 + result.setMatchMessage("自动匹配成功"); + } else if (result.getCustomerId() != null) { + result.setMatchStatus(1); // 部分匹配 + result.setMatchMessage("客户匹配成功,但缺少车辆或合同信息"); + } else { + result.setMatchStatus(2); // 未匹配 + result.setMatchMessage("未找到匹配的客户"); + } + + return result; + } + +} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/match/dto/MatchResultDTO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/match/dto/MatchResultDTO.java new file mode 100644 index 0000000..c825621 --- /dev/null +++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/match/dto/MatchResultDTO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.energy.service.match.dto; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * 批量匹配结果 DTO + * + * @author 芋道源码 + */ +@Data +public class MatchResultDTO { + + /** + * 成功数量 + */ + private Integer successCount = 0; + + /** + * 失败数量 + */ + private Integer failCount = 0; + + /** + * 成功的记录ID列表 + */ + private List successIds = new ArrayList<>(); + + /** + * 失败的记录ID列表 + */ + private List failIds = new ArrayList<>(); + +} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/match/vo/MatchResultVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/match/vo/MatchResultVO.java new file mode 100644 index 0000000..9de9f90 --- /dev/null +++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/match/vo/MatchResultVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.energy.service.match.vo; + +import lombok.Data; + +/** + * 匹配结果 VO + * + * @author 芋道源码 + */ +@Data +public class MatchResultVO { + + /** + * 车辆ID + */ + private Long vehicleId; + + /** + * 客户ID + */ + private Long customerId; + + /** + * 合同ID + */ + private Long contractId; + + /** + * 匹配状态(0=完全匹配,1=部分匹配,2=未匹配) + */ + private Integer matchStatus; + + /** + * 匹配说明 + */ + private String matchMessage; + +} diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/record/HydrogenRecordServiceImpl.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/record/HydrogenRecordServiceImpl.java index 8c44272..34c76e4 100644 --- a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/record/HydrogenRecordServiceImpl.java +++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/service/record/HydrogenRecordServiceImpl.java @@ -14,7 +14,6 @@ import cn.iocoder.yudao.module.energy.dal.mysql.record.EnergyHydrogenRecordMappe import cn.iocoder.yudao.module.energy.enums.MatchStatusEnum; import cn.iocoder.yudao.module.energy.enums.SourceTypeEnum; import cn.iocoder.yudao.module.energy.event.RecordImportedEvent; -import cn.iocoder.yudao.module.energy.event.RecordMatchedEvent; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationEventPublisher; @@ -132,8 +131,7 @@ public class HydrogenRecordServiceImpl implements HydrogenRecordService { .customerId(customerId) .matchStatus(MatchStatusEnum.MATCHED.getStatus()) .build()); - // Publish event - eventPublisher.publishEvent(new RecordMatchedEvent(id, record.getStationId(), vehicleId, customerId, record.getPlateNumber())); + // 手动匹配功能保留,批量匹配和明细生成由 RecordImportedEvent 统一处理 } @Override diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/resources/application-local.yaml b/yudao-module-energy/yudao-module-energy-server/src/main/resources/application-local.yaml new file mode 100644 index 0000000..4ad5a20 --- /dev/null +++ b/yudao-module-energy/yudao-module-energy-server/src/main/resources/application-local.yaml @@ -0,0 +1,107 @@ +server: + port: 48085 + +spring: + application: + name: energy-server + + # 允许 Bean 覆盖 + main: + allow-bean-definition-overriding: true + + # 禁用 Nacos 配置中心 + cloud: + nacos: + config: + enabled: false + import-check: + enabled: false + + # 数据源配置 + datasource: + druid: + url: jdbc:mysql://47.103.115.36:3306/oneos_energy?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true + username: root + password: Passw0rd2026 + driver-class-name: com.mysql.cj.jdbc.Driver + initial-size: 5 + min-idle: 5 + max-active: 20 + max-wait: 60000 + test-while-idle: true + test-on-borrow: false + test-on-return: false + + # Redis 配置 + data: + redis: + host: 47.103.115.36 + port: 6379 + database: 0 + password: Passw0rd2026 + timeout: 10s + lettuce: + pool: + max-active: 8 + max-idle: 8 + min-idle: 0 + max-wait: -1ms + +# MyBatis Plus 配置 +mybatis-plus: + configuration: + map-underscore-to-camel-case: true + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + global-config: + db-config: + id-type: auto + logic-delete-field: deleted + logic-delete-value: 1 + logic-not-delete-value: 0 + type-aliases-package: cn.iocoder.yudao.module.energy.dal.dataobject + +# 日志配置 +logging: + level: + root: INFO + cn.iocoder.yudao.module.energy: DEBUG + cn.iocoder.yudao.framework: INFO + pattern: + console: '%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n' + +# 芋道配置 +yudao: + info: + version: 1.0.0 + base-package: cn.iocoder.yudao.module.energy + web: + admin-api: + prefix: /admin-api + controller: '**.controller.admin.**' + admin-ui: + url: http://localhost:3000 + security: + permit-all_urls: [] + xss: + enable: false + access-log: + enable: true + error-code: + enable: true + demo: false + tenant: + enable: false + +# Swagger 配置 +springdoc: + api-docs: + enabled: true + path: /v3/api-docs + swagger-ui: + enabled: true + path: /swagger-ui.html + +knife4j: + enable: true + setting: + language: zh_cn diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/resources/application.yaml b/yudao-module-energy/yudao-module-energy-server/src/main/resources/application.yaml new file mode 100644 index 0000000..ac178d2 --- /dev/null +++ b/yudao-module-energy/yudao-module-energy-server/src/main/resources/application.yaml @@ -0,0 +1,27 @@ +spring: + application: + name: energy-server + + profiles: + active: dev + + # 允许 Bean 覆盖 + main: + allow-bean-definition-overriding: true + + config: + import: + - optional:nacos:common-dev.yaml + - optional:nacos:${spring.application.name}-${spring.profiles.active}.yaml + + cloud: + nacos: + server-addr: ${NACOS_ADDR:localhost:8848} + namespace: ${NACOS_NAMESPACE:dev} + username: ${NACOS_USERNAME:nacos} + password: ${NACOS_PASSWORD:nacos} + discovery: + namespace: ${NACOS_NAMESPACE:dev} + config: + namespace: ${NACOS_NAMESPACE:dev} + file-extension: yaml diff --git a/yudao-module-ocr/yudao-module-ocr-api/src/main/java/cn/iocoder/yudao/module/ocr/api/OcrApi.java b/yudao-module-ocr/yudao-module-ocr-api/src/main/java/cn/iocoder/yudao/module/ocr/api/OcrApi.java index 27172ee..cb97198 100644 --- a/yudao-module-ocr/yudao-module-ocr-api/src/main/java/cn/iocoder/yudao/module/ocr/api/OcrApi.java +++ b/yudao-module-ocr/yudao-module-ocr-api/src/main/java/cn/iocoder/yudao/module/ocr/api/OcrApi.java @@ -1,14 +1,14 @@ package cn.iocoder.yudao.module.ocr.api; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.ocr.api.dto.VehicleLicenseReqDTO; import cn.iocoder.yudao.module.ocr.api.dto.VehicleLicenseRespDTO; import cn.iocoder.yudao.module.ocr.enums.ApiConstants; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestBody; /** * OCR 识别 API 接口 @@ -23,10 +23,7 @@ public interface OcrApi { @PostMapping(PREFIX + "/vehicle-license") @Operation(summary = "识别行驶证(提供给内部模块)") - @Parameter(name = "imageData", description = "图片数据(Base64编码)", required = true) - @Parameter(name = "provider", description = "OCR厂商(可选,默认使用配置的默认厂商)", example = "baidu") CommonResult recognizeVehicleLicense( - @RequestParam("imageData") String imageData, - @RequestParam(value = "provider", required = false) String provider); + @RequestBody VehicleLicenseReqDTO reqDTO); } diff --git a/yudao-module-ocr/yudao-module-ocr-api/src/main/java/cn/iocoder/yudao/module/ocr/api/dto/VehicleLicenseReqDTO.java b/yudao-module-ocr/yudao-module-ocr-api/src/main/java/cn/iocoder/yudao/module/ocr/api/dto/VehicleLicenseReqDTO.java new file mode 100644 index 0000000..44209e9 --- /dev/null +++ b/yudao-module-ocr/yudao-module-ocr-api/src/main/java/cn/iocoder/yudao/module/ocr/api/dto/VehicleLicenseReqDTO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.ocr.api.dto; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class VehicleLicenseReqDTO implements Serializable { + + /** 图片数据(Base64编码) */ + private String imageData; + + /** OCR厂商(可选) */ + private String provider; + +} diff --git a/yudao-module-ocr/yudao-module-ocr-server/src/main/java/cn/iocoder/yudao/module/ocr/api/OcrApiImpl.java b/yudao-module-ocr/yudao-module-ocr-server/src/main/java/cn/iocoder/yudao/module/ocr/api/OcrApiImpl.java index eda14fe..83853b0 100644 --- a/yudao-module-ocr/yudao-module-ocr-server/src/main/java/cn/iocoder/yudao/module/ocr/api/OcrApiImpl.java +++ b/yudao-module-ocr/yudao-module-ocr-server/src/main/java/cn/iocoder/yudao/module/ocr/api/OcrApiImpl.java @@ -1,25 +1,22 @@ package cn.iocoder.yudao.module.ocr.api; -import cn.hutool.core.codec.Base64; -import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.ocr.api.dto.VehicleLicenseReqDTO; import cn.iocoder.yudao.module.ocr.api.dto.VehicleLicenseRespDTO; -import cn.iocoder.yudao.module.ocr.framework.ocr.core.client.OcrClient; -import cn.iocoder.yudao.module.ocr.framework.ocr.core.client.OcrClientFactory; +import cn.iocoder.yudao.module.ocr.convert.ocr.OcrConvert; import cn.iocoder.yudao.module.ocr.framework.ocr.core.result.VehicleLicenseResult; +import cn.iocoder.yudao.module.ocr.service.ocr.OcrService; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RestController; import jakarta.annotation.Resource; +import java.util.Base64; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; /** * OCR 识别 API 实现类 - * - * @author 芋道源码 */ @RestController @Validated @@ -27,37 +24,23 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; public class OcrApiImpl implements OcrApi { @Resource - private OcrClientFactory ocrClientFactory; + private OcrService ocrService; @Override - public CommonResult recognizeVehicleLicense(String imageData, String provider) { - long startTime = System.currentTimeMillis(); + public CommonResult recognizeVehicleLicense(VehicleLicenseReqDTO reqDTO) { + try { + // Base64 解码图片数据 + byte[] imageBytes = Base64.getDecoder().decode(reqDTO.getImageData()); - log.info("[recognizeVehicleLicense][开始识别行驶证,provider:{},数据长度:{}]", - provider, imageData != null ? imageData.length() : 0); + // 调用识别服务 + VehicleLicenseResult result = ocrService.recognizeVehicleLicense(imageBytes, reqDTO.getProvider()); - // Base64 解码图片数据 - byte[] imageBytes = Base64.decode(imageData); - - // 获取 OCR 客户端 - OcrClient ocrClient; - if (StrUtil.isNotBlank(provider)) { - ocrClient = ocrClientFactory.getClient(provider); - } else { - ocrClient = ocrClientFactory.getDefaultClient(); + // 转换并返回 + return success(OcrConvert.INSTANCE.convertDto(result)); + } catch (Exception e) { + log.error("[recognizeVehicleLicense][识别行驶证失败]", e); + throw new RuntimeException("识别行驶证失败: " + e.getMessage()); } - - // 调用识别 - VehicleLicenseResult result = ocrClient.recognizeVehicleLicense(imageBytes); - - // 转换为 DTO - VehicleLicenseRespDTO respDTO = BeanUtils.toBean(result, VehicleLicenseRespDTO.class); - - long costTime = System.currentTimeMillis() - startTime; - log.info("[recognizeVehicleLicense][识别完成,耗时:{}ms,VIN:{},车牌号:{}]", - costTime, respDTO.getVin(), respDTO.getPlateNo()); - - return success(respDTO); } } diff --git a/yudao-module-ocr/yudao-module-ocr-server/src/main/java/cn/iocoder/yudao/module/ocr/convert/ocr/OcrConvert.java b/yudao-module-ocr/yudao-module-ocr-server/src/main/java/cn/iocoder/yudao/module/ocr/convert/ocr/OcrConvert.java index bfef112..5e1a087 100644 --- a/yudao-module-ocr/yudao-module-ocr-server/src/main/java/cn/iocoder/yudao/module/ocr/convert/ocr/OcrConvert.java +++ b/yudao-module-ocr/yudao-module-ocr-server/src/main/java/cn/iocoder/yudao/module/ocr/convert/ocr/OcrConvert.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.ocr.convert.ocr; +import cn.iocoder.yudao.module.ocr.api.dto.VehicleLicenseRespDTO; import cn.iocoder.yudao.module.ocr.controller.admin.ocr.vo.VehicleLicenseRespVO; import cn.iocoder.yudao.module.ocr.framework.ocr.core.result.VehicleLicenseResult; import org.mapstruct.Mapper; @@ -14,8 +15,13 @@ public interface OcrConvert { OcrConvert INSTANCE = Mappers.getMapper(OcrConvert.class); /** - * 转换行驶证识别结果 + * 转换行驶证识别结果(Controller 使用) */ VehicleLicenseRespVO convert(VehicleLicenseResult result); + /** + * 转换行驶证识别结果(API 使用) + */ + VehicleLicenseRespDTO convertDto(VehicleLicenseResult result); + } diff --git a/yudao-module-ocr/yudao-module-ocr-server/src/main/java/cn/iocoder/yudao/module/ocr/framework/security/config/SecurityConfiguration.java b/yudao-module-ocr/yudao-module-ocr-server/src/main/java/cn/iocoder/yudao/module/ocr/framework/security/config/SecurityConfiguration.java new file mode 100644 index 0000000..77de959 --- /dev/null +++ b/yudao-module-ocr/yudao-module-ocr-server/src/main/java/cn/iocoder/yudao/module/ocr/framework/security/config/SecurityConfiguration.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.ocr.framework.security.config; + +import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer; + +/** + * OCR 模块的 Security 配置 + */ +@Configuration +public class SecurityConfiguration { + + @Bean + public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() { + return new AuthorizeRequestsCustomizer() { + @Override + public void customize(AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry registry) { + // OCR 识别接口需要认证 + registry.requestMatchers("/admin-api/ocr/**").authenticated(); + } + }; + } + +} diff --git a/yudao-module-ocr/yudao-module-ocr-server/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-module-ocr/yudao-module-ocr-server/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..76ac1f3 --- /dev/null +++ b/yudao-module-ocr/yudao-module-ocr-server/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cn.iocoder.yudao.module.ocr.framework.ocr.config.OcrAutoConfiguration diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index b7d46d0..8dd3763 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -115,6 +115,13 @@ + + + cn.iocoder.cloud + yudao-module-energy-server + ${revision} + + org.springframework.boot