diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java index 82692c21e..3e58ab090 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java @@ -362,6 +362,7 @@ public class ValidationConfig { return new ValidatorImpl<>(context, StatusExtractValidationRule.Fields, new PresentById(IMDGDistributedNames.Map_Registry, ClearingError.RecordNotFound, true), + StatusExtractValidationRule.RegistryCodeCheck, StatusExtractValidationRule.ContractCheck, StatusExtractValidationRule.RegistryStatusValid ); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java index 7741ef6c1..7f449a5ac 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java @@ -30,6 +30,7 @@ public enum ClearingError implements IErrorEnumId { ObligationsAlreadyCalculated(5425L), ActiveSessionIsPresent(5428L), AccountIsNotMatchedWithCompany(5429L), + RgsWrongCode(5430L), //ошибки "перенесенные" из balance-service, CompanyNotFoundB(5211L), CurrencyNotFound(5213L), @@ -40,6 +41,8 @@ public enum ClearingError implements IErrorEnumId { BalanceInsufficient(5222L), TCRegistryNotFound(3022L), WrongField(5004L), + GatewayTimeout(6003L), + GatewayNotApproved(6004L), ; private final Long id; diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java index 6460275a0..7e44d6b48 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java @@ -8,7 +8,9 @@ import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.notification.NotificationSender; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.clearing.AssetOperationRequest; import ru.spcex.clearing.platform.messaging.domain.cud.clearing.CreateRegistryRequest; import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeRefundDateRequest; import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeStatusExtractRequest; @@ -16,7 +18,10 @@ import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryReturnDe import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistrySplitDepositActionRequest; import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; import ru.spcex.clearing.platform.messaging.service.Status; +import ru.spcex.clearing.service.integration.GatewayRequestCreator; +import ru.spcex.clearing.service.schedule.TradingTimeService; import ru.spcex.clearing.service.validation.ValidationStored; +import ru.spcex.clearing.session.stage.impl.GatewayRequester; import ru.spcex.clearing.session.stage.util.RegistryUtil; import ru.spcex.clearing.util.security.UserRoleVerification; import ru.spcex.clearing.util.services.RequestHelper; @@ -39,6 +44,9 @@ import java.util.Collection; import java.util.Map; import java.util.Optional; import java.util.function.Function; +import java.util.function.Supplier; + +import static ru.spcex.clearing.session.stage.impl.GatewayRequester.mapError; @Service public class RegistryService { @@ -51,6 +59,9 @@ public class RegistryService { private final Function refundDateVal; private final Function statusExtractVal; private final Function splitDepositActionVal; + private final GatewayRequester gateway; + private final TradingTimeService trdTime; + private final NotificationSender notification; private final IMessageResolver msgResolver; private final RequestHelper reqHelp; @@ -61,7 +72,7 @@ public class RegistryService { @Qualifier("refundDateValidator") Function refundDateVal, @Qualifier("splitDepositValidator") Function splitDepositActionVal, @Qualifier("statusExtractValidator") Function statusExtractVal, - IMessageResolver msgResolver, + GatewayRequester gateway, TradingTimeService tradingTimeService, NotificationSender notification, IMessageResolver msgResolver, RequestHelper reqHelp, UserRoleVerification rights) { this.imdgProvider = imdgProvider; this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class); @@ -70,6 +81,10 @@ public class RegistryService { this.refundDateVal = refundDateVal; this.splitDepositActionVal = splitDepositActionVal; this.statusExtractVal = statusExtractVal; + this.gateway = gateway; + this.trdTime = tradingTimeService; + this.notification = notification; + this.gateway.setName("RgsService|DM*V"); this.msgResolver = msgResolver; this.reqHelp = reqHelp; this.rights = rights; @@ -177,10 +192,28 @@ public class RegistryService { msgResolver.resolve(err.get())); return reqHelp.error(req.getId(), err.get()); } - Registry registry = validator.getStored(Stored.PresentById); - registry.setRegistryStatus(payload.getRegistryStatus()); - log.debug("changing registry.id={} status to {}", registry.getId(), payload.getRegistryStatus()); - registryImdg.update(registry); + Registry rgs = validator.getStored(Stored.PresentById); + Supplier gtwBuilder = () -> GatewayRequestCreator.from(rgs); + Optional gatewayOk; + if (trdTime.isTradingTime()) { + gatewayOk = gateway.gatewayRequestAndWait(gtwBuilder); + } else { + log.debug("RegistryChangeStatusExtractRequest rgs.id={} not sending gateway request", rgs.getId()); + gatewayOk = Optional.of(true); + } + if (gatewayOk.isEmpty() || !gatewayOk.get()) { + String gtwErr = msgResolver.resolve(mapError(gatewayOk)); + log.error("{}.id={} {}", + rgs.getRegistryCode(), + rgs.getId(), + gtwErr); + notification.sendNotification(ObjectType.rgst, + "Отметка о получении выписки: %s".formatted(gtwErr), + Priority.HIGH); + } + rgs.setRegistryStatus(payload.getRegistryStatus()); + log.debug("changing registry.id={} status to {}", rgs.getId(), payload.getRegistryStatus()); + registryImdg.update(rgs); return reqHelp.success(req.getId()); } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/integration/GatewayRequestCreator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/integration/GatewayRequestCreator.java index 885c2e219..52d773617 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/integration/GatewayRequestCreator.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/integration/GatewayRequestCreator.java @@ -6,6 +6,7 @@ import ru.clearing.classes.statics.data.statement.Statement; import ru.spcex.clearing.platform.messaging.domain.cud.clearing.AssetOperationRequest; import ru.spcex.platform.enumeration.CurrencyCode; import ru.spcex.platform.enumeration.InOutDirection; +import ru.spcex.platform.utils.number.BigDecimalUtil; import java.math.BigDecimal; @@ -21,13 +22,13 @@ public class GatewayRequestCreator { return req; } - public static AssetOperationRequest from(Registry om_t) { - return from(om_t.getId(), + public static AssetOperationRequest from(Registry rgs) { + return from(rgs.getId(), null, - om_t.getBalance(), + BigDecimalUtil.safeBD(rgs.getBalance()).abs(), InOutDirection.out, - om_t.getTradingCode(), - om_t.getTradingClearingRegistry()); + rgs.getTradingCode(), + rgs.getTradingClearingRegistry()); } public static AssetOperationRequest from(PaymentInstruction pmt, String tradingCode, String tcr) { diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/payment/PaymentInstructionOutboundService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/payment/PaymentInstructionOutboundService.java index 4aabdeb6c..1f1057ec2 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/payment/PaymentInstructionOutboundService.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/payment/PaymentInstructionOutboundService.java @@ -49,6 +49,7 @@ import java.util.Optional; import java.util.function.Function; import java.util.function.Supplier; +import static ru.spcex.clearing.session.stage.impl.GatewayRequester.mapError; import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD; @Service @@ -183,11 +184,12 @@ public class PaymentInstructionOutboundService { tcr.getCode()); Optional gatewayOk = gateway.gatewayRequestAndWait(builder); if (gatewayOk.isEmpty() || gatewayOk.get().equals(Boolean.FALSE)) { - log.error("sdf54.id={} pmt.id={} gateway {}", sDf54.getId(), + String gtwErrMsg = msgs.resolve(mapError(gatewayOk)); + log.error("sdf54.id={} pmt.id={} {}", sDf54.getId(), pmt.getId(), - gatewayOk.isPresent() ? "failed" : "timeout"); + gtwErrMsg); notification.sendNotification(ObjectType.gateway, - gatewayOk.isPresent() ? "gateway not approved" : "gateway timeout", + gtwErrMsg, Priority.HIGH); pmt.setTransactionStatus(TransactionStatus.fail.getKey()); pmt.setUpdated(now); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/schedule/TradingTimeService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/schedule/TradingTimeService.java index fc4b38836..48421c68a 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/schedule/TradingTimeService.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/schedule/TradingTimeService.java @@ -45,7 +45,8 @@ public class TradingTimeService { return false; } LocalTime now = LocalTime.now(); - log.debug("now: {}, startTradingTime: {}, endTradingTime: {}", now, startTradingTime, endTradingTime); - return !now.isBefore(startTradingTime) && !now.isAfter(endTradingTime); + boolean isTradingTime = !now.isBefore(startTradingTime) && !now.isAfter(endTradingTime); + log.debug("now: {}, startTradingTime: {}, endTradingTime: {}. trading time: {}", now, startTradingTime, endTradingTime, isTradingTime); + return isTradingTime; } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/StatusExtractValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/StatusExtractValidationRule.java index c97a56646..0bd51ec41 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/StatusExtractValidationRule.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/StatusExtractValidationRule.java @@ -6,6 +6,7 @@ import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeStatusExtractRequest; import ru.spcex.platform.enumeration.RegistryStatus; +import ru.spcex.platform.enumeration.RegistryTradingParams; import ru.spcex.platform.imdg.validation.ImdgValidationContext; import ru.spcex.platform.imdg.validation.Stored; import ru.spcex.platform.utils.enumeration.EnumMessage; @@ -16,6 +17,8 @@ import ru.spcex.platform.utils.validation.IValidationRule; import java.util.Objects; import java.util.Optional; +import static ru.spcex.clearing.service.registry.RegistryManager.equalsByCode; + public enum StatusExtractValidationRule implements IValidationRule> { Fields() { @Override @@ -30,6 +33,18 @@ public enum StatusExtractValidationRule implements IValidationRule validate(ImdgValidationContext context) { + Registry rgs = context.getStoredObject(Stored.PresentById); + if (!equalsByCode(RegistryTradingParams.D__V, rgs)) { + return of(ClearingError.RgsWrongCode, "%s.id=%d".formatted( + rgs.getRegistryCode(), + rgs.getId())); + } + return empty(); + } + }, ContractCheck() { @Override public Optional validate(ImdgValidationContext context) { diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/GatewayRequester.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/GatewayRequester.java index e35502c6f..556c841b0 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/GatewayRequester.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/GatewayRequester.java @@ -11,6 +11,7 @@ import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import ru.spcex.clearing.config.element.ClearingServiceSettings; import ru.spcex.clearing.config.element.SessionStageSettings; +import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.Consts; import ru.spcex.clearing.platform.messaging.domain.cud.clearing.AssetOperationListRequest; @@ -19,6 +20,7 @@ import ru.spcex.clearing.platform.messaging.domain.cud.gateway.AssetOperationApp import ru.spcex.clearing.platform.messaging.domain.cud.gateway.SingleAssetResponse; import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.log.ExceptionUtils; import java.util.ArrayList; @@ -139,4 +141,12 @@ public class GatewayRequester extends QueueConsumer implements InitializingBean public void setName(String name) { this.name = name; } + + public static EnumMessage mapError(Optional gtwRsp) { + if (gtwRsp.isEmpty()) { + return new EnumMessage(ClearingError.GatewayTimeout); + } else if (!gtwRsp.get()) { + return new EnumMessage(ClearingError.GatewayNotApproved); + } else throw new IllegalArgumentException("gateway response was OK. cannot create error message"); + } }