Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
ialbert 2025-07-09 14:44:41 +03:00
commit 11ba4d9515
4 changed files with 69 additions and 16 deletions

View file

@ -4,10 +4,13 @@ import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@ -21,9 +24,6 @@ import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllRespo
import ru.spcex.clearing.backendapi.service.IOperator;
import ru.spcex.clearing.backendapi.service.IStateLoader;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import java.util.Collection;
import java.util.Map;
import ru.spcex.clearing.platform.messaging.domain.Consts;
@Controller
@ -50,21 +50,19 @@ public class SessionController extends AbstractQueueController {
@ApiOperation(value = "Continue session")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)})
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@RequestMapping(value = "/{event_type}", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public CudResponse repeatSession(
@ApiParam(value = "Параметры команды в JSON формате.", required = true)
@PathVariable("event_type") String eventType,
@RequestBody ContinueSessionAction continueSessionAction) throws ExecutionException, InterruptedException {
return processRequest(Consts.REPEAT_SESSION, continueSessionAction);
if ("REPT".equals(eventType)) {
return processRequest(Consts.REPEAT_SESSION, continueSessionAction);
} else if ("NEXT".equals(eventType)){
return processRequest(Consts.CONTINUE_SESSION, continueSessionAction);
} else {
throw new UnsupportedOperationException("Unsupported event type: " + eventType);
}
}
@ApiOperation(value = "Continue session")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)})
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public CudResponse continueSession(
@ApiParam(value = "Параметры команды в JSON формате.", required = true)
@RequestBody ContinueSessionAction continueSessionAction) throws ExecutionException, InterruptedException {
return processRequest(Consts.CONTINUE_SESSION, continueSessionAction);
}
}

View file

