diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..88f8dcb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,41 @@
+# Java class files
+*.class
+
+#package file
+*.war
+*.ear
+
+#kdiff3 ignore
+*.orig
+
+#maven ignore
+target/
+
+#eclipse ignore
+.settings/
+.project
+.classpath
+
+#idea
+.idea/
+/idea/
+/out/
+*.ipr
+*.iml
+*.iws
+
+#temp file
+*.log
+*.cache
+*.diff
+*.patch
+*.tmp
+*.log.gz
+
+# system ignore
+.DS_Store
+Thumbs.db
+.apt_generated/
+.factorypath
+rebel.xml
+generator/dist/
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..132404b
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..fea3135
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1731982764438
+
+
+ 1731982764438
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/deploy/bin/spring-boot.sh b/deploy/bin/spring-boot.sh
new file mode 100644
index 0000000..02231c1
--- /dev/null
+++ b/deploy/bin/spring-boot.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+SpringBoot=$2
+
+if [ "$1" = "" ];
+then
+ echo -e "\033[0;31m 未输入操作名 \033[0m \033[0;34m {start|stop|restart|status} \033[0m"
+ exit 1
+fi
+
+if [ "$SpringBoot" = "" ];
+then
+ echo -e "\033[0;31m 未输入应用名 \033[0m"
+ exit 1
+fi
+
+function start()
+{
+ count=`ps -ef |grep java|grep $SpringBoot|grep -v grep|wc -l`
+ if [ $count != 0 ];then
+ echo "$SpringBoot is running..."
+ else
+ echo "Start $SpringBoot success..."
+ nohup java -jar $SpringBoot > /dev/null 2>&1 &
+ fi
+}
+
+function stop()
+{
+ echo "Stop $SpringBoot"
+ boot_id=`ps -ef |grep java|grep $SpringBoot|grep -v grep|awk '{print $2}'`
+ count=`ps -ef |grep java|grep $SpringBoot|grep -v grep|wc -l`
+
+ if [ $count != 0 ];then
+ kill $boot_id
+ count=`ps -ef |grep java|grep $SpringBoot|grep -v grep|wc -l`
+
+ boot_id=`ps -ef |grep java|grep $SpringBoot|grep -v grep|awk '{print $2}'`
+ kill -9 $boot_id
+ fi
+}
+
+function restart()
+{
+ stop
+ sleep 2
+ start
+}
+
+function status()
+{
+ count=`ps -ef |grep java|grep $SpringBoot|grep -v grep|wc -l`
+ if [ $count != 0 ];then
+ echo "$SpringBoot is running..."
+ else
+ echo "$SpringBoot is not running..."
+ fi
+}
+
+case $1 in
+ start)
+ start;;
+ stop)
+ stop;;
+ restart)
+ restart;;
+ status)
+ status;;
+ *)
+
+ echo -e "\033[0;31m Usage: \033[0m \033[0;34m sh $0 {start|stop|restart|status} {SpringBootJarName} \033[0m
+\033[0;31m Example: \033[0m
+ \033[0;33m sh $0 start esmart-test.jar \033[0m"
+esac
\ No newline at end of file
diff --git a/doc/sql/geyuan-hesi.sql b/doc/sql/geyuan-hesi.sql
new file mode 100644
index 0000000..cd5a9ff
--- /dev/null
+++ b/doc/sql/geyuan-hesi.sql
@@ -0,0 +1,469 @@
+/*
+Navicat MySQL Data Transfer
+
+Source Server : 119.23.149.63
+Source Server Version : 80019
+Source Host : 119.23.149.63:3306
+Source Database : geyuan-hesi
+
+Target Server Type : MYSQL
+Target Server Version : 80019
+File Encoding : 65001
+
+Date: 2024-10-16 11:48:16
+*/
+
+SET FOREIGN_KEY_CHECKS=0;
+
+-- ----------------------------
+-- Table structure for `fin_filing_sync_cursor`
+-- ----------------------------
+DROP TABLE IF EXISTS `fin_filing_sync_cursor`;
+CREATE TABLE `fin_filing_sync_cursor` (
+ `cursor_id` bigint NOT NULL AUTO_INCREMENT COMMENT '游标ID',
+ `channel_id` varchar(64) DEFAULT '' COMMENT '输入渠道',
+ `form_id` varchar(128) DEFAULT '' COMMENT '输入表单ID',
+ `start_cursor` datetime DEFAULT NULL COMMENT '开始游标',
+ `end_cursor` datetime DEFAULT NULL COMMENT '结束游标',
+ `sync_num` int DEFAULT '0' COMMENT '同步数量',
+ `trace_id` varchar(64) DEFAULT '' COMMENT '日志跟踪ID',
+ `create_by` varchar(64) DEFAULT '' COMMENT '创建者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ `remark` varchar(4096) DEFAULT NULL COMMENT '备注',
+ PRIMARY KEY (`cursor_id`),
+ KEY `index_channel_id_form_id` (`channel_id`,`form_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=63 DEFAULT CHARSET=utf8 COMMENT='财务归档同步游标表';
+
+-- ----------------------------
+-- Records of fin_filing_sync_cursor
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `fin_filing_sync_log`
+-- ----------------------------
+DROP TABLE IF EXISTS `fin_filing_sync_log`;
+CREATE TABLE `fin_filing_sync_log` (
+ `log_id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志ID',
+ `input_channel_id` varchar(64) DEFAULT '' COMMENT '输入渠道ID',
+ `input_form_id` varchar(128) DEFAULT '' COMMENT '输入表单ID',
+ `input_data_id` varchar(64) DEFAULT '' COMMENT '输入渠道返回的数据唯一标示',
+ `input_data` text COMMENT '输入数据原始JSON,记录起来,同步失败时,方便定位问题及补刀',
+ `input_data_at_json` json DEFAULT NULL COMMENT '输入数据包含的附件地址',
+ `output_channel_id` varchar(64) DEFAULT '' COMMENT '输出渠道ID',
+ `output_form_id` varchar(128) DEFAULT '' COMMENT '输出表单ID',
+ `output_data_id` varchar(64) DEFAULT '' COMMENT '输出渠道返回的数据唯一标示',
+ `sync_state` int DEFAULT '0' COMMENT '同步状态:0-初始化,1-成功,2-失败',
+ `error_msg` text COMMENT '错误原因',
+ `at_sync_state` int DEFAULT '0' COMMENT '附件同步状态:0-初始化,1-成功,2-失败',
+ `at_error_msg` text COMMENT '错误原因',
+ `trace_id` varchar(64) DEFAULT '' COMMENT '日志跟踪ID',
+ `create_by` varchar(64) DEFAULT '' COMMENT '创建者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ `remark` varchar(4096) DEFAULT NULL COMMENT '备注',
+ PRIMARY KEY (`log_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=56 DEFAULT CHARSET=utf8 COMMENT='财务归档同步日志表';
+
+-- ----------------------------
+-- Records of fin_filing_sync_log
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `QRTZ_BLOB_TRIGGERS`
+-- ----------------------------
+DROP TABLE IF EXISTS `QRTZ_BLOB_TRIGGERS`;
+CREATE TABLE `QRTZ_BLOB_TRIGGERS` (
+ `sched_name` varchar(120) COLLATE utf8mb4_general_ci NOT NULL COMMENT '调度名称',
+ `trigger_name` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键',
+ `trigger_group` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
+ `blob_data` blob COMMENT '存放持久化Trigger对象',
+ PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`),
+ CONSTRAINT `QRTZ_BLOB_TRIGGERS_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `QRTZ_TRIGGERS` (`sched_name`, `trigger_name`, `trigger_group`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='Blob类型的触发器表';
+
+-- ----------------------------
+-- Records of QRTZ_BLOB_TRIGGERS
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `QRTZ_CALENDARS`
+-- ----------------------------
+DROP TABLE IF EXISTS `QRTZ_CALENDARS`;
+CREATE TABLE `QRTZ_CALENDARS` (
+ `sched_name` varchar(120) COLLATE utf8mb4_general_ci NOT NULL COMMENT '调度名称',
+ `calendar_name` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT '日历名称',
+ `calendar` blob NOT NULL COMMENT '存放持久化calendar对象',
+ PRIMARY KEY (`sched_name`,`calendar_name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='日历信息表';
+
+-- ----------------------------
+-- Records of QRTZ_CALENDARS
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `QRTZ_CRON_TRIGGERS`
+-- ----------------------------
+DROP TABLE IF EXISTS `QRTZ_CRON_TRIGGERS`;
+CREATE TABLE `QRTZ_CRON_TRIGGERS` (
+ `sched_name` varchar(120) COLLATE utf8mb4_general_ci NOT NULL COMMENT '调度名称',
+ `trigger_name` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键',
+ `trigger_group` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
+ `cron_expression` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'cron表达式',
+ `time_zone_id` varchar(80) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '时区',
+ PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`),
+ CONSTRAINT `QRTZ_CRON_TRIGGERS_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `QRTZ_TRIGGERS` (`sched_name`, `trigger_name`, `trigger_group`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='Cron类型的触发器表';
+
+-- ----------------------------
+-- Records of QRTZ_CRON_TRIGGERS
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `QRTZ_FIRED_TRIGGERS`
+-- ----------------------------
+DROP TABLE IF EXISTS `QRTZ_FIRED_TRIGGERS`;
+CREATE TABLE `QRTZ_FIRED_TRIGGERS` (
+ `sched_name` varchar(120) COLLATE utf8mb4_general_ci NOT NULL COMMENT '调度名称',
+ `entry_id` varchar(95) COLLATE utf8mb4_general_ci NOT NULL COMMENT '调度器实例id',
+ `trigger_name` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键',
+ `trigger_group` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
+ `instance_name` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT '调度器实例名',
+ `fired_time` bigint NOT NULL COMMENT '触发的时间',
+ `sched_time` bigint NOT NULL COMMENT '定时器制定的时间',
+ `priority` int NOT NULL COMMENT '优先级',
+ `state` varchar(16) COLLATE utf8mb4_general_ci NOT NULL COMMENT '状态',
+ `job_name` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '任务名称',
+ `job_group` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '任务组名',
+ `is_nonconcurrent` varchar(1) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '是否并发',
+ `requests_recovery` varchar(1) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '是否接受恢复执行',
+ PRIMARY KEY (`sched_name`,`entry_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='已触发的触发器表';
+
+-- ----------------------------
+-- Records of QRTZ_FIRED_TRIGGERS
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `QRTZ_JOB_DETAILS`
+-- ----------------------------
+DROP TABLE IF EXISTS `QRTZ_JOB_DETAILS`;
+CREATE TABLE `QRTZ_JOB_DETAILS` (
+ `sched_name` varchar(120) COLLATE utf8mb4_general_ci NOT NULL COMMENT '调度名称',
+ `job_name` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务名称',
+ `job_group` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务组名',
+ `description` varchar(250) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '相关介绍',
+ `job_class_name` varchar(250) COLLATE utf8mb4_general_ci NOT NULL COMMENT '执行任务类名称',
+ `is_durable` varchar(1) COLLATE utf8mb4_general_ci NOT NULL COMMENT '是否持久化',
+ `is_nonconcurrent` varchar(1) COLLATE utf8mb4_general_ci NOT NULL COMMENT '是否并发',
+ `is_update_data` varchar(1) COLLATE utf8mb4_general_ci NOT NULL COMMENT '是否更新数据',
+ `requests_recovery` varchar(1) COLLATE utf8mb4_general_ci NOT NULL COMMENT '是否接受恢复执行',
+ `job_data` blob COMMENT '存放持久化job对象',
+ PRIMARY KEY (`sched_name`,`job_name`,`job_group`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='任务详细信息表';
+
+-- ----------------------------
+-- Records of QRTZ_JOB_DETAILS
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `QRTZ_LOCKS`
+-- ----------------------------
+DROP TABLE IF EXISTS `QRTZ_LOCKS`;
+CREATE TABLE `QRTZ_LOCKS` (
+ `sched_name` varchar(120) COLLATE utf8mb4_general_ci NOT NULL COMMENT '调度名称',
+ `lock_name` varchar(40) COLLATE utf8mb4_general_ci NOT NULL COMMENT '悲观锁名称',
+ PRIMARY KEY (`sched_name`,`lock_name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='存储的悲观锁信息表';
+
+-- ----------------------------
+-- Records of QRTZ_LOCKS
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `QRTZ_PAUSED_TRIGGER_GRPS`
+-- ----------------------------
+DROP TABLE IF EXISTS `QRTZ_PAUSED_TRIGGER_GRPS`;
+CREATE TABLE `QRTZ_PAUSED_TRIGGER_GRPS` (
+ `sched_name` varchar(120) COLLATE utf8mb4_general_ci NOT NULL COMMENT '调度名称',
+ `trigger_group` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
+ PRIMARY KEY (`sched_name`,`trigger_group`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='暂停的触发器表';
+
+-- ----------------------------
+-- Records of QRTZ_PAUSED_TRIGGER_GRPS
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `QRTZ_SCHEDULER_STATE`
+-- ----------------------------
+DROP TABLE IF EXISTS `QRTZ_SCHEDULER_STATE`;
+CREATE TABLE `QRTZ_SCHEDULER_STATE` (
+ `sched_name` varchar(120) COLLATE utf8mb4_general_ci NOT NULL COMMENT '调度名称',
+ `instance_name` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT '实例名称',
+ `last_checkin_time` bigint NOT NULL COMMENT '上次检查时间',
+ `checkin_interval` bigint NOT NULL COMMENT '检查间隔时间',
+ PRIMARY KEY (`sched_name`,`instance_name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='调度器状态表';
+
+-- ----------------------------
+-- Records of QRTZ_SCHEDULER_STATE
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `QRTZ_SIMPLE_TRIGGERS`
+-- ----------------------------
+DROP TABLE IF EXISTS `QRTZ_SIMPLE_TRIGGERS`;
+CREATE TABLE `QRTZ_SIMPLE_TRIGGERS` (
+ `sched_name` varchar(120) COLLATE utf8mb4_general_ci NOT NULL COMMENT '调度名称',
+ `trigger_name` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键',
+ `trigger_group` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
+ `repeat_count` bigint NOT NULL COMMENT '重复的次数统计',
+ `repeat_interval` bigint NOT NULL COMMENT '重复的间隔时间',
+ `times_triggered` bigint NOT NULL COMMENT '已经触发的次数',
+ PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`),
+ CONSTRAINT `QRTZ_SIMPLE_TRIGGERS_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `QRTZ_TRIGGERS` (`sched_name`, `trigger_name`, `trigger_group`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='简单触发器的信息表';
+
+-- ----------------------------
+-- Records of QRTZ_SIMPLE_TRIGGERS
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `QRTZ_SIMPROP_TRIGGERS`
+-- ----------------------------
+DROP TABLE IF EXISTS `QRTZ_SIMPROP_TRIGGERS`;
+CREATE TABLE `QRTZ_SIMPROP_TRIGGERS` (
+ `sched_name` varchar(120) COLLATE utf8mb4_general_ci NOT NULL COMMENT '调度名称',
+ `trigger_name` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键',
+ `trigger_group` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
+ `str_prop_1` varchar(512) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'String类型的trigger的第一个参数',
+ `str_prop_2` varchar(512) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'String类型的trigger的第二个参数',
+ `str_prop_3` varchar(512) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'String类型的trigger的第三个参数',
+ `int_prop_1` int DEFAULT NULL COMMENT 'int类型的trigger的第一个参数',
+ `int_prop_2` int DEFAULT NULL COMMENT 'int类型的trigger的第二个参数',
+ `long_prop_1` bigint DEFAULT NULL COMMENT 'long类型的trigger的第一个参数',
+ `long_prop_2` bigint DEFAULT NULL COMMENT 'long类型的trigger的第二个参数',
+ `dec_prop_1` decimal(13,4) DEFAULT NULL COMMENT 'decimal类型的trigger的第一个参数',
+ `dec_prop_2` decimal(13,4) DEFAULT NULL COMMENT 'decimal类型的trigger的第二个参数',
+ `bool_prop_1` varchar(1) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Boolean类型的trigger的第一个参数',
+ `bool_prop_2` varchar(1) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Boolean类型的trigger的第二个参数',
+ PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`),
+ CONSTRAINT `QRTZ_SIMPROP_TRIGGERS_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `QRTZ_TRIGGERS` (`sched_name`, `trigger_name`, `trigger_group`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='同步机制的行锁表';
+
+-- ----------------------------
+-- Records of QRTZ_SIMPROP_TRIGGERS
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `QRTZ_TRIGGERS`
+-- ----------------------------
+DROP TABLE IF EXISTS `QRTZ_TRIGGERS`;
+CREATE TABLE `QRTZ_TRIGGERS` (
+ `sched_name` varchar(120) COLLATE utf8mb4_general_ci NOT NULL COMMENT '调度名称',
+ `trigger_name` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT '触发器的名字',
+ `trigger_group` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT '触发器所属组的名字',
+ `job_name` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'qrtz_job_details表job_name的外键',
+ `job_group` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'qrtz_job_details表job_group的外键',
+ `description` varchar(250) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '相关介绍',
+ `next_fire_time` bigint DEFAULT NULL COMMENT '上一次触发时间(毫秒)',
+ `prev_fire_time` bigint DEFAULT NULL COMMENT '下一次触发时间(默认为-1表示不触发)',
+ `priority` int DEFAULT NULL COMMENT '优先级',
+ `trigger_state` varchar(16) COLLATE utf8mb4_general_ci NOT NULL COMMENT '触发器状态',
+ `trigger_type` varchar(8) COLLATE utf8mb4_general_ci NOT NULL COMMENT '触发器的类型',
+ `start_time` bigint NOT NULL COMMENT '开始时间',
+ `end_time` bigint DEFAULT NULL COMMENT '结束时间',
+ `calendar_name` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '日程表名称',
+ `misfire_instr` smallint DEFAULT NULL COMMENT '补偿执行的策略',
+ `job_data` blob COMMENT '存放持久化job对象',
+ PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`),
+ KEY `sched_name` (`sched_name`,`job_name`,`job_group`),
+ CONSTRAINT `QRTZ_TRIGGERS_ibfk_1` FOREIGN KEY (`sched_name`, `job_name`, `job_group`) REFERENCES `QRTZ_JOB_DETAILS` (`sched_name`, `job_name`, `job_group`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='触发器详细信息表';
+
+-- ----------------------------
+-- Records of QRTZ_TRIGGERS
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `sys_config`
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_config`;
+CREATE TABLE `sys_config` (
+ `config_id` int NOT NULL AUTO_INCREMENT COMMENT '参数主键',
+ `config_name` varchar(100) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '参数名称',
+ `config_key` varchar(100) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '参数键名',
+ `config_value` varchar(500) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '参数键值',
+ `config_type` char(1) COLLATE utf8mb4_general_ci DEFAULT 'N' COMMENT '系统内置(Y是 N否)',
+ `create_by` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '创建者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ `update_by` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '更新者',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ `remark` varchar(500) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
+ PRIMARY KEY (`config_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='参数配置表';
+
+-- ----------------------------
+-- Records of sys_config
+-- ----------------------------
+INSERT INTO `sys_config` VALUES ('1', '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'admin', '2024-10-11 15:32:44', '', null, '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow');
+INSERT INTO `sys_config` VALUES ('2', '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', '2024-10-11 15:32:44', '', null, '初始化密码 123456');
+INSERT INTO `sys_config` VALUES ('3', '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', '2024-10-11 15:32:44', '', null, '深色主题theme-dark,浅色主题theme-light');
+INSERT INTO `sys_config` VALUES ('4', '账号自助-验证码开关', 'sys.account.captchaEnabled', 'true', 'Y', 'admin', '2024-10-11 15:32:44', '', null, '是否开启验证码功能(true开启,false关闭)');
+INSERT INTO `sys_config` VALUES ('5', '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'admin', '2024-10-11 15:32:44', '', null, '是否开启注册用户功能(true开启,false关闭)');
+INSERT INTO `sys_config` VALUES ('6', '用户登录-黑名单列表', 'sys.login.blackIPList', '', 'Y', 'admin', '2024-10-11 15:32:44', '', null, '设置登录IP黑名单限制,多个匹配项以;分隔,支持匹配(*通配、网段)');
+
+-- ----------------------------
+-- Table structure for `sys_dict_data`
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_dict_data`;
+CREATE TABLE `sys_dict_data` (
+ `dict_code` bigint NOT NULL AUTO_INCREMENT COMMENT '字典编码',
+ `dict_sort` int DEFAULT '0' COMMENT '字典排序',
+ `dict_label` varchar(100) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '字典标签',
+ `dict_value` varchar(100) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '字典键值',
+ `dict_type` varchar(100) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '字典类型',
+ `css_class` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '样式属性(其他样式扩展)',
+ `list_class` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '表格回显样式',
+ `is_default` char(1) COLLATE utf8mb4_general_ci DEFAULT 'N' COMMENT '是否默认(Y是 N否)',
+ `status` char(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '状态(0正常 1停用)',
+ `create_by` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '创建者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ `update_by` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '更新者',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ `remark` varchar(500) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
+ PRIMARY KEY (`dict_code`)
+) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='字典数据表';
+
+-- ----------------------------
+-- Records of sys_dict_data
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `sys_dict_type`
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_dict_type`;
+CREATE TABLE `sys_dict_type` (
+ `dict_id` bigint NOT NULL AUTO_INCREMENT COMMENT '字典主键',
+ `dict_name` varchar(100) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '字典名称',
+ `dict_type` varchar(100) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '字典类型',
+ `status` char(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '状态(0正常 1停用)',
+ `create_by` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '创建者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ `update_by` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '更新者',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ `remark` varchar(500) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
+ PRIMARY KEY (`dict_id`),
+ UNIQUE KEY `dict_type` (`dict_type`)
+) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='字典类型表';
+
+-- ----------------------------
+-- Records of sys_dict_type
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `sys_job`
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_job`;
+CREATE TABLE `sys_job` (
+ `job_id` bigint NOT NULL AUTO_INCREMENT COMMENT '任务ID',
+ `job_name` varchar(64) NOT NULL DEFAULT '' COMMENT '任务名称',
+ `job_group` varchar(64) NOT NULL DEFAULT 'DEFAULT' COMMENT '任务组名',
+ `invoke_target` varchar(500) NOT NULL COMMENT '调用目标字符串',
+ `cron_expression` varchar(255) DEFAULT '' COMMENT 'cron执行表达式',
+ `misfire_policy` varchar(20) DEFAULT '3' COMMENT '计划执行错误策略(1立即执行 2执行一次 3放弃执行)',
+ `concurrent` char(1) DEFAULT '1' COMMENT '是否并发执行(0允许 1禁止)',
+ `status` char(1) DEFAULT '0' COMMENT '状态(0正常 1暂停)',
+ `create_by` varchar(64) DEFAULT '' COMMENT '创建者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ `remark` varchar(500) DEFAULT '' COMMENT '备注信息',
+ PRIMARY KEY (`job_id`,`job_name`,`job_group`)
+) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='定时任务调度表';
+
+-- ----------------------------
+-- Records of sys_job
+-- ----------------------------
+INSERT INTO `sys_job` VALUES ('1', '系统默认(无参)', 'DEFAULT', 'ryTask.ryNoParams', '0/10 * * * * ?', '3', '1', '1', 'admin', '2024-10-14 05:24:40', '', null, '');
+INSERT INTO `sys_job` VALUES ('2', '系统默认(有参)', 'DEFAULT', 'ryTask.ryParams(\'ry\')', '0/15 * * * * ?', '3', '1', '1', 'admin', '2024-10-14 05:24:40', '', null, '');
+INSERT INTO `sys_job` VALUES ('3', '系统默认(多参)', 'DEFAULT', 'ryTask.ryMultipleParams(\'ry\', true, 2000L, 316.50D, 100)', '0/20 * * * * ?', '3', '1', '1', 'admin', '2024-10-14 05:24:40', '', null, '');
+INSERT INTO `sys_job` VALUES ('100', '差旅和外出申请同步', 'DEFAULT', 'abnormalRetryTask.retry', '0 0/30 * * * ?', '3', '1', '0', 'admin', '2024-10-15 02:51:04', '', null, '');
+
+-- ----------------------------
+-- Table structure for `sys_job_log`
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_job_log`;
+CREATE TABLE `sys_job_log` (
+ `job_log_id` bigint NOT NULL AUTO_INCREMENT COMMENT '任务日志ID',
+ `job_name` varchar(64) NOT NULL COMMENT '任务名称',
+ `job_group` varchar(64) NOT NULL COMMENT '任务组名',
+ `invoke_target` varchar(500) NOT NULL COMMENT '调用目标字符串',
+ `job_message` varchar(500) DEFAULT NULL COMMENT '日志信息',
+ `status` char(1) DEFAULT '0' COMMENT '执行状态(0正常 1失败)',
+ `exception_info` varchar(2000) DEFAULT '' COMMENT '异常信息',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ PRIMARY KEY (`job_log_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='定时任务调度日志表';
+
+-- ----------------------------
+-- Records of sys_job_log
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `sys_logininfor`
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_logininfor`;
+CREATE TABLE `sys_logininfor` (
+ `info_id` bigint NOT NULL AUTO_INCREMENT COMMENT '访问ID',
+ `user_name` varchar(50) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户账号',
+ `ipaddr` varchar(128) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '登录IP地址',
+ `login_location` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '登录地点',
+ `browser` varchar(50) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '浏览器类型',
+ `os` varchar(50) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '操作系统',
+ `status` char(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '登录状态(0成功 1失败)',
+ `msg` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '提示消息',
+ `login_time` datetime DEFAULT NULL COMMENT '访问时间',
+ PRIMARY KEY (`info_id`),
+ KEY `idx_sys_logininfor_s` (`status`),
+ KEY `idx_sys_logininfor_lt` (`login_time`)
+) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统访问记录';
+
+-- ----------------------------
+-- Records of sys_logininfor
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for `sys_user`
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_user`;
+CREATE TABLE `sys_user` (
+ `user_id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
+ `dept_id` bigint DEFAULT NULL COMMENT '部门ID',
+ `user_name` varchar(30) COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户账号',
+ `nick_name` varchar(30) COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户昵称',
+ `user_type` varchar(2) COLLATE utf8mb4_general_ci DEFAULT '00' COMMENT '用户类型(00系统用户)',
+ `email` varchar(50) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户邮箱',
+ `phonenumber` varchar(11) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '手机号码',
+ `sex` char(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '用户性别(0男 1女 2未知)',
+ `avatar` varchar(100) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '头像地址',
+ `password` varchar(100) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '密码',
+ `status` char(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '帐号状态(0正常 1停用)',
+ `del_flag` char(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)',
+ `login_ip` varchar(128) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '最后登录IP',
+ `login_date` datetime DEFAULT NULL COMMENT '最后登录时间',
+ `create_by` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '创建者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ `update_by` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '更新者',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ `remark` varchar(500) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
+ PRIMARY KEY (`user_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户信息表';
+
+-- ----------------------------
+-- Records of sys_user
+-- ----------------------------
+INSERT INTO `sys_user` VALUES ('1', '103', 'admin', '玮驰', '00', null, null, '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', null, '2024-10-11 15:32:36', 'admin', '2024-10-11 15:32:36', '', null, '管理员');
diff --git a/doc/框架说明文档.docx b/doc/框架说明文档.docx
new file mode 100644
index 0000000..4f1ece1
Binary files /dev/null and b/doc/框架说明文档.docx differ
diff --git a/fin-filing-admin/pom.xml b/fin-filing-admin/pom.xml
new file mode 100644
index 0000000..8f4aa13
--- /dev/null
+++ b/fin-filing-admin/pom.xml
@@ -0,0 +1,68 @@
+
+
+
+ dipinshi-hesi
+ cn.jiutqy
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ fin-filing-admin
+
+
+ 8
+ 8
+
+
+
+
+ cn.jiutqy
+ fin-filing-common
+
+
+
+ cn.jiutqy
+ fin-filing-quartz
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 2.5.15
+
+ true
+
+
+
+
+ repackage
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.1.0
+
+ false
+ ${project.artifactId}
+
+
+
+ ${project.artifactId}
+
+
\ No newline at end of file
diff --git a/fin-filing-admin/src/main/java/cn/jiutqy/finfiling/AdminApplication.java b/fin-filing-admin/src/main/java/cn/jiutqy/finfiling/AdminApplication.java
new file mode 100644
index 0000000..5221ec1
--- /dev/null
+++ b/fin-filing-admin/src/main/java/cn/jiutqy/finfiling/AdminApplication.java
@@ -0,0 +1,22 @@
+package cn.jiutqy.finfiling;
+
+import lombok.extern.slf4j.Slf4j;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.ComponentScans;
+
+
+@Slf4j
+@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
+@ComponentScans({@ComponentScan("cn.jiutqy")})
+@MapperScan({"cn.jiutqy.**.mapper"})
+public class AdminApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(AdminApplication.class, args);
+ }
+
+}
\ No newline at end of file
diff --git a/fin-filing-admin/src/main/resources/META-INF/spring-devtools.properties b/fin-filing-admin/src/main/resources/META-INF/spring-devtools.properties
new file mode 100644
index 0000000..37e7b58
--- /dev/null
+++ b/fin-filing-admin/src/main/resources/META-INF/spring-devtools.properties
@@ -0,0 +1 @@
+restart.include.json=/com.alibaba.fastjson2.*.jar
\ No newline at end of file
diff --git a/fin-filing-admin/src/main/resources/application-dev.yml b/fin-filing-admin/src/main/resources/application-dev.yml
new file mode 100644
index 0000000..9985951
--- /dev/null
+++ b/fin-filing-admin/src/main/resources/application-dev.yml
@@ -0,0 +1,115 @@
+# 项目相关配置
+jiutqy:
+ # 名称
+ name: 九天青云财务归档平台
+ # 版本
+ version: 3.8.8
+ # 版权年份
+ copyrightYear: 2024
+ # 文件路径 示例( Windows配置D:/jiutqy/uploadPath,Linux配置 /home/jiutqy/uploadPath)
+ profile: D:/jiutqy/uploadPath
+ # 获取ip地址开关
+ addressEnabled: false
+ # 验证码类型 math 数字计算 char 字符验证
+ captchaType: math
+
+
+# 开发环境配置
+server:
+ # 服务器的HTTP端口,默认为8080
+ port: 8080
+ servlet:
+ # 应用的访问路径
+ context-path: /
+ tomcat:
+ # tomcat的URI编码
+ uri-encoding: UTF-8
+ # 连接数满后的排队数,默认为100
+ accept-count: 1000
+ threads:
+ # tomcat最大线程数,默认为200
+ max: 800
+ # Tomcat启动初始化的线程数,默认值10
+ min-spare: 100
+
+# 日志配置
+logging:
+ level:
+ cn.jiutqy: debug
+ org.springframework: warn
+
+# token配置
+token:
+ # 令牌自定义标识
+ header: Authorization
+ # 令牌密钥
+ secret: abcdefghijklmnopqrstuvwxyz
+ # 令牌有效期(默认30分钟)
+ expireTime: 30
+
+
+# Swagger配置
+swagger:
+ # 是否开启swagger
+ enabled: true
+ # 请求前缀
+ pathMapping: /dev-api
+
+
+# 数据源配置
+spring:
+ datasource:
+ druid:
+ stat-view-servlet:
+ enabled: true
+ loginUsername: jiutqy
+ loginPassword: 123456
+ dynamic:
+ druid:
+ initial-size: 5
+ min-idle: 5
+ maxActive: 20
+ maxWait: 60000
+ connectTimeout: 30000
+ socketTimeout: 60000
+ timeBetweenEvictionRunsMillis: 60000
+ minEvictableIdleTimeMillis: 300000
+ validationQuery: SELECT 1 FROM DUAL
+ testWhileIdle: true
+ testOnBorrow: false
+ testOnReturn: false
+ poolPreparedStatements: true
+ maxPoolPreparedStatementPerConnectionSize: 20
+ filters: stat,slf4j
+ connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
+ datasource:
+ # 主库数据源
+ master:
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://127.0.0.1:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: root
+ password:
+
+
+
+finfiling:
+ storeType: yml
+ input:
+ channel:
+ dipinshi:
+ host: https://qyapi.weixin.qq.com
+ oauth:
+ reqUrl: https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpid}}&corpsecret={corpsecret}
+ appId:
+ appSecret:
+
+ output:
+ channel:
+ hosecloud:
+ host: https://app.ekuaibao.com
+ oauth:
+ reqUrl: https://app.ekuaibao.com/api/openapi/v1/auth/getAccessToken
+ appId: 0ed9a207-c594-460c-9245-91dee9260a9c
+ appSecret: fc559d05-bc67-4d34-9c15-e2953fe97bb8
+
+
diff --git a/fin-filing-admin/src/main/resources/application.yml b/fin-filing-admin/src/main/resources/application.yml
new file mode 100644
index 0000000..d9768b6
--- /dev/null
+++ b/fin-filing-admin/src/main/resources/application.yml
@@ -0,0 +1,68 @@
+# 用户配置
+user:
+ password:
+ # 密码最大错误次数
+ maxRetryCount: 5
+ # 密码锁定时间(默认10分钟)
+ lockTime: 10
+
+# Spring配置
+spring:
+ profiles:
+ active: dev
+ # 文件上传
+ servlet:
+ multipart:
+ # 单个文件大小
+ max-file-size: 10MB
+ # 设置总上传的文件大小
+ max-request-size: 20MB
+ # 服务模块
+ devtools:
+ restart:
+ # 热部署开关
+ enabled: true
+
+
+# MyBatis Plus配置
+mybatis-plus:
+ # 搜索指定包别名
+ typeAliasesPackage: cn.jiutqy.**.domain
+ # 配置mapper的扫描,找到所有的mapper.xml映射文件
+ mapperLocations: classpath*:mapper/**/*Mapper.xml
+ # 加载全局的配置文件
+ configLocation: classpath:mybatis/mybatis-config.xml
+ global-config:
+ enable-sql-runner: true
+
+# PageHelper分页插件
+pagehelper:
+ helperDialect: mysql
+ supportMethodsArguments: true
+ params: count=countSql
+
+
+# 防止XSS攻击
+xss:
+ # 过滤开关
+ enabled: true
+ # 排除链接(多个用逗号分隔)
+ excludes: /system/notice
+ # 匹配链接
+ urlPatterns: /system/*,/monitor/*,/tool/*
+
+ok:
+ http:
+ connect-timeout: 60
+ read-timeout: 60
+ write-timeout: 60
+ # 连接池中整体的空闲连接的最大数量
+ max-idle-connections: 200
+ # 连接空闲时间最多为 300 秒
+ keep-alive-duration: 300
+
+tlog:
+ pattern: '$traceId'
+
+
+
diff --git a/fin-filing-admin/src/main/resources/banner.txt b/fin-filing-admin/src/main/resources/banner.txt
new file mode 100644
index 0000000..6f6b449
--- /dev/null
+++ b/fin-filing-admin/src/main/resources/banner.txt
@@ -0,0 +1,11 @@
+
+
+ ( ( ( * ) ( )
+ ( ( )\ ) )\ ) )\ ) ( ( ` ( ( ( /( )\ ) ( /(
+ )\ )\ (()/( (()/( (()/( )\ )\))( ( )\))( ')\()) (()/( )\())
+ (((_)((((_)( /(_)) /(_)) /(_))((((_)( ((_)()\ )\ ((_)()\ )((_)\ /(_))|((_)\
+ )\___ )\ _ )\ (_)) (_))_|(_)) )\ _ )\ (_()((_)((_) _(())\_)() ((_) (_)) |_ ((_)
+((/ __|(_)_\(_)| _ \ | |_ | _ \ (_)_\(_)| \/ || __|\ \((_)/ // _ \ | _ \ | |/ /
+ | (__ / _ \ | _/ | __| | / / _ \ | |\/| || _| \ \/\/ /| (_) || / ' <
+ \___|/_/ \_\ |_| |_| |_|_\ /_/ \_\ |_| |_||___| \_/\_/ \___/ |_|_\ _|\_\
+ :: JIUTQY FRAMEWORK :: (v1.0.0.SNAPSHOT)
\ No newline at end of file
diff --git a/fin-filing-admin/src/main/resources/logback.xml b/fin-filing-admin/src/main/resources/logback.xml
new file mode 100644
index 0000000..57de6d5
--- /dev/null
+++ b/fin-filing-admin/src/main/resources/logback.xml
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${log.pattern}
+
+
+
+
+
+ ${log.path}/sys-info.log
+
+
+
+ ${log.path}/sys-info.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+ INFO
+
+ ACCEPT
+
+ DENY
+
+
+
+
+ ${log.path}/sys-error.log
+
+
+
+ ${log.path}/sys-error.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+ ERROR
+
+ ACCEPT
+
+ DENY
+
+
+
+
+
+ ${log.path}/sys-user.log
+
+
+ ${log.path}/sys-user.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fin-filing-admin/src/main/resources/mybatis/mybatis-config.xml b/fin-filing-admin/src/main/resources/mybatis/mybatis-config.xml
new file mode 100644
index 0000000..ac47c03
--- /dev/null
+++ b/fin-filing-admin/src/main/resources/mybatis/mybatis-config.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/fin-filing-admin/src/test/java/cn/jiutqy/finfiling/TestEmailSend.java b/fin-filing-admin/src/test/java/cn/jiutqy/finfiling/TestEmailSend.java
new file mode 100644
index 0000000..2c19986
--- /dev/null
+++ b/fin-filing-admin/src/test/java/cn/jiutqy/finfiling/TestEmailSend.java
@@ -0,0 +1,25 @@
+package cn.jiutqy.finfiling;
+
+
+import cn.jiutqy.archives.common.utils.email.EmailSendUtil;
+import cn.jiutqy.finfiling.common.dto.FinFilingAccessToken;
+import cn.jiutqy.finfiling.common.enums.ChannelEnum;
+import com.alibaba.fastjson.JSONObject;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
+@TestPropertySource(properties = "server.port=8080")
+public class TestEmailSend {
+
+ @Autowired
+ private EmailSendUtil emailSendUtil;
+
+ @Test
+ public void testEmailSend(){
+ emailSendUtil.sendEmail("pengzhihao@jiutqy.com", "测试邮件", "测试邮件内容");
+ System.out.println("发送结束");
+ }
+}
diff --git a/fin-filing-admin/src/test/java/cn/jiutqy/finfiling/TestHuiLianYiFinFilingService.java b/fin-filing-admin/src/test/java/cn/jiutqy/finfiling/TestHuiLianYiFinFilingService.java
new file mode 100644
index 0000000..032c5b6
--- /dev/null
+++ b/fin-filing-admin/src/test/java/cn/jiutqy/finfiling/TestHuiLianYiFinFilingService.java
@@ -0,0 +1,101 @@
+package cn.jiutqy.finfiling;
+
+import cn.jiutqy.finfiling.common.service.DefaultFormAtFinFilingService;
+import cn.jiutqy.finfiling.common.service.DefaultFormFinFilingService;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
+@TestPropertySource(properties = "server.port=8080")
+public class TestHuiLianYiFinFilingService {
+
+ @Autowired
+ private DefaultFormFinFilingService defaultFormFinFilingService;
+
+ @Autowired
+ private DefaultFormAtFinFilingService defaultFormAtFinFilingService;
+
+ // 测试汇联易附件上传
+ @Test
+ public void testSyncAt(){
+ defaultFormAtFinFilingService.syncData("huilianyi","at");
+ }
+
+ //测试报销单
+ @Test
+ public void testSyncExpense(){
+ String startCursor = "2024-09-26 00:00:00";
+ String endCursor = "2024-09-26 23:59:59";
+ String channelId = "huilianyi";
+ String formId = "expenseReport";
+ defaultFormFinFilingService.syncData(startCursor, endCursor, channelId, formId);
+ }
+
+ //测试报销单
+ @Test
+ public void testSyncExpense2(){
+ String channelId = "huilianyi";
+ String formId = "expenseReport";
+ defaultFormFinFilingService.syncData(channelId, formId);
+ }
+
+ //测试出差申请单
+ @Test
+ public void testSyncTravelApplication(){
+ String startCursor = "2024-09-26 00:00:00";
+ String endCursor = "2024-09-26 23:59:59";
+ String channelId = "huilianyi";
+ String formId = "travelApplication";
+ defaultFormFinFilingService.syncData(startCursor, endCursor, channelId, formId);
+ }
+
+ @Test
+ public void testSyncTravelApplication2(){
+ String channelId = "huilianyi";
+ String formId = "travelApplication";
+ defaultFormFinFilingService.syncData(channelId, formId);
+ }
+
+ //测试招待单
+ @Test
+ public void testSyncReceptionApplication(){
+ String startCursor = "2024-09-26 00:00:00";
+ String endCursor = "2024-09-27 23:59:59";
+ String channelId = "huilianyi";
+ String formId = "receptionApplication";
+ defaultFormFinFilingService.syncData(startCursor, endCursor, channelId, formId);
+
+ }
+
+ //测试借款单
+ @Test
+ public void testLoanBill(){
+ String startCursor = "2024-09-25 00:00:00";
+ String endCursor = "2024-09-28 23:59:59";
+ String channelId = "huilianyi";
+ String formId = "loanBill";
+ defaultFormFinFilingService.syncData(startCursor, endCursor, channelId, formId);
+ }
+
+ //对公报销 + 对公借款
+ @Test
+ public void testForCorporateExpense(){
+ String startCursor = "2024-09-25 00:00:00";
+ String endCursor = "2024-09-29 23:59:59";
+ String channelId = "huilianyi";
+ String formId = "corExpenseReport";
+ defaultFormFinFilingService.syncData(startCursor, endCursor, channelId, formId);
+ }
+
+ @Test
+ public void testInvoice(){
+ String startCursor = "2024-09-25 00:00:00";
+ String endCursor = "2024-09-29 23:59:59";
+ String channelId = "huilianyi";
+ String formId = "invoice";
+ defaultFormFinFilingService.syncData(startCursor, endCursor, channelId, formId);
+ }
+
+}
diff --git a/fin-filing-admin/src/test/java/cn/jiutqy/finfiling/TestU9CFinFilingService.java b/fin-filing-admin/src/test/java/cn/jiutqy/finfiling/TestU9CFinFilingService.java
new file mode 100644
index 0000000..c8c2abb
--- /dev/null
+++ b/fin-filing-admin/src/test/java/cn/jiutqy/finfiling/TestU9CFinFilingService.java
@@ -0,0 +1,34 @@
+package cn.jiutqy.finfiling;
+
+import cn.jiutqy.finfiling.common.service.DefaultFormAtFinFilingService;
+import cn.jiutqy.finfiling.common.service.DefaultFormFinFilingService;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
+@TestPropertySource(properties = "server.port=8080")
+public class TestU9CFinFilingService {
+
+ @Autowired
+ private DefaultFormFinFilingService defaultFormFinFilingService;
+
+ @Autowired
+ private DefaultFormAtFinFilingService defaultFormAtFinFilingService;
+
+ // 测试U9C附件上传
+ @Test
+ public void testSyncAt(){
+ defaultFormAtFinFilingService.syncData("u9c","at");
+ }
+
+ //测试报销单
+ @Test
+ public void testSyncExpense2(){
+ String channelId = "u9c";
+ String formId = "UFData9002021";
+ defaultFormFinFilingService.syncData(channelId, formId);
+ }
+
+}
diff --git a/fin-filing-common/pom.xml b/fin-filing-common/pom.xml
new file mode 100644
index 0000000..6000c37
--- /dev/null
+++ b/fin-filing-common/pom.xml
@@ -0,0 +1,20 @@
+
+
+
+ dipinshi-hesi
+ cn.jiutqy
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ fin-filing-common
+ jar
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/FinFilingConfig.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/FinFilingConfig.java
new file mode 100644
index 0000000..7005094
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/FinFilingConfig.java
@@ -0,0 +1,23 @@
+package cn.jiutqy.finfiling.common.config;
+
+import cn.jiutqy.finfiling.common.config.properties.FinFilingInputProperties;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingMappingProperties;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingOutputProperties;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Data
+@Component
+@ConfigurationProperties(prefix = "finfiling")
+public class FinFilingConfig {
+
+ private String storeType;
+
+ private FinFilingInputProperties input;
+
+ private FinFilingMappingProperties mapping;
+
+ private FinFilingOutputProperties output;
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingChannelProperties.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingChannelProperties.java
new file mode 100644
index 0000000..14ce548
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingChannelProperties.java
@@ -0,0 +1,34 @@
+package cn.jiutqy.finfiling.common.config.properties;
+
+import cn.jiutqy.archives.common.utils.DateUtils;
+import lombok.Data;
+
+import java.util.Map;
+
+@Data
+public class FinFilingChannelProperties {
+
+ private String channelId;
+
+ private String host;
+
+ private Integer pageNum = 1;
+
+ private Integer pageSize = 5;
+
+ /**
+ * 首次同步过去多长时间的数据,格式为:1d 1h 1min 1sec,默认为:1d
+ */
+ private String firstPassTime = "30d";
+
+ private String cursorFormat = DateUtils.YYYY_MM_DD_HH_MM_SS;
+
+ private Map reqHeader;
+
+ private FinFilingOauthProperties oauth;
+
+ private Map forms;
+
+ private String key;
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingFormProperties.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingFormProperties.java
new file mode 100644
index 0000000..6bb9e65
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingFormProperties.java
@@ -0,0 +1,41 @@
+package cn.jiutqy.finfiling.common.config.properties;
+
+import lombok.Data;
+
+import java.util.Map;
+
+@Data
+public class FinFilingFormProperties {
+
+ private String formId;
+
+ private Integer pageNum;
+
+ private Integer pageSize;
+
+ /**
+ * 同步过去多长时间的数据,格式为:1d 1h 1min 1sec,默认为:1d
+ */
+ private String firstPassTime;
+
+ private String cursorFormat;
+
+ private String groupByField;
+
+ private String reqUrl;
+
+ private String reqMethod;
+
+ private Map reqParam;
+
+ private Map reqHeader;
+
+ private String reqBody;
+
+ private String resDataRootNode = "$";
+
+ private String resDataIdNode;
+
+ private Integer sleepMS = 100;
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingInputProperties.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingInputProperties.java
new file mode 100644
index 0000000..cb2ac14
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingInputProperties.java
@@ -0,0 +1,13 @@
+package cn.jiutqy.finfiling.common.config.properties;
+
+import lombok.Data;
+
+import java.util.Map;
+
+@Data
+public class FinFilingInputProperties {
+
+
+ private Map channel;
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingMappingChannelRelationProperties.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingMappingChannelRelationProperties.java
new file mode 100644
index 0000000..f9b460d
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingMappingChannelRelationProperties.java
@@ -0,0 +1,12 @@
+package cn.jiutqy.finfiling.common.config.properties;
+
+import lombok.Data;
+
+@Data
+public class FinFilingMappingChannelRelationProperties {
+
+ private String inputChannelId;
+
+ private String outputChannelId;
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingMappingFieldRelationProperties.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingMappingFieldRelationProperties.java
new file mode 100644
index 0000000..c39744d
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingMappingFieldRelationProperties.java
@@ -0,0 +1,12 @@
+package cn.jiutqy.finfiling.common.config.properties;
+
+import lombok.Data;
+
+@Data
+public class FinFilingMappingFieldRelationProperties {
+
+ private String inputField;
+
+ private String outputField;
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingMappingFormRelationProperties.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingMappingFormRelationProperties.java
new file mode 100644
index 0000000..759c09b
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingMappingFormRelationProperties.java
@@ -0,0 +1,16 @@
+package cn.jiutqy.finfiling.common.config.properties;
+
+import lombok.Data;
+
+import java.util.Map;
+
+@Data
+public class FinFilingMappingFormRelationProperties {
+
+ private String inputFormId;
+
+ private String outputFormId;
+
+ private String outputAtFormId;
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingMappingProperties.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingMappingProperties.java
new file mode 100644
index 0000000..5a26de1
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingMappingProperties.java
@@ -0,0 +1,12 @@
+package cn.jiutqy.finfiling.common.config.properties;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class FinFilingMappingProperties {
+
+ private List relation;
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingMappingRelationProperties.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingMappingRelationProperties.java
new file mode 100644
index 0000000..7acdc73
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingMappingRelationProperties.java
@@ -0,0 +1,18 @@
+package cn.jiutqy.finfiling.common.config.properties;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class FinFilingMappingRelationProperties {
+
+ private FinFilingMappingChannelRelationProperties channelRelation;
+
+ private FinFilingMappingFormRelationProperties formRelation;
+
+ private List fieldRelation;
+
+
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingOauthProperties.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingOauthProperties.java
new file mode 100644
index 0000000..b64b33f
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingOauthProperties.java
@@ -0,0 +1,18 @@
+package cn.jiutqy.finfiling.common.config.properties;
+
+import lombok.Data;
+
+@Data
+public class FinFilingOauthProperties {
+
+ private String reqUrl;
+
+ private String reqMethod;
+
+ private String appId;
+
+ private String appSecret;
+
+ private String channelKey;
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingOutputProperties.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingOutputProperties.java
new file mode 100644
index 0000000..1bdbbc8
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/config/properties/FinFilingOutputProperties.java
@@ -0,0 +1,12 @@
+package cn.jiutqy.finfiling.common.config.properties;
+
+import lombok.Data;
+
+import java.util.Map;
+
+@Data
+public class FinFilingOutputProperties {
+
+ private Map channel;
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/domain/FinFilingSyncCursor.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/domain/FinFilingSyncCursor.java
new file mode 100644
index 0000000..13633e3
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/domain/FinFilingSyncCursor.java
@@ -0,0 +1,49 @@
+package cn.jiutqy.finfiling.common.domain;
+
+import cn.jiutqy.archives.common.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+@TableName("fin_filing_sync_cursor")
+public class FinFilingSyncCursor extends BaseEntity {
+
+ @TableId(type = IdType.AUTO)
+ private Long cursorId;
+
+ /**
+ * 输入渠道ID
+ */
+ private String channelId;
+
+ /**
+ * 输入表单ID
+ */
+ private String formId;
+
+ /**
+ * 开始游标
+ */
+ private Date startCursor;
+
+ /**
+ * 结束游标
+ */
+ private Date endCursor;
+
+ /**
+ * 同步数量
+ */
+ private Integer syncNum;
+
+ /**
+ * 日志跟踪ID
+ */
+ private String traceId;
+
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/domain/FinFilingSyncLog.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/domain/FinFilingSyncLog.java
new file mode 100644
index 0000000..9d9b37b
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/domain/FinFilingSyncLog.java
@@ -0,0 +1,83 @@
+package cn.jiutqy.finfiling.common.domain;
+
+import cn.jiutqy.archives.common.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName("fin_filing_sync_log")
+public class FinFilingSyncLog extends BaseEntity {
+
+ @TableId(type = IdType.AUTO)
+ private Long logId;
+
+ /**
+ * 输入渠道ID
+ */
+ private String inputChannelId;
+
+ /**
+ * 输入表单ID
+ */
+ private String inputFormId;
+
+ /**
+ * 输入渠道返回的数据唯一标示
+ */
+ private String inputDataId;
+
+ /**
+ * 输入数据原始JSON,记录起来,同步失败时,方便定位问题及补刀
+ */
+ private String inputData;
+
+ /**
+ * 输入数据包含的附件地址
+ */
+ private String inputDataAtJson;
+
+
+ /**
+ * 输出渠道ID
+ */
+ private String outputChannelId;
+
+ /**
+ * 输出表单ID
+ */
+ private String outputFormId;
+
+ /**
+ * 输出渠道返回的数据唯一标示
+ */
+ private String outputDataId;
+
+ /**
+ * 同步状态:0-初始化,1-成功,2-失败
+ */
+ private Integer syncState;
+
+ /**
+ * 错误原因
+ */
+ private String errorMsg;
+
+ /**
+ * 附件同步状态:0-初始化,1-成功,2-失败
+ */
+ private Integer atSyncState;
+
+ /**
+ * 错误原因
+ */
+ private String atErrorMsg;
+
+ /**
+ * 日志跟踪ID
+ */
+ private String traceId;
+
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/dto/FinFilingAccessToken.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/dto/FinFilingAccessToken.java
new file mode 100644
index 0000000..1591121
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/dto/FinFilingAccessToken.java
@@ -0,0 +1,16 @@
+package cn.jiutqy.finfiling.common.dto;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@Data
+public class FinFilingAccessToken {
+
+ private String accessToken;
+
+ private String refreshToken;
+
+ private Long expireTime;
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/dto/FinFilingData.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/dto/FinFilingData.java
new file mode 100644
index 0000000..c0944d5
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/dto/FinFilingData.java
@@ -0,0 +1,33 @@
+package cn.jiutqy.finfiling.common.dto;
+
+import com.alibaba.fastjson2.JSONObject;
+import lombok.Data;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+
+@Data
+public class FinFilingData {
+
+ private String inputDataId;
+
+ private JSONObject inputData;
+
+ private FinFilingDataAtJson inputDataAtJson;
+
+ private String outputDataId;
+
+ private JSONObject outputData;
+
+ public void addFinFilingDataAtUploadUrls(List uploadUrls){
+ if(CollectionUtils.isEmpty(uploadUrls)){
+ return;
+ }
+ if(null == inputDataAtJson){
+ inputDataAtJson = new FinFilingDataAtJson();
+ }
+ inputDataAtJson.setType("1");
+ inputDataAtJson.getUploadUrls().addAll(uploadUrls);
+ }
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/dto/FinFilingDataAtJson.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/dto/FinFilingDataAtJson.java
new file mode 100644
index 0000000..a94ed59
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/dto/FinFilingDataAtJson.java
@@ -0,0 +1,20 @@
+package cn.jiutqy.finfiling.common.dto;
+
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class FinFilingDataAtJson {
+
+ /**
+ * 文件关联类型不能为空,0-关联源文件,1-关联附件,2-关联电子凭证验签包
+ */
+ private String type;
+
+ /**
+ * 上传文件信息数组
+ */
+ private List uploadUrls = new ArrayList<>();
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/dto/FinFilingDataAtUploadUrl.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/dto/FinFilingDataAtUploadUrl.java
new file mode 100644
index 0000000..528453d
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/dto/FinFilingDataAtUploadUrl.java
@@ -0,0 +1,22 @@
+package cn.jiutqy.finfiling.common.dto;
+
+import lombok.Data;
+
+@Data
+public class FinFilingDataAtUploadUrl {
+
+ /**
+ * 文件唯一标识,如果type = 0,非必填;如果type = 1 或 2,必填;
+ */
+ private String fileKey;
+
+ /**
+ * 文件名称
+ */
+ private String fileName;
+
+ /**
+ * 文件url
+ */
+ private String url;
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/dto/FinFilingJSONObject.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/dto/FinFilingJSONObject.java
new file mode 100644
index 0000000..b80c574
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/dto/FinFilingJSONObject.java
@@ -0,0 +1,8 @@
+package cn.jiutqy.finfiling.common.dto;
+
+import com.alibaba.fastjson2.JSONObject;
+
+public class FinFilingJSONObject extends JSONObject {
+
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/ChannelEnum.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/ChannelEnum.java
new file mode 100644
index 0000000..2dd9aeb
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/ChannelEnum.java
@@ -0,0 +1,47 @@
+package cn.jiutqy.finfiling.common.enums;
+
+import cn.jiutqy.finfiling.common.service.IFinFilingChannelService;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum ChannelEnum implements IFinFilingChannelService {
+
+
+ U9C("u9c"),
+ GE_YUAN("geyuan"),
+
+ DI_PIN_SHI("dipinshi"),
+ HOSECLOUD("hosecloud");
+
+
+ private static final Map CHANNEL_ID_MAPPINGS = new HashMap<>();
+
+ static
+ {
+ for (ChannelEnum channelEnum : values())
+ {
+ CHANNEL_ID_MAPPINGS.put(channelEnum.getChannelId(), channelEnum);
+ }
+ }
+
+ private final String channelId;
+
+
+ ChannelEnum(String channelId) {
+ this.channelId = channelId;
+ }
+
+
+ @Override
+ public String getChannelId() {
+ return channelId;
+ }
+
+
+
+ @Override
+ public IFinFilingChannelService resolveChannelId(String channelId) {
+ return (channelId != null ? CHANNEL_ID_MAPPINGS.get(channelId) : null);
+ }
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/ChannelTypeEnum.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/ChannelTypeEnum.java
new file mode 100644
index 0000000..66a4f03
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/ChannelTypeEnum.java
@@ -0,0 +1,16 @@
+package cn.jiutqy.finfiling.common.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum ChannelTypeEnum {
+
+ IN(1),
+ OUT(2);
+
+ private final Integer type;
+
+ ChannelTypeEnum(Integer type){
+ this.type = type;
+ }
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/DatasourceEnum.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/DatasourceEnum.java
new file mode 100644
index 0000000..d376788
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/DatasourceEnum.java
@@ -0,0 +1,17 @@
+package cn.jiutqy.finfiling.common.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum DatasourceEnum {
+
+
+
+ U9C_UF_SYSTEM("UFSystem");
+
+ private final String datasource;
+
+ DatasourceEnum(String datasource){
+ this.datasource = datasource;
+ }
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/FormEnum.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/FormEnum.java
new file mode 100644
index 0000000..2609f4e
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/FormEnum.java
@@ -0,0 +1,57 @@
+package cn.jiutqy.finfiling.common.enums;
+
+import cn.jiutqy.finfiling.common.service.IFinFilingChannelService;
+import cn.jiutqy.finfiling.common.service.IFinFilingFormService;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum FormEnum implements IFinFilingFormService {
+
+ UF_DATA_9002021("UFData9002021"),
+ UF_DATA_3012018("UFData3012018"),
+ UF_DATA_3022018("UFData3022018"),
+ UF_DATA_3112021("UFData3112021"),
+ UF_DATA_5012021("UFData5012021"),
+ UF_DATA_5022023("UFData5022023"),
+ UF_DATA_5032024("UFData5032024"),
+ UF_DATA_5042024("UFData5042024"),
+ UF_DATA_5052024("UFData5052024"),
+
+ ;
+
+ private static final Map FORM_ID_MAPPINGS = new HashMap<>();
+
+ static
+ {
+ for (FormEnum formEnum : values())
+ {
+ FORM_ID_MAPPINGS.put(formEnum.getFormId(), formEnum);
+ }
+ }
+
+ private IFinFilingChannelService channelService;
+ private String formId;
+
+
+ FormEnum(String formId) {
+ this.formId = formId;
+ this.channelService = ChannelEnum.U9C;
+ }
+
+
+ @Override
+ public String getChannelId() {
+ return channelService.getChannelId();
+ }
+
+ @Override
+ public String getFormId() {
+ return formId;
+ }
+
+ @Override
+ public IFinFilingFormService resolveFormId(String formId) {
+ return (formId != null ? FORM_ID_MAPPINGS.get(formId) : null);
+ }
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/StoreType.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/StoreType.java
new file mode 100644
index 0000000..97faa90
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/StoreType.java
@@ -0,0 +1,5 @@
+package cn.jiutqy.finfiling.common.enums;
+
+public enum StoreType {
+ yml,mysql,redis
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/SyncStateEnum.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/SyncStateEnum.java
new file mode 100644
index 0000000..6136264
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/enums/SyncStateEnum.java
@@ -0,0 +1,20 @@
+package cn.jiutqy.finfiling.common.enums;
+
+public enum SyncStateEnum {
+
+ INIT(0),
+ SUCCESSED(1),
+ FAILED(2);
+
+ private final int value;
+
+ SyncStateEnum(int value)
+ {
+ this.value = value;
+ }
+
+ public int value()
+ {
+ return this.value;
+ }
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/factory/FinFilingAccessTokenFactory.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/factory/FinFilingAccessTokenFactory.java
new file mode 100644
index 0000000..0d7a446
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/factory/FinFilingAccessTokenFactory.java
@@ -0,0 +1,20 @@
+package cn.jiutqy.finfiling.common.factory;
+
+import cn.jiutqy.finfiling.common.service.IFinFilingAccessTokenService;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class FinFilingAccessTokenFactory {
+
+ private static Map CONTAINER = new HashMap<>();
+
+ public static void addContainer(String channelId, IFinFilingAccessTokenService accessTokenService){
+ CONTAINER.put(channelId,accessTokenService);
+ }
+
+ public static IFinFilingAccessTokenService getContainer(String channelId){
+ return CONTAINER.get(channelId);
+ }
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/factory/FinFilingMappingFactory.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/factory/FinFilingMappingFactory.java
new file mode 100644
index 0000000..caeb0a4
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/factory/FinFilingMappingFactory.java
@@ -0,0 +1,36 @@
+package cn.jiutqy.finfiling.common.factory;
+
+import cn.jiutqy.finfiling.common.service.IFinFilingMapping;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class FinFilingMappingFactory {
+
+ private static Map CONTAINER = new HashMap<>();
+
+ public static void addContainer(String channelId, String formId, IFinFilingMapping mappingService){
+ CONTAINER.put(buildContainerKey(channelId,formId),mappingService);
+ }
+
+ public static void addContainer(String channelId, String formId, String groupId, IFinFilingMapping mappingService){
+ CONTAINER.put(buildContainerKey(channelId,formId,groupId),mappingService);
+ }
+
+ public static IFinFilingMapping getContainer(String channelId, String formId, String groupId){
+ return CONTAINER.get(buildContainerKey(channelId,formId,groupId));
+ }
+
+ public static IFinFilingMapping getContainer(String channelId, String formId){
+ return CONTAINER.get(buildContainerKey(channelId,formId));
+ }
+
+ public static String buildContainerKey(String channelId, String formId, String groupId){
+ return channelId + "/" + formId + "/" + groupId;
+ }
+
+ public static String buildContainerKey(String channelId, String formId){
+ return channelId + "/" + formId;
+ }
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/mapper/FinFilingSyncCursorMapper.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/mapper/FinFilingSyncCursorMapper.java
new file mode 100644
index 0000000..50a6197
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/mapper/FinFilingSyncCursorMapper.java
@@ -0,0 +1,12 @@
+package cn.jiutqy.finfiling.common.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import cn.jiutqy.finfiling.common.domain.FinFilingSyncCursor;
+
+public interface FinFilingSyncCursorMapper extends BaseMapper {
+
+
+
+
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/mapper/FinFilingSyncLogMapper.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/mapper/FinFilingSyncLogMapper.java
new file mode 100644
index 0000000..ff63304
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/mapper/FinFilingSyncLogMapper.java
@@ -0,0 +1,10 @@
+package cn.jiutqy.finfiling.common.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import cn.jiutqy.finfiling.common.domain.FinFilingSyncLog;
+
+public interface FinFilingSyncLogMapper extends BaseMapper {
+
+
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/AbstractFinFilingAccessTokenService.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/AbstractFinFilingAccessTokenService.java
new file mode 100644
index 0000000..11ad051
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/AbstractFinFilingAccessTokenService.java
@@ -0,0 +1,74 @@
+package cn.jiutqy.finfiling.common.service;
+
+import cn.jiutqy.archives.common.core.cache.LocalCache;
+import cn.jiutqy.archives.common.exception.ServiceException;
+import cn.jiutqy.finfiling.common.config.FinFilingConfig;
+import cn.jiutqy.finfiling.common.enums.ChannelEnum;
+import cn.jiutqy.finfiling.common.enums.ChannelTypeEnum;
+import com.alibaba.fastjson2.JSON;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingChannelProperties;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingOauthProperties;
+import cn.jiutqy.finfiling.common.dto.FinFilingAccessToken;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+
+@Component
+public abstract class AbstractFinFilingAccessTokenService implements IFinFilingAccessTokenService, InitializingBean {
+
+
+ private static final String FORMAT_REDISKEY = "finfiling:access_token:%s";
+
+ private static ReentrantLock lock = new ReentrantLock();
+
+ @Resource
+ private FinFilingConfig finFilingConfig;
+
+ public FinFilingAccessToken getAccessToken(String channelId, ChannelTypeEnum channelTypeEnum){
+ FinFilingChannelProperties channelProperties;
+ if (channelTypeEnum.equals(ChannelTypeEnum.IN)){
+ channelProperties = finFilingConfig.getInput().getChannel().get(channelId);
+ } else {
+ channelProperties = finFilingConfig.getOutput().getChannel().get(channelId);
+ }
+ channelProperties.setChannelId(channelId);
+ return getAccessToken(channelProperties);
+ }
+
+ @Override
+ public FinFilingAccessToken getAccessToken(FinFilingChannelProperties channelProperties) {
+ String cacheKey = buildCacheKey(channelProperties);
+ FinFilingAccessToken accessToken = null;
+
+ accessToken = JSON.parseObject((String) LocalCache.getCacheObject(cacheKey),FinFilingAccessToken.class);
+
+ if(null != accessToken){
+ return accessToken;
+ }
+
+ lock.lock();
+ try {
+ accessToken = getAccessToken(channelProperties.getOauth());
+ Long timeout = accessToken.getExpireTime() - System.currentTimeMillis();
+ if(timeout > 0){
+ LocalCache.setCacheObject(cacheKey, JSON.toJSONString(accessToken),timeout.intValue(), TimeUnit.MILLISECONDS);
+ }
+ } catch (Exception e){
+ ServiceException exception = new ServiceException("获取AccessToken失败:" + JSON.toJSONString(channelProperties.getOauth()));
+ exception.setDetailMessage(e.getMessage());
+ throw exception;
+ } finally {
+ lock.unlock();
+ }
+ return accessToken;
+ }
+
+ protected abstract FinFilingAccessToken getAccessToken(FinFilingOauthProperties oauthProperties);
+
+ private String buildCacheKey(FinFilingChannelProperties channelProperties){
+ return String.format(FORMAT_REDISKEY, channelProperties.getChannelId());
+ }
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/AbstractFinFilingService.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/AbstractFinFilingService.java
new file mode 100644
index 0000000..372eaee
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/AbstractFinFilingService.java
@@ -0,0 +1,420 @@
+package cn.jiutqy.finfiling.common.service;
+
+import cn.jiutqy.archives.common.enums.HttpMethod;
+import cn.jiutqy.archives.common.utils.DateUtils;
+import cn.jiutqy.archives.common.utils.ExceptionUtil;
+import cn.jiutqy.archives.common.utils.http.OkHttpClientUtil;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.alibaba.fastjson2.JSONPath;
+import com.github.pagehelper.PageInfo;
+import cn.jiutqy.finfiling.common.config.FinFilingConfig;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingChannelProperties;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingFormProperties;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingMappingRelationProperties;
+import cn.jiutqy.finfiling.common.domain.FinFilingSyncCursor;
+import cn.jiutqy.finfiling.common.domain.FinFilingSyncLog;
+import cn.jiutqy.finfiling.common.dto.FinFilingData;
+import cn.jiutqy.finfiling.common.dto.FinFilingDataAtJson;
+import cn.jiutqy.finfiling.common.enums.SyncStateEnum;
+import cn.jiutqy.finfiling.common.factory.FinFilingAccessTokenFactory;
+import cn.jiutqy.finfiling.common.factory.FinFilingMappingFactory;
+import cn.jiutqy.finfiling.common.utils.TimeParser;
+import com.yomahub.tlog.context.TLogContext;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Component
+public abstract class AbstractFinFilingService implements IFinFilingService {
+
+ @Autowired
+ private IFinFilingSyncLogService finFilingSyncLogService;
+
+ @Autowired
+ private IFinFilingSyncCursorService finFilingSyncCursorService;
+
+ @Autowired
+ private FinFilingConfig finFilingConfig;
+
+ public AbstractFinFilingService(){}
+
+ @Override
+ public void syncData(String channelId, String formId) {
+ FinFilingChannelProperties channelProperties = finFilingConfig.getInput().getChannel().get(channelId);
+ FinFilingFormProperties formProperties = channelProperties.getForms().get(formId);
+
+ Integer pageNum = formProperties.getPageNum();
+ if(null == pageNum){
+ pageNum = channelProperties.getPageNum();
+ }
+
+ Integer pageSize = formProperties.getPageSize();
+ if(null == pageSize){
+ pageSize = channelProperties.getPageSize();
+ }
+
+ String firstPassTime = formProperties.getFirstPassTime();
+ if(null == firstPassTime){
+ firstPassTime = channelProperties.getFirstPassTime();
+ }
+
+ String cursorFormat = formProperties.getCursorFormat();
+ if(null == cursorFormat){
+ cursorFormat = channelProperties.getCursorFormat();
+ }
+
+ Date now = new Date();
+ String endCursor = DateUtils.parseDateToStr(cursorFormat, now);
+
+ String startCursor;
+ FinFilingSyncCursor finFilingSyncCursor = finFilingSyncCursorService.findByChannelIdAndFormId(channelId, formId);
+ if(null == finFilingSyncCursor){
+ startCursor = DateUtils.parseDateToStr(cursorFormat, DateUtils.addSeconds(now, -TimeParser.parseTime(firstPassTime)));
+ }else{
+ startCursor = DateUtils.parseDateToStr(cursorFormat, finFilingSyncCursor.getEndCursor());
+ }
+
+ Integer totalCount = syncData(startCursor,endCursor,channelId, formId, pageNum, pageSize, 0);
+
+ finFilingSyncCursor = new FinFilingSyncCursor();
+ finFilingSyncCursor.setChannelId(channelId);
+ finFilingSyncCursor.setFormId(formId);
+ finFilingSyncCursor.setStartCursor(DateUtils.parseDate(startCursor));
+ finFilingSyncCursor.setEndCursor(DateUtils.parseDate(endCursor));
+ finFilingSyncCursor.setSyncNum(totalCount);
+ finFilingSyncCursor.setTraceId(TLogContext.getTraceId());
+ finFilingSyncCursor.setCreateTime(new Date());
+ finFilingSyncCursorService.save(finFilingSyncCursor);
+ }
+
+
+ @Override
+ public void syncData(String startCursor, String endCursor, String channelId, String formId) {
+ FinFilingChannelProperties channelProperties = finFilingConfig.getInput().getChannel().get(channelId);
+ FinFilingFormProperties formProperties = channelProperties.getForms().get(formId);
+
+ Integer pageNum = formProperties.getPageNum();
+ if(null == pageNum){
+ pageNum = channelProperties.getPageNum();
+ }
+
+ Integer pageSize = formProperties.getPageSize();
+ if(null == pageSize){
+ pageSize = channelProperties.getPageSize();
+ }
+ syncData(startCursor,endCursor,channelId, formId, pageNum, pageSize, 0);
+ }
+
+ private int syncData(String startCursor, String endCursor,String channelId, String formId,Integer pageNum,Integer pageSize,Integer totalCount) {
+ // 调用渠道客户系统的接口获取数据
+ PageInfo pageInfo = this.inputData(new FinFilingContext(startCursor, endCursor, channelId, formId,pageNum,pageSize),finFilingConfig);
+ totalCount = totalCount + pageInfo.getList().size();
+
+ // 对输入数据进行分组,key为分组字段的值
+ Map> dataMap = this.groupByInputData(channelId, formId, pageInfo.getList());
+
+ // 将获取到的数据进行转换
+ for (String groupId : dataMap.keySet()) {
+ List dataList = dataMap.get(groupId);
+
+ // 根据分组后的字段获取mapping实现类
+ IFinFilingMapping mappingService = getFinFilingMappingService(channelId, formId, groupId);
+
+ if(null == mappingService){
+ log.error("映射实现类找不到,请检查对应实现类是否配置或者重写afterPropertiesSet方法是否设置了正确的formId值:channelId={},formId={}",channelId,groupId);
+ continue;
+ }
+
+ // 获取映射配置
+ FinFilingMappingRelationProperties mappingRelationProperties = getMappingRelationProperties(channelId,formId, groupId);
+ if(null == mappingRelationProperties){
+ log.warn("mapping配置不正确,当前渠道或表单未配置映射关系:channelId={},formId={}",channelId,groupId);
+ continue;
+ }
+
+ // 初始化上下文对象
+ FinFilingContext context = new FinFilingContext(startCursor,endCursor,mappingRelationProperties);
+
+ // 字段映射
+ mappingService.mapping(dataList, context, mappingRelationProperties, finFilingConfig);
+
+ // 调用渠道客户系统的接口推送数据
+ for (FinFilingData data : dataList) {
+ if (data.getOutputData().isEmpty()){
+ continue;
+ }
+ FinFilingChannelProperties channelProperties = finFilingConfig.getOutput().getChannel().get(context.getOutputChannelId());
+ channelProperties.setChannelId(context.getOutputChannelId());
+ FinFilingFormProperties formProperties = channelProperties.getForms().get(context.getOutputFormId());
+
+ // 记录同步结果,数据同步状态
+ FinFilingSyncLog finFilingSyncLog = null;
+ try {
+ finFilingSyncLog = this.saveSyncLog(data,context);
+ } catch (Exception e) {
+ log.error("写入同步日志失败:{}",JSON.toJSONString(data));
+ continue;
+ }
+
+ try {
+ // 将转换之后的数据同步到合思
+ this.outputData(data,context,finFilingConfig);
+ finFilingSyncLog.setInputDataId(data.getInputDataId());
+ finFilingSyncLog.setSyncState(SyncStateEnum.SUCCESSED.value());
+ finFilingSyncLog.setOutputDataId(data.getOutputDataId());
+ log.info("输出成功:{}", JSON.toJSONString(finFilingSyncLog));
+ } catch (Exception e) {
+ log.error("输出异常",e);
+ // 异常状态才记录输入JSON报文,异常信息
+ finFilingSyncLog.setSyncState(SyncStateEnum.FAILED.value());
+ finFilingSyncLog.setErrorMsg(ExceptionUtil.getExceptionMessage(e));
+ log.error("输出失败:{}", JSON.toJSONString(finFilingSyncLog));
+ }
+
+ try {
+ updateSyncLog(finFilingSyncLog,context);
+ } catch (Exception e) {
+ log.error("修改同步日志失败",e);
+ continue;
+ }
+
+ try {
+ Thread.sleep(formProperties.getSleepMS());
+ } catch (InterruptedException e) {
+ log.error("等待异常", e);
+ //continue;
+ }
+ }
+ }
+
+
+ if (pageInfo.isHasNextPage()) {
+ syncData(startCursor, endCursor, channelId, formId, pageInfo.getNextPage(), pageSize, totalCount);
+ }
+
+ return totalCount;
+ }
+
+ private IFinFilingMapping getFinFilingMappingService(String channelId, String formId, String groupId) {
+ FinFilingChannelProperties channelProperties = finFilingConfig.getInput().getChannel().get(channelId);
+ FinFilingFormProperties formProperties = channelProperties.getForms().get(formId);
+ if (StringUtils.isNotBlank(formProperties.getGroupByField())) {
+ return FinFilingMappingFactory.getContainer(channelId, formId, groupId);
+ }else{
+ return FinFilingMappingFactory.getContainer(channelId, formId);
+ }
+ }
+
+ private Map> groupByInputData(String channelId, String formId, List jsonList) {
+ Map> dataMap = new HashMap<>();
+ FinFilingChannelProperties channelProperties = finFilingConfig.getInput().getChannel().get(channelId);
+ FinFilingFormProperties formProperties = channelProperties.getForms().get(formId);
+ String groupByField = formProperties.getGroupByField();
+ if (StringUtils.isNotBlank(groupByField)) {
+ Map> groupByData = jsonList.stream()
+ .collect(Collectors.groupingBy(json -> json.getString(groupByField)));
+ for (String inputFormId : groupByData.keySet()) {
+ List dataList = toFinFilingDataList(groupByData.get(inputFormId));
+ dataMap.put(inputFormId,dataList);
+ }
+ }else{
+ List dataList = toFinFilingDataList(jsonList);
+ dataMap.put(formId,dataList);
+ }
+ return dataMap;
+ }
+
+ private List toFinFilingDataList(List jsonList){
+ List dataList = new ArrayList<>();
+ for (JSONObject inputData : jsonList) {
+ FinFilingData data = new FinFilingData();
+ data.setInputData(inputData);
+ // 这里初始化mapping方法中就不用初始化了,直接赋值即可
+ data.setOutputData(new JSONObject());
+ dataList.add(data);
+ }
+ return dataList;
+ }
+
+ private FinFilingMappingRelationProperties getMappingRelationProperties(String channelId, String formId, String groupId) {
+ FinFilingChannelProperties channelProperties = finFilingConfig.getInput().getChannel().get(channelId);
+ FinFilingFormProperties formProperties = channelProperties.getForms().get(formId);
+
+ List relationProperties = finFilingConfig.getMapping().getRelation();
+ FinFilingMappingRelationProperties matchedRelationProperty = null;
+ for (FinFilingMappingRelationProperties relationProperty : relationProperties) {
+ String inputChannelId = relationProperty.getChannelRelation().getInputChannelId();
+ String inputFormId = relationProperty.getFormRelation().getInputFormId();
+
+ String sourceKey;
+ if (StringUtils.isNotBlank(formProperties.getGroupByField())) {
+ sourceKey = FinFilingMappingFactory.buildContainerKey(channelId,formId,groupId);
+ }else{
+ sourceKey = FinFilingMappingFactory.buildContainerKey(channelId,formId);
+ }
+
+ String targetKey = FinFilingMappingFactory.buildContainerKey(inputChannelId,inputFormId);
+ if (StringUtils.equalsIgnoreCase(sourceKey, targetKey)) {
+ matchedRelationProperty = relationProperty;
+ break;
+ }
+ }
+ return matchedRelationProperty;
+ }
+
+ protected FinFilingSyncLog saveSyncLog(FinFilingData data, FinFilingContext context){
+ FinFilingSyncLog finFilingSyncLog = buildSyncLog(data,context);
+ finFilingSyncLogService.save(finFilingSyncLog);
+ return finFilingSyncLog;
+ }
+
+
+ protected void updateSyncLog(FinFilingSyncLog finFilingSyncLog,FinFilingContext context) {
+ finFilingSyncLog.setUpdateTime(new Date());
+ finFilingSyncLogService.updateById(finFilingSyncLog);
+ }
+
+ protected FinFilingSyncLog buildSyncLog(FinFilingData data, FinFilingContext context) {
+ FinFilingSyncLog finFilingSyncLog = new FinFilingSyncLog();
+ finFilingSyncLog.setInputChannelId(context.getInputChannelId());
+ finFilingSyncLog.setInputFormId(context.getInputFormId());
+ finFilingSyncLog.setInputDataId((data.getInputDataId()));
+ finFilingSyncLog.setInputData(data.getInputData().toJSONString());
+ FinFilingDataAtJson inputDataAtJson = data.getInputDataAtJson();
+ if (null != inputDataAtJson) {
+ finFilingSyncLog.setInputDataAtJson(JSON.toJSONString(inputDataAtJson));
+ }
+
+ finFilingSyncLog.setOutputChannelId(context.getOutputChannelId());
+ finFilingSyncLog.setOutputFormId((context.getOutputFormId()));
+ finFilingSyncLog.setOutputDataId((data.getOutputDataId()));
+
+ finFilingSyncLog.setSyncState(SyncStateEnum.INIT.value());
+ finFilingSyncLog.setAtSyncState(SyncStateEnum.INIT.value());
+ finFilingSyncLog.setTraceId(TLogContext.getTraceId());
+ Date now = new Date();
+ finFilingSyncLog.setCreateTime(now);
+ finFilingSyncLog.setUpdateTime(now);
+ return finFilingSyncLog;
+ }
+
+ protected Object callData(FinFilingChannelProperties channelProperties, FinFilingFormProperties formProperties,String reqBody, FinFilingContext context){
+ String result = null;
+ String reqUrl = formProperties.getReqUrl();
+ if(!(StringUtils.startsWithIgnoreCase(reqUrl,"http://") || StringUtils.startsWithIgnoreCase(reqUrl,"https://"))){
+ String host = channelProperties.getHost();
+ reqUrl = host + reqUrl;
+ }
+ reqUrl = replaceVariable(reqUrl, context, channelProperties);
+
+ Map reqHeader = replaceVariable(channelProperties.getReqHeader(), context, channelProperties);
+
+ String reqMethod = formProperties.getReqMethod();
+ if(HttpMethod.GET.name().equalsIgnoreCase(reqMethod)){
+ Map reqParam = replaceVariable(formProperties.getReqParam(), context, channelProperties);
+ if(!CollectionUtils.isEmpty(formProperties.getReqHeader())) {
+ if (!CollectionUtils.isEmpty(reqHeader)) {
+ reqHeader.putAll(replaceVariable(formProperties.getReqHeader(), context, channelProperties));
+ } else {
+ reqHeader = replaceVariable(formProperties.getReqHeader(), context, channelProperties);
+ }
+ }
+ result = OkHttpClientUtil.doGet(reqUrl, reqParam, reqHeader);
+ }else if(HttpMethod.POST.name().equalsIgnoreCase(reqMethod)){
+ if(StringUtils.isBlank(reqBody)){
+ reqBody = replaceVariable(formProperties.getReqBody(), context, channelProperties);
+ }
+ if(!CollectionUtils.isEmpty(formProperties.getReqHeader())) {
+ if (!CollectionUtils.isEmpty(reqHeader)) {
+ reqHeader.putAll(replaceVariable(formProperties.getReqHeader(), context, channelProperties));
+ } else {
+ reqHeader = replaceVariable(formProperties.getReqHeader(), context, channelProperties);
+ }
+ }
+ result = OkHttpClientUtil.doPostJson(reqUrl, reqBody, reqHeader);
+ }else{
+ throw new RuntimeException("暂不支持的请求方式:"+reqMethod);
+ }
+ if(StringUtils.isBlank(result)){
+ throw new RuntimeException("接口返回报文为空:"+context);
+ }
+ String resDataRootNode = formProperties.getResDataRootNode();
+ return JSONPath.eval(result, resDataRootNode);
+ }
+
+ private Map replaceVariable(Map param,FinFilingContext context,FinFilingChannelProperties channelProperties) {
+ if (!CollectionUtils.isEmpty(param)) {
+ param = param.entrySet().stream()
+ .map(entry -> {
+ String value = entry.getValue();
+ value = replaceVariable(value,context,channelProperties);
+ return new AbstractMap.SimpleEntry<>(entry.getKey(), value);
+ }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+
+ }
+ return param;
+ }
+
+ private String replaceVariable(String param, FinFilingContext context) {
+ if (StringUtils.isNotBlank(param)) {
+ if(StringUtils.contains(param,"{startCursor}")){
+ param = StringUtils.replace(param, "{startCursor}", context.getStartCursor());
+ }
+ if(StringUtils.contains(param,"{endCursor}")){
+ param = StringUtils.replace(param, "{endCursor}", context.getEndCursor());
+ }
+ if(StringUtils.contains(param,"{pageNum}")){
+ param = StringUtils.replace(param, "{pageNum}", context.getPageNum().toString());
+ }
+ if(StringUtils.contains(param,"{pageSize}")){
+ param = StringUtils.replace(param, "{pageSize}", context.getPageSize().toString());
+ }
+ if(StringUtils.contains(param,"{inputChannelId}")){
+ param = StringUtils.replace(param, "{inputChannelId}", context.getInputChannelId());
+ }
+ if(StringUtils.contains(param,"{inputFormId}")){
+ param = StringUtils.replace(param, "{inputFormId}", context.getInputFormId());
+ }
+ if(StringUtils.contains(param,"{outputChannelId}")){
+ param = StringUtils.replace(param, "{outputChannelId}", context.getOutputChannelId());
+ }
+ if(StringUtils.contains(param,"{outputFormId}")){
+ param = StringUtils.replace(param, "{outputFormId}", context.getOutputFormId());
+ }
+ if(StringUtils.contains(param,"{outputDataId}")){
+ param = StringUtils.replace(param, "{outputDataId}", context.getOutputDataId());
+ }
+ }
+ return param;
+ }
+
+ private String replaceVariable(String param, FinFilingContext context,FinFilingChannelProperties channelProperties) {
+ param = replaceVariable(param, context);
+ if (StringUtils.isNotBlank(param)) {
+ if(StringUtils.contains(param,"{accessToken}")){
+ IFinFilingAccessTokenService accessTokenService = getAccessTokenService(channelProperties.getChannelId());
+ String accessToken = accessTokenService.getAccessToken(channelProperties).getAccessToken();
+ param = StringUtils.replace(param, "{accessToken}", accessToken);
+ }
+ }
+ return param;
+ }
+
+ protected IFinFilingAccessTokenService getAccessTokenService(String channelId){
+ return FinFilingAccessTokenFactory.getContainer(channelId);
+ }
+
+ protected abstract PageInfo inputData(FinFilingContext context, FinFilingConfig finFilingConfig);
+
+ protected abstract void outputData(FinFilingData data, FinFilingContext context, FinFilingConfig finFilingConfig);
+
+
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/DefaultFormAtFinFilingService.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/DefaultFormAtFinFilingService.java
new file mode 100644
index 0000000..c6e5bea
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/DefaultFormAtFinFilingService.java
@@ -0,0 +1,84 @@
+package cn.jiutqy.finfiling.common.service;
+
+import cn.jiutqy.archives.common.exception.ServiceException;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.alibaba.fastjson2.JSONPath;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.pagehelper.PageInfo;
+import cn.jiutqy.finfiling.common.config.FinFilingConfig;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingChannelProperties;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingFormProperties;
+import cn.jiutqy.finfiling.common.domain.FinFilingSyncLog;
+import cn.jiutqy.finfiling.common.dto.FinFilingData;
+import cn.jiutqy.finfiling.common.enums.SyncStateEnum;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.List;
+
+@Slf4j
+@Component
+public class DefaultFormAtFinFilingService extends AbstractFinFilingService{
+
+ @Autowired
+ private IFinFilingSyncLogService finFilingSyncLogService;
+
+
+ @Override
+ protected PageInfo inputData(FinFilingContext context, FinFilingConfig finFilingConfig) {
+ LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
+ queryWrapper.eq(FinFilingSyncLog::getInputChannelId,context.getInputChannelId());
+ //queryWrapper.likeRight(FinFilingSyncLog::getInputFormId,context.getInputFormId());
+ queryWrapper.eq(FinFilingSyncLog::getSyncState, SyncStateEnum.SUCCESSED.value());
+ queryWrapper.ne(FinFilingSyncLog::getAtSyncState, SyncStateEnum.SUCCESSED.value());
+
+ Page page = new Page<>(context.getPageNum(),context.getPageSize());
+ page = finFilingSyncLogService.page(page,queryWrapper);
+
+ List jsonList = (List) JSON.toJSON(page.getRecords());
+
+ PageInfo pageInfo = new PageInfo<>(jsonList);
+
+ pageInfo.setHasNextPage(page.hasNext());
+ pageInfo.setNextPage(context.getPageNum() + 1);
+
+ return pageInfo;
+
+ }
+
+ @Override
+ protected void outputData(FinFilingData data, FinFilingContext context, FinFilingConfig finFilingConfig){
+ FinFilingChannelProperties channelProperties = finFilingConfig.getOutput().getChannel().get(context.getOutputChannelId());
+ channelProperties.setChannelId(context.getOutputChannelId());
+ FinFilingFormProperties formProperties = channelProperties.getForms().get(context.getOutputFormId());
+
+ Object result = callData(channelProperties,formProperties,String.valueOf(data.getOutputData()),context);
+ String outputDataId = null;
+ try {
+ outputDataId = (String) JSONPath.eval(result, formProperties.getResDataIdNode());
+ } catch (Exception e) {
+ throw new ServiceException("无法解析resDataIdNode,返回报文:"+result);
+ }
+ context.addOutputDataId(outputDataId);
+ }
+
+ @Override
+ protected FinFilingSyncLog saveSyncLog(FinFilingData data, FinFilingContext context) {
+ FinFilingSyncLog finFilingSyncLog = data.getInputData().toJavaObject(FinFilingSyncLog.class);
+ return finFilingSyncLog;
+ }
+
+ @Override
+ protected void updateSyncLog(FinFilingSyncLog finFilingSyncLog, FinFilingContext context) {
+ FinFilingSyncLog entity = new FinFilingSyncLog();
+ entity.setLogId(finFilingSyncLog.getLogId());
+ entity.setAtSyncState(finFilingSyncLog.getSyncState());
+ entity.setAtErrorMsg(finFilingSyncLog.getErrorMsg());
+ entity.setUpdateTime(new Date());
+ finFilingSyncLogService.updateById(entity);
+ }
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/DefaultFormFinFilingService.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/DefaultFormFinFilingService.java
new file mode 100644
index 0000000..583910f
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/DefaultFormFinFilingService.java
@@ -0,0 +1,66 @@
+package cn.jiutqy.finfiling.common.service;
+
+import cn.jiutqy.archives.common.exception.ServiceException;
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.alibaba.fastjson2.JSONPath;
+import com.github.pagehelper.PageInfo;
+import cn.jiutqy.finfiling.common.config.FinFilingConfig;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingChannelProperties;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingFormProperties;
+import cn.jiutqy.finfiling.common.dto.FinFilingData;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+@Slf4j
+@Component
+public class DefaultFormFinFilingService extends AbstractFinFilingService{
+
+
+ @Override
+ protected PageInfo inputData(FinFilingContext context, FinFilingConfig finFilingConfig){
+ FinFilingChannelProperties channelProperties = finFilingConfig.getInput().getChannel().get(context.getInputChannelId());
+ channelProperties.setChannelId(context.getInputChannelId());
+ FinFilingFormProperties formProperties = channelProperties.getForms().get(context.getInputFormId());
+
+ JSONArray jsonArray = (JSONArray)callData(channelProperties, formProperties, null, context);
+
+ List jsonList = IntStream.range(0, jsonArray.size())
+ .mapToObj(jsonArray::getJSONObject)
+ .collect(Collectors.toList());
+
+ PageInfo pageInfo = new PageInfo<>(jsonList);
+
+ pageInfo.setHasNextPage(jsonList.size() == context.getPageSize());
+ pageInfo.setNextPage(context.getPageNum() + 1);
+
+ return pageInfo;
+ }
+
+ @Override
+ protected void outputData(FinFilingData data, FinFilingContext context, FinFilingConfig finFilingConfig){
+ FinFilingChannelProperties channelProperties = finFilingConfig.getOutput().getChannel().get(context.getOutputChannelId());
+ channelProperties.setChannelId(context.getOutputChannelId());
+ FinFilingFormProperties formProperties = channelProperties.getForms().get(context.getOutputFormId());
+
+ Object result = callData(channelProperties,formProperties,String.valueOf(data.getOutputData()),context);
+ log.info("输出报文:{}",result);
+ String outputDataId = null;
+ try {
+ outputDataId = (String) JSONPath.eval(result, formProperties.getResDataIdNode());
+ } catch (Exception e) {
+ throw new ServiceException("无法解析resDataIdNode,返回报文:"+result+" 上下文:"+context);
+ }
+
+ if(StringUtils.isBlank(outputDataId)){
+ throw new ServiceException("无法解析resDataIdNode,返回报文: "+ result+" 上下文:"+context);
+ }
+ data.setOutputDataId(outputDataId);
+ }
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/FinFilingContext.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/FinFilingContext.java
new file mode 100644
index 0000000..6f4b680
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/FinFilingContext.java
@@ -0,0 +1,157 @@
+package cn.jiutqy.finfiling.common.service;
+
+import cn.jiutqy.finfiling.common.config.properties.FinFilingMappingChannelRelationProperties;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingMappingFormRelationProperties;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingMappingRelationProperties;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+public class FinFilingContext {
+
+ public static final String PARAM_STARTCURSOR = "startCursor";
+ public static final String PARAM_ENDCURSOR = "endCursor";
+ public static final String PARAM_PAGENUM = "pageNum";
+ public static final String PARAM_PAGESIZE = "pageSize";
+ public static final String PARAM_INPUTCHANNELID = "inputChannelId";
+ public static final String PARAM_OUTPUTCHANNELID = "outputChannelId";
+ public static final String PARAM_INPUTFORMID = "inputFormId";
+ public static final String PARAM_OUTPUTFORMID = "outputFormId";
+ public static final String PARAM_OUTPUTDATAID = "outputDataId";
+
+ private Map context;
+
+ public FinFilingContext() {
+ this(null,null,null,null,null,null);
+ }
+
+ public FinFilingContext(String startCursor,String endCursor,String inputChannelId,String inputFormId,Integer pageNum,Integer pageSize) {
+ this.context = new HashMap<>();
+ if (StringUtils.isNotBlank(startCursor)) {
+ this.context.put(PARAM_STARTCURSOR,startCursor);
+ }
+ if (StringUtils.isNotBlank(endCursor)) {
+ this.context.put(PARAM_ENDCURSOR,endCursor);
+ }
+ if (StringUtils.isNotBlank(inputChannelId)) {
+ this.context.put(PARAM_INPUTCHANNELID,inputChannelId);
+ }
+ if (StringUtils.isNotBlank(inputFormId)) {
+ this.context.put(PARAM_INPUTFORMID,inputFormId);
+ }
+ if (null != pageNum) {
+ this.context.put(PARAM_PAGENUM,pageNum);
+ }
+ if (null != pageSize) {
+ this.context.put(PARAM_PAGESIZE,pageSize);
+ }
+ }
+
+ public FinFilingContext(String startCursor, String endCursor, FinFilingMappingRelationProperties mappingRelationProperties) {
+ this.context = new HashMap<>();
+ if (StringUtils.isNotBlank(startCursor)) {
+ this.context.put(PARAM_STARTCURSOR,startCursor);
+ }
+ if (StringUtils.isNotBlank(endCursor)) {
+ this.context.put(PARAM_ENDCURSOR,endCursor);
+ }
+ FinFilingMappingChannelRelationProperties channelRelation = mappingRelationProperties.getChannelRelation();
+ if (StringUtils.isNotBlank(channelRelation.getInputChannelId())) {
+ this.context.put(PARAM_INPUTCHANNELID,channelRelation.getInputChannelId());
+ }
+ if (StringUtils.isNotBlank(channelRelation.getOutputChannelId())) {
+ this.context.put(PARAM_OUTPUTCHANNELID,channelRelation.getOutputChannelId());
+ }
+
+ FinFilingMappingFormRelationProperties formRelation = mappingRelationProperties.getFormRelation();
+ if (StringUtils.isNotBlank(formRelation.getInputFormId())) {
+ this.context.put(PARAM_INPUTFORMID,formRelation.getInputFormId());
+ }
+ if (StringUtils.isNotBlank(formRelation.getOutputFormId())) {
+ this.context.put(PARAM_OUTPUTFORMID,formRelation.getOutputFormId());
+ }
+ }
+
+ public FinFilingContext add(String key,Object value){
+ context.put(key,value);
+ return this;
+ }
+
+ public FinFilingContext addOutputFormId(Object value){
+ context.put(PARAM_OUTPUTFORMID,value);
+ return this;
+ }
+
+ public FinFilingContext addOutputChannelId(Object value){
+ context.put(PARAM_OUTPUTCHANNELID,value);
+ return this;
+ }
+
+ public Object get(String key){
+ return context.get(key);
+ }
+
+ public String getString(String key){
+ return String.valueOf(context.get(key));
+ }
+
+ public Integer getInteger(String key){
+ return (Integer) context.get(key);
+ }
+
+ public Long getLong(String key){
+ return (Long)context.get(key);
+ }
+
+ public Boolean isBoolean(String key){
+ return (Boolean)context.get(key);
+ }
+
+ public String getStartCursor(){
+ return String.valueOf(context.get(PARAM_STARTCURSOR));
+ }
+ public String getEndCursor(){
+ return String.valueOf(context.get(PARAM_ENDCURSOR));
+ }
+
+ public Integer getPageNum(){
+ return (Integer) context.get(PARAM_PAGENUM);
+ }
+
+ public Integer getPageSize(){
+ return (Integer) context.get(PARAM_PAGESIZE);
+ }
+
+ public String getInputChannelId(){
+ return String.valueOf(context.get(PARAM_INPUTCHANNELID));
+ }
+ public String getOutputChannelId(){
+ return String.valueOf(context.get(PARAM_OUTPUTCHANNELID));
+ }
+
+ public String getInputFormId(){
+ return String.valueOf(context.get(PARAM_INPUTFORMID));
+ }
+
+ public String getOutputFormId(){
+ return String.valueOf(context.get(PARAM_OUTPUTFORMID));
+ }
+
+ public String getOutputDataId(){
+ return String.valueOf(context.get(PARAM_OUTPUTDATAID));
+ }
+
+ public FinFilingContext addOutputDataId(String outputDataId){
+ context.put(PARAM_OUTPUTDATAID,outputDataId);
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "FinFilingContext{" +
+ "context=" + context +
+ '}';
+ }
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/FinFilingSyncCursorService.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/FinFilingSyncCursorService.java
new file mode 100644
index 0000000..a50d933
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/FinFilingSyncCursorService.java
@@ -0,0 +1,33 @@
+package cn.jiutqy.finfiling.common.service;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import cn.jiutqy.finfiling.common.domain.FinFilingSyncCursor;
+import cn.jiutqy.finfiling.common.mapper.FinFilingSyncCursorMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+
+@Service
+public class FinFilingSyncCursorService extends ServiceImpl implements IFinFilingSyncCursorService {
+
+ @Autowired
+ private FinFilingSyncCursorMapper finFilingSyncCursorMapper;
+
+ @Override
+ public FinFilingSyncCursor findByChannelIdAndFormId(String channelId, String formId) {
+ LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper();
+
+ queryWrapper.eq(FinFilingSyncCursor::getChannelId,channelId);
+ queryWrapper.eq(FinFilingSyncCursor::getFormId,formId);
+ queryWrapper.orderByDesc(FinFilingSyncCursor::getEndCursor);
+
+ List list = super.list(queryWrapper);
+ if(CollectionUtils.isEmpty(list)){
+ return null;
+ }
+ return list.get(0);
+ }
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/FinFilingSyncLogService.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/FinFilingSyncLogService.java
new file mode 100644
index 0000000..0dbac13
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/FinFilingSyncLogService.java
@@ -0,0 +1,39 @@
+package cn.jiutqy.finfiling.common.service;
+
+import cn.jiutqy.archives.common.utils.DateUtils;
+import cn.jiutqy.finfiling.common.enums.SyncStateEnum;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import cn.jiutqy.finfiling.common.domain.FinFilingSyncLog;
+import cn.jiutqy.finfiling.common.mapper.FinFilingSyncLogMapper;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+
+@Service
+public class FinFilingSyncLogService extends ServiceImpl implements IFinFilingSyncLogService {
+
+
+ @Override
+ public FinFilingSyncLog getFinFilingSyncLogByInputDataId(String inputDataId) {
+ List list = this.list(new LambdaQueryWrapper()
+ .eq(FinFilingSyncLog::getInputDataId, inputDataId));
+ return list == null || list.isEmpty() ? null : list.get(0);
+ }
+
+ @Override
+ public FinFilingSyncLog getFinFilingSyncLogByInputChannelAndInputDataId(String inputChannelId, String inputDataId) {
+ List list = this.list(new LambdaQueryWrapper()
+ .eq(FinFilingSyncLog::getInputChannelId, inputChannelId)
+ .eq(FinFilingSyncLog::getInputDataId, inputDataId));
+ return list == null || list.isEmpty() ? null : list.get(0);
+ }
+
+ @Override
+ public List listFailFinFiling(Date beforeTime) {
+ return this.list((new LambdaQueryWrapper()
+ .eq(FinFilingSyncLog::getSyncState, SyncStateEnum.FAILED.value()))
+ .ge(FinFilingSyncLog::getCreateTime, beforeTime));
+ }
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingAccessTokenService.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingAccessTokenService.java
new file mode 100644
index 0000000..6dab150
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingAccessTokenService.java
@@ -0,0 +1,18 @@
+package cn.jiutqy.finfiling.common.service;
+
+import cn.jiutqy.finfiling.common.config.properties.FinFilingChannelProperties;
+import cn.jiutqy.finfiling.common.dto.FinFilingAccessToken;
+import cn.jiutqy.finfiling.common.enums.ChannelTypeEnum;
+import cn.jiutqy.finfiling.common.factory.FinFilingAccessTokenFactory;
+
+public interface IFinFilingAccessTokenService {
+
+ FinFilingAccessToken getAccessToken(String channelId, ChannelTypeEnum channelTypeEnum);
+
+ FinFilingAccessToken getAccessToken(FinFilingChannelProperties channelProperties);
+
+ default void registerSelf(IFinFilingChannelService channel, IFinFilingAccessTokenService accessTokenService){
+ FinFilingAccessTokenFactory.addContainer(channel.getChannelId(),accessTokenService);
+ }
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingApiService.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingApiService.java
new file mode 100644
index 0000000..cf85894
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingApiService.java
@@ -0,0 +1,7 @@
+package cn.jiutqy.finfiling.common.service;
+
+public interface IFinFilingApiService {
+
+
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingChannelService.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingChannelService.java
new file mode 100644
index 0000000..780487a
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingChannelService.java
@@ -0,0 +1,10 @@
+package cn.jiutqy.finfiling.common.service;
+
+public interface IFinFilingChannelService {
+
+ String name();
+
+ String getChannelId();
+
+ public IFinFilingChannelService resolveChannelId(String channelId);
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingFormService.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingFormService.java
new file mode 100644
index 0000000..08b1dc4
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingFormService.java
@@ -0,0 +1,13 @@
+package cn.jiutqy.finfiling.common.service;
+
+public interface IFinFilingFormService {
+
+ String name();
+
+ String getChannelId();
+
+ String getFormId();
+
+ IFinFilingFormService resolveFormId(String formId);
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingMapping.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingMapping.java
new file mode 100644
index 0000000..fd19e58
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingMapping.java
@@ -0,0 +1,30 @@
+package cn.jiutqy.finfiling.common.service;
+
+import cn.jiutqy.finfiling.common.config.FinFilingConfig;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingMappingRelationProperties;
+import cn.jiutqy.finfiling.common.dto.FinFilingData;
+import cn.jiutqy.finfiling.common.factory.FinFilingMappingFactory;
+
+import java.util.List;
+
+public interface IFinFilingMapping {
+
+ default void mapping(List dataList, FinFilingContext context, FinFilingMappingRelationProperties mappingRelationProperties, FinFilingConfig finFilingConfig){
+ for (FinFilingData data : dataList) {
+ mapping(data,context,mappingRelationProperties,finFilingConfig);
+ }
+ }
+ //void mapping(List dataList, FinFilingContext context, FinFilingMappingRelationProperties mappingRelationProperties, FinFilingConfig finFilingConfig);
+
+ void mapping(FinFilingData data, FinFilingContext context, FinFilingMappingRelationProperties mappingRelationProperties, FinFilingConfig finFilingConfig);
+
+ default void registerSelf(IFinFilingFormService form, IFinFilingMapping mappingService){
+ FinFilingMappingFactory.addContainer(form.getChannelId(),form.getFormId(),mappingService);
+ }
+
+ default void registerSelf(IFinFilingFormService form, String groupId, IFinFilingMapping mappingService){
+ FinFilingMappingFactory.addContainer(form.getChannelId(),form.getFormId(),groupId,mappingService);
+ }
+
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingService.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingService.java
new file mode 100644
index 0000000..a6be7cd
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingService.java
@@ -0,0 +1,9 @@
+package cn.jiutqy.finfiling.common.service;
+
+public interface IFinFilingService {
+
+ void syncData(String channelId, String formId);
+
+ void syncData(String startCursor, String endCursor,String channelKey, String formKey);
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingSyncCursorService.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingSyncCursorService.java
new file mode 100644
index 0000000..98c30b8
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingSyncCursorService.java
@@ -0,0 +1,11 @@
+package cn.jiutqy.finfiling.common.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import cn.jiutqy.finfiling.common.domain.FinFilingSyncCursor;
+
+public interface IFinFilingSyncCursorService extends IService {
+
+
+ FinFilingSyncCursor findByChannelIdAndFormId(String channelId,String formId);
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingSyncLogService.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingSyncLogService.java
new file mode 100644
index 0000000..083b1da
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/service/IFinFilingSyncLogService.java
@@ -0,0 +1,23 @@
+package cn.jiutqy.finfiling.common.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import cn.jiutqy.finfiling.common.domain.FinFilingSyncLog;
+
+import java.util.Date;
+import java.util.List;
+
+public interface IFinFilingSyncLogService extends IService {
+
+
+ FinFilingSyncLog getFinFilingSyncLogByInputDataId(String inputDataId);
+
+ FinFilingSyncLog getFinFilingSyncLogByInputChannelAndInputDataId(String inputChannelId, String inputDataId);
+
+ /**
+ * 查询同步失败的记录
+ * @return
+ */
+ List listFailFinFiling(Date beforeTime);
+
+
+}
diff --git a/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/utils/TimeParser.java b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/utils/TimeParser.java
new file mode 100644
index 0000000..8f70a5a
--- /dev/null
+++ b/fin-filing-common/src/main/java/cn/jiutqy/finfiling/common/utils/TimeParser.java
@@ -0,0 +1,38 @@
+package cn.jiutqy.finfiling.common.utils;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class TimeParser {
+
+ private static Pattern PATTERN = Pattern.compile("(\\d+)\\s*(d|h|min|sec)");
+
+ public static int parseTime(String timeStr) {
+ int seconds = 0;
+
+ Matcher matcher = PATTERN.matcher(timeStr);
+
+ while (matcher.find()) {
+ int amount = Integer.parseInt(matcher.group(1));
+ String unit = matcher.group(2);
+ switch (unit) {
+ case "d":
+ seconds += amount * 24 * 60 * 60;
+ break;
+ case "h":
+ seconds += amount * 60 * 60;
+ break;
+ case "min":
+ seconds += amount * 60;
+ break;
+ case "sec":
+ seconds += amount;
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown time unit: " + unit);
+ }
+ }
+
+ return seconds;
+ }
+}
\ No newline at end of file
diff --git a/fin-filing-quartz/pom.xml b/fin-filing-quartz/pom.xml
new file mode 100644
index 0000000..5d1b845
--- /dev/null
+++ b/fin-filing-quartz/pom.xml
@@ -0,0 +1,28 @@
+
+
+
+ dipinshi-hesi
+ cn.jiutqy
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ fin-filing-quartz
+
+
+ 8
+ 8
+
+
+
+
+
+ cn.jiutqy
+ fin-filing-common
+
+
+
+
+
\ No newline at end of file
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/DiPinShiAccessTokenService.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/DiPinShiAccessTokenService.java
new file mode 100644
index 0000000..14728fa
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/DiPinShiAccessTokenService.java
@@ -0,0 +1,33 @@
+package cn.jiutqy.finfiling.quartz.dipinshi;
+
+import cn.jiutqy.archives.common.utils.http.OkHttpClientUtil;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingOauthProperties;
+import cn.jiutqy.finfiling.common.dto.FinFilingAccessToken;
+import cn.jiutqy.finfiling.common.enums.ChannelEnum;
+import cn.jiutqy.finfiling.common.service.AbstractFinFilingAccessTokenService;
+import cn.jiutqy.finfiling.common.service.IFinFilingAccessTokenService;
+import cn.jiutqy.finfiling.quartz.dipinshi.dto.DiPinShiAccessToken;
+import com.alibaba.fastjson2.JSON;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.InitializingBean;
+
+public class DiPinShiAccessTokenService extends AbstractFinFilingAccessTokenService implements IFinFilingAccessTokenService, InitializingBean {
+ @Override
+ protected FinFilingAccessToken getAccessToken(FinFilingOauthProperties oauthProperties) {
+ String corpId = oauthProperties.getAppId();
+ String corpSecret = oauthProperties.getAppSecret();
+ String url = StringUtils.replace(oauthProperties.getReqUrl(), "{corpid}", corpId);
+ url = StringUtils.replace(url, "{corpsecret}", corpSecret);
+ String result = OkHttpClientUtil.doGet(url);
+ DiPinShiAccessToken diPinShiAccessToken = JSON.parseObject(result, DiPinShiAccessToken.class);
+ diPinShiAccessToken.setAccessToken(diPinShiAccessToken.getAccess_token());
+ diPinShiAccessToken.setRefreshToken(diPinShiAccessToken.getAccess_token());
+ diPinShiAccessToken.setExpireTime(Long.valueOf(diPinShiAccessToken.getExpires_in()));
+ return diPinShiAccessToken;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ super.registerSelf(ChannelEnum.DI_PIN_SHI,this);
+ }
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/DiPinShiFinFilingService.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/DiPinShiFinFilingService.java
new file mode 100644
index 0000000..d22940d
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/DiPinShiFinFilingService.java
@@ -0,0 +1,106 @@
+package cn.jiutqy.finfiling.quartz.dipinshi;
+
+import cn.jiutqy.archives.common.utils.StringUtils;
+import cn.jiutqy.archives.common.utils.http.OkHttpClientUtil;
+import cn.jiutqy.finfiling.common.enums.ChannelEnum;
+import cn.jiutqy.finfiling.common.enums.ChannelTypeEnum;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.time.*;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+@Component
+public class DiPinShiFinFilingService extends AbstractDiPinShiBaseService implements IDiPinShiFinFilingService{
+
+ private static final String BATCH_APPROVAL_NO = "https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovalinfo?access_token={accessToken}";
+
+ private static final String APPROVAL_NO_DETAIL = "https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovaldetail?access_token={accessToken}";
+
+ private static final String APPLICATION_TEM_ID = "";
+
+ private static final String TRAVEL = "3";
+
+ private static final String GO_OUT = "4";
+
+ @Override
+ public List getBatchApprovalNoTravel(String start,String end,String type) {
+ List spNoList = new ArrayList<>();
+ //构建请求体
+ JSONObject reqBody = buildReqBody(start,end,type);
+ String url = getAccessToken(BATCH_APPROVAL_NO, ChannelEnum.DI_PIN_SHI.getChannelId(), ChannelTypeEnum.IN);
+ String result = OkHttpClientUtil.doPostJson(url, reqBody.toJSONString());
+ JSONObject res = JSONObject.parseObject(JSONObject.toJSONString(result));
+
+ JSONArray jsonArray = res.getJSONArray("sp_no_list");
+ for (Object spNo : jsonArray) {
+ spNoList.add((String) spNo);
+ }
+
+ //判断后面还有没有数据
+ String newNextCursor = res.getString("new_next_cursor");
+ while (StringUtils.isNotBlank(newNextCursor)){
+ result = OkHttpClientUtil.doPostJson(url, reqBody.toJSONString());
+ res = JSONObject.parseObject(JSONObject.toJSONString(result));
+ jsonArray = res.getJSONArray("sp_no_list");
+ for (Object spNo : jsonArray) {
+ spNoList.add((String) spNo);
+ }
+ newNextCursor = res.getString("new_next_cursor");
+ }
+
+ return spNoList;
+ }
+
+ @Override
+ public String getApprovalNoDetail(String approvalNo) {
+ //构建请求体
+ JSONObject reqBody = new JSONObject();
+ reqBody.put("sp_no",approvalNo);
+ String url = getAccessToken(APPROVAL_NO_DETAIL, ChannelEnum.DI_PIN_SHI.getChannelId(), ChannelTypeEnum.IN);
+ return OkHttpClientUtil.doPostJson(url, reqBody.toJSONString());
+ }
+
+ private JSONObject buildReqBody(String start,String end,String type){
+ JSONObject reqBody = new JSONObject();
+ reqBody.put("starttime", convert(start));
+ reqBody.put("endtime", convert(end));
+ reqBody.put("new_cursor","");
+ reqBody.put("size",100);
+ JSONArray filters = new JSONArray();
+ JSONObject template = new JSONObject();
+ template.put("key","template_id");
+ template.put("value",APPLICATION_TEM_ID);
+ JSONObject type1 = new JSONObject();
+ template.put("key","record_type");
+ if ("TRAVEL".equals(type)){
+ template.put("value",TRAVEL);
+ }else {
+ template.put("value",GO_OUT);
+ }
+ filters.add(template);
+ filters.add(type1);
+ reqBody.put("filters",filters);
+ return reqBody;
+ }
+
+ //将日期转成时间戳 xxxx-xx-xx
+ public long convert(String dateStr){
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+ LocalDate date = LocalDate.parse(dateStr, formatter);
+
+ LocalDateTime dateTime = LocalDateTime.of(date, LocalTime.MIDNIGHT);
+
+ ZonedDateTime zonedDateTime = dateTime.atZone(ZoneOffset.UTC);
+
+ return zonedDateTime.toInstant().toEpochMilli();
+ }
+
+
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/IDiPinShiFinFilingService.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/IDiPinShiFinFilingService.java
new file mode 100644
index 0000000..80c13fc
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/IDiPinShiFinFilingService.java
@@ -0,0 +1,13 @@
+package cn.jiutqy.finfiling.quartz.dipinshi;
+
+import java.util.List;
+
+public interface IDiPinShiFinFilingService {
+
+ // 获取批量审批号
+ List getBatchApprovalNoTravel(String start, String end, String type);
+
+ // 获取审批单号详情
+ String getApprovalNoDetail(String approvalNo);
+
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/DiPinShiAttendanceService.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/DiPinShiAttendanceService.java
new file mode 100644
index 0000000..a29c7aa
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/DiPinShiAttendanceService.java
@@ -0,0 +1,29 @@
+package cn.jiutqy.finfiling.quartz.dipinshi.attendance;
+
+import cn.jiutqy.finfiling.quartz.dipinshi.attendance.vo.DiPinShiAttendanceGoOutReqVO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+
+@Component
+@Slf4j
+public class DiPinShiAttendanceService implements IDiPinShiAttendanceService{
+ @Override
+ public void attendanceGoOut(DiPinShiAttendanceGoOutReqVO goOut) {
+ log.info("外出申请单号:{}", goOut.getApprovalNo());
+ //获取合思token
+
+ //构建请求体
+
+ //发送请求
+
+
+
+ }
+
+ @Override
+ public void attenancedTravel(HashMap map) {
+
+ }
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/IDiPinShiAttendanceService.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/IDiPinShiAttendanceService.java
new file mode 100644
index 0000000..2ceba58
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/IDiPinShiAttendanceService.java
@@ -0,0 +1,18 @@
+package cn.jiutqy.finfiling.quartz.dipinshi.attendance;
+
+import cn.jiutqy.finfiling.quartz.dipinshi.attendance.vo.DiPinShiAttendanceGoOutReqVO;
+
+import java.util.HashMap;
+
+public interface IDiPinShiAttendanceService {
+
+ /**
+ * 同步外出
+ */
+ void attendanceGoOut(DiPinShiAttendanceGoOutReqVO goOut);
+
+ /**
+ * 同步出差
+ */
+ void attenancedTravel(HashMap map);
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceGoOutReqVO.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceGoOutReqVO.java
new file mode 100644
index 0000000..c63baf5
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceGoOutReqVO.java
@@ -0,0 +1,9 @@
+package cn.jiutqy.finfiling.quartz.dipinshi.attendance.vo;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DiPinShiAttendanceGoOutReqVO extends DiPinShiAttendanceReqVO{
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceReqVO.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceReqVO.java
new file mode 100644
index 0000000..a256361
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceReqVO.java
@@ -0,0 +1,38 @@
+package cn.jiutqy.finfiling.quartz.dipinshi.attendance.vo;
+
+import lombok.Data;
+
+@Data
+public class DiPinShiAttendanceReqVO {
+
+ /**
+ * 申请人
+ */
+ private String applicant;
+
+ /**
+ * 申请类型
+ */
+ private String applicationType;
+
+ /**
+ * 开始时间
+ */
+ private String startTime;
+
+ /**
+ * 结束时间
+ */
+ private String endTime;
+
+ /**
+ * 审批单号
+ */
+ private String approvalNo;
+
+ /**
+ * 数据
+ */
+ private String data;
+
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceRespVO.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceRespVO.java
new file mode 100644
index 0000000..f8c9942
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceRespVO.java
@@ -0,0 +1,7 @@
+package cn.jiutqy.finfiling.quartz.dipinshi.attendance.vo;
+
+import lombok.Data;
+
+@Data
+public class DiPinShiAttendanceRespVO {
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceTravelInReqVO.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceTravelInReqVO.java
new file mode 100644
index 0000000..7bbddd8
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceTravelInReqVO.java
@@ -0,0 +1,9 @@
+package cn.jiutqy.finfiling.quartz.dipinshi.attendance.vo;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DiPinShiAttendanceTravelInReqVO extends DiPinShiAttendanceReqVO{
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceTravelOutNotUSAReqVO.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceTravelOutNotUSAReqVO.java
new file mode 100644
index 0000000..312b434
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceTravelOutNotUSAReqVO.java
@@ -0,0 +1,9 @@
+package cn.jiutqy.finfiling.quartz.dipinshi.attendance.vo;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DiPinShiAttendanceTravelOutNotUSAReqVO extends DiPinShiAttendanceReqVO{
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceTravelOutReqVO.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceTravelOutReqVO.java
new file mode 100644
index 0000000..167aa0e
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/attendance/vo/DiPinShiAttendanceTravelOutReqVO.java
@@ -0,0 +1,9 @@
+package cn.jiutqy.finfiling.quartz.dipinshi.attendance.vo;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DiPinShiAttendanceTravelOutReqVO extends DiPinShiAttendanceReqVO{
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/dto/DiPinShiAccessToken.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/dto/DiPinShiAccessToken.java
new file mode 100644
index 0000000..4fccf5f
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/dipinshi/dto/DiPinShiAccessToken.java
@@ -0,0 +1,16 @@
+package cn.jiutqy.finfiling.quartz.dipinshi.dto;
+
+import cn.jiutqy.finfiling.common.dto.FinFilingAccessToken;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@Data
+public class DiPinShiAccessToken extends FinFilingAccessToken {
+
+ private String access_token;
+ private String expires_in;
+
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/enums/GeYuanOutboundTypeEnum.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/enums/GeYuanOutboundTypeEnum.java
new file mode 100644
index 0000000..3068103
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/enums/GeYuanOutboundTypeEnum.java
@@ -0,0 +1,28 @@
+package cn.jiutqy.finfiling.quartz.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum GeYuanOutboundTypeEnum {
+
+ GY_ADD("gy_add"),
+ GY_UPDATE("gy_update"),
+ GY_DELETE("gy_delete"),
+ GY_GET("gy_get")
+ ;
+
+ private final String type;
+
+ GeYuanOutboundTypeEnum(String type){
+ this.type = type;
+ }
+
+ public static GeYuanOutboundTypeEnum getByType(String type){
+ for(GeYuanOutboundTypeEnum typeEnum : GeYuanOutboundTypeEnum.values()){
+ if(typeEnum.getType().equals(type)){
+ return typeEnum;
+ }
+ }
+ return null;
+ }
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/enums/U9cMappingHoseEntityIdEnum.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/enums/U9cMappingHoseEntityIdEnum.java
new file mode 100644
index 0000000..978bfc0
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/enums/U9cMappingHoseEntityIdEnum.java
@@ -0,0 +1,30 @@
+package cn.jiutqy.finfiling.quartz.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum U9cMappingHoseEntityIdEnum {
+
+ //测试
+ UF_DATA_900_2021("UFData9002021", "上海玮驰仪器有限公司", "ID01C0qw92g4rB"),
+ //正式
+ UF_DATA_301_2018("UFData3012018", "上海玮驰仪器有限公司", "ID01C0qw92g4rB"),
+ UF_DATA_302_2018("UFData3022018", "上海修睿科学仪器有限公司", "ID01C0qwdSvb9Z"),
+ UF_DATA_311_2021("UFData3112021", "上海看咔科技有限公司", "ID01C0qycSdGnJ"),
+ UF_DATA_501_2021("UFData5012021", "上海逐典生物科技有限公司", "ID01C0qD5FxL7V"),
+ UF_DATA_502_2023("UFData5022023", "上海晴筝科技有限公司", "ID01C0qEk2fic7"),
+ UF_DATA_503_2024("UFData5032024", "上海普纳生物技术有限公司", "ID01C0qJnGX39d"),
+ UF_DATA_504_2024("UFData5042024", "上海阜金生物科技有限公司", "ID01C2KOZrONaf"),
+ UF_DATA_505_2024("UFData5052024", "上海雏田生物技术有限公司", "ID01C0qzCCbwF9");
+
+
+ private final String database;
+ private final String name;
+ private final String id;
+
+ U9cMappingHoseEntityIdEnum(String database, String name, String id){
+ this.database = database;
+ this.name = name;
+ this.id = id;
+ }
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/AbstractHoseCloudBaseService.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/AbstractHoseCloudBaseService.java
new file mode 100644
index 0000000..ba16121
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/AbstractHoseCloudBaseService.java
@@ -0,0 +1,19 @@
+package cn.jiutqy.finfiling.quartz.hosecloud;
+
+import cn.jiutqy.finfiling.common.enums.ChannelTypeEnum;
+import cn.jiutqy.finfiling.common.factory.FinFilingAccessTokenFactory;
+import cn.jiutqy.finfiling.common.service.IFinFilingAccessTokenService;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+@Component
+public abstract class AbstractHoseCloudBaseService {
+
+ protected final String BASE_URL = "https://app.ekuaibao.com";
+
+ protected String getAccessToken(String url, String channelId, ChannelTypeEnum channelTypeEnum){
+ IFinFilingAccessTokenService accessTokenService = FinFilingAccessTokenFactory.getContainer(channelId);
+ String accessToken = accessTokenService.getAccessToken(channelId, channelTypeEnum).getAccessToken();
+ return StringUtils.replace(url, "{accessToken}", accessToken);
+ }
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/HoseCloudAccessToken.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/HoseCloudAccessToken.java
new file mode 100644
index 0000000..81dba49
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/HoseCloudAccessToken.java
@@ -0,0 +1,13 @@
+package cn.jiutqy.finfiling.quartz.hosecloud;
+
+import cn.jiutqy.finfiling.common.dto.FinFilingAccessToken;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@Data
+public class HoseCloudAccessToken extends FinFilingAccessToken {
+
+ private String corporationId;
+
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/HoseCloudFinFilingAccessTokenService.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/HoseCloudFinFilingAccessTokenService.java
new file mode 100644
index 0000000..bc03fde
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/HoseCloudFinFilingAccessTokenService.java
@@ -0,0 +1,38 @@
+package cn.jiutqy.finfiling.quartz.hosecloud;
+
+import cn.jiutqy.archives.common.utils.http.OkHttpClientUtil;
+import cn.jiutqy.finfiling.common.config.properties.FinFilingOauthProperties;
+import cn.jiutqy.finfiling.common.dto.FinFilingAccessToken;
+import cn.jiutqy.finfiling.common.enums.ChannelEnum;
+import cn.jiutqy.finfiling.common.service.AbstractFinFilingAccessTokenService;
+import cn.jiutqy.finfiling.common.service.IFinFilingAccessTokenService;
+import com.alibaba.fastjson2.JSON;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class HoseCloudFinFilingAccessTokenService extends AbstractFinFilingAccessTokenService implements IFinFilingAccessTokenService,InitializingBean {
+
+ @Override
+ public FinFilingAccessToken getAccessToken(FinFilingOauthProperties oauthProperties) {
+ String appId = oauthProperties.getAppId();
+ String appSecret = oauthProperties.getAppSecret();
+
+ Map body = new HashMap<>();
+ body.put("appKey",appId);
+ body.put("appSecurity",appSecret);
+
+ String result = OkHttpClientUtil.doPostJson(oauthProperties.getReqUrl(),JSON.toJSONString(body));
+
+ return JSON.parseObject(JSON.parseObject(result).getString("value"), HoseCloudAccessToken.class);
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ super.registerSelf(ChannelEnum.HOSECLOUD,this);
+ }
+
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/HoseCloudPersonnelService.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/HoseCloudPersonnelService.java
new file mode 100644
index 0000000..ee4f505
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/HoseCloudPersonnelService.java
@@ -0,0 +1,40 @@
+package cn.jiutqy.finfiling.quartz.hosecloud;
+
+import cn.jiutqy.archives.common.utils.StringUtils;
+import cn.jiutqy.archives.common.utils.http.OkHttpClientUtil;
+import cn.jiutqy.finfiling.common.enums.ChannelEnum;
+import cn.jiutqy.finfiling.common.enums.ChannelTypeEnum;;
+import cn.jiutqy.finfiling.quartz.hosecloud.vo.HoseCloudPersonnelVO;
+import com.alibaba.fastjson2.JSON;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Component
+public class HoseCloudPersonnelService extends AbstractHoseCloudBaseService implements IHoseCloudPersonnelService {
+
+ @Override
+ public List queryUser(List ids) {
+ Map body = new HashMap<>();
+ //STAFFID : 员工ID
+ //CODE : 工号
+ //CELLPHONE : 手机号
+ //MAIL : 邮箱
+ //USERID : 第三方ID
+ body.put("type","STAFFID");
+ body.put("conditionIds", ids);
+
+ //请求链接
+ String url = BASE_URL + "/api/openapi/v1/staffs/getStaffIds?accessToken={accessToken}";
+ String result = OkHttpClientUtil.doPostJson(getAccessToken(url, ChannelEnum.HOSECLOUD.getChannelId(), ChannelTypeEnum.OUT),
+ JSON.toJSONString(body));
+ List list = new ArrayList<>();
+ if (StringUtils.isNotBlank(result)){
+ list = JSON.parseArray(JSON.parseObject(result).getString("items"), HoseCloudPersonnelVO.class);
+ }
+ return list.isEmpty() ? null : list;
+ }
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/IHoseCloudPersonnelService.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/IHoseCloudPersonnelService.java
new file mode 100644
index 0000000..e6e2cbf
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/IHoseCloudPersonnelService.java
@@ -0,0 +1,10 @@
+package cn.jiutqy.finfiling.quartz.hosecloud;
+
+import cn.jiutqy.finfiling.quartz.hosecloud.vo.HoseCloudPersonnelVO;
+
+import java.util.List;
+
+public interface IHoseCloudPersonnelService {
+
+ List queryUser(List ids);
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/vo/HoseCloudPersonnelVO.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/vo/HoseCloudPersonnelVO.java
new file mode 100644
index 0000000..eb13d4b
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/hosecloud/vo/HoseCloudPersonnelVO.java
@@ -0,0 +1,19 @@
+package cn.jiutqy.finfiling.quartz.hosecloud.vo;
+
+import lombok.Data;
+
+@Data
+public class HoseCloudPersonnelVO {
+ private String id;
+
+ private String name;
+
+ private String nickName;
+
+ private String code;
+
+ private String defaultDepartment;
+
+ //第三方平台人员ID
+ private String userId;
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/sync/IOutboundSyncDiPinShiService.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/sync/IOutboundSyncDiPinShiService.java
new file mode 100644
index 0000000..5998beb
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/sync/IOutboundSyncDiPinShiService.java
@@ -0,0 +1,15 @@
+package cn.jiutqy.finfiling.quartz.sync;
+
+import cn.jiutqy.finfiling.quartz.enums.GeYuanOutboundTypeEnum;
+
+import java.util.Date;
+import java.util.Map;
+
+public interface IOutboundSyncDiPinShiService {
+
+ void updateSyncTravel(String start, String end);
+
+ void updateSyncGoOut(String start, String end);
+
+ void retry(Date beforeTime);
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/sync/OutboundSyncGeYuanService.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/sync/OutboundSyncGeYuanService.java
new file mode 100644
index 0000000..146ad9f
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/sync/OutboundSyncGeYuanService.java
@@ -0,0 +1,208 @@
+package cn.jiutqy.finfiling.quartz.sync;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.jiutqy.archives.common.utils.ExceptionUtil;
+import cn.jiutqy.archives.common.utils.email.EmailSendUtil;
+import cn.jiutqy.finfiling.common.domain.FinFilingSyncLog;
+import cn.jiutqy.finfiling.common.enums.ChannelEnum;
+import cn.jiutqy.finfiling.common.enums.SyncStateEnum;
+import cn.jiutqy.finfiling.common.service.IFinFilingSyncLogService;
+import cn.jiutqy.finfiling.quartz.dipinshi.IDiPinShiFinFilingService;
+import cn.jiutqy.finfiling.quartz.dipinshi.attendance.IDiPinShiAttendanceService;
+import cn.jiutqy.finfiling.quartz.dipinshi.attendance.vo.*;
+import cn.jiutqy.finfiling.quartz.enums.GeYuanOutboundTypeEnum;
+import cn.jiutqy.finfiling.quartz.hosecloud.HoseCloudPersonnelService;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+
+@Slf4j
+@Component
+public class OutboundSyncGeYuanService implements IOutboundSyncDiPinShiService{
+
+ @Autowired
+ private IFinFilingSyncLogService finFilingSyncLogService;
+
+ @Autowired
+ private IDiPinShiFinFilingService diPinShiFinFilingService;
+
+ @Autowired
+ private IDiPinShiAttendanceService attendanceService;
+
+ private final static String TRAVEL_IN = "国内出差";
+
+ private final static String TRAVEL_OUT = "国际出差";
+
+ private final static String TRAVEL_OUT_NOT_USA = "国际出差非美国";
+
+ @Override
+ public void updateSyncTravel(String start, String end) {
+ //批量获取数据单号
+ List approvalNos = diPinShiFinFilingService.getBatchApprovalNoTravel(start, end , "TRAVEL");
+
+ HashMap map = new HashMap<>();
+ List travelIns = new ArrayList<>();
+ List travelOutNotUSAs = new ArrayList<>();
+ List travelOuts = new ArrayList<>();
+
+ //根据单号查询详情 取出有效数据x
+ for (String approvalNo : approvalNos) {
+ String detail = diPinShiFinFilingService.getApprovalNoDetail(approvalNo);
+
+ //根据类型判断:外出、国内出差、国际出差、国际出差非美国
+
+
+ }
+
+ //记录同步结果
+ if (CollectionUtil.isNotEmpty(travelIns)){
+ travelIns.forEach(this::recordSyncData);
+ }
+ if (CollectionUtil.isNotEmpty(travelOutNotUSAs)){
+ travelOutNotUSAs.forEach(this::recordSyncData);
+ }
+ if (CollectionUtil.isNotEmpty(travelOuts)){
+ travelOuts.forEach(this::recordSyncData);
+ }
+
+ map.put(TRAVEL_IN,travelIns);
+ map.put(TRAVEL_OUT,travelOuts);
+ map.put(TRAVEL_OUT_NOT_USA,travelOutNotUSAs);
+
+ //数据的字段进行映射
+ HashMap reqBodys = travelMapping(map);
+
+ //数据同步到合思
+ attendanceService.attenancedTravel(reqBodys);
+
+
+
+ }
+
+
+
+ @Override
+ public void updateSyncGoOut(String start, String end) {
+ //批量获取数据单号
+ List approvalNos = diPinShiFinFilingService.getBatchApprovalNoTravel(start, end , "GoOut");
+
+ List goOuts = new ArrayList<>();
+ //根据单号查询单号详情
+ for (String approvalNo : approvalNos) {
+ String detail = diPinShiFinFilingService.getApprovalNoDetail(approvalNo);
+ DiPinShiAttendanceGoOutReqVO goOut = JSONObject.parseObject(detail, DiPinShiAttendanceGoOutReqVO.class);
+ goOuts.add(goOut);
+ }
+
+ FinFilingSyncLog finFilingSyncLog;
+ if (CollectionUtil.isNotEmpty(goOuts)){
+ for (DiPinShiAttendanceGoOutReqVO goOut : goOuts) {
+ //记录同步日志
+ try {
+ finFilingSyncLog = finFilingSyncLogService.getFinFilingSyncLogByInputChannelAndInputDataId(ChannelEnum.DI_PIN_SHI.getChannelId(), goOut.getApprovalNo());
+ if (finFilingSyncLog == null){
+ finFilingSyncLog = new FinFilingSyncLog();
+ finFilingSyncLog.setInputChannelId(ChannelEnum.DI_PIN_SHI.getChannelId());
+ finFilingSyncLog.setInputDataId(goOut.getApprovalNo());
+ finFilingSyncLog.setInputData(JSON.toJSONString(goOut.getData()));
+ finFilingSyncLog.setSyncState(SyncStateEnum.INIT.value());
+ finFilingSyncLog.setCreateTime(new Date());
+ finFilingSyncLogService.save(finFilingSyncLog);
+ }
+ } catch (Exception e) {
+ log.error("写入同步日志失败:{}-{}", ChannelEnum.DI_PIN_SHI.getChannelId() , JSON.toJSONString(goOut));
+ return;
+ }
+
+ try {
+ //数据同步到合思,更改同步状态
+ attendanceService.attendanceGoOut(goOut);
+ finFilingSyncLog.setOutputChannelId(ChannelEnum.HOSECLOUD.getChannelId());
+ finFilingSyncLog.setOutputDataId(goOut.getApprovalNo());
+ finFilingSyncLog.setSyncState(SyncStateEnum.SUCCESSED.value());
+ log.info("输出成功:{}", JSON.toJSONString(finFilingSyncLog));
+ } catch (Exception e) {
+ log.error("输出异常",e);
+ finFilingSyncLog.setSyncState(SyncStateEnum.FAILED.value());
+ finFilingSyncLog.setErrorMsg(ExceptionUtil.getExceptionMessage(e));
+ log.error("输出失败:{}", JSON.toJSONString(finFilingSyncLog));
+ }
+
+ try {
+ finFilingSyncLog.setUpdateTime(new Date());
+ finFilingSyncLogService.updateById(finFilingSyncLog);
+ } catch (Exception e) {
+ log.error("修改同步日志失败",e);
+ }
+ }
+ }
+
+
+ }
+
+ private HashMap travelMapping(HashMap map) {
+ HashMap reqBodys = new HashMap<>();
+ List travelInList = new ArrayList<>();
+ List travelOutList = new ArrayList<>();
+ List travelOutNotUSAList = new ArrayList<>();
+
+ //字段映射
+
+ reqBodys.put(TRAVEL_IN,travelInList);
+ reqBodys.put(TRAVEL_OUT,travelOutList);
+ reqBodys.put(TRAVEL_OUT_NOT_USA,travelOutNotUSAList);
+ return reqBodys;
+ }
+
+ //记录同步数据
+ private void recordSyncData(DiPinShiAttendanceReqVO reqVO){
+ FinFilingSyncLog finFilingSyncLog;
+
+ try {
+ finFilingSyncLog = finFilingSyncLogService.getFinFilingSyncLogByInputChannelAndInputDataId(ChannelEnum.DI_PIN_SHI.getChannelId(), "审批单号");
+ if (finFilingSyncLog == null){
+ finFilingSyncLog = new FinFilingSyncLog();
+ finFilingSyncLog.setInputChannelId(ChannelEnum.DI_PIN_SHI.getChannelId());
+ finFilingSyncLog.setInputDataId("审批单号");
+ finFilingSyncLog.setInputData(JSON.toJSONString("获取的数据"));
+ finFilingSyncLog.setSyncState(SyncStateEnum.INIT.value());
+ finFilingSyncLog.setCreateTime(new Date());
+ finFilingSyncLogService.save(finFilingSyncLog);
+ }
+ } catch (Exception e) {
+ log.error("写入同步日志失败:{}-{}", ChannelEnum.DI_PIN_SHI.getChannelId(), reqVO.getData());
+ }
+
+ }
+
+ @Override
+ public void retry(Date beforeTime) {
+ List list = finFilingSyncLogService.listFailFinFiling(beforeTime);
+ list.forEach(item -> {
+ GeYuanOutboundTypeEnum typeEnum = GeYuanOutboundTypeEnum.getByType(item.getInputChannelId());
+ if (typeEnum == null){
+ return;
+ }
+ Map map = JSON.parseObject(item.getInputData());
+
+ });
+ }
+
+
+ //转成日期格式yyyy-mm-dd mm:ss
+ public String convertDateFormat(String stamp){
+ long timestamp = Long.parseLong(stamp);
+
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+ sdf.setTimeZone(TimeZone.getTimeZone("GMT+08:00"));
+
+ Date date = new Date(timestamp);
+ return sdf.format(date);
+ }
+}
diff --git a/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/task/DiPinShiSyncDataTask.java b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/task/DiPinShiSyncDataTask.java
new file mode 100644
index 0000000..358079d
--- /dev/null
+++ b/fin-filing-quartz/src/main/java/cn/jiutqy/finfiling/quartz/task/DiPinShiSyncDataTask.java
@@ -0,0 +1,33 @@
+package cn.jiutqy.finfiling.quartz.task;
+
+import cn.jiutqy.finfiling.common.service.DefaultFormAtFinFilingService;
+import cn.jiutqy.finfiling.common.service.DefaultFormFinFilingService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Date;
+
+@Slf4j
+@Component("diPinShiSyncDataTask")
+public class DiPinShiSyncDataTask {
+
+ @Autowired
+ private DefaultFormFinFilingService defaultFormFinFilingService;
+ @Autowired
+ private DefaultFormAtFinFilingService defaultFormAtFinFilingService;
+
+ public void syncData(String channelId,String formId){
+ long startTime = System.currentTimeMillis();
+ try {
+ log.info("同步({}/{})数据开始",channelId,formId);
+ defaultFormFinFilingService.syncData("2024-01-01 00:00:00","2024-01-31 23:59:59",channelId,formId);
+ long endTime = System.currentTimeMillis();
+ log.info("同步({}/{})数据结束,耗时:{}ms",channelId,formId,endTime-startTime);
+ } catch (Exception e) {
+ long endTime = System.currentTimeMillis();
+ log.error("同步({}/{})数据异常,耗时:{}ms",channelId,formId,endTime-startTime,e);
+ }
+ }
+}
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..b752690
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,178 @@
+
+
+
+ 4.0.0
+ cn.jiutqy
+ dipinshi-hesi
+ 1.0-SNAPSHOT
+ pom
+
+ dipinshi-hesi
+ http://www.jiutqy.com
+
+
+ 1.0.0-SNAPSHOT
+ UTF-8
+ UTF-8
+ 1.8
+
+ 1.18.26
+ 5.3.33
+ 3.8.8-SNAPSHOT
+
+
+
+ fin-filing-common
+ fin-filing-admin
+ fin-filing-quartz
+
+
+
+
+
+
+ org.springframework
+ spring-framework-bom
+ ${spring-framework.version}
+ pom
+ import
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ 2.5.15
+ pom
+ import
+
+
+
+ cn.jiutqy
+ fin-filing-common
+ 1.0-SNAPSHOT
+
+
+
+ cn.jiutqy
+ fin-filing-quartz
+ 1.0-SNAPSHOT
+
+
+
+ cn.jiutqy.archives
+ jiutqy-admin
+ ${jiutqy.version}
+
+
+
+
+
+
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+ cn.jiutqy.archives
+ jiutqy-admin
+
+
+
+
+ com.squareup.okhttp3
+ okhttp
+ 4.9.3
+
+
+ com.squareup.okhttp3
+ logging-interceptor
+ 4.9.3
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.1
+
+ true
+ ${java.version}
+ ${java.version}
+ true
+ ${project.build.sourceEncoding}
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ verify
+
+ jar-no-fork
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+
+
+
+
+
+
+
+ public
+ aliyun nexus
+ https://maven.aliyun.com/repository/public
+
+ true
+
+
+
+
+
+
+ public
+ aliyun nexus
+ https://maven.aliyun.com/repository/public
+
+ true
+
+
+ false
+
+
+
+
+
\ No newline at end of file