diff --git a/clearing-parent/reports-service/pom.xml b/clearing-parent/reports-service/pom.xml index a5e83d1ba..e4a52d469 100644 --- a/clearing-parent/reports-service/pom.xml +++ b/clearing-parent/reports-service/pom.xml @@ -35,6 +35,10 @@ org.springframework.boot spring-boot-autoconfigure + + org.springframework.integration + spring-integration-sftp + com.fasterxml.jackson.dataformat jackson-dataformat-xml diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/ClearingImdgConfig.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/ClearingImdgConfig.java index 95f1bb7a9..27de4b75c 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/ClearingImdgConfig.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/ClearingImdgConfig.java @@ -5,7 +5,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import ru.spcex.clearing.reports.config.element.ReportsServiceSettings; +import ru.spcex.clearing.reports.config.settings.ReportsServiceSettings; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/KafkaConfig.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/KafkaConfig.java index 8246741f0..2ed531e19 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/KafkaConfig.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/KafkaConfig.java @@ -15,7 +15,7 @@ import ru.spcex.clearing.platform.messaging.config.KafkaProducerFactory; import ru.spcex.clearing.platform.messaging.config.element.KafkaProducerSettings; import ru.spcex.clearing.platform.messaging.service.RequestInfo; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; -import ru.spcex.clearing.reports.config.element.ReportsServiceSettings; +import ru.spcex.clearing.reports.config.settings.ReportsServiceSettings; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgId; import ru.spcex.platform.imdg.api.ImdgProvider; diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/SFTPNotificationsConfig.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/SFTPNotificationsConfig.java new file mode 100644 index 000000000..cb93816da --- /dev/null +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/SFTPNotificationsConfig.java @@ -0,0 +1,115 @@ +package ru.spcex.clearing.reports.config; + +import com.jcraft.jsch.ChannelSftp; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.expression.common.LiteralExpression; +import org.springframework.integration.annotation.Gateway; +import org.springframework.integration.annotation.MessagingGateway; +import org.springframework.integration.annotation.ServiceActivator; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.dsl.IntegrationFlow; +import org.springframework.integration.dsl.IntegrationFlows; +import org.springframework.integration.file.remote.session.CachingSessionFactory; +import org.springframework.integration.file.remote.session.SessionFactory; +import org.springframework.integration.sftp.gateway.SftpOutboundGateway; +import org.springframework.integration.sftp.outbound.SftpMessageHandler; +import org.springframework.integration.sftp.session.DefaultSftpSessionFactory; +import org.springframework.integration.sftp.session.SftpFileInfo; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.MessageHandler; +import ru.spcex.clearing.reports.config.settings.ReportsServiceSettings; + +import java.io.File; +import java.util.List; + +import static org.springframework.integration.file.remote.gateway.AbstractRemoteFileOutboundGateway.Command.LS; + +@Configuration +public class SFTPNotificationsConfig { + + @Bean("notificationsSftpSessionFactory") + public SessionFactory sftpSessionFactory(ReportsServiceSettings settings) { + DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true); + factory.setHost(settings.getNotificationsStore().getServerIp()); + factory.setPort(settings.getNotificationsStore().getServerPort()); + factory.setUser(settings.getNotificationsStore().getUser()); + factory.setPassword(settings.getNotificationsStore().getPassword()); + factory.setAllowUnknownKeys(true); + return new CachingSessionFactory<>(factory); + } + + @Bean("notificationsSftpHandler") + @ServiceActivator(inputChannel = "notificationsToSftpChannel") + public MessageHandler handler( + @Qualifier("notificationsSftpSessionFactory") + SessionFactory sessionFactory, + ReportsServiceSettings settings + ) { + SftpMessageHandler handler = new SftpMessageHandler(sessionFactory); + handler.setRemoteDirectoryExpression(new LiteralExpression(settings.getNotificationsStore().getOutDir())); + handler.setAutoCreateDirectory(true); + handler.setFileNameGenerator(message -> { + if (message.getPayload() instanceof File) { + return ((File) message.getPayload()).getName(); + } else { + throw new IllegalArgumentException("File must expected as payload."); + } + }); + return handler; + } + + @Bean("notificationsListSftpChannel") + public MessageChannel listSftpChannel( + @Qualifier("notificationsSftpSessionFactory") + SessionFactory sessionFactory, + ReportsServiceSettings settings + ) { + DirectChannel dc = new DirectChannel(); + dc.subscribe(handlerList(sessionFactory, settings)); + return dc; + } + + @Bean("notificationsToSftpChannel") + public MessageChannel toSftpChannel( + @Qualifier("notificationsSftpSessionFactory") + SessionFactory sessionFactory, + ReportsServiceSettings settings + ) { + DirectChannel dc = new DirectChannel(); + dc.subscribe(handler(sessionFactory, settings)); + return dc; + } + + @Bean("notificationsHandlerList") + @ServiceActivator(inputChannel = "notificationsListSftpChannel") + public MessageHandler handlerList( + @Qualifier("notificationsSftpSessionFactory") + SessionFactory sessionFactory, + ReportsServiceSettings settings + ) { + String expression = "'/%s'".formatted(settings.getNotificationsStore().getOutDir()); + SftpOutboundGateway sftpOutboundGateway = new SftpOutboundGateway(sessionFactory, LS.getCommand(), expression); + return sftpOutboundGateway; + } + + @Bean("notificationsSftpOutboundListFlow") + public IntegrationFlow sftpOutboundListFlow( + @Qualifier("notificationsSftpSessionFactory") + SessionFactory sessionFactory + ) { + return IntegrationFlows.from("notificationsListSftpChannel") + .handle(new SftpOutboundGateway(sessionFactory, "ls", "payload")) + .get(); + } + + @MessagingGateway(name = "notificationsSftpGateway") + public interface NotificationsGateway { + @Gateway(requestChannel = "notificationsToSftpChannel") + void sendToSftp(File file); + + @Gateway(requestChannel = "notificationsListSftpChannel") + List listFiles(String dir); + } +} diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/SFTPReportsConfig.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/SFTPReportsConfig.java new file mode 100644 index 000000000..1fa057fc2 --- /dev/null +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/SFTPReportsConfig.java @@ -0,0 +1,115 @@ +package ru.spcex.clearing.reports.config; + +import com.jcraft.jsch.ChannelSftp; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.expression.common.LiteralExpression; +import org.springframework.integration.annotation.Gateway; +import org.springframework.integration.annotation.MessagingGateway; +import org.springframework.integration.annotation.ServiceActivator; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.dsl.IntegrationFlow; +import org.springframework.integration.dsl.IntegrationFlows; +import org.springframework.integration.file.remote.session.CachingSessionFactory; +import org.springframework.integration.file.remote.session.SessionFactory; +import org.springframework.integration.sftp.gateway.SftpOutboundGateway; +import org.springframework.integration.sftp.outbound.SftpMessageHandler; +import org.springframework.integration.sftp.session.DefaultSftpSessionFactory; +import org.springframework.integration.sftp.session.SftpFileInfo; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.MessageHandler; +import ru.spcex.clearing.reports.config.settings.ReportsServiceSettings; + +import java.io.File; +import java.util.List; + +import static org.springframework.integration.file.remote.gateway.AbstractRemoteFileOutboundGateway.Command.LS; + +@Configuration +public class SFTPReportsConfig { + + @Bean("reportsSftpSessionFactory") + public SessionFactory sftpSessionFactory(ReportsServiceSettings settings) { + DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true); + factory.setHost(settings.getReportsStore().getServerIp()); + factory.setPort(settings.getReportsStore().getServerPort()); + factory.setUser(settings.getReportsStore().getUser()); + factory.setPassword(settings.getReportsStore().getPassword()); + factory.setAllowUnknownKeys(true); + return new CachingSessionFactory<>(factory); + } + + @Bean("reportsSftpHandler") + @ServiceActivator(inputChannel = "reportsToSftpChannel") + public MessageHandler handler( + @Qualifier("reportsSftpSessionFactory") + SessionFactory sessionFactory, + ReportsServiceSettings settings + ) { + SftpMessageHandler handler = new SftpMessageHandler(sessionFactory); + handler.setRemoteDirectoryExpression(new LiteralExpression(settings.getReportsStore().getOutDir())); + handler.setAutoCreateDirectory(true); + handler.setFileNameGenerator(message -> { + if (message.getPayload() instanceof File) { + return ((File) message.getPayload()).getName(); + } else { + throw new IllegalArgumentException("File must expected as payload."); + } + }); + return handler; + } + + @Bean("reportsListSftpChannel") + public MessageChannel listSftpChannel( + @Qualifier("reportsSftpSessionFactory") + SessionFactory sessionFactory, + ReportsServiceSettings settings + ) { + DirectChannel dc = new DirectChannel(); + dc.subscribe(handlerList(sessionFactory, settings)); + return dc; + } + + @Bean("reportsToSftpChannel") + public MessageChannel toSftpChannel( + @Qualifier("reportsSftpSessionFactory") + SessionFactory sessionFactory, + ReportsServiceSettings settings + ) { + DirectChannel dc = new DirectChannel(); + dc.subscribe(handler(sessionFactory, settings)); + return dc; + } + + @Bean("reportsHandlerList") + @ServiceActivator(inputChannel = "reportsListSftpChannel") + public MessageHandler handlerList( + @Qualifier("reportsSftpSessionFactory") + SessionFactory sessionFactory, + ReportsServiceSettings settings + ) { + String expression = "'/%s'".formatted(settings.getReportsStore().getOutDir()); + SftpOutboundGateway sftpOutboundGateway = new SftpOutboundGateway(sessionFactory, LS.getCommand(), expression); + return sftpOutboundGateway; + } + + @Bean("reportsSftpOutboundListFlow") + public IntegrationFlow sftpOutboundListFlow( + @Qualifier("reportsSftpSessionFactory") + SessionFactory sessionFactory + ) { + return IntegrationFlows.from("reportsListSftpChannel") + .handle(new SftpOutboundGateway(sessionFactory, "ls", "payload")) + .get(); + } + + @MessagingGateway(name = "reportsSftpGateway") + public interface ReportsGateway { + @Gateway(requestChannel = "reportsToSftpChannel") + void sendToSftp(File file); + + @Gateway(requestChannel = "reportsListSftpChannel") + List listFiles(String dir); + } +} diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/element/ReportsServiceSettings.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/settings/ReportsServiceSettings.java similarity index 72% rename from clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/element/ReportsServiceSettings.java rename to clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/settings/ReportsServiceSettings.java index ec52a7c55..1583c3774 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/element/ReportsServiceSettings.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/settings/ReportsServiceSettings.java @@ -1,4 +1,4 @@ -package ru.spcex.clearing.reports.config.element; +package ru.spcex.clearing.reports.config.settings; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.PropertySource; @@ -14,8 +14,8 @@ public class ReportsServiceSettings { private HazelcastClientParams hazelcast; private KafkaConsumerSettings kafkaConsumer; private KafkaProducerSettings kafkaProducer; - private String reportModuleOut; - private String notificationModuleOut; + private Store reportsStore; + private Store notificationsStore; public HazelcastClientParams getHazelcast() { return hazelcast; @@ -41,19 +41,19 @@ public class ReportsServiceSettings { this.kafkaProducer = kafkaProducer; } - public String getReportModuleOut() { - return reportModuleOut; + public Store getReportsStore() { + return reportsStore; } - public void setReportModuleOut(String reportModuleOut) { - this.reportModuleOut = reportModuleOut; + public void setReportsStore(Store reportsStore) { + this.reportsStore = reportsStore; } - public String getNotificationModuleOut() { - return notificationModuleOut; + public Store getNotificationsStore() { + return notificationsStore; } - public void setNotificationModuleOut(String notificationModuleOut) { - this.notificationModuleOut = notificationModuleOut; + public void setNotificationsStore(Store notificationsStore) { + this.notificationsStore = notificationsStore; } } diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/settings/Store.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/settings/Store.java new file mode 100644 index 000000000..a32e1cd47 --- /dev/null +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/config/settings/Store.java @@ -0,0 +1,69 @@ +package ru.spcex.clearing.reports.config.settings; + +public class Store { + + private String outDir; + private String localTempDir; + private String user; + private String password; + private String serverIp; + private int serverPort; + + public boolean isDeleteAfterSend() { + return deleteAfterSend; + } + + public void setDeleteAfterSend(boolean deleteAfterSend) { + this.deleteAfterSend = deleteAfterSend; + } + + private boolean deleteAfterSend; + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getServerIp() { + return serverIp; + } + + public void setServerIp(String serverIp) { + this.serverIp = serverIp; + } + + public int getServerPort() { + return serverPort; + } + + public void setServerPort(int serverPort) { + this.serverPort = serverPort; + } + + public String getOutDir() { + return outDir; + } + + public void setOutDir(String outDir) { + this.outDir = outDir; + } + + public String getLocalTempDir() { + return localTempDir; + } + + public void setLocalTempDir(String localTempDir) { + this.localTempDir = localTempDir; + } +} diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/NotificationService.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/NotificationService.java index a775d0276..54960dcca 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/NotificationService.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/NotificationService.java @@ -11,12 +11,15 @@ import ru.spcex.clearing.platform.messaging.domain.Consts; import ru.spcex.clearing.platform.messaging.domain.cud.reports.NotificationRequest; import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; -import ru.spcex.clearing.reports.config.element.ReportsServiceSettings; +import ru.spcex.clearing.reports.config.SFTPNotificationsConfig; +import ru.spcex.clearing.reports.config.settings.ReportsServiceSettings; import ru.spcex.clearing.reports.notifications.NCMPNotificationBuilder; import ru.spcex.clearing.reports.notifications.NTCRNotificationBuilder; import ru.spcex.clearing.util.security.UserRoleVerification; import java.io.File; +import java.util.Collection; +import java.util.List; import java.util.Map; @Service @@ -27,19 +30,30 @@ public class NotificationService extends QueueConsumer implements InitializingBe private final NTCRNotificationBuilder ntcrNotificationBuilder; private final File outFolder; + private final boolean deleteAfterSend; + private final SFTPNotificationsConfig.NotificationsGateway notificationsSftpGateway; public NotificationService(Consumer kafkaQueue, Producer kafkaResponseQueue, UserRoleVerification userRoleVerification, NCMPNotificationBuilder ncmpNotificationBuilder, NTCRNotificationBuilder ntcrNotificationBuilder, - ReportsServiceSettings reportsServiceSettings) { + ReportsServiceSettings reportsServiceSettings, + SFTPNotificationsConfig.NotificationsGateway notificationsSftpGateway) { super(kafkaQueue, kafkaResponseQueue); this.userRoleVerification = userRoleVerification; this.ncmpNotificationBuilder = ncmpNotificationBuilder; this.ntcrNotificationBuilder = ntcrNotificationBuilder; - this.outFolder = new File(reportsServiceSettings.getNotificationModuleOut()); + this.notificationsSftpGateway = notificationsSftpGateway; + this.outFolder = new File(reportsServiceSettings.getNotificationsStore().getLocalTempDir()); + if (!outFolder.exists()) { + boolean mkDirOk = outFolder.mkdirs(); + if (!mkDirOk) throw new IllegalStateException("Can't create output directory for reports, reports-service was terminated"); + } else if (!outFolder.isDirectory()) { + throw new IllegalStateException("Output reports path from settings is not directory!"); + } assert outFolder.isDirectory(); + this.deleteAfterSend = reportsServiceSettings.getNotificationsStore().isDeleteAfterSend(); } @Override @@ -63,10 +77,11 @@ public class NotificationService extends QueueConsumer implements InitializingBe logUnknownProperties(userRequest); File outFile = ncmpNotificationBuilder.buildNotification(req.getConsumerId(), outFolder); - if (outFile == null) { - log.error("Create notification NCMP for id={} failed, see log", req.getConsumerId()); - } else { + if (outFile != null) { log.debug("Notification NCMP for id={} successfully created. Output files: {}", req.getConsumerId(), outFile); + sendFilesToSftp(List.of(outFile)); + } else { + log.error("Create notification NCMP for id={} failed, see log", req.getConsumerId()); } return null; } @@ -81,10 +96,11 @@ public class NotificationService extends QueueConsumer implements InitializingBe logUnknownProperties(userRequest); File outFile = ntcrNotificationBuilder.buildNotification(req.getConsumerId(), outFolder); - if (outFile == null) { - log.error("Create notification NTCR for id={} failed, see log", req.getConsumerId()); - } else { + if (outFile != null) { log.debug("Notification NTCR for id={} successfully created. Output files: {}", req.getConsumerId(), outFile); + sendFilesToSftp(List.of(outFile)); + } else { + log.error("Create notification NTCR for id={} failed, see log", req.getConsumerId()); } return null; } @@ -95,4 +111,16 @@ public class NotificationService extends QueueConsumer implements InitializingBe log.warn("Unknown property in request {} = {}", unknownProperty.getKey(), unknownProperty.getValue()); } } + + private void sendFilesToSftp(Collection files) { + for (File file : files) { + notificationsSftpGateway.sendToSftp(file); + if (deleteAfterSend) { + boolean delete = file.delete(); + if (!delete) { + log.warn("Can't delete temp file {}", file.getAbsolutePath()); + } + } + } + } } diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/ReportService.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/ReportService.java index dfa173181..b8282602d 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/ReportService.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/ReportService.java @@ -19,7 +19,8 @@ import ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandR import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; -import ru.spcex.clearing.reports.config.element.ReportsServiceSettings; +import ru.spcex.clearing.reports.config.SFTPReportsConfig; +import ru.spcex.clearing.reports.config.settings.ReportsServiceSettings; import ru.spcex.clearing.reports.reports.CSVReportBuilder; import ru.spcex.clearing.reports.reports.EmptyParams; import ru.spcex.clearing.reports.reports.ReportInfo; @@ -62,6 +63,8 @@ public class ReportService extends QueueConsumer implements InitializingBean { private final Imdg sessionImdg; private final File outFolder; + private final SFTPReportsConfig.ReportsGateway reportsSftpGateway; + private final boolean deleteAfterSend; public ReportService(Consumer kafkaQueue, Producer kafkaResponseQueue, @@ -94,8 +97,8 @@ public class ReportService extends QueueConsumer implements InitializingBean { @Qualifier("reportRequestGREFValidator") Function reportRequestGREFValidator, - ImdgProvider imdgProvider - + ImdgProvider imdgProvider, + SFTPReportsConfig.ReportsGateway reportsSftpGateway ) { super(kafkaQueue, kafkaResponseQueue); this.userRoleVerification = userRoleVerification; @@ -111,8 +114,9 @@ public class ReportService extends QueueConsumer implements InitializingBean { this.reportBuildersForGREP = reportBuildersForGREP; this.reportBuildersForGREF = reportBuildersForGREF; this.reportBuildersForGRET = reportBuildersForGRET; + this.reportsSftpGateway = reportsSftpGateway; this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class); - this.outFolder = new File(reportsServiceSettings.getReportModuleOut()); + this.outFolder = new File(reportsServiceSettings.getReportsStore().getLocalTempDir()); if (!outFolder.exists()) { boolean mkDirOk = outFolder.mkdirs(); if (!mkDirOk) throw new IllegalStateException("Can't create output directory for reports, reports-service was terminated"); @@ -120,6 +124,7 @@ public class ReportService extends QueueConsumer implements InitializingBean { throw new IllegalStateException("Output reports path from settings is not directory!"); } assert outFolder.isDirectory(); + this.deleteAfterSend = reportsServiceSettings.getReportsStore().isDeleteAfterSend(); } @Override @@ -160,10 +165,12 @@ public class ReportService extends QueueConsumer implements InitializingBean { IEnumKey.getEnumByKey(ReportBuilderType.class, req.getReportId()) ); List outFilenames = new ArrayList<>(); + List outFiles = new ArrayList<>(); for (CSVReportBuilder builder : builders) { File outFile = builder.createReport(new EmptyParams(), outFolder); if (outFile == null) continue; outFilenames.add(outFile.getAbsolutePath()); + outFiles.add(outFile); } int outFilesCnt = outFilenames.size(); @@ -174,6 +181,8 @@ public class ReportService extends QueueConsumer implements InitializingBean { } else { log.debug("Reports {} successfully created. Output files: {}", req.getReportId(), String.join(", ", outFilenames)); } + + sendFilesToSftp(outFiles); return null; } @@ -195,6 +204,7 @@ public class ReportService extends QueueConsumer implements InitializingBean { IEnumKey.getEnumByKey(ReportBuilderType.class, req.getReportId()) ); List outFilenames = new ArrayList<>(); + List outFiles = new ArrayList<>(); for (CSVReportBuilder builder : builders) { SessionIdParam sessionIdParam = new SessionIdParam(); sessionIdParam.setSessionId(List.of(req.getSessionId())); @@ -211,6 +221,8 @@ public class ReportService extends QueueConsumer implements InitializingBean { } else { log.debug("Reports {} successfully created. Output files: {}", req.getReportId(), String.join(", ", outFilenames)); } + + sendFilesToSftp(outFiles); return null; } @@ -229,9 +241,10 @@ public class ReportService extends QueueConsumer implements InitializingBean { } else { sessionIds = getSessionIdsForDate(LocalDate.now()); } - Map outFilenames = createReportsForTask(sessionIds, reportBuildersForGREP.values()); + Map outFiles = createReportsForTask(sessionIds, reportBuildersForGREP.values()); - sendReportsToGateway(sessionIds, outFilenames, ReportType.REPORT_KS_TMP.getKey()); + sendReportsToGateway(sessionIds, outFiles, ReportType.REPORT_KS_TMP.getKey()); + sendFilesToSftp(outFiles.keySet()); return null; } @@ -250,9 +263,10 @@ public class ReportService extends QueueConsumer implements InitializingBean { } else { sessionIds = getSessionIdsForDate(LocalDate.now()); } - Map outFilenames = createReportsForTask(sessionIds, reportBuildersForGRET.values()); + Map outFiles = createReportsForTask(sessionIds, reportBuildersForGRET.values()); - sendReportsToGateway(sessionIds, outFilenames, null); + sendReportsToGateway(sessionIds, outFiles, null); + sendFilesToSftp(outFiles.keySet()); return null; } @@ -271,14 +285,15 @@ public class ReportService extends QueueConsumer implements InitializingBean { } else { sessionIds = getSessionIdsForDate(LocalDate.now()); } - Map outFilenames = createReportsForTask(sessionIds, reportBuildersForGREF.values()); + Map outFiles = createReportsForTask(sessionIds, reportBuildersForGREF.values()); - sendReportsToGateway(sessionIds, outFilenames, ReportType.REPORT_KS_FINAL.getKey()); + sendReportsToGateway(sessionIds, outFiles, ReportType.REPORT_KS_FINAL.getKey()); + sendFilesToSftp(outFiles.keySet()); return null; } - private Map createReportsForTask(List sessionIds, Collection>> buildersForTask) { - Map outFilenames = new HashMap<>(); + private Map createReportsForTask(List sessionIds, Collection>> buildersForTask) { + Map outFiles = new HashMap<>(); int cntErrors = 0; for (List> builders : buildersForTask) { for (CSVReportBuilder builder : builders) { @@ -290,7 +305,7 @@ public class ReportService extends QueueConsumer implements InitializingBean { cntErrors++; continue; } - outFilenames.put(outFile.getName(), new ReportInfo(builder.getReportKey().getKey(), builder.getSection())); + outFiles.put(outFile, new ReportInfo(builder.getReportKey().getKey(), builder.getSection())); } else if (builder.getParamsClass() == SessionIdParam.class) { SessionIdParam sessionIdParam = new SessionIdParam(); sessionIdParam.setSessionId(sessionIds); @@ -300,28 +315,38 @@ public class ReportService extends QueueConsumer implements InitializingBean { cntErrors++; continue; } - outFilenames.put(outFile.getName(), reportInfo); + outFiles.put(outFile, reportInfo); } } } - if (cntErrors == 0) log.debug("All reports successfully created. Output files: {}", String.join(", ", outFilenames.keySet())); - else log.debug("Some reports ({}) create failed. Output files: {}", cntErrors, String.join(", ", outFilenames.keySet())); + if (cntErrors == 0) { + log.debug( + "All reports successfully created. Output files: {}", + outFiles.keySet().stream().map(File::getName).collect(Collectors.joining(", ")) + ); + } else { + log.debug( + "Some reports ({}) create failed. Output files: {}", + cntErrors, + outFiles.keySet().stream().map(File::getName).collect(Collectors.joining(", ")) + ); + } - return outFilenames; + return outFiles; } - private void sendReportsToGateway(List sessionIds, Map reportsWithReportType, String type) { + private void sendReportsToGateway(List sessionIds, Map reportsWithReportType, String type) { SendReportRequest sendReportRequest = new SendReportRequest(); sendReportRequest.setSessionId(sessionIds); sendReportRequest.setType(type); List reports = new ArrayList<>(reportsWithReportType.size()); - for (Map.Entry entry : reportsWithReportType.entrySet()) { + for (Map.Entry entry : reportsWithReportType.entrySet()) { ReportInfo reportInfo = entry.getValue(); ReportPart reportPart = new ReportPart(); reportPart.setReportType(reportInfo.reportKey()); reportPart.setSection(reportInfo.section()); - reportPart.setFileName(entry.getKey()); + reportPart.setFileName(entry.getKey().getName()); reports.add(reportPart); } @@ -346,4 +371,15 @@ public class ReportService extends QueueConsumer implements InitializingBean { return sessionIds.stream().toList(); } + private void sendFilesToSftp(Collection files) { + for (File file : files) { + reportsSftpGateway.sendToSftp(file); + if (deleteAfterSend) { + boolean delete = file.delete(); + if (!delete) { + log.warn("Can't delete temp file {}", file.getAbsolutePath()); + } + } + } + } } diff --git a/clearing-parent/reports-service/src/main/resources/application.properties b/clearing-parent/reports-service/src/main/resources/application.properties index 82290ecaa..9b4350755 100644 --- a/clearing-parent/reports-service/src/main/resources/application.properties +++ b/clearing-parent/reports-service/src/main/resources/application.properties @@ -17,5 +17,16 @@ reports-service.kafka-producer.batch-size=16384 reports-service.kafka-producer.linger-ms=1 reports-service.kafka-producer.buffer-memory=33554432 -reports-service.ReportModuleOut=./report_out -reports-service.NotificationModuleOut=./notification_out +reports-service.reports-store.local-temp-dir=./reports_out_temp +reports-service.reports-store.out-dir=reports +reports-service.reports-store.user=teste +reports-service.reports-store.password=password +reports-service.reports-store.server-ip=10.230.238.53 +reports-service.reports-store.server-port=2222 + +reports-service.notifications-store.local-temp-dir=./notifications_out_temp +reports-service.notifications-store.out-dir=notifications +reports-service.notifications-store.user=tester +reports-service.notifications-store.password=password +reports-service.notifications-store.server-ip=10.230.238.53 +reports-service.notifications-store.server-port=2222 \ No newline at end of file diff --git a/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/config/SFTPTestConfig.java b/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/config/SFTPTestConfig.java new file mode 100644 index 000000000..0f766cd5a --- /dev/null +++ b/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/config/SFTPTestConfig.java @@ -0,0 +1,48 @@ +package ru.spcex.clearing.reports.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.integration.sftp.session.SftpFileInfo; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +@Configuration +public class SFTPTestConfig { + @Bean + public SFTPReportsConfig.ReportsGateway reportsGateway(){ + return new ReportsGateway(); + } + + public static class ReportsGateway implements SFTPReportsConfig.ReportsGateway { + + @Override + public void sendToSftp(File file) { + + } + + @Override + public List listFiles(String dir) { + return new ArrayList<>(); + } + } + + @Bean + public SFTPNotificationsConfig.NotificationsGateway notificationsGateway(){ + return new NotificationsGateway(); + } + + public static class NotificationsGateway implements SFTPNotificationsConfig.NotificationsGateway { + + @Override + public void sendToSftp(File file) { + + } + + @Override + public List listFiles(String dir) { + return new ArrayList<>(); + } + } +} diff --git a/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/config/TestConfig.java b/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/config/TestConfig.java index 4133bd829..c521efbb3 100644 --- a/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/config/TestConfig.java +++ b/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/config/TestConfig.java @@ -2,7 +2,8 @@ package ru.spcex.clearing.reports.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import ru.spcex.clearing.reports.config.element.ReportsServiceSettings; +import ru.spcex.clearing.reports.config.settings.ReportsServiceSettings; +import ru.spcex.clearing.reports.config.settings.Store; @Configuration public class TestConfig { @@ -10,7 +11,9 @@ public class TestConfig { @Bean public ReportsServiceSettings reportsServiceSettings() { ReportsServiceSettings reportsServiceSettings = new ReportsServiceSettings(); - reportsServiceSettings.setReportModuleOut("out"); + Store store = new Store(); + store.setLocalTempDir("out"); + reportsServiceSettings.setReportsStore(store); return reportsServiceSettings; } diff --git a/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/services/ReportServiceTest_BP.java b/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/services/ReportServiceTest_BP.java index 6fb95ef71..67f44f43a 100644 --- a/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/services/ReportServiceTest_BP.java +++ b/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/services/ReportServiceTest_BP.java @@ -29,6 +29,7 @@ import ru.spcex.clearing.platform.messaging.domain.Consts; import ru.spcex.clearing.platform.messaging.domain.cud.reports.ReportRequestWithSessionId; import ru.spcex.clearing.reports.config.BeanConfiguration; import ru.spcex.clearing.reports.config.ReportBuildersConfig; +import ru.spcex.clearing.reports.config.SFTPTestConfig; import ru.spcex.clearing.reports.config.TestConfig; import ru.spcex.clearing.reports.config.validation.ValidationConfig; import ru.spcex.clearing.test.TestUtils; @@ -58,7 +59,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; ImdgTestConfig.class, KafkaTestConfig.class, ReportBuildersConfig.class, - TestConfig.class + TestConfig.class, + SFTPTestConfig.class }) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class ReportServiceTest_BP { diff --git a/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/services/ReportServiceTest_KS.java b/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/services/ReportServiceTest_KS.java index 5d835fb0c..a8d7170ce 100644 --- a/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/services/ReportServiceTest_KS.java +++ b/clearing-parent/reports-service/src/test/java/ru/spcex/clearing/reports/services/ReportServiceTest_KS.java @@ -31,6 +31,7 @@ import ru.spcex.clearing.platform.messaging.domain.cud.reports.ReportRequest; import ru.spcex.clearing.platform.messaging.domain.cud.reports.ReportRequestWithSessionId; import ru.spcex.clearing.reports.config.BeanConfiguration; import ru.spcex.clearing.reports.config.ReportBuildersConfig; +import ru.spcex.clearing.reports.config.SFTPTestConfig; import ru.spcex.clearing.reports.config.TestConfig; import ru.spcex.clearing.reports.config.validation.ValidationConfig; import ru.spcex.clearing.test.TestUtils; @@ -62,7 +63,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; ImdgTestConfig.class, KafkaTestConfig.class, ReportBuildersConfig.class, - TestConfig.class + TestConfig.class, + SFTPTestConfig.class }) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class ReportServiceTest_KS {