|
|
@@ -0,0 +1,403 @@
|
|
|
+package jp.yamoto.farm.quartz.task;
|
|
|
+
|
|
|
+import com.jcraft.jsch.ChannelSftp;
|
|
|
+import com.jcraft.jsch.JSchException;
|
|
|
+import jp.yamoto.farm.quartz.util.SftpUtils;
|
|
|
+import jp.yamoto.farm.quartz.util.ZipUtils;
|
|
|
+import jp.yamoto.farm.quartz.util.AwsS3Utils;
|
|
|
+import jp.yamoto.farm.quartz.util.AwsSesUtils;
|
|
|
+import jp.yamoto.farm.quartz.util.CsvUtils;
|
|
|
+import jp.yamoto.farm.common.biz.domain.entity.MastCustomerEntity;
|
|
|
+import jp.yamoto.farm.common.biz.service.IMastCustomerBaseService;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 顧客マスタ詳細情報CSVファイルを読み込み処理
|
|
|
+ *
|
|
|
+ * @author yamoto
|
|
|
+ * @version 1.0
|
|
|
+ */
|
|
|
+@Component("mastCustomerTask")
|
|
|
+public class MastCustomerTask {
|
|
|
+
|
|
|
+ private static final Logger logger = LoggerFactory.getLogger(MastCustomerTask.class);
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IMastCustomerBaseService mastCustomerBaseService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AwsS3Utils awsS3Utils;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AwsSesUtils awsSesUtils;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 定时任务方法 - 顧客マスタ詳細情報CSVファイルを読み込み処理
|
|
|
+ */
|
|
|
+ public void executeMastCustomer(String cooperationDate) {
|
|
|
+ logger.info("开始执行顧客マスタ詳細情報CSVファイルを読み込み処理");
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (cooperationDate == null || cooperationDate.isEmpty()) {
|
|
|
+ cooperationDate = getCurrentDateYYYYMMDD();
|
|
|
+ }
|
|
|
+
|
|
|
+ mastCustomerOperations(cooperationDate);
|
|
|
+ logger.info("顧客マスタ詳細情報CSVファイルを読み込み処理完成");
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("顧客マスタ詳細情報CSVファイルを読み込み処理失敗: {}", e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 顧客マスタ詳細情報流程
|
|
|
+ */
|
|
|
+ public void mastCustomerOperations(String cooperationDate) {
|
|
|
+ logger.info("开始読み込处理流程");
|
|
|
+ // 1. 下载SFTP文件到本地
|
|
|
+ String localPath = downloadSftpFile(cooperationDate);
|
|
|
+ String[][] csvData = null;
|
|
|
+ if (localPath.isEmpty()) {
|
|
|
+ logger.error("顧客マスタ詳細情報 SFTP文件下载失败");
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ // 2. 解析CSV文件
|
|
|
+ try {
|
|
|
+ csvData = CsvUtils.readCsv(localPath);
|
|
|
+ if (csvData == null || csvData.length == 0) {
|
|
|
+ logger.error("顧客マスタ詳細情報 CSV文件解析失败");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ logger.info("CSV文件解析成功,共读取{}行数据", csvData.length);
|
|
|
+ } catch (java.io.IOException e) {
|
|
|
+ logger.error("顧客マスタ詳細情報 CSV文件读取失败: {}", e.getMessage());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 顧客マスタ詳細情報CSV文件内容检查和数据库插入
|
|
|
+ int successCount = 0;
|
|
|
+ int errorCount = 0;
|
|
|
+
|
|
|
+ if (csvData != null && csvData.length > 1) {
|
|
|
+
|
|
|
+ // 跳过表头行,从第1行开始(索引0是表头)
|
|
|
+ for (int i = 1; i < csvData.length; i++) {
|
|
|
+ String[] rowData = csvData[i];
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 字段长度检查
|
|
|
+ if (!validateFieldLengths(rowData)) {
|
|
|
+ logger.warn("第{}行数据字段长度检查失败,跳过插入", i + 1);
|
|
|
+ errorCount++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建实体对象
|
|
|
+ MastCustomerEntity customer = createCustomerEntity(rowData);
|
|
|
+
|
|
|
+ // 插入数据库
|
|
|
+ int result = mastCustomerBaseService.insert(customer);
|
|
|
+ if (result > 0) {
|
|
|
+ successCount++;
|
|
|
+ logger.info("第{}行数据插入成功,顾客ID: {}", i + 1, customer.getCustomerId());
|
|
|
+ } else {
|
|
|
+ errorCount++;
|
|
|
+ logger.warn("第{}行数据插入失败", i + 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 继续处理下一行
|
|
|
+ errorCount++;
|
|
|
+ logger.error("第{}行数据处理异常: {}", i + 1, e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ logger.info("顧客マスタデータ插入完成 - 成功: {}行, 失败: {}行", successCount, errorCount);
|
|
|
+ } else {
|
|
|
+ logger.warn("CSV数据为空或只有表头,跳过数据库插入");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4.将顧客マスタ詳細情報CSV文件ZIP压缩
|
|
|
+ String zipFilePath = localPath.replace(".txt", ".zip");
|
|
|
+ boolean isCompressSuccess = ZipUtils.compressFile(localPath, zipFilePath);
|
|
|
+ if (!isCompressSuccess) {
|
|
|
+ logger.error("顧客マスタ詳細情報 CSV文件ZIP压缩失败");
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ logger.info("顧客マスタ詳細情報 CSV文件ZIP压缩成功 - 压缩文件: {}", zipFilePath);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5.将压缩文件上传到AWS S3服务器
|
|
|
+ boolean isUploadSuccess = awsS3Utils.uploadFile("mast_customer/" + cooperationDate + ".zip", zipFilePath);
|
|
|
+ if (!isUploadSuccess) {
|
|
|
+ logger.error("顧客マスタ詳細情報 ZIP文件上传到AWS S3服务器失败");
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ logger.info("顧客マスタ詳細情報 ZIP文件上传到AWS S3服务器成功 - 存储路径: s3://{}/mast_customer/{}.zip", "my-unencrypted-bucket",
|
|
|
+ cooperationDate);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 6.发送电子邮件通知
|
|
|
+ sendBatchCompletionEmail(cooperationDate, successCount, errorCount);
|
|
|
+
|
|
|
+ logger.info("顧客マスタ詳細情報連携処理流程完成");
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送批量处理完成邮件通知
|
|
|
+ *
|
|
|
+ * @param cooperationDate 合作日期
|
|
|
+ * @param successCount 成功记录数
|
|
|
+ * @param errorCount 失败记录数
|
|
|
+ */
|
|
|
+ private void sendBatchCompletionEmail(String cooperationDate, int successCount, int errorCount) {
|
|
|
+ try {
|
|
|
+ // 获取当前时间
|
|
|
+ java.time.LocalDateTime currentTime = java.time.LocalDateTime.now();
|
|
|
+ java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
+ String currentTimeStr = currentTime.format(formatter);
|
|
|
+
|
|
|
+ // 构建邮件主题
|
|
|
+ String subject = "顧客マスタ連携バッチ実行状況報告" + cooperationDate;
|
|
|
+
|
|
|
+ // 构建邮件内容(使用您提供的模板)
|
|
|
+ String content = "管理者 様:\n\n" +
|
|
|
+ "今日の顧客マスタ連携バッチ実行状況を報告致します。\n\n" +
|
|
|
+ currentTimeStr + "時点に顧客マスタ連携バッチが実施完了しました。\n" +
|
|
|
+ "・連携成功レコード:" + successCount + "件\n" +
|
|
|
+ "・連携失敗レコード:" + errorCount + "件\n\n";
|
|
|
+
|
|
|
+ if (errorCount > 0) {
|
|
|
+ content += "連携失敗がある場合、添付ファイルを確認してください。\n\n";
|
|
|
+ }
|
|
|
+
|
|
|
+ content += "※このメールは自動的に送信しています。\n" +
|
|
|
+ "送信専用メールアカウントのため、ご返信することが出来ませんのでご注意下さい。\n\n" +
|
|
|
+ "以上です。\nよろしくお願い致します。";
|
|
|
+
|
|
|
+ // 发送邮件(需要配置收件人邮箱)
|
|
|
+ // 这里需要配置实际的收件人邮箱地址
|
|
|
+ String toEmail = "admin@example.com"; // 请修改为实际收件人邮箱
|
|
|
+
|
|
|
+ boolean emailSent = awsSesUtils.sendSimpleEmail(toEmail, subject, content);
|
|
|
+
|
|
|
+ if (emailSent) {
|
|
|
+ logger.info("批量处理完成邮件发送成功");
|
|
|
+ } else {
|
|
|
+ logger.error("批量处理完成邮件发送失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("发送邮件通知异常: {}", e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前系统时间(YYYYMMDD格式)
|
|
|
+ *
|
|
|
+ * @return 当前日期字符串(YYYYMMDD)
|
|
|
+ */
|
|
|
+ public String getCurrentDateYYYYMMDD() {
|
|
|
+ java.time.LocalDate currentDate = java.time.LocalDate.now();
|
|
|
+ java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd");
|
|
|
+ return currentDate.format(formatter);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 下载SFTP文件到本地
|
|
|
+ *
|
|
|
+ * @param cooperationDate 合作日期,用于生成文件名
|
|
|
+ * @return 下载成功的本地文件路径,失败返回null
|
|
|
+ */
|
|
|
+ public String downloadSftpFile(String cooperationDate) {
|
|
|
+ String host = "172.14.3.40";
|
|
|
+ String username = "ftpshukou";
|
|
|
+ String password = "ScmAy3#w";
|
|
|
+ String remotePath = "/upload/downloaded_" + cooperationDate + "_test.txt";
|
|
|
+ String localPath = "temp/downloaded_" + cooperationDate + "_test.txt";
|
|
|
+
|
|
|
+ ChannelSftp channel = null;
|
|
|
+ try {
|
|
|
+ channel = SftpUtils.connect(host, username, password);
|
|
|
+
|
|
|
+ // 检查文件是否存在
|
|
|
+ if (SftpUtils.fileExists(channel, remotePath)) {
|
|
|
+ boolean success = SftpUtils.downloadFile(channel, remotePath, localPath);
|
|
|
+ if (success) {
|
|
|
+ logger.info("SFTP文件下载成功 - 远程文件: {}, 本地文件: {}", remotePath, localPath);
|
|
|
+ return localPath;
|
|
|
+ } else {
|
|
|
+ logger.error("SFTP文件下载失败");
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ logger.warn("远程文件不存在: {}", remotePath);
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (JSchException e) {
|
|
|
+ logger.error("SFTP连接失败: {}", e.getMessage());
|
|
|
+ return "";
|
|
|
+ } finally {
|
|
|
+ if (channel != null) {
|
|
|
+ SftpUtils.disconnect(channel);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证字段长度是否符合数据库表定义
|
|
|
+ *
|
|
|
+ * @param rowData CSV行数据
|
|
|
+ * @return 验证通过返回true,否则返回false
|
|
|
+ */
|
|
|
+ private boolean validateFieldLengths(String[] rowData) {
|
|
|
+ if (rowData == null || rowData.length < 2) {
|
|
|
+ logger.warn("CSV行数据为空或列数不足");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 根据表定义检查字段长度
|
|
|
+ // id: varchar(20)
|
|
|
+ if (rowData.length > 0 && rowData[0] != null && rowData[0].length() > 20) {
|
|
|
+ logger.warn("ID字段长度超过20字符限制: {}", rowData[0]);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // customer_id: varchar(20)
|
|
|
+ if (rowData.length > 1 && rowData[1] != null && rowData[1].length() > 20) {
|
|
|
+ logger.warn("顾客ID字段长度超过20字符限制: {}", rowData[1]);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // first_name: varchar(64)
|
|
|
+ if (rowData.length > 2 && rowData[2] != null && rowData[2].length() > 64) {
|
|
|
+ logger.warn("姓名字段长度超过64字符限制: {}", rowData[2]);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // last_name: varchar(32)
|
|
|
+ if (rowData.length > 3 && rowData[3] != null && rowData[3].length() > 32) {
|
|
|
+ logger.warn("名字字段长度超过32字符限制: {}", rowData[3]);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // customer_name: varchar(128)
|
|
|
+ if (rowData.length > 4 && rowData[4] != null && rowData[4].length() > 128) {
|
|
|
+ logger.warn("顾客名字段长度超过128字符限制: {}", rowData[4]);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // phone_number: varchar(256)
|
|
|
+ if (rowData.length > 5 && rowData[5] != null && rowData[5].length() > 256) {
|
|
|
+ logger.warn("电话号码字段长度超过256字符限制: {}", rowData[5]);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 其他字段长度检查...
|
|
|
+ // sys_customer_id: varchar(20)
|
|
|
+ if (rowData.length > 6 && rowData[6] != null && rowData[6].length() > 20) {
|
|
|
+ logger.warn("系统顾客ID字段长度超过20字符限制: {}", rowData[6]);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // member_id: varchar(20)
|
|
|
+ if (rowData.length > 7 && rowData[7] != null && rowData[7].length() > 20) {
|
|
|
+ logger.warn("会员ID字段长度超过20字符限制: {}", rowData[7]);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // furigana_sei: varchar(56)
|
|
|
+ if (rowData.length > 8 && rowData[8] != null && rowData[8].length() > 56) {
|
|
|
+ logger.warn("姓フリガナ字段长度超过56字符限制: {}", rowData[8]);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // furigana_mei: varchar(56)
|
|
|
+ if (rowData.length > 9 && rowData[9] != null && rowData[9].length() > 56) {
|
|
|
+ logger.warn("名フリガナ字段长度超过56字符限制: {}", rowData[9]);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 继续检查其他字段...
|
|
|
+
|
|
|
+ return true;
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("字段长度检查异常: {}", e.getMessage());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据CSV行数据创建顾客实体对象
|
|
|
+ *
|
|
|
+ * @param rowData CSV行数据
|
|
|
+ * @return 顾客实体对象
|
|
|
+ */
|
|
|
+ private MastCustomerEntity createCustomerEntity(String[] rowData) {
|
|
|
+ MastCustomerEntity customer = new MastCustomerEntity();
|
|
|
+
|
|
|
+ // 设置必填字段
|
|
|
+ if (rowData.length > 0)
|
|
|
+ customer.setId(rowData[0]);
|
|
|
+ if (rowData.length > 1)
|
|
|
+ customer.setCustomerId(rowData[1]);
|
|
|
+ if (rowData.length > 2)
|
|
|
+ customer.setFirstName(rowData[2]);
|
|
|
+ if (rowData.length > 3)
|
|
|
+ customer.setLastName(rowData[3]);
|
|
|
+ if (rowData.length > 4)
|
|
|
+ customer.setCustomerName(rowData[4]);
|
|
|
+ if (rowData.length > 5)
|
|
|
+ customer.setPhoneNumber(rowData[5]);
|
|
|
+
|
|
|
+ // 设置可选字段
|
|
|
+ if (rowData.length > 6)
|
|
|
+ customer.setSysCustomerId(rowData[6]);
|
|
|
+ if (rowData.length > 7)
|
|
|
+ customer.setMemberId(rowData[7]);
|
|
|
+ if (rowData.length > 8)
|
|
|
+ customer.setFuriganaSei(rowData[8]);
|
|
|
+ if (rowData.length > 9)
|
|
|
+ customer.setFuriganaMei(rowData[9]);
|
|
|
+ if (rowData.length > 10)
|
|
|
+ customer.setCompanyName(rowData[10]);
|
|
|
+ if (rowData.length > 11)
|
|
|
+ customer.setDepartmentName(rowData[11]);
|
|
|
+ if (rowData.length > 12)
|
|
|
+ customer.setPostalCode(rowData[12]);
|
|
|
+ if (rowData.length > 13)
|
|
|
+ customer.setPrefecture(rowData[13]);
|
|
|
+ if (rowData.length > 14)
|
|
|
+ customer.setCity(rowData[14]);
|
|
|
+ if (rowData.length > 15)
|
|
|
+ customer.setTownStreetArea(rowData[15]);
|
|
|
+ if (rowData.length > 16)
|
|
|
+ customer.setBuildingEtc(rowData[16]);
|
|
|
+ if (rowData.length > 17)
|
|
|
+ customer.setAddress(rowData[17]);
|
|
|
+ if (rowData.length > 18)
|
|
|
+ customer.setMailAddress(rowData[18]);
|
|
|
+ if (rowData.length > 19)
|
|
|
+ customer.setMobile(rowData[19]);
|
|
|
+ if (rowData.length > 20)
|
|
|
+ customer.setFax(rowData[20]);
|
|
|
+ if (rowData.length > 21)
|
|
|
+ customer.setFarmerId(rowData[21]);
|
|
|
+
|
|
|
+ // 设置默认值
|
|
|
+ customer.setSystemSourceFlg("0");
|
|
|
+ customer.setDiscontinuedFlg("0");
|
|
|
+ customer.setVersion(1);
|
|
|
+
|
|
|
+ return customer;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|