diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/TaskType.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/TaskType.java index 5517afc3b..e25a6d371 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/TaskType.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/TaskType.java @@ -25,4 +25,9 @@ public enum TaskType { */ FormingRegistersOnOS, + + /** + * step 8 + */ + UnlockResources, } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/UnlockResources.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/UnlockResources.java new file mode 100644 index 000000000..c563c84b5 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/UnlockResources.java @@ -0,0 +1,147 @@ +package ru.spcex.clearing.session.stage.impl; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.registry.Registry; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.session.stage.ISessionStage; +import ru.spcex.clearing.session.stage.StageResult; +import ru.spcex.clearing.session.stage.Task; +import ru.spcex.clearing.session.stage.task.UnlockResourcesPayload; +import ru.spcex.platform.enumeration.RegistryDesignation; +import ru.spcex.platform.enumeration.RegistryInstrumentType; +import ru.spcex.platform.enumeration.RegistryUnit; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; + +import java.math.BigDecimal; +import java.time.Instant; +import java.util.Collection; + +@Service +public class UnlockResources implements ISessionStage { + private final Logger log = LoggerFactory.getLogger(getClass()); + + private final Imdg registryImdg; + + @Autowired + public UnlockResources(ImdgProvider imdgProvider) { + this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); + + } + + @Override + public StageResult submit(Task task) { + switch (task.getTaskType()) { + case UnlockResources -> { + UnlockResourcesPayload payload = (UnlockResourcesPayload) task.getData(); + return unlockResources(payload.getSdfMode(), payload.getSessionId(), + payload.getAccount(), + payload.getSecurityId(), + payload.getFullNames(), + payload.getValue() + ); + } + default -> { + throw new IllegalStateException("Unknown task type: " + task.getTaskType()); + } + } + } + + /** + * Select Registry by: account; fullName* / securityId + */ + protected Collection selectRegistry(Long sessionId, String account, Long securityId, Collection fullNames) { + ImdgPredicateBuilder pb = registryImdg.predicateBuilder(); + ImdgPredicate queryPart; + if (securityId != null) { + queryPart = pb.in("securityId", securityId); + } else if (fullNames != null && !fullNames.isEmpty()) { + queryPart = pb.in("fullName", fullNames.toArray(new String[fullNames.size()])); + } else { + throw new IllegalArgumentException("Required securityId or fullNames"); + } + ImdgPredicate query = pb.and( + pb.and( + pb.equals("sessionId", sessionId), + pb.equals("registryDesignation", RegistryDesignation.A.getKey()) // не все нужны, только с этим кодом отфильтруем. + ), + pb.equals("account", account), + queryPart + ); + + Collection result = registryImdg.getCollectionObjectsByPredicate(query); + log.trace("Selected {} registry's by sql: {}", result.size(), query); + return result; + } + + /** + * @param sdfMode UnlockResourcesPayload.sdfMode + * @param sessionId + * @param account + * @param securityId + * @param fullNames + * @return + */ + protected StageResult unlockResources(String sdfMode, Long sessionId, String account, Long securityId, Collection fullNames, BigDecimal value) { + Collection forRegistries = selectRegistry(sessionId, account, securityId, fullNames); + + //todo при перезапуске после незапланированного завершения стадии: надо ли проверять уже созданные регистры и не создавать дубликаты? + if (UnlockResourcesPayload.MODE_SDF04.equals(sdfMode)) { + forRegistries = forRegistries.stream().filter( + (Registry r) -> + RegistryDesignation.A.equalsByKey(r.getRegistryDesignation()) + && + RegistryInstrumentType.M.equalsByKey(r.getRegistryInstrumentType()) + && + (RegistryUnit.F.equalsByKey(r.getRegistryUnit()) || RegistryUnit.B.equalsByKey(r.getRegistryUnit())) + ).toList(); + } else if (UnlockResourcesPayload.MODE_SDF12.equals(sdfMode)) { + forRegistries = forRegistries.stream().filter( + (Registry r) -> + RegistryDesignation.A.equalsByKey(r.getRegistryDesignation()) + && + RegistryInstrumentType.S.equalsByKey(r.getRegistryInstrumentType()) + && + (RegistryUnit.F.equalsByKey(r.getRegistryUnit()) || RegistryUnit.B.equalsByKey(r.getRegistryUnit())) + ).toList(); + } else { + throw new IllegalArgumentException("Mode not support: " + sdfMode); + } + + for (Registry registry : forRegistries) { + boolean modified = unlockRegistry(registry, value); + if (modified) { + registry.setUpdated(Instant.now()); + registryImdg.update(registry); + log.trace("Registry {} changed; value +- registry", + registry.getId(), registry.getRegistryCode(), value); + } + } + //todo рекомендуется делать транзакцией. + + StageResult> res = new StageResult<>(null, true); + res.setStageResult(forRegistries); + return res; + } + + boolean unlockRegistry(Registry registry, BigDecimal value) { + if (RegistryUnit.F.equalsByKey(registry.getRegistryUnit())) { + if (registry.getBalance() == null) registry.setBalance(BigDecimal.ZERO); + registry.setBalance(registry.getBalance().add(value)); + return true; + } else if (RegistryUnit.B.equalsByKey(registry.getRegistryUnit())) { + if (registry.getBalance() == null) registry.setBalance(BigDecimal.ZERO); + registry.setBalance(registry.getBalance().subtract(value)); + return true; + } else { + log.warn("For registry {} registryUnit={} unlock operation not implemented.", + registry.getId(), registry.getRegistryUnit()); + return false; + } + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/task/UnlockResourcesPayload.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/task/UnlockResourcesPayload.java new file mode 100644 index 000000000..1b9525f23 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/task/UnlockResourcesPayload.java @@ -0,0 +1,88 @@ +package ru.spcex.clearing.session.stage.task; + +import java.math.BigDecimal; +import java.util.List; + +public class UnlockResourcesPayload { + public static final String MODE_SDF04 = "sDf04"; + public static final String MODE_SDF12 = "sDf12"; + + /** + * MODE_SDF04/MODE_SDF12 + */ + private String sdfMode; + + private Long sessionId; + + /** + * sDf04.c_acc_cred + * sDf12.depoCodeSender + */ + private String account; + /** + * sDf04.(sbanknam1, sbanknam2 и т.д.) + */ + private List fullNames; + + /** + * sDf12.securityCode + */ + private Long securityId; + + /** + * sDf04.pay_val + * sDf12.quantity + */ + private BigDecimal value; + + + + public String getSdfMode() { + return sdfMode; + } + + public void setSdfMode(String sdfMode) { + this.sdfMode = sdfMode; + } + + + public Long getSessionId() { + return sessionId; + } + + public void setSessionId(Long sessionId) { + this.sessionId = sessionId; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public List getFullNames() { + return fullNames; + } + + public void setFullNames(List fullNames) { + this.fullNames = fullNames; + } + + public Long getSecurityId() { + return securityId; + } + + public void setSecurityId(Long securityId) { + this.securityId = securityId; + } + + public BigDecimal getValue() { + return value; + } + + public void setValue(BigDecimal value) { + this.value = value; + } +}