@ -424,7 +424,7 @@ public class FormingPaymentInstructionAssetsAction extends AbstractSessionAction
Registry rgs = pair.getSecond();
Account account = accountImdg.getSingleObjectByID(paymentInstruction.getCreditLeg_accountId());
Security security = securityImdg.getSingleObjectByID(paymentInstruction.getCreditLeg_securityId());
if (SessionType.CURR.equals(sessionType) || (rgs != null
if (SessionType.CURR.equals(sessionType) || SessionType.PAYM.equals(sessionType) || (rgs != null
&& RegistryInstrumentType.M.equalsByKey(rgs.getRegistryInstrumentType())
&& !CurrencyCode.isRub(rgs.getSecuritySymbol()))) {
boolean madeStatements = statementsWereMade(paymentInstruction, rgs);

View file

@ -164,7 +164,7 @@ public class InclusionToPoolAction extends AbstractSessionActionForOkErrorHandli
switch (ssnTpe) {
case MEDM, FINL, XDEP -> execImdg = (Imdg<T>) executionDepositImdg;
case IPO0, IPOB, TRDT, IPOT -> execImdg = (Imdg<T>) executionFondImdg;
case CURR -> execImdg = (Imdg<T>) executionCurrImdg;
case CURR, PAYM -> execImdg = (Imdg<T>) executionCurrImdg;
default -> {
//кейс для "общих" сессий (напр. UNIT) в которых сочетаются разные сделки
//смотрим на секцию регистра.

View file

@ -40,6 +40,7 @@ import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.service.TcrSearcher;
import ru.spcex.clearing.session.stage.TaskType;
import ru.spcex.clearing.session.stage.impl.IRegistryBuilder;
import ru.spcex.clearing.session.stage.impl.RegistryCkBuilder;
import ru.spcex.clearing.session.stage.impl.RegistryCurrBuilder;
import ru.spcex.clearing.session.stage.impl.RegistryDepoBuilder;
import ru.spcex.clearing.session.stage.impl.RegistryFondBuilder;
@ -55,6 +56,8 @@ import ru.spcex.platform.enumeration.RegistryDesignation;
import ru.spcex.platform.enumeration.RegistryInstrumentType;
import ru.spcex.platform.enumeration.RegistryTradingParams;
import ru.spcex.platform.enumeration.RegistryUnit;
import ru.spcex.platform.enumeration.Sender;
import ru.spcex.platform.enumeration.SessionType;
import ru.spcex.platform.enumeration.Side;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgId;
@ -69,6 +72,7 @@ import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2ById;
import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2ByIdAndString;
import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2ByString;
import ru.spcex.platform.utils.collection.Pair;
import ru.spcex.platform.utils.enumeration.IEnumKey;
@Service("requirementAndObligationCreationAction")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@ -94,6 +98,8 @@ public class RequirementAndObligationCreationAction extends AbstractSessionActio
private final Imdg<Currency> currImdg;
private final TcrSearcher tcrSearcher;
private final SecuritySelector<Security> secSelector;
private SessionType sessionType;
private TradingClearingRegistry ckTcr;
@Autowired
public RequirementAndObligationCreationAction(ImdgProvider imdgProvider) {
@ -141,6 +147,7 @@ public class RequirementAndObligationCreationAction extends AbstractSessionActio
@SuppressWarnings("unchecked")
List<ExecutionCommon> list = ctx.getExtendedState().get(DataEnum.dealsPrepared, List.class);
Long sessionId = ctx.getExtendedState().get(DataEnum.sessionId, Long.class);
SessionType sessionType = ctx.getExtendedState().get(DataEnum.sessionType, SessionType.class);
createRegisters(list, sessionId, null);
} finally {
doRgsSearch = null;
@ -148,6 +155,7 @@ public class RequirementAndObligationCreationAction extends AbstractSessionActio
}
protected void createRegisters(List<ExecutionCommon> data, Long sessionId, Map<Long, Registry> rgsStorage) {
this.ckTcr = null;
data.sort(tradeTimeComparator.thenComparing(execIdComparator).thenComparing(execMarketComparator));
Map<Long, Registry> newRgss = rgsStorage != null ? rgsStorage : storageMap(data);
//см. описание к #matchExecutions
@ -221,6 +229,12 @@ public class RequirementAndObligationCreationAction extends AbstractSessionActio
findAndUpdateOrCreate.accept(counterExec, RegistryDesignation.T, true);
findAndUpdateOrCreate.accept(counterExec, RegistryDesignation.O, true);
}
if (isCk()) {
createRegistryForCK(partyExec, RegistryDesignation.O, newRgss);
createRegistryForCK(partyExec, RegistryDesignation.T, newRgss);
createRegistryForCK(counterExec, RegistryDesignation.O, newRgss);
createRegistryForCK(counterExec, RegistryDesignation.T, newRgss);
}
}
if (rgsStorage == null) {
log.info("batch insert {} registries into map", newRgss.size());
@ -228,7 +242,48 @@ public class RequirementAndObligationCreationAction extends AbstractSessionActio
}
}
private boolean isCk() {
return IEnumKey.contains(sessionType, SessionType.PREP, SessionType.PAYM);
}
private void createRegistryForCK(
ExecutionCommon exec,
RegistryDesignation rgsDsgn,
Map<Long, Registry> newRgss
) {
if (this.ckTcr == null) {
this.ckTcr = tcrImdg.getSingleObjectByPredicate(
tcrImdg.predicateBuilder().equals("companyId", Sender.CK.getId())
);
}
IRegistryBuilder registryBuilder = RegistryCkBuilder.builder();
Registry newRegister = registryBuilder
//cashes
.dpAccCash(cash.dpAccCash)
.currCash(cash.currCash)
.clrAccCash(cash.clrAccCash)
//imdg
.cmpImdg(cmpImdg)
.tcrImdg(tcrImdg)
.accImdg(accImdg)
.ssnImdg(ssnImdg)
.clAccImdg(clAccImdg)
.dpAccImdg(dpAccImdg)
.currPairSecImdg(currPairSecImdg)
.currPairDictImdg(currPairDictImdg)
.currImdg(currImdg)
.tcrSearcher(tcrSearcher)
.secSelector(secSelector)
.imdg(imdgProvider)
.ckTcr(ckTcr)
.exec(exec)
.registryDesignation(rgsDsgn)
.returnDeposit(false)
.build();
newRegister.setId(idGen.nextId());
newRgss.put(newRegister.getId(), newRegister);
log.debug("execution id {}: created rgs.id={}", exec, newRegister.getId());
}
protected boolean searchForRegisters(Long sessionId) {
if (sessionId == null) return true